Browse Source

chore: 删除已替换为ReviewCenter的旧审核页面

Xiaogang Liao 2 tháng trước cách đây
mục cha
commit
5b6d83b3e1

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

@@ -296,12 +296,6 @@ const routes = [
         component: () => import('@/views/admin/ProductPpointManage.vue'),
         meta: { title: 'P点配置', perm: 'commerce:ppoint' }
       },
-      {
-        path: 'withdraw-audit',
-        name: 'WithdrawAudit',
-        component: () => import('@/views/admin/WithdrawAudit.vue'),
-        meta: { title: '提现审核', perm: 'audit:withdraw' }
-      },
       {
         path: 'supply-system',
         name: 'SupplySystemList',

+ 0 - 225
cfc-web/src/views/GuideAudit.vue

@@ -1,225 +0,0 @@
-<template>
-  <div class="page-container">
-    <el-card>
-      <div slot="header">
-        <span>成长规划师审核</span>
-        <el-button style="float: right" size="small" @click="loadData" :loading="loading">刷新</el-button>
-      </div>
-
-      <el-form :inline="true" :model="searchForm" style="margin-bottom: 20px">
-        <el-form-item label="状态">
-          <el-select v-model="searchForm.status" placeholder="全部" clearable @change="loadData">
-            <el-option label="待审核" value="pending"></el-option>
-            <el-option label="已通过" value="approved"></el-option>
-            <el-option label="已拒绝" value="rejected"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="loadData">搜索</el-button>
-          <el-button @click="handleReset">重置</el-button>
-        </el-form-item>
-        </el-form>
-
-        <div style="overflow:auto;max-height:calc(100vh - 300px);">
-        <el-table :data="tableData" border v-loading="loading" style="max-height:calc(100vh - 300px);">
-        <el-table-column prop="id" label="ID" width="60"></el-table-column>
-        <el-table-column prop="nickname" label="昵称" min-width="100"></el-table-column>
-        <el-table-column prop="realName" label="真实姓名" width="100"></el-table-column>
-        <el-table-column prop="phone" label="手机号" width="120"></el-table-column>
-        <el-table-column prop="idCard" label="身份证号" width="180"></el-table-column>
-        <el-table-column prop="address" label="地址" min-width="160">
-          <template slot-scope="{ row }">{{ row.address || '无' }}</template>
-        </el-table-column>
-        <el-table-column prop="teacherNo" label="证书号" width="120">
-          <template slot-scope="{ row }">{{ row.teacherNo || '无' }}</template>
-        </el-table-column>
-        <el-table-column label="证书/照片" width="120">
-          <template slot-scope="{ row }">
-            <el-button v-if="row.certificateImage" type="text" size="small" @click="previewImage(row.certificateImage)">查看证书</el-button>
-            <span v-else>无</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="teacherStatus" label="状态" width="100">
-          <template slot-scope="{ row }">
-            <el-tag :type="getStatusType(row.teacherStatus)" size="small">{{ getStatusText(row.teacherStatus) }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="updatedAt" label="申请时间" width="160">
-          <template slot-scope="{ row }">{{ formatDate(row.updatedAt) }}</template>
-        </el-table-column>
-        <el-table-column label="操作" width="180" fixed="right">
-          <template slot-scope="{ row }">
-            <el-button v-if="row.teacherStatus === 'pending'" size="mini" type="primary" @click="handleApprove(row)">通过</el-button>
-            <el-dropdown v-if="row.teacherStatus === 'pending'" trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-              <el-button size="mini">
-                更多<i class="el-icon-arrow-down el-icon--right"></i>
-              </el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item command="reject" icon="el-icon-close">拒绝</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-          </template>
-      </el-table-column>
-    </el-table></div>
-
-  <el-pagination
-        v-if="total > 0"
-        style="margin-top: 20px; text-align: right"
-        :current-page="pagination.page"
-        :page-size="pagination.size"
-        :total="total"
-        layout="total, prev, pager, next"
-        @current-change="handlePageChange"
-      />
-    </el-card>
-
-    <el-dialog title="图片预览" :visible.sync="previewVisible" width="500px">
-      <img :src="previewUrl" style="width: 100%" />
-    </el-dialog>
-
-    <el-dialog title="拒绝申请" :visible.sync="rejectDialogVisible" width="400px">
-      <el-form>
-        <el-form-item label="拒绝原因" required>
-          <el-input
-            type="textarea"
-            v-model="rejectForm.reason"
-            :rows="4"
-            placeholder="请输入拒绝原因,申请人将收到此原因"
-          />
-        </el-form-item>
-      </el-form>
-      <div slot="footer">
-        <el-button @click="rejectDialogVisible = false">取消</el-button>
-        <el-button type="danger" @click="confirmReject" :loading="rejectLoading">确认拒绝</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { getGuideApplications, approveGuide, rejectGuide } from '@/api/admin'
-
-export default {
-  data() {
-    return {
-      loading: false,
-      tableData: [],
-      total: 0,
-      pagination: {
-        page: 1,
-        size: 10
-      },
-      searchForm: {
-        status: 'pending'
-      },
-      previewVisible: false,
-      previewUrl: '',
-      rejectDialogVisible: false,
-      rejectLoading: false,
-      rejectForm: {
-        userId: null,
-        userName: '',
-        reason: ''
-      }
-    }
-  },
-  mounted() {
-    this.loadData()
-  },
-  methods: {
-    handleActionCmd(row, cmd) {
-      switch (cmd) {
-        case 'approve': this.handleApprove(row); break;
-        case 'reject': this.handleReject(row); break;
-      }
-    },
-    async loadData() {
-      this.loading = true
-      try {
-        const params = {
-          page: this.pagination.page,
-          size: this.pagination.size,
-          status: this.searchForm.status || undefined
-        }
-        const res = await getGuideApplications(params)
-        if (res.code === 200) {
-          this.tableData = (res.data && res.data.records) || []
-          this.total = (res.data && res.data.total) || 0
-        }
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.loading = false
-      }
-    },
-    handleReset() {
-      this.searchForm = { status: 'pending' }
-      this.pagination.page = 1
-      this.loadData()
-    },
-    handlePageChange(page) {
-      this.pagination.page = page
-      this.loadData()
-    },
-    async handleApprove(row) {
-      try {
-        await this.$confirm(`确认通过 "${row.realName || row.nickname}" 的成长规划师申请?`, '提示')
-        const res = await approveGuide(row.id)
-        if (res.code === 200) {
-          this.$message.success('审核通过成功')
-          this.loadData()
-        } else {
-          this.$message.error(res.message || '操作失败')
-        }
-      } catch (e) {
-        if (e !== 'cancel') {
-          this.$message.error('操作失败')
-        }
-      }
-    },
-    async handleReject(row) {
-      this.rejectForm.userId = row.id
-      this.rejectForm.userName = row.realName || row.nickname
-      this.rejectForm.reason = ''
-      this.rejectDialogVisible = true
-    },
-    async confirmReject() {
-      if (!this.rejectForm.reason || !this.rejectForm.reason.trim()) {
-        this.$message.warning('请输入拒绝原因')
-        return
-      }
-      this.rejectLoading = true
-      try {
-        const res = await rejectGuide(this.rejectForm.userId, this.rejectForm.reason)
-        if (res.code === 200) {
-          this.$message.success('已拒绝')
-          this.rejectDialogVisible = false
-          this.loadData()
-        } else {
-          this.$message.error((res.data && res.data.message) || '操作失败')
-        }
-      } catch (e) {
-        this.$message.error('操作失败')
-      } finally {
-        this.rejectLoading = false
-      }
-    },
-    previewImage(url) {
-      this.previewUrl = url
-      this.previewVisible = true
-    },
-    getStatusType(status) {
-      const map = { pending: 'warning', approved: 'success', rejected: 'danger' }
-      return map[status] || 'info'
-    },
-    getStatusText(status) {
-      const map = { pending: '待审核', approved: '已通过', rejected: '已拒绝' }
-      return map[status] || status
-    },
-    formatDate(date) {
-      if (!date) return ''
-      return date.substring(0, 19).replace('T', ' ')
-    }
-  }
-}
-</script>

+ 0 - 217
cfc-web/src/views/PackageAudit.vue

@@ -1,217 +0,0 @@
-<template>
-  <div class="page-container">
-    <el-card>
-      <div slot="header">
-        <span>套餐审核</span>
-        <el-button style="float: right" size="small" @click="loadData" :loading="loading">刷新</el-button>
-      </div>
-
-      <!-- 筛选 -->
-      <el-form :inline="true" :model="searchForm" style="margin-bottom: 20px">
-        <el-form-item label="状态">
-          <el-select v-model="searchForm.status" placeholder="全部" clearable @change="loadData">
-            <el-option label="待审核" value="pending"></el-option>
-            <el-option label="已通过" value="approved"></el-option>
-            <el-option label="已拒绝" value="rejected"></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="loadData">搜索</el-button>
-          <el-button @click="handleReset">重置</el-button>
-        </el-form-item>
-      </el-form>
-
-      <!-- 套餐列表 -->
-      <div style="overflow:auto;max-height:calc(100vh - 300px);">
-<el-table style="max-height:calc(100vh - 300px);" :data="tableData" border v-loading="loading">
-        <el-table-column prop="id" label="ID" width="60"></el-table-column>
-        <el-table-column prop="name" label="套餐名称" min-width="150"></el-table-column>
-        <el-table-column prop="cycleDays" label="周期" width="80">
-          <template slot-scope="{ row }">{{ row.cycleDays }}天</template>
-        </el-table-column>
-        <el-table-column prop="price" label="价格" width="80">
-          <template slot-scope="{ row }">{{ formatPriceWithSymbol(row.price) }}</template>
-        </el-table-column>
-        <el-table-column prop="category" label="分类" width="80"></el-table-column>
-        <el-table-column prop="status" label="状态" width="100">
-          <template slot-scope="{ row }">
-            <el-tag :type="getStatusType(row.status)" size="small">{{ getStatusText(row.status) }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="createdAt" label="创建时间" width="160">
-          <template slot-scope="{ row }">{{ formatDate(row.createdAt) }}</template>
-        </el-table-column>
-        <el-table-column label="操作" width="200" fixed="right">
-          <template slot-scope="{ row }">
-            <el-button size="mini" @click="handleView(row)">详情</el-button>
-            <el-dropdown v-if="row.status === 'pending'" trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-              <el-button size="mini">
-                更多<i class="el-icon-arrow-down el-icon--right"></i>
-              </el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item command="approve" icon="el-icon-check">通过</el-dropdown-item>
-                <el-dropdown-item command="reject" icon="el-icon-close">拒绝</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-          </template>
-        </el-table-column>
-      </el-table></div>
-
-      <!-- 分页 -->
-      <el-pagination
-        v-if="total > 0"
-        style="margin-top: 20px; text-align: right"
-        :current-page="pagination.page"
-        :page-size="pagination.size"
-        :total="total"
-        layout="total, prev, pager, next"
-        @current-change="handlePageChange"
-      />
-    </el-card>
-
-    <!-- 详情弹窗 -->
-    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
-      <el-form v-if="currentRow" label-width="100px">
-        <el-form-item label="套餐名称">{{ currentRow.name }}</el-form-item>
-        <el-form-item label="周期">{{ currentRow.cycleDays }}天</el-form-item>
-        <el-form-item label="价格">{{ formatPriceWithSymbol(currentRow.price) }}</el-form-item>
-        <el-form-item label="分类">{{ currentRow.category }}</el-form-item>
-        <el-form-item label="描述">{{ currentRow.description }}</el-form-item>
-        <el-form-item label="状态">
-          <el-tag :type="getStatusType(currentRow.status)">{{ getStatusText(currentRow.status) }}</el-tag>
-        </el-form-item>
-        <el-form-item v-if="currentRow.rejectReason" label="拒绝原因">{{ currentRow.rejectReason }}</el-form-item>
-      </el-form>
-      <div slot="footer">
-        <el-button @click="dialogVisible = false">关闭</el-button>
-        <el-button v-if="currentRow && currentRow.status === 'pending'" type="primary" @click="handleApprove(currentRow)">通过</el-button>
-        <el-button v-if="currentRow && currentRow.status === 'pending'" type="danger" @click="handleReject(currentRow)">拒绝</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 拒绝原因弹窗 -->
-    <el-dialog title="拒绝原因" :visible.sync="rejectDialogVisible" width="400px">
-      <el-input type="textarea" v-model="rejectReason" rows="4" placeholder="请输入拒绝原因"></el-input>
-      <div slot="footer">
-        <el-button @click="rejectDialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="confirmReject">确定</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { getPendingPackages, getMyPackages, approvePackage, rejectPackage } from '@/api/package'
-
-export default {
-  name: 'PackageAudit',
-  data() {
-    return {
-      loading: false,
-      tableData: [],
-      total: 0,
-      searchForm: {
-        status: 'pending'
-      },
-      pagination: {
-        page: 1,
-        size: 10
-      },
-      dialogVisible: false,
-      dialogTitle: '套餐详情',
-      currentRow: null,
-      rejectDialogVisible: false,
-      rejectReason: ''
-    }
-  },
-  mounted() {
-    this.loadData()
-  },
-  methods: {
-    handleActionCmd(row, cmd) {
-      switch (cmd) {
-        case 'view': this.handleView(row); break;
-        case 'approve': this.handleApprove(row); break;
-        case 'reject': this.handleReject(row); break;
-      }
-    },
-    async loadData() {
-      this.loading = true
-      try {
-        const res = this.searchForm.status === 'pending' 
-          ? await getPendingPackages()
-          : await getMyPackages()
-        this.tableData = res.data || []
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.loading = false
-      }
-    },
-    handleReset() {
-      this.searchForm = { status: 'pending' }
-      this.loadData()
-    },
-    handlePageChange(page) {
-      this.pagination.page = page
-      this.loadData()
-    },
-    getStatusType(status) {
-      const map = { pending: 'warning', approved: 'success', rejected: 'danger', draft: 'info' }
-      return map[status] || 'info'
-    },
-    getStatusText(status) {
-      const map = { draft: '草稿', pending: '待审核', approved: '已通过', rejected: '已拒绝', offline: '已下架' }
-      return map[status] || status
-    },
-    formatDate(date) {
-      if (!date) return '-'
-      return new Date(date).toLocaleString()
-    },
-    handleView(row) {
-      this.currentRow = row
-      this.dialogTitle = '套餐详情'
-      this.dialogVisible = true
-    },
-    async handleApprove(row) {
-      try {
-        await this.$confirm('确认审核通过此套餐?', '提示', { type: 'success' })
-        await approvePackage(row.id)
-        this.$message.success('审核通过')
-        this.dialogVisible = false
-        this.loadData()
-      } catch (e) {
-        if (e !== 'cancel') {
-          this.$message.error('操作失败')
-        }
-      }
-    },
-    handleReject(row) {
-      this.currentRow = row
-      this.rejectReason = ''
-      this.rejectDialogVisible = true
-    },
-    async confirmReject() {
-      if (!this.rejectReason.trim()) {
-        this.$message.warning('请输入拒绝原因')
-        return
-      }
-      try {
-        await rejectPackage(this.currentRow.id, this.rejectReason)
-        this.$message.success('已拒绝')
-        this.rejectDialogVisible = false
-        this.dialogVisible = false
-        this.loadData()
-      } catch (e) {
-        this.$message.error('操作失败')
-      }
-    }
-  }
-}
-</script>
-
-<style scoped>
-.page-container {
-  padding: 20px;
-}
-</style>

+ 0 - 264
cfc-web/src/views/admin/ButlerReview.vue

@@ -1,264 +0,0 @@
-<template>
-  <div class="butler-review admin-page">
-    <el-tabs v-model="activeTab" @tab-click="onTabChange">
-      <el-tab-pane label="管家审核" name="review">
-        <div class="header admin-page-header">
-          <h2 class="admin-page-title">管家审核</h2>
-          <div class="flex items-center gap-sm">
-            <el-select v-model="statusFilter" placeholder="审核状态" @change="loadList">
-              <el-option label="全部状态" value="" />
-              <el-option label="待审核" value="pending" />
-              <el-option label="已通过" value="approved" />
-              <el-option label="已拒绝" value="rejected" />
-            </el-select>
-          </div>
-        </div>
-
-        <div class="table-scroll-wrap">
-          <el-table :data="list" v-loading="loading" border stripe>
-            <el-table-column prop="id" label="档案ID" width="80" />
-            <el-table-column prop="userId" label="用户ID" width="80" />
-            <el-table-column label="管家等级" width="100">
-              <template slot-scope="{ row }">{{ row.tier || '-' }}</template>
-            </el-table-column>
-            <el-table-column label="审核状态" width="100">
-              <template slot-scope="{ row }">
-                <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column prop="description" label="申请说明" min-width="200" show-overflow-tooltip />
-            <el-table-column prop="memberCount" label="已服务人数" width="100" />
-            <el-table-column prop="maxMembers" label="上限人数" width="80" />
-            <el-table-column prop="rejectReason" label="拒绝原因" width="150" show-overflow-tooltip />
-            <el-table-column label="操作" width="160" fixed="right">
-              <template slot-scope="{ row }">
-                <template v-if="row.status === 'pending'">
-                  <el-button size="mini" type="success" @click="handleReview(row, 'approve')">通过</el-button>
-                  <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-                    <el-button size="mini">
-                      更多<i class="el-icon-arrow-down el-icon--right"></i>
-                    </el-button>
-                    <el-dropdown-menu slot="dropdown">
-                      <el-dropdown-item command="reject" icon="el-icon-close">拒绝</el-dropdown-item>
-                    </el-dropdown-menu>
-                  </el-dropdown>
-                </template>
-                <span v-else class="no-op">—</span>
-              </template>
-            </el-table-column>
-          </el-table>
-        </div>
-
-        <el-pagination
-          @size-change="onPageChange"
-          @current-change="onPageChange"
-          :current-page="page"
-          :page-size="size"
-          :total="total"
-          layout="total, prev, pager, next"
-          class="pagination-wrap"
-        />
-
-        <el-dialog title="填写拒绝原因" :visible.sync="rejectDialogVisible" width="400px">
-          <el-input v-model="rejectReason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />
-          <span slot="footer">
-            <el-button @click="rejectDialogVisible = false">取消</el-button>
-            <el-button type="danger" @click="confirmReject">确认拒绝</el-button>
-          </span>
-        </el-dialog>
-      </el-tab-pane>
-
-      <el-tab-pane label="服务记录" name="service-records">
-        <div class="header admin-page-header">
-          <h2 class="admin-page-title">管家服务记录</h2>
-        </div>
-        <div class="table-scroll-wrap">
-          <el-table :data="serviceRecords" v-loading="srLoading" border stripe>
-            <el-table-column prop="id" label="记录ID" width="80" />
-            <el-table-column prop="butlerId" label="管家ID" width="80" />
-            <el-table-column prop="memberUserId" label="会员ID" width="80" />
-            <el-table-column label="服务类型" width="120">
-              <template slot-scope="{ row }">{{ serviceTypeLabel(row.serviceType) }}</template>
-            </el-table-column>
-            <el-table-column prop="amountP" label="金额(P点)" width="100" />
-            <el-table-column prop="platformFeeP" label="平台留成" width="100" />
-            <el-table-column prop="butlerAmountP" label="管家所得" width="100" />
-            <el-table-column prop="yearMonth" label="结算年月" width="100" />
-            <el-table-column prop="createdAt" label="创建时间" width="160" />
-          </el-table>
-        </div>
-        <el-pagination
-          @size-change="srPage = $event; loadServiceRecords()"
-          @current-change="srPage = $event; loadServiceRecords()"
-          :current-page="srPage"
-          :page-size="srSize"
-          :total="srTotal"
-          layout="total, prev, pager, next"
-          class="pagination-wrap"
-        />
-      </el-tab-pane>
-
-      <el-tab-pane label="佣金结算" name="settlements">
-        <div class="header admin-page-header">
-          <h2 class="admin-page-title">管家佣金结算</h2>
-        </div>
-        <div class="table-scroll-wrap">
-          <el-table :data="settlements" v-loading="stLoading" border stripe>
-            <el-table-column prop="id" label="结算单ID" width="80" />
-            <el-table-column prop="butlerId" label="管家ID" width="80" />
-            <el-table-column prop="yearMonth" label="结算年月" width="100" />
-            <el-table-column prop="memberCount" label="服务家庭数" width="100" />
-            <el-table-column prop="annualBaseAmountP" label="年费基准" width="100" />
-            <el-table-column prop="totalButlerAmountP" label="管家总所得" width="120" />
-            <el-table-column label="结算状态" width="100">
-              <template slot-scope="{ row }">
-                <el-tag :type="row.status === 'paid' ? 'success' : 'warning'">{{ row.status === 'paid' ? '已结算' : '待结算' }}</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column prop="settledAt" label="结算时间" width="160" />
-          </el-table>
-        </div>
-        <el-pagination
-          @size-change="stPage = $event; loadSettlements()"
-          @current-change="stPage = $event; loadSettlements()"
-          :current-page="stPage"
-          :page-size="stSize"
-          :total="stTotal"
-          layout="total, prev, pager, next"
-          class="pagination-wrap"
-        />
-      </el-tab-pane>
-    </el-tabs>
-  </div>
-</template>
-
-<script>
-import { getButlerList, reviewButler, getButlerServiceRecords, getButlerSettlements } from '@/api/butler'
-
-export default {
-  data() {
-    return {
-      activeTab: 'review',
-      // 审核列表
-      list: [],
-      loading: false,
-      page: 1,
-      size: 20,
-      total: 0,
-      statusFilter: 'pending',
-      rejectDialogVisible: false,
-      rejectTarget: null,
-      rejectReason: '',
-      // 服务记录
-      serviceRecords: [],
-      srLoading: false,
-      srPage: 1,
-      srSize: 20,
-      srTotal: 0,
-      // 结算
-      settlements: [],
-      stLoading: false,
-      stPage: 1,
-      stSize: 20,
-      stTotal: 0
-    }
-  },
-  mounted() {
-    this.loadList()
-  },
-  methods: {
-    statusType(status) {
-      const map = { pending: 'warning', approved: 'success', rejected: 'danger' }
-      return map[status] || 'info'
-    },
-    statusLabel(status) {
-      const map = { pending: '待审核', approved: '已通过', rejected: '已拒绝' }
-      return map[status] || status
-    },
-    serviceTypeLabel(type) {
-      const map = { annual: '年费服务', per_session: '按次服务' }
-      return map[type] || type
-    },
-    onTabChange() {
-      this.page = 1
-      if (this.activeTab === 'review') this.loadList()
-      else if (this.activeTab === 'service-records') this.loadServiceRecords()
-      else if (this.activeTab === 'settlements') this.loadSettlements()
-    },
-    async loadList() {
-      this.loading = true
-      try {
-        const params = { page: this.page, size: this.size, status: this.statusFilter }
-        const res = await getButlerList(params)
-        this.list = res.data.list || []
-        this.total = res.data.total || 0
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.loading = false
-      }
-    },
-    async loadServiceRecords() {
-      this.srLoading = true
-      try {
-        const res = await getButlerServiceRecords({ page: this.srPage, size: this.srSize })
-        this.serviceRecords = res.data.list || []
-        this.srTotal = res.data.total || 0
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.srLoading = false
-      }
-    },
-    async loadSettlements() {
-      this.stLoading = true
-      try {
-        const res = await getButlerSettlements({ page: this.stPage, size: this.stSize })
-        this.settlements = res.data.list || []
-        this.stTotal = res.data.total || 0
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.stLoading = false
-      }
-    },
-    onPageChange(val) {
-      this.page = val
-      this.loadList()
-    },
-    async handleReview(row, action) {
-      try {
-        await reviewButler({ userId: row.userId, action: action, reason: this.rejectReason })
-        this.$message.success('审核完成')
-        this.loadList()
-      } catch (e) {
-        this.$message.error('操作失败')
-      }
-    },
-    showRejectDialog(row) {
-      this.rejectTarget = row
-      this.rejectReason = ''
-      this.rejectDialogVisible = true
-    },
-    handleActionCmd(row, cmd) {
-      switch (cmd) {
-        case 'reject': this.showRejectDialog(row); break
-      }
-    },
-    async confirmReject() {
-      if (!this.rejectReason) {
-        this.$message.warning('请填写拒绝原因')
-        return
-      }
-      await this.handleReview(this.rejectTarget, 'reject')
-      this.rejectDialogVisible = false
-    }
-  }
-}
-</script>
-
-<style scoped>
-.no-op {
-  color: #ccc;
-}
-</style>

+ 0 - 164
cfc-web/src/views/admin/VendorReview.vue

@@ -1,164 +0,0 @@
-<template>
-  <div class="vendor-review admin-page">
-    <div class="header admin-page-header">
-      <h2 class="admin-page-title">服务商入驻审核</h2>
-      <div class="flex items-center gap-sm">
-        <el-select v-model="statusFilter" placeholder="审核状态" @change="loadList">
-          <el-option label="全部状态" value="" />
-          <el-option label="待审核" value="pending" />
-          <el-option label="已通过" value="approved" />
-          <el-option label="已拒绝" value="rejected" />
-        </el-select>
-        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-      </div>
-    </div>
-
-    <div class="table-scroll-wrap">
-    <el-table :data="list" v-loading="loading" border stripe>
-      <el-table-column prop="id" label="用户ID" width="80" />
-      <el-table-column prop="nickname" label="昵称" width="120" />
-      <el-table-column prop="realName" label="真实姓名" width="120" />
-      <el-table-column prop="phone" label="手机号" width="140" />
-      <el-table-column label="服务商类型" width="140">
-        <template slot-scope="{ row }">
-          {{ vendorTypeLabel(row.vendorType) }}
-        </template>
-      </el-table-column>
-      <el-table-column prop="vendorInfo" label="资质说明" min-width="200" show-overflow-tooltip />
-      <el-table-column label="审核状态" width="100">
-        <template slot-scope="{ row }">
-          <el-tag :type="statusType(row.vendorStatus)">{{ statusLabel(row.vendorStatus) }}</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column prop="vendorRejectReason" label="拒绝原因" width="150" show-overflow-tooltip />
-        <el-table-column label="操作" width="160" fixed="right">
-          <template slot-scope="{ row }">
-            <template v-if="row.vendorStatus === 'pending'">
-              <el-button size="mini" type="success" @click="handleReview(row, 'approve')">通过</el-button>
-              <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-                <el-button size="mini">
-                  更多<i class="el-icon-arrow-down el-icon--right"></i>
-                </el-button>
-                <el-dropdown-menu slot="dropdown">
-                  <el-dropdown-item command="reject" icon="el-icon-close">拒绝</el-dropdown-item>
-                </el-dropdown-menu>
-              </el-dropdown>
-            </template>
-            <span v-else class="no-op">—</span>
-          </template>
-        </el-table-column>
-    </el-table></div>
-
-    <el-pagination
-      @size-change="onPageChange"
-      @current-change="onPageChange"
-      :current-page="page"
-      :page-size="size"
-      :total="total"
-      layout="total, prev, pager, next"
-      class="pagination-wrap"
-    />
-
-    <!-- 拒绝弹窗 -->
-    <el-dialog title="填写拒绝原因" :visible.sync="rejectDialogVisible" width="400px">
-      <el-input v-model="rejectReason" type="textarea" :rows="3" placeholder="请输入拒绝原因" />
-      <span slot="footer">
-        <el-button @click="rejectDialogVisible = false">取消</el-button>
-        <el-button type="danger" @click="confirmReject">确认拒绝</el-button>
-      </span>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { getVendorList, reviewVendor } from '@/api/vendor'
-
-export default {
-  data() {
-    return {
-      list: [],
-      loading: false,
-      page: 1,
-      size: 20,
-      total: 0,
-      keyword: '',
-      statusFilter: 'pending',
-      rejectDialogVisible: false,
-      rejectTarget: null,
-      rejectReason: ''
-    }
-  },
-  mounted() {
-    this.loadList()
-  },
-  methods: {
-    vendorTypeLabel(type) {
-      const map = { planner: '成长规划师', activity_provider: '活动提供商', product_supplier: '商品供应商' }
-      return map[type] || type
-    },
-    statusType(status) {
-      const map = { pending: 'warning', approved: 'success', rejected: 'danger' }
-      return map[status] || 'info'
-    },
-    statusLabel(status) {
-      const map = { pending: '待审核', approved: '已通过', rejected: '已拒绝' }
-      return map[status] || status
-    },
-    async loadList() {
-      this.loading = true
-      try {
-        const params = { page: this.page, size: this.size, status: this.statusFilter }
-        if (this.keyword) params.keyword = this.keyword
-        const res = await getVendorList(params)
-        this.list = res.data.list || []
-        this.total = res.data.total || 0
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.loading = false
-      }
-    },
-    onPageChange(val) {
-      this.page = val
-      this.loadList()
-    },
-    handleSearch() {
-      this.page = 1
-      this.loadList()
-    },
-    async handleReview(row, action) {
-      try {
-        await reviewVendor({ userId: row.id, action })
-        this.$message.success('审核完成')
-        this.loadList()
-      } catch (e) {
-        this.$message.error('操作失败')
-      }
-    },
-    showRejectDialog(row) {
-      this.rejectTarget = row
-      this.rejectReason = ''
-      this.rejectDialogVisible = true
-    },
-    handleActionCmd(row, cmd) {
-      switch (cmd) {
-        case 'reject': this.showRejectDialog(row); break
-      }
-    },
-    async confirmReject() {
-      if (!this.rejectReason) {
-        this.$message.warning('请填写拒绝原因')
-        return
-      }
-      await this.handleReview(this.rejectTarget, 'reject')
-      this.rejectDialogVisible = false
-    }
-  }
-}
-</script>
-
-<style scoped>
-.no-op {
-  color: #ccc;
-}
-</style>

+ 0 - 221
cfc-web/src/views/admin/WithdrawAudit.vue

@@ -1,221 +0,0 @@
-<template>
-  <div class="withdraw-audit admin-page">
-    <div class="header admin-page-header">
-      <h2 class="admin-page-title">提现审核</h2>
-      <div class="flex items-center gap-sm">
-        <el-select v-model="statusFilter" placeholder="审核状态" @change="loadList">
-          <el-option label="全部状态" value="" />
-          <el-option label="待审核" value="pending" />
-          <el-option label="已通过" value="approved" />
-          <el-option label="已拒绝" value="rejected" />
-        </el-select>
-        <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
-      </div>
-    </div>
-
-    <div class="table-scroll-wrap">
-    <el-table :data="list" v-loading="loading" border stripe>
-      <el-table-column prop="id" label="ID" width="70" />
-      <el-table-column label="用户" width="120">
-        <template slot-scope="{ row }">
-          {{ row.nickname || row.userName || '-' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="提现金额" width="120">
-        <template slot-scope="{ row }">
-          <span class="amount">{{ formatPriceWithSymbol(row.amount) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="账户信息" min-width="160" show-overflow-tooltip>
-        <template slot-scope="{ row }">
-          {{ row.accountInfo || '-' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="状态" width="100">
-        <template slot-scope="{ row }">
-          <el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column label="申请人备注" width="160" show-overflow-tooltip>
-        <template slot-scope="{ row }">
-          {{ row.remark || '-' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="审核人" width="100">
-        <template slot-scope="{ row }">
-          {{ row.auditBy || '-' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="审核时间" width="160">
-        <template slot-scope="{ row }">
-          {{ row.auditAt ? formatTime(row.auditAt) : '-' }}
-        </template>
-      </el-table-column>
-      <el-table-column prop="createTime" label="申请时间" width="160">
-        <template slot-scope="{ row }">
-          {{ formatTime(row.createTime) }}
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" width="180" fixed="right">
-        <template slot-scope="{ row }">
-          <el-button size="mini" type="info" @click="viewDetail(row)">详情</el-button>
-          <el-dropdown v-if="row.status === 'pending'" trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
-            <el-button size="mini">
-              审核<i class="el-icon-arrow-down el-icon--right"></i>
-            </el-button>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item command="approve" icon="el-icon-check">通过</el-dropdown-item>
-              <el-dropdown-item command="reject" icon="el-icon-close">拒绝</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
-        </template>
-      </el-table-column>
-    </el-table></div>
-
-    <el-pagination
-      @size-change="onPageChange"
-      @current-change="onPageChange"
-      :current-page="page"
-      :page-size="size"
-      :total="total"
-      layout="total, prev, pager, next"
-      class="pagination-wrap"
-    />
-
-    <!-- 拒绝原因弹窗 -->
-    <el-dialog title="拒绝提现" :visible.sync="rejectDialogVisible" width="400px">
-      <el-input v-model="rejectReason" type="textarea" :rows="3" placeholder="请输入拒绝原因(选填)" />
-      <span slot="footer">
-        <el-button @click="rejectDialogVisible = false">取消</el-button>
-        <el-button type="danger" @click="confirmReject">确认拒绝</el-button>
-      </span>
-    </el-dialog>
-
-    <!-- 提现详情弹窗 -->
-    <el-dialog title="提现详情" :visible.sync="detailDialogVisible" width="600px">
-      <el-descriptions :column="2" border v-if="detail">
-        <el-descriptions-item label="申请ID">{{ detail.id }}</el-descriptions-item>
-        <el-descriptions-item label="用户昵称">{{ detail.nickname || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="提现金额">{{ formatPriceWithSymbol(detail.amount) }}</el-descriptions-item>
-        <el-descriptions-item label="账户信息">{{ detail.accountInfo || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="申请备注">{{ detail.remark || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="审核状态">
-          <el-tag :type="statusType(detail.status)">{{ statusLabel(detail.status) }}</el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="审核人">{{ detail.auditBy || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="审核备注">{{ detail.auditRemark || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="审核时间">{{ detail.auditAt ? formatTime(detail.auditAt) : '-' }}</el-descriptions-item>
-        <el-descriptions-item label="申请时间">{{ formatTime(detail.createTime) }}</el-descriptions-item>
-      </el-descriptions>
-      <span slot="footer">
-        <el-button @click="detailDialogVisible = false">关闭</el-button>
-      </span>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { getWithdrawalList, auditWithdrawal } from '@/api/admin'
-
-export default {
-  data() {
-    return {
-      list: [],
-      loading: false,
-      keyword: '',
-      page: 1,
-      size: 20,
-      total: 0,
-      statusFilter: '',
-      rejectDialogVisible: false,
-      rejectTarget: null,
-      rejectReason: '',
-      detailDialogVisible: false,
-      detail: null
-    }
-  },
-  mounted() {
-    this.loadList()
-  },
-  methods: {
-    async loadList() {
-      this.loading = true
-      try {
-        const res = await getWithdrawalList({ status: this.statusFilter, keyword: this.keyword })
-        this.list = res.data || []
-        this.total = (res.data || []).length
-      } catch (e) {
-        this.$message.error('加载失败')
-      } finally {
-        this.loading = false
-      }
-    },
-    handleSearch() {
-      this.page = 1
-      this.loadList()
-    },
-    onPageChange(val) {
-      this.page = val
-      this.loadList()
-    },
-    statusType(status) {
-      const map = { pending: 'warning', approved: 'success', rejected: 'danger' }
-      return map[status] || 'info'
-    },
-    statusLabel(status) {
-      const map = { pending: '待审核', approved: '已通过', rejected: '已拒绝' }
-      return map[status] || status
-    },
-    formatTime(t) {
-      if (!t) return '-'
-      return t.replace ? t.replace('T', ' ').substring(0, 19) : t
-    },
-    async handleAudit(row, status) {
-      const actionLabel = status === 'approved' ? '通过' : '拒绝'
-      try {
-        await this.$confirm(`确认${actionLabel}该提现申请?`, '提示')
-        await auditWithdrawal(row.id, status, '')
-        this.$message.success('操作成功')
-        this.loadList()
-      } catch (e) {
-        if (e !== 'cancel') this.$message.error('操作失败')
-      }
-    },
-    showRejectDialog(row) {
-      this.rejectTarget = row
-      this.rejectReason = ''
-      this.rejectDialogVisible = true
-    },
-    async confirmReject() {
-      try {
-        await auditWithdrawal(this.rejectTarget.id, 'rejected', this.rejectReason)
-        this.$message.success('已拒绝')
-        this.rejectDialogVisible = false
-        this.loadList()
-      } catch (e) {
-        this.$message.error('操作失败')
-      }
-    },
-    handleActionCmd(row, cmd) {
-      switch (cmd) {
-        case 'approve': this.handleAudit(row, 'approved'); break
-        case 'reject': this.showRejectDialog(row); break
-      }
-    },
-    viewDetail(row) {
-      this.detail = row
-      this.detailDialogVisible = true
-    }
-  }
-}
-</script>
-
-<style scoped>
-.withdraw-audit {
-  padding: 20px;
-}
-.amount {
-  font-weight: bold;
-  color: #f56c6c;
-}
-</style>