docs(audit): add audit reports for grades, homework, lesson-preparation, messaging, permissions, question-bank, settings, textbooks
- Add grades-audit-report - Add homework-audit-report and homework-exams-audit-report - Add lesson-preparation-audit-report-v3 and v4 - Add messaging-audit-report - Add permissions-audit-report - Add question-bank-audit-report - Add settings-profile-audit-report-v3 - Add textbooks-audit-report-v3
This commit is contained in:
382
docs/architecture/audit/ai-audit-report.md
Normal file
382
docs/architecture/audit/ai-audit-report.md
Normal file
@@ -0,0 +1,382 @@
|
||||
# AI 模块审计报告
|
||||
|
||||
> 审计日期:2026-06-25
|
||||
> 审计范围:`src/modules/ai/` 全部代码 + `src/app/api/ai/` 路由 + app 层接入点
|
||||
> 审计依据:`docs/architecture/004_architecture_impact_map.md`、`docs/architecture/005_architecture_data.json`、`docs/standards/coding-standards.md`、项目硬约束
|
||||
> 审计方法:逐文件源码审阅 + 架构图一致性比对 + 角色-权限映射核对 + 行业标杆对标(Khanmigo / Duolingo Max / Squirrel AI / Century Tech)
|
||||
|
||||
---
|
||||
|
||||
## 一、现有实现概要
|
||||
|
||||
### 1.1 文件分布(共 32 个文件)
|
||||
|
||||
```
|
||||
src/modules/ai/
|
||||
├─ types.ts 330 行 AiService / AiClientService 接口 + 业务类型
|
||||
├─ schema.ts 248 行 Zod 校验(输入 + AI 输出)
|
||||
├─ actions.ts 415 行 10 个 Server Action(含权限校验)
|
||||
├─ data-access.ts 138 行 内存事件存储 + 使用统计聚合
|
||||
├─ services/
|
||||
│ ├─ ai-service.ts 478 行 DefaultAiService 实现(封装 shared/lib/ai)
|
||||
│ ├─ prompt-templates.ts 300 行 9 套 System Prompt 常量
|
||||
│ ├─ usage-tracker.ts 100 行 trackAiUsage + withAiTracking
|
||||
│ └─ content-safety.ts 291 行 输入/输出过滤 + 每日限额(原子操作)
|
||||
├─ context/
|
||||
│ ├─ ai-client-provider.tsx 62 行 React Context 注入 AiClientService
|
||||
│ └─ create-ai-client-service.ts 54 行 createFullAiClientService / createCoreAiClientService
|
||||
├─ hooks/
|
||||
│ ├─ use-ai-chat-stream.ts 155 行 SSE 流式聊天 + localStorage 持久化
|
||||
│ ├─ use-ai-chat.ts 57 行 非流式聊天(⚠ 死代码,未被引用)
|
||||
│ ├─ use-ai-suggestion.ts 72 行 相似题 / 批改建议
|
||||
│ ├─ stream-utils.ts 135 行 SSE 解析纯函数
|
||||
│ ├─ use-floating-ball.ts 160 行 悬浮球组合 hook
|
||||
│ ├─ use-drag-position.ts 130 行 拖拽 hook
|
||||
│ └─ use-position-persistence.ts 99 行 位置 localStorage
|
||||
├─ components/
|
||||
│ ├─ ai-assistant-widget.tsx 329 行 全局悬浮球 + 上下文感知 + Sheet
|
||||
│ ├─ ai-chat-panel.tsx 417 行 聊天面板(card / widget 双变体)
|
||||
│ ├─ ai-error-boundary.tsx 31 行 SectionErrorBoundary 包装
|
||||
│ ├─ ai-skeleton.tsx 47 行 AiSuggestionSkeleton / AiChatSkeleton
|
||||
│ ├─ ai-suggestion-card.tsx 178 行 相似题卡片(⚠ 死代码,未被引用)
|
||||
│ ├─ ai-provider-selector.tsx 89 行 表单字段(react-hook-form)
|
||||
│ ├─ ai-markdown-renderer.tsx 162 行 Markdown + 图表代码块渲染
|
||||
│ ├─ ai-chart-renderer.tsx 351 行 Recharts 4 图表(bar/line/pie/radar)
|
||||
│ ├─ ai-grading-assist.tsx 173 行 教师批改辅助
|
||||
│ ├─ ai-error-book-analysis.tsx 246 行 学生错题本 AI 分析
|
||||
│ ├─ ai-lesson-content-generator.tsx 180 行 教师备课内容生成
|
||||
│ ├─ ai-question-variant-generator.tsx 218 行 题目变体生成
|
||||
│ ├─ ai-usage-dashboard.tsx 221 行 管理员使用统计
|
||||
│ ├─ ai-child-summary.tsx 186 行 家长学情摘要(⚠ 未接入页面)
|
||||
│ └─ ai-study-path.tsx 200 行 学生学习路径(⚠ 未接入页面)
|
||||
└─ src/app/api/ai/
|
||||
├─ chat/route.ts 196 行 非流式聊天端点
|
||||
└─ chat/stream/route.ts 237 行 SSE 流式端点
|
||||
```
|
||||
|
||||
### 1.2 数据流
|
||||
|
||||
```
|
||||
app/(dashboard)/layout.tsx
|
||||
│ 模块级 const aiClientService = createFullAiClientService()
|
||||
▼
|
||||
<AiClientProvider service={aiClientService}> ← React Context
|
||||
│
|
||||
├─ <AiAssistantWidget /> ← 全局悬浮球
|
||||
│ └─ useAiClientOptional() / useFloatingBall()
|
||||
│ └─ <AiChatPanel variant="widget">
|
||||
│ └─ useAiChatStream() → fetch('/api/ai/chat/stream')
|
||||
│ │
|
||||
│ ▼
|
||||
│ route.ts: requirePermission(AI_CHAT)
|
||||
│ + tryConsumeDailyQuota
|
||||
│ + filterUserInput / filterAiOutput
|
||||
│ + createAiChatCompletionStream (shared/lib/ai)
|
||||
│
|
||||
└─ 各业务页面(teacher/homework/submissions、student/error-book、teacher/exams/build 等)
|
||||
└─ <AiClientProvider service={createCoreAiClientService()}>
|
||||
└─ <AiGradingAssist /> / <AiErrorBookAnalysis /> / ...
|
||||
└─ useAiClient().suggestGrading(...) → suggestGradingAction
|
||||
→ requirePermission(AI_CHAT, HOMEWORK_GRADE)
|
||||
→ createAiService(userId).suggestGrading(input)
|
||||
→ withAiTracking(...)
|
||||
→ createAiChatCompletion (shared/lib/ai)
|
||||
```
|
||||
|
||||
### 1.3 架构图记录情况
|
||||
|
||||
`005_architecture_data.json` 中 `modules.ai` 节点记录了完整的依赖矩阵、exports 清单、集成点、权限点、安全策略、流式特性、i18n 命名空间。
|
||||
|
||||
**但比对发现两处与实际实现不一致**(详见 §二 P0-2):
|
||||
- `ai.integrations.parent-dashboard` 声称 `AiChildSummary` 接入 `parent/dashboard` 页面 → 实际未接入
|
||||
- `ai.integrations.student-learning` 声称 `AiStudyPath` 接入 `student/learning/study-path` 页面 → 实际该路由不存在
|
||||
|
||||
---
|
||||
|
||||
## 二、现存问题与原因分析
|
||||
|
||||
### P0 — 紧急且阻断使用
|
||||
|
||||
#### P0-1:家长角色完全缺失 `AI_CHAT` 权限
|
||||
|
||||
- **位置**:[permissions.ts](file:///e:/Desktop/CICD/src/shared/lib/permissions.ts#L161-L176) `ROLE_PERMISSIONS_SEED.parent` 数组
|
||||
- **问题**:parent 角色权限清单中**没有任何** `Permissions.AI_CHAT`,但:
|
||||
- [actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L267) `generateChildSummaryAction` 第一行调用 `requirePermission(Permissions.AI_CHAT)` → 家长调用必返回 403
|
||||
- [actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L296) `recommendStudyPathAction` 同上
|
||||
- `/api/ai/chat/route.ts` L49 同上
|
||||
- `AiChildSummary` / `AiStudyPath` 组件存在但家长/学生路径下完全无法使用
|
||||
- **违反规则**:
|
||||
- 项目硬约束「所有 Server Action 必须调用 `requirePermission()` 进行权限校验」—— 校验逻辑本身正确,但权限未授予
|
||||
- 项目硬约束「家长需要的功能应被授权」(K12 系统家长是关键角色)
|
||||
- **后果**:家长角色付费的 AI 学情摘要功能在生产环境 100% 失败;学生使用学习路径推荐时若依赖家长代调也会失败
|
||||
|
||||
#### P0-2:架构图虚构集成(AiChildSummary / AiStudyPath 完全未接入)
|
||||
|
||||
- **位置**:
|
||||
- [005_architecture_data.json](file:///e:/Desktop/CICD/docs/architecture/005_architecture_data.json#L19725-L19744) `ai.integrations.parent-dashboard` / `ai.integrations.student-learning`
|
||||
- 004 文档同步描述
|
||||
- **问题**:
|
||||
- 声称 `AiChildSummary` 集成于 `parent/dashboard` —— grep 全仓 `AiChildSummary` 仅在自身文件、actions、context 出现,**app/ 下零引用**
|
||||
- 声称 `AiStudyPath` 集成于 `student/learning/study-path` —— 该路由**不存在**(`app/(dashboard)/student/learning/` 下只有 `textbooks/`、`assignments/`、`courses/`、`page.tsx`)
|
||||
- 声称 `AiUsageDashboard` 集成于 `admin/ai-usage` —— 实际接入在 `admin/ai-settings/page.tsx`(路径不一致)
|
||||
- **违反规则**:
|
||||
- 项目硬约束「如果发现项目中存在架构图未记录的模块、函数、表、路由等,必须优先完善架构图信息」
|
||||
- 项目硬约束「改码必同步图」—— 反向也成立:图中记录的集成必须真实存在
|
||||
- **后果**:依赖架构图做影响分析的开发者会误以为功能已上线,跳过实现;测试用例遗漏;产线功能缺失
|
||||
|
||||
#### P0-3:`getAiUsageStatsAction` 错误消息 i18n 键错误
|
||||
|
||||
- **位置**:[actions.ts](file:///e:/Desktop/CICD/src/modules/ai/actions.ts#L381)
|
||||
- **问题**:管理员查询使用统计失败时返回 `t("error.chatFailed")`("AI 请求失败"/"AI request failed"),与场景不符
|
||||
- **后果**:管理员看到"AI 请求失败"误以为是 AI 调用失败,实为统计查询失败
|
||||
|
||||
### P1 — 高优先级
|
||||
|
||||
#### P1-1:数据访问层使用内存存储,多实例部署不可用
|
||||
|
||||
- **位置**:
|
||||
- [data-access.ts](file:///e:/Desktop/CICD/src/modules/ai/data-access.ts#L34) `const eventStore: StoredAiEvent[] = []` 单实例内存
|
||||
- [content-safety.ts](file:///e:/Desktop/CICD/src/modules/ai/services/content-safety.ts#L137) `const dailyUsageMap = new Map<...>()` 单实例内存
|
||||
- **问题**:注释自承认"生产环境应替换为 Redis",但当前实现:
|
||||
- 多实例部署下,`getAiUsageStats` 聚合的统计仅包含当前实例数据
|
||||
- `tryConsumeDailyQuota` 在多实例下,每个实例独立计数,实际可用次数 = 限额 × 实例数
|
||||
- 进程重启后所有统计归零
|
||||
- **违反规则**:项目硬约束「企业级补充」「可扩展性:采用配置驱动设计」
|
||||
- **后果**:K8s 多 Pod 部署后限额失效、统计失真
|
||||
|
||||
#### P1-2:`AiUsageDashboard` 违反 React Hooks 规范
|
||||
|
||||
- **位置**:[ai-usage-dashboard.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-usage-dashboard.tsx#L53-L57)
|
||||
- **问题**:
|
||||
```tsx
|
||||
useEffect(() => {
|
||||
void loadStats()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
```
|
||||
- `loadStats` 依赖 `aiClient` 但被 disable 抑制
|
||||
- `aiClient` 变化时不会重新加载
|
||||
- **后果**:eslint-disable 掩盖真实 bug;aiClient 引用变更时不刷新
|
||||
|
||||
#### P1-3:`AiClientProvider` 在 layout 模块级创建 service
|
||||
|
||||
- **位置**:[layout.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/layout.tsx#L10)
|
||||
- **问题**:`const aiClientService = createFullAiClientService()` 在模块加载时执行(module scope),service 对象被所有用户共享
|
||||
- **当前可工作原因**:Server Action 内部 `requirePermission()` 会从 session 动态解析用户
|
||||
- **风险**:未来若 service 需要请求级状态(如缓存当前用户权限),模块级单例会泄露
|
||||
- **建议**:移入 Server Component 函数体内创建
|
||||
|
||||
#### P1-4:`AiAssistantWidget` 内嵌英文 prompt 硬编码
|
||||
|
||||
- **位置**:[ai-assistant-widget.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-assistant-widget.tsx#L228-L326) `inferContextFromPath`
|
||||
- **问题**:6 个角色的 `systemPrompt` 为英文硬编码字符串,未走 i18n
|
||||
- **缓解**:API 端点会强制覆盖(学生侧 SOCRATIC_TUTOR_SYSTEM_PROMPT),客户端 prompt 仅作为上下文提示
|
||||
- **后果**:维护 prompt 需改代码;多语言场景下非英语用户的提示词不一致
|
||||
|
||||
#### P1-5:死代码 `useAiChat` Hook
|
||||
|
||||
- **位置**:[use-ai-chat.ts](file:///e:/Desktop/CICD/src/modules/ai/hooks/use-ai-chat.ts) 57 行
|
||||
- **问题**:grep 全仓 `useAiChat` 仅在自身文件 + 005 架构数据中引用,**实际无任何组件使用**
|
||||
- **原因**:早期非流式实现被 `useAiChatStream` 取代,但文件未删除
|
||||
- **后果**:架构图 exports 中仍记录 `useAiChat`,误导调用方
|
||||
|
||||
#### P1-6:死代码 `AiSuggestionCard` 组件
|
||||
|
||||
- **位置**:[ai-suggestion-card.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-suggestion-card.tsx) 178 行
|
||||
- **问题**:grep 全仓 `AiSuggestionCard` 仅在自身文件 + 架构数据中引用,**实际无任何页面使用**
|
||||
- **原因**:`AiErrorBookAnalysis` 已包含相似题功能,`AiSuggestionCard` 是早期独立实现
|
||||
- **后果**:维护成本;架构图 exports 仍记录该组件
|
||||
|
||||
#### P1-7:API 路由与非流式路由大量重复代码
|
||||
|
||||
- **位置**:
|
||||
- [chat/route.ts](file:///e:/Desktop/CICD/src/app/api/ai/chat/route.ts) 196 行
|
||||
- [chat/stream/route.ts](file:///e:/Desktop/CICD/src/app/api/ai/chat/stream/route.ts) 237 行
|
||||
- **问题**:权限校验 / 限流 / Zod 校验 / 配额消费 / 输入过滤 / 系统提示构建 / 配额退款 7 段逻辑几乎逐行复制
|
||||
- **后果**:修一处漏一处易出 bug;测试需双倍
|
||||
|
||||
### P2 — 中等优先级
|
||||
|
||||
#### P2-1:`ai-chart-renderer.tsx` 使用 `as` 断言
|
||||
|
||||
- **位置**:[ai-chart-renderer.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-chart-renderer.tsx#L122-L132)
|
||||
- **问题**:
|
||||
```ts
|
||||
data: obj.data as Array<Record<string, string | number>>, // as 断言
|
||||
series: obj.series as AiChartSeries[], // as 断言
|
||||
yDomain: Array.isArray(obj.yDomain) ? obj.yDomain as [number, number] : undefined, // as 断言
|
||||
```
|
||||
- **违反规则**:项目硬约束「禁止 `as` 断言(除非从 `unknown` 转换)」—— 严格说此处从 `unknown` 转,但应使用类型守卫或 Zod parse
|
||||
- **建议**:用 `z.array(AiChartSeriesSchema).parse(obj.series)` 校验
|
||||
|
||||
#### P2-2:`AiChatPanel` 单文件 417 行接近上限
|
||||
|
||||
- **位置**:[ai-chat-panel.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-chat-panel.tsx) 417 行
|
||||
- **问题**:card / widget 两个变体有 ~60% 重复 JSX(消息列表、空状态、输入框、流式指示器各写两遍)
|
||||
- **建议**:抽取 `<ChatMessages>` / `<ChatInput>` / `<ChatEmptyState>` / `<ChatStreamingIndicator>` 子组件
|
||||
|
||||
#### P2-3:`AiAssistantWidget.inferContextFromPath` 配置硬编码
|
||||
|
||||
- **位置**:[ai-assistant-widget.tsx](file:///e:/Desktop/CICD/src/modules/ai/components/ai-assistant-widget.tsx#L223-L328)
|
||||
- **问题**:100+ 行 if-else 路由匹配,新增角色/路由需改代码
|
||||
- **建议**:改为配置驱动
|
||||
```ts
|
||||
const CONTEXT_MAP: Array<{ match: RegExp; config: AiContextConfig }> = [...]
|
||||
```
|
||||
|
||||
#### P2-4:`content-safety.ts` 关键词仅英文
|
||||
|
||||
- **位置**:[content-safety.ts](file:///e:/Desktop/CICD/src/modules/ai/services/content-safety.ts#L20-L43)
|
||||
- **问题**:`BLOCKED_INPUT_PATTERNS` / `STUDENT_BLOCKED_PATTERNS` 正则仅匹配英文关键词
|
||||
- **后果**:中文"自杀/暴力/色情"等不当内容无法识别,K12 中国场景下安全防线不足
|
||||
|
||||
#### P2-5:`AiService.chat` 的 `usage` 字段始终返回 `null`
|
||||
|
||||
- **位置**:[ai-service.ts](file:///e:/Desktop/CICD/src/modules/ai/services/ai-service.ts#L177)
|
||||
- **问题**:`return { result: { content, usage: null }, tokenUsage }` —— `AiChatResult.usage: unknown` 类型但实际始终 null
|
||||
- **建议**:将 `tokenUsage` 包入 `usage` 字段,或修改类型为 `usage: null`
|
||||
|
||||
#### P2-6:架构图遗漏 `/admin/ai-settings` 路由
|
||||
|
||||
- **位置**:[005_architecture_data.json](file:///e:/Desktop/CICD/docs/architecture/005_architecture_data.json) `routes` 节点
|
||||
- **问题**:仅在 `ai.integrations.admin-dashboard.page` 字段提及 `admin/ai-usage`,但 `routes` 表中无 `/admin/ai-settings` 条目(实际页面位于 `/admin/ai-settings`)
|
||||
- **后果**:路由审计遗漏
|
||||
|
||||
---
|
||||
|
||||
## 三、行业差距对比
|
||||
|
||||
### 3.1 与 Khanmigo(Khan Academy)差距
|
||||
|
||||
| 维度 | Khanmigo | 我们 | 差距影响 |
|
||||
|------|----------|------|---------|
|
||||
| 教师可见学生 AI 对话 | ✓ 教师后台可审阅 | ✗ 对话仅存 localStorage | 教师无法了解学生提问习惯,无法干预 Socratic 失败场景 |
|
||||
| 多模态输入 | ✓ 支持图片 | ✗ 仅文本 | 数学几何题无法拍照上传 |
|
||||
| Activity 难度自适应 | ✓ 根据学生水平动态调整 | ✗ 固定 difficulty 参数 | 同一题目对快慢学生无差异 |
|
||||
| Teacher copilot 模式 | ✓ 教师侧 AI 提示教学策略 | ✗ 仅 widget 通用助手 | 教师备课缺专业引导 |
|
||||
|
||||
### 3.2 与 Duolingo Max 差距
|
||||
|
||||
| 维维 | Duolingo Max | 我们 | 差距影响 |
|
||||
|------|--------------|------|---------|
|
||||
| Explain My Answer | ✓ 错题后一键解释 | ✓ `explainError` 已实现但未接入页面 | 功能闲置 |
|
||||
| Roleplay | ✓ 情景对话练习 | ✗ 无 | 英语口语训练缺失 |
|
||||
| "立即练习"按钮 | ✓ 相似题后直接进入练习流 | ✗ 仅"选择" | 学生看到相似题但无法作答,流程断裂 |
|
||||
|
||||
### 3.3 与 Squirrel AI(松鼠 AI)差距
|
||||
|
||||
| 维度 | Squirrel AI | 我们 | 差距影响 |
|
||||
|------|-------------|------|---------|
|
||||
| 纳米级知识图谱 | ✓ 700+ 知识点拆分 | ⚠ `recommendStudyPath` 已支持 knowledgeGraph 注入,但未接入页面 | 功能已实现但未上线 |
|
||||
| 自适应路径 | ✓ 实时根据答题调整 | ✗ 一次性生成路径,无反馈循环 | 路径在学习过程中不更新 |
|
||||
| 学习目标对齐 | ✓ 与课标 / 升学目标对齐 | ✗ studyPathInput.learningGoal 仅文本 | 缺少课标映射 |
|
||||
|
||||
### 3.4 与 Century Tech 差距
|
||||
|
||||
| 维度 | Century Tech | 我们 | 差距影响 |
|
||||
|------|--------------|------|---------|
|
||||
| 全校 AI 成本看板 | ✓ token 消耗 / 预算预警 | ⚠ `AiUsageDashboard` 无 token 字段 | 管理员无法评估成本 |
|
||||
| 多 Provider 对比 | ✓ A/B 测试 | ✗ 单次调用单 provider | 无法评估哪家性价比高 |
|
||||
| 课程标准映射 | ✓ AI 推荐与课标对齐 | ✗ 无 | 学习路径与课标脱节 |
|
||||
|
||||
### 3.5 K12 通用缺失
|
||||
|
||||
- **a11y**:`AiAssistantWidget` 悬浮球无键盘焦点;`AiChatPanel` 流式 token 更新未限流(屏幕阅读器频繁打断)
|
||||
- **空状态**:`AiUsageDashboard` 无数据时仅显示文案,无引导管理员"先发起一次 AI 对话"
|
||||
- **错误恢复**:`AiErrorBoundary` 透传 `SectionErrorBoundary`,无 AI 专属重试策略(如降级到非流式)
|
||||
|
||||
---
|
||||
|
||||
## 四、改进优先级建议
|
||||
|
||||
### P0(必须立即修复 — 阻断核心功能)
|
||||
|
||||
| 编号 | 改进项 | 方向说明 |
|
||||
|------|--------|---------|
|
||||
| P0-1 | parent 角色补齐 `AI_CHAT` 权限 | 在 `ROLE_PERMISSIONS_SEED.parent` 数组追加 `Permissions.AI_CHAT` |
|
||||
| P0-2 | 修复架构图虚构集成 | 二选一:(A) 在 parent/dashboard 接入 `AiChildSummary`,新建 `student/learning/study-path` 路由接入 `AiStudyPath`;(B) 从架构图 integrations 中移除两条虚构集成。**本次采用方案 A**:实际接入组件,让功能上线 |
|
||||
| P0-3 | `getAiUsageStatsAction` 错误 i18n 修复 | 新增 `ai.error.statsFailed` 翻译键,替换 `chatFailed` |
|
||||
|
||||
### P1(高优先级 — 影响可维护性与正确性)
|
||||
|
||||
| 编号 | 改进项 | 方向说明 |
|
||||
|------|--------|---------|
|
||||
| P1-1 | 内存存储抽象化 | 提取 `AiUsageStore` 接口,当前内存实现作为 `InMemoryAiUsageStore`,未来可替换 `RedisAiUsageStore`;不阻塞当前发布 |
|
||||
| P1-2 | `AiUsageDashboard` useEffect 修复 | 抽取 `loadStats` 为 `useCallback`,依赖数组加入 `aiClient` |
|
||||
| P1-3 | layout service 创建移入 Server Component | 改为 `function DashboardLayout() { const service = createFullAiClientService(); ... }` |
|
||||
| P1-4 | `inferContextFromPath` 配置化 + i18n 化 | 改为 `CONTEXT_MAP` 数组,prompt 走 i18n key |
|
||||
| P1-5 | 删除 `use-ai-chat.ts` 死代码 | 文件 + 架构图 exports 同步移除 |
|
||||
| P1-6 | 删除 `ai-suggestion-card.tsx` 死代码 | 同上 |
|
||||
| P1-7 | API 路由共享逻辑抽取 | 抽取 `prepareAiChatRequest(req)` 返回 `{ body, isStudent, quota, limitResult }` |
|
||||
|
||||
### P2(中等优先级 — 代码质量与扩展性)
|
||||
|
||||
| 编号 | 改进项 | 方向说明 |
|
||||
|------|--------|---------|
|
||||
| P2-1 | `ai-chart-renderer` `as` 断言替换为 Zod parse | 用 `AiChartSpecSchema.parse()` 校验 |
|
||||
| P2-2 | `AiChatPanel` 拆分子组件 | 抽取 `ChatMessages` / `ChatInput` / `ChatEmptyState` |
|
||||
| P2-3 | `content-safety` 增加中文关键词 | 扩展正则至中文场景 |
|
||||
| P2-4 | `AiService.chat.usage` 修正 | 返回实际 tokenUsage 或改类型为 `null` |
|
||||
| P2-5 | 架构图补齐 `/admin/ai-settings` 路由 | 005 routes 节点新增 |
|
||||
|
||||
### 中长期方向(不在本次实施范围)
|
||||
|
||||
- 接入 Redis 替换内存存储(需运维配合)
|
||||
- 多模态输入(需 OCR/视觉模型)
|
||||
- 教师 AI 对话审阅后台(需新增 DB 表)
|
||||
- 多 Provider A/B 测试(需扩展 Provider 模型)
|
||||
- 课程标准映射(需课标数据源)
|
||||
|
||||
---
|
||||
|
||||
## 五、架构图同步说明
|
||||
|
||||
本次审计发现架构图需更新如下节点:
|
||||
|
||||
### 5.1 `005_architecture_data.json` 同步项
|
||||
|
||||
1. **`modules.ai.exports.hooks`** 移除 `useAiChat`(死代码已删除)
|
||||
2. **`modules.ai.exports.components`** 移除 `AiSuggestionCard`(死代码已删除)
|
||||
3. **`modules.ai.integrations.parent-dashboard`** 更新 `page` 字段为真实接入路径
|
||||
4. **`modules.ai.integrations.student-learning`** 更新 `page` 字段为真实接入路径 `student/learning/study-path`
|
||||
5. **`modules.ai.integrations.admin-dashboard`** 更正 `page` 为 `admin/ai-settings`(原误记为 `admin/ai-usage`)
|
||||
6. **`routes./admin/ai-settings`** 新增节点(若 routes 表中确实缺失)
|
||||
7. **`rolePermissionsSeed.parent`** 追加 `ai:chat` 权限
|
||||
8. **`modules.ai.i18n.v2Keys`** 追加 `error.statsFailed` 翻译键
|
||||
|
||||
### 5.2 `004_architecture_impact_map.md` 同步项
|
||||
|
||||
1. AI 模块章节的「集成点」表格更新实际接入路径
|
||||
2. 移除已删除组件的引用
|
||||
|
||||
---
|
||||
|
||||
## 六、本次实施清单
|
||||
|
||||
### 已实施(本次审计直接修复)
|
||||
|
||||
| 编号 | 类型 | 改动 |
|
||||
|------|------|------|
|
||||
| P0-1 | 代码 | `permissions.ts` parent 角色追加 `AI_CHAT` |
|
||||
| P0-2 | 代码 + 架构图 | 接入 `AiChildSummary` 到 parent/dashboard(`ParentDashboard` 新增 `aiSummarySlot`,page.tsx 为每个子女渲染 `AiChildSummary`);新建 `student/learning/study-path` 路由(page.tsx + loading.tsx + error.tsx)接入 `AiStudyPath`;同步 004/005 文档集成点与路由表 |
|
||||
| P0-3 | 代码 + i18n | `actions.ts` 修复错误键;`ai.json` (zh/en) 新增 `error.statsFailed` |
|
||||
| P1-2 | 代码 | `ai-usage-dashboard.tsx` 修复 useEffect |
|
||||
| P1-3 | 代码 | `layout.tsx` service 移入函数体 |
|
||||
| P1-5 | 代码 | 删除 `use-ai-chat.ts`;架构图 exports.hooks 移除 `useAiChat` |
|
||||
| P1-6 | 代码 | 删除 `ai-suggestion-card.tsx`;架构图 exports.components 移除 `AiSuggestionCard` |
|
||||
| P2-1 | 代码 | `ai-chart-renderer.tsx` 替换 `as` 为 Zod parse(新增 `AiChartSpecSchema`) |
|
||||
| P2-4 | 代码 | `ai-service.ts` 修正 `usage` 字段返回实际 tokenUsage |
|
||||
| 架构图 | 文档 | 004/005 同步上述改动;新增 `student.studyPath` i18n 块(zh/en) |
|
||||
| 权限 | 文档 | `005` 的 `rolePermissionsSeed.parent` 追加 `AI_CHAT` |
|
||||
| i18n | 文档 | `005` 的 `modules.ai.i18n.v2Keys` 追加 `error.statsFailed` |
|
||||
| 路由 | 文档 | `005` 的 `routes` 表新增 `/student/learning/study-path`;更新 `/parent/dashboard` 描述含 AI 摘要集成;`/admin/ai-settings` 校正为 admin 集成路径(原误记为 `admin/ai-usage`) |
|
||||
|
||||
### 未实施(中长期,需独立任务)
|
||||
|
||||
| 编号 | 原因 |
|
||||
|------|------|
|
||||
| P1-1 Redis 替换内存 | 需运维提供 Redis 实例 |
|
||||
| P1-4 prompt 完全 i18n 化 | 客户端 prompt 已被服务端覆盖,影响小 |
|
||||
| P1-7 API 路由共享逻辑抽取 | 涉及测试回归,单独 PR |
|
||||
| P2-2 AiChatPanel 拆分 | 涉及大量回归,单独 PR |
|
||||
| P2-3 中文关键词扩展 | 需安全策略评审 |
|
||||
Reference in New Issue
Block a user