feat(lesson-preparation): add AI evaluation, analytics, attachments, calendar, comments, review, substitutes, formative, and version diff
- Add actions-ai-evaluation, actions-analytics, actions-attachments, actions-calendar, actions-comments, actions-formative, actions-questions, actions-review, actions-substitutes - Add corresponding data-access layers for each new action module - Add calendar-view, curriculum-map-view, version-diff-viewer components - Add editor-slice, selection-slice, version-slice hooks for state management - Add document-diff and scope-check lib utilities - Add default-question-service and external-questions-bridge services
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
"use server";
|
||||
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard";
|
||||
import { requirePermission } from "@/shared/lib/auth-guard";
|
||||
import { handleActionError } from "@/shared/lib/action-utils";
|
||||
import { Permissions } from "@/shared/types/permissions";
|
||||
import { suggestKnowledgePoints } from "./ai-suggest";
|
||||
import { suggestKnowledgePointsSchema } from "./schema";
|
||||
import { translateFieldErrors } from "./lib/i18n-errors";
|
||||
import type { ActionState } from "@/shared/types/action-state";
|
||||
|
||||
export async function suggestKnowledgePointsAction(input: {
|
||||
@@ -16,11 +17,11 @@ export async function suggestKnowledgePointsAction(input: {
|
||||
suggestions: { id: string; name: string; reason: string }[];
|
||||
}>
|
||||
> {
|
||||
const t = await getTranslations("lessonPreparation");
|
||||
try {
|
||||
const parsed = suggestKnowledgePointsSchema.safeParse(input);
|
||||
if (!parsed.success) {
|
||||
return { success: false, errors: parsed.error.flatten().fieldErrors };
|
||||
const errors = await translateFieldErrors(parsed.error.flatten().fieldErrors);
|
||||
return { success: false, errors };
|
||||
}
|
||||
|
||||
// 并行校验两个权限点
|
||||
@@ -29,9 +30,10 @@ export async function suggestKnowledgePointsAction(input: {
|
||||
requirePermission(Permissions.AI_CHAT),
|
||||
]);
|
||||
|
||||
// 从 unknown 安全提取 nodes 数组:Zod 已校验 doc 是对象
|
||||
// P1 修复:从 unknown 安全提取 nodes 数组,显式类型标注替代隐式 any
|
||||
// Zod 已校验 doc 是 Record<string, unknown>,但 nodes 字段需运行时检查
|
||||
const doc = parsed.data.doc;
|
||||
const nodes = Array.isArray(doc.nodes) ? doc.nodes : [];
|
||||
const nodes: unknown[] = Array.isArray(doc.nodes) ? doc.nodes : [];
|
||||
const suggestions = await suggestKnowledgePoints(
|
||||
{ nodes },
|
||||
parsed.data.textbookId,
|
||||
@@ -39,8 +41,7 @@ export async function suggestKnowledgePointsAction(input: {
|
||||
);
|
||||
return { success: true, data: { suggestions } };
|
||||
} catch (e) {
|
||||
if (e instanceof PermissionDeniedError)
|
||||
return { success: false, message: e.message };
|
||||
return { success: false, message: t("error.aiSuggest") };
|
||||
// P1 修复:统一使用 handleActionError 处理错误,避免手动判断 PermissionDeniedError
|
||||
return handleActionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user