# 字典数据联调 :::tip 说明 字典数据通过后端字典 API 获取,前端在下拉选择器中渲染选项。字典项的 `value` 字段统一为字符串类型,前端使用时需要注意类型转换。 ::: ## 后端字典 API ### 获取字典数据 ``` GET /api/v1/dict/data/{code} ``` 返回: ```json { "code": 0, "data": [ { "id": 1, "label": "系统", "value": "0" }, { "id": 2, "label": "业务", "value": "1" } ], "msg": "操作成功", "ok": true } ``` ### 字典数据结构 | 字段 | 类型 | 说明 | |------|------|------| | `id` | number | 字典项 ID | | `label` | string | 显示文本 | | `value` | string | 值(注意:统一为字符串) | :::warning 值类型注意 字典项的 `value` 字段统一为字符串类型,即使存储的是数字。前端使用时需要注意类型转换。 ::: --- ## 序列化映射 BaseService 的 `serialize_maps` 自动将字典值映射为显示名,列表和详情接口均生效。 ### 基本用法(以 param 模块为例) ```python # src/modules/param/service.py class ParamService(BaseService): repository = ParamRepository model = Param # 字段名 → 数据字典编码 serialize_maps = {'type': 'param_type', 'status': 'param_status'} ``` `serialize_maps` 的 key 是模型字段名,value 是数据字典编码。BaseService 序列化时自动: 1. 取出模型字段的原始值(如 `type=0`) 2. 从数据字典查询对应的 label(如 `param_type` 字典中 `value='0'` 的 `label='系统'`) 3. 以 `字段名驼峰 + Text` 为 key 写入响应(如 `type` → `typeText`) ### 响应示例 模型原始数据: ``` Param(id=1, name="默认密码", code="DEFAULT_PASSWORD", value="123456", type=0, status=1, sort=1) ``` 列表/详情接口返回: ```json { "id": 1, "name": "默认密码", "code": "DEFAULT_PASSWORD", "value": "123456", "type": 0, "typeText": "系统", "status": 1, "statusText": "正常", "sort": 1, "note": null, "createUser": "管理员", "createTime": "2025-03-06 14:30:25" } ``` ### 字段命名规则 | 模型字段 | serialize_maps key | 响应字段 | 说明 | |----------|-------------------|----------|------| | `type` | `'type'` | `typeText` | snake_case → camelCase + `Text` | | `status` | `'status'` | `statusText` | 同上 | | `log_type` | `'log_type'` | `logTypeText` | 下划线也转驼峰 | | `source` | `'source'` | `sourceText` | 同上 | 转换逻辑(`src/common/utils/case_converter.py`): ```python def convert_camel_case(name: str) -> str: """snake_case → camelCase(log_type → logType)""" parts = name.split('_') return parts[0] + ''.join(word.capitalize() for word in parts[1:]) ``` ### 数据字典编码 `serialize_maps` 的 value 必须是已配置的数据字典编码。常用编码: | 字典编码 | 说明 | 字典项示例 | |----------|------|-----------| | `param_type` | 参数类型 | 0-系统, 1-业务 | | `param_status` | 参数状态 | 1-正常, 2-禁用 | | `operation_type` | 操作类型 | 0-其他, 1-新增, 2-修改, 3-删除 | | `operation_source` | 操作来源 | 0-后台, 1-前台 | | `operation_status` | 操作状态 | 0-正常, 1-异常 | | `log_type` | 日志类型 | 1-登录, 2-退出 | | `login_source` | 登录来源 | 0-后台, 1-前台 | | `login_status` | 登录状态 | 0-成功, 1-失败 | 字典编码在后台「字典管理」中配置,或通过 `scripts/seed_dict.py` 初始化。 ### 完整示例:param 模块 **后端 Service**: ```python # src/modules/param/service.py class ParamService(BaseService): repository = ParamRepository form = ParamForm status_form = ParamStatusForm model_name = "参数" # 枚举显示名:字段名 → 数据字典编码 serialize_maps = {'type': 'param_type', 'status': 'param_status'} ``` **前端 columns.ts**: ```typescript // src/views/system/param/columns.ts { title: '参数类型', key: 'type', width: 100, // 方式一:直接使用后端返回的 typeText 字段 render(record) { return h(NTag, { bordered: false, type: record.type == 0 ? 'info' : 'warning' }, { default: () => record.typeText }); }, }, { title: '状态', key: 'status', width: 100, // 方式二:直接使用后端返回的 statusText 字段 render(record) { return h(NTag, { bordered: false, type: record.status == 1 ? 'success' : 'error' }, { default: () => record.statusText }); }, }, ``` ### 其他模块示例 ```python # src/modules/operation_log/service.py serialize_maps = { 'type': 'operation_type', # typeText: "新增"/"修改"/"删除" 'source': 'operation_source', # sourceText: "后台"/"前台" 'status': 'operation_status', # statusText: "正常"/"异常" } # src/modules/login_log/service.py serialize_maps = { 'log_type': 'log_type', # logTypeText: "登录"/"退出" 'source': 'login_source', # sourceText: "后台"/"前台" 'status': 'login_status', # statusText: "成功"/"失败" } ``` --- ## 前端字典管理 ### 搜索表单中的字典选项 搜索表单中直接硬编码选项(简单场景)或通过 API 获取(动态场景): **硬编码选项(简单场景)** ```typescript // src/views/system/param/querySchemas.ts export const schemas: FormSchema[] = [ { field: 'type', component: 'Select', label: '参数类型', componentProps: { placeholder: '请选择参数类型', clearable: true, options: [ { label: '系统', value: 0 }, { label: '业务', value: 1 }, ], }, }, { field: 'status', component: 'Select', label: '状态', componentProps: { placeholder: '请选择状态', clearable: true, options: [ { label: '正常', value: 1 }, { label: '禁用', value: 2 }, ], }, }, ]; ``` **API 获取选项(动态场景)** ```typescript import { getDictItemByCode } from '@/api/common'; const typeOptions = ref([]); const statusOptions = ref([]); onMounted(async () => { const res1 = await getDictItemByCode('param_type'); typeOptions.value = res1.data; // [{ label: '系统', value: '0' }, ...] const res2 = await getDictItemByCode('param_status'); statusOptions.value = res2.data; }); const schemas: FormSchema[] = [ { field: 'type', component: 'Select', label: '参数类型', componentProps: { options: typeOptions }, }, { field: 'status', component: 'Select', label: '状态', componentProps: { options: statusOptions }, }, ]; ``` ### 前端字典 API 字典相关 API 位于 `src/api/data/dictionary.ts`: ```typescript // src/api/data/dictionary.ts import { http } from '@/utils/http/axios'; // 字典列表(分页) export function getDictList(params?) { return http.request({ url: '/dict/page', method: 'GET', params }); } // 字典项列表(分页) export function getDictItemList(params?) { return http.request({ url: '/dict/item/page', method: 'GET', params }); } ``` 按字典编码获取字典项(下拉框用)位于 `src/api/common/index.ts`: ```typescript // src/api/common/index.ts export function getDictItemByCode(code) { return http.request({ url: '/dict/item/getDictItemList/' + code, method: 'GET', }); } ``` 后端对应接口:`GET /api/v1/dict/data/{code}`(`src/modules/dictionary/dict/router.py`)。 --- ## 值类型处理 字典 value 统一为字符串,但业务字段可能为数字,需要注意转换: ```typescript // 字典选项值为字符串 const options = [ { label: '系统', value: '0' }, { label: '业务', value: '1' }, ]; // 业务字段为数字 formData.type = 0; // n-select 的 options 中 value 为字符串,绑定数字时需要转换 ``` 搜索表单中的 `options` 的 `value` 为字符串 `'0'`/`'1'`,后端 `filters` 中的 `type` 字段期望数字。前端 API 传参时自动转换。 --- ## 字典管理 ### 配置字典 在后台「字典管理」中配置字典类型和字典项: ``` 字典类型: param_type(参数类型) 字典项: - label: 系统, value: 0 - label: 业务, value: 1 字典类型: param_status(参数状态) 字典项: - label: 正常, value: 1 - label: 禁用, value: 2 ``` ### 字典类型命名规范 ``` sys_ —— 系统类字典(sys_status, sys_gender 等) param_ —— 参数类字典(param_type, param_status 等) operation_ —— 操作日志类字典(operation_type, operation_status 等) login_ —— 登录日志类字典(log_type, login_source, login_status 等) cms_ —— 内容类字典(cms_article_status 等) biz_ —— 业务类字典 ``` --- ## 联调流程 ``` 1. 后台「字典管理」中新增字典类型和字典项 2. 后端 service 设置 serialize_maps(字段名 → 字典编码) 3. 前端 columns.ts 使用 render 函数渲染状态标签(直接用 xxxText 字段) 4. 前端 querySchemas.ts 中配置搜索选项(硬编码或 API 获取) 5. 表单提交时 value 为字符串,后端存储时注意类型处理 ``` --- ## 总结 字典数据联调通过后端字典 API + `serialize_maps` 映射显示名 + 前端 `render` 函数渲染标签实现。`serialize_maps` 的 value 为数据字典编码,BaseService 自动查询字典并以 `xxxText` 格式输出。字典值统一为字符串,前端使用时注意类型转换。简单场景硬编码选项,动态场景通过 API 获取。