import type { OaCommentAttachmentRef, OaInstanceComment } from '@/api/oaApproval' /** 进度链条目(与 OaProgressChain 对齐;评论条目带扩展字段) */ export type ProgressTimelineItem = { key: string title: string status: string timestamp?: string assignee?: string resolveSource?: string commentText?: string taskType?: string kind?: string signMode?: string people?: Array> attachmentRefs?: OaCommentAttachmentRef[] canRevoke?: boolean commentId?: string commentStatus?: string revokedTime?: string mentions?: Array<{ userId: string; userName: string }> } /** 当前待审 / 未落地节点:不参与与评论的时间交错,挂在已办节点与评论之后。 */ function isNotReached(item: ProgressTimelineItem): boolean { return String(item.status || '') === 'not_reached' } function isCurrentPending(item: ProgressTimelineItem): boolean { if (isNotReached(item)) return false const status = String(item.status || '') const kind = String(item.kind || '') return status === 'pending' || status === 'running' || kind === 'pending_node' } /** * 将讨论评论按时间插入审批进度(钉钉式)。 * - 已办节点(发起/已同意/已拒绝/抄送完成等)与评论按时间交错 * - 当前待审节点挂在其后(评论落在「最后一个已办节点」后面) * - 未到达节点仍在轴末 */ export function mergeProgressWithComments( progressItems: ProgressTimelineItem[], comments: OaInstanceComment[] | undefined | null ): ProgressTimelineItem[] { const base = Array.isArray(progressItems) ? [...progressItems] : [] const future = base.filter((p) => isNotReached(p)) const current = base.filter((p) => isCurrentPending(p)) const done = base.filter((p) => !isNotReached(p) && !isCurrentPending(p)) const commentRows: ProgressTimelineItem[] = (comments || []).map((c) => ({ key: `comment-${c.id}`, kind: 'comment', title: c.createByName || c.createBy || '评论', status: c.status === 'revoked' ? 'revoked' : 'commented', timestamp: c.createTime || '', commentText: c.content || '', assignee: c.createByName || c.createBy || '', attachmentRefs: Array.isArray(c.attachmentRefs) ? c.attachmentRefs : [], canRevoke: !!c.canRevoke, commentId: c.id, commentStatus: c.status || 'normal', revokedTime: c.revokedTime || '', mentions: Array.isArray(c.mentions) ? c.mentions : [] })) const merged = [...done, ...commentRows].sort((a, b) => { const ta = String(a.timestamp || '') const tb = String(b.timestamp || '') if (ta !== tb) return ta < tb ? -1 : 1 const aIsComment = a.kind === 'comment' const bIsComment = b.kind === 'comment' if (aIsComment !== bIsComment) return aIsComment ? 1 : -1 return String(a.key || '').localeCompare(String(b.key || '')) }) return [...merged, ...current, ...future] }