# 内容导入契约 更新时间:2026-06-21 ## 结论 内容导入的最终规范化、校验、租户隔离、幂等和审计必须由后端负责。 前端只负责: - 上传或粘贴 JSON/Excel/CSV。 - 做轻量格式预检查,减少明显错误。 - 展示后端 preview 返回的 `job/items/issues`。 - 让运营人员修正数据后再确认导入。 迁移脚本只负责: - 从 PocketBase 导出或旧 JSON 中抽取数据。 - 转换成新架构推荐格式。 - 调用后端 preview/import API。 不建议迁移脚本直接绕过后端写业务表,除非是一次性内控迁移,并且必须额外跑导入后校验。 ## 已实现导入 API ```text POST /api/tenant-content/imports/preview/questions POST /api/tenant-content/imports/questions POST /api/tenant-content/imports/preview/vocabulary POST /api/tenant-content/imports/vocabulary POST /api/tenant-content/imports/preview/handbook POST /api/tenant-content/imports/handbook GET /api/tenant-content/imports GET /api/tenant-content/imports/issues ``` 所有导入都会写入: - `content_import_jobs` - `content_import_items` - `content_import_issues` - `audit_logs` ## 单词导入 推荐新格式: ```json { "regionId": "uuid", "entryId": "uuid", "contentNodeId": "uuid", "units": [ { "legacyId": "unit-1", "name": "Unit 1 - 高频核心词", "description": "专升本考试高频词汇", "order": 1, "words": [ { "legacyId": "word-abandon", "word": "abandon", "phonetic": "/əˈbændən/", "meaning": "v. 放弃,抛弃", "example": "He had to abandon his car in the snow.", "exampleTranslation": "他不得不把车丢弃在雪地里。", "difficulty": 3, "tags": ["高频词"], "order": 1 } ] } ] } ``` 兼容旧模板: - `vocabulary_units_示例数据` - `vocabulary_示例数据` 后端会把旧模板归一化为 `vocabulary_units/vocabulary_words`,并可自动挂到 `content_entries/content_nodes`。 ## 知识手册导入 推荐新格式: ```json { "regionId": "uuid", "entryId": "uuid", "contentNodeId": "uuid", "subjects": [ { "legacyId": "handbook-chinese", "name": "大学语文", "type": "guide", "chapters": [ { "legacyId": "chapter-outline", "name": "一、语文考纲", "sections": [ { "legacyId": "section-outline", "name": "考纲解读", "entries": [ { "legacyId": "entry-outline", "title": "2024年天津专升本语文考试大纲", "summary": "全面解读语文考试要求", "content": "Markdown 内容", "tags": ["考纲"] } ] } ] } ] } ] } ``` 映射规则: - 手册入口:`content_entries.entry_type = handbook` - 书籍/科目:`handbook_subjects`,并生成或绑定一个 `content_nodes` - 章节:`handbook_chapters`,并生成章节节点 - 小节:默认进入 `content_nodes`,作为知识点的目录节点 - 知识点:`handbook_entries`,通过 `content_node_id` 归属到小节或章节 ## 题目导入 题目继续兼容旧题库 JSON 数组格式,并支持 Markdown、KaTeX、图片、表格、阅读理解子题等字段。导入时可以传: - `subjectId` - `categoryId` - `entryId` - `contentNodeId` - `collectionId` 这样题目会同时落到旧兼容表和新内容导航/题目集合。 ## 幂等规则 - 优先使用 `legacyId` 作为跨迁移稳定标识。 - 没有 `legacyId` 时,后端按导入 job 和行号生成内部标识。 - 相同 `legacyId` 再导入会更新。 - 内容 hash 未变化时标记为 `skipped`。 ## 下一步 - 增加 Excel/CSV 解析入口,但解析后仍进入同一套 preview/import 管线。 - 增加分数线、视频导入。 - 增加异步 worker,处理大批量导入、重试和导入后校验。