feat: AI 对话支持 A2UI 表单/审查/图表与 Agent 工具
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import type { AiReviewSection, AiReviewSectionStatus, AiReviewSectionType } from './types';
|
||||
|
||||
export const SECTION_TYPE_LABELS: Record<AiReviewSectionType, string> = {
|
||||
students: '学生',
|
||||
rooms: '宿舍',
|
||||
transfers: '换宿',
|
||||
checkins: '入住记录',
|
||||
};
|
||||
|
||||
export const SECTION_ORDER: AiReviewSectionType[] = ['students', 'rooms', 'transfers', 'checkins'];
|
||||
|
||||
const SECTION_DEPENDENCIES: Record<AiReviewSectionType, AiReviewSectionType[]> = {
|
||||
students: [],
|
||||
rooms: [],
|
||||
transfers: ['students', 'rooms'],
|
||||
checkins: [],
|
||||
};
|
||||
|
||||
export function sectionType(section: Pick<AiReviewSection, 'key' | 'type'>): 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<AiReviewSectionStatus, string> = {
|
||||
pending: '待确认',
|
||||
submitted: '已导入',
|
||||
failed: '失败',
|
||||
skipped: '已跳过',
|
||||
};
|
||||
|
||||
export type GroupStatus = 'pending' | 'partial' | 'submitted' | 'failed' | 'importing';
|
||||
|
||||
export const GROUP_STATUS_LABELS: Record<GroupStatus, string> = {
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user