277 lines
11 KiB
Markdown
277 lines
11 KiB
Markdown
:::tip 参数管理
|
||
参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。支持按参数键查询、修改,无需重启服务即可生效。本模块是典型的「BaseService 简单模块」,通过声明差异点即可获得完整 CRUD 能力。
|
||
:::
|
||
|
||
## 模块结构
|
||
|
||
```
|
||
src/modules/param/
|
||
├── models.py # 参数模型
|
||
├── schemas.py # 表单验证
|
||
├── repository.py # 数据访问层
|
||
└── service.py # 业务逻辑层(继承 BaseService)
|
||
```
|
||
|
||
## 参数模型
|
||
|
||
```python
|
||
# src/modules/param/models.py
|
||
class Param(base_model, base_db):
|
||
"""参数模型类"""
|
||
__tablename__ = DB_PREFIX + "param"
|
||
__table_comment__ = "系统参数表"
|
||
|
||
# 参数名称
|
||
name = Column(String(100), nullable=False, index=True, comment="参数名称")
|
||
# 参数编码(唯一标识,用于业务代码中按编码取值)
|
||
code = Column(String(100), nullable=False, index=True, comment="参数编码")
|
||
# 参数值
|
||
value = Column(String(255), nullable=False, comment="参数值")
|
||
# 参数类型:0-系统 1-业务
|
||
type = Column(Integer, nullable=False, comment="参数类型:0-系统 1-业务")
|
||
# 参数状态:1-正常 2-禁用
|
||
status = Column(Integer, nullable=False, index=True, comment="参数状态:1-正常 2-禁用")
|
||
# 参数排序
|
||
sort = Column(Integer, nullable=False, comment="参数排序")
|
||
# 参数备注
|
||
note = Column(String(255), nullable=True, comment="参数备注")
|
||
```
|
||
|
||
其中 `id`、`create_user`、`create_time`、`update_user`、`update_time`、`is_delete` 由基类 `base_model` 自动提供。
|
||
|
||
## 表单验证
|
||
|
||
```python
|
||
class ParamForm(BaseForm):
|
||
name: str = Field(..., min_length=1, max_length=100, description="参数名称")
|
||
code: str = Field(..., min_length=1, max_length=100, description="参数编码")
|
||
value: str = Field(..., min_length=1, max_length=255, description="参数值")
|
||
type: int = Field(..., ge=0, le=1, description="参数类型:0-系统 1-业务")
|
||
status: int = Field(..., ge=1, le=2, description="参数状态:1-正常 2-禁用")
|
||
sort: int = Field(..., ge=0, le=99999, description="参数排序")
|
||
note: Optional[str] = Field(None, max_length=255, description="参数备注")
|
||
```
|
||
|
||
| 字段 | 必填 | 约束 | 说明 |
|
||
|:----|:----|:----|:----|
|
||
| `name` | 是 | `1~100 字符` | 参数名称,唯一 |
|
||
| `code` | 是 | `1~100 字符` | 参数编码,唯一,业务代码中按此取值 |
|
||
| `value` | 是 | `1~255 字符` | 参数值,字符串类型 |
|
||
| `type` | 是 | `0~1` | 0=系统参数,1=业务参数 |
|
||
| `status` | 是 | `1~2` | 1=正常,2=禁用(注意:非 0/1) |
|
||
| `sort` | 是 | `0~99999` | 排序号,值越大越靠前 |
|
||
| `note` | 否 | `max_length=255` | 备注说明 |
|
||
|
||
:::warning status 字段的取值范围
|
||
参数模块的 `status` 使用 `1=正常, 2=禁用`,与文章模块的 `0=正常, 1=下架` 不同。这是历史约定,开发时需注意区分。
|
||
:::
|
||
|
||
## Service 层设计
|
||
|
||
### 继承 BaseService
|
||
|
||
参数模块是典型的 BaseService 简单模块,只需声明差异点即可获得完整 CRUD 能力:
|
||
|
||
```python
|
||
class ParamService(BaseService[Param]):
|
||
"""参数业务服务类,继承基础服务获得通用 CRUD 能力"""
|
||
|
||
# ============ 必须声明 ============
|
||
repo = param_repo # 数据访问层实例
|
||
model = Param # 模型类
|
||
|
||
# ============ 分页差异点 ============
|
||
page_like_fields = ('name', 'code') # 模糊搜索字段
|
||
page_eq_fields = ('type', 'status') # 等值搜索字段
|
||
page_order_by = (('sort', 'asc'), ('id', 'desc')) # 排序规则
|
||
|
||
# ============ 唯一性校验 ============
|
||
unique_fields = {
|
||
'name': '参数名称不能重复',
|
||
'code': '参数编码不能重复'
|
||
}
|
||
|
||
# ============ 枚举显示名映射 ============
|
||
serialize_maps = {
|
||
'type': 'param_type', # 参数类型 → 数据字典
|
||
'status': 'param_status' # 参数状态 → 数据字典
|
||
}
|
||
|
||
# ============ 自定义方法 ============
|
||
def get_value_by_code(self, code: str, default: Optional[str] = None) -> Optional[str]:
|
||
"""根据参数编码获取参数值"""
|
||
param = self.repo.get_one(code=code, status=1)
|
||
return param.value if param else default
|
||
```
|
||
|
||
### 差异点详解
|
||
|
||
#### page_like_fields(模糊搜索)
|
||
|
||
声明后,BaseService 自动从 `request.query_params` 中取同名参数做 `LIKE %值%` 查询:
|
||
|
||
```python
|
||
# 声明 page_like_fields = ('name', 'code') 后
|
||
# 请求 GET /api/v1/param/page?name=默认&code=PASSWORD
|
||
# 自动生成:WHERE name LIKE '%默认%' AND code LIKE '%PASSWORD%'
|
||
```
|
||
|
||
#### page_eq_fields(等值搜索)
|
||
|
||
声明后,自动取同名参数做精确匹配:
|
||
|
||
```python
|
||
# 声明 page_eq_fields = ('type', 'status') 后
|
||
# 请求 GET /api/v1/param/page?type=0&status=1
|
||
# 自动生成:WHERE type = 0 AND status = 1
|
||
```
|
||
|
||
#### page_order_by(排序规则)
|
||
|
||
```python
|
||
# 声明 page_order_by = (('sort', 'asc'), ('id', 'desc'))
|
||
# 生成:ORDER BY sort ASC, id DESC
|
||
# 即排序号越小越靠前,同排序号时新记录在前
|
||
```
|
||
|
||
#### unique_fields(唯一性校验)
|
||
|
||
```python
|
||
# 声明 unique_fields = {'name': '参数名称不能重复', 'code': '参数编码不能重复'}
|
||
# 新增时:查询是否存在同名/同编码记录
|
||
# 编辑时:查询是否存在同名/同编码记录(排除自身 ID)
|
||
# 若重复:返回 R.failed('参数名称不能重复')
|
||
```
|
||
|
||
BaseService 内部自动调用 `repo.exists_by_field(field, value, exclude_id)` 实现,无需手写校验逻辑。
|
||
|
||
#### serialize_maps(枚举显示名映射)
|
||
|
||
```python
|
||
# 声明 serialize_maps = {'type': 'param_type', 'status': 'param_status'}
|
||
# 序列化时自动调用 get_dict_map('param_type') 获取字典映射
|
||
# 输出时自动补 data['type_name'] = '系统参数' / '业务参数'
|
||
# 输出时自动补 data['status_name'] = '正常' / '禁用'
|
||
```
|
||
|
||
分页列表和详情接口均自动输出枚举名称,前端可直接展示中文。
|
||
|
||
## 按编码取值
|
||
|
||
这是参数模块的核心自定义方法,供其他业务模块调用:
|
||
|
||
```python
|
||
param_service = ParamService()
|
||
|
||
# 获取参数值(存在且状态=正常时返回值,否则返回默认值)
|
||
default_pwd = param_service.get_value_by_code("USER_DEFAULT_PASSWORD", "123456")
|
||
upload_limit = param_service.get_value_by_code("UPLOAD_MAX_SIZE", "10")
|
||
maintenance = param_service.get_value_by_code("MAINTENANCE_MODE", "0")
|
||
```
|
||
|
||
### 实现原理
|
||
|
||
```python
|
||
def get_value_by_code(self, code: str, default: Optional[str] = None) -> Optional[str]:
|
||
param = self.repo.get_one(code=code, status=1) # 按编码查询,状态必须为正常
|
||
return param.value if param else default
|
||
```
|
||
|
||
- `repo.get_one(code=code, status=1)` 自动过滤软删除记录(`is_delete=0`)
|
||
- `status=1` 确保禁用的参数不会被读取
|
||
- 未找到时返回 `default` 值,避免调用方判空
|
||
|
||
:::tip 典型用法
|
||
在其他 service 中注入参数值,实现运行时可调的业务配置:
|
||
|
||
```python
|
||
from modules.param.service import param_service
|
||
|
||
def reset_password(user_id):
|
||
# 从参数表读取默认密码,无需硬编码
|
||
default_pwd = param_service.get_value_by_code("USER_DEFAULT_PASSWORD", "123456")
|
||
# ... 重置密码逻辑
|
||
```
|
||
:::
|
||
|
||
## Repository 层
|
||
|
||
```python
|
||
class ParamRepository(BaseRepository[Param]):
|
||
"""参数数据仓库,继承基础仓库获得通用 CRUD 能力"""
|
||
pass
|
||
|
||
param_repo = ParamRepository(Param)
|
||
```
|
||
|
||
参数模块无需自定义查询方法,BaseRepository 的通用方法已满足需求。
|
||
|
||
## API 接口
|
||
|
||
| 接口 | 方法 | 权限节点 | 说明 |
|
||
|:----|:----|:----|:----|
|
||
| `/api/v1/param/page` | GET | `sys:param:page` | 分页查询(支持 name/code 模糊搜索 + type/status 精确匹配) |
|
||
| `/api/v1/param/detail/{id}` | GET | `sys:param:detail` | 详情查询 |
|
||
| `/api/v1/param/add` | POST | `sys:param:add` | 新增参数(自动校验 name/code 唯一性) |
|
||
| `/api/v1/param/update` | PUT | `sys:param:update` | 编辑参数(自动校验 name/code 唯一性,排除自身) |
|
||
| `/api/v1/param/delete/{id}` | DELETE | `sys:param:delete` | 单条删除 |
|
||
| `/api/v1/param/batchDelete` | DELETE | `sys:param:batchDelete` | 批量删除 |
|
||
|
||
### 查询参数
|
||
|
||
分页接口支持以下查询参数(BaseService 自动处理):
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|:----|:----|:----|
|
||
| `pageNo` | int | 页码,默认 1 |
|
||
| `pageSize` | int | 每页条数,默认 10 |
|
||
| `name` | string | 参数名称,模糊搜索 |
|
||
| `code` | string | 参数编码,模糊搜索 |
|
||
| `type` | int | 参数类型,精确匹配(0=系统 1=业务) |
|
||
| `status` | int | 参数状态,精确匹配(1=正常 2=禁用) |
|
||
|
||
## 数据字典
|
||
|
||
参数模块使用以下数据字典(需在字典管理中配置):
|
||
|
||
| 字典编码 | 用途 | 字典项示例 |
|
||
|:----|:----|:----|
|
||
| `param_type` | 参数类型名称 | 0=系统参数, 1=业务参数 |
|
||
| `param_status` | 参数状态名称 | 1=正常, 2=禁用 |
|
||
|
||
BaseService 的 `serialize_maps` 声明后,分页列表和详情接口自动输出 `type_name` 和 `status_name` 字段。
|
||
|
||
## 与系统配置的区别
|
||
|
||
| 特性 | 参数管理(Param) | 系统配置(Config) |
|
||
|:----|:----|:----|
|
||
| 用途 | 单个系统参数 | 配置分组 + 配置项 |
|
||
| 结构 | 扁平(name+code+value) | 两级(config + config_item) |
|
||
| 典型场景 | 默认密码、功能开关、上传限制 | SMTP 配置、站点信息、第三方服务 |
|
||
| 取值方式 | `param_service.get_value_by_code()` | `config_service.get_value_by_key()` |
|
||
| Service 模式 | BaseService 子类 | BaseService 子类 |
|
||
|
||
## 开发要点
|
||
|
||
```
|
||
1. BaseService 子类:声明差异点即可,无需手写 CRUD 逻辑
|
||
2. 唯一性校验:unique_fields 声明后自动校验 name 和 code 唯一性
|
||
3. 枚举映射:serialize_maps 声明后自动输出 type_name 和 status_name
|
||
4. 按编码取值:get_value_by_code() 是核心方法,供其他模块调用
|
||
5. 状态值注意:status 使用 1=正常 2=禁用(非 0/1),与文章模块不同
|
||
6. 排序规则:page_order_by = (('sort', 'asc'), ('id', 'desc')),排序号越小越靠前
|
||
```
|
||
|
||
## 总结
|
||
|
||
参数管理模块是项目中典型的 BaseService 简单模块,核心特点:
|
||
|
||
```
|
||
1. 继承 BaseService:声明 repo/model/page_like_fields/page_eq_fields/unique_fields/serialize_maps 即可
|
||
2. 模糊 + 等值搜索:name/code 模糊搜索,type/status 等值搜索,BaseService 自动处理
|
||
3. 唯一性校验:name 和 code 双重唯一性,BaseService 自动校验
|
||
4. 枚举映射:type 和 status 自动映射为中文名称
|
||
5. 按编码取值:get_value_by_code() 供其他业务模块调用,实现运行时可调配置
|
||
6. 软删除 + 状态过滤:get_one 自动过滤已删除和已禁用的参数
|
||
```
|