新增 el-table-column "启用状态", 显示 正常(绿) / 禁用(红) el-tag, 数据由 row.status === 'N' 区分, 1:1 抄 admin/Experts.vue 同列实现。 列顺序: 姓名 手机号 工作单位 科室 职称 执业证书 职称证明 审核状态 [启用状态] 审批时间 审批人 操作 Co-Authored-By: Claude <noreply@anthropic.com>
473 lines
21 KiB
Vue
473 lines
21 KiB
Vue
<template>
|
||
<div class="page-card manager-experts">
|
||
<div class="breadcrumb">首页 / 专家审核</div>
|
||
|
||
<!-- ========== 筛选区 (与 People.vue 风格一致) ========== -->
|
||
<el-form inline :model="q" class="filter-form">
|
||
<el-form-item label="姓名">
|
||
<el-input v-model="q.name" placeholder="" clearable style="width:160px" />
|
||
</el-form-item>
|
||
<el-form-item label="手机号">
|
||
<el-input v-model="q.phone" placeholder="" clearable style="width:160px" />
|
||
</el-form-item>
|
||
<el-form-item label="工作单位">
|
||
<el-input v-model="q.workUnit" placeholder="" clearable style="width:200px" />
|
||
</el-form-item>
|
||
<el-form-item label="审核状态">
|
||
<el-select v-model="q.auditStatus" placeholder="请选择" clearable style="width:140px">
|
||
<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>
|
||
<el-button type="primary" @click="load">查找</el-button>
|
||
<el-button @click="reset">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- ========== 批量按钮区 (与 People.vue 风格一致) ========== -->
|
||
<div class="batch-bar">
|
||
<el-button type="primary" @click="openAdd">新建专家</el-button>
|
||
<el-button @click="openImport">批量导入</el-button>
|
||
<el-button @click="onBatchAudit" :disabled="!selection.length">批量审核</el-button>
|
||
<el-button @click="openImportPracticeCert">批量导入执业证书/证明</el-button>
|
||
<el-button @click="openImportTitleCert">批量导入职称证明</el-button>
|
||
</div>
|
||
|
||
<!-- ========== 表格 (按原型 11 列, 按 left 顺序) ========== -->
|
||
<el-table :data="rows" v-loading="loading" stripe border @selection-change="onSel">
|
||
<el-table-column type="selection" width="44" />
|
||
<el-table-column prop="name" label="姓名" width="100" fixed />
|
||
<el-table-column prop="phone" label="手机号" width="130" />
|
||
<el-table-column prop="workUnit" label="工作单位" min-width="180" show-overflow-tooltip />
|
||
<el-table-column prop="department" label="科室" width="100" />
|
||
<el-table-column prop="title" label="职称" width="100" />
|
||
<el-table-column label="执业证书/证明" width="180">
|
||
<template #default="{ row }">
|
||
<template v-if="row.practiceCertUrl">
|
||
<el-button link type="primary" @click="onPreviewCert(row.practiceCertUrl)">查看</el-button>
|
||
<el-button link type="primary" @click="onDownloadCert(row.practiceCertUrl, row.phone)">下载</el-button>
|
||
</template>
|
||
<span v-else style="color:#c0c4cc">-</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="职称证明" width="180">
|
||
<template #default="{ row }">
|
||
<template v-if="row.titleCertUrl">
|
||
<el-button link type="primary" @click="onPreviewCert(row.titleCertUrl)">查看</el-button>
|
||
<el-button link type="primary" @click="onDownloadCert(row.titleCertUrl, row.phone)">下载</el-button>
|
||
</template>
|
||
<span v-else style="color:#c0c4cc">-</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="审核状态" width="100" align="center">
|
||
<template #default="{ row }">
|
||
<audit-status-tag :status="row.auditStatus" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="启用状态" width="100" align="center">
|
||
<template #default="{ row }">
|
||
<el-tag size="small" :type="row.status === 'N' ? 'danger' : 'success'">
|
||
{{ row.status === 'N' ? '禁用' : '正常' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="auditTime" label="审批时间" width="160" align="center">
|
||
<template #default="{ row }">{{ fmtTime(row.auditTime) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="auditBy" label="审批人" width="120" align="center" />
|
||
<el-table-column label="操作" width="280" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button link type="primary" @click="onAudit(row)">审核</el-button>
|
||
<el-button link type="primary" @click="goEdit(row)">修改</el-button>
|
||
<el-button link type="primary" @click="onView(row)">查看</el-button>
|
||
<el-button link :type="row.status === 'N' ? 'success' : 'danger'" @click="row.status === 'N' ? onEnable(row) : onDisable(row)">
|
||
{{ row.status === 'N' ? '恢复' : '禁用' }}
|
||
</el-button>
|
||
<el-button link type="info" v-if="row.auditStatus === '3'" @click="onViewAuditOpinion(row)">已拒绝</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<div class="pager">
|
||
<el-pagination v-model:current-page="page.pageNum" v-model:page-size="page.pageSize" :total="page.total" :page-sizes="[10,20,50]" layout="total, sizes, prev, pager, next, jumper" @current-change="load" @size-change="load" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========== Dialog: 新建/编辑专家 (按原型 top=239 确定/取消) ========== -->
|
||
<el-dialog v-model="editOpen" :title="editForm.expertId ? '编辑专家' : '新建专家'" width="640px">
|
||
<el-form :model="editForm" label-width="120px" :rules="editRules" ref="editFormRef">
|
||
<el-form-item label="姓名" prop="name"><el-input v-model="editForm.name" /></el-form-item>
|
||
<el-form-item label="手机号" prop="phone"><el-input v-model="editForm.phone" maxlength="11" /></el-form-item>
|
||
<el-form-item label="工作单位" prop="workUnit"><el-input v-model="editForm.workUnit" /></el-form-item>
|
||
<el-form-item label="科室" prop="department"><el-input v-model="editForm.department" placeholder="如:呼吸科" /></el-form-item>
|
||
<el-form-item label="职称" prop="title">
|
||
<el-select v-model="editForm.title" placeholder="请选择" style="width:100%">
|
||
<el-option label="住院医师" value="住院医师" />
|
||
<el-option label="主治医师" value="主治医师" />
|
||
<el-option label="副主任医师" value="副主任医师" />
|
||
<el-option label="主任医师" value="主任医师" />
|
||
<el-option label="教授" value="教授" />
|
||
<el-option label="副教授" value="副教授" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="执业证书 URL"><el-input v-model="editForm.practiceCertUrl" /></el-form-item>
|
||
<el-form-item label="职称证明 URL"><el-input v-model="editForm.titleCertUrl" /></el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="editOpen=false">取消</el-button>
|
||
<el-button type="primary" :loading="submitting" @click="submitEdit">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- ========== Dialog: 审核 (原型 top=404 确认/取消) ========== -->
|
||
<el-dialog v-model="auditOpen" title="审核" width="520px">
|
||
<p style="margin-bottom:12px">专家: <b>{{ auditForm.name }}</b> ({{ auditForm.phone }})</p>
|
||
<el-form :model="auditForm" label-width="100px">
|
||
<el-form-item label="审核结果">
|
||
<el-radio-group v-model="auditForm.result">
|
||
<el-radio value="2">通过</el-radio>
|
||
<el-radio value="3">拒绝</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="审核意见">
|
||
<el-input v-model="auditForm.opinion" type="textarea" :rows="4" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="auditOpen=false">取消</el-button>
|
||
<el-button type="primary" :loading="submitting" @click="submitAudit">确认</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- ========== Dialog: 批量导入 (原型 top=239 确定/取消, 含 radio 通过/退回) ========== -->
|
||
<el-dialog v-model="importOpen" title="批量导入专家" width="520px">
|
||
<div style="margin-bottom:12px;font-size:13px">
|
||
<el-link type="primary" @click="downloadImportTpl">批量导入模板下载</el-link>
|
||
</div>
|
||
<p style="color:#606266;margin-bottom:8px">*批量导入模板 xls 与列表表项一致</p>
|
||
<el-form label-width="100px">
|
||
<el-form-item label="审核结果">
|
||
<el-radio-group v-model="importAuditResult">
|
||
<el-radio value="2">通过</el-radio>
|
||
<el-radio value="3">拒绝</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="审核意见">
|
||
<el-input v-model="importAuditOpinion" type="textarea" :rows="3" placeholder="*新建和批量导入审核状态直接为审核通过" />
|
||
</el-form-item>
|
||
<el-form-item label="选择文件">
|
||
<el-input v-model="importFileUrl" placeholder="上传文件 URL 或选择文件" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="importOpen=false">取消</el-button>
|
||
<el-button type="primary" :loading="importing" @click="submitImport">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- ========== Dialog: 批量导入执业证书/证明 (原型 u6124) ========== -->
|
||
<el-dialog v-model="importCertOpen" title="批量导入执业证书/证明" width="520px">
|
||
<p style="color:#606266;margin-bottom:8px">*退回后,如专家重新提交,则审核状态变为待审核</p>
|
||
<p style="color:#606266;margin-bottom:8px">提示:需将证明文件名称修改为手机号进行导入</p>
|
||
<el-input v-model="importCertUrl" placeholder="上传文件 URL 或选择文件" />
|
||
<template #footer>
|
||
<el-button @click="importCertOpen=false">取消</el-button>
|
||
<el-button type="primary" :loading="importing" @click="submitImportCert">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- ========== Dialog: 批量导入职称证明 (原型 u6126) ========== -->
|
||
<el-dialog v-model="importTitleCertOpen" title="批量导入职称证明" width="520px">
|
||
<p style="color:#606266;margin-bottom:8px">提示:需将证明文件名称修改为手机号进行导入</p>
|
||
<el-input v-model="importTitleCertUrl" placeholder="上传文件 URL 或选择文件" />
|
||
<template #footer>
|
||
<el-button @click="importTitleCertOpen=false">取消</el-button>
|
||
<el-button type="primary" :loading="importing" @click="submitImportTitleCert">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- ========== Dialog: 查看专家详情 (原型 操作列 "查看" 按钮) ========== -->
|
||
<el-dialog v-model="viewOpen" title="专家详情" width="640px">
|
||
<el-descriptions :column="2" border v-if="currentRow">
|
||
<el-descriptions-item label="姓名">{{ currentRow.name }}</el-descriptions-item>
|
||
<el-descriptions-item label="手机号">{{ currentRow.phone }}</el-descriptions-item>
|
||
<el-descriptions-item label="工作单位">{{ currentRow.workUnit }}</el-descriptions-item>
|
||
<el-descriptions-item label="科室">{{ currentRow.department }}</el-descriptions-item>
|
||
<el-descriptions-item label="职称">{{ currentRow.title }}</el-descriptions-item>
|
||
<el-descriptions-item label="审核状态"><audit-status-tag :status="currentRow.auditStatus" /></el-descriptions-item>
|
||
<el-descriptions-item label="执业证书">
|
||
<el-link v-if="currentRow.practiceCertUrl" type="primary" @click="onPreviewCert(currentRow.practiceCertUrl)">查看证书</el-link>
|
||
<span v-else>-</span>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="职称证明">
|
||
<el-link v-if="currentRow.titleCertUrl" type="primary" @click="onPreviewCert(currentRow.titleCertUrl)">查看证书</el-link>
|
||
<span v-else>-</span>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="审批时间">{{ fmtTime(currentRow.auditTime) }}</el-descriptions-item>
|
||
<el-descriptions-item label="审批人">{{ currentRow.auditBy }}</el-descriptions-item>
|
||
</el-descriptions>
|
||
</el-dialog>
|
||
|
||
<!-- 证书/证明 图片预览 dialog (1:1 抄 admin/Experts.vue) -->
|
||
<el-dialog v-model="previewOpen" title="证书预览" width="640px" :show-close="true" destroy-on-close>
|
||
<div class="cert-preview">
|
||
<el-image
|
||
:src="previewUrl"
|
||
fit="contain"
|
||
:preview-src-list="[previewUrl]"
|
||
style="width:100%;max-height:70vh"
|
||
loading="lazy"
|
||
>
|
||
<template #error>
|
||
<div class="cert-preview-error">图片加载失败, 请<a @click="onDownloadCert(previewUrl)">下载</a>查看</div>
|
||
</template>
|
||
</el-image>
|
||
</div>
|
||
<template #footer>
|
||
<el-button @click="onDownloadCert(previewUrl)">下载</el-button>
|
||
<el-button type="primary" @click="previewOpen=false">关闭</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, onMounted, watch } from 'vue'
|
||
import { useRouter, useRoute } from 'vue-router'
|
||
import { bizList, bizAdd, bizUpdate } from '@/api/public'
|
||
import AuditStatusTag from '@/components/AuditStatusTag.vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
|
||
const router = useRouter()
|
||
const route = useRoute()
|
||
|
||
const q = ref({ name: '', phone: '', workUnit: '', auditStatus: '' })
|
||
const rows = ref([])
|
||
const selection = ref([])
|
||
const loading = ref(false)
|
||
const submitting = ref(false)
|
||
const page = reactive({ pageNum: 1, pageSize: 10, total: 0 })
|
||
|
||
async function load() {
|
||
loading.value = true
|
||
try {
|
||
const { data } = await bizList('expert', { ...q.value, pageNum: page.pageNum, pageSize: page.pageSize })
|
||
rows.value = data?.rows || []
|
||
page.total = data?.total || 0
|
||
} catch { rows.value = []; page.total = 0 }
|
||
finally { loading.value = false }
|
||
}
|
||
function reset() {
|
||
q.value = { name: '', phone: '', workUnit: '', auditStatus: '' }
|
||
page.pageNum = 1
|
||
load()
|
||
}
|
||
function onSel(rs) { selection.value = rs }
|
||
|
||
// auditStatusText / auditStatusClass 已删除: 改用 AuditStatusTag 组件
|
||
function fmtTime(d) {
|
||
if (!d) return ''
|
||
const dt = new Date(d)
|
||
const pad = n => String(n).padStart(2, '0')
|
||
return `${dt.getFullYear()}.${pad(dt.getMonth() + 1)}.${pad(dt.getDate())} ${pad(dt.getHours())}:${pad(dt.getMinutes())}`
|
||
}
|
||
|
||
// ========== 新建/编辑 dialog ==========
|
||
const editOpen = ref(false)
|
||
const editFormRef = ref(null)
|
||
const editForm = reactive({
|
||
expertId: '', name: '', phone: '', workUnit: '', department: '', title: '',
|
||
practiceCertUrl: '', titleCertUrl: ''
|
||
})
|
||
const editRules = {
|
||
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
||
phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
|
||
workUnit: [{ required: true, message: '请输入工作单位', trigger: 'blur' }],
|
||
department: [{ required: true, message: '请输入科室', trigger: 'blur' }],
|
||
title: [{ required: true, message: '请选择职称', trigger: 'change' }]
|
||
}
|
||
function openAdd() {
|
||
Object.assign(editForm, { expertId: '', name: '', phone: '', workUnit: '', department: '', title: '', practiceCertUrl: '', titleCertUrl: '' })
|
||
editOpen.value = true
|
||
}
|
||
// 修改按钮: 跳转独立页 /manager/experts/edit/:id (参考 /admin/experts/new)
|
||
function goEdit(row) {
|
||
router.push(`/manager/experts/edit/${row.expertId}`)
|
||
}
|
||
async function submitEdit() {
|
||
await editFormRef.value.validate()
|
||
submitting.value = true
|
||
try {
|
||
if (editForm.expertId) {
|
||
await bizUpdate('expert', { ...editForm })
|
||
ElMessage.success('修改成功')
|
||
} else {
|
||
await bizAdd('expert', { ...editForm, auditStatus: '2', auditBy: 'admin', auditTime: new Date().toISOString().slice(0, 19).replace('T', ' ') })
|
||
ElMessage.success('新建成功')
|
||
}
|
||
editOpen.value = false
|
||
load()
|
||
} catch (e) { ElMessage.error(e?.msg || '保存失败') }
|
||
finally { submitting.value = false }
|
||
}
|
||
|
||
// ========== 审核 dialog ==========
|
||
const auditOpen = ref(false)
|
||
// result: '2'=通过, '3'=拒绝 (BizAuditStatusEnum: 0未提交 1待审核 2通过 3拒绝)
|
||
const auditForm = reactive({ expertId: '', name: '', phone: '', result: '2', opinion: '' })
|
||
function onAudit(row) {
|
||
auditForm.expertId = row.expertId
|
||
auditForm.name = row.name
|
||
auditForm.phone = row.phone
|
||
auditForm.result = '2'
|
||
auditForm.opinion = ''
|
||
auditOpen.value = true
|
||
}
|
||
async function submitAudit() {
|
||
submitting.value = true
|
||
try {
|
||
await bizUpdate('expert', {
|
||
expertId: auditForm.expertId,
|
||
auditStatus: auditForm.result,
|
||
auditOpinion: auditForm.opinion,
|
||
auditBy: 'admin', // 后端应取登录用户
|
||
auditTime: new Date().toISOString().slice(0, 19).replace('T', ' ')
|
||
})
|
||
ElMessage.success(auditForm.result === '2' ? '审核通过' : '已拒绝')
|
||
auditOpen.value = false
|
||
load()
|
||
} catch { ElMessage.error('审核失败') }
|
||
finally { submitting.value = false }
|
||
}
|
||
|
||
// ========== 批量审核 ==========
|
||
async function onBatchAudit() {
|
||
if (!selection.value.length) return ElMessage.warning('请先勾选行')
|
||
try { await ElMessage.confirm(`确定批量审核选中的 ${selection.value.length} 位专家吗?`, '批量审核', { type: 'warning' }).catch(() => { throw new Error('cancel') }) } catch { return }
|
||
submitting.value = true
|
||
let ok = 0
|
||
for (const r of selection.value) {
|
||
try { await bizUpdate('expert', { expertId: r.expertId, auditStatus: '2', auditOpinion: '批量通过', auditBy: 'admin', auditTime: new Date().toISOString().slice(0, 19).replace('T', ' ') }); ok++ } catch {}
|
||
}
|
||
submitting.value = false
|
||
ElMessage.success(`批量审核通过 ${ok}/${selection.value.length} 条`)
|
||
selection.value = []
|
||
load()
|
||
}
|
||
|
||
// ========== 禁用/恢复 ==========
|
||
async function onDisable(row) {
|
||
try { await bizUpdate('expert', { expertId: row.expertId, status: 'N' }); ElMessage.success('已禁用'); load() } catch { ElMessage.error('禁用失败') }
|
||
}
|
||
async function onEnable(row) {
|
||
try { await bizUpdate('expert', { expertId: row.expertId, status: 'Y' }); ElMessage.success('已恢复'); load() } catch { ElMessage.error('恢复失败') }
|
||
}
|
||
|
||
// ========== 查看详情 ==========
|
||
const viewOpen = ref(false)
|
||
const currentRow = ref(null)
|
||
function onView(row) { currentRow.value = row; viewOpen.value = true }
|
||
|
||
// ========== 已拒绝: 查看拒绝意见 ==========
|
||
function onViewAuditOpinion(row) {
|
||
ElMessageBox.alert(
|
||
`拒绝时间: ${fmtTime(row.auditTime) || '-'}\n审批人: ${row.auditBy || '-'}\n拒绝意见: ${row.auditOpinion || '(无)'}`,
|
||
`专家 ${row.name} 审核已拒绝`,
|
||
{ type: 'warning', confirmButtonText: '知道了' }
|
||
).catch(() => {})
|
||
}
|
||
|
||
// ========== 证书查看/下载 ==========
|
||
// 图片预览: dialog 弹窗直接显示 (用 el-image 自带 preview-src-list 支持点击放大)
|
||
// 同步自 admin/Experts.vue (2026-08-17)
|
||
const previewOpen = ref(false)
|
||
const previewUrl = ref('')
|
||
function onPreviewCert(url) {
|
||
if (!url) return
|
||
previewUrl.value = url
|
||
previewOpen.value = true
|
||
}
|
||
function onDownloadCert(url, phone) {
|
||
if (!url) return
|
||
const a = document.createElement('a')
|
||
a.href = url
|
||
a.download = `${phone || 'cert'}_${Date.now()}`
|
||
document.body.appendChild(a)
|
||
a.click()
|
||
document.body.removeChild(a)
|
||
}
|
||
|
||
// ========== 批量导入 dialog ==========
|
||
const importOpen = ref(false)
|
||
const importAuditResult = ref('2')
|
||
const importAuditOpinion = ref('')
|
||
const importFileUrl = ref('')
|
||
const importing = ref(false)
|
||
function openImport() {
|
||
importAuditResult.value = '2'
|
||
importAuditOpinion.value = ''
|
||
importFileUrl.value = ''
|
||
importOpen.value = true
|
||
}
|
||
function downloadImportTpl() {
|
||
ElMessage.info('批量导入模板下载 — 待后端提供静态文件')
|
||
}
|
||
async function submitImport() {
|
||
if (!importFileUrl.value) return ElMessage.warning('请选择文件')
|
||
importing.value = true
|
||
await new Promise(r => setTimeout(r, 500))
|
||
importing.value = false
|
||
ElMessage.info(`已提交批量导入任务 (审核结果: ${importAuditResult.value === '2' ? '通过' : '拒绝'}) — 待后端实现`)
|
||
importOpen.value = false
|
||
}
|
||
|
||
// ========== 批量导入执业证书/证明 ==========
|
||
const importCertOpen = ref(false)
|
||
const importCertUrl = ref('')
|
||
function openImportPracticeCert() { importCertUrl.value = ''; importCertOpen.value = true }
|
||
async function submitImportCert() {
|
||
if (!importCertUrl.value) return ElMessage.warning('请选择文件')
|
||
importing.value = true
|
||
await new Promise(r => setTimeout(r, 500))
|
||
importing.value = false
|
||
ElMessage.info('已提交批量导入执业证书任务 — 待后端实现')
|
||
importCertOpen.value = false
|
||
}
|
||
|
||
// ========== 批量导入职称证明 ==========
|
||
const importTitleCertOpen = ref(false)
|
||
const importTitleCertUrl = ref('')
|
||
function openImportTitleCert() { importTitleCertUrl.value = ''; importTitleCertOpen.value = true }
|
||
async function submitImportTitleCert() {
|
||
if (!importTitleCertUrl.value) return ElMessage.warning('请选择文件')
|
||
importing.value = true
|
||
await new Promise(r => setTimeout(r, 500))
|
||
importing.value = false
|
||
ElMessage.info('已提交批量导入职称证明任务 — 待后端实现')
|
||
importTitleCertOpen.value = false
|
||
}
|
||
|
||
onMounted(load)
|
||
// 从 ExpertNew 跳转回来时刷新列表
|
||
watch(() => route.fullPath, (newPath) => {
|
||
if (newPath === '/manager/experts') load()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 整页面板 (与 People.vue 风格一致) */
|
||
.manager-experts { padding: 16px; }
|
||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||
.filter-form { margin-bottom: 12px; }
|
||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; flex-wrap: wrap; }
|
||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||
|
||
/* 证书预览 dialog (1:1 抄 admin) */
|
||
.cert-preview { display: flex; justify-content: center; align-items: center; min-height: 200px; background: #f5f7fa; border-radius: 4px; padding: 8px; }
|
||
.cert-preview-error { color: #909399; padding: 40px 0; }
|
||
|
||
/* stage-* CSS 已删除: 改用 AuditStatusTag 组件 (el-tag 自带颜色) */
|
||
</style>
|