feat(ai): V2 深度增强 — SSE 流式/全局助手/内容安全/多角色覆盖

对标 Khanmigo/Duolingo Max/Squirrel AI/Century Tech 实现:

- SSE 流式响应:createAiChatCompletionStream AsyncGenerator + /api/ai/chat/stream SSE 端点 + useAiChatStream hook(AbortController 停止生成 + localStorage 持久化)

- Markdown 渲染:AiMarkdownRenderer(react-markdown + remark-gfm + 代码块/表格/列表 + hover 复制按钮)

- 全局 AI 助手:AiAssistantWidget 浮动按钮 + Sheet 侧抽屉 + usePathname 路由推断上下文(7 类场景系统提示)+ dashboard layout 全局注入 AiClientProvider

- 内容安全:content-safety.ts 多层过滤(输入/输出安全过滤 + 每日限制 student 50/teacher 200/parent 30/admin 500 + 学生苏格拉底模式),COPPA/FERPA K12 合规

- 多角色 AI 覆盖:家长端 AiChildSummary(学情摘要)+ 管理员端 AiUsageDashboard(使用监控)+ 学生端 AiStudyPath(个性化学习路径)

- i18n 修复:8 处错误键引用 + zh-CN/en ai.json 全面扩展

- 架构文档 004/005 同步更新
This commit is contained in:
SpecialX
2026-06-23 01:34:37 +08:00
parent a60105455e
commit 4da9194a5e
27 changed files with 3522 additions and 172 deletions

View File

@@ -132,3 +132,74 @@ export const WeaknessAnalysisResultSchema = z.object({
studyPlan: z.string().min(1),
recommendedResources: z.array(z.string()),
})
// ---------------------------------------------------------------------------
// 家长学情摘要校验
// ---------------------------------------------------------------------------
export const ChildSummaryInputSchema = z.object({
studentId: z.string().min(1),
studentName: z.string().optional(),
grade: z.string().optional(),
recentGrades: z
.array(
z.object({
subject: z.string().min(1),
score: z.number(),
maxScore: z.number(),
trend: z.enum(["up", "down", "stable"]),
})
)
.optional(),
attendanceRate: z.number().min(0).max(1).optional(),
errorBookSummary: z
.object({
totalErrors: z.number().int().min(0),
topWeakSubjects: z.array(z.string()),
masteryTrend: z.enum(["improving", "declining", "stable"]),
})
.optional(),
homeworkCompletionRate: z.number().min(0).max(1).optional(),
})
export const ChildSummaryResultSchema = z.object({
overallAssessment: z.string().min(1),
strengths: z.array(z.string()),
areasForImprovement: z.array(z.string()),
familyTutoringSuggestions: z.array(z.string()),
nextSteps: z.array(z.string()),
})
// ---------------------------------------------------------------------------
// 学习路径推荐校验
// ---------------------------------------------------------------------------
export const StudyPathInputSchema = z.object({
studentId: z.string().min(1),
subject: z.string().optional(),
currentMastery: z
.array(
z.object({
knowledgePoint: z.string().min(1),
masteryLevel: z.number().min(0).max(5),
errorCount: z.number().int().min(0),
})
)
.optional(),
learningGoal: z.string().optional(),
})
export const StudyPathResultSchema = z.object({
currentLevel: z.string().min(1),
learningPath: z.array(
z.object({
step: z.number().int().min(1),
knowledgePoint: z.string().min(1),
status: z.enum(["mastered", "in_progress", "needs_work"]),
recommendedAction: z.string().min(1),
estimatedTime: z.string().min(1),
})
),
summary: z.string().min(1),
motivation: z.string().min(1),
})