feat: 会议提交剩余时间+解冻 + 会务/劳务材料批量下载 + 多角色人员/账号模块完善
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
* 会议阶段显示 (事实驱动, 与后端 StageDeriver 镜像).
|
||||
*
|
||||
* biz_meeting 现在存「事实」: is_executed / is_frozen / is_settled / is_finished
|
||||
* + material_audit_stage / voucher_audit_stage (4 值: NOT_SUBMITTED/SUBMITTED/APPROVED/REJECTED)
|
||||
* + material/voucher_compliance_approved (区分两级审核) + 审核时间.
|
||||
* + material_audit_stage (4 值: NOT_SUBMITTED/SUBMITTED/APPROVED/REJECTED)
|
||||
* + material_compliance_approved (区分两级审核) + 审核时间.
|
||||
*
|
||||
* 各角色看到的「阶段名称」由这些事实实时推导, 不再是单一 current_stage 枚举投影.
|
||||
* current_stage 仍是物理阶段缓存 (10 值), 仅供列表筛选精确匹配.
|
||||
@@ -15,14 +15,12 @@ function isTrue(v) {
|
||||
return v === 1 || v === '1' || v === true
|
||||
}
|
||||
|
||||
/** 待结算: 材料+凭证都通过 且 最晚审核时间已超 24h */
|
||||
/** 待结算: 材料审核通过 且 材料审核时间已超 24h */
|
||||
function settlementReady(row) {
|
||||
if (row.voucherAuditStage !== 'APPROVED') return false
|
||||
if (row.materialAuditStage !== 'APPROVED') return false
|
||||
const mat = row.materialAuditTime ? new Date(row.materialAuditTime).getTime() : 0
|
||||
const vch = row.voucherAuditTime ? new Date(row.voucherAuditTime).getTime() : 0
|
||||
const later = Math.max(mat, vch)
|
||||
if (!later) return false
|
||||
return Date.now() - later >= H24
|
||||
if (!mat) return false
|
||||
return Date.now() - mat >= H24
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,14 +36,17 @@ request.interceptors.response.use(
|
||||
const redirect = window.location.hash.slice(1) || ''
|
||||
window.location.href = import.meta.env.BASE_URL + '#/login' + (redirect ? '?redirect=' + encodeURIComponent(redirect) : '')
|
||||
}
|
||||
// __silentError: 调用方已经接管错误 toast (如把红错改成黄警), 拦截器不再重复弹
|
||||
if (!res.config?.__silentError) {
|
||||
// 写操作 (POST/PUT/DELETE) 的错误由调用方 catch 自己 toast (避免拦截器 + catch 双 toast);
|
||||
// 读操作 (GET) 没有统一 catch toast, 由拦截器兜底提示。__silentError: 调用方已接管, 拦截器不弹。
|
||||
const isMutation = ['post', 'put', 'delete'].includes(String(res.config?.method || '').toLowerCase())
|
||||
if (!res.config?.__silentError && !isMutation) {
|
||||
ElMessage.error(data?.msg || '请求失败')
|
||||
}
|
||||
return Promise.reject(Object.assign(new Error(data?.msg || '请求失败'), { msg: data?.msg, code: data?.code, silentError: !!res.config?.__silentError }))
|
||||
},
|
||||
(err) => {
|
||||
if (!err.config?.__silentError) {
|
||||
const isMutation = ['post', 'put', 'delete'].includes(String(err.config?.method || '').toLowerCase())
|
||||
if (!err.config?.__silentError && !isMutation) {
|
||||
ElMessage.error(err.message || '网络错误')
|
||||
}
|
||||
return Promise.reject(err)
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
/**
|
||||
* biz_person.role enum key → 中文 label 翻译
|
||||
* 跟 sys_user.role_type 模式一致: DB 存 enum key, UI 显示中文
|
||||
*
|
||||
* 适用场景:
|
||||
* - executor/People.vue 列表/详情显示 role
|
||||
* - 各处 NewPerson 表单 el-option (label=中文, value=key)
|
||||
* - 查询条件 role=key
|
||||
* 角色展示 = f(unitType, accountType) — 单一可信源.
|
||||
* biz_person.role 列已废弃 (DROP COLUMN), 角色由账号层级 (sys_user.account_type) + 单位类型推导.
|
||||
*/
|
||||
export const PERSON_ROLE_LABEL = {
|
||||
meetingExecutor: '会议执行',
|
||||
supervisor: '监察员',
|
||||
admin: '管理员'
|
||||
|
||||
/**
|
||||
* 角色 = f(unitType, accountType) — biz_person.role 与 sys_user.account_type 合并后的单一可信源.
|
||||
* 不再读 biz_person.role, 直接由账号层级 (MAIN/SUB) + 单位类型推导:
|
||||
* 支持方 (sponsor): MAIN=管理员, SUB=监察员
|
||||
* 执行方 (executor): MAIN=管理员, SUB=执行人员
|
||||
* @param {string} unitType 'sponsor' | 'executor'
|
||||
* @param {string} accountType 'MAIN' | 'SUB'
|
||||
* @returns {string} 推导不出时返回 ''
|
||||
*/
|
||||
export function accountTypeRoleLabel(unitType, accountType) {
|
||||
if (accountType === 'MAIN') return '管理员'
|
||||
if (accountType === 'SUB') return unitType === 'executor' ? '执行人员' : '监察员'
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译 biz_person.role enum key → 中文 label
|
||||
* @param {string} key
|
||||
* @returns {string} 没匹配到时返回原 key, 避免显示 'undefined'
|
||||
* 角色 tag 类型: 主账号高亮 (warning), 子账号普通 (primary)
|
||||
* @param {string} accountType
|
||||
*/
|
||||
export function translatePersonRole(key) {
|
||||
if (!key) return ''
|
||||
return PERSON_ROLE_LABEL[key] || key
|
||||
export function accountTypeRoleTagType(accountType) {
|
||||
return accountType === 'MAIN' ? 'warning' : 'primary'
|
||||
}
|
||||
Reference in New Issue
Block a user