📚 系统配置
配置用于控制系统行为:站点开关、上传存储、应用接入、AI 模型参数等。它保存在 configs 表,通过 group + key 唯一定位。本页讲后台配置的读写、缓存、类型转换;选项集合性质的数据请看 数据字典。
🎯 本页目标
读完本章节后,应能掌握:
- 一个业务值应该做成配置、字典、Enum,还是写入
.env。 - 如何使用
sysConfig()读取配置、GroupedConfigService写入配置。 - 配置类型转换(image、editor、checkbox、JSON)的入库与读取规则。
- 配置缓存的失效时机与手动清理方法。
🧭 配置 / 字典 / Enum / .env 选型
| 场景 | 推荐方案 | 例子 |
|---|---|---|
| 部署环境相关,通常不让后台运营修改 | .env / config/*.php | 数据库连接、Redis、队列连接、第三方基础域名 |
| 后台可维护,会影响系统行为 | 配置 configs | 站点开关、上传大小、存储驱动、AI 开关 |
| 后台可维护,主要给表单或页面展示选项 | 数据字典 | 银行类型、用户类型、业务状态、来源渠道 |
| 代码内稳定且不希望后台随意改 | PHP Enum / 常量 | 支付状态、订单状态、终端类型、核心业务流转状态 |
经验规则:如果这个值改变后会影响“系统怎么运行”,优先考虑配置;如果它只是“页面上有哪些选项”,优先考虑字典;如果它是核心流程状态,不应被后台随意调整,优先使用 Enum。
📦 配置是什么
配置保存到 configs 表,用 group + key 唯一定位一个配置项。
例如:
| group | key | 说明 |
|---|---|---|
basics | sys_status | 站点开关 |
storage | default | 默认存储驱动 |
ai | ai_enabled | AI 总开关 |
wechat | app_id | 微信配置 |
pay | default_driver | 支付接入中的默认支付驱动 |
wechat_pay | wx_mch_id | 微信支付模块安装后维护的商户号 |
wallet | withdrawal_fee_type | 钱包模块安装后维护的提现手续费模式 |
wallet | withdrawal_fee | 钱包模块安装后维护的提现手续费 |
后台端外观配置
后台端布局、菜单与主题色由 configs.admin 分组维护。管理端启动时会优先请求 /adminapi/system/config/getConfig,拿到配置后再挂载页面并写入主题 CSS 变量;只有接口不可用时才使用前端源码中的默认配置兜底。这样可以避免先显示默认主题、再切换为后台配置主题造成的闪烁。
常用配置项:
| key | 说明 |
|---|---|
show_crumb | 是否显示面包屑 |
show_logo | 是否显示后台 Logo |
unique_opened | 侧边栏是否只展开一个菜单 |
side_width | 侧边栏宽度,单位 px |
open_multiple_tabs | 是否开启多标签页栏 |
top_menu | 是否启用顶部菜单模式 |
top_menu_hover | 顶部菜单是否支持 Hover 展开 |
theme / success_theme / warning_theme / danger_theme / info_theme | Element Plus 主题色配置,配置类型使用 color,后台以颜色选择器维护;--el-color-error 跟随 danger_theme 生成,不单独维护配置项 |
前端的 frontend/admin/src/config/setting.ts 只作为启动兜底和类型归一化来源。需要调整后台端外观时,优先在“系统配置 -> 后台端”中维护,不直接修改构建后的前端文件。
配置字段语义
| 字段 | 说明 |
|---|---|
group | 配置分组,例如 storage、ai、basics |
key | 配置键,同一分组内应唯一 |
name | 配置名称,后台表单展示用 |
type | 配置类型,例如 string、image、checkbox、editor |
value | 配置值,入库时可能是字符串、JSON、相对路径等 |
source | 选项来源,通常用于 radio、checkbox、select |
tips | 配置项提示文案 |
lock | 是否锁定,锁定后通常不允许后台随意修改 |
锁定配置与按钮权限
configs.lock 用来标记“需要更谨慎维护”的配置项。常见场景是支付、存储、AI、微信等会影响系统运行或包含敏感参数的配置。
后台系统配置页面会结合菜单按钮权限判断可操作范围:
| 权限按钮 | 权限标识 | 作用 |
|---|---|---|
| 维护配置项 | setting.system.config.edit | 允许新增、删除和维护未锁定配置项的元信息,例如名称、类型、键名、选项来源、提示文案 |
| 维护锁定配置项 | setting.system.config.manageLock | 在拥有“维护配置项”的基础上,允许维护已锁定配置项的元信息,并在配置项弹窗中调整 lock 状态 |
使用规则:
- “填写配置值”和“维护配置项”是两个概念:前者是修改当前配置的
value,后者是修改配置项本身的定义。 - 没有“维护配置项”权限时,不显示新增、删除、配置项编辑入口,也不显示配置调用信息入口。
- 有“维护配置项”权限、没有“维护锁定配置项”权限时,只能维护
lock = 0的配置项;lock = 1的配置项会显示锁定标识,并隐藏配置项编辑和删除入口。 - 同时拥有“维护配置项”和“维护锁定配置项”权限时,才可以维护锁定配置项,并调整配置项是否锁定。
lock不是配置值只读开关,也不是加密机制或后端业务安全边界;它用于约束后台是否允许维护配置项定义。真正的敏感数据仍应避免通过公开接口输出。
🔍 配置读取
业务代码不要直接散写查询配置表,优先使用全局 sysConfig()。它底层仍然走 GroupedConfigService,会保留配置缓存、类型解码和附件 URL 处理。
读取整个分组:
$storage = sysConfig('storage');读取单个配置:
$defaultDisk = sysConfig('storage', 'default', 'local');
$defaultDisk = sysConfig('storage.default', 'local');读取多个分组:
$configs = sysConfig(['basics', 'storage', 'ai']);如果需要在底层服务中做批量写入、清理缓存等更细的操作,再直接注入或调用 GroupedConfigService。
适合读取配置的位置:
- Service 中读取业务开关。
- 中间件中读取站点状态。
- 支付模块、上传、AI 等工厂类读取驱动配置。
- 用户端公开配置 Action 中输出允许前端读取的配置。
不建议在前端直接猜配置表结构。前端应该通过后端接口读取已经过滤和格式化后的配置。
✍️ 配置写入
新增或完整写入单个配置项:
app(GroupedConfigService::class)->setValue(
'basics',
'sys_status',
1,
'站点状态',
'switch'
);如果配置项已经存在,只想把 basics.sys_status 的值改为 0,不要用上面的完整写入方式,直接更新 value:
app(GroupedConfigService::class)->updateValue('basics', 'sys_status', 0);updateValue() 只修改已有配置项的 value,不会覆盖 name、type、source、tips、lock 等元信息。适合后台保存配置、脚本调整开关这类“只改值”的场景。
两种写入方式都会自动处理缓存失效:
setValue()会更新或创建group + key对应配置,并写入元信息。updateValue()只更新已有配置项的value,不存在时会返回数据不存在异常。- 清理当前配置分组缓存。
- 如果修改的是站点状态,同步清理站点状态中间件缓存。
- bump
public_config版本,让前端感知公开配置变化。
🧪 配置类型转换
Config 模型提供 decoded_value 访问器,会根据 type 把入库值转换为业务可用值。
| 类型 | 读取输出规则 |
|---|---|
image | 相对路径转公开 URL |
images | 图片数组逐项转公开 URL,后台使用多图选择器维护 |
color | 颜色值原样返回,适合 #053DC8、rgba(...) 等颜色配置 |
longtext / textarea / editor / html | 富文本中的资源地址转公开 URL |
checkbox | 逗号字符串转数组 |
| JSON 字符串 | 尝试 json_decode 为数组或对象 |
| 普通字符串 | 原样返回 |
保存 value 时模型会做反向归一化:
- 图片类型会把本站完整 URL 还原为相对路径;
images会按数组逐项处理。 - 富文本会把本站资源 URL 还原为相对路径。
- 数组会以 JSON 保存。
这意味着业务代码读取配置时应优先使用 sysConfig()、decoded_value 或 GroupedConfigService,不要直接使用原始 value 猜类型。
🧊 配置缓存
GroupedConfigService 缓存的是原始配置行,再通过 Config 模型解码输出。这样模型解码规则更新后,不会因为缓存里存了旧结构而产生不一致。
缓存 key 规则:
sunadmin:config:group:{group}实际前缀、TTL、是否启用由 config/sunadmin.php 中的 config_cache 控制:
'config_cache' => [
'enabled' => true,
'ttl' => 300,
'prefix' => 'sunadmin:config',
],修改配置后,必须清理对应分组缓存。使用 GroupedConfigService::setValue() 会自动处理;如果绕过服务直接改表,需要手动清理,否则前端或业务读取到的可能仍是旧值。
🧑💻 新增配置项流程
- 判断是否应该是后台配置,而不是
.env、字典或 Enum。 - 确定
group、key、type、默认值和展示名称。 - 后台配置页面或对应 Action 增加读取、保存逻辑。
- 业务代码通过
sysConfig()读取,不直接查表。 - 如果需要给前端读取,只通过公开配置接口输出必要字段。
- 保存后确认分组缓存和
public_config版本已刷新。 - 如需新部署环境自带该配置,同步维护 Seeder 或初始化数据。
✅ 使用建议
- 后台可配置、会影响系统行为的值使用配置。
- 稳定业务枚举优先写 PHP Enum / 常量类。
- 选项集合性质的数据用字典,详见 数据字典。
- 配置项不要无限膨胀,强业务表单数据应放业务表,不要塞进
configs。 - 涉及支付、AI、存储、微信等敏感配置时,前端公开接口只输出必要信息,不输出密钥。
