Files
cursor/plans/Plan-95f2e196.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

163 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 95f2e196-ce33-4253-ace0-0a2ba260a0c2 -->
---
todos:
- id: "finalize-article-schema"
content: "course_article 增加 content_json含 nameList/skipWords正文不再依赖 course_article_sentence"
status: pending
- id: "nce-import-command"
content: "NCE_*.json → course + course_article导入时写入 skipWords/nameList人名/地名免敲)"
status: pending
- id: "article-api"
content: "GET 课文 APIcontent_json 直出 TypeWords Article DTOnameList 供默写/听写跳过)"
status: pending
- id: "article-vocab-api"
content: "课文生词 APIcourse_article_vocab词头+ vocab_sense + course_word_sense与正文分离"
status: pending
- id: "content-patch-admin"
content: "低频勘误PATCH content_json 的 text/translate/skipWords或单课重导"
status: pending
isProject: false
---
# 课文内容存储方案建议(修订 v2
## 结论
- **课文正文**`course_article.content_json`(几乎不改,偶发勘误)
- **课文生词**:关系表(`course_article_vocab` + `course_word_sense`
- **人名/地名免敲**:写在 `content_json`**`skipWords`**API 层映射为 TypeWords 的 `nameList`
---
## 人名 / 地名:练习时不用敲
### 需求
默写或听写课文时,**人名、地名**应预先标注,练习流程 **自动跳过**,不要求学生输入(如 `Silbury``Pinhurst``James``Scott`)。
### TypeWords 已有能力(可直接复用)
[`TypingArticle.vue`](TypeWords/packages/core/src/components/article/TypingArticle.vue) 已支持 `article.nameList`
- 命中 `nameList` 的 token 在 `next()`**自动跳过**
- 内置跳过:`Mr` / `Mrs` / `Ms` / `Dr` / `Miss`
- 多词条目 `"James Scott"` 会拆成 `james``scott` 分别匹配
**不需要**在正文里加 `{Silbury}` 这类 inline 标记;**维护一份免敲词表**即可。
### 在 `content_json` 里怎么存
推荐 **两层字段**(存库清晰 + 对接 TypeWords 零改动):
```json
{
"title": "No wrong numbers",
"text": "Mr.James Scott has a garage in Silbury ...",
"textTranslate": "...",
"audioSrc": "/sound/article/nce2-1/No wrong numbers.mp3",
"lrcPosition": [[15.45, 24.87]],
"skipWords": [
{ "token": "James", "type": "person" },
{ "token": "Scott", "type": "person" },
{ "token": "Silbury", "type": "place" },
{ "token": "Pinhurst", "type": "place" }
]
}
```
| 字段 | 用途 |
|------|------|
| `skipWords[]` | collin **权威存储**`type`: `person` / `place`(可扩展 `org` |
| `nameList` | **API 输出** 时由 `skipWords[].token` 去重生成为 TypeWords 字段(可不落库重复存) |
Lesson5 示例映射:
```
skipWords → nameList: ["James", "Scott", "Silbury", "Pinhurst"]
Mr 已由 TypeWords 内置跳过)
```
### 练习端行为
```mermaid
flowchart LR
API["GET 课文 API"]
Map["skipWords → nameList"]
TW["TypeWords TypingArticle"]
Skip["isNameWord 自动 next"]
API --> Map --> TW --> Skip
```
- **默写 / 听写**:同一套 `nameList` 逻辑
- **UI 可选增强**(后续):按 `skipWords.type` 在课文预览里给人名/地名不同样式(不影响是否跳过)
### 导入时谁维护 skipWords
1. **人工标注**(推荐 MVP导入 NCE 时在源 JSON 或 Excel 补一列「免敲词」
2. **半自动**:导入脚本从 `text` 匹配已知的本课 `course_article_vocab` 之外的专名词表(准确度有限)
3. **勘误**:只改 `content_json.skipWords``content_version + 1`
**不要**单独建 `course_article_skip_token` 表 — 与「几乎不改」的 JSON 方案一致,免敲词随课文打包即可。
---
## 课文正文content_json不变
| 层级 | 存储 |
|------|------|
| 正文 | `course_article.content_json` |
| 元数据 | `course_article` 列:`lesson_no`, `title`, `audio_url`, `status` |
| 生词 | 关系表(一词一行 + 义项) |
| 词典 | `word` / `dict` |
`content_json` **不含** `newWords`**含** `skipWords`(人名/地名)。
完整示例:
```json
{
"title": "A private conversation",
"titleTranslate": "私人谈话",
"text": "...",
"textTranslate": "...",
"audioSrc": "...",
"lrcPosition": [],
"skipWords": [
{ "token": "theatre", "type": "place" }
],
"quote": null,
"question": null
}
```
---
## 与 TypeWords 字段对照
| TypeWords `Article` | collin 来源 |
|---------------------|-------------|
| `title`, `text`, `textTranslate`, `lrcPosition`, `audioSrc` | `content_json` |
| `nameList` | API 由 `skipWords[].token` 生成 |
| `sections` | 前端 `genArticleSectionData(text)` |
| 生词 | 独立 API不进 JSON |
---
## 对迁移 / API 的调整
1. `course_article.content_json` 文档化 **`skipWords`** 结构
2. `ArticleApiService`:读 JSON → 填充 `nameList` → 返回 TypeWords DTO
3. NCE 导入 Command支持从源文件 `nameList` 迁移,或从 sidecar 配置读 `skipWords`
4. 废弃 `course_article_sentence`(正文不再用句子表)
---
## 实施优先级
1. 定稿 `content_json` schema`skipWords`
2. NCE 导入 + 首批课文手工标注免敲词
3. GET 课文 API`skipWords``nameList`
4. 生词 API与正文分离
5. 勘误PATCH `text` / `translate` / `skipWords`