Files
zkxw/web-admin/src/utils/oa-progress-person-lines.ts
T
2026-08-13 14:31:57 +08:00

122 lines
3.8 KiB
TypeScript

/**
* 或签/会签进度人员行格式化
* Spec: docs/superpowers/specs/2026-07-23-oa-or-and-sign-display-design.md
* 转交行:docs/superpowers/specs/2026-07-23-oa-approval-transfer-design.md(扩展展示转交目标)
*/
export type ProgressPersonInput = {
id?: string
nickName?: string
status?: string
timestamp?: string
commentText?: string
/** 转交目标用户 id(后端 build_progress_items 补齐) */
transferToUserId?: string
/** 转交目标用户昵称 */
transferToUserName?: string
}
export type PersonLineTone = 'ok' | 'pending' | 'danger' | 'mute' | ''
export type ProgressPersonLine = {
/** 完整一行(含时间),详情页等纯文本场景用 */
text: string
tone: PersonLineTone
/** 不含时间的主体,打印右对齐时间用 */
body: string
/** 审批时间(可空) */
timestamp: string
}
const ACTED_STATUS = new Set(['approved', 'rejected', 'returned', 'completed', 'transferred'])
function displayName(p: ProgressPersonInput): string {
return String(p.nickName || p.id || '').trim()
}
function transferTargetName(p: ProgressPersonInput): string {
return String(p.transferToUserName || p.transferToUserId || '').trim()
}
function statusFallbackLabel(status: string): string {
const s = (status || '').trim()
if (s === 'approved') return '已同意'
if (s === 'rejected') return '已拒绝'
if (s === 'returned') return '已打回'
if (s === 'completed') return '已完成'
if (s === 'transferred') return '已转交'
return s || '已处理'
}
function toneForStatus(status: string): PersonLineTone {
const s = (status || '').trim()
if (s === 'approved' || s === 'completed') return 'ok'
if (s === 'pending' || s === 'running' || s === 'not_reached') return 'pending'
if (s === 'rejected' || s === 'returned') return 'danger'
if (s === 'done' || s === 'transferred' || s === 'cancelled') return 'mute'
return ''
}
function pushLine(
out: ProgressPersonLine[],
body: string,
timestamp: string,
tone: PersonLineTone
) {
const ts = String(timestamp || '').trim()
out.push({
body,
timestamp: ts,
text: ts ? `${body} ${ts}` : body,
tone
})
}
/** 将 progress.people 格式化为「姓名 意见/状态 时间」纯文本行 */
export function formatProgressPersonLines(
people: ProgressPersonInput[] | null | undefined
): ProgressPersonLine[] {
const list = Array.isArray(people) ? people : []
const out: ProgressPersonLine[] = []
for (const p of list) {
const name = displayName(p)
if (!name) continue
const status = String(p.status || '').trim()
const comment = String(p.commentText || '').trim()
const ts = String(p.timestamp || '').trim()
const tone = toneForStatus(status)
if (status === 'done' || status === 'cancelled') {
pushLine(out, `${name} 无需处理`, '', 'mute')
continue
}
if (status === 'transferred') {
const target = transferTargetName(p)
const mid = target
? comment
? `转交给${target} ${comment}`
: `转交给${target}`
: comment || statusFallbackLabel('transferred')
pushLine(out, `${name} ${mid}`, ts, 'mute')
continue
}
if (status === 'pending' || status === 'running' || status === 'not_reached' || !status) {
// 无 status 时:若有意见/时间仍按已处理拼;否则待处理
if (!status && (comment || ts)) {
const mid = comment || statusFallbackLabel('approved')
pushLine(out, `${name} ${mid}`, ts, 'ok')
continue
}
pushLine(out, `${name} 待处理`, '', 'pending')
continue
}
if (ACTED_STATUS.has(status) || comment || ts) {
const mid = comment || statusFallbackLabel(status)
pushLine(out, `${name} ${mid}`, ts, tone || 'ok')
continue
}
pushLine(out, `${name} 待处理`, '', 'pending')
}
return out
}