<script setup lang="ts">
|
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
import { useRoute, useRouter } from 'vue-router'
|
import { Download, Edit, Plus, Refresh, Search, View } from '@element-plus/icons-vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
import {
|
createAdminRole,
|
createAdminStaff,
|
deleteAdminRole,
|
getAdminRoles,
|
getAdminStaff,
|
getUpgradeApplications,
|
updateAdminRole,
|
updateAdminRoleStatus,
|
updateAdminStaff,
|
} from '../api/admin'
|
import type { AdminRole, AdminStaff } from '../types/admin'
|
import { TALENT_CARD_LEVELS } from '../utils/cardLevels'
|
import { downloadExcel } from '../utils/excel'
|
|
const route = useRoute()
|
const router = useRouter()
|
const kind = computed(() => String(route.meta.businessKind || 'upgrade'))
|
const isUpgrade = computed(() => kind.value === 'upgrade')
|
const isRole = computed(() => kind.value === 'role')
|
const title = computed(() => isUpgrade.value ? '升级申请' : isRole.value ? '角色管理' : '员工管理')
|
const loading = ref(false)
|
const rows = ref<Record<string, unknown>[]>([])
|
const dialogVisible = ref(false)
|
const editVisible = ref(false)
|
const formRef = ref<FormInstance>()
|
const activeRow = ref<Record<string, unknown>>()
|
const editingId = ref<number | string>()
|
const filters = reactive({ keyword: '', cardLevel: '', status: '', timeRange: [] as string[] })
|
const pagination = reactive({ page: 1, size: 10, total: 0 })
|
const form = reactive({ name: '', code: '', password: '', remark: '', status: 1 })
|
const accountPattern = /^[A-Za-z0-9]+$/
|
const rules = computed<FormRules>(() => ({
|
name: [{ required: true, message: isRole.value ? '请输入角色名称' : '请输入员工姓名', trigger: 'blur' }],
|
code: [
|
{ required: true, message: isRole.value ? '请输入角色编码' : '请输入登录账号', trigger: 'blur' },
|
{
|
validator: (_rule, value, callback) => !isRole.value && value && !accountPattern.test(String(value).trim())
|
? callback(new Error('登录账号仅支持英文、数字或英文+数字'))
|
: callback(),
|
trigger: 'blur',
|
},
|
],
|
password: [{
|
validator: (_rule, value, callback) => !isRole.value && !editingId.value && !value
|
? callback(new Error('请设置登录密码'))
|
: callback(),
|
trigger: 'blur',
|
}],
|
}))
|
|
const filteredRows = computed(() => isRole.value
|
? rows.value.filter((row) => (!filters.keyword || String(row.roleName || '').includes(filters.keyword)) && (!filters.status || String(row.status) === filters.status))
|
: rows.value)
|
const pagedRows = computed(() => isUpgrade.value
|
? rows.value
|
: filteredRows.value.slice((pagination.page - 1) * pagination.size, pagination.page * pagination.size))
|
const pageTotal = computed(() => isRole.value ? filteredRows.value.length : pagination.total)
|
|
const columns = computed(() => isUpgrade.value
|
? [['applicationNo', '申请编号'], ['talentName', '持卡人名称'], ['talentMobile', '持卡人手机号'], ['targetLevel', '卡片等级'], ['applyTime', '申请时间'], ['status', '状态']]
|
: isRole.value
|
? [['serialNo', '序号'], ['roleName', '角色名称'], ['remark', '备注'], ['statusText', '状态'], ['createdAt', '创建时间']]
|
: [['account', '登录账号'], ['displayName', '员工姓名'], ['roleCode', '所属角色'], ['statusText', '状态'], ['createdAt', '创建时间']])
|
|
function statusText(value: unknown) { return Number(value) === 1 ? '启用' : '停用' }
|
function formatDateTime(value: unknown) {
|
return typeof value === 'string' && value ? value.replace('T', ' ').slice(0, 19) : ''
|
}
|
function normalizeRole(row: AdminRole, index: number) { return { ...row, serialNo: index + 1, createdAt: formatDateTime(row.createdAt), statusText: statusText(row.status) } }
|
function normalizeStaff(row: AdminStaff) { return { ...row, createdAt: formatDateTime(row.createdAt), statusText: statusText(row.status) } }
|
function normalizeUpgrade(row: Record<string, unknown>) { return { ...row, applyTime: formatDateTime(row.applyTime) } }
|
function isPlatformAdminRole(row: Record<string, unknown>) { return String(row.roleCode || '') === 'platform_admin' }
|
|
async function loadData() {
|
loading.value = true
|
try {
|
if (isUpgrade.value) {
|
const result = await getUpgradeApplications({ page: pagination.page, size: pagination.size, keyword: filters.keyword || undefined, targetLevel: filters.cardLevel || undefined, status: filters.status || undefined, applyStart: filters.timeRange[0], applyEnd: filters.timeRange[1] })
|
rows.value = result.records.map((row) => normalizeUpgrade(row as unknown as Record<string, unknown>))
|
pagination.total = result.total
|
} else if (isRole.value) {
|
rows.value = (await getAdminRoles()).map(normalizeRole)
|
pagination.total = rows.value.length
|
} else {
|
rows.value = (await getAdminStaff()).map(normalizeStaff)
|
pagination.total = rows.value.length
|
}
|
} finally { loading.value = false }
|
}
|
|
function search() { pagination.page = 1; loadData() }
|
function reset() { filters.keyword = ''; filters.cardLevel = ''; filters.status = ''; filters.timeRange = []; search() }
|
function changePage() { if (isUpgrade.value) loadData() }
|
function view(row: Record<string, unknown>) {
|
if (isUpgrade.value) {
|
router.push(`/upgrade-applications/${row.id}`)
|
return
|
}
|
if (isRole.value) {
|
router.push(`/roles/${row.id}/view`)
|
return
|
}
|
activeRow.value = row
|
dialogVisible.value = true
|
}
|
|
function openCreate() {
|
if (isRole.value) { router.push('/roles/new'); return }
|
editingId.value = undefined
|
Object.assign(form, { name: '', code: '', password: '', remark: '', status: 1 })
|
editVisible.value = true
|
}
|
|
function openEdit(row: Record<string, unknown>) {
|
if (isRole.value) { router.push(`/roles/${row.id}`); return }
|
editingId.value = row.id as number | string
|
Object.assign(form, { name: String(row.roleName || row.displayName || ''), code: String(row.roleCode || row.account || ''), password: '', remark: String(row.remark || ''), status: Number(row.status) })
|
editVisible.value = true
|
}
|
|
async function save() {
|
const valid = await formRef.value?.validate().catch(() => false)
|
if (!valid) return
|
if (isRole.value) {
|
const payload = { roleName: form.name.trim(), roleCode: form.code.trim(), remark: form.remark.trim(), status: form.status }
|
if (editingId.value) await updateAdminRole(editingId.value, payload); else await createAdminRole(payload)
|
} else {
|
if (!editingId.value && !form.password.trim()) { ElMessage.warning('请输入登录密码'); return }
|
const payload = { account: form.code.trim(), displayName: form.name.trim(), mobile: '', roleCode: '', positionName: '未设置', customerWechat: '', status: form.status, password: form.password || undefined }
|
if (editingId.value) await updateAdminStaff(editingId.value, payload); else await createAdminStaff(payload as typeof payload & { password: string })
|
}
|
ElMessage.success('保存成功')
|
editVisible.value = false
|
loadData()
|
}
|
|
async function changeRoleStatus(row: Record<string, unknown>) {
|
const status = Number(row.status) === 1 ? 0 : 1
|
await updateAdminRoleStatus(row.id as number | string, status)
|
ElMessage.success(status === 1 ? '已启用' : '已停用')
|
await loadData()
|
}
|
|
async function removeRole(row: Record<string, unknown>) {
|
await ElMessageBox.confirm(`确认删除角色“${row.roleName}”?`, '删除角色', { type: 'warning' })
|
await deleteAdminRole(row.id as number | string)
|
ElMessage.success('已删除')
|
await loadData()
|
}
|
|
async function download() {
|
let data = rows.value
|
if (isUpgrade.value) {
|
const result = await getUpgradeApplications({ page: 1, size: 1000, keyword: filters.keyword || undefined, targetLevel: filters.cardLevel || undefined, status: filters.status || undefined, applyStart: filters.timeRange[0], applyEnd: filters.timeRange[1] })
|
data = result.records.map((row) => normalizeUpgrade(row as unknown as Record<string, unknown>))
|
}
|
downloadExcel(title.value, columns.value.map(([key, label]) => ({ title: label, value: (row: Record<string, unknown>) => {
|
const value = row[key]
|
return value === null || value === undefined ? '' : typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? value : String(value)
|
} })), data)
|
ElMessage.success(`已导出 ${data.length} 条${title.value}数据`)
|
}
|
|
watch(() => route.fullPath, reset)
|
onMounted(loadData)
|
</script>
|
|
<template>
|
<div class="page-stack prototype-page business-fill-page" :class="{ 'role-management-page': isRole }">
|
<section class="panel">
|
<div class="panel-header"><h3>{{ title }}</h3></div>
|
<el-form class="business-fill-filter-form" :class="{ 'role-management-filter-form': isRole, 'upgrade-management-filter-form': isUpgrade }" :label-width="isRole ? undefined : '86px'">
|
<el-form-item :label="isUpgrade ? '持卡人' : isRole ? '角色' : '员工'">
|
<el-input v-model="filters.keyword" :placeholder="isUpgrade ? '持卡人姓名、手机号、卡号' : '请输入关键词'" clearable />
|
</el-form-item>
|
<el-form-item v-if="isUpgrade" label="卡片等级">
|
<el-select v-model="filters.cardLevel" clearable placeholder="全部">
|
<el-option label="全部" value="" />
|
<el-option v-for="level in TALENT_CARD_LEVELS" :key="level" :label="level" :value="level" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="状态">
|
<el-select v-model="filters.status" clearable placeholder="全部">
|
<el-option v-if="!isUpgrade" label="启用" value="1" />
|
<el-option v-if="!isUpgrade" label="停用" value="0" />
|
<el-option v-if="isUpgrade" label="全部" value="" />
|
<el-option v-if="isUpgrade" label="待审核" value="待审核" />
|
<el-option v-if="isUpgrade" label="已通过" value="已通过" />
|
<el-option v-if="isUpgrade" label="已驳回" value="已驳回" />
|
</el-select>
|
</el-form-item>
|
<el-form-item v-if="isUpgrade" label="申请时间" class="upgrade-management-filter-date">
|
<el-date-picker v-model="filters.timeRange" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="结束日期" />
|
</el-form-item>
|
<div class="business-fill-filter-actions">
|
<el-button type="primary" :icon="Search" @click="search">查询</el-button>
|
<el-button :icon="Refresh" @click="reset">重置</el-button>
|
</div>
|
</el-form>
|
<div class="business-fill-tools">
|
<el-button v-if="!isUpgrade" v-permission="isRole ? 'admin.roles.create' : 'admin.staff.create'" type="primary" :icon="Plus" @click="openCreate">新建</el-button>
|
<el-button v-permission="isUpgrade ? 'admin.upgrade-applications.export' : isRole ? 'admin.roles.export' : 'admin.staff.export'" :icon="Download" @click="download">下载</el-button>
|
</div>
|
<el-table v-loading="loading" :data="pagedRows" border class="business-fill-table" :empty-text="`暂无${title}数据`">
|
<el-table-column v-for="[key, label] in columns" :key="key" :prop="key" :label="label" min-width="130" show-overflow-tooltip />
|
<el-table-column label="操作" width="150" fixed="right" align="center">
|
<template #default="{ row }">
|
<el-button v-permission="isUpgrade ? 'admin.upgrade-applications.view' : isRole ? 'admin.roles.view' : 'admin.staff.view'" link type="primary" :icon="View" @click="view(row)">查看</el-button>
|
<el-button v-if="!isUpgrade && !(isRole && isPlatformAdminRole(row))" v-permission="isRole ? 'admin.roles.edit' : 'admin.staff.edit'" link type="primary" :icon="Edit" @click="openEdit(row)">编辑</el-button>
|
<template v-if="isRole && !isPlatformAdminRole(row)">
|
<el-button v-permission="'admin.roles.disable'" link type="primary" @click="changeRoleStatus(row)">{{ Number(row.status) === 1 ? '停用' : '启用' }}</el-button>
|
<el-button v-permission="'admin.roles.delete'" link type="danger" @click="removeRole(row)">删除</el-button>
|
</template>
|
</template>
|
</el-table-column>
|
</el-table>
|
<div class="pagination-row">
|
<el-pagination v-model:current-page="pagination.page" v-model:page-size="pagination.size" background layout="total, sizes, prev, pager, next" :page-sizes="[10, 20, 50]" :total="pageTotal" @change="changePage" />
|
</div>
|
</section>
|
<el-dialog v-model="dialogVisible" :title="title" width="520px" :close-on-click-modal="false">
|
<el-descriptions v-if="activeRow" :column="1" border>
|
<el-descriptions-item v-for="[key, label] in columns" :key="key" :label="label">{{ activeRow[key] || '-' }}</el-descriptions-item>
|
</el-descriptions>
|
</el-dialog>
|
<el-dialog v-model="editVisible" :title="`编辑${title}`" width="480px" destroy-on-close :close-on-click-modal="false">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="92px">
|
<el-form-item :label="isRole ? '角色名称' : '员工姓名'" prop="name" required><el-input v-model="form.name" /></el-form-item>
|
<el-form-item :label="isRole ? '角色编码' : '登录账号'" prop="code" required><el-input v-model="form.code" :placeholder="isRole ? '' : '仅支持英文和数字'" maxlength="32" /></el-form-item>
|
<el-form-item v-if="!isRole" label="登录密码" prop="password" :required="!editingId"><el-input v-model="form.password" type="password" :placeholder="editingId ? '留空则不修改' : '请输入登录密码'" /></el-form-item>
|
<el-form-item v-if="isRole" label="备注"><el-input v-model="form.remark" /></el-form-item>
|
<el-form-item label="状态"><el-switch v-model="form.status" :active-value="1" :inactive-value="0" /></el-form-item>
|
</el-form>
|
<template #footer>
|
<el-button @click="editVisible = false">取消</el-button>
|
<el-button type="primary" @click="save">保存</el-button>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|