# 开发指南 **本文引用的文件** - [fms-vue/package.json](file://fms-vue/package.json) - [fms-vue/.oxfmtrc.json](file://fms-vue/.oxfmtrc.json) - [fms-vue/.oxlintrc.json](file://fms-vue/.oxlintrc.json) - [fms-vue/vitest.config.js](file://fms-vue/vitest.config.js) - [fms-vue/tests/README.md](file://fms-vue/tests/README.md) - [fms-vue/tests/setup.js](file://fms-vue/tests/setup.js) - [fms-vue/src/main.js](file://fms-vue/src/main.js) - [fms-vue/src/services/http.js](file://fms-vue/src/services/http.js) - [fms-vue/src/stores/auth.js](file://fms-vue/src/stores/auth.js) - [fms-vue/src/components/ui/button/Button.vue](file://fms-vue/src/components/ui/button/Button.vue) - [fms-api/pom.xml](file://fms-api/pom.xml) - [fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本指南面向FMS项目的开发者,聚焦以下目标: - 明确前端(Vue/JS)与后端(Java/Spring Boot)的开发规范与编码标准 - 解释目录结构与模块划分原则,帮助新成员快速上手 - 提供Vue组件开发模式、Props设计、事件处理的最佳实践 - 统一测试策略与用例编写规范(单元、集成、E2E) - 给出调试技巧与常见问题排查方法(浏览器工具、日志、性能分析) ## 项目结构 仓库采用前后端分离的多模块组织: - fms-vue:基于Vite + Vue 3的前端工程,包含UI组件库、页面、路由、状态管理、服务层与测试 - fms-api:基于Spring Boot的后端API工程,包含控制器、服务、数据库配置、迁移脚本等 - fms-vue-old1 / fms-vue-old2:历史版本或实验分支,当前以fms-vue为主 - .playwright-cli / .fps-probe:辅助调试与测量脚本 - 参考组件库:外部参考实现,不直接参与构建 ```mermaid graph TB subgraph "前端 fms-vue" A["src/main.js"] --> B["src/router/index.js"] A --> C["src/stores/*.js"] A --> D["src/services/http.js"] D --> E["后端 fms-api"] F["src/components/ui/*"] --> G["页面 views/*"] end subgraph "后端 fms-api" H["FmsApiApplication.java"] --> I["controller/service/database"] end ``` 图表来源 - [fms-vue/src/main.js:1-22](file://fms-vue/src/main.js#L1-L22) - [fms-vue/src/services/http.js:1-15](file://fms-vue/src/services/http.js#L1-L15) - [fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java:1-22](file://fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java#L1-L22) 章节来源 - [fms-vue/package.json:1-48](file://fms-vue/package.json#L1-L48) - [fms-api/pom.xml:1-108](file://fms-api/pom.xml#L1-L108) ## 核心组件 - 应用入口与启动流程:初始化Pinia、插件、路由、主题同步,并在路由就绪后挂载应用,处理引导屏与错误兜底 - HTTP客户端:封装Axios,统一注入Authorization头、统一响应格式、鉴权失败跳转登录、网络异常提示 - 认证状态:集中管理登录凭证与用户信息,支持持久化到sessionStorage/localStorage - UI组件:统一的按钮等基础组件,遵循Props校验、可访问性属性、加载态与禁用态组合 章节来源 - [fms-vue/src/main.js:14-22](file://fms-vue/src/main.js#L14-L22) - [fms-vue/src/services/http.js:40-47](file://fms-vue/src/services/http.js#L40-L47) - [fms-vue/src/stores/auth.js:14-25](file://fms-vue/src/stores/auth.js#L14-L25) - [fms-vue/src/components/ui/button/Button.vue:11-41](file://fms-vue/src/components/ui/button/Button.vue#L11-L41) ## 架构总览 前端通过HTTP客户端调用后端API;鉴权失败时由拦截器清理会话并跳转登录页;状态通过Pinia管理并持久化。 ```mermaid sequenceDiagram participant U as "用户" participant V as "Vue应用" participant H as "http.js" participant S as "后端API" participant P as "Pinia(auth)" U->>V : 触发操作 V->>H : 发起请求 H->>P : 读取token H->>S : 携带Authorization头 alt 成功 S-->>H : {code : 0, data} H-->>V : 返回数据 else 鉴权失败(401/40101) S-->>H : {code : 401/40101} H->>P : clearSession() H-->>U : 跳转/login?reason=... else 网络/服务器错误 S-->>H : 无status或5xx H-->>U : 弹出Message提示 end ``` 图表来源 - [fms-vue/src/services/http.js:40-103](file://fms-vue/src/services/http.js#L40-L103) - [fms-vue/src/stores/auth.js:22-25](file://fms-vue/src/stores/auth.js#L22-L25) ## 详细组件分析 ### 前端应用启动流程 - 创建Pinia并启用持久化插件 - 注册路由与主题同步 - 等待路由就绪后挂载应用,处理引导屏淡出与错误兜底 ```mermaid flowchart TD Start(["应用启动"]) --> Init["创建Pinia并安装插件"] Init --> Router["注册路由"] Router --> Theme["初始化主题同步"] Theme --> Ready{"路由是否就绪?"} Ready -- 否 --> Wait["等待路由就绪"] Wait --> Ready Ready -- 是 --> Mount["挂载应用 #app"] Mount --> Boot["显示/隐藏引导屏"] Boot --> End(["完成"]) ``` 图表来源 - [fms-vue/src/main.js:14-22](file://fms-vue/src/main.js#L14-L22) - [fms-vue/src/main.js:41-77](file://fms-vue/src/main.js#L41-L77) 章节来源 - [fms-vue/src/main.js:1-78](file://fms-vue/src/main.js#L1-L78) ### HTTP客户端与鉴权流程 - 请求拦截器:从auth store读取token并注入Authorization头 - 响应拦截器:统一包装success/code/message/data;鉴权失败清理会话并跳转;网络/服务端错误统一提示 - 便捷方法:post(path, data, config) ```mermaid flowchart TD Req["发起请求"] --> Interp["请求拦截器注入Token"] Interp --> Send["发送HTTP请求"] Send --> Resp{"响应码"} Resp -- code==0 --> Ok["返回data"] Resp -- 401/40101 --> AuthErr["clearSession并跳转登录"] Resp -- 其他业务错误 --> BizErr["抛出带code/data的错误"] Resp -- 网络/5xx --> NetErr["Message.error并标记toasted"] ``` 图表来源 - [fms-vue/src/services/http.js:40-103](file://fms-vue/src/services/http.js#L40-L103) 章节来源 - [fms-vue/src/services/http.js:1-111](file://fms-vue/src/services/http.js#L1-L111) ### 认证状态管理(Pinia) - 维护loginInfo(token/user)与userInfo(orgId/account) - setSession兼容不同字段名;clearSession仅清空会话,不清“记住的账号” - 持久化:loginInfo存sessionStorage,userInfo存localStorage ```mermaid classDiagram class AuthStore { +loginInfo +userInfo +isAuthenticated +setSession(session, organizationId) +clearSession() +saveLastLogin(orgId, account) } ``` 图表来源 - [fms-vue/src/stores/auth.js:1-49](file://fms-vue/src/stores/auth.js#L1-L49) 章节来源 - [fms-vue/src/stores/auth.js:1-49](file://fms-vue/src/stores/auth.js#L1-L49) ### UI组件开发模式(以Button为例) - Props设计:type/disabled/loading/block/htmlType,均提供默认值与校验 - 计算属性:isDisabled合并disabled与loading;classes根据props动态生成 - 模板:使用原生button语义,暴露aria-busy,支持插槽内容 - 样式:按BEM风格命名类,便于主题扩展 ```mermaid classDiagram class Button { +props : type, disabled, loading, block, htmlType +computed : isDisabled, classes +template : button(slot) } ``` 图表来源 - [fms-vue/src/components/ui/button/Button.vue:11-63](file://fms-vue/src/components/ui/button/Button.vue#L11-L63) 章节来源 - [fms-vue/src/components/ui/button/Button.vue:1-69](file://fms-vue/src/components/ui/button/Button.vue#L1-L69) ### 后端应用启动 - Spring Boot主类初始化雪花ID生成器选项并启动应用 章节来源 - [fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java:1-22](file://fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java#L1-L22) ## 依赖分析 - 前端依赖:Vue 3、Vue Router、Pinia、Axios、DayJS、Lucide图标、stk-table-vue、Vitest、Oxlint/Oxfmt等 - 后端依赖:Spring Boot Web/JDBC、Druid、JWT、Jackson、IP定位、UA解析、SQL Server驱动等 ```mermaid graph LR FE["fms-vue/package.json"] --> Vue["Vue 3"] FE --> Pinia["Pinia"] FE --> Axios["Axios"] FE --> Vitest["Vitest"] FE --> OX["Oxlint/Oxfmt"] BE["fms-api/pom.xml"] --> SB["Spring Boot"] BE --> JDBC["JDBC/Druid"] BE --> JWT["JWT"] BE --> DB["SQL Server"] ``` 图表来源 - [fms-vue/package.json:21-45](file://fms-vue/package.json#L21-L45) - [fms-api/pom.xml:32-95](file://fms-api/pom.xml#L32-L95) 章节来源 - [fms-vue/package.json:1-48](file://fms-vue/package.json#L1-L48) - [fms-api/pom.xml:1-108](file://fms-api/pom.xml#L1-L108) ## 性能考虑 - 首屏优化:路由就绪后再挂载应用,避免菜单“跳出”;引导屏使用合成属性过渡,减少重排 - 按需特性:表格区域选择等能力按需注册,减少无关逻辑 - 网络层:超时与统一错误提示,避免重复弹窗(toasted标记) - 状态持久化:仅持久化必要字段,降低存储体积 章节来源 - [fms-vue/src/main.js:41-77](file://fms-vue/src/main.js#L41-L77) - [fms-vue/src/services/http.js:8-15](file://fms-vue/src/services/http.js#L8-L15) - [fms-vue/src/services/http.js:94-100](file://fms-vue/src/services/http.js#L94-L100) ## 故障排查指南 - 启动失败:检查main.js中的bootstrap异常捕获与引导屏错误展示 - 鉴权问题:确认http拦截器是否正确注入Authorization;401/40101会清理会话并跳转 - 网络异常:检查超时配置与Message提示;区分业务错误与服务端不可达 - 测试环境问题:setup.js已补齐ResizeObserver/IntersectionObserver/matchMedia等全局对象;确保在jsdom环境运行 - 覆盖率门槛:使用test:coverage命令检查阈值(lines/functions/branches/statements ≥ 60%) 章节来源 - [fms-vue/src/main.js:24-39](file://fms-vue/src/main.js#L24-L39) - [fms-vue/src/services/http.js:19-38](file://fms-vue/src/services/http.js#L19-L38) - [fms-vue/tests/setup.js:11-57](file://fms-vue/tests/setup.js#L11-L57) - [fms-vue/vitest.config.js:17-31](file://fms-vue/vitest.config.js#L17-L31) ## 结论 本指南总结了FMS项目的目录结构、核心流程、组件开发模式与测试策略。建议新成员: - 先阅读tests/README.md了解测试命令与规范 - 在新增功能时遵循现有组件Props设计与事件约定 - 通过http.js统一进行网络交互,避免绕过拦截器 - 使用vitest与覆盖率门禁保障质量 ## 附录 ### 开发规范与编码标准 - 代码风格 - 使用Oxlint进行静态检查,规则见配置文件 - 使用Oxfmt进行格式化,单引号、尾随逗号、行宽等见配置文件 - 命名约定 - 组件目录按功能拆分(如ui/button),文件名与组件名一致 - Store按领域划分(auth/app/preferences等) - 服务层集中在services,HTTP封装在http.js - 注释规范 - Props使用JSDoc标注类型与说明 - 关键函数与拦截器添加行为说明 章节来源 - [fms-vue/.oxlintrc.json:1-21](file://fms-vue/.oxlintrc.json#L1-L21) - [fms-vue/.oxfmtrc.json:1-8](file://fms-vue/.oxfmtrc.json#L1-L8) - [fms-vue/src/components/ui/button/Button.vue:6-19](file://fms-vue/src/components/ui/button/Button.vue#L6-L19) ### 组件开发最佳实践 - Props设计:最小可用集合,提供默认值与校验;对敏感/可选参数使用validator - 事件处理:优先使用v-model双向绑定;复杂交互通过emit传递结构化数据 - 可访问性:为交互元素设置aria-*属性(如aria-busy) - 样式:使用BEM命名,避免全局污染;通过CSS变量支持主题 章节来源 - [fms-vue/src/components/ui/button/Button.vue:11-63](file://fms-vue/src/components/ui/button/Button.vue#L11-L63) ### 测试策略与用例规范 - 命令速查:全部测试、单文件测试、覆盖率、监听模式 - 目录与命名:按源码结构对应spec文件;每个被测对象一个spec - 模板与装配:页面测试用mountPage;store测试用createTestPinia;纯函数直接断言 - 覆盖率:≥60%;仅在coverage模式下检查阈值 - 常见坑:pinia必须用createTestPinia;persist格式注意;跨用例清理存储;异步用flushPromises+nextTick 章节来源 - [fms-vue/tests/README.md:10-57](file://fms-vue/tests/README.md#L10-L57) - [fms-vue/tests/README.md:59-189](file://fms-vue/tests/README.md#L59-L189) - [fms-vue/tests/README.md:191-256](file://fms-vue/tests/README.md#L191-L256) - [fms-vue/vitest.config.js:12-31](file://fms-vue/vitest.config.js#L12-L31) ### 调试技巧与常见问题 - 浏览器调试:利用Network面板查看请求头Authorization;Console中查看Message提示 - 日志分析:关注http拦截器的错误分支与跳转逻辑 - 性能分析:使用Performance面板观察首屏渲染与引导屏过渡;关注表格虚拟滚动与懒加载 - 常见问题: - 401反复跳转:检查是否在/login路径重复跳转 - 网络错误误登出:确认仅鉴权错误清会话 - 组件尺寸相关断言失败:jsdom下尺寸多为0,应改为状态/事件断言 章节来源 - [fms-vue/src/services/http.js:19-38](file://fms-vue/src/services/http.js#L19-L38) - [fms-vue/tests/README.md:247-256](file://fms-vue/tests/README.md#L247-L256)