backup: kefu state before examiner-add feature on ExaminerManage

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-28 00:31:26 +08:00
parent a7f7bd0c39
commit b161077400
53 changed files with 6254 additions and 567 deletions

View File

@@ -6,6 +6,17 @@
<div class="no-permission-desc">请联系管理员开通权限</div>
</div>
<div v-else-if="!isAllClubScope" class="scope-block">
<el-alert
type="warning"
:closable="false"
show-icon
title="当前为具体小程序视图"
description="此处不可新增/编辑/删除全局考核称号。请切换顶栏为「集团汇总」后使用本页;或在「小程序配置 → 抢单考核标签」中仅做上架/下架。"
/>
<el-button type="primary" link @click="$router.push('/miniapp/kaohe-tags')">前往抢单考核标签</el-button>
</div>
<div v-else>
<!-- 板块选择 + 添加按钮 -->
<div class="section-header">
@@ -113,6 +124,9 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import request from '@/utils/request'
import { cloneDeep } from 'lodash-es'
import { getAdminClubScope } from '@/utils/club-context'
const isAllClubScope = computed(() => getAdminClubScope() === 'all')
const username = localStorage.getItem('username') || ''
const hasPermission = ref(true)

View File

@@ -1,8 +1,603 @@
<template>
<div class="exam-record-page">
<div v-if="!hasPermission" class="no-permission">
<el-empty description="无考核管理权限,请联系管理员开通 kaohepeizhi" />
</div>
<template v-else>
<!-- 统计概览 -->
<el-row :gutter="16" class="stats-row">
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card">
<div class="stat-label">记录总数</div>
<div class="stat-value">{{ stats.total }}</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card stat-pass">
<div class="stat-label">已通过</div>
<div class="stat-value">{{ stats.passed }}</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card stat-fail">
<div class="stat-label">未通过</div>
<div class="stat-value">{{ stats.failed }}</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card stat-doing">
<div class="stat-label">考核中</div>
<div class="stat-value">{{ stats.in_progress }}</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card stat-wait">
<div class="stat-label">待审核</div>
<div class="stat-value">{{ stats.pending }}</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="8" :md="4">
<el-card shadow="never" class="stat-card stat-fee">
<div class="stat-label">累计缴费()</div>
<div class="stat-value">{{ formatMoney(stats.total_fee) }}</div>
</el-card>
</el-col>
</el-row>
<!-- 标签维度统计 -->
<el-card v-if="stats.tag_stats?.length" shadow="never" class="section-card">
<template #header>
<span class="section-title">各标签考核统计</span>
</template>
<el-table :data="stats.tag_stats" size="small" stripe>
<el-table-column prop="chenghao_name" label="考核标签" min-width="140" />
<el-table-column prop="total" label="总数" width="80" align="center" />
<el-table-column prop="passed" label="通过" width="80" align="center">
<template #default="{ row }">
<span class="text-success">{{ row.passed }}</span>
</template>
</el-table-column>
<el-table-column prop="failed" label="未通过" width="80" align="center">
<template #default="{ row }">
<span class="text-danger">{{ row.failed }}</span>
</template>
</el-table-column>
<el-table-column prop="in_progress" label="考核中" width="80" align="center" />
<el-table-column prop="pending" label="待审核" width="80" align="center" />
</el-table>
</el-card>
<!-- 筛选 -->
<el-card shadow="never" class="section-card filter-card">
<el-form :inline="true" :model="filter" class="filter-form" @submit.prevent="handleSearch">
<el-form-item label="记录ID">
<el-input v-model="filter.jilu_id" placeholder="SH..." clearable style="width: 160px" />
</el-form-item>
<el-form-item label="打手">
<el-input v-model="filter.dashou_keyword" placeholder="ID / 昵称 / 手机" clearable style="width: 150px" />
</el-form-item>
<el-form-item label="考核官">
<el-input v-model="filter.kaoheguan_keyword" placeholder="ID / 昵称 / 手机" clearable style="width: 150px" />
</el-form-item>
<el-form-item label="板块">
<el-select v-model="filter.bankuai_id" placeholder="全部" clearable style="width: 120px">
<el-option v-for="b in allBankuai" :key="b.bankuai_id" :label="b.mingcheng" :value="b.bankuai_id" />
</el-select>
</el-form-item>
<el-form-item label="标签">
<el-select v-model="filter.chenghao_id" placeholder="全部" clearable filterable style="width: 140px">
<el-option v-for="t in allTags" :key="t.id" :label="t.mingcheng" :value="t.id" />
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="filter.zhuangtai" placeholder="全部" clearable style="width: 110px">
<el-option label="考核中" :value="0" />
<el-option label="已通过" :value="1" />
<el-option label="未通过" :value="2" />
<el-option label="待审核" :value="3" />
</el-select>
</el-form-item>
<el-form-item label="进度">
<el-select v-model="filter.assessed" placeholder="全部" clearable style="width: 120px">
<el-option label="已考核完" value="done" />
<el-option label="未考核完" value="undone" />
</el-select>
</el-form-item>
<el-form-item label="第几次">
<el-input v-model="filter.cishu" placeholder="次数" clearable style="width: 80px" />
</el-form-item>
<el-form-item label="时间">
<el-date-picker
v-model="dateRange"
type="datetimerange"
range-separator=""
start-placeholder="开始"
end-placeholder="结束"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 340px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="resetFilter">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 列表 -->
<el-card shadow="never" class="section-card table-card">
<el-table
v-loading="loading"
:data="recordList"
stripe
border
style="width: 100%"
class="record-table"
empty-text="暂无考核记录"
>
<el-table-column prop="jilu_id" label="记录ID" min-width="200" show-overflow-tooltip />
<el-table-column label="打手" min-width="180">
<template #default="{ row }">
<div class="user-cell">
<el-avatar :size="32" :src="avatarUrl(row.dashou?.avatar)" />
<div class="user-meta">
<div class="user-name">{{ row.dashou?.nicheng || '-' }}</div>
<div class="user-sub">{{ row.dashou?.yonghuid }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="考核官" min-width="180">
<template #default="{ row }">
<div v-if="row.kaoheguan" class="user-cell">
<el-avatar :size="32" :src="avatarUrl(row.kaoheguan.avatar)" />
<div class="user-meta">
<div class="user-name">{{ row.kaoheguan.nicheng }}</div>
<div class="user-sub">{{ row.kaoheguan.yonghuid }}</div>
</div>
</div>
<el-tag v-else type="info" size="small">未分配</el-tag>
</template>
</el-table-column>
<el-table-column prop="bankuai_name" label="板块" width="90" />
<el-table-column prop="chenghao_name" label="考核标签" width="110" show-overflow-tooltip />
<el-table-column prop="cishu" label="第几次" width="72" align="center" />
<el-table-column label="本次费用" width="90" align="right">
<template #default="{ row }">¥{{ formatMoney(row.current_fee) }}</template>
</el-table-column>
<el-table-column label="累计缴费" width="90" align="right">
<template #default="{ row }">¥{{ formatMoney(row.jiaofei_jine) }}</template>
</el-table-column>
<el-table-column label="状态" width="88" align="center">
<template #default="{ row }">
<el-tag :type="statusTagType(row.zhuangtai)" size="small">{{ row.zhuangtai_text }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="CreateTime" label="申请时间" width="168" />
<el-table-column label="操作" width="160" align="center">
<template #default="{ row }">
<el-button link type="primary" @click="openDetail(row)">详情</el-button>
<el-button
v-if="row.zhuangtai === 0"
link
type="warning"
@click="handleToPending(row)"
>退回待审核</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-wrap">
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
background
@current-change="fetchList"
@size-change="fetchList"
/>
</div>
</el-card>
</template>
<!-- 详情抽屉 -->
<el-drawer v-model="detailVisible" title="考核记录详情" size="520px" destroy-on-close>
<template v-if="detailData">
<el-descriptions :column="1" border size="small" class="detail-block">
<el-descriptions-item label="记录ID">{{ detailData.jilu_id }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="statusTagType(detailData.zhuangtai)" size="small">{{ detailData.zhuangtai_text }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="板块">{{ detailData.bankuai_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="考核标签">{{ detailData.chenghao_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="第几次考核"> {{ detailData.cishu }} </el-descriptions-item>
<el-descriptions-item label="申请时间">{{ detailData.CreateTime }}</el-descriptions-item>
<el-descriptions-item label="更新时间">{{ detailData.UpdateTime }}</el-descriptions-item>
</el-descriptions>
<h4 class="block-title">打手信息</h4>
<div class="profile-card">
<el-avatar :size="48" :src="avatarUrl(detailData.dashou?.avatar)" />
<div>
<div>{{ detailData.dashou?.nicheng }}{{ detailData.dashou?.yonghuid }}</div>
<div class="sub">手机{{ detailData.dashou?.phone || '-' }} · 游戏ID{{ detailData.dashou?.game_id || '-' }}</div>
<div v-if="detailData.dashou?.beizhu" class="sub">备注{{ detailData.dashou.beizhu }}</div>
</div>
</div>
<h4 class="block-title">考核官</h4>
<div v-if="detailData.kaoheguan" class="profile-card">
<el-avatar :size="48" :src="avatarUrl(detailData.kaoheguan.avatar)" />
<div>
<div>{{ detailData.kaoheguan.nicheng }}{{ detailData.kaoheguan.yonghuid }}</div>
<div class="sub">手机{{ detailData.kaoheguan.phone || '-' }} · 游戏ID{{ detailData.kaoheguan.game_id || '-' }}</div>
</div>
</div>
<el-empty v-else description="尚未分配考核官" :image-size="60" />
<h4 v-if="detailData.guize_neirong" class="block-title">考核规则</h4>
<div v-if="detailData.guize_neirong" class="rule-box">{{ detailData.guize_neirong }}</div>
<h4 class="block-title">缴费明细</h4>
<el-table :data="detailData.fee_list || []" size="small" border empty-text="暂无明细">
<el-table-column prop="cishu" label="第几次" width="80" align="center" />
<el-table-column label="金额" align="right">
<template #default="{ row }">¥{{ formatMoney(row.jine) }}</template>
</el-table-column>
</el-table>
<h4 class="block-title">拒绝历史</h4>
<el-timeline v-if="detailData.reject_list?.length">
<el-timeline-item
v-for="(item, idx) in detailData.reject_list"
:key="idx"
:timestamp="item.CreateTime"
placement="top"
>
<div> {{ item.cishu }} · 考核官{{ item.shenheguan_nicheng }}{{ item.shenheguan_id }}</div>
<div class="reject-reason">{{ item.yuanyin }}</div>
</el-timeline-item>
</el-timeline>
<el-empty v-else description="无拒绝记录" :image-size="60" />
<div v-if="detailData.zhuangtai === 0" class="drawer-actions">
<el-button type="warning" @click="handleToPending(detailData, true)">退回待审核取消指定考核官</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
<script>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
const username = localStorage.getItem('username') || ''
const hasPermission = ref(true)
const loading = ref(false)
const recordList = ref([])
const allBankuai = ref([])
const allTags = ref([])
const dateRange = ref(null)
const stats = reactive({
total: 0,
passed: 0,
failed: 0,
in_progress: 0,
pending: 0,
total_fee: 0,
tag_stats: [],
})
const filter = reactive({
jilu_id: '',
dashou_keyword: '',
kaoheguan_keyword: '',
bankuai_id: null,
chenghao_id: null,
zhuangtai: null,
assessed: null,
cishu: '',
})
const pagination = reactive({
page: 1,
pageSize: 20,
total: 0,
})
const detailVisible = ref(false)
const detailData = ref(null)
const formatMoney = (val) => {
if (val === undefined || val === null) return '0.00'
return Number(val).toFixed(2)
}
const avatarUrl = (path) => {
if (!path) return ''
if (path.startsWith('http')) return path
return (window.$ossURL || '') + path
}
const statusTagType = (s) => {
const map = { 0: 'warning', 1: 'success', 2: 'danger', 3: 'info' }
return map[s] || 'info'
}
const buildParams = () => {
const params = {
phone: username,
page: pagination.page,
page_size: pagination.pageSize,
}
if (filter.jilu_id) params.jilu_id = filter.jilu_id
if (filter.dashou_keyword) params.dashou_keyword = filter.dashou_keyword
if (filter.kaoheguan_keyword) params.kaoheguan_keyword = filter.kaoheguan_keyword
if (filter.bankuai_id != null && filter.bankuai_id !== '') params.bankuai_id = filter.bankuai_id
if (filter.chenghao_id != null && filter.chenghao_id !== '') params.chenghao_id = filter.chenghao_id
if (filter.zhuangtai != null && filter.zhuangtai !== '') params.zhuangtai = filter.zhuangtai
if (filter.assessed) params.assessed = filter.assessed
if (filter.cishu) params.cishu = filter.cishu
if (dateRange.value?.length === 2) {
params.start_time = dateRange.value[0]
params.end_time = dateRange.value[1]
}
return params
}
const fetchList = async () => {
loading.value = true
try {
const res = await request.post('/houtai/khjlgl', buildParams())
if (res.code === 0) {
const data = res.data || {}
recordList.value = Array.isArray(data.list) ? data.list : []
pagination.total = Number(data.total) || 0
allBankuai.value = data.all_bankuai || []
allTags.value = data.all_tags || []
const s = data.stats || {}
Object.assign(stats, {
total: s.total || 0,
passed: s.passed || 0,
failed: s.failed || 0,
in_progress: s.in_progress || 0,
pending: s.pending || 0,
total_fee: s.total_fee || 0,
tag_stats: s.tag_stats || [],
})
if (pagination.total > 0 && recordList.value.length === 0) {
ElMessage.warning('统计有数据但当前页列表为空,请检查后端是否已部署最新 khjlgl 接口')
}
} else if (res.code === 403) {
hasPermission.value = false
} else {
ElMessage.error(res.msg || '加载失败')
}
} catch (e) {
ElMessage.error('请求失败:请确认后端已部署 /houtai/khjlgl')
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.page = 1
fetchList()
}
const resetFilter = () => {
filter.jilu_id = ''
filter.dashou_keyword = ''
filter.kaoheguan_keyword = ''
filter.bankuai_id = null
filter.chenghao_id = null
filter.zhuangtai = null
filter.assessed = null
filter.cishu = ''
dateRange.value = null
pagination.page = 1
fetchList()
}
const openDetail = async (row) => {
try {
const res = await request.post('/houtai/khjlcz', {
phone: username,
action: 'get_detail',
jilu_id: row.jilu_id,
})
if (res.code === 0) {
detailData.value = res.data
detailVisible.value = true
} else {
ElMessage.error(res.msg || '获取详情失败')
}
} catch (e) {
ElMessage.error('网络错误')
}
}
const handleToPending = async (row, fromDrawer = false) => {
try {
await ElMessageBox.confirm(
'将把该记录从「考核中」退回「待审核」,并取消当前考核官指定。是否继续?',
'确认操作',
{ type: 'warning' },
)
const res = await request.post('/houtai/khjlcz', {
phone: username,
action: 'to_pending',
jilu_id: row.jilu_id,
})
if (res.code === 0) {
ElMessage.success(res.msg || '操作成功')
if (fromDrawer) detailVisible.value = false
fetchList()
} else {
ElMessage.error(res.msg || '操作失败')
}
} catch (e) {
if (e !== 'cancel') ElMessage.error('操作失败')
}
}
onMounted(() => {
if (!username) {
ElMessage.error('未登录')
return
}
fetchList()
})
</script>
<style>
</style>
<style scoped>
.exam-record-page {
padding: 16px;
background: #f5f7fa;
min-height: 100%;
}
.stats-row {
margin-bottom: 16px;
}
.stat-card {
text-align: center;
margin-bottom: 8px;
}
.stat-card :deep(.el-card__body) {
padding: 16px 12px;
}
.stat-label {
font-size: 13px;
color: #909399;
margin-bottom: 6px;
}
.stat-value {
font-size: 24px;
font-weight: 600;
color: #303133;
}
.stat-pass .stat-value { color: #67c23a; }
.stat-fail .stat-value { color: #f56c6c; }
.stat-doing .stat-value { color: #e6a23c; }
.stat-wait .stat-value { color: #409eff; }
.stat-fee .stat-value { font-size: 18px; }
.section-card {
margin-bottom: 16px;
}
.section-title {
font-weight: 600;
}
.filter-form {
display: flex;
flex-wrap: wrap;
gap: 4px 0;
}
/* 仅保证明细表格文字在 Layout 深色背景下可读,不改布局 */
.record-table :deep(.el-table__body),
.record-table :deep(.el-table__header) {
color: #303133;
}
.record-table :deep(.el-table__header th) {
color: #606266;
background: #fafafa;
}
.user-cell {
display: flex;
align-items: center;
gap: 8px;
}
.user-meta {
min-width: 0;
}
.user-name {
font-size: 13px;
font-weight: 500;
line-height: 1.3;
color: #303133;
}
.user-sub {
font-size: 12px;
color: #909399;
}
.text-success { color: #67c23a; }
.text-danger { color: #f56c6c; }
.pagination-wrap {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
.no-permission {
padding: 80px 0;
}
.block-title {
margin: 20px 0 10px;
font-size: 14px;
font-weight: 600;
color: #303133;
}
.profile-card {
display: flex;
gap: 12px;
align-items: center;
padding: 12px;
background: #f5f7fa;
border-radius: 8px;
}
.profile-card .sub {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
.rule-box {
padding: 12px;
background: #fafafa;
border-radius: 6px;
font-size: 13px;
line-height: 1.6;
white-space: pre-wrap;
}
.reject-reason {
margin-top: 4px;
color: #606266;
font-size: 13px;
}
.drawer-actions {
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #ebeef5;
}
.detail-block {
margin-bottom: 8px;
}
</style>

View File

@@ -21,8 +21,19 @@
<el-input v-model="filter.bankuai_name" placeholder="板块名称" clearable class="dark-input filter-input" />
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="resetFilter">重置</el-button>
<el-button type="success" :disabled="isAllClubScope" @click="openAddDialog">添加考核官</el-button>
</div>
<el-alert
v-if="isAllClubScope"
type="warning"
:closable="false"
show-icon
class="scope-alert"
title="请切换到具体小程序视图后再添加考核官"
description="添加考核官只能为本俱乐部用户操作,集团汇总视图下不可用。"
/>
<!-- 板块标签统计可折叠 -->
<el-collapse v-model="activeCollapse" class="stat-collapse">
<el-collapse-item title="板块标签统计" name="stats">
@@ -211,6 +222,46 @@
<el-button v-if="isEditMode" type="success" @click="saveExaminer" :loading="saving">保存</el-button>
</template>
</el-dialog>
<!-- 添加考核官 -->
<el-dialog
v-model="addVisible"
title="添加考核官"
width="520px"
@close="closeAddDialog"
custom-class="dark-dialog"
>
<el-form :model="addForm" label-width="110px">
<el-form-item label="用户ID" required>
<el-input v-model="addForm.yonghuid" placeholder="输入要打手用户ID" clearable class="dark-input" />
</el-form-item>
<el-form-item label="认证板块" required>
<el-select
v-model="addForm.bankuai_ids"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="选择板块(可多选)"
class="dark-select"
style="width: 100%"
>
<el-option
v-for="bk in allBankuaiList"
:key="bk.bankuai_id"
:label="bk.mingcheng"
:value="bk.bankuai_id"
/>
</el-select>
</el-form-item>
<el-form-item label="认证状态">
<el-switch v-model="addForm.is_renzheng" active-text="已认证" inactive-text="未认证" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="addVisible = false">取消</el-button>
<el-button type="primary" :loading="addSaving" @click="submitAddExaminer">确认添加</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -219,10 +270,12 @@ import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import request from '@/utils/request'
import { cloneDeep } from 'lodash-es'
import { JITUAN_API, getAdminClubScope } from '@/utils/club-context'
const username = localStorage.getItem('username') || ''
const hasPermission = ref(true)
const loading = ref(false)
const isAllClubScope = computed(() => getAdminClubScope() === 'all')
// 筛选条件
const filter = reactive({
@@ -248,6 +301,13 @@ const detailVisible = ref(false)
const isEditMode = ref(false)
const currentExaminer = ref({})
const saving = ref(false)
const addVisible = ref(false)
const addSaving = ref(false)
const addForm = reactive({
yonghuid: '',
bankuai_ids: [],
is_renzheng: true,
})
// 板块标签统计
const bankuaiTagsData = ref([])
@@ -286,7 +346,7 @@ const fetchExaminerList = async () => {
page_size: pagination.pageSize,
...filter
}
const res = await request.post('/houtai/khggl', params)
const res = await request.post(JITUAN_API.khggl, params)
if (res.code === 0) {
const list = (res.data.list || []).map(item => ({
...item,
@@ -354,7 +414,7 @@ const addBankuai = async () => {
return
}
try {
const res = await request.post('/houtai/shgxgsj', {
const res = await request.post(JITUAN_API.shgxgsj, {
phone: username,
yonghuid: currentExaminer.value.yonghuid,
action: 'add_bankuai',
@@ -382,7 +442,7 @@ const addBankuai = async () => {
// 移除板块
const removeBankuai = async (bankuaiId) => {
try {
const res = await request.post('/houtai/shgxgsj', {
const res = await request.post(JITUAN_API.shgxgsj, {
phone: username,
yonghuid: currentExaminer.value.yonghuid,
action: 'remove_bankuai',
@@ -413,7 +473,7 @@ const saveExaminer = async () => {
saving.value = true
try {
const res = await request.post('/houtai/shgxgsj', payload)
const res = await request.post(JITUAN_API.shgxgsj, payload)
if (res.code === 0) {
ElMessage.success('修改成功')
isEditMode.value = false
@@ -434,6 +494,53 @@ const saveExaminer = async () => {
}
}
const openAddDialog = () => {
if (isAllClubScope.value) {
ElMessage.warning('请切换到具体小程序视图后再添加考核官')
return
}
addForm.yonghuid = ''
addForm.bankuai_ids = []
addForm.is_renzheng = true
addVisible.value = true
}
const closeAddDialog = () => {
addVisible.value = false
}
const submitAddExaminer = async () => {
const uid = (addForm.yonghuid || '').trim()
if (!uid) {
ElMessage.warning('请输入用户ID')
return
}
if (!addForm.bankuai_ids.length) {
ElMessage.warning('请选择至少一个板块')
return
}
addSaving.value = true
try {
const res = await request.post(JITUAN_API.khgglAdd, {
phone: username,
yonghuid: uid,
bankuai_ids: addForm.bankuai_ids,
is_renzheng: addForm.is_renzheng,
})
if (res.code === 0) {
ElMessage.success(res.msg || '添加成功')
addVisible.value = false
fetchExaminerList()
} else {
ElMessage.error(res.msg || '添加失败')
}
} catch (e) {
ElMessage.error('网络错误')
} finally {
addSaving.value = false
}
}
onMounted(() => {
if (!username) {
ElMessage.error('未登录')
@@ -474,6 +581,7 @@ onMounted(() => {
}
.filter-input { width: 160px; }
.filter-select { width: 140px; }
.scope-alert { margin-bottom: 16px; }
/* 板块标签统计面板 */
.stat-collapse {