# 基础设施:系统配置(tb_system_config) > 被依赖:需求 02(H5流程配置)、需求 09(C端支付限制) --- ## 一、设计目标 将散落在代码里的"写死配置"提取到数据库,平台管理员可通过后台页面修改,无需重新部署。 --- ## 二、数据库 ```sql -- 迁移文件:YYYYMMDD_create_tb_system_config.sql CREATE TABLE tb_system_config ( id BIGSERIAL PRIMARY KEY, config_key VARCHAR(100) NOT NULL, -- 唯一键,格式:module.group.name config_value TEXT NOT NULL DEFAULT '', -- 值(string/number/json字符串) value_type VARCHAR(20) NOT NULL DEFAULT 'string', -- string | int | bool | json module VARCHAR(50) NOT NULL DEFAULT 'general', -- 所属模块(便于按模块查询) description TEXT, -- 中文说明(前端展示用) is_readonly BOOLEAN NOT NULL DEFAULT FALSE, -- 是否只读(代码内部,不允许后台改) creator BIGINT NOT NULL DEFAULT 0, updater BIGINT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT uq_system_config_key UNIQUE (config_key) ); COMMENT ON TABLE tb_system_config IS '系统全局配置表'; -- 初始化数据 INSERT INTO tb_system_config (config_key, config_value, value_type, module, description) VALUES -- C端支付限制(需求9) ('c2b.payment.card_allowed_methods', '["alipay","wallet"]', 'json', 'c2b.payment', '卡资产C端允许的支付方式(alipay/wechat/wallet)'), ('c2b.payment.device_allowed_methods', '["wechat","wallet"]', 'json', 'c2b.payment', '设备C端允许的支付方式'), -- H5流程顺序(需求2,per-asset 覆盖,此处是全局默认) -- 注意:per-asset 的 realname_policy 已在 iot_card.realname_policy 字段存储 -- 此处仅存"H5绑定手机后的默认流程" ('h5.flow.default_realname_policy', 'after_order', 'string', 'h5.flow', 'H5新用户默认实名策略(none/before_order/after_order)'); ``` --- ## 三、Model ```go // internal/model/system_config.go // SystemConfig 系统全局配置模型 type SystemConfig struct { ID uint `gorm:"column:id;primaryKey" json:"id"` ConfigKey string `gorm:"column:config_key;uniqueIndex;not null" json:"config_key"` ConfigValue string `gorm:"column:config_value;type:text;not null;default:''" json:"config_value"` ValueType string `gorm:"column:value_type;type:varchar(20);not null;default:'string'" json:"value_type"` Module string `gorm:"column:module;type:varchar(50);not null;default:'general';index" json:"module"` Description string `gorm:"column:description;type:text" json:"description"` IsReadonly bool `gorm:"column:is_readonly;not null;default:false" json:"is_readonly"` Creator uint `gorm:"column:creator;not null;default:0" json:"creator"` Updater uint `gorm:"column:updater;not null;default:0" json:"updater"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"` } func (SystemConfig) TableName() string { return "tb_system_config" } ``` --- ## 四、Store ```go // internal/store/postgres/system_config_store.go type SystemConfigStore struct { db *gorm.DB } func (s *SystemConfigStore) GetByKey(ctx context.Context, key string) (*model.SystemConfig, error) func (s *SystemConfigStore) GetByModule(ctx context.Context, module string) ([]model.SystemConfig, error) func (s *SystemConfigStore) UpdateValue(ctx context.Context, key string, value string, updaterID uint) error func (s *SystemConfigStore) BatchGet(ctx context.Context, keys []string) (map[string]*model.SystemConfig, error) ``` --- ## 五、配置读取辅助包 业务代码不直接操作 Store,通过辅助函数读取,带 Redis 缓存(5分钟TTL): ```go // pkg/sysconfig/config.go // GetString 读取字符串配置,返回默认值 func GetString(ctx context.Context, key string, defaultVal string) string // GetStringSlice 读取 JSON 数组配置 func GetStringSlice(ctx context.Context, key string) ([]string, error) // GetBool 读取布尔配置 func GetBool(ctx context.Context, key string, defaultVal bool) bool // InvalidateCache 更新配置后清缓存(在 UpdateValue 后调用) func InvalidateCache(ctx context.Context, key string) ``` Redis Key:`sys:config:{config_key}`,TTL 5分钟。 业务代码用法: ```go // 读取卡的允许支付方式 allowedMethods, _ := sysconfig.GetStringSlice(ctx, "c2b.payment.card_allowed_methods") // 返回 ["alipay","wallet"] ``` --- ## 六、API 设计 ### 6.1 获取配置列表 ``` GET /admin/system/config?module=c2b.payment ``` 响应: ```json { "code": 0, "data": { "list": [ { "config_key": "c2b.payment.card_allowed_methods", "config_value": "[\"alipay\",\"wallet\"]", "value_type": "json", "description": "卡资产C端允许的支付方式", "is_readonly": false, "updated_at": "2026-07-11T10:00:00Z" } ] } } ``` ### 6.2 更新配置 ``` PUT /admin/system/config/{config_key} ``` 请求体: ```json { "config_value": "[\"alipay\",\"wallet\",\"wechat\"]" } ``` 权限:仅平台超管可操作。 ### DTO ```go // internal/model/dto/system_config_dto.go // SystemConfigListRequest 配置列表查询请求 type SystemConfigListRequest struct { Module string `query:"module" description:"按模块过滤(可选)"` } // SystemConfigItem 配置项响应 type SystemConfigItem struct { ConfigKey string `json:"config_key"` ConfigValue string `json:"config_value"` ValueType string `json:"value_type" description:"值类型 (string/int/bool/json)"` Module string `json:"module"` Description string `json:"description"` IsReadonly bool `json:"is_readonly"` UpdatedAt time.Time `json:"updated_at"` } // UpdateSystemConfigRequest 更新配置请求 type UpdateSystemConfigRequest struct { ConfigValue string `json:"config_value" validate:"required" description:"新配置值"` } ``` --- ## 七、前端对接 ### 页面:系统设置 > 系统配置 **初期可以做一个通用的 Key-Value 管理页面,按 module 分组展示。** 调用流程: 1. 进入页面 → `GET /admin/system/config`(不传 module = 返回全部) 2. 按 module 分组展示,`is_readonly=true` 的配置只读 3. 修改某项 → `PUT /admin/system/config/{config_key}`,body: `{config_value}` 4. 修改成功后提示"配置已更新,约5分钟后生效"(Redis 缓存 TTL) **C端支付限制配置展示建议**(针对 `c2b.payment` 模块): 不要让后台用户手动填 JSON,前端渲染成 CheckboxGroup: ``` 卡资产允许支付方式: ☑ 支付宝 ☑ 钱包 ☐ 微信 设备允许支付方式: ☐ 支付宝 ☑ 钱包 ☑ 微信 ``` 前端把选中项序列化成 `["alipay","wallet"]` 提交。