Files
workspace/code/fms/.qoder/repowiki/zh/content/前端架构/服务层.md
T
2026-08-23 21:02:41 +08:00

14 KiB
Raw Blame History

服务层

**本文引用的文件** - [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)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与并发
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向 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 校验,不匹配时返回明确错误码与降级指引。
  • 迁移与回滚
    • 前端维护版本矩阵,支持按环境切换目标版本。
    • 服务端提供兼容层,逐步淘汰旧逻辑。

[本节为通用指导,不直接分析具体文件]