9.5 KiB
9.5 KiB
FMS 项目长期约定
目录 / 文档 / 库
- 后端
fms-api(Spring Boot + JDK21,JDBC+Druid 无 ORM);前端fms-vue(Vue 3.5 + Vite 8 + Pinia,纯 JS)。fms-vue-old1/old2仅供历史参考,不要改。 - 根目录设计文档:
FMS新系统核心表结构设计.md(权威表结构)、FMS业务表设计.md、开发规范.md(AI 规范)、Fms旧系统表结构.md(旧库 G3HY2025,只有表无视图)、FMS删除规则引擎设计.md。 - 建库/模块注册脚本在
sql/(fms_core.sql、fms_business_*.sql、fms_module_*.sql)。 - SQL Server
118.89.70.199:1433:旧库G3HY2025,新库 FMS(新系统一律用 FMS,生产库,写前先确认)。 - 机构→库映射在
fms-api/config/dbconfigs/{ORG_ID}.properties(gitignore):G3HD.properties→ FMS,G3HY2025.properties→ G3HY2025。没有 FMS.properties。 - 后端 8088(context-path
/api),前端 dev 5082(/api→ 127.0.0.1:8088)。直连接口需先/auth/login。
元数据核心表(真实列名,已连库核对,别再猜)
s_module:PKb_id(无b_module_code;无b_route,那是s_menu的);本身是树:b_parent_id/b_depth/b_path;另有b_module_type(module/data/virtual)、b_view_table、b_save_table、b_key_field、b_order_sql、b_query_sql、b_config_json、b_canuse、b_xh、b_bz、b_name、b_i18n。s_field:PK(b_module_id, b_field),无b_id;b_type实测input/number/checkbox/datetime/date。s_module_schema:PK(b_module_id, b_schema_type∈view|edit|query),b_schema_json。s_menu:b_id/b_parent_id/b_depth/b_path/b_menu_type(directory|page)/b_route/b_icon;s_menu_module绑菜单与模块。- 权限靠
b_id:permissionStore 的moduleCodes即s_module.b_id,页面MODULE_CODE必须等于它; 还要在s_menu_module里绑菜单,否则非超管看不到授权入口。 - 列表模块编码统一
v_+表名(v_b_othercompany),b_view_table→视图,b_save_table→真实表。 - schema JSON 形状:
view{columns:[{field,width}|{type:group,title,children}]}、edit{children:[{field,span,required,readonly,defaultValue}|group]}、query{groups:[{conditions}],quick}。 - 路由守卫只看
meta.moduleId/meta.adminOnly;views/module/**是 adminOnly(仅 g3soft)。
树结构规范(模块/菜单/部门/分类树通用)
b_parent_id 是权威关系,b_depth(根=0)、b_path(/cn/east/)是派生字段,移动节点要同事务更新全部后代;
不一致时以 b_parent_id 为准。工具在 src/utils/tree.js(buildSortedTree/computeTreeMove/collectDescendantIds/
applyTreePosition/filterTreeByText/findTreeNode),展示层用 components/fms-tree/FmsTree.vue(自管虚拟根)。
后端通用接口(前端业务数据只走这几个)
POST /auth/login:字段是小写orgid/userid/password;orgid=G3HD。/data/loaddata:view_name/search_condition/可选order_by/search_columns(真 JSON 数组)。/data/page:order_by必填(DbUtils.buildPageOrderBy会报「order_by 不能为空」), 分页参数名是page_no/page_size(不是 pageindex/pagesize)。/data/saveobjt:body 是数组,每项{table, key_field, deletes, updates, inserts},key_field必填 (复合主键逗号分隔),顺序 delete→update→insert。- 模块元数据不由接口下发,前端读本地 schema JSON,改元数据无需重启后端。
DbUtils是 SQL 唯一出口:标识符加[],validateReadOnlySql()只允许查询。
环境坑(本机特有)
- 编译/测试 fms-api 唯一可行命令(start.cmd 里的 JDK/Maven 路径都是坏的):
本地仓库是
cd /d/workspace/code/fms/fms-api && /d/devtool/jdk/jdk21/bin/java \ -Dclassworlds.conf="D:/devtool/maven/bin/m2.conf" -Dmaven.home="D:/devtool/maven" \ -Dmaven.multiModuleProjectDirectory="D:/workspace/code/fms/fms-api" \ -cp "D:/devtool/maven/boot/plexus-classworlds-2.11.0.jar" \ org.codehaus.plexus.classworlds.launcher.Launcher -o -Dtest=XxxTests testD:\data\maven(不是 ~/.m2);联网下载去掉-o;target/被 git 跟踪,编译后有噪音。 - 无 sqlcmd/pyodbc/pymssql:用
fms-api/tools/migration/RunSqlFile.java或一次性SqlRunner.java- JDBC jar(
~/.m2/.../mssql-jdbc-13.4.0.jre11.jar)+/d/devtool/jdk/jdk17/bin/java。 脚本要按行首GO分批,路径传绝对路径。
- JDBC jar(
vite build被 safe-delete 守卫拦(要删 600+ 文件):用--outDir dist-verify --emptyOutDir; 清理用find dist-verify -type f -delete再find dist-verify -type d -empty -delete。oxfmt --check全仓库都报 format issues(版本漂移),不是自己引入的,别顺手格式化整个仓库。- 本工作区可能被多会话同时编辑,验证失败项先用
find <dir> -mmin -N确认是否自己引入。
测试基线(既有失败,别去修)
- 后端
OrgDataSourceFactoryTests.databaseConnectionFailureDoesNotRetry(断言 Druid retry=0,实测 1)。 - 前端
tests/unit/fms-module-list-page.spec.js里引用.filter-drawer/.filter-row__*的用例 (类名已不存在,是高级查询面板改版后的过期断言)—— 另有约 13 个长期失败基线。 tests/helpers/app.js的mountPage用 shallowMount 且默认打桩子组件:给Splitter/SplitterPanel打桩时键名要写 Vue 推断名'splitter'/'panel'(文件名小写),写'SplitterPanel'打不上桩; 自定义组件传false可强制真实挂载。global会整体覆盖内部 stubs,别在里面再写 stubs。
主题约定
- 配色唯一真相
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-*,不受表单布局配置影响。
导出(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 可直接用。