import { knowledgeAreas, processGroups, processes, } from '@/data' import type { Process } from '@/types/itto' export interface CellInfo { id: string // 格子唯一标识 type: 'knowledge-area' | 'process' knowledgeAreaId: string processGroupId?: string // 知识领域格子无此字段 processId?: string // 过程格子才有 answer: string // 正确答案(原始) normalizedAnswer: string // 标准化答案(用于比对) order: number // 全局顺序 } /** * 答案标准化函数 * @param str 原始字符串 * @param isKnowledgeArea 是否为知识领域(只对知识领域去除"项目"前缀) */ export function normalizeAnswer( str: string, isKnowledgeArea: boolean = false ): string { let normalized = str .replace(/\s+/g, '') // 去除空格 .toLowerCase() // 转小写(如有英文) .replace(/[,。、;:""''()【】]/g, '') // 去除中文标点 // 只对知识领域去除"项目"前缀 if (isKnowledgeArea) { normalized = normalized.replace(/^项目/, '') } return normalized } /** * 生成格子顺序列表 * 顺序:KA01 → P1.1 → P1.2 → ... → P1.7 → KA02 → P2.1 → ... */ export function generateCellSequence(): CellInfo[] { const sequence: CellInfo[] = [] let order = 0 // 确保数据源按 order 字段排序 const sortedKAs = [...knowledgeAreas].sort((a, b) => a.order - b.order) const sortedPGs = [...processGroups].sort((a, b) => a.order - b.order) sortedKAs.forEach((ka) => { // 1. 添加知识领域格子 sequence.push({ id: `ka-${ka.id}`, type: 'knowledge-area', knowledgeAreaId: ka.id, answer: ka.name.replace('项目', ''), // "项目整合管理" -> "整合管理" normalizedAnswer: normalizeAnswer(ka.name, true), // 知识领域去除"项目" order: order++, }) // 2. 添加该知识领域下的所有过程格子(按过程组顺序) sortedPGs.forEach((pg) => { const kaProcesses = processes .filter((p) => p.knowledgeAreaId === ka.id && p.processGroupId === pg.id) .sort((a, b) => a.order - b.order) kaProcesses.forEach((p) => { sequence.push({ id: `process-${p.id}`, type: 'process', knowledgeAreaId: ka.id, processGroupId: pg.id, processId: p.id, answer: p.name, normalizedAnswer: normalizeAnswer(p.name, false), // 过程不去除"项目" order: order++, }) }) }) }) return sequence } /** * 获取指定知识领域和过程组下的所有过程 */ export function getProcessesByKaAndPg( knowledgeAreaId: string, processGroupId: string ): Process[] { return processes .filter( (p) => p.knowledgeAreaId === knowledgeAreaId && p.processGroupId === processGroupId ) .sort((a, b) => a.order - b.order) } /** * 无障碍通告函数 */ export function announceToScreenReader(message: string): void { const liveRegion = document.getElementById('aria-live-region') if (liveRegion) { liveRegion.textContent = message // 清空,以便下次通告 setTimeout(() => { liveRegion.textContent = '' }, 1000) } }