import type { AiReviewSection, AiReviewSectionStatus, AiReviewSectionType } from './types'; export const SECTION_TYPE_LABELS: Record = { students: '学生', rooms: '宿舍', transfers: '换宿', checkins: '入住记录', }; export const SECTION_ORDER: AiReviewSectionType[] = ['students', 'rooms', 'transfers', 'checkins']; const SECTION_DEPENDENCIES: Record = { students: [], rooms: [], transfers: ['students', 'rooms'], checkins: [], }; export function sectionType(section: Pick): AiReviewSectionType { if ( section.type === 'students' || section.type === 'rooms' || section.type === 'transfers' || section.type === 'checkins' ) { return section.type; } const key = section.key as AiReviewSectionType; if (key === 'students' || key === 'rooms' || key === 'transfers' || key === 'checkins') { return key; } const prefix = SECTION_ORDER.find((type) => section.key.startsWith(`${type}_`)); return prefix ?? 'students'; } export function sectionCount(section: AiReviewSection): number { return section.rows.length; } export function sectionStatus(section: AiReviewSection): AiReviewSectionStatus { return section.status ?? 'pending'; } export function sectionResultText(section: AiReviewSection): string { if (!section.resultSummary) return ''; try { const parsed = JSON.parse(section.resultSummary) as { message?: unknown }; if (typeof parsed.message === 'string') return parsed.message; } catch { // Older data may store a plain text summary. } return section.resultSummary; } export const SECTION_STATUS_LABELS: Record = { pending: '待确认', submitted: '已导入', failed: '失败', skipped: '已跳过', }; export type GroupStatus = 'pending' | 'partial' | 'submitted' | 'failed' | 'importing'; export const GROUP_STATUS_LABELS: Record = { pending: '待确认', partial: '部分完成', submitted: '已导入', failed: '失败', importing: '导入中', }; export function groupSections( sections: AiReviewSection[], type: AiReviewSectionType, ): AiReviewSection[] { return sections.filter((section) => sectionType(section) === type); } export function groupStatus( sections: AiReviewSection[], type: AiReviewSectionType, submittingKey: string | null, submittingGroup: boolean, activeType?: AiReviewSectionType, ): GroupStatus { const items = groupSections(sections, type); if (items.length === 0) return 'pending'; if ( (submittingGroup && type === activeType) || items.some((item) => submittingKey === item.key) ) { return 'importing'; } if (items.some((item) => sectionStatus(item) === 'failed')) return 'failed'; if (items.every((item) => sectionStatus(item) === 'submitted')) return 'submitted'; return 'partial'; } export function dependencyHint( sections: AiReviewSection[], type: AiReviewSectionType, ): { step: number; title: string } | null { for (const dependencyType of SECTION_DEPENDENCIES[type] ?? []) { const matches = groupSections(sections, dependencyType); if (matches.length === 0) { return { step: -1, title: SECTION_TYPE_LABELS[dependencyType] }; } for (const section of matches) { if (sectionStatus(section) !== 'submitted') { return { step: sections.indexOf(section), title: section.title }; } } } return null; }