# 分类树多语言实施计划 > 状态:待执行 > 目标:合作伙伴、其他数据两个基础资料页的分类树支持多语言;翻译作为分类录入的一部分,显示时缺失回退默认语言。 ## 背景 - 项目多语言能力已落地:`b_i18n_type` 维护语言(`zh-CN` 为默认,`en-US` 已启用);`b_i18n(b_key, b_locale, b_value)` 按语言存翻译;前端 `appStore.t(key, fallback)` 查不到翻译时回退 `fallback`(即中文 `b_name`)。 - 分类树是「引用数据」,按主流 ERP 惯例(SAP 语言相关文本表 MAKT / Odoo 可翻译字段)应支持多语言。 - 现状差异: - 其他数据 `b_other_bmfl` 已有 `b_i18n` 列与键(`category.base_otherdata.{id}`),树标题已走 `t()`;**但分类维护弹窗没有录入其他语言文本的入口,b_i18n 表里没有对应翻译行**。 - 合作伙伴 `b_othercompany_bmfl` **完全没有** `b_i18n` 列。 - 参照写法:`fms-vue/src/views/base/otherdata/index.vue` 的 `buildCategoryTreeNode`(`appStore.t(item.b_i18n, item.b_name)`)、`buildCategoryI18nKey`。 ## 已定设计(执行时不做设计变更) - `b_name` 恒为默认语言(`zh-CN`)名称,**必填**。 - 其他语言文本存 `b_i18n`,键格式: - 合作伙伴分类:`category.base_othercompany.{b_id}` - 其他数据分类:`category.base_otherdata.{b_id}`(已存在,沿用) - 显示一律 `appStore.t(b_i18n, b_name)`,未填翻译回退中文。 - 键基于 `b_id`(snowflake 不变),分类改名不影响翻译。 - 不翻译:公司名、联系人名等自由文本/专有名词。 ## 任务一:迁移脚本 `fms-api/config/migrations/027_add_othercompany_category_i18n.sql` 仿照 `025`/`026` 的写法(`SET NOCOUNT ON` + `SET XACT_ABORT ON` + `BEGIN TRANSACTION` + 存在性判断,幂等可重复执行): 1. `b_othercompany_bmfl` 若无 `b_i18n varchar(150) NULL` 列则 `ALTER TABLE ... ADD`。 2. 回填:`UPDATE dbo.b_othercompany_bmfl SET b_i18n = 'category.base_othercompany.' + CAST(b_id AS varchar(30)) WHERE b_i18n IS NULL OR b_i18n = ''`。 3. 不动其他任何表。 ## 任务二:合作伙伴页 `fms-vue/src/views/base/othercompany/index.vue` 1. `CATEGORY_COLUMNS` 增加 `b_i18n`。 2. 引入 `useAppStore`;`categoryTree` 的 `mapNode` 中 `title` 改为 `appStore.t(item.b_i18n, item.b_name)`(停用后缀「(停用)」保持追加)。 3. `columnExtensions` 里 `b_cate_id` 列 formatter 改为 `appStore.t(cat.b_i18n, cat.b_name) || value || ""`(`categoryById` 需带上 `b_i18n`)。 4. 分类新增/编辑弹窗增加「其他语言名称」录入: - 语言列表取 `appStore.languages`,过滤 `b_canuse = 1` 且非默认(`b_default !== 1`);默认语言(`zh-CN`)即现有「名称」输入框(`b_name`)。 - 编辑时:`loadDataApi("b_i18n", "b_key = N'{escapedKey}'", "b_locale ASC")` 加载该分类已有翻译行,按 `b_locale` 存到草稿(含 `b_id`)。 - 保存时一个 `saveObjectApi` 同时提交分类表与 `b_i18n` 表(参照 `fms-vue/src/views/module-management/components/I18nQuickSetModal.vue` 的 `{ table: "b_i18n", key_field: "b_id", inserts: [], updates: [] }`): - 分类表:新增插入(含 `b_i18n` 键)、编辑更新 `b_name`(键存在则不重写)。 - `b_i18n` 表:某语言有值且已有行 → `updates`;有值无行 → `inserts`(新 `nextIdApi`);值被清空且已有行 → `deletes`(按 `b_id`)。 - 新增分类时键 = `category.base_othercompany.{新分类 nextId}`。 - 分类保存成功后重载分类列表。 ## 任务三:其他数据页 `fms-vue/src/views/base/otherdata/index.vue` 1. 树标题已支持 `t()`,不改。 2. 分类节点(`modalType === "category"`)的新增/编辑弹窗,补上与任务二相同的「其他语言名称」录入与 `b_i18n` 表保存逻辑;键 = `category.base_otherdata.{id}`(`buildCategoryI18nKey` 已生成,直接复用)。 3. 模块节点(`b_node_type = "module"`)不需要语言录入(名称来自 `s_module.b_i18n`),保持现状。 ## 边界与约束(MUST) - 只修改:`027_add_othercompany_category_i18n.sql`(新增)、`othercompany/index.vue`、`otherdata/index.vue`。 - 不修改任何 `/data/*` 通用接口、不新增后端接口、不新增 Service 类。 - 不执行构建、不启动服务、**不执行迁移脚本到数据库**(只创建 SQL 文件)。 - 不提交 git;改动保留在工作区供审查。 - 遵循 `CODEBUDDY.md` 与 `开发规范.md`:表格用 `fms-table`、输入控件不添加 `placeholder`、样式 `scoped`、桌面端无响应式、`bigint` 以字符串处理、写法与现有同类代码一致不自创。 ## 验收 - 两个页面的分类新增/编辑可录入其他语言名称;切换语言后树标题与(合作伙伴)列表分类列显示对应语言,未填语言回退中文。 - `git diff` 仅涉及上述文件;前端 `pnpm fmt:check` 通过。