feat: 会议劳务/会务材料分轨审核 + 注册页标题 + 下拉空值修复

会议材料分轨 (material_audit_stage 单轨 → labor/service 双轨):
- biz_meeting: labor_audit_stage/labor_compliance_approved + service_audit_stage/service_compliance_approved 四列替换原单轨两列
- StageDeriver: 单轨状态机(R/N/C0/C1/A) + 角色优先级选代表轨 + 会议物理态取两轨最小进度
- MeetingAuditStageEnum / 前端 meetingStage.js 镜像: 分轨推导 + 颜色跟随角色展示阶段(避免文案与颜色错位)
- BizMeetingController/ServiceImpl/AuditLog + mapper + MeetingStageScheduler 同步分轨字段
- MeetingDetail/Meetings/doctor/executor Meetings/ManagerProjectDetail/ManagerProjectsAssign/PublicityDetail 同步双轨

其它:
- 注册页 (执行单位/专家/支持单位) 加居中页标题
- DoctorDeptSelect/DoctorTitleSelect 空字符串统一 null, 避免挂载必填项飘红
- BizOrgMapper sponsor/executor options 加 status 字段
- sponsor/NewPerson 编辑态 orgName 只读
This commit is contained in:
郭庆泰
2026-08-26 18:13:22 +08:00
parent b5b3e3a213
commit b0256ccac3
25 changed files with 752 additions and 449 deletions
+5 -26
View File
@@ -6,7 +6,7 @@
筛选栏: <el-form inline :model="q" class="filter-form">
工具栏: <div class="toolbar">
列表列 (按原型 sponsor-people.html left 排序):
复选框 / 姓名 / 手机号 / 工作单位 / 部门 / 职务 / 角色(角色+账号类型已合并) / 状态 / 操作
姓名 / 手机号 / 工作单位 / 部门 / 职务 / 角色(角色+账号类型已合并) / 状态 / 操作
-->
<div class="page-card">
<div class="breadcrumb">首页 / 人员管理</div>
@@ -39,11 +39,9 @@
<div class="toolbar">
<el-button type="primary" @click="onCreate">新建人员</el-button>
<el-button @click="onImport">批量导入</el-button>
<el-button :disabled="!selected.length || hasSelfInSelection" @click="onBatchRemove">批量删除</el-button>
</div>
<el-table :data="rows" v-loading="loading" stripe border @selection-change="onSelectionChange">
<el-table-column type="selection" width="48" :selectable="(row) => row.userId !== store.user?.userId" />
<el-table :data="rows" v-loading="loading" stripe border>
<el-table-column prop="account" label="账号" width="120" show-overflow-tooltip />
<el-table-column prop="name" label="姓名" width="100" />
<el-table-column prop="phone" label="手机号" width="130" />
@@ -136,7 +134,7 @@
</template>
<script setup>
import { reactive, ref, computed } from 'vue'
import { reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { bizUpdate, bizDelete, resetPersonPassword } from '@/api/public'
@@ -148,9 +146,6 @@ import request from '@/utils/request'
const router = useRouter()
const store = useUserStore()
// 批量操作禁用判断: 选了主账号自己 (跟"操作列禁用/删除隐藏"是同一条规则, 防止误删)
const hasSelfInSelection = computed(() => selected.value.some(r => r.userId === store.user?.userId))
// sponsor 端只看自己团队 (主账号+子账号) 创建的人, 走专属接口 /business/person/sponsorList (后端强制隔离)
const q = reactive({
name: '', phone: '', orgName: '', department: '', status: ''
@@ -158,7 +153,6 @@ const q = reactive({
const page = reactive({ pageNum: 1, pageSize: 20, total: 0 })
const rows = ref([])
const loading = ref(false)
const selected = ref([])
async function load() {
loading.value = true
@@ -183,8 +177,6 @@ function reset() {
load()
}
function onSelectionChange(arr) { selected.value = arr }
function onCreate() {
router.push({ path: '/sponsor/people/new' })
}
@@ -241,21 +233,6 @@ async function onRemoveOne(row) {
}
}
async function onBatchRemove() {
if (!selected.value.length) { ElMessage.warning('请先勾选要删除的人员'); return }
if (hasSelfInSelection.value) { ElMessage.warning('选中的包含您本人, 不能删除'); return }
try {
await ElMessageBox.confirm(`确定删除选中的 ${selected.value.length} 条? 该操作不可恢复`, '批量删除', { type: 'warning' })
} catch { return }
let ok = 0
for (const r of selected.value) {
try { await bizDelete('person', r.personId); ok++ } catch {}
}
ElMessage.success(`已删除 ${ok}`)
selected.value = []
load()
}
// 批量导入 (Excel)
const importVisible = ref(false)
const uploadRef = ref()
@@ -338,4 +315,6 @@ load()
:deep(.el-table .el-button.is-link) { color: var(--brand-primary); background: transparent; border: none; }
:deep(.el-table .el-button.is-link:hover) { color: var(--brand-primary-deep); background: transparent; }
:deep(.el-table .el-button.is-link.is-disabled) { color: #c0c4cc; background: transparent; }
:deep(.el-table .el-button--danger.is-link) { color: var(--el-color-danger); }
:deep(.el-table .el-button--danger.is-link:hover) { color: var(--el-color-danger); }
</style>