第一次提交:Vue3 后台前端项目当前最新版
This commit is contained in:
420
src/views/assessment/ExamConfig.vue
Normal file
420
src/views/assessment/ExamConfig.vue
Normal file
@@ -0,0 +1,420 @@
|
||||
<template>
|
||||
<div class="exam-config">
|
||||
<div v-if="!hasPermission" class="no-permission">
|
||||
<div class="no-permission-icon">🔒</div>
|
||||
<div class="no-permission-text">您无权访问此页面</div>
|
||||
<div class="no-permission-desc">请联系管理员开通权限</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<!-- 板块选择 + 添加按钮 -->
|
||||
<div class="section-header">
|
||||
<div class="header-item">
|
||||
<span class="label">选择板块</span>
|
||||
<el-select v-model="currentBankuaiId" placeholder="全部板块" clearable @change="onBankuaiChange" class="dark-select">
|
||||
<el-option v-for="bk in bankuaiList" :key="bk.bankuai_id" :label="bk.mingcheng" :value="bk.bankuai_id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button type="primary" :icon="Plus" @click="openCreateDialog">添加新称号</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 称号卡片网格 -->
|
||||
<div class="chenghao-grid" v-loading="loading">
|
||||
<div v-for="ch in filteredChenghao" :key="ch.id" class="chenghao-card">
|
||||
<div class="card-header">
|
||||
<span class="ch-name">{{ ch.mingcheng }}</span>
|
||||
<span class="ch-type">{{ ch.leixing_name }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="info-line"><span>所属板块:</span>{{ getBankuaiName(ch.bankuai_id) }}</div>
|
||||
<div class="info-line"><span>金牌:</span>{{ ch.kaioi_jinpai ? '开启' : '关闭' }}</div>
|
||||
<div class="info-line"><span>创建时间:</span>{{ ch.create_time }}</div>
|
||||
<div class="info-line"><span>考核次数:</span>{{ ch.max_cishu }} 次</div>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<el-button size="small" @click="openDetailDialog(ch)">详情</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && filteredChenghao.length === 0" class="empty-state">
|
||||
<el-empty description="暂无称号数据" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详情/编辑弹窗 -->
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
:title="isNewChenghao ? '新建称号' : (isEditMode ? '编辑称号' : '称号详情')"
|
||||
width="700px"
|
||||
@close="closeDetailDialog"
|
||||
custom-class="dark-dialog"
|
||||
>
|
||||
<el-form :model="currentChenghao" :rules="formRules" ref="detailFormRef" label-width="100px" :disabled="!isEditMode">
|
||||
<el-form-item label="称号名称" prop="mingcheng">
|
||||
<el-input v-model="currentChenghao.mingcheng" maxlength="50" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="leixing">
|
||||
<el-select v-model="currentChenghao.leixing" class="dark-select">
|
||||
<el-option label="打手" value="dashou" />
|
||||
<el-option label="老板" value="boss" />
|
||||
<el-option label="商家" value="shangjia" />
|
||||
<el-option label="管事" value="guanshi" />
|
||||
<el-option label="组长" value="zuzhang" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属板块" prop="bankuai_id">
|
||||
<el-select v-model="currentChenghao.bankuai_id" placeholder="可选" clearable class="dark-select">
|
||||
<el-option v-for="bk in bankuaiList" :key="bk.bankuai_id" :label="bk.mingcheng" :value="bk.bankuai_id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="特效描述">
|
||||
<el-input v-model="currentChenghao.texiao_miaoshu" type="textarea" rows="3" />
|
||||
</el-form-item>
|
||||
<el-form-item label="考核规则">
|
||||
<el-input v-model="currentChenghao.kaohe_guize" type="textarea" rows="4" />
|
||||
</el-form-item>
|
||||
<el-form-item label="同时开启金牌">
|
||||
<el-switch v-model="currentChenghao.kaioi_jinpai" :disabled="!isEditMode" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 考核费用区域 -->
|
||||
<el-divider content-position="left">考核费用 (每次需缴纳金额)</el-divider>
|
||||
<div class="feiyong-section">
|
||||
<div v-if="feiyongList.length === 0" class="empty-feiyong">暂未设置费用</div>
|
||||
<div v-for="(item, index) in feiyongList" :key="index" class="feiyong-row">
|
||||
<span class="feiyong-label">第 {{ item.cishu }} 次:</span>
|
||||
<template v-if="isEditMode">
|
||||
<el-input-number v-model="item.feiyong" :min="0" :step="10" style="width: 140px" />
|
||||
<el-button v-if="item.cishu > 1" size="small" type="danger" plain @click="removeFeiyong(index)">删除</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="feiyong-value">{{ formatMoney(item.feiyong) }} 元</span>
|
||||
</template>
|
||||
</div>
|
||||
<el-button v-if="isEditMode" size="small" type="primary" plain @click="addFeiyongRow" class="add-row-btn">
|
||||
+ 添加新次数
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">取消</el-button>
|
||||
<el-button v-if="!isEditMode && !isNewChenghao" type="primary" @click="enterEditMode">编辑</el-button>
|
||||
<el-button v-if="isEditMode" type="success" @click="saveChenghao" :loading="saving">保存</el-button>
|
||||
<el-button v-if="isEditMode && !isNewChenghao" type="danger" plain @click="deleteChenghao">删除此称号</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import request from '@/utils/request'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
const username = localStorage.getItem('username') || ''
|
||||
const hasPermission = ref(true)
|
||||
const loading = ref(false)
|
||||
|
||||
// 板块
|
||||
const bankuaiList = ref([])
|
||||
const currentBankuaiId = ref(null)
|
||||
|
||||
// 称号数据
|
||||
const allChenghao = ref([])
|
||||
const filteredChenghao = computed(() => {
|
||||
if (!currentBankuaiId.value) return allChenghao.value
|
||||
return allChenghao.value.filter(ch => ch.bankuai_id === currentBankuaiId.value)
|
||||
})
|
||||
|
||||
// 弹窗状态
|
||||
const detailVisible = ref(false)
|
||||
const isEditMode = ref(false)
|
||||
const isNewChenghao = ref(false)
|
||||
const currentChenghao = ref({})
|
||||
const feiyongList = ref([]) // [{cishu, feiyong}, ...]
|
||||
const detailFormRef = ref(null)
|
||||
const saving = ref(false)
|
||||
|
||||
// 表单校验
|
||||
const formRules = {
|
||||
mingcheng: [{ required: true, message: '请输入称号名称', trigger: 'blur' }],
|
||||
leixing: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
||||
}
|
||||
|
||||
// 工具函数
|
||||
const getBankuaiName = (id) => {
|
||||
const bk = bankuaiList.value.find(b => b.bankuai_id === id)
|
||||
return bk ? bk.mingcheng : '未指定'
|
||||
}
|
||||
const formatMoney = (val) => {
|
||||
if (val === undefined || val === null) return '0.00'
|
||||
return Number(val).toFixed(2)
|
||||
}
|
||||
|
||||
// 获取所有配置
|
||||
const fetchData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/khpzhq', { phone: username })
|
||||
if (res.code === 0) {
|
||||
bankuaiList.value = res.data.bankuai || []
|
||||
allChenghao.value = res.data.chenghao || []
|
||||
if (bankuaiList.value.length > 0 && !currentBankuaiId.value) {
|
||||
currentBankuaiId.value = bankuaiList.value[0].bankuai_id
|
||||
}
|
||||
} else if (res.code === 403) {
|
||||
hasPermission.value = false
|
||||
} else {
|
||||
ElMessage.error(res.msg || '获取数据失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 板块切换
|
||||
const onBankuaiChange = () => {}
|
||||
|
||||
// 打开详情
|
||||
const openDetailDialog = (ch) => {
|
||||
isNewChenghao.value = false
|
||||
isEditMode.value = false
|
||||
currentChenghao.value = cloneDeep(ch)
|
||||
// 费用字典转数组排序
|
||||
const feeDict = ch.feiyong || {}
|
||||
feiyongList.value = Object.keys(feeDict).map(cishu => ({
|
||||
cishu: Number(cishu),
|
||||
feiyong: feeDict[cishu]
|
||||
})).sort((a, b) => a.cishu - b.cishu)
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
// 进入编辑模式
|
||||
const enterEditMode = () => {
|
||||
isEditMode.value = true
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const closeDetailDialog = () => {
|
||||
detailVisible.value = false
|
||||
isEditMode.value = false
|
||||
isNewChenghao.value = false
|
||||
currentChenghao.value = {}
|
||||
feiyongList.value = []
|
||||
}
|
||||
|
||||
// 添加新费用次数
|
||||
const addFeiyongRow = () => {
|
||||
const maxCishu = feiyongList.value.length > 0
|
||||
? Math.max(...feiyongList.value.map(f => f.cishu))
|
||||
: 0
|
||||
feiyongList.value.push({ cishu: maxCishu + 1, feiyong: 0 })
|
||||
}
|
||||
|
||||
// 删除费用项
|
||||
const removeFeiyong = (index) => {
|
||||
feiyongList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
// 保存(创建或更新)
|
||||
const saveChenghao = async () => {
|
||||
try {
|
||||
await detailFormRef.value?.validate()
|
||||
} catch { return }
|
||||
|
||||
// 确保至少有一次费用
|
||||
if (feiyongList.value.length === 0) {
|
||||
ElMessage.warning('请至少设置第1次考核费用')
|
||||
return
|
||||
}
|
||||
// 确保序号连续并包含第1次
|
||||
const cishuSet = new Set(feiyongList.value.map(f => f.cishu))
|
||||
if (!cishuSet.has(1)) {
|
||||
ElMessage.warning('必须包含第1次考核费用')
|
||||
return
|
||||
}
|
||||
|
||||
const payload = {
|
||||
phone: username,
|
||||
action: isNewChenghao.value ? 'create' : 'update',
|
||||
mingcheng: currentChenghao.value.mingcheng,
|
||||
leixing: currentChenghao.value.leixing,
|
||||
bankuai_id: currentChenghao.value.bankuai_id,
|
||||
texiao_miaoshu: currentChenghao.value.texiao_miaoshu || '',
|
||||
kaohe_guize: currentChenghao.value.kaohe_guize || '',
|
||||
kaioi_jinpai: currentChenghao.value.kaioi_jinpai,
|
||||
feiyong_list: feiyongList.value.map(item => ({
|
||||
cishu: item.cishu,
|
||||
feiyong: item.feiyong
|
||||
}))
|
||||
}
|
||||
if (!isNewChenghao.value) {
|
||||
payload.chenghao_id = currentChenghao.value.id
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/chzsgc', payload)
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(isNewChenghao.value ? '创建成功' : '修改成功')
|
||||
detailVisible.value = false
|
||||
await fetchData()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '操作失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除称号
|
||||
const deleteChenghao = async () => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定删除该称号吗?所有相关费用将被清除。', '警告', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确认删除'
|
||||
})
|
||||
} catch { return }
|
||||
|
||||
try {
|
||||
const res = await request.post('/houtai/chzsgc', {
|
||||
phone: username,
|
||||
action: 'delete',
|
||||
chenghao_id: currentChenghao.value.id
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功')
|
||||
detailVisible.value = false
|
||||
await fetchData()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
}
|
||||
}
|
||||
|
||||
// 打开创建弹窗
|
||||
const openCreateDialog = () => {
|
||||
isNewChenghao.value = true
|
||||
isEditMode.value = true
|
||||
currentChenghao.value = {
|
||||
mingcheng: '',
|
||||
leixing: 'dashou',
|
||||
bankuai_id: currentBankuaiId.value || (bankuaiList.value.length > 0 ? bankuaiList.value[0].bankuai_id : null),
|
||||
texiao_miaoshu: '',
|
||||
kaohe_guize: '',
|
||||
kaioi_jinpai: false
|
||||
}
|
||||
feiyongList.value = [{ cishu: 1, feiyong: 0 }]
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!username) {
|
||||
ElMessage.error('未登录')
|
||||
return
|
||||
}
|
||||
fetchData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.exam-config {
|
||||
padding: 20px;
|
||||
color: #e0e0e0;
|
||||
min-height: 100vh;
|
||||
background: radial-gradient(circle at top, #1a1a2e 0%, #0d0d1a 100%);
|
||||
}
|
||||
|
||||
.no-permission {
|
||||
text-align: center;
|
||||
padding: 120px 0;
|
||||
color: #c0a060;
|
||||
}
|
||||
.no-permission-icon { font-size: 64px; filter: drop-shadow(0 0 10px #ffd700); }
|
||||
.no-permission-text { font-size: 22px; margin: 24px 0 12px; color: #ffd700; }
|
||||
.no-permission-desc { font-size: 15px; color: #b0a080; }
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.header-item { display: flex; align-items: center; gap: 12px; }
|
||||
.label { font-weight: bold; color: #ffd700; }
|
||||
|
||||
.chenghao-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
.chenghao-card {
|
||||
background: rgba(18,18,30,0.8);
|
||||
backdrop-filter: blur(14px);
|
||||
border: 1px solid rgba(255,215,0,0.25);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 8px 20px rgba(0,0,0,0.5);
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(255,215,0,0.15);
|
||||
}
|
||||
.ch-name { font-size: 18px; font-weight: 600; color: #ffd700; }
|
||||
.ch-type { font-size: 12px; background: rgba(255,215,0,0.15); color: #ffd700; padding: 2px 8px; border-radius: 10px; }
|
||||
.card-body .info-line { font-size: 13px; color: #ccc; margin-bottom: 6px; }
|
||||
.card-body .info-line span { color: #888; }
|
||||
.card-actions { margin-top: 12px; text-align: right; }
|
||||
.empty-state { margin-top: 40px; }
|
||||
|
||||
/* 弹窗暗黑 */
|
||||
:deep(.dark-dialog) {
|
||||
background: #1a1a2e !important;
|
||||
border: 1px solid #ffd700 !important;
|
||||
border-radius: 20px !important;
|
||||
}
|
||||
:deep(.dark-dialog .el-dialog__header) { border-bottom: 1px solid #ffd700; }
|
||||
:deep(.dark-dialog .el-dialog__title) { color: #ffd700; font-weight: bold; }
|
||||
|
||||
/* 费用区域 */
|
||||
.feiyong-section {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.feiyong-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.feiyong-label { color: #ccc; width: 80px; }
|
||||
.feiyong-value { color: #ffd700; font-weight: 600; }
|
||||
.empty-feiyong { color: #888; margin-bottom: 10px; }
|
||||
.add-row-btn { margin-top: 5px; }
|
||||
|
||||
/* 全局控件暗黑 */
|
||||
:deep(.el-input__inner),
|
||||
:deep(.el-select .el-input__inner),
|
||||
:deep(.el-textarea__inner) {
|
||||
background-color: #2a2a3c !important;
|
||||
border-color: #ffd700 !important;
|
||||
color: #e0e0e0 !important;
|
||||
}
|
||||
:deep(.el-input-number__decrease),
|
||||
:deep(.el-input-number__increase) {
|
||||
background-color: #1f1f30 !important;
|
||||
color: #ffd700 !important;
|
||||
}
|
||||
</style>
|
||||
8
src/views/assessment/ExamRecord.vue
Normal file
8
src/views/assessment/ExamRecord.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
586
src/views/assessment/ExaminerManage.vue
Normal file
586
src/views/assessment/ExaminerManage.vue
Normal file
@@ -0,0 +1,586 @@
|
||||
<template>
|
||||
<div class="examiner-manager">
|
||||
<div v-if="!hasPermission" class="no-permission">
|
||||
<div class="no-permission-icon">🔒</div>
|
||||
<div class="no-permission-text">您无权访问此页面</div>
|
||||
<div class="no-permission-desc">请联系管理员开通权限</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<!-- 顶部筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<el-input v-model="filter.yonghuid" placeholder="用户ID" clearable class="dark-input filter-input" />
|
||||
<el-select v-model="filter.zhuangtai" placeholder="账号状态" clearable class="dark-select filter-select">
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
<el-select v-model="filter.shenhe_zhuangtai" placeholder="审核官状态" clearable class="dark-select filter-select">
|
||||
<el-option label="空闲" :value="0" />
|
||||
<el-option label="审核中" :value="1" />
|
||||
</el-select>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<!-- 板块标签统计(可折叠) -->
|
||||
<el-collapse v-model="activeCollapse" class="stat-collapse">
|
||||
<el-collapse-item title="板块标签统计" name="stats">
|
||||
<div class="bankuai-tags-grid">
|
||||
<div v-for="bk in bankuaiTagsData" :key="bk.bankuai_id" class="bankuai-tags-card">
|
||||
<div class="card-title">{{ bk.mingcheng }}</div>
|
||||
<div class="tags-list">
|
||||
<el-tag v-for="tag in bk.tags" :key="tag.id" size="small" class="tag-item">
|
||||
{{ tag.name }}({{ tag.user_count }})
|
||||
</el-tag>
|
||||
<span v-if="bk.tags.length === 0" class="empty-tip">暂无标签</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table :data="examinerList" style="width: 100%" class="dark-table" v-loading="loading" border>
|
||||
<el-table-column prop="yonghuid" label="用户ID" width="120" />
|
||||
<el-table-column prop="phone" label="手机号" width="140" />
|
||||
<el-table-column prop="nicheng" label="打手昵称" width="120" />
|
||||
<el-table-column label="认证状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.is_renzheng ? 'success' : 'info'">
|
||||
{{ row.is_renzheng ? '已认证' : '未认证' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zhuangtai" label="账号状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.zhuangtai === 1 ? 'success' : 'danger'">
|
||||
{{ row.zhuangtai === 1 ? '正常' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="shenhe_zhuangtai" label="审核官状态" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.shenhe_zhuangtai === 0 ? 'info' : 'warning'">
|
||||
{{ row.shenhe_zhuangtai === 0 ? '空闲' : '审核中' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="shenhe_zongshu" label="审核总数" width="100" />
|
||||
<el-table-column prop="tongguo_zongshu" label="通过总数" width="100" />
|
||||
<el-table-column prop="yue" label="可提现余额(¥)" width="130">
|
||||
<template #default="{ row }"> ¥{{ formatMoney(row.yue) }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关联板块" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-for="bk in row.bankuai" :key="bk.bankuai_id" size="small" class="bankuai-tag">
|
||||
{{ bk.mingcheng }}({{ bk.dashou_count }})
|
||||
</el-tag>
|
||||
<span v-if="row.bankuai.length === 0" class="empty-tip">无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="openDetailDialog(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, 15, 20, 30]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="handlePageChange"
|
||||
@size-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详情/编辑弹窗 -->
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
:title="isEditMode ? '编辑审核官' : '审核官详情'"
|
||||
width="650px"
|
||||
@close="closeDetailDialog"
|
||||
custom-class="dark-dialog"
|
||||
>
|
||||
<el-form :model="currentExaminer" label-width="110px" :disabled="!isEditMode">
|
||||
<el-form-item label="头像">
|
||||
<img :src="currentExaminer.avatar_full || ''" class="avatar-img" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户ID">
|
||||
<el-input :model-value="currentExaminer.yonghuid" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号">
|
||||
<el-input :model-value="currentExaminer.phone" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="打手昵称">
|
||||
<el-input :model-value="currentExaminer.nicheng || '无'" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="认证状态">
|
||||
<el-switch v-model="currentExaminer.is_renzheng" active-text="已认证" inactive-text="未认证" :disabled="!isEditMode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="账号状态">
|
||||
<el-select v-model="currentExaminer.zhuangtai" class="dark-select" :disabled="!isEditMode">
|
||||
<el-option label="正常" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核官状态">
|
||||
<el-select v-model="currentExaminer.shenhe_zhuangtai" class="dark-select" :disabled="!isEditMode">
|
||||
<el-option label="空闲" :value="0" />
|
||||
<el-option label="审核中" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="可提现余额">
|
||||
<el-input-number v-model="currentExaminer.yue" :min="0" :step="10" :precision="2" :disabled="!isEditMode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="审核总数">
|
||||
<el-input-number :model-value="currentExaminer.shenhe_zongshu" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="通过总数">
|
||||
<el-input-number :model-value="currentExaminer.tongguo_zongshu" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="赚取总额">
|
||||
<el-input-number :model-value="currentExaminer.zonge" disabled :precision="2" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 板块管理区域 -->
|
||||
<el-divider content-position="left">关联板块</el-divider>
|
||||
<div class="bankuai-manage">
|
||||
<div class="bankuai-current">
|
||||
<span class="label">已关联板块:</span>
|
||||
<template v-if="currentExaminer.bankuai && currentExaminer.bankuai.length > 0">
|
||||
<el-tag
|
||||
v-for="bk in currentExaminer.bankuai"
|
||||
:key="bk.bankuai_id"
|
||||
size="small"
|
||||
closable
|
||||
:disable-transitions="false"
|
||||
@close="removeBankuai(bk.bankuai_id)"
|
||||
v-if="isEditMode"
|
||||
class="bankuai-tag"
|
||||
>
|
||||
{{ bk.mingcheng }}({{ bk.dashou_count }})
|
||||
</el-tag>
|
||||
<template v-if="!isEditMode">
|
||||
<el-tag v-for="bk in currentExaminer.bankuai" :key="bk.bankuai_id" size="small" class="bankuai-tag">
|
||||
{{ bk.mingcheng }}({{ bk.dashou_count }})
|
||||
</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
<span v-else class="empty-tip">暂无关联板块</span>
|
||||
</div>
|
||||
|
||||
<div v-if="isEditMode" class="bankuai-add-row">
|
||||
<el-select
|
||||
v-model="pendingBankuaiId"
|
||||
placeholder="选择板块"
|
||||
class="dark-select add-select"
|
||||
size="small"
|
||||
clearable
|
||||
@change="onSelectBankuai"
|
||||
>
|
||||
<el-option
|
||||
v-for="bk in availableBankuai"
|
||||
:key="bk.bankuai_id"
|
||||
:label="bk.mingcheng"
|
||||
:value="bk.bankuai_id"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:disabled="!pendingBankuaiId"
|
||||
@click="addBankuai"
|
||||
style="margin-left: 8px;"
|
||||
>
|
||||
确认添加
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">取消</el-button>
|
||||
<el-button v-if="!isEditMode" type="primary" @click="isEditMode = true">编辑</el-button>
|
||||
<el-button v-if="isEditMode" type="success" @click="saveExaminer" :loading="saving">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
const username = localStorage.getItem('username') || ''
|
||||
const hasPermission = ref(true)
|
||||
const loading = ref(false)
|
||||
|
||||
// 筛选条件
|
||||
const filter = reactive({
|
||||
yonghuid: '',
|
||||
zhuangtai: null,
|
||||
shenhe_zhuangtai: null,
|
||||
bankuai_name: ''
|
||||
})
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 列表数据
|
||||
const examinerList = ref([])
|
||||
const allBankuaiList = ref([]) // 所有板块(用于添加时下拉)
|
||||
|
||||
// 详情弹窗相关
|
||||
const detailVisible = ref(false)
|
||||
const isEditMode = ref(false)
|
||||
const currentExaminer = ref({})
|
||||
const saving = ref(false)
|
||||
|
||||
// 板块标签统计
|
||||
const bankuaiTagsData = ref([])
|
||||
const activeCollapse = ref([]) // 默认收起
|
||||
|
||||
// 待添加的板块ID
|
||||
const pendingBankuaiId = ref(null)
|
||||
|
||||
// 当前审核官可添加的板块
|
||||
const availableBankuai = computed(() => {
|
||||
if (!currentExaminer.value.bankuai) return allBankuaiList.value
|
||||
const associatedIds = currentExaminer.value.bankuai.map(b => b.bankuai_id)
|
||||
return allBankuaiList.value.filter(bk => !associatedIds.includes(bk.bankuai_id))
|
||||
})
|
||||
|
||||
// 格式化金额
|
||||
const formatMoney = (val) => {
|
||||
if (val === undefined || val === null) return '0.00'
|
||||
return Number(val).toFixed(2)
|
||||
}
|
||||
|
||||
// 拼接头像完整URL
|
||||
const getFullAvatar = (avatar) => {
|
||||
if (!avatar) return ''
|
||||
if (avatar.startsWith('http')) return avatar
|
||||
return (window.$ossURL || '') + avatar
|
||||
}
|
||||
|
||||
// 获取考核官列表
|
||||
const fetchExaminerList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
phone: username,
|
||||
page: pagination.page,
|
||||
page_size: pagination.pageSize,
|
||||
...filter
|
||||
}
|
||||
const res = await request.post('/houtai/khggl', params)
|
||||
if (res.code === 0) {
|
||||
const list = (res.data.list || []).map(item => ({
|
||||
...item,
|
||||
avatar_full: getFullAvatar(item.avatar)
|
||||
}))
|
||||
examinerList.value = list
|
||||
pagination.total = res.data.total || 0
|
||||
allBankuaiList.value = res.data.all_bankuai || []
|
||||
bankuaiTagsData.value = res.data.bankuai_tags || [] // 接收板块标签数据
|
||||
} else if (res.code === 403) {
|
||||
hasPermission.value = false
|
||||
} else {
|
||||
ElMessage.error(res.msg || '获取数据失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.page = 1
|
||||
fetchExaminerList()
|
||||
}
|
||||
|
||||
// 重置
|
||||
const resetFilter = () => {
|
||||
filter.yonghuid = ''
|
||||
filter.zhuangtai = null
|
||||
filter.shenhe_zhuangtai = null
|
||||
filter.bankuai_name = ''
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
// 翻页
|
||||
const handlePageChange = () => {
|
||||
fetchExaminerList()
|
||||
}
|
||||
|
||||
// 打开详情弹窗(查看模式)
|
||||
const openDetailDialog = (row) => {
|
||||
const detail = cloneDeep(row)
|
||||
detail.avatar_full = getFullAvatar(detail.avatar)
|
||||
currentExaminer.value = detail
|
||||
isEditMode.value = false
|
||||
pendingBankuaiId.value = null
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
// 关闭详情弹窗
|
||||
const closeDetailDialog = () => {
|
||||
detailVisible.value = false
|
||||
isEditMode.value = false
|
||||
currentExaminer.value = {}
|
||||
pendingBankuaiId.value = null
|
||||
}
|
||||
|
||||
// 添加板块
|
||||
const addBankuai = async () => {
|
||||
const bankuaiId = pendingBankuaiId.value
|
||||
if (!bankuaiId) {
|
||||
ElMessage.warning('请先选择板块')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await request.post('/houtai/shgxgsj', {
|
||||
phone: username,
|
||||
yonghuid: currentExaminer.value.yonghuid,
|
||||
action: 'add_bankuai',
|
||||
bankuai_id: bankuaiId
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('板块添加成功')
|
||||
const bk = allBankuaiList.value.find(b => b.bankuai_id === bankuaiId)
|
||||
if (bk) {
|
||||
currentExaminer.value.bankuai.push({
|
||||
bankuai_id: bankuaiId,
|
||||
mingcheng: bk.mingcheng,
|
||||
dashou_count: 0
|
||||
})
|
||||
}
|
||||
pendingBankuaiId.value = null
|
||||
} else {
|
||||
ElMessage.error(res.msg || '添加失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
}
|
||||
}
|
||||
|
||||
// 移除板块
|
||||
const removeBankuai = async (bankuaiId) => {
|
||||
try {
|
||||
const res = await request.post('/houtai/shgxgsj', {
|
||||
phone: username,
|
||||
yonghuid: currentExaminer.value.yonghuid,
|
||||
action: 'remove_bankuai',
|
||||
bankuai_id: bankuaiId
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('板块移除成功')
|
||||
currentExaminer.value.bankuai = currentExaminer.value.bankuai.filter(b => b.bankuai_id !== bankuaiId)
|
||||
} else {
|
||||
ElMessage.error(res.msg || '移除失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
}
|
||||
}
|
||||
|
||||
// 保存基本信息
|
||||
const saveExaminer = async () => {
|
||||
const payload = {
|
||||
phone: username,
|
||||
yonghuid: currentExaminer.value.yonghuid,
|
||||
action: 'update_info',
|
||||
yue: currentExaminer.value.yue,
|
||||
zhuangtai: currentExaminer.value.zhuangtai,
|
||||
shenhe_zhuangtai: currentExaminer.value.shenhe_zhuangtai,
|
||||
is_renzheng: currentExaminer.value.is_renzheng
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/shgxgsj', payload)
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('修改成功')
|
||||
isEditMode.value = false
|
||||
const index = examinerList.value.findIndex(item => item.yonghuid === currentExaminer.value.yonghuid)
|
||||
if (index !== -1) {
|
||||
examinerList.value[index].zhuangtai = currentExaminer.value.zhuangtai
|
||||
examinerList.value[index].shenhe_zhuangtai = currentExaminer.value.shenhe_zhuangtai
|
||||
examinerList.value[index].yue = currentExaminer.value.yue
|
||||
examinerList.value[index].is_renzheng = currentExaminer.value.is_renzheng
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res.msg || '修改失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!username) {
|
||||
ElMessage.error('未登录')
|
||||
return
|
||||
}
|
||||
fetchExaminerList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.examiner-manager {
|
||||
padding: 20px;
|
||||
color: #e0e0e0;
|
||||
background: radial-gradient(circle at top, #1a1a2e 0%, #0d0d1a 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.no-permission {
|
||||
text-align: center;
|
||||
padding: 120px 0;
|
||||
color: #c0a060;
|
||||
}
|
||||
.no-permission-icon { font-size: 64px; filter: drop-shadow(0 0 10px #ffd700); }
|
||||
.no-permission-text { font-size: 22px; margin: 24px 0 12px; color: #ffd700; }
|
||||
.no-permission-desc { font-size: 15px; color: #b0a080; }
|
||||
|
||||
.filter-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
padding: 16px;
|
||||
background: rgba(18,18,30,0.8);
|
||||
backdrop-filter: blur(14px);
|
||||
border: 1px solid rgba(255,215,0,0.2);
|
||||
border-radius: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-input { width: 160px; }
|
||||
.filter-select { width: 140px; }
|
||||
|
||||
/* 板块标签统计面板 */
|
||||
.stat-collapse {
|
||||
margin-bottom: 20px;
|
||||
background: rgba(18,18,30,0.8);
|
||||
border: 1px solid rgba(255,215,0,0.2);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bankuai-tags-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
gap: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
.bankuai-tags-card {
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
border: 1px solid rgba(255,215,0,0.1);
|
||||
}
|
||||
.card-title {
|
||||
color: #ffd700;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.tags-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
.tag-item {
|
||||
background: rgba(255,215,0,0.15);
|
||||
border-color: #ffd700;
|
||||
color: #ffd700;
|
||||
}
|
||||
.empty-tip {
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 表格暗黑主题 */
|
||||
:deep(.dark-table) {
|
||||
--el-table-bg-color: rgba(18,18,30,0.7);
|
||||
--el-table-tr-bg-color: transparent;
|
||||
--el-table-header-bg-color: rgba(0,0,0,0.5);
|
||||
--el-table-border-color: rgba(255,215,0,0.15);
|
||||
--el-table-text-color: #e0e0e0;
|
||||
--el-table-header-text-color: #ffd700;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.bankuai-tag {
|
||||
margin-right: 6px;
|
||||
margin-bottom: 4px;
|
||||
background: rgba(255,215,0,0.15);
|
||||
border-color: #ffd700;
|
||||
color: #ffd700;
|
||||
}
|
||||
.empty-tip { color: #888; }
|
||||
|
||||
.pagination-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
/* 详情弹窗 */
|
||||
:deep(.dark-dialog) {
|
||||
background: #1a1a2e !important;
|
||||
border: 1px solid #ffd700 !important;
|
||||
border-radius: 20px !important;
|
||||
}
|
||||
:deep(.dark-dialog .el-dialog__header) { border-bottom: 1px solid #ffd700; }
|
||||
:deep(.dark-dialog .el-dialog__title) { color: #ffd700; font-weight: bold; }
|
||||
|
||||
.bankuai-manage { margin-top: 10px; }
|
||||
.bankuai-current { margin-bottom: 12px; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
|
||||
.bankuai-current .label { color: #ccc; }
|
||||
.bankuai-add-row { display: flex; align-items: center; margin-top: 10px; }
|
||||
.add-select { width: 200px; }
|
||||
|
||||
:deep(.dark-input .el-input__inner),
|
||||
:deep(.dark-select .el-input__inner),
|
||||
:deep(.el-input-number .el-input__inner) {
|
||||
background-color: #2a2a3c !important;
|
||||
border-color: #ffd700 !important;
|
||||
color: #e0e0e0 !important;
|
||||
}
|
||||
:deep(.el-input-number__decrease),
|
||||
:deep(.el-input-number__increase) {
|
||||
background-color: #1f1f30 !important;
|
||||
color: #ffd700 !important;
|
||||
}
|
||||
:deep(.el-button--primary) {
|
||||
background: linear-gradient(135deg, #ffd700, #f0a500) !important;
|
||||
border: none !important;
|
||||
color: #000 !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #ffd700;
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user