From 0a4f97d10521a8c8de44bf25b6e4663e15a5ac41 Mon Sep 17 00:00:00 2001 From: shenlei Date: Fri, 18 Sep 2026 17:55:44 +0900 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E4=B8=AA=E8=AF=BE=E7=A8=8B=E5=92=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AEUI=E9=87=8D=E6=96=B0=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Doc/COURSE-PACK-JSON.md | 63 +- Doc/learning-app-prototype.html | 181 +- kouyu_english/.gitignore | 3 + .../assets/config/ai_config.example.json | 8 + kouyu_english/assets/config/ai_config.json | 8 - kouyu_english/assets/courses/A0/a0-01.json | 342 +++ kouyu_english/assets/courses/A0/a0-02.json | 170 ++ kouyu_english/assets/courses/A0/a0-03.json | 266 +++ kouyu_english/assets/courses/A0/a0-04.json | 762 +++++++ kouyu_english/assets/courses/A0/a0-05.json | 284 +++ kouyu_english/assets/courses/A0/a0-06.json | 187 ++ kouyu_english/assets/courses/A0/a0-07.json | 305 +++ kouyu_english/assets/courses/A0/a0-08.json | 603 ++++++ kouyu_english/assets/courses/A0/a0-09.json | 373 ++++ kouyu_english/assets/courses/A0/a0-10.json | 207 ++ .../assets/courses/A0/assessment.json | 1612 ++++++++++++++ kouyu_english/assets/courses/A1/A1-U01.json | 3 +- kouyu_english/assets/courses/A1/A1-U02.json | 3 +- kouyu_english/assets/courses/A1/A1-U03.json | 3 +- kouyu_english/assets/courses/A1/A1-U04.json | 3 +- kouyu_english/assets/courses/A1/A1-U05.json | 3 +- kouyu_english/assets/courses/A1/A1-U06.json | 3 +- kouyu_english/assets/courses/A1/A1-U07.json | 3 +- kouyu_english/assets/courses/A1/A1-U08.json | 3 +- kouyu_english/assets/courses/A1/A1-U09.json | 3 +- kouyu_english/assets/courses/A1/A1-U10.json | 3 +- kouyu_english/assets/courses/A1/A1-U11.json | 3 +- kouyu_english/assets/courses/A1/A1-U12.json | 3 +- kouyu_english/assets/courses/A1/A1-U13.json | 3 +- kouyu_english/assets/courses/A1/A1-U14.json | 3 +- kouyu_english/assets/courses/A1/A1-U15.json | 3 +- kouyu_english/assets/courses/A1/A1-U16.json | 3 +- kouyu_english/assets/courses/A1/A1-U17.json | 3 +- kouyu_english/assets/courses/A1/A1-U18.json | 3 +- kouyu_english/assets/courses/A1/A1-U19.json | 3 +- kouyu_english/assets/courses/A1/A1-U20.json | 3 +- kouyu_english/assets/courses/A1/A1-U21.json | 3 +- kouyu_english/assets/courses/A2/A2-U01.json | 3 +- kouyu_english/assets/courses/A2/A2-U02.json | 3 +- kouyu_english/assets/courses/A2/A2-U03.json | 3 +- kouyu_english/assets/courses/A2/A2-U04.json | 3 +- kouyu_english/assets/courses/A2/A2-U05.json | 3 +- kouyu_english/assets/courses/A2/A2-U06.json | 3 +- kouyu_english/assets/courses/A2/A2-U07.json | 3 +- kouyu_english/assets/courses/A2/A2-U08.json | 3 +- kouyu_english/assets/courses/A2/A2-U09.json | 3 +- kouyu_english/assets/courses/A2/A2-U10.json | 3 +- kouyu_english/assets/courses/A2/A2-U11.json | 3 +- kouyu_english/assets/courses/A2/A2-U12.json | 3 +- kouyu_english/assets/courses/A2/A2-U13.json | 3 +- kouyu_english/assets/courses/A2/A2-U14.json | 3 +- kouyu_english/assets/courses/A2/A2-U15.json | 3 +- kouyu_english/assets/courses/B1/B1-U01.json | 3 +- kouyu_english/assets/courses/B1/B1-U02.json | 3 +- kouyu_english/assets/courses/B1/B1-U03.json | 3 +- kouyu_english/assets/courses/B1/B1-U04.json | 3 +- kouyu_english/assets/courses/B1/B1-U05.json | 3 +- kouyu_english/assets/courses/B1/B1-U06.json | 3 +- kouyu_english/assets/courses/B1/B1-U07.json | 3 +- kouyu_english/assets/courses/B1/B1-U08.json | 3 +- kouyu_english/assets/courses/B1/B1-U09.json | 3 +- kouyu_english/assets/courses/B1/B1-U10.json | 3 +- kouyu_english/assets/courses/B1/B1-U11.json | 3 +- kouyu_english/assets/courses/B1/B1-U12.json | 3 +- kouyu_english/assets/courses/B1/B1-U13.json | 3 +- kouyu_english/assets/courses/B1/B1-U14.json | 3 +- kouyu_english/assets/courses/course-map.json | 77 + kouyu_english/lib/core/a0_core.dart | 275 --- kouyu_english/lib/core/ai_config.dart | 9 +- kouyu_english/lib/core/ai_service.dart | 257 ++- kouyu_english/lib/core/app_state.dart | 16 +- .../lib/core/app_state_assessment.dart | 51 +- kouyu_english/lib/core/app_state_lesson.dart | 93 +- kouyu_english/lib/core/app_state_review.dart | 20 +- kouyu_english/lib/core/app_theme.dart | 5 +- kouyu_english/lib/core/assessment_bank.dart | 321 --- .../lib/core/courses/answer_matching.dart | 81 + .../lib/core/courses/answer_rules.dart | 174 ++ .../lib/core/courses/assessment.dart | 132 ++ .../lib/core/courses/core_items.dart | 132 ++ .../lib/core/courses/course_catalog.dart | 129 ++ .../lib/core/courses/course_models.dart | 177 ++ .../lib/core/courses/course_pack.dart | 480 +++++ .../lib/core/courses/course_repository.dart | 336 +++ kouyu_english/lib/core/courses/courses.dart | 11 + .../lib/core/courses/option_order.dart | 25 + kouyu_english/lib/core/generated_content.dart | 40 +- kouyu_english/lib/core/local_store.dart | 5 +- kouyu_english/lib/core/models.dart | 18 +- kouyu_english/lib/core/review_feedback.dart | 123 +- kouyu_english/lib/core/seed_courses.dart | 1865 ----------------- .../lib/core/sherpa_stt_service.dart | 94 +- .../lib/core/sync/sync_coordinator.dart | 3 +- kouyu_english/lib/core/sync/sync_merger.dart | 24 +- kouyu_english/lib/core/sync/sync_models.dart | 119 +- kouyu_english/lib/core/sync/sync_service.dart | 97 +- kouyu_english/lib/core/voice_service.dart | 24 +- kouyu_english/lib/core/writing_feedback.dart | 119 +- .../features/assessment/assessment_page.dart | 63 +- .../lib/features/dialogue/dialogue_flow.dart | 164 +- .../lib/features/home/home_page.dart | 223 +- .../lib/features/home/lesson_path.dart | 113 + .../lib/features/home/today_task_card.dart | 135 ++ .../lib/features/lesson/lesson_flow.dart | 24 +- .../lesson/steps/independent_step.dart | 121 +- .../features/lesson/steps/material_step.dart | 344 +++ .../features/lesson/steps/reading_step.dart | 19 +- .../features/lesson/steps/writing_step.dart | 6 +- .../features/onboarding/onboarding_pages.dart | 3 +- .../lib/features/profile/ai_service_page.dart | 171 ++ .../profile/assessment_list_page.dart | 75 + .../profile/learning_records_page.dart | 124 ++ .../features/profile/level_progress_page.dart | 72 + .../features/profile/preference_pages.dart | 112 + .../lib/features/profile/profile_page.dart | 317 +++ .../lib/features/profile/profile_widgets.dart | 296 +++ .../lib/features/profile/recordings_page.dart | 101 + .../sync_settings_sheet.dart | 49 +- .../lib/features/progress/progress_pages.dart | 744 ------- .../lib/features/review/review_page.dart | 388 +++- .../lib/features/shell/learning_shell.dart | 198 +- kouyu_english/lib/main.dart | 6 +- kouyu_english/lib/widgets/lexicon_lookup.dart | 109 +- kouyu_english/pubspec.yaml | 5 + .../test/ai_audio_transcribe_test.dart | 46 +- kouyu_english/test/ai_config_test.dart | 66 +- .../test/answer_confirmation_test.dart | 215 ++ kouyu_english/test/app_state_test.dart | 58 +- kouyu_english/test/course_content_test.dart | 47 +- .../test/course_repository_test.dart | 132 ++ .../test/course_self_consistency_test.dart | 87 + .../test/deepseek_thinking_test.dart | 28 +- .../test/dialogue_ai_check_test.dart | 127 ++ kouyu_english/test/dialogue_task_test.dart | 104 +- .../test/dialogue_translation_test.dart | 125 +- kouyu_english/test/flutter_test_config.dart | 11 + kouyu_english/test/input_feedback_test.dart | 160 ++ kouyu_english/test/lesson_options_test.dart | 18 +- kouyu_english/test/lexicon_lookup_test.dart | 15 +- kouyu_english/test/live_endpoint_test.dart | 53 +- kouyu_english/test/local_store_test.dart | 47 + kouyu_english/test/material_step_test.dart | 107 + .../test/navigation_back_button_test.dart | 133 +- kouyu_english/test/review_ai_check_test.dart | 166 ++ kouyu_english/test/review_feedback_test.dart | 16 +- .../test/sentence_analysis_test.dart | 115 +- kouyu_english/test/sherpa_stt_test.dart | 39 +- kouyu_english/test/support/app_assets.dart | 18 + kouyu_english/test/sync_test.dart | 138 +- kouyu_english/test/unlock_chain_test.dart | 122 ++ kouyu_english/test/widget_test.dart | 7 +- kouyu_english/test/writing_feedback_test.dart | 27 +- .../tool/courses/course_validator.dart | 39 +- kouyu_english/tool/courses/validate.dart | 46 +- 154 files changed, 12366 insertions(+), 4784 deletions(-) create mode 100644 kouyu_english/assets/config/ai_config.example.json delete mode 100644 kouyu_english/assets/config/ai_config.json create mode 100644 kouyu_english/assets/courses/A0/a0-01.json create mode 100644 kouyu_english/assets/courses/A0/a0-02.json create mode 100644 kouyu_english/assets/courses/A0/a0-03.json create mode 100644 kouyu_english/assets/courses/A0/a0-04.json create mode 100644 kouyu_english/assets/courses/A0/a0-05.json create mode 100644 kouyu_english/assets/courses/A0/a0-06.json create mode 100644 kouyu_english/assets/courses/A0/a0-07.json create mode 100644 kouyu_english/assets/courses/A0/a0-08.json create mode 100644 kouyu_english/assets/courses/A0/a0-09.json create mode 100644 kouyu_english/assets/courses/A0/a0-10.json create mode 100644 kouyu_english/assets/courses/A0/assessment.json delete mode 100644 kouyu_english/lib/core/a0_core.dart delete mode 100644 kouyu_english/lib/core/assessment_bank.dart create mode 100644 kouyu_english/lib/core/courses/answer_matching.dart create mode 100644 kouyu_english/lib/core/courses/answer_rules.dart create mode 100644 kouyu_english/lib/core/courses/assessment.dart create mode 100644 kouyu_english/lib/core/courses/core_items.dart create mode 100644 kouyu_english/lib/core/courses/course_catalog.dart create mode 100644 kouyu_english/lib/core/courses/course_models.dart create mode 100644 kouyu_english/lib/core/courses/course_pack.dart create mode 100644 kouyu_english/lib/core/courses/course_repository.dart create mode 100644 kouyu_english/lib/core/courses/courses.dart create mode 100644 kouyu_english/lib/core/courses/option_order.dart delete mode 100644 kouyu_english/lib/core/seed_courses.dart create mode 100644 kouyu_english/lib/features/home/lesson_path.dart create mode 100644 kouyu_english/lib/features/home/today_task_card.dart create mode 100644 kouyu_english/lib/features/lesson/steps/material_step.dart create mode 100644 kouyu_english/lib/features/profile/ai_service_page.dart create mode 100644 kouyu_english/lib/features/profile/assessment_list_page.dart create mode 100644 kouyu_english/lib/features/profile/learning_records_page.dart create mode 100644 kouyu_english/lib/features/profile/level_progress_page.dart create mode 100644 kouyu_english/lib/features/profile/preference_pages.dart create mode 100644 kouyu_english/lib/features/profile/profile_page.dart create mode 100644 kouyu_english/lib/features/profile/profile_widgets.dart create mode 100644 kouyu_english/lib/features/profile/recordings_page.dart rename kouyu_english/lib/features/{progress => profile}/sync_settings_sheet.dart (91%) delete mode 100644 kouyu_english/lib/features/progress/progress_pages.dart create mode 100644 kouyu_english/test/answer_confirmation_test.dart create mode 100644 kouyu_english/test/course_repository_test.dart create mode 100644 kouyu_english/test/course_self_consistency_test.dart create mode 100644 kouyu_english/test/dialogue_ai_check_test.dart create mode 100644 kouyu_english/test/flutter_test_config.dart create mode 100644 kouyu_english/test/input_feedback_test.dart create mode 100644 kouyu_english/test/material_step_test.dart create mode 100644 kouyu_english/test/review_ai_check_test.dart create mode 100644 kouyu_english/test/support/app_assets.dart create mode 100644 kouyu_english/test/unlock_chain_test.dart diff --git a/Doc/COURSE-PACK-JSON.md b/Doc/COURSE-PACK-JSON.md index 7a766e2..ad5f0f0 100644 --- a/Doc/COURSE-PACK-JSON.md +++ b/Doc/COURSE-PACK-JSON.md @@ -1,6 +1,6 @@ # 课程内容包 JSON 格式 -> 对应《学习引擎规格》第 5 节。本文说明 A1–B1 单元内容包的文件位置、字段和程序校验规则。A0 仍按《A0 初始核心课程包》,不在此格式内。 +> 对应《学习引擎规格》第 5 节。本文说明 A0–B1 单元内容包的文件位置、字段和程序校验规则。所有等级共用这一套结构,由 `CourseRepository` 用同一套规则转换成学习和复习数据;A0 的内容标准仍以《A0 初始核心课程包》为准(见 4.10)。 ## 1. 文件与工具 @@ -8,6 +8,7 @@ |---|---| | `kouyu_english/assets/courses/course-map.json` | 主题地图:等级、单元顺序、每级的数量范围、名称白名单 | | `kouyu_english/assets/courses/<等级>/<单元ID>.json` | 单元内容包,一个单元一个文件 | +| `kouyu_english/assets/courses/A0/assessment.json` | A0 阶段测评题(见 4.11) | | `kouyu_english/tool/courses/lexicon/` | 锁定的 CEFR-J 数据与 `SOURCES.md` | | `kouyu_english/tool/courses/pools/` | 等级词池(`build_word_pools.py` 生成) | | `kouyu_english/tool/courses/validate.dart` | 校验全部内容包,报告词池覆盖率 | @@ -20,17 +21,18 @@ dart run tool/courses/validate.dart --uncovered B1 # 按主题列出未覆盖 dart run tool/courses/validate.dart --levels B1-U14 # 打印条目的计算等级 ``` -内容包目前只是资源文件,尚未加入 `pubspec.yaml`,运行时也还不读取。 +运行时由 `lib/core/courses/course_repository.dart` 读取:`main` 启动前先加载 A0,`AppState.load` 再加载其余等级。学习(教学段、对话、写作、独立表达)和复习(产出核心的 `match` 与 `review`)都只读这些 JSON,代码里不再写死课程数据。`test/course_self_consistency_test.dart` 要求每个示范答案都能通过它自己的判定规则。 -## 2. 当前内容(2026-09-17,全部为 `draft`) +## 2. 当前内容(2026-09-18,A1–B1 为 `draft`) | 等级 | 单元 | 产出核心 | 理解词 | 听读材料 | 词池覆盖 | |---|---|---|---|---|---| +| A0 | 10 | 见 A0 标准 | — | — | —(`approved`,不参与词池校验) | | A1 | 21 | 265 | 598 | 42 | 840/933(90.0%) | | A2 | 15 | 217 | 862 | 44 | 1040/1078(96.5%) | | B1 | 14 | 206 | 1121 | 42 | 1345/1552(86.7%) | -全部由 AI 起草、程序校验通过,尚未经过独立审核和用户确认,不能冻结。 +A1–B1 全部由 AI 起草、程序校验通过,尚未经过独立审核和用户确认,不能冻结。 ## 3. course-map.json @@ -48,6 +50,7 @@ dart run tool/courses/validate.dart --levels B1-U14 # 打印条目的计算等 "coreRange": [10, 15], "receptiveRange": [70, 110], "materials": {"count": [2, 3], "listeningWords": [250, 550], "readingWords": [300, 500]}, + "assessment": "A0/assessment.json", // 可选:本级阶段测评题,目前只有 A0 有 // A1 的材料较短,且可选 "unknownTolerance"(默认 0.02)放宽超纲词占比 "units": [{"id": "B1-U01", "file": "B1/B1-U01.json", "title": "…", "categories": ["旅行"], "canDo": "…"}] }] @@ -202,6 +205,58 @@ A1 材料短、面向零基础,`unknownTolerance` 设为 0.08(听读材料 至少 2 个维度,每维至少 3 档;`pass` 是及格档在 `bands` 中的下标(从 0 起),须大于 0。 +### 4.9 可选字段:显式规则优先 + +以下字段都可省略;省略时由 `itemIds` 引用的产出核心推导(`match` 合并成一组“或”,示范取 `en`),写了就以写的为准。规则写法见 `lib/core/courses/answer_rules.dart`:外层“且”、内层“或”,内层首项可写 `#min:N` 表示至少用上 N 项;词条可写 `a + b`、`/正则/`,以及 `#spelling`、`#digit`、`#word`、`#question`、`#numbers:N`、`#words:N` 这些结构。 + +| 位置 | 字段 | 作用 | 省略时 | +|---|---|---|---| +| 单元 | `status` | `approved` / `draft` 等 | `draft` | +| 单元 | `vocabulary` | 整课词表(离线查词) | 产出核心 + 理解词 | +| 教学段 | `grammarNote` | 本段语法提示 | 不显示 | +| 教学段 | `vocabulary` | 预习词表 `[{id, word, meaning, example, exampleMeaning}]` | 本段产出核心 | +| 教学段 | `sceneId` | 本段对话用的场景 | 第 N 段用第 N 个场景,没有则用 main 场景 | +| 教学段 | `writing.accept` / `writing.hint` | 写作判定规则 / 未通过时的提示 | 由 `writing.itemIds` 推导 | +| 教学段 | `independent.accept` / `independent.help` | 独立表达的完整规则 / 帮助 | 由 `independent.itemIds` 推导;为空则任何真实尝试都算 | +| 场景 | `goal` | 对话目标 | `setting`,再没有则 `title` | +| 场景 | `practice` | 同时作为自由练习场景:`{title, summary, recapPrompt, alwaysOpen}`,都可省略;写 `{}` 即可 | 不进入自由练习 | +| 轮次 | `aiZh` | `ai` 这句的中文(`zh` 是示范回答的中文) | 不提供翻译 | +| 轮次 | `accept` | 本轮判定用的一组“或” | 由本轮 `itemIds` 推导 | + +自由练习场景在其所属单元完成后解锁,`alwaysOpen: true` 则一开始就开放。 + +### 4.10 A0 单元 + +A0 用同一结构,文件为 `A0/a0-01.json` … `a0-10.json`,在 `course-map.json` 中排在最前。为兼容已保存的学习进度,A0 保留原有 ID:单元 `a0-01`,教学段 `a0-01-a`(拆段课为 `a0-04-a/b/c`、`a0-08-a/b/c`),产出核心 `A0-W01` / `A0-P01`。A0 的规则、提示和对话都用上面的显式字段写明;`validate.dart` 只把 A0 的产出核心和听写句当作“已教的词”,不按 A1–B1 的数量范围和词池校验 A0。 + +### 4.11 阶段测评(assessment.json) + +等级在 `course-map.json` 里写了 `assessment`,就由 `CourseRepository` 加载对应文件,运行时代码在 `lib/core/courses/assessment.dart`。目前只有 A0 的 `A0/assessment.json`: + +```jsonc +{ + "schemaVersion": 1, + "packs": [ + {"id": "A0-E1", "level": "A0", "tasks": [ + {"id": "A0-A-L1", "skill": "listening", "prompt": "选择正确答案", + "audio": "Hello. I’m Mia.", "choices": ["自我介绍", "买东西", "问时间"], "answerIndex": 0}, + {"id": "A0-A-W1", "skill": "writing", "prompt": "用英语介绍自己。", + "accept": [["hello", "hi"], ["i am", "my name is"]], + "guide": "试着同时写一句问候和姓名,例如:Hello. I’m …"} + ]}, + {"id": "A0-E1R", "level": "A0", "replaces": "A0-E1", "tasks": […]} + ] +} +``` + +- `skill` 取 `listening` / `reading` / `writing` / `speaking`。听力、阅读是选择题,写 `choices` 和 `answerIndex`(从 0 开始);听力另写 `audio`。 +- 写作、口语是开放题,`accept` 用 4.9 的规则写法,`guide` 是答错后展示的要求。 +- 没有 `replaces` 的套题按文件顺序解锁:第一套直接开放,之后每套要在上一套通过 24 小时后才开放。 +- 有 `replaces` 的是替换题,用不同的人名、地点、数字考同样的能力,成绩记在原题 ID 上。 +- 题目和套题 ID 写进学习记录,发布后不要改。 + +`test/course_self_consistency_test.dart` 检查:每道开放题都有 `accept` 和 `guide`,每道选择题的 `answerIndex` 有效,`replaces` 指向存在的套题。 + ## 5. 文本用词检查 “已知词”包括:`alwaysAllowedWords`、功能词、A0 已教的词、推荐顺序在前的单元的产出核心和理解词、本单元的产出核心和理解词(均按词形还原),以及全局与本单元的 `names`。数字不计。 diff --git a/Doc/learning-app-prototype.html b/Doc/learning-app-prototype.html index 1a039d9..832d41b 100644 --- a/Doc/learning-app-prototype.html +++ b/Doc/learning-app-prototype.html @@ -24,6 +24,7 @@ #learning-app-prototype .screen-list { display:flex; flex-direction:column; gap:3px; margin-top:15px; } #learning-app-prototype .screen-link { text-align:left; border:0; border-radius:10px; color:var(--ka-ink); background:transparent; padding:9px 10px; font-size:13px; } #learning-app-prototype .screen-link[aria-pressed="true"] { background:var(--ka-soft-green); color:var(--ka-green); font-weight:500; } + #learning-app-prototype .screen-link.sub { padding-left:22px; font-size:12px; } #learning-app-prototype .legend-title { font-size:13px; font-weight:500; margin:0 0 10px; } #learning-app-prototype .flow { display:flex; flex-direction:column; gap:8px; } #learning-app-prototype .flow-row { border-left:2px solid var(--ka-line); padding:3px 0 3px 9px; font-size:12px; line-height:1.35; } @@ -115,6 +116,62 @@ #learning-app-prototype .mac-main h1 { font-size:23px; } #learning-app-prototype .mac-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:16px; } #learning-app-prototype .mac-grid .slot { margin:0; min-height:104px; } + #learning-app-prototype .me-card { background:var(--ka-surface); border:1px solid var(--ka-line); border-radius:18px; padding:14px; } + #learning-app-prototype .me-head { display:flex; align-items:center; gap:12px; } + #learning-app-prototype .avatar { width:48px; height:48px; border-radius:50%; display:grid; place-items:center; background:var(--ka-soft-green); color:var(--ka-green); font-size:19px; font-weight:500; } + #learning-app-prototype .me-name { font-size:17px; font-weight:500; } + #learning-app-prototype .level-badge { display:inline-block; margin-left:6px; padding:2px 7px; border-radius:999px; background:var(--ka-soft-green); color:var(--ka-green); font-size:11px; vertical-align:2px; } + #learning-app-prototype .stats { display:grid; grid-template-columns:repeat(4,1fr); margin-top:13px; padding-top:12px; border-top:1px solid var(--ka-line); } + #learning-app-prototype .stat { border:0; background:transparent; color:var(--ka-ink); text-align:center; padding:0; } + #learning-app-prototype .stat b { display:block; font-size:19px; font-weight:500; } + #learning-app-prototype .stat span { color:var(--ka-muted); font-size:11px; } + #learning-app-prototype .stat.due b { color:var(--ka-warm-ink); } + #learning-app-prototype .goal-card { width:100%; display:block; text-align:left; border:0; border-radius:16px; padding:13px 14px; margin-top:11px; background:var(--ka-soft-green); color:var(--ka-ink); } + #learning-app-prototype .goal-card .meter { margin:9px 0 8px; background:light-dark(#c9e4d3, #2a4a37); } + #learning-app-prototype .group-title { color:var(--ka-muted); font-size:12px; margin:17px 4px 6px; } + #learning-app-prototype .menu { background:var(--ka-surface); border:1px solid var(--ka-line); border-radius:15px; overflow:hidden; } + #learning-app-prototype .menu-row { width:100%; display:flex; align-items:center; gap:11px; border:0; border-bottom:1px solid var(--ka-line); background:transparent; color:var(--ka-ink); padding:11px 12px; text-align:left; font-size:14px; } + #learning-app-prototype .menu-row:last-child { border-bottom:0; } + #learning-app-prototype .menu-row .ico { width:28px; height:28px; flex:none; display:grid; place-items:center; border-radius:8px; background:var(--ka-surface-2); font-size:14px; } + #learning-app-prototype .menu-row .label { flex:1; } + #learning-app-prototype .menu-row .label small { display:block; color:var(--ka-muted); font-size:11px; margin-top:1px; } + #learning-app-prototype .menu-row .val { color:var(--ka-muted); font-size:12px; } + #learning-app-prototype .menu-row .chev { color:var(--ka-muted); font-size:16px; } + #learning-app-prototype .menu-row.danger { color:light-dark(#b3261e, #ffb4ab); justify-content:center; } + #learning-app-prototype .version { text-align:center; color:var(--ka-muted); font-size:11px; margin:12px 0 0; } + #learning-app-prototype .scroll { height:593px; overflow-y:auto; } + #learning-app-prototype .ability { padding:11px 0; border-bottom:1px solid var(--ka-line); } + #learning-app-prototype .ability:last-child { border-bottom:0; } + #learning-app-prototype .ability .meter { margin:7px 0 0; } + #learning-app-prototype details { margin-top:11px; padding:11px 12px; background:var(--ka-surface); border:1px solid var(--ka-line); border-radius:15px; font-size:13px; } + #learning-app-prototype details p { color:var(--ka-muted); font-size:12px; line-height:1.55; margin:8px 0 0; } + #learning-app-prototype .tag { display:inline-block; padding:2px 7px; border-radius:999px; font-size:11px; font-weight:400; background:var(--ka-surface-2); color:var(--ka-muted); } + #learning-app-prototype .tag.ok { background:var(--ka-soft-green); color:var(--ka-green); } + #learning-app-prototype .tag.help { background:var(--ka-warm); color:var(--ka-warm-ink); } + #learning-app-prototype .day { color:var(--ka-muted); font-size:12px; margin:14px 4px 6px; } + #learning-app-prototype .field { padding:10px 12px; border-bottom:1px solid var(--ka-line); font-size:13px; } + #learning-app-prototype .field span { display:block; color:var(--ka-muted); font-size:11px; margin-bottom:3px; } + #learning-app-prototype .segmented { display:flex; padding:3px; border-radius:12px; background:var(--ka-surface-2); margin-top:9px; } + #learning-app-prototype .segmented button { flex:1; border:0; border-radius:9px; padding:8px 0; background:transparent; color:var(--ka-muted); font-size:13px; } + #learning-app-prototype .segmented button.on { background:var(--ka-surface); color:var(--ka-ink); font-weight:500; box-shadow:0 1px 3px rgba(0,0,0,.12); } + #learning-app-prototype .row2 { display:flex; gap:8px; } #learning-app-prototype .row2 > * { flex:1; } + #learning-app-prototype .state-switch { display:flex; flex-wrap:wrap; align-items:center; gap:5px; margin:10px 0 2px; padding:7px 8px; border:1px dashed var(--ka-line); border-radius:11px; font-size:11px; color:var(--ka-muted); } + #learning-app-prototype .state-switch button { border:1px solid var(--ka-line); border-radius:999px; padding:3px 8px; background:var(--ka-surface); color:var(--ka-muted); font-size:11px; } + #learning-app-prototype .state-switch button.on { border-color:var(--ka-green); color:var(--ka-green); } + #learning-app-prototype .slot[hidden] { display:none; } + #learning-app-prototype .path-head { display:flex; justify-content:space-between; align-items:baseline; margin-top:20px; font-size:15px; } + #learning-app-prototype .path-head b { font-weight:500; } + #learning-app-prototype .path { margin-top:8px; background:var(--ka-surface); border:1px solid var(--ka-line); border-radius:15px; overflow:hidden; } + #learning-app-prototype .lesson-row { display:flex; align-items:center; gap:11px; padding:11px 12px; border-bottom:1px solid var(--ka-line); } + #learning-app-prototype .lesson-row:last-child { border-bottom:0; } + #learning-app-prototype .lesson-row .label { flex:1; } + #learning-app-prototype .lesson-row b { display:block; font-size:14px; font-weight:500; } + #learning-app-prototype .lesson-row small { color:var(--ka-muted); font-size:11px; } + #learning-app-prototype .lesson-ico { width:26px; height:26px; flex:none; display:grid; place-items:center; border-radius:50%; font-style:normal; font-size:12px; background:var(--ka-surface-2); color:var(--ka-muted); } + #learning-app-prototype .lesson-row.done .lesson-ico { background:var(--ka-green); color:var(--ka-green-ink); } + #learning-app-prototype .lesson-row.current { background:var(--ka-soft-green); } + #learning-app-prototype .lesson-row.current .lesson-ico { background:var(--ka-green); color:var(--ka-green-ink); } + #learning-app-prototype .lesson-row.locked b { color:var(--ka-muted); } @media (max-width: 880px) { #learning-app-prototype .studio { grid-template-columns:180px minmax(300px, 1fr); } #learning-app-prototype .flow-panel { display:none; } } @media (max-width: 590px) { #learning-app-prototype .studio { display:block; } #learning-app-prototype .panel { margin-bottom:15px; } #learning-app-prototype .screen-list { display:grid; grid-template-columns:1fr 1fr; } #learning-app-prototype .phone { width:100%; max-width:352px; } #learning-app-prototype .phone.mac { width:100%; max-width:430px; } } @@ -125,8 +182,7 @@
- - + @@ -135,8 +191,15 @@ - - + + + + + + + + + @@ -167,23 +230,25 @@
9:41● ● ●
-
-
早上好,Shen

今天,说 3 句英语。

第 1 课已完成。今天把姓名介绍说得更自然。

-

A0 起步 · 已完成 3 个核心任务

-
第 2 课 · 拼读姓名12 分钟
先认识 4 个词 · 听 · 说 · 读 · 写
-
快速练习 · 初次见面
3 分钟 AI 对话 · 介绍姓名与来自哪里
+
+
早上好,Shen

今天,说几句能用的英语。

+
原型状态:
+
今天先复习 3 项6 分钟
昨天练过的关键句,今天换个情境再用一次。复习完再上新课。
+ + +
A0 课程2 / 8 完成
+
+
+
第 1 课 · 你好,我是……介绍姓名并回应问候
+
第 2 课 · 拼读姓名听懂拼写,说出名字字母
+
第 3 课 · 来自哪里说出来自哪里 · 小段 1/3
+
🔒
第 4 课 · 数字与电话号码说 0–10 与简单号码
+
🔒
第 5 课 · 你好吗?问候并表达简单状态
+
🔒
…… 第 8 课A0 课程结束后进入巩固与阶段评估
+
+

已完成的课可以随时点开重练;有复习积压时,新课会暂时锁住。

- -
-
- +