# 主题 / UI 组件库 / i18n / 导出 ## 主题 - 唯一真相 `fms-vue/src/theme/tokens.css`:`:root` 浅色 + `.dark` 深色必须同步增删同名变量, `--fms-primary` 由 JS 写入,衍生色用 `color-mix()`。改主题只动这个文件。 - **侧栏当前是浅色的**(不存在 `--fms-sidebar-*` 变量;若再看到「侧栏是黑的」即为过期信息)。 要改侧栏配色就新增 `--fms-sidebar-*` 只给 `AppSidebar.vue`/`NavMenuItem.vue` 用, **别动 `--fms-surface`/`--fms-text` 等全局中性色**(顶栏与所有业务页共用)。 - 深底 + 主题色高亮必须用「深底 + 白字 + 主色亮描边」:填充 `color-mix(primary 38%, #000)`、 描边 `color-mix(primary 40%, #fff)`;「浅底 + 白字」对比度只有 1.4~2.7:1,不可用。 - Teleport 到 body 的浮层(如 `.fms-team-menu-*`)不在侧栏内,保持全局浅色 token。 ## UI 组件库全局配置 - 唯一入口 `fms-vue/src/components/ui/config.js`:`uiConfig`(reactive)+ `setUIConfig(patch)` (按组件维度浅合并)+ `resetUIConfig()`,也从 `@/components/ui` 具名导出。 **没有 ConfigProvider、没有 app.use 插件**。 - 回落顺序固定 **自身 prop > uiConfig > 组件内置默认**;要支持全局覆盖的 prop,`default` 必须写 `undefined` 且 validator 要放行 `undefined`(Vue 会拿 default 跑校验)。 - Form 的 `layout`/`labelAlign`/`labelWidth`/`validateTrigger` 已接入;provide 下发回落后的最终值。 语言联动在 `src/App.vue`:中文 `horizontal`、其他语言 `vertical`(判定 `/^zh/i`)。 - **多列紧凑网格的表单必须显式 `layout="vertical"`**(如自动编码面板 columns=5), 否则横排的 88px 标签会把控件压到几十像素。prop 优先于全局配置。 - `defineModel` 写完**不能立刻回读**:写了只 emit,prop 下一轮才回来;要取刚写入的值就自己先 `reactive()` 包一层再赋值,返回其中的代理对象。 ## i18n 运行时 - 语言清单 `s_i18n_type`(`b_id` 即语种编码,zh-CN 默认 / en-US);译文 `s_i18n(b_key, b_locale, b_value)`。 - store `stores/i18n.js`:`loadLanguages()` 拉清单、**`loadMessages(locale)` 拉译文**(按语种缓存 + 并发去重 + 失败静默;只把「当前语种」的译文写进运行时)。**别只看 locale —— 不调 loadMessages 界面不会变。** - 合并顺序 **前端内置 < 库表译文**:内置只有 en-US 的 `common.*`(`src/i18n/builtin-messages.js`, 代码约定 `t('common.x', '中文兜底')`);业务文案/字段名/菜单名的译文一律进 `s_i18n` 由实施维护。 - 现状:`s_i18n` 只登记了 zh-CN(约 134 条),en-US 尚无数据 → 英文界面只有框架按钮/提示是英文, 字段名等仍回落中文,需要补录。 - 顶栏语种下拉取自 `s_i18n_type` 清单,不要硬编码语言编码。 - 查询区(`FmsQueryToolbar`)已改用 Form/FormItem,因此也跟随该配置;Form 根靠 `display: contents` 透明化,让 FormItem 直接参与 `.query-grid`(`minmax(0,200px)`)布局,label 宽局部 72px。 高级查询面板(`FmsAdvancedQueryPanel`)仍是自绘 `.filter-*`,**不受**表单布局配置影响。 ## 模块管理页的分节布局(2026-09-24) - 右栏是「卡头(模块名 + 动作)+ 分节导航(`mm-config-nav`,Tabs `nav-only`)+ `.mm-config-stack`」; 每个分节是 `.mm-config-pane`(`flex:1; overflow:auto; padding:12px 16px 16px`),**滚动由它负责**。 - **面板自身不要做「撑满 + 内部滚动」**:需要一页平铺时用 `flex: 1 0 auto`(内容少时填满、内容多时 撑高让 `.mm-config-pane` 滚动)。`ModuleQueryConfigPanel` 已按此改造 —— 四个分节(更多条件字段 / 工作队列页签 / 关键词字段 / 快捷筛选字段)同页平铺,**不再用内层页签**。 - **`FmsTable` 必须有确定高度**(根 `.fms-table` 是 `height:100%`,且虚拟滚动要容器尺寸)。 平铺多个表格时不能靠 `flex:1` 撑满,要按行数算高度:表头 34 + 行数×30 + 2, clamp 到 140~420px(见 `ModuleQueryConfigPanel.tableHeightOf`),超出上限才在表格内部滚动。 ## 导出(P0 已落地) - `POST /api/export/list` 返回文件流:`SqlPermissionService` → `ExportSchemaService`(列与列表同源推导) → `ExportService`(Fesod 流式写)→ xlsx。**导出列不由前端传**,否则字段权限形同虚设; 校验必须在 `getOutputStream()` 前完成。 - 依赖 `org.apache.fesod:fesod-sheet:2.0.2-incubating`(自带 POI,别再引)。 - Fesod 坑:0 行也要调一次 `write`,否则无工作表;合计行要自己构造标签。 - 权限现状:`s_power` 只有 2 行,非超管会被拒,g3soft 可直接用。