81 lines
3.3 KiB
Markdown
81 lines
3.3 KiB
Markdown
# 4.7 基座与公共体系
|
||
|
||
:::tip 概述
|
||
项目有三个"基座"承担复用:`repository.Base`(数据访问红线入口)、`ModuleSpec`(声明式 CRUD)、`dto` 公共结构(分页/时间/空响应)。跨模块协作靠同包直调与 init 注册的接线机制。
|
||
:::
|
||
|
||
## repository.Base
|
||
|
||
```go
|
||
// internal/repository/base.go
|
||
type Base struct{ table string }
|
||
|
||
func (b Base) Ctx(ctx) *gorm.DB // 唯一常规入口:注入 del_flag=0 + 租户 Scope
|
||
func (b Base) Raw(ctx) *gorm.DB // 受限入口:无 Scope,导入/字典等明确场景
|
||
func (b Base) SoftDelete(ctx, conds...) // 软删除统一入口
|
||
func (b Base) SoftDeleteByID(ctx, id)
|
||
func (b Base) ExistsByCond(ctx, conds...) (bool, error)
|
||
```
|
||
|
||
所有仓储内嵌 Base 获得能力,表名在构造时传入。事务连接经 `db.FromContext(ctx)` 自动复用。
|
||
|
||
## ModuleSpec 声明式基座
|
||
|
||
`internal/service/module_spec.go` 的泛型结构,把标准 CRUD 的全部差异点参数化:
|
||
|
||
| 类别 | 声明字段 |
|
||
|---|---|
|
||
| 查询 | Model / LikeFields / EqFields / KeywordFields / Filter / OrderBy / ListOrderBy / OrderableFields |
|
||
| 输出 | IsTree / ParentOf / ChildSetter / SerializeMaps / FileFields / MultiFileFields / ContentFields / FileSaveDir / FieldLabels |
|
||
| 规则 | UniqueFields / DataScope |
|
||
| 钩子 | Before/AfterAdd、Before/AfterUpdate、Before/AfterDelete、Before/AfterBatchDelete、AfterPageList、AfterDetail |
|
||
|
||
标准方法 Page/List/Detail/Add/Update/Delete/BatchDelete 在声明之上执行固定流水线。完整字段语义见 [附录 G ModuleSpec 声明速查](/zh/appendix/module-spec.html)。
|
||
|
||
**钩子使用约束**:错误原样上抛;禁 HTTP/文件 IO;禁 append(可就地改元素);data 已含 ToData 结果与自动补齐的审计字段。
|
||
|
||
## dto 公共结构
|
||
|
||
| 结构 | 用途 |
|
||
|---|---|
|
||
| PageReq | 分页入参(pageNo/pageSize + GetPageNo/GetPageSize 兜底) |
|
||
| PageData[T] | 分页壳(records/total/size/current/pages;records 空时输出 []) |
|
||
| EmptyRes | 无数据响应的统一壳 |
|
||
| LocalTime | 时间输出格式化包装(NULL 输出 null) |
|
||
|
||
## 跨模块协作
|
||
|
||
```text
|
||
同包直调:service 包内模块互相引用零 import —— User.Page(ctx, req)
|
||
仓储构造:任何模块可 repository.NewDeptRepo()
|
||
字典查询:DictGetText(ctx, dictCode, value)(dict 模块对外能力)
|
||
```
|
||
|
||
## init 接线机制
|
||
|
||
服务模块用 init 把能力注册到包级变量,中间件/钩子消费已注册能力:
|
||
|
||
| 接线点 | 注册方 | 消费方 |
|
||
|---|---|---|
|
||
| IdentityLoader / TenantLoader | auth 模块 init | JWT / Tenant 中间件 |
|
||
| LogSink | operation_log 模块 init | OperationLog 中间件 |
|
||
| SetDictLookup | dict 模块 init | ModuleSpec 字典回填 |
|
||
| 任务自注册 | task 包 init | 调度器 |
|
||
|
||
未注册不 panic——`WireCheck` 启动时探测三个接线点,缺失打告警并说明降级后果,支持按模块裁剪部署。
|
||
|
||
## 定时任务体系
|
||
|
||
```text
|
||
internal/task/task.go 调度器(cron 表达式 + 执行锁 + 日志)
|
||
internal/task/xxx.go 任务实现(init 自注册)
|
||
service/daemon.go DaemonInit 启动接线
|
||
service/job*.go 任务管理与日志的业务接口
|
||
```
|
||
|
||
新增任务 = 写一个 task 文件 + init 注册,无需改调度器。
|
||
|
||
## 下一步
|
||
|
||
→ [4.8 横切机制](/zh/architecture/cross-cutting.html)
|