Files
wdh-home 8164eec650
Some checks failed
CI / init (push) Has been cancelled
CI / Frontend node 18.16.0 (push) Has been cancelled
CI / Backend go (1.22) (push) Has been cancelled
CI / devops-test (1.22, 18.16.0) (push) Has been cancelled
CI / release-pr (push) Has been cancelled
CI / release-please (push) Has been cancelled
CI / devops-prod (1.22, 18.x) (push) Has been cancelled
CI / docker (push) Has been cancelled
服务端
2026-04-22 15:49:50 +08:00

6.6 KiB
Raw Permalink Blame History

系统参数SysParams使用规范

适用范围

  • 需要读取或写入 sys_params 表中的系统参数时,使用本文。
  • 需要给某一个固定参数提供独立业务 API但底层仍保存到 sys_params 时,使用本文。

现有落点

  • 表结构:model/system/sys_params.go
  • Serviceservice/system/sys_params.go
  • APIapi/v1/system/sys_params.go
  • Routerrouter/system/sys_params.go

现有接口

  • 实际完整路径 = <router-prefix>/sysParams/...
  • 如果环境把 router-prefix 配成 /api,则完整路径就是 /api/sysParams/...
  • 当前仓库 config.yamlrouter-prefix 默认值为空字符串;不要把 /api 写死为项目事实。
  • 这组路由在 initialize/router.go 中挂到 PrivateGroup,默认需要鉴权。
  • GET /sysParams/getSysParam?key=xxx:按 key 读取单条参数。
  • GET /sysParams/getSysParamsList:分页读取参数列表。
  • POST /sysParams/createSysParams:创建参数。
  • PUT /sysParams/updateSysParams:按 ID 更新参数。
  • DELETE /sysParams/deleteSysParams:按 ID 删除参数。
  • 结论:这组接口适合“通用参数管理页”,不适合业务围绕某一个固定参数直接做长期读写。

强制规则

  • 后端代码禁止通过 HTTP 反调自己的 /sysParams 接口;统一在 Service 层直接调用 service.ServiceGroupApp.SystemServiceGroup.SysParamsService
  • API 层禁止直接操作 global.GVA_DB
  • Value 是字符串存储;简单值可直接存字符串,结构化配置必须由业务 Service 负责 json.Marshal / json.Unmarshal
  • 不要把 sys_paramsID 暴露给前端,作为某个固定配置的长期主键。
  • 固定配置统一按 key 识别;key 必须稳定、唯一、可读,建议使用 <module>.<scene>,例如 device.runtimeConfig
  • 参数不存在时必须显式处理:返回业务错误、初始化默认值、或创建后再返回;禁止静默吞掉。
  • 通用参数管理页面可以直接调用 /sysParams;具体业务页面优先调用该业务自己的独立 API。
  • 参数属于某个业务模块时,落点放到该业务模块;只有平台级通用参数才继续放在 system 模块。

代码内直接读取

  • 读取动作统一放在 service/<module>
  • 调用入口:
param, err := service.ServiceGroupApp.SystemServiceGroup.SysParamsService.GetSysParam("device.runtimeConfig")
  • param.Value 就是最终存储值。
  • 如果 Value 存的是 JSON必须先反序列化为业务结构体再继续使用。
package device

import (
    "encoding/json"

    "github.com/flipped-aurora/gin-vue-admin/server/service"
)

type RuntimeConfig struct {
    Enable bool   `json:"enable"`
    Mode   string `json:"mode"`
}

func (s *DeviceService) GetRuntimeConfig() (RuntimeConfig, error) {
    param, err := service.ServiceGroupApp.SystemServiceGroup.SysParamsService.GetSysParam("device.runtimeConfig")
    if err != nil {
        return RuntimeConfig{}, err
    }

    var cfg RuntimeConfig
    if err = json.Unmarshal([]byte(param.Value), &cfg); err != nil {
        return RuntimeConfig{}, err
    }

    return cfg, nil
}

代码内直接写入

  • 当前 SysParamsService 没有“按 key 直接写入”的现成能力。
  • 现在只有 CreateSysParamsUpdateSysParamsGetSysParam
  • 这意味着:业务写入固定参数时,必须先按 key 查询,再决定 create 还是 update
  • 这段逻辑必须收口到业务 Service,不要放在 API,也不要交给前端拼 ID
package device

import (
    "encoding/json"
    "errors"

    "github.com/flipped-aurora/gin-vue-admin/server/model/system"
    "github.com/flipped-aurora/gin-vue-admin/server/service"
    "gorm.io/gorm"
)

const runtimeConfigKey = "device.runtimeConfig"

func (s *DeviceService) SaveRuntimeConfig(cfg RuntimeConfig) error {
    valueBytes, err := json.Marshal(cfg)
    if err != nil {
        return err
    }

    sysParamsSvc := service.ServiceGroupApp.SystemServiceGroup.SysParamsService
    param, err := sysParamsSvc.GetSysParam(runtimeConfigKey)
    if err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            return sysParamsSvc.CreateSysParams(&system.SysParams{
                Name:  "设备运行配置",
                Key:   runtimeConfigKey,
                Value: string(valueBytes),
                Desc:  "device 模块运行配置",
            })
        }
        return err
    }

    param.Value = string(valueBytes)
    param.Name = "设备运行配置"
    param.Desc = "device 模块运行配置"
    return sysParamsSvc.UpdateSysParams(param)
}

什么时候必须写独立 API

  • 前端只关心某一个固定参数,不应该先查列表、拿 ID、再更新时。
  • 参数值是 JSON需要强类型请求体和响应体时。
  • 这个参数有明确业务语义,例如“设备运行配置”“首页配置”“第三方回调配置”时。
  • 该参数需要单独做权限控制、默认值处理、字段校验、审计说明时。

独立 API 规范

  • 独立 API 仍按 Router → API → Service → GORM → Database 分层实现。
  • 底层存储仍使用 sys_params;不要因为一个配置项就单独建表,除非它已经演变成独立业务实体。
  • 对外接口暴露业务语义,不暴露 sys_paramsID、通用 CRUD 细节。
  • Service 负责固定 key、处理 JSON 转换、决定 create/update、处理不存在时的策略。
  • 参数属于业务模块时,文件落点统一为 model/<module>/requestmodel/<module>/responseservice/<module>api/v1/<module>router/<module>
  • 新增业务路由统一注册到 initialize/router_biz.go

推荐落地方式

  • 对外提供两个独立接口即可:一个“获取配置”,一个“保存配置”。
  • 接口名使用业务语义,不使用 sysParams 命名。
  • 示例接口:GET <router-prefix>/deviceConfig/getRuntimeConfigPUT <router-prefix>/deviceConfig/updateRuntimeConfig
  • GET 接口返回业务结构体。
  • PUT 接口接收业务结构体。
  • 底层统一在 service/device 中转成 sys_params.value 的 JSON 字符串。

禁止事项

  • 禁止在业务代码里直接写 SQL 操作 sys_params,绕开现有 Service 分层。
  • 禁止在业务 API 中直接处理 sys_paramsID
  • 禁止让前端把一个固定配置当成“参数管理列表中的某一行”去长期维护。
  • 禁止把结构化 JSON 配置直接裸透传为字符串给业务页面,除非该页面本身就是通用参数管理页。