Skip to content

三端表/列全量重命名 — 最终改名清单(供核对)

状态:✅ 三端全部完成(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_entriesreading_notes 的 "note" 撞车与"排除词"偏负面命名,且表/列/代码标识符/注释/ i18n 三端统一,不留坑。本文件是执行前供用户核对的主清单;实际改动分端执行(RVH 必在专门会话)。

已锁定决策(用户确认)

  1. i18n 语义翻转excluded/排除known/已认识,用户可见文案全部改写,并统一到 Triage 已用的"认识/Known"术语。
  2. "生词本/Notebook" 品牌词保留:表/代码/变量改 learning_entries,但用户可见文案保留"生词本/Notebook"(不译成"学习条目")。
  3. 全量标识符跟改:Tauri 命令名、类型、变量、invoke 参数名、文件名、索引名、RVH feature 目录名,全部跟改;FE+Rust 同 commit。
  4. 系统停用词表名 = default_stopwords(已定)。
  5. 停用词改纯本地预装(已定):停用词静态 → 砍掉 Supabase 单向拉取,只留 App 安装期 seed (init_data.sql / RVH 03_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 改)

概念旧(三端基名)RBRVHSupabase
SM-2 学习状态notebook_entrieslearning_entriesuser_notebook_entries→user_learning_entries
阅读页面reading_sourcesreading_pagesuser_reading_sources→user_reading_pages
词↔页关联word_sourcesword_page_linksuser_word_sources→user_word_page_links
收藏站点sitesfavorite_sites✗(无此表)user_sites→user_favorite_sites
已认识词(每用户)excluded_wordsknown_wordsuser_excluded_words→user_known_words
默认停用词(系统)recommended_excluded_wordsdefault_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_idlearning_entry_idword_page_links(RB+RVH)+ user_word_page_links
reading_source_idreading_page_idword_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 很少):

  1. SQL 表名/列名/FK/索引assets/sql/schema.sql(6 张 CREATE + FK + 索引 + page_annotations 列)、init_data.sql
  2. Rust commands(约 120+83+39+39+63+16 处 line-hits):commands/vocabulary/{query,crud,mod}.rssrs.rscommands/excluded_words.rs(→文件改名 known_words.rs)、commands/sites.rs(→favorite_sites.rs)、 notes.rsannotations.rsreading.rshistory.rspronunciation.rsrecommend.rsdb/word_list.rsauth.rs
  3. Tauri 命令名(跨 FE↔Rust,同 commit 改):add_excluded_wordadd_known_wordget_excluded_wordsget_known_wordsis_word_excludedis_word_knownbatch_remove_excluded_words→…;add_site/remove_site/is_site_saved/get_sites*_favorite_site(s)remove_reading_sourceremove_reading_pageremove_word_sourceremove_word_page_link。 命令注册:commands/mod.rspub 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 引用删。
  4. Rust 类型ExcludedWord/ExcludedWordListResultKnownWord*Site/SitesFavoriteSite*ReadingSourceItemReadingPageItemRemoteWordSource/RemotePageAnnotation 字段(serde 无 rename,字段名=远端列名,跟列改)。
  5. sync 层commands/sync/{push,pull,common,mod}.rs):本地名参数 + 远端名参数都改(三端统一,非只改本地); push.rs/pull/*.rs 每处 post_rows/fetch_remote 配对(行号见调查)、JSON key = 远端列名、on_conflict 串、 mod.rs pending-count SQL。common.rs::mark_synced 泛型无硬编码,安全。
  6. 前端 src/:0 直查 SQL(无需改 SQL);改类型ExcludedWordKnownWordSiteFavoriteSiteReadingSourceItemReadingPageItem)、commands.ts invoke 封装函数名 + 命令字符串 + 参数名(readingSourceIdreadingPageId)、 storesuseLibraryStore'notebook'|'excluded' tab/filter 字段、useAnnotationStore.sourceIdusePanelStore 'mysites')、 组件(MySitesPanelMyFavoriteSitesPanel 等)。
  7. i18n src/lib/strings/(语义翻转,决策 1):VocabPanel「排除」整套文案(topTab/batchExclude/addPlaceholder/ emptyPrimary/badgeExcluded/excludeChipTitle…EN+ZH + facade)改写为"已认识/Known/标记已认识/取消已认识",统一 Triage 术语; 动作方向重写("排除此词"→"标记为已认识")。"生词本/Notebook" 文案保留(决策 2)。
  8. scripts/cross-end-check.shSHARED_TABLES/SHARED_SYNC 数组更新为新名(三端都改后仍是同名比对,直接换新名即可); Supabase 探针 user_$t 随之变 user_learning_entries 等。
  9. 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_linksnotebook_entry_id/reading_source_id 改; user_page_annotations(表名留)列 reading_source_idreading_page_id + idx_upa_sourcerecommended_excluded_words 公开表整段 DROP(决策 5,不再拉取) + 从 sync-tables.sql 移除其 CREATE/idx/策略。 recommended_sites 段不动。配套:recommended-excluded-words-seed.sql 不再需要(本地 seed 已含,Supabase 侧删表即可, 该 seed 文件可删或留档)、storage-setup.sqluser_reading_sourcesuser_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)

先长后短、先列后表、排除清单

  1. 先替最长/最具体串:recommended_excluded_wordsdefault_stopwordsuser_excluded_wordsuser_known_wordsuser_reading_sourcesuser_reading_pages 等(先于裸表名)。
  2. 再替列:notebook_entry_idlearning_entry_idreading_source_idreading_page_id先于裸表名 notebook_entries/reading_sources)。
  3. 最后替裸表名,并显式排除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 或直接消除)。
  4. 关键防炸点:sites→favorite_sitesrecommended_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 清单。

验证

  1. RB:删 dev DB → pnpm tauri dev 重建、PRAGMA foreign_key_check 空、cargo check + pnpm build 过。
  2. grep 审计:全仓无裸旧名残留(排除合法处:无——三端全改后旧名应彻底消失,除 git 历史/CHANGELOG); 确认 recommended_sites/word_source_id/source_ref未被误伤
  3. sync 往返冒烟(MCP):登录 → 存词/建笔记/标记已认识 → sync_nowrb_supabase_queryuser_learning_entries/ user_word_page_links/user_known_words 有新行 → 删本地重拉回来。前提:Supabase DDL 已先执行
  4. i18n:VocabPanel 通读,"已认识"术语与 Triage 一致,无"排除"残留,"生词本"品牌词保留。
  5. /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 最终名后再进入执行。