Files
easygoadmin-wiki/EasyGoAdmin_GoFrame_EleVue/zh/architecture/extensibility.md
T
2026-10-20 21:19:44 +08:00

118 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 4.11 扩展性设计
:::tip 概述
扩展性来自两方面:一是**标准变更的操作清单**(按变更类型给出 checklist,不漏步骤、不变异架构);二是**逃生舱挂点**(基座装不下的需求有明确的合法出口)。本节按变更类型组织。
:::
## 变更类型 Checklist
### 1. 给现有模块新增一个接口
```text
□ api/v1/{模块}.go:新增 {Mod}{Action}Req(内嵌 gmeta.Meta,path 带 /api 前缀、
permission、log、logType)+ {Mod}{Action}Res
□ controller:同名方法,签名 func (c *CXxx) Action(ctx, req) (res, err)
□ service/{模块}.go:接口追加方法声明(手维护)
□ logic:实现方法(基座可表达走 spec 钩子,复杂走手写)
□ 权限节点同步:若 permission 为新码,需在菜单管理为角色勾选
(或插入 goframe_menu type=1 节点)
□ go build ./... && gofmt;重启;/api.json 核对新条目
```
### 2. 给现有模块加字段
```text
□ MySQL ALTER(列注释按枚举规范写"字段:1-x 2-y";需要唯一性则补 uk_*)
□ gf gen dao -c hack/config.yaml(刷新 entity/do/dao internal;service 不动)
□ api/v1:Req/Res/Item 结构体补字段(json 驼峰 + dc 注释)
□ logic:ToData 补键;枚举补 SerializeMaps(字典编码 {模块}_{字段});
文件字段补 FileFields+FileSaveDir;富文本补 ContentFields
□ 前端:columns.ts / querySchemas.ts / edit.vue 同步
□ document/ 五方言脚本同步;必要时附录表清单更新
□ go build → 重启 → page/detail 黄金样本更新
```
### 3. 新增模块
```text
□ 设计表(统一审计列 + del_flag + uk_* + 注释枚举)→ DDL 落库
□ 租户级?→ hooks.tenantTables 登记
□ go run ./cmd/generator -tables "goframe_x|中文名"(或手动四件套)
□ logic 调整:spec 声明(筛选/树形/字典/文件/唯一 Group)、扩展接口
□ service 接口核对;router.go 注册行确认
□ go build ./... → 重启 → 角色勾选新权限节点
```
### 4. 新增中间件
```text
□ internal/middleware/{name}.go:func(r *ghttp.Request),职责单一;
读配置用 cfgBool/cfgInt;客户端 IP 用 realClientIP;响应用 utility/response
□ 不得 import 业务包——需要业务数据时在 wire.go 增加 Loader 函数变量,
由 logic init 注册(参照 IdentityLoader 模式)
□ router.Register 的 s.Use 链按序插入(顺序即语义,评审明确插入点)
□ public 路径行为:确认对 IsPublicPath 的放行策略
```
### 5. 新增定时任务
```text
□ internal/task/{task_name}.go + init RegisterJobHandler("TaskName", h)
□ handler 签名 (ctx, params) (string, error);长任务分批+上限;禁 HTTP 于事务内
□ 任务表配置:url="TaskName"、params JSON、cron(6 段或 # 5 段)、
execute_policy/is_sync;发布(status=1)
□ 验证:daemonStatus 挂载 + runOnce + job/log 成功记录
□ go build 重启(init 注册发生在进程加载期)
```
### 6. 自定义 / 扩展 dao
```text
□ dao/{m}.go 尾部"Add your custom methods"区追加方法(统计/联查等)
□ 修改模板本身:改 hack/tpl/dao_index.tpl 后 gf gen dao 重新生成
(overwriteDao:false 保留手工扩展;新旧模板产物差异需人工合并)
□ 红线:自定义方法也必须以 Ctx(ctx) 为查询入口;禁止在 dao 内做业务判断
```
### 7. 配置变更
```text
□ manifest/config/config.yaml 修改
□ 多环境差异用 GF_ 环境变量覆盖,不改文件
□ 新增配置键:注释说明 + 代码 cfgBool/cfgInt 带默认值读取(缺失不 panic)
□ 影响限流/日志/上传/调度的键变更后跑对应回归
```
## 逃生舱与扩展挂点
| 挂点 | 场景 | 说明 |
|------|------|------|
| BodyUnmarshaler | 请求体形态不规则(平铺 map 等) | Req 实现 `UnmarshalBody(r)` 跳过默认 Parse(自行做 gvalid) |
| ModuleSpec.Filter | 复杂查询条件 | 不与 Like/Eq 重复声明 |
| ModuleSpec.DataScope | 数据权限挂点 | 共享工厂 `ApplyDataScope(col)`,声明即生效 |
| ModuleSpec 钩子装不下 | 基座禁止按模块分支 | 整个方法手写(合法逃生舱,如 job.Detail 因嵌入结构手写) |
| logic 包级共享函数 | 跨模块复用 | 放具体模块文件顶部(同包可见);横切能力进 base.go(15 导出上限) |
| RegisterJobHandler | 本地任务处理器 | 全局注册表(重名 panic) |
| middleware wire | 业务与中间件解耦 | 三 Loader/Sink 函数变量 |
## 未启用项与前端遗留
| 项 | 现状 | 启用/处理要点 |
|----|------|-------------|
| 用户注册 | publicPaths 含 /api/register(路由未注册) | 启用时补建表逻辑 + 开放策略 + 租户归属规则 |
| 数据范围自定义档 | 现四档纯列值(role.data_scope) | 第 5 档需部门关联表 + 角色表单部门树多选 |
| 导出增强 | 当前导出返回临时文件 URL | 可加流式下载/异步导出 |
| SendSms 任务 | task/send_sms.go 仅记日志 | 接短信通道时替换实现 |
| 站内信/数据源/短信/OSS/WebSocket | 前端遗留死代码(后端桩已删除) | 不再调用即无影响 |
## 封板后的变更纪律
```text
1) 一切接口行为以 API 接口清单 + /api.json 为准,改动即更新文档
2) 表结构改动三同步:document/mysql/ 定稿 → 其余四方言脚本 → 迁移(跨环境时)
3) 破坏性变更(改名/删字段/改枚举值)必须走版本化说明 + 前端同步 +
黄金样本更新,禁止静默变更
4) 架构红线复查:绕过 dao / 手写租户条件 / 反向依赖 task / 超 15 导出的 base /
未登记 tenantTables——任何一项都应打回
```