122 lines
3.8 KiB
TypeScript
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
|
|
}
|