Files
saas-mbr/abacus-static-framework/.project.agents/docs/context/ARCHITECTURE.md
T

8.0 KiB
Raw Blame History

abacus-static-framework — 架构文档(ARCHITECTURE

模块、依赖、契约、目录布局的唯一权威(本仓库视角)。新增/重命名/移动模块或调整依赖方向,必须先改本文,再改代码(同一个 commit)。 上游:PRD.md(行为)。前后端共享约束见工作区 docs/../../../../docs/coding-standards.md../../../../docs/architecture.md),本文不复制其正文。

0. 阅读指引

本文描述前端底座的模块划分与依赖方向;§2 模块清单与 §6 目录一一对应,§3.2 是跨模块接口契约(写代码必须遵守)。新会话先读 §2 + §6 定位任务归属,再动手。

1. 领域模型(Domain Model

1.1 实体

前端无持久化实体;领域概念即运行时状态:

实体 字段 关系 持久化?
用户会话(userStore access_token/refresh_token/expires_dt/user_type 全局单例 否(localStorage
菜单/路由(permissionStore routes(过滤后)、menuTree 依赖后端菜单接口 否(内存)
应用设置(settingsStore backendServices、loginType、loginAddress 来自 window.frameBaseConfig 否(运行时注入)

1.2 派生概念(非持久化)

  • backendServices 别名→真实服务名映射(window.frameBaseConfig 注入)。
  • 当前路由上下文(currentRouter())用于组装 commonParammenuName/moduleId/moduleName)。

1.3 不变量(任何模块都必须维护)

  • I1. src/framework/** 只读:业务代码不得 import 后修改框架文件;框架变更只能由框架负责人进行。
  • I2. 业务请求一律经 framework/utils/request.ts,禁止裸 axios/fetch
  • I3. 服务别名首段必须是 settingsStore.backendServices 中已注册的键。

2. 模块清单

按依赖层级从低到高排列。

Layer 0 — framework/utils(基础设施)

## 模块名:framework/utils
- 职责:请求管线(request.ts)、标准工具(standard/*vxe、dataHandleUtil、globalHandle、security、baiduMap
- 不负责:业务逻辑、页面状态
- 输入:各业务模块的请求配置
- 输出:统一响应体解包后的数据 / Blob;标准工具函数
- 关键类型/接口:request(config) -> Promise<data>gridDefaultProps(opts)useQueryParamsHandle(...)
- 持有状态:token 刷新队列(模块内闭包)、settingsStore 引用

Layer 0 — framework/components/standard(视觉基座)

## 模块名:framework/components/standard
- 职责:标准 UI 组件(AbForm/AbQueryForm/AbSection/ClickCopy/FilePreviewDialog/ImportExcel/LogShow/RealTimeSearchSelect/SensitiveText/Text/BottomFloat
- 不负责:业务特有布局(业务自建 components
- 输入:props/插槽
- 输出:统一风格组件
- 持有状态:无(受控组件)

Layer 1 — framework/store(有状态服务)

## 模块名:framework/store
- 职责:全局 Pinia 状态(settingsbackendServices/loginTypepermission:菜单生成与过滤;user:token/业务域)
- 不负责:页面级状态(业务自建 store
- 输入:window.frameBaseConfig、后端菜单接口
- 输出:状态与 actions
- 持有状态:是

Layer 2 — framework/router + hooks + directives(路由与通用逻辑)

## 模块名:framework/router + hooks + directives
- 职责:静态路由与动态路由装配支持;useVxeTableHandle 等通用组合式函数;v-debounce/v-throttle 指令
- 不负责:业务菜单路由(subsystem/router/dynamicRouter.ts
- 输入:permissionStore 过滤后的路由
- 输出:可用路由表、表格查询联动能力
- 持有状态:路由表(由 permissionStore 维护)

Layer 3 — subsystem(业务可写区)

## 模块名:subsystem
- 职责:业务子系统(api 封装、dynamicRouter 菜单路由、views 页面、extend 扩展、自建 components/hooks/store/styles/types/utils
- 不负责:框架能力(一律复用 framework)
- 输入:后端接口、用户操作
- 输出:业务页面与接口调用
- 持有状态:业务自身状态(自建 store)

3. 依赖图(DAG

graph TD
    subsystem --> framework_utils[framework/utils]
    subsystem --> framework_components[framework/components/standard]
    subsystem --> framework_hooks[framework/hooks]
    subsystem --> framework_router[framework/router]
    framework_router --> framework_store[framework/store]
    framework_hooks --> framework_utils
    framework_hooks --> framework_components
    framework_store --> framework_utils
    framework_utils --> framework_store

3.1 依赖方向规则

  • 高层依赖低层;业务(subsystem)依赖框架(framework),框架各层按上图单向;反向依赖一律禁止(如 framework 不得 import subsystem)。
  • 例外:framework/utils/request.ts 依赖 framework/storesettingsStore)获取别名映射——两者同属 framework 层,允许。

3.2 跨模块接口契约(写代码时必须遵守的签名)

// module: framework/utils/request
//   request(config: {url, method, params|data, headers?, custom?}) -> Promise<data>   // status===200 已解包 dataArrayBuffer 返回整个 response
//   url 首段 = 服务别名(I3),自动携带 token/commonParamI2

// module: framework/utils/standard/vxe
//   gridDefaultProps(opts: {params, rowConfig, pagerConfig, proxyConfig, columns}) -> VxeGridProps

// module: framework/hooks/useVxeTableHandle
//   useQueryParamsHandle(params, page, sorts, filters) -> query params   // 分页契约 {data,total},见共享规范 §6.4
//   useTableQueryReload(...) / useInVxeGridSearch(...)

4. 持久化与边界

  • 无后端式持久化;前端持久化仅 tokenlocalStorage,由 userStore 管理)。
  • 外部边界:所有 HTTP 请求必须经 request.ts;开发期经 vite proxy;运行时经 Nginx 反代;window.frameBaseConfig 由宿主页面注入(含 backendServices)。

5. 测试边界

  • 无自动化单测(PRD 已声明);每页面人工冒烟(列表/查询/新增/编辑/导出)。
  • 真机/真环境必验:多数据源路由、Kafka 消费、XXL-JOB 调度、Nacos 配置拉取、真实数据库迁移(属后端,但前端联调需一并验证)。

6. 目录结构(与 §2 模块清单一一对应)

src/
├── framework/                     # Layer 0~2(只读共享)
│   ├── api/ components/ hooks/ layout/ router/ store/ styles/ types/ utils/ views/ directives/
│   └── utils/request.ts           # 请求管线(契约见 §3.2
├── subsystem/                     # Layer 3(业务可写区)
│   ├── api/<服务别名>/            # 按 Controller 分 ts(如 sms/{index,applog,abnormal,config}.ts
│   ├── router/dynamicRouter.ts    # 菜单路由唯一注册点
│   ├── views/<一级菜单>/<二级菜单>/index.vue
│   ├── extend/                    # 框架扩展钩子
│   └── (自建) components/ hooks/ store/ styles/ types/ utils/
├── permission.ts                  # 全局路由守卫(生成/过滤动态路由)
└── main.ts                        # 入口

7. 自检(架构健康度三问)

  1. 出 bug 了,能否 30 秒内指出是 framework 还是 subsystem、哪个子目录的责任?
  2. 替换 UI 库/表格库,改动能否控制在 framework/components 与 utils/standard 内 + 适配层?
  3. 加新业务页面,能否立刻说出落在 subsystem/views/<一级>/<二级>/ 哪个位置?

8. 待办与已知技术负债

  • 前端 README 引用的 docs/ 文档中心已补齐(../../../../docs/)。
  • 旧框架兼容入口 externalOldERPIndex(data.js)仅在需要兼容历史模块时配置。

9. 文档变更协议

  • 加/删模块或改依赖方向 → 改本文 §2 + §3,同一 commit。
  • 改对外签名(request/gridDefaultProps 等)→ 先改 §3.2,再改代码。
  • PRD.md 冲突 → 以 PRD.md 为准,回改本文;与共享 docs/coding-standards.md 冲突 → 以 docs/ 为准并回改本文。