签入版本
This commit is contained in:
@@ -8,14 +8,15 @@
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 基类 | BaseLogic(系统共享,不隔离) |
|
||||
| Service 基类 | `BaseService`(系统共享,不隔离);读取封装 `ConfigService` |
|
||||
| 关联 | 与 ConfigItem 一对多(通过 config_id) |
|
||||
| 用途 | 网站名称、Logo、版权信息等动态配置 |
|
||||
| 缓存 | DictService 两级缓存(请求级 + Redis),减少数据库查询 |
|
||||
| 控制器 | `ConfigController`(配置组)+ `ConfigItemController`(配置项) |
|
||||
| 值处理 | `HasConfigValueProcessing` Trait:按 type 做文件迁移与 `valueList` 生成 |
|
||||
|
||||
## 数据库表结构
|
||||
|
||||
### 主表 `think_config`(配置组)
|
||||
### 主表 `laravel_config`(配置组)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
@@ -24,31 +25,25 @@
|
||||
| code | varchar(150) | 配置组编码(如 `website_config`) |
|
||||
| sort | int | 排序(升序) |
|
||||
| note | varchar(255) | 备注说明 |
|
||||
| create_user | varchar(50) | 创建人(BaseModel 自动写入) |
|
||||
| create_time | datetime | 创建时间(BaseModel 自动写入) |
|
||||
| update_user | varchar(50) | 更新人(BaseModel 自动写入) |
|
||||
| update_time | datetime | 更新时间(BaseModel 自动写入) |
|
||||
| create_user / create_time / update_user / update_time | | 审计字段(模型 Trait 自动写入) |
|
||||
| is_delete | int | 软删除标记(0=正常,1=已删除) |
|
||||
|
||||
### 子表 `think_config_item`(配置项)
|
||||
### 子表 `laravel_config_item`(配置项)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | int | 主键,自增 |
|
||||
| config_id | int | 所属配置组 ID(关联 think_config.id) |
|
||||
| config_id | int | 所属配置组 ID(关联 laravel_config.id) |
|
||||
| name | varchar(150) | 配置项名称(如「网站名称」) |
|
||||
| code | varchar(150) | 配置项编码(如 `site_name`) |
|
||||
| value | varchar(1000) | 配置值 |
|
||||
| options | text | 配置选项(JSON 格式,用于 select/radio 等类型) |
|
||||
| type | varchar(150) | 值类型(text / textarea / number / switch / image / file / select) |
|
||||
| value | text | 配置值,按 type 存相对路径、`文件名\|路径`、逗号串或富文本 HTML |
|
||||
| options | text | 选项串 `k=v,k=v`(逗号分隔),用于 radio / checkbox / select 等类型 |
|
||||
| type | varchar(150) | 表单类型:hidden / readonly / number / text / textarea / password / radio / checkbox / select / selects / icon / date / datetime / image / images / file / files / ueditor |
|
||||
| status | int | 状态(1=正常,2=停用) |
|
||||
| sort | int | 排序(升序) |
|
||||
| note | varchar(255) | 配置项备注 |
|
||||
| create_user | varchar(50) | 创建人(BaseModel 自动写入) |
|
||||
| create_time | datetime | 创建时间(BaseModel 自动写入) |
|
||||
| update_user | varchar(50) | 更新人(BaseModel 自动写入) |
|
||||
| update_time | datetime | 更新时间(BaseModel 自动写入) |
|
||||
| is_delete | int | 软删除标记(0=正常,1=已删除) |
|
||||
| create_user / create_time / update_user / update_time | | 审计字段 |
|
||||
| is_delete | int | 软删除标记 |
|
||||
|
||||
## API 接口
|
||||
|
||||
@@ -58,28 +53,92 @@
|
||||
|------|------|--------|------|
|
||||
| GET | `/api/config/page` | sys:config:page | 分页列表 |
|
||||
| GET | `/api/config/list` | sys:config:list | 全量列表 |
|
||||
| GET | `/api/config/detail/:id` | sys:config:detail | 详情 |
|
||||
| GET | `/api/config/detail/{id}` | sys:config:detail | 详情 |
|
||||
| POST | `/api/config/add` | sys:config:add | 新增 |
|
||||
| PUT | `/api/config/update` | sys:config:update | 修改 |
|
||||
| DELETE | `/api/config/delete/:id` | sys:config:delete | 删除 |
|
||||
| DELETE | `/api/config/delete/{id}` | sys:config:delete | 删除 |
|
||||
| DELETE | `/api/config/batchDelete` | sys:config:batchDelete | 批量删除 |
|
||||
|
||||
### 网站配置(快捷接口)
|
||||
|
||||
| 方法 | 路径 | 权限码 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| GET | `/api/config/web/index` | sys:config:web | 获取网站配置(按组返回所有配置项) |
|
||||
| POST | `/api/config/web/save` | sys:config:web | 保存网站配置(批量更新配置项值) |
|
||||
| GET | `/api/config/web/index` | sys:config:webIndex | 获取网站配置(按组返回所有配置项) |
|
||||
| POST | `/api/config/web/save` | sys:config:update | 保存网站配置(批量更新配置项值) |
|
||||
|
||||
### 配置项
|
||||
|
||||
| 方法 | 路径 | 权限码 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| GET | `/api/config/item/page` | sys:config:item:page | 分页列表 |
|
||||
| GET | `/api/config/item/list` | sys:config:item:list | 全量列表 |
|
||||
| GET | `/api/config/item/detail/:id` | sys:config:item:detail | 详情 |
|
||||
| POST | `/api/config/item/add` | sys:config:item:add | 新增 |
|
||||
| PUT | `/api/config/item/update` | sys:config:item:update | 修改 |
|
||||
| DELETE | `/api/config/item/delete/:id` | sys:config:item:delete | 删除 |
|
||||
| GET | `/api/config/item/page` | sys:config:page | 分页列表 |
|
||||
| GET | `/api/config/item/list` | sys:config:list | 全量列表 |
|
||||
| GET | `/api/config/item/detail/{id}` | sys:config:detail | 详情 |
|
||||
| POST | `/api/config/item/add` | sys:config:add | 新增 |
|
||||
| PUT | `/api/config/item/update` | sys:config:update | 修改 |
|
||||
| DELETE | `/api/config/item/delete/{id}` | sys:config:delete | 删除 |
|
||||
| DELETE | `/api/config/item/batchDelete` | sys:config:batchDelete | 批量删除 |
|
||||
|
||||
### 配置项详情响应
|
||||
|
||||
`GET /api/config/item/detail/{id}`:
|
||||
|
||||
- `value` — 数据库存储的原始值;
|
||||
- `valueList` — 按类型加工后的可展示值,供前端直接使用(不涉及的类型为 `null`);
|
||||
- `configCode` — 所属配置组编码。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"ok": true,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"id": 7,
|
||||
"name": "网站图集",
|
||||
"code": "website_album",
|
||||
"value": "config/20260923/110133_AtVRHXAW.png,config/20260923/110133_8ERxsPCx.png,config/20260923/110133_lYnVEf9f.png",
|
||||
"options": "",
|
||||
"configId": 1,
|
||||
"type": "images",
|
||||
"status": 1,
|
||||
"sort": 30,
|
||||
"note": "网站图集",
|
||||
"createUser": "admin",
|
||||
"createTime": "2026-09-01 10:37:35",
|
||||
"updateUser": "admin",
|
||||
"updateTime": "2026-09-01 10:37:35",
|
||||
"isDelete": 0,
|
||||
"configCode": "website_config",
|
||||
"valueList": [
|
||||
"http://cdn.example.com/config/20260923/110133_AtVRHXAW.png",
|
||||
"http://cdn.example.com/config/20260923/110133_8ERxsPCx.png",
|
||||
"http://cdn.example.com/config/20260923/110133_lYnVEf9f.png"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## value 的类型化处理
|
||||
|
||||
配置项的 `value` 随 `type` 变化,保存与读取由 `HasConfigValueProcessing` Trait 统一处理,
|
||||
`ConfigItemService`(配置项 CRUD)与 `ConfigService`(网站配置)共用。
|
||||
文件一律落在 `config/file.php` 的 `upload_dir` 下的 `config/` 子目录。
|
||||
|
||||
| type | 入库 value | 详情 value | 详情 valueList |
|
||||
|------|-----------|-----------|----------------|
|
||||
| `image` | `config/Ymd/xxx.png`(去域名 + 临时文件迁移) | 完整 URL | `null` |
|
||||
| `images` | 逗号分隔的相对路径 | 原值 | 逐个完整 URL |
|
||||
| `file` / `files` | `文件名\|相对路径`(逗号分隔) | 原值 | `文件名\|完整URL` |
|
||||
| `checkbox` | 逗号分隔原值 | 原值 | 拆分后的数组 |
|
||||
| `ueditor` | 富文本 HTML,内嵌图片迁移为 `[IMG_URL]/config/...` 占位 | 占位还原为当前 `FILE_DOMAIN_URL` | `null` |
|
||||
| 其余类型 | 原值 | 原值 | `null` |
|
||||
|
||||
处理规则:
|
||||
|
||||
- **保存**(`beforeAdd` / `beforeUpdate`):走 `save_file()` —— 去掉域名前缀、把 `temp/` 临时文件迁移到正式目录;
|
||||
富文本走 `save_content()` —— 迁移内容中的图片并写入 `[IMG_URL]` 占位;
|
||||
- **读取**:走 `get_file_url()` 补全域名;富文本把 `[IMG_URL]` 还原为 `FILE_DOMAIN_URL`;
|
||||
- 迁移失败时保留原值,不清空字段;
|
||||
- `image` 与 `ueditor` 的 `value` 直接返回可渲染值(前端回显直连 `value`),其余类型 `value` 保持原值。
|
||||
|
||||
## 使用场景
|
||||
|
||||
@@ -96,63 +155,119 @@
|
||||
|
||||
### 后端获取配置值
|
||||
|
||||
项目中没有 `ConfigService`,配置值通过 `ConfigItem` 模型直接查询:
|
||||
配置值可通过 `ConfigService`(网站配置快捷接口的封装)或 `ConfigItem` 模型直接查询:
|
||||
|
||||
```php
|
||||
<?php
|
||||
use app\model\ConfigItem;
|
||||
use app\model\Config;
|
||||
use App\Models\ConfigItem;
|
||||
use App\Models\Config;
|
||||
|
||||
// 获取单个配置项的值(按配置组 code + 配置项 code 查询)
|
||||
$value = ConfigItem::whereHas('config', function ($query) {
|
||||
$query->where('code', 'website_config')->where('is_delete', 0);
|
||||
})
|
||||
->where('code', 'site_name')
|
||||
->where('status', 1)
|
||||
->where('is_delete', 0)
|
||||
->value('value');
|
||||
// 返回:'RXThinkCMF'
|
||||
$config = Config::where('code', 'website_config')->where('is_delete', 0)->first();
|
||||
$value = $config
|
||||
? ConfigItem::where('config_id', $config->id)
|
||||
->where('code', 'site_name')
|
||||
->where('status', 1)
|
||||
->where('is_delete', 0)
|
||||
->value('value')
|
||||
: null;
|
||||
// 返回:'My CMS'
|
||||
|
||||
// 获取整个配置组的所有配置项(关联数组)
|
||||
$config = Config::where('code', 'website_config')->where('is_delete', 0)->find();
|
||||
$config = Config::where('code', 'website_config')->where('is_delete', 0)->first();
|
||||
if ($config) {
|
||||
$items = ConfigItem::where('config_id', $config->id)
|
||||
->where('status', 1)
|
||||
->where('is_delete', 0)
|
||||
->column('value', 'code');
|
||||
// 返回:['site_name' => 'RXThinkCMF', 'site_logo' => '...', 'copyright' => '...']
|
||||
->pluck('value', 'code');
|
||||
// 返回:['site_name' => 'My CMS', 'site_logo' => '...', 'copyright' => '...']
|
||||
}
|
||||
```
|
||||
|
||||
// 通过 API 获取网站配置(推荐,含类型处理和 URL 拼接)
|
||||
// GET /api/config/web/index → 返回按配置组组织的完整数据
|
||||
### 网站配置快捷服务
|
||||
|
||||
```php
|
||||
// app/Services/ConfigService.php
|
||||
public function getWebConfig(): array // GET /api/config/web/index:按组返回 configId/configName/dataList(含 param、valueList)
|
||||
public function saveWebConfig(array $data): void // POST /api/config/web/save:按编码批量回写,经 save_file / save_content 归一化
|
||||
```
|
||||
|
||||
### 前端获取配置值
|
||||
|
||||
`GET /api/config/web/index` 返回按配置组分组的配置项数组:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"configId": 1,
|
||||
"configName": "网站配置",
|
||||
"dataList": [
|
||||
{
|
||||
"id": 3, "configId": 1, "name": "网站Logo", "code": "website_logo",
|
||||
"value": "http://cdn.example.com/config/20260923/110055_w3KY8kS7.png",
|
||||
"valueList": null, "options": "", "type": "image",
|
||||
"status": 1, "sort": 10, "note": "网站Logo", "param": null
|
||||
},
|
||||
{
|
||||
"id": 7, "code": "website_album", "type": "images",
|
||||
"value": "config/20260923/110133_AtVRHXAW.png,config/20260923/110133_8ERxsPCx.png",
|
||||
"valueList": [
|
||||
"http://cdn.example.com/config/20260923/110133_AtVRHXAW.png",
|
||||
"http://cdn.example.com/config/20260923/110133_8ERxsPCx.png"
|
||||
],
|
||||
"param": null
|
||||
},
|
||||
{
|
||||
"id": 11, "code": "website_keywords", "type": "checkbox",
|
||||
"value": "1,2,5,3",
|
||||
"valueList": ["1", "2", "5", "3"],
|
||||
"options": "1=软件架构,2=官方网站",
|
||||
"param": { "1": "软件架构", "2": "官方网站" }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
取值约定:
|
||||
|
||||
- `image` 与 `ueditor` 读 `value`(返回可直接渲染的完整 URL / 富文本 HTML);
|
||||
- `images` / `files` 读 `valueList`(完整 URL 串、`文件名|完整URL` 串);
|
||||
- `radio` / `checkbox` / `select` 的候选项读 `param`(由 `options` 解析成键值对象);
|
||||
- 其余类型的 `value` 为数据库原值,拼接 `FILE_DOMAIN_URL` 即可访问。
|
||||
|
||||
```typescript
|
||||
// 获取网站配置
|
||||
// 获取网站配置(按配置组分组)
|
||||
const { data } = await http.get('/api/config/web/index')
|
||||
|
||||
// 使用配置值
|
||||
const siteName = data.site_name
|
||||
const siteLogo = data.site_logo
|
||||
data.forEach((group) => {
|
||||
group.dataList.forEach((item) => {
|
||||
// image / ueditor 取 value,images / files 取 valueList,选项类取 param
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 网站配置保存接口
|
||||
|
||||
`POST /api/config/web/save` 的请求体为「配置项编码 => 配置值」的扁平结构,
|
||||
只更新已存在的生效配置项,编码不存在时忽略;数组值(多图 / 多文件 / 复选)按逗号拼接后入库,
|
||||
文件与图片同样迁移到 `config/` 子目录。
|
||||
|
||||
```bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# 批量保存网站配置(按配置组 code 批量更新)
|
||||
# 批量保存网站配置(key 为配置项编码)
|
||||
# -----------------------------------------------------------------------------
|
||||
curl -X POST http://localhost:8000/api/config/web/save \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-d '{
|
||||
"website": {
|
||||
"site_name": "RXThinkCMF",
|
||||
"site_logo": "/uploads/logo.png",
|
||||
"copyright": "© 2026 RXThinkCMF"
|
||||
}
|
||||
"website_name": "My CMS",
|
||||
"website_logo": "http://cdn.example.com/temp/20261007/123456_a1b2c3d4.png",
|
||||
"website_album": [
|
||||
"http://cdn.example.com/temp/20261007/123456_a1b2c3d4.png",
|
||||
"http://cdn.example.com/temp/20261007/123456_e5f6a7b8.png"
|
||||
],
|
||||
"website_keywords": ["1", "2"]
|
||||
}'
|
||||
```
|
||||
|
||||
@@ -163,30 +278,32 @@ curl -X POST http://localhost:8000/api/config/web/save \
|
||||
| 数据结构 | 分组 + 配置项(一对多) | 独立参数实体 |
|
||||
| 适用场景 | 关联性强的配置(如网站配置包含多个字段) | 独立的开关、阈值 |
|
||||
| 管理界面 | 按组展示,表单式编辑 | 列表式管理 |
|
||||
| 获取方式 | `ConfigItem` 模型查询或 `/api/config/web/index` 接口 | `ParamService::getValue(code)` |
|
||||
| 缓存策略 | 两级缓存(请求级 + Redis) | 两级缓存(请求级 + Redis) |
|
||||
| 获取方式 | `ConfigItem` 模型查询或 `/api/config/web/index` 接口 | `ParamService::get(code)` |
|
||||
| 服务封装 | `ConfigService`(webIndex/webSave) | `ParamService`(带缓存) |
|
||||
|
||||
## 数据库操作示例
|
||||
|
||||
```sql
|
||||
-- 查询所有未删除的配置组
|
||||
SELECT * FROM think_config WHERE is_delete = 0 ORDER BY sort;
|
||||
SELECT * FROM laravel_config WHERE is_delete = 0 ORDER BY sort;
|
||||
|
||||
-- 查询某个配置组下的所有启用配置项
|
||||
SELECT ci.* FROM think_config_item ci
|
||||
INNER JOIN think_config c ON ci.config_id = c.id
|
||||
SELECT ci.* FROM laravel_config_item ci
|
||||
INNER JOIN laravel_config c ON ci.config_id = c.id
|
||||
WHERE c.code = 'website_config' AND ci.status = 1 AND ci.is_delete = 0
|
||||
ORDER BY ci.sort;
|
||||
|
||||
-- 直接更新配置项值
|
||||
UPDATE think_config_item SET value = '新网站名称'
|
||||
UPDATE laravel_config_item SET value = '新网站名称'
|
||||
WHERE code = 'site_name' AND config_id = (
|
||||
SELECT id FROM think_config WHERE code = 'website_config' AND is_delete = 0
|
||||
SELECT id FROM laravel_config WHERE code = 'website_config' AND is_delete = 0
|
||||
);
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [5.12 系统参数管理](/zh/core/param.html) — 独立参数实体管理
|
||||
- [5.13 系统参数管理](/zh/core/param.html) — 独立参数实体管理
|
||||
- [5.10 字典模块](/zh/core/dict.html) — 枚举/字典数据管理
|
||||
- [5.11 系统配置管理](/zh/core/config.html) — 本文档
|
||||
- [7.1 文件上传全流程](/zh/tools/upload.html) — 配置项图片/附件的上传与临时文件迁移
|
||||
- [7.3 富文本处理](/zh/tools/rich-text.html) — `[IMG_URL]` 占位符机制
|
||||
- [附录 C 配置项速查](/zh/appendix/config-reference.html) — `config/*.php` 配置文件速查(与本模块的"动态配置"不同,后者存数据库)
|
||||
|
||||
Reference in New Issue
Block a user