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:
@@ -2,8 +2,8 @@
|
||||
* 会议阶段显示 (事实驱动, 与后端 StageDeriver 镜像).
|
||||
*
|
||||
* biz_meeting 现在存「事实」: is_executed / is_frozen / is_settled / is_finished
|
||||
* + material_audit_stage (4 值: NOT_SUBMITTED/SUBMITTED/APPROVED/REJECTED)
|
||||
* + material_compliance_approved (区分两级审核) + 审核时间.
|
||||
* + 劳务/会务两轨各自 audit_stage (4 值: NOT_SUBMITTED/SUBMITTED/APPROVED/REJECTED)
|
||||
* + 各自 compliance_approved (区分两级审核) + 审核时间.
|
||||
*
|
||||
* 各角色看到的「阶段名称」由这些事实实时推导, 不再是单一 current_stage 枚举投影.
|
||||
* current_stage 仍是物理阶段缓存 (10 值), 仅供列表筛选精确匹配.
|
||||
@@ -13,21 +13,87 @@ function isTrue(v) {
|
||||
return v === 1 || v === '1' || v === true
|
||||
}
|
||||
|
||||
/** 单轨状态码: R=0, N=1, C0=2, C1=3, A=4 (数值越小 = 流程越靠前). */
|
||||
function stateOf(stage, complianceApproved) {
|
||||
if (stage === 'REJECTED') return 0
|
||||
if (stage === 'SUBMITTED') return isTrue(complianceApproved) ? 3 : 2
|
||||
if (stage === 'APPROVED') return 4
|
||||
return 1 // NOT_SUBMITTED (或空兜底)
|
||||
}
|
||||
|
||||
function laborState(row) {
|
||||
return stateOf(row.laborAuditStage, row.laborComplianceApproved)
|
||||
}
|
||||
|
||||
function serviceState(row) {
|
||||
return stateOf(row.serviceAuditStage, row.serviceComplianceApproved)
|
||||
}
|
||||
|
||||
/**
|
||||
* 10 值物理阶段 (镜像后端 StageDeriver.derivePhysicalStage), 用于颜色/筛选.
|
||||
* 两轨取最小进度 (流程最靠前的一轨决定会议物理态).
|
||||
*/
|
||||
export function derivePhysicalStage(row) {
|
||||
if (!row) return 'NOT_STARTED'
|
||||
if (isTrue(row.isFrozen)) return 'FROZEN'
|
||||
if (isTrue(row.isFinished)) return 'FINISHED'
|
||||
if (isTrue(row.isSettled)) return 'SETTLED'
|
||||
const material = row.materialAuditStage
|
||||
if (material === 'REJECTED') return 'RECTIFYING'
|
||||
if (material === 'APPROVED') return 'AWAITING_SETTLEMENT'
|
||||
if (material === 'SUBMITTED') return isTrue(row.materialComplianceApproved) ? 'AWAITING_SUPERVISION' : 'AWAITING_COMPLIANCE'
|
||||
const s = Math.min(laborState(row), serviceState(row))
|
||||
if (s === 0) return 'RECTIFYING'
|
||||
if (s === 2) return 'AWAITING_COMPLIANCE'
|
||||
if (s === 3) return 'AWAITING_SUPERVISION'
|
||||
if (s === 4) return 'AWAITING_SETTLEMENT'
|
||||
return isTrue(row.isExecuted) ? 'RUNNING' : 'NOT_STARTED'
|
||||
}
|
||||
|
||||
/** manager 优先级: C0=0, R=1, N=2, C1=3, A=4 (越小越优先). C0=有活最优先; 无活时按最早环节优先(R<N<C1<A). */
|
||||
function managerPriority(s) {
|
||||
switch (s) {
|
||||
case 2: return 0
|
||||
case 0: return 1
|
||||
case 1: return 2
|
||||
case 3: return 3
|
||||
default: return 4
|
||||
}
|
||||
}
|
||||
|
||||
/** sponsor 优先级: C1=0, R=1, N=2, C0=3, A=4 (越小越优先). C1=有活最优先; 无活时按最早环节优先(R<N<C0<A). */
|
||||
function sponsorPriority(s) {
|
||||
switch (s) {
|
||||
case 3: return 0
|
||||
case 0: return 1
|
||||
case 1: return 2
|
||||
case 2: return 3
|
||||
default: return 4
|
||||
}
|
||||
}
|
||||
|
||||
/** 按角色优先级选代表轨 (两轨中优先级更高的那轨). */
|
||||
function chooseState(role, labor, service) {
|
||||
if (role === 'manager') return managerPriority(labor) <= managerPriority(service) ? labor : service
|
||||
if (role === 'sponsor') return sponsorPriority(labor) <= sponsorPriority(service) ? labor : service
|
||||
return Math.min(labor, service)
|
||||
}
|
||||
|
||||
/** 单轨措辞 (代表轨状态 + 角色 → 展示名). */
|
||||
function render(role, s, executed) {
|
||||
switch (s) {
|
||||
case 0: // R 退回
|
||||
return role === 'executor' ? '已退回' : '待整改'
|
||||
case 1: // N 未提交
|
||||
if (!executed) return '未执行'
|
||||
return role === 'executor' ? '执行中' : '已执行未传材料'
|
||||
case 2: // C0 合规审中
|
||||
if (role === 'sponsor') return '已执行未传材料' // 只读
|
||||
return '待审核'
|
||||
case 3: // C1 支持方审中
|
||||
if (role === 'manager') return '审核通过'
|
||||
return '待审核'
|
||||
default: // 4 = A 已通过
|
||||
return '待结算'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 各角色展示阶段名 (镜像后端 StageDeriver.deriveDisplay).
|
||||
* role ∈ {executor, sponsor, manager, admin, doctor, expert}; 非流程角色回退 admin 中性.
|
||||
@@ -37,34 +103,8 @@ export function deriveStage(role, row) {
|
||||
if (isTrue(row.isFrozen)) return '冻结中'
|
||||
if (isTrue(row.isFinished)) return '已完结'
|
||||
if (isTrue(row.isSettled)) return '已结算'
|
||||
|
||||
const material = row.materialAuditStage
|
||||
|
||||
// 退回: 执行方看「已退回」, 其他方看「待整改」
|
||||
if (material === 'REJECTED') {
|
||||
return role === 'executor' ? '已退回' : '待整改'
|
||||
}
|
||||
|
||||
// 材料已支持方通过 → 待结算 (不再有 24h 慢路径)
|
||||
if (material === 'APPROVED') {
|
||||
return '待结算'
|
||||
}
|
||||
|
||||
// 材料在审 (SUBMITTED)
|
||||
if (material === 'SUBMITTED') {
|
||||
if (isTrue(row.materialComplianceApproved)) {
|
||||
// 支持方审中
|
||||
return role === 'manager' ? '审核通过' : '待审核'
|
||||
}
|
||||
// 合规审中
|
||||
return role === 'sponsor' ? '已执行未传材料' : '待审核'
|
||||
}
|
||||
|
||||
// 未提交
|
||||
if (isTrue(row.isExecuted)) {
|
||||
return role === 'executor' ? '执行中' : '已执行未传材料'
|
||||
}
|
||||
return '未执行'
|
||||
const chosen = chooseState(role, laborState(row), serviceState(row))
|
||||
return render(role, chosen, isTrue(row.isExecuted))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,31 +114,38 @@ export function stageLabel(role, row) {
|
||||
return deriveStage(role, row)
|
||||
}
|
||||
|
||||
/** 颜色 class (业务专用 tag), 基于物理阶段 */
|
||||
export function stageClass(row) {
|
||||
const s = derivePhysicalStage(row)
|
||||
if (s === 'NOT_STARTED') return 'pending'
|
||||
if (s === 'RUNNING') return 'running'
|
||||
if (s === 'AWAITING_COMPLIANCE' || s === 'AWAITING_SUPERVISION') return 'reviewing'
|
||||
if (s === 'SUPERVISION_APPROVED') return 'done'
|
||||
if (s === 'RECTIFYING') return 'waiting'
|
||||
if (s === 'AWAITING_SETTLEMENT') return 'waiting'
|
||||
if (s === 'SETTLED') return 'done'
|
||||
if (s === 'FINISHED') return 'done'
|
||||
if (s === 'FROZEN') return 'frozen'
|
||||
return 'default'
|
||||
/**
|
||||
* 展示阶段名 → 颜色映射 (class + el-tag type), 与 render() 措辞一一对应.
|
||||
* 颜色跟随「各角色看到的展示阶段」而非物理阶段, 避免文案与颜色错位
|
||||
* (如 sponsor 看「待审核」却因物理阶段 RECTIFYING 显示红色).
|
||||
* 规则: 待整改/已退回=红, 未执行=灰, 执行中/已执行未传材料=蓝, 待审核=橙, 通过/待结算/完结=绿.
|
||||
*/
|
||||
const STAGE_STYLE = {
|
||||
'冻结中': { cls: 'frozen', tag: 'info' },
|
||||
'已完结': { cls: 'done', tag: 'success' },
|
||||
'已结算': { cls: 'done', tag: 'success' },
|
||||
'待整改': { cls: 'waiting', tag: 'danger' },
|
||||
'已退回': { cls: 'waiting', tag: 'danger' },
|
||||
'未执行': { cls: 'pending', tag: 'info' },
|
||||
'执行中': { cls: 'running', tag: 'primary' },
|
||||
'已执行未传材料': { cls: 'running', tag: 'primary' },
|
||||
'待审核': { cls: 'reviewing', tag: 'warning' },
|
||||
'审核通过': { cls: 'done', tag: 'success' },
|
||||
'待结算': { cls: 'done', tag: 'success' },
|
||||
}
|
||||
|
||||
/** el-tag type (doctor 列表用), 基于物理阶段 */
|
||||
export function stageTag(row) {
|
||||
const s = derivePhysicalStage(row)
|
||||
if (s === 'NOT_STARTED') return 'info'
|
||||
if (s === 'RUNNING' || s === 'RECTIFYING') return 'primary'
|
||||
if (s === 'AWAITING_COMPLIANCE' || s === 'AWAITING_SUPERVISION') return 'warning'
|
||||
if (s === 'SUPERVISION_APPROVED' || s === 'SETTLED' || s === 'FINISHED') return 'success'
|
||||
if (s === 'AWAITING_SETTLEMENT') return 'warning'
|
||||
if (s === 'FROZEN') return 'info'
|
||||
return 'info'
|
||||
function stageStyle(role, row) {
|
||||
return STAGE_STYLE[deriveStage(role, row)] || { cls: 'default', tag: 'info' }
|
||||
}
|
||||
|
||||
/** 颜色 class (业务专用 tag), 基于角色展示阶段 (与 stageLabel 文案一致). */
|
||||
export function stageClass(role, row) {
|
||||
return stageStyle(role, row).cls
|
||||
}
|
||||
|
||||
/** el-tag type (doctor 列表用), 基于角色展示阶段. */
|
||||
export function stageTag(role, row) {
|
||||
return stageStyle(role, row).tag
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user