主题
三端表/列全量重命名 — 最终改名清单(供核对)
状态:✅ 三端全部完成(RB + Supabase 2026-07 上旬;RVH 2026-07-09 schema v56,07-10 verified)。 执行清单见同目录
table-rename-rvh-handoff.md。 按本文件原定的「RVH 收尾后一并归档」,2026-08-29(rvh-merge-plan T4-7)归档 —— 迟了七周, 因为两份文件的状态行都没人回填(详见那份 handoff 顶部的说明)。
Context
开发阶段、未上线、无兼容负担。目标:让三端(RB 桌面 / RVH 移动 / Supabase)数据库命名语义更准确、 彻底消除 notebook_entries↔reading_notes 的 "note" 撞车与"排除词"偏负面命名,且表/列/代码标识符/注释/ i18n 三端统一,不留坑。本文件是执行前供用户核对的主清单;实际改动分端执行(RVH 必在专门会话)。
已锁定决策(用户确认)
- i18n 语义翻转:
excluded/排除→known/已认识,用户可见文案全部改写,并统一到 Triage 已用的"认识/Known"术语。 - "生词本/Notebook" 品牌词保留:表/代码/变量改
learning_entries,但用户可见文案保留"生词本/Notebook"(不译成"学习条目")。 - 全量标识符跟改:Tauri 命令名、类型、变量、invoke 参数名、文件名、索引名、RVH feature 目录名,全部跟改;FE+Rust 同 commit。
- 系统停用词表名 =
default_stopwords(已定)。 - 停用词改纯本地预装(已定):停用词静态 → 砍掉 Supabase 单向拉取,只留 App 安装期 seed (
init_data.sql/ RVH03_init_data.sql,现状已在 v2 播种 ~211 词)。因此 Supabase 公开表recommended_excluded_words直接 DROP(不改名),两端拉取代码删除(不改名)。本地default_stopwords表 + "merge 进 known_words" 逻辑保留,merge 源改为本地 seed、在 init/app-start 触发(不再依赖 pull)。此简化并入本次。
命名规范(三端统一)
- 基名三端一致;Supabase 每用户同步表加
user_前缀(既有约定,标记 per-user + RLS),公开表无前缀。 - RB-local = RVH-local =
learning_entries;Supabase =user_learning_entries。
主改名映射
表(6 改)
| 概念 | 旧(三端基名) | 新 | RB | RVH | Supabase |
|---|---|---|---|---|---|
| SM-2 学习状态 | notebook_entries | learning_entries | ✓ | ✓ | user_notebook_entries→user_learning_entries |
| 阅读页面 | reading_sources | reading_pages | ✓ | ✓ | user_reading_sources→user_reading_pages |
| 词↔页关联 | word_sources | word_page_links | ✓ | ✓ | user_word_sources→user_word_page_links |
| 收藏站点 | sites | favorite_sites | ✓ | ✗(无此表) | user_sites→user_favorite_sites |
| 已认识词(每用户) | excluded_words | known_words | ✓ | ✓ | user_excluded_words→user_known_words |
| 默认停用词(系统) | recommended_excluded_words | default_stopwords | ✓(本地改名,纯预装 seed) | ✓(同) | DROP 公开表(不再拉取,见决策 5) |
保持不变:vocabulary, reading_notes, reference_words, domain_prefs, rss_feeds, rss_items, page_annotations(表名留,列改), recommended_sites, recommended_feeds, recommended_articles, resource_history, reading_log, settings, pronunciation_attempts, word_cloze_contexts, word_personalized_examples, phrase_interaction_log, ocr_word_positions(RVH,表名留,列改)。
列(2 改)
| 旧列 | 新列 | 出现于 |
|---|---|---|
| notebook_entry_id | learning_entry_id | word_page_links(RB+RVH)+ user_word_page_links |
| reading_source_id | reading_page_id | word_page_links、page_annotations(RB);word_page_links、ocr_word_positions(RVH);对应 user_* 远端表 |
不改的近似列(防误伤):
word_source_id(notes.rs 里指 word_sources 行 PK 的引用变量,非本次列)、source_id(pronunciation_attempts 列)、note_id(→reading_notes,不变)、source_ref/source_type(reading_pages 内容来源字段,保留)。
端 A:RB(本会话执行,Rust 为主)
迁移机制(no-坑 flatten):无兼容负担 → 直接改 baseline assets/sql/schema.sql + init_data.sql 到新名, 并同步更新引用了被改对象的 post-v1 迁移条目(db/migrations.rs:v5 excluded拆分 / v6 page_annotations列 / v9 notebook_entries FK 翻转含 notebook_entries_new 重建块 / v23 word_sources+reading_sources ADD deleted_at), 使整条链内部一致;删本地 dev DB 重建,不新增 rename-migration。(seed 文件里只有 recommended_sites 不改。)
代码面(全 inline SQL 字符串为主,Rust struct 很少):
- SQL 表名/列名/FK/索引:
assets/sql/schema.sql(6 张 CREATE + FK + 索引 + page_annotations 列)、init_data.sql。 - Rust commands(约 120+83+39+39+63+16 处 line-hits):
commands/vocabulary/{query,crud,mod}.rs、srs.rs、commands/excluded_words.rs(→文件改名known_words.rs)、commands/sites.rs(→favorite_sites.rs)、notes.rs、annotations.rs、reading.rs、history.rs、pronunciation.rs、recommend.rs、db/word_list.rs、auth.rs。 - Tauri 命令名(跨 FE↔Rust,同 commit 改):
add_excluded_word→add_known_word、get_excluded_words→get_known_words、is_word_excluded→is_word_known、batch_remove_excluded_words→…;add_site/remove_site/is_site_saved/get_sites→*_favorite_site(s);remove_reading_source→remove_reading_page、remove_word_source→remove_word_page_link。 命令注册:commands/mod.rs(pub mod行)+lib.rs(handler 列表)。 停用词(决策 5):fetch_recommended_excluded_words及其 Supabase 拉取路径删除(不改名);本地default_stopwords的 seed(init_data.sql)+ merge-into-known_words 保留,merge 在 init 触发。recommend.rs:286的远端 endpoint 引用删。 - Rust 类型:
ExcludedWord/ExcludedWordListResult→KnownWord*;Site/Sites→FavoriteSite*;ReadingSourceItem→ReadingPageItem;RemoteWordSource/RemotePageAnnotation字段(serde 无 rename,字段名=远端列名,跟列改)。 - sync 层(
commands/sync/{push,pull,common,mod}.rs):本地名参数 + 远端名参数都改(三端统一,非只改本地);push.rs/pull/*.rs每处post_rows/fetch_remote配对(行号见调查)、JSON key = 远端列名、on_conflict 串、mod.rspending-count SQL。common.rs::mark_synced泛型无硬编码,安全。 - 前端
src/:0 直查 SQL(无需改 SQL);改类型(ExcludedWord→KnownWord、Site→FavoriteSite、ReadingSourceItem→ReadingPageItem)、commands.ts invoke 封装函数名 + 命令字符串 + 参数名(readingSourceId→readingPageId)、 stores(useLibraryStore的'notebook'|'excluded'tab/filter 字段、useAnnotationStore.sourceId、usePanelStore 'mysites')、 组件(MySitesPanel→MyFavoriteSitesPanel等)。 - i18n
src/lib/strings/(语义翻转,决策 1):VocabPanel「排除」整套文案(topTab/batchExclude/addPlaceholder/ emptyPrimary/badgeExcluded/excludeChipTitle…EN+ZH + facade)改写为"已认识/Known/标记已认识/取消已认识",统一 Triage 术语; 动作方向重写("排除此词"→"标记为已认识")。"生词本/Notebook" 文案保留(决策 2)。 scripts/cross-end-check.sh:SHARED_TABLES/SHARED_SYNC数组更新为新名(三端都改后仍是同名比对,直接换新名即可); Supabase 探针user_$t随之变user_learning_entries等。- RB 文档:
docs/database-schema.md/database-tables-overview.md/CLAUDE.md(§9 统一表名列表、§5 迁移表、 关键文件索引、红线 #7/#9 表名)/MEMORY.md/ 其余 docs grep-audit。
端 B:Supabase(本会话产出 DDL,用户在 Dashboard 手动执行)
改 supabase/sql/sync-tables.sql:5 张 user_* 表 CREATE + 索引(idx_une/urs/uws/uew/usites_) + 触发器 (trg__server_ts) + RLS 策略名 全部改新基名;user_word_page_links 列 notebook_entry_id/reading_source_id 改; user_page_annotations(表名留)列 reading_source_id→reading_page_id + idx_upa_source; recommended_excluded_words 公开表整段 DROP(决策 5,不再拉取) + 从 sync-tables.sql 移除其 CREATE/idx/策略。 recommended_sites 段不动。配套:recommended-excluded-words-seed.sql 不再需要(本地 seed 已含,Supabase 侧删表即可, 该 seed 文件可删或留档)、storage-setup.sql(user_reading_sources→user_reading_pages)。 cron-setup.sql/recommend-pool-governance.sql 仅 recommended_sites,不动。Edge Functions 零改动(已核实无命中)。 → 产出"Dashboard 执行顺序"SQL(因无数据直接 DROP+CREATE;含 DROP TABLE recommended_excluded_words)。 注:第 3 仓库 readVocab-admin 若有管理 recommended_excluded_words 的入口,需在其会话同步移除(本次仅记录,不动)。
端 C:RVH(必在专门会话执行,本清单交付给它)
机制:_schemaVersion 55→56 + 改 assets/sql/01_create_tables.sql(表/列/FK/UNIQUE) + 02_create_indexes.sql(索引名) → dev _onUpgrade 抛异常即删库重建,无需 migration。RVH 无 sites 表(跳过 favorite_sites);ocr_word_positions 列 reading_source_id→reading_page_id 别漏。 Dart:model 类改名(NotebookEntry*→LearningEntry*、ReadingSource*→ReadingPage*、WordSource*→WordPageLink*、 ExcludedWord*→KnownWord*)+ fromMap/toMap 的 key 字符串(=列名)+ datasource/repository/usecase 方法名 + sync_repository_impl.dart 本地↔远端配对(本地名 + user_* 远端名都改);freezed/json → dart run build_runner build 重生成; i18n app_en.arb/app_zh.arb 同样翻转 exclude→known(ja 无 exclude 键);feature 目录 excluded_words/→known_words/ 等(决策 3)。 停用词(决策 5):supabase_recommended_excluded_words_datasource.dart + 其拉取/replaceRecommendedCache 路径删除; 本地 default_stopwords(03_init_data.sql seed)+ mergeRecommendedIntoExcluded(→改名 mergeStopwordsIntoKnown,源改本地)保留。
子串碰撞安全序(三端通用铁律 — 禁止盲 sed)
先长后短、先列后表、排除清单:
- 先替最长/最具体串:
recommended_excluded_words→default_stopwords、user_excluded_words→user_known_words、user_reading_sources→user_reading_pages等(先于裸表名)。 - 再替列:
notebook_entry_id→learning_entry_id、reading_source_id→reading_page_id(先于裸表名 notebook_entries/reading_sources)。 - 最后替裸表名,并显式排除:
recommended_sites/recommended_feeds/recommended_articles/nav_sites(不含sites改)、word_source_id/source_id/source_ref/source_type(不含reading_source/word_source改)、reading_notes(不含reading_source改)、notebook_entries_new(迁移临时块,随 notebook_entries 一起改成 learning_entries_new 或直接消除)。 - 关键防炸点:
sites→favorite_sites时recommended_sites必须不动(RB recommend.rs/init_data/sync-tables/discover-sites 并排)。
执行模型
用 sonnet 子 agent 分端执行,交付本清单为规则表:
- 阶段 1(RB):SQL+migrations+Rust commands+命令名 →
cargo check闭环 → 再 sync 层 → 再 FE 类型/commands.ts/stores → 再 i18n 翻转 → cross-end-check.sh + 文档。 - 阶段 2(Supabase):产出 DDL 脚本,用户 Dashboard 执行。
- 阶段 3(RVH):新会话,交付端 C 清单。
验证
- RB:删 dev DB →
pnpm tauri dev重建、PRAGMA foreign_key_check空、cargo check+pnpm build过。 - grep 审计:全仓无裸旧名残留(排除合法处:无——三端全改后旧名应彻底消失,除 git 历史/CHANGELOG); 确认
recommended_sites/word_source_id/source_ref等未被误伤。 - sync 往返冒烟(MCP):登录 → 存词/建笔记/标记已认识 →
sync_now→rb_supabase_query查user_learning_entries/user_word_page_links/user_known_words有新行 → 删本地重拉回来。前提:Supabase DDL 已先执行。 - i18n:VocabPanel 通读,"已认识"术语与 Triage 一致,无"排除"残留,"生词本"品牌词保留。
/arch-check+/build-check+/code-review+/cross-end-check(应无漂移,因三端同步改)。
关键提醒
- 执行顺序依赖:Supabase DDL 必须先于 RB/RVH 新客户端跑 sync(否则 PostgREST 报未知表)。但因无数据,DROP+CREATE 即可。
- 三端同一 commit 语义:本次是"三端统一改",不是"RB 单改 + 映射"——远端名也改,
user_前缀保留。 - RVH 改动另开会话(CLAUDE.md §9);本会话只交付 RVH 清单 + 执行 RB + 产出 Supabase DDL。
- 待用户敲定
default_stopwords最终名后再进入执行。