Просмотр исходного кода

feat: 管理端CF值余额与流水查询页面

Xiaogang Liao 1 месяц назад
Родитель
Сommit
2402ad238f
3 измененных файлов с 164 добавлено и 0 удалено
  1. 25 0
      cfc-web/src/api/admin.js
  2. 6 0
      cfc-web/src/router/index.js
  3. 133 0
      cfc-web/src/views/admin/CfValueManage.vue

+ 25 - 0
cfc-web/src/api/admin.js

@@ -1896,3 +1896,28 @@ export function getHealthReportDetail(reportId) {
     data: { reportId }
   })
 }
+
+// ===== CF值(平台积分)管理 =====
+export function getCfValueBalance(data) {
+  return request({
+    url: '/api/admin/cf-value/balance',
+    method: 'post',
+    data
+  })
+}
+
+export function getCfValueLogs(data) {
+  return request({
+    url: '/api/admin/cf-value/logs',
+    method: 'post',
+    data
+  })
+}
+
+export function getCfValueAllBalances(data) {
+  return request({
+    url: '/api/admin/cf-value/all-balances',
+    method: 'post',
+    data
+  })
+}

+ 6 - 0
cfc-web/src/router/index.js

@@ -374,6 +374,12 @@ const routes = [
         component: () => import('@/views/admin/ProductPpointManage.vue'),
         meta: { title: 'P点配置', perm: 'commerce:ppoint' }
       },
+      {
+        path: 'cf-value',
+        name: 'CfValueManage',
+        component: () => import('@/views/admin/CfValueManage.vue'),
+        meta: { title: 'CF值管理', perm: 'finance:cf-value' }
+      },
       {
         path: 'supply-system',
         name: 'SupplySystemList',

+ 133 - 0
cfc-web/src/views/admin/CfValueManage.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="cf-value admin-page">
+    <div class="header">
+      <h2>CF值(平台积分)管理</h2>
+      <div class="filters">
+        <el-input v-model="searchUserId" placeholder="用户ID搜索" style="width: 200px;" clearable @keyup.enter.native="searchBalance" />
+        <el-button type="primary" @click="searchBalance">查询余额</el-button>
+      </div>
+    </div>
+
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="余额列表" name="balances">
+        <el-table :data="balanceList" v-loading="loadingBalance" border stripe>
+          <el-table-column prop="id" label="ID" width="70" />
+          <el-table-column prop="userId" label="用户ID" width="100" />
+          <el-table-column prop="familyId" label="家庭ID" width="100" />
+          <el-table-column prop="totalEarned" label="累计获得" width="100" />
+          <el-table-column prop="available" label="可用" width="80" />
+          <el-table-column prop="frozen" label="冻结" width="80" />
+          <el-table-column prop="withdrawn" label="已提现" width="80" />
+          <el-table-column prop="exchanged" label="已兑换" width="80" />
+          <el-table-column label="操作" width="100">
+            <template slot-scope="{ row }">
+              <el-button type="text" size="small" @click="viewLogs(row.userId)">流水</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-pagination v-if="balanceTotal > 0" :current-page="balancePage" :page-size="balanceSize" :total="balanceTotal" layout="prev, pager, next" @current-change="pageBalances" />
+      </el-tab-pane>
+
+      <el-tab-pane label="流水查询" name="logs">
+        <div class="filters">
+          <el-input v-model="logUserId" placeholder="用户ID" style="width: 200px;" clearable @keyup.enter.native="searchLogs" />
+          <el-button type="primary" @click="searchLogs">查询流水</el-button>
+        </div>
+        <el-table :data="logList" v-loading="loadingLog" border stripe>
+          <el-table-column prop="id" label="ID" width="70" />
+          <el-table-column prop="userId" label="用户ID" width="80" />
+          <el-table-column prop="type" label="类型" width="100">
+            <template slot-scope="{ row }">
+              <el-tag :type="typeTag(row.type)" size="small">{{ row.type }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="amount" label="数量" width="80" />
+          <el-table-column prop="balanceAfter" label="变动后余额" width="100" />
+          <el-table-column prop="refType" label="来源" width="130" />
+          <el-table-column prop="refId" label="关联ID" width="80" />
+          <el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
+          <el-table-column prop="createdAt" label="时间" width="160" />
+        </el-table>
+        <el-pagination v-if="logTotal > 0" :current-page="logPage" :page-size="logSize" :total="logTotal" layout="prev, pager, next" @current-change="pageLogs" />
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import { getCfValueBalance, getCfValueLogs, getCfValueAllBalances } from '@/api/admin'
+
+export default {
+  data() {
+    return {
+      activeTab: 'balances',
+      searchUserId: '',
+      logUserId: '',
+      // Balances
+      balanceList: [],
+      loadingBalance: false,
+      balancePage: 1,
+      balanceSize: 20,
+      balanceTotal: 0,
+      // Logs
+      logList: [],
+      loadingLog: false,
+      logPage: 1,
+      logSize: 20,
+      logTotal: 0
+    }
+  },
+  mounted() {
+    this.loadBalances()
+  },
+  methods: {
+    typeTag(type) {
+      const map = { earn: 'success', spend: 'warning', freeze: 'info', unfreeze: 'info', withdraw: 'primary' }
+      return map[type] || 'info'
+    },
+    loadBalances() {
+      this.loadingBalance = true
+      getCfValueAllBalances({ page: this.balancePage, size: this.balanceSize }).then(res => {
+        if (res.code === 200) {
+          this.balanceList = res.data.records || []
+          this.balanceTotal = res.data.total || 0
+        }
+      }).finally(() => { this.loadingBalance = false })
+    },
+    pageBalances(page) {
+      this.balancePage = page
+      this.loadBalances()
+    },
+    searchBalance() {
+      if (!this.searchUserId) { this.loadBalances(); return }
+      this.loadingBalance = true
+      getCfValueBalance({ userId: this.searchUserId }).then(res => {
+        if (res.code === 200) {
+          this.balanceList = [res.data]
+          this.balanceTotal = 1
+        }
+      }).finally(() => { this.loadingBalance = false })
+    },
+    viewLogs(userId) {
+      this.logUserId = String(userId)
+      this.activeTab = 'logs'
+      this.searchLogs()
+    },
+    searchLogs() {
+      if (!this.logUserId) return
+      this.loadingLog = true
+      this.logPage = 1
+      getCfValueLogs({ userId: this.logUserId, page: 1, size: this.logSize }).then(res => {
+        if (res.code === 200) {
+          this.logList = res.data.records || []
+          this.logTotal = res.data.total || 0
+        }
+      }).finally(() => { this.loadingLog = false })
+    },
+    pageLogs(page) {
+      this.logPage = page
+      this.searchLogs()
+    }
+  }
+}
+</script>