Become a sponsor

概述
项目有三个"基座"承担复用:repository.Base(数据访问红线入口)、ModuleSpec(声明式 CRUD)、dto 公共结构(分页/时间/空响应)。跨模块协作靠同包直调与 init 注册的接线机制。
// 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) 自动复用。
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 声明速查。
钩子使用约束:错误原样上抛;禁 HTTP/文件 IO;禁 append(可就地改元素);data 已含 ToData 结果与自动补齐的审计字段。
| 结构 | 用途 |
|---|---|
| PageReq | 分页入参(pageNo/pageSize + GetPageNo/GetPageSize 兜底) |
| PageData[T] | 分页壳(records/total/size/current/pages;records 空时输出 []) |
| EmptyRes | 无数据响应的统一壳 |
| LocalTime | 时间输出格式化包装(NULL 输出 null) |
同包直调:service 包内模块互相引用零 import —— User.Page(ctx, req)
仓储构造:任何模块可 repository.NewDeptRepo()
字典查询:DictGetText(ctx, dictCode, value)(dict 模块对外能力)服务模块用 init 把能力注册到包级变量,中间件/钩子消费已注册能力:
| 接线点 | 注册方 | 消费方 |
|---|---|---|
| IdentityLoader / TenantLoader | auth 模块 init | JWT / Tenant 中间件 |
| LogSink | operation_log 模块 init | OperationLog 中间件 |
| SetDictLookup | dict 模块 init | ModuleSpec 字典回填 |
| 任务自注册 | task 包 init | 调度器 |
未注册不 panic——WireCheck 启动时探测三个接线点,缺失打告警并说明降级后果,支持按模块裁剪部署。
internal/task/task.go 调度器(cron 表达式 + 执行锁 + 日志)
internal/task/xxx.go 任务实现(init 自注册)
service/daemon.go DaemonInit 启动接线
service/job*.go 任务管理与日志的业务接口新增任务 = 写一个 task 文件 + init 注册,无需改调度器。
→ 4.8 横切机制