:::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 自动过滤已删除和已禁用的参数 ```