14 KiB
14 KiB
服务层
**本文引用的文件** - [http.js](file://fms-vue/src/services/http.js) - [api.js](file://fms-vue/src/services/api.js) - [fileService.js](file://fms-vue/src/services/fileService.js) - [auth.js](file://fms-vue/src/stores/auth.js) - [FmsFile.vue](file://fms-vue/src/components/fms-file/FmsFile.vue) - [http.spec.js](file://fms-vue/tests/services/http.spec.js) - [api.spec.js](file://fms-vue/tests/services/api.spec.js)目录
简介
本文件面向 FMS 前端服务层,系统性说明 HTTP 请求封装、API 接口组织、文件上传下载服务、错误处理统一机制、日志记录方案、缓存策略与并发控制,以及 API 版本管理与向后兼容建议。文档以代码为依据,结合测试用例,帮助读者快速理解并安全扩展服务层能力。
项目结构
服务层位于 fms-vue/src/services 下,包含:
- http.js:基于 axios 的 HTTP 客户端封装,提供请求/响应拦截器、统一错误处理、登录态注入与跳转。
- api.js:业务 API 函数集合,按功能分组暴露方法,内部调用 http.post。
- fileService.js:文件服务,支持本地直传与阿里云 OSS 直传,含凭证缓存、批量上传、预览与删除。
graph TB
subgraph "服务层"
A["http.js<br/>axios实例/拦截器"]
B["api.js<br/>业务API集合"]
C["fileService.js<br/>文件上传/下载/删除"]
end
subgraph "状态管理"
D["auth.js<br/>登录态/会话"]
end
subgraph "UI组件"
E["FmsFile.vue<br/>文件面板"]
end
B --> A
C --> A
C --> B
A --> D
E --> B
E --> C
图表来源
章节来源
核心组件
- HTTP 客户端(http.js)
- 创建 axios 实例,设置 baseURL、超时、默认头。
- 请求拦截器:从 Pinia 读取 token,自动注入 Authorization 头。
- 响应拦截器:统一包装 ApiResult;对认证失败(401/40101)清理会话并跳转登录;网络异常时给出友好提示并标记 tosted 避免重复弹窗。
- 导出 post(path, data, config) 简化调用。
- API 接口(api.js)
- 按功能分组:认证、数据加载、分页、保存、ID/编号生成、表结构描述等。
- 所有接口通过 http.post 发起,参数映射到后端约定字段。
- 文件服务(fileService.js)
- initFileConfig/getStorageType:初始化存储模式(local 或 aliyun-oss)。
- upload:根据模式选择本地打包上传或 OSS 直传;OSS 路径下逐个回调 save-record 写入元数据。
- 凭证缓存:getOssCredential 带过期缓冲刷新。
- 工具:预览地址获取、删除文件、扩展名解析。
章节来源
架构总览
下图展示一次典型的数据查询流程:页面调用 api.js 中的接口,经 http.js 的请求拦截器注入鉴权头,到达服务端后由响应拦截器统一处理成功/失败/认证失效分支。
sequenceDiagram
participant UI as "页面/组件"
participant API as "api.js"
participant HTTP as "http.js"
participant AUTH as "auth.js"
participant S as "后端服务"
UI->>API : 调用 loadDataApi(...)
API->>HTTP : post('/data/loaddata', params)
HTTP->>AUTH : 读取token
AUTH-->>HTTP : token
HTTP->>S : 发送请求(携带Authorization)
S-->>HTTP : 返回{code,data,message}
alt 认证成功且业务成功
HTTP-->>API : 透传response.data
API-->>UI : 数据
else 业务错误
HTTP-->>API : 抛出Error(code/message/data/success=false)
API-->>UI : 捕获并处理
else 认证失败(401/40101)
HTTP->>AUTH : clearSession()
HTTP-->>UI : 抛错(可被上层捕获)
Note over HTTP,AUTH : 同时触发跳转登录页
end
图表来源
详细组件分析
HTTP 客户端(http.js)
- 实例配置
- baseURL 来自环境变量或默认 /api;timeout 15s;默认 JSON 头。
- 请求拦截器
- 动态读取 auth store 的 token,若存在则注入 Authorization: Bearer 。
- 响应拦截器
- 无 code 字段时按成功透传并包装为 {success:true, code:0, message:'', data}。
- code===0 视为成功,直接返回原 response。
- 业务错误:构造 Error 并附加 code、data、success=false。
- 认证错误:401/40101 时清除会话并跳转登录页,附带 reason=expired 或 session-replaced。
- 网络异常:区分超时与一般网络错误;当无 status 或 status>=500 时统一弹出全局 Message 并标记 tosted=true,避免与已有消息重复。
- 便捷方法
- post(path, data, config) 返回 response.data,简化调用方使用。
flowchart TD
Start(["进入响应拦截器"]) --> CheckCode{"响应体是否有code?"}
CheckCode --> |否| WrapSuccess["包装为ApiResult(success=true)"]
CheckCode --> |是| SuccessCheck{"code===0 ?"}
SuccessCheck --> |是| ReturnResp["返回原response"]
SuccessCheck --> |否| AuthCheck{"是否认证错误(401/40101)?"}
AuthCheck --> |是| HandleAuth["clearSession + 跳转登录"]
AuthCheck --> |否| ThrowBizErr["抛业务错误Error(code/message/data/success=false)"]
ReturnResp --> End(["结束"])
ThrowBizErr --> End
HandleAuth --> End
图表来源
章节来源
API 接口(api.js)
- 模块化设计
- 认证:loginApi
- 数据访问:loadDataApi、loadDataBySqlApi、pageDataApi
- 数据变更:saveObjectApi
- 标识与编码:nextIdApi、nextCodeApi
- 元信息:describeApi
- 参数约定
- 统一通过 http.post 发送 JSON;分页默认 page_no=1、page_size=20。
- 模块编号 moduleId 在 nextCodeApi 中转为字符串。
- 测试覆盖
- 针对每个接口的请求路径与参数进行断言,确保契约稳定。
graph LR
P["页面/组件"] --> L["api.js"]
L --> H["http.post"]
H --> S["后端接口"]
图表来源
章节来源
文件服务(fileService.js)
- 存储模式
- initFileConfig 调用 /file/config 获取 storageType(local 或 aliyun-oss),并在模块级缓存。
- 上传流程
- Local:一次性 FormData 打包多个文件,POST /file/upload,后端写磁盘并插入记录。
- OSS:共享凭证 → 逐个 XHR 直传到 OSS host → 逐个 POST /file/save-record 写入元数据。
- 凭证缓存
- getOssCredential 缓存最近一次凭证,credExpiring 根据 expire/Expiration 或 fetchedAt 计算是否过期,提前 5 分钟刷新。
- 其他能力
- getPreviewUrl:返回 mx_mapfilename。
- removeFile:POST /file/delete。
- extname:提取扩展名用于对象命名。
sequenceDiagram
participant UI as "文件组件"
participant FS as "fileService.js"
participant API as "api.js"
participant HTTP as "http.js"
participant OSS as "OSS直传"
UI->>FS : upload({files,father,moduleId,cateId})
FS->>FS : initFileConfig()
alt storageType === 'aliyun-oss'
FS->>FS : getOssCredential()
loop 逐个文件
FS->>API : nextIdApi()
API->>HTTP : post('/data/nextid')
HTTP-->>API : id
API-->>FS : id
FS->>OSS : XHR直传(key,policy,signature,file)
OSS-->>FS : 返回URL
FS->>API : post('/file/save-record', record)
API->>HTTP : post('/file/save-record')
HTTP-->>API : 成功
API-->>FS : 成功
end
else storageType === 'local'
FS->>API : post('/file/upload', FormData)
API->>HTTP : post('/file/upload')
HTTP-->>API : List<Map>
API-->>FS : 结果
end
FS-->>UI : 文件记录列表
图表来源
章节来源
组件集成(FmsFile.vue)
- 通过 loadDataApi 解析模块 ID,加载分类树与文件列表。
- 事件代理 uploaded/deleted/selected,便于上层处理。
- 与 fileService 配合完成上传、预览、删除等操作。
章节来源
依赖关系分析
- http.js 依赖 auth.js 的 Pinia store 获取 token,并在认证失败时调用 clearSession。
- api.js 仅依赖 http.js 的 post,保持轻量与高内聚。
- fileService.js 依赖 http.js 的 post 与 api.js 的 nextIdApi,形成“文件服务 -> 数据服务 -> HTTP”的层次。
- FmsFile.vue 作为 UI 入口,组合 api.js 与 fileService.js 的能力。
graph TB
F["FmsFile.vue"] --> A["api.js"]
F --> S["fileService.js"]
A --> H["http.js"]
S --> H
S --> A
H --> U["auth.js"]
图表来源
章节来源
性能与并发
- 请求超时与重试
- 当前未实现全局重试;可在 http.js 中引入重试策略(如指数退避)以提升弱网稳定性。
- 并发控制
- 当前未实现全局并发限制;对于大量文件上传场景,可在 fileService.js 中对 OSS 直传增加并发度控制(如队列+最大并发数)。
- 缓存策略
- 凭证缓存:OSS 凭证带过期缓冲刷新,减少频繁请求。
- 页面级缓存:路由 keep-alive 通过 cacheKeyOf(fullPath) 生成唯一组件名,避免同组件不同参数的缓存冲突。
- 传输优化
- Local 模式一次性打包多文件上传,减少握手开销。
- OSS 直传绕过后端,降低服务器压力。
[本节为通用指导,不直接分析具体文件]
故障排查指南
- 认证失效
- 现象:401/40101 时自动清空会话并跳转登录页。
- 排查:检查 token 是否存在、是否过期;确认后端返回码;查看跳转 URL 是否携带 reason。
- 参考:http.js:34-38、http.spec.js:101-157
- 网络异常
- 现象:ECONNABORTED 提示“请求超时”,其他网络错误提示“网络异常”。
- 排查:检查网络连通性、后端可用性;关注是否出现 tosted 标记的全局错误提示。
- 参考:http.js:85-103、http.spec.js:159-200
- 业务错误
- 现象:后端返回非 0 的 code,错误信息优先使用后端 message。
- 排查:在调用处捕获 Error,读取 code/message/data 进行差异化处理。
- 参考:http.js:64-74
- 文件上传失败
- 现象:OSS 直传失败或 save-record 失败。
- 排查:检查凭证是否有效、OSS 直传 host 是否正确、save-record 参数是否完整。
- 参考:fileService.js:51-85
章节来源
结论
FMS 前端服务层通过 http.js 实现了统一的请求封装与错误处理,api.js 提供了清晰分组的业务接口,fileService.js 支持灵活的本地/OSS 文件上传与凭证缓存。整体架构职责清晰、易于扩展。建议在后续迭代中补充全局重试、并发控制与更完善的日志采集,进一步提升健壮性与可观测性。
[本节为总结性内容,不直接分析具体文件]
附录
API 版本管理与向后兼容性建议
- 版本化策略
- 在 baseURL 或路径前缀中加入版本号(如 /api/v1),便于多版本并存与灰度发布。
- 在请求头中携带 clientVersion,便于服务端做兼容判断。
- 向后兼容
- 新增可选字段时保持旧字段可用;废弃字段保留一段时间并输出告警日志。
- 对关键接口增加 version 校验,不匹配时返回明确错误码与降级指引。
- 迁移与回滚
- 前端维护版本矩阵,支持按环境切换目标版本。
- 服务端提供兼容层,逐步淘汰旧逻辑。
[本节为通用指导,不直接分析具体文件]