export interface HandoffRequestFacts { source?: 'gitea' | 'youtrack' column: 'todo' | 'in-progress' | 'review' | 'done' handoffAttachmentId?: string handoffRequestFrom?: string handoffRequestError?: string assignees?: string[] } function openReview(issue: HandoffRequestFacts): boolean { return issue.source !== 'youtrack' && issue.column === 'review' && !issue.handoffAttachmentId } /** 审查列里同事负责的工单,且当前没有别的申请。 */ export function canAskHandoff(issue: HandoffRequestFacts, me: string | undefined): boolean { if (!me || !openReview(issue)) return false const assignees = issue.assignees ?? [] if (assignees.length === 0 || assignees.includes(me)) return false return !issue.handoffRequestFrom } /** 申请人在对方回应前可以取消。 */ export function canCancelHandoffRequest(issue: HandoffRequestFacts, me: string | undefined): boolean { return !!me && openReview(issue) && issue.handoffRequestFrom === me } /** 负责人同意或拒绝。同意会走现有移交。 */ export function handoffRequestNotices(before: HandoffRequestFacts & { number: number }, next: HandoffRequestFacts & { number: number }, me: string): string[] { const notices: string[] = [] if ( next.handoffRequestFrom && next.handoffRequestFrom !== before.handoffRequestFrom && next.handoffRequestFrom !== me && (next.assignees ?? []).includes(me) ) { notices.push(`${next.handoffRequestFrom} 想要 #${next.number}`) } if (before.handoffRequestFrom === me && next.handoffRequestError === 'rejected' && before.handoffRequestError !== 'rejected') notices.push(`#${next.number} 的移交申请被拒绝了`) if ( next.handoffRequestFrom === me && next.handoffRequestError && next.handoffRequestError !== 'rejected' && next.handoffRequestError !== before.handoffRequestError ) { notices.push(`#${next.number} 没交出来:${next.handoffRequestError}`) } return notices } export function canAnswerHandoffRequest(issue: HandoffRequestFacts, me: string | undefined): boolean { return !!me && openReview(issue) && !!issue.handoffRequestFrom && (issue.assignees ?? []).includes(me) }