Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp6_NaiveVue/zh/core/dict.md
T
2026-10-10 19:17:02 +08:00

11 KiB
Raw Blame History

5.10 字典模块

:::tip 概述 DictService 提供字典项的读取、正反向转换与缓存管理,是字典体系的核心服务。采用两级缓存(请求级 + 持久缓存),同一请求内不重复查库,跨请求复用持久缓存。 :::

字典体系架构

┌─────────────────────────────────────────────────────────────────────┐
│                         字典体系                                     │
│                                                                     │
│  ┌──────────────────┐    ┌──────────────────┐                      │
│  │ think_dict       │    │ think_dict_item  │                      │
│  │ 字典主表         │    │ 字典项表         │                      │
│  │                  │    │                  │                      │
│  │ id               │◄───│ dict_id          │                      │
│  │ name (字典名称)  │    │ name (项名称)    │                      │
│  │ code (字典编码)  │    │ value (项值)     │                      │
│  │ remark           │    │ sort (排序)      │                      │
│  └──────────────────┘    │ note (备注)      │                      │
│                          └──────────────────┘                      │
│                                                                     │
│  ┌──────────────────┐    ┌──────────────────┐                      │
│  │ DictService      │    │ Logic 层         │                      │
│  │ 字典服务         │    │ serializeMaps    │                      │
│  │                  │    │ 自动翻译         │                      │
│  │ getText()        │    │                  │                      │
│  │ getValue()       │◄───│ 'status' =>      │                      │
│  │ getOptions()     │    │   'user_status'  │                      │
│  │ clearCache()     │    │                  │                      │
│  └──────────────────┘    └──────────────────┘                      │
└─────────────────────────────────────────────────────────────────────┘

缓存架构

请求级缓存(static::$localCache)    ← 同一请求内不重复查库
        │ 未命中
        ▼
持久缓存(cache() 门面,1小时)      ← 跨请求复用(file/redis)
        │ 未命中
        ▼
数据库查询(dict → dict_item)       ← 查询后写入两级缓存

缓存 Key 格式

缓存类型 Key 格式 存储内容
请求级 $localCache['gender'] ['1'=>'男', '2'=>'女']
请求级(完整) $localCache['full_gender'] [{id, name, value, sort, note}, ...]
持久缓存 dict_gender ['1'=>'男', '2'=>'女']
持久缓存(完整) dict_full_gender [{id, name, value, sort, note}, ...]

缓存生命周期

1. 首次查询 → 数据库 → 写入持久缓存 + 请求级缓存
2. 同一请求再次命中 → 直接返回请求级缓存(最快)
3. 不同请求命中 → 读取持久缓存(不查库)
4. 缓存过期(1小时)→ 重新查库 → 更新两级缓存
5. 字典数据变更 → 调用 clearCache() 清除 → 下次查询重新加载

核心方法

getText — 根据值获取名称(最常用)

DictService::getText('gender', 1);        // '男'
DictService::getText('user_status', 1);   // '启用'
DictService::getText('gender', '');       // ''(空值返回空字符串)
DictService::getText('gender', null);     // ''(空值返回空字符串)

用途: 列表展示时将数据库值转换为可读名称。

getValue — 根据名称反向获取值

DictService::getValue('gender', '男');    // '1'
DictService::getValue('user_status', '启用'); // '1'
DictService::getValue('gender', '');     // ''(空值返回空字符串)

用途: Excel 导入时将中文文字转换为数据库存储的数值。

getOptions — 获取下拉框选项

DictService::getOptions('gender');
// [
//     ['label' => '男', 'value' => '1'],
//     ['label' => '女', 'value' => '2'],
// ]

用途: 前端下拉框、单选框、复选框组件的数据源。

getFullItems — 获取完整字典项

DictService::getFullItems('gender');
// [
//     ['id' => 1, 'name' => '男', 'value' => '1', 'sort' => 1, 'note' => ''],
//     ['id' => 2, 'name' => '女', 'value' => '2', 'sort' => 2, 'note' => ''],
// ]

用途: 需要 id、排序、备注等完整信息的场景。

clearCache — 清除缓存

DictService::clearCache('gender');    // 清除指定字典的缓存
DictService::clearCache();            // 仅清空请求级缓存
DictService::clearAllCache();         // 清除所有字典持久缓存

方法清单

方法 说明 返回值
getText($code, $value) 值 → 名称 string
getValue($code, $text) 名称 → 值 string
getItems($code) 获取值→名称映射 array ['1'=>'男', '2'=>'女']
getOptions($code) 获取下拉框选项 array [['label'=>'男','value'=>'1'], ...]
getFullItems($code) 获取完整字典项 array [{id, name, value, sort, note}, ...]
clearCache($code?) 清除指定/请求级缓存 void
clearAllCache() 清除所有字典缓存 void

在 Logic 中使用

自动翻译(serializeMaps)

配置 serializeMaps 后,查询数据时自动补全 {字段名}Text 字段,无需手动调用 DictService:

class UserLogic extends BaseTenantLogic
{
    /**
     * 枚举显示名映射
     *
     * @var array
     */
    protected array $serializeMaps = [
        'gender' => 'gender',
        'status' => 'user_status',
    ];
}

效果:

数据库:{ gender: 1, status: 1 }
    │
    ▼ processSerializeMaps()
    │ DictService::getText('gender', 1) → '男'
    │ DictService::getText('user_status', 1) → '启用'
    ▼
前端接收:{ gender: 1, genderText: '男', status: 1, statusText: '启用' }

手动调用

// 在 Logic 或 Service 中手动调用
$genderText = DictService::getText('gender', $user['gender']);
$options = DictService::getOptions('gender');

在 Controller 中使用

获取下拉框数据

// app/controller/DictController.php

/**
 * 获取字典项下拉列表
 *
 * GET /dict/getOptions/{code}
 */
public function getOptions(string $code): Json
{
    $options = DictService::getOptions($code);
    return $this->success($options);
}

刷新字典缓存

/**
 * 刷新字典缓存
 *
 * GET /dict/refreshCache
 */
public function refreshCache(): Json
{
    DictService::clearAllCache();
    return $this->success(null, '缓存刷新成功');
}

在导入导出中使用

导入时:文字转值

// UserLogic::import()
foreach ($data as &$row) {
    // Excel 中"男" → 数据库中 1
    if (!empty($row['gender']) && !is_numeric($row['gender'])) {
        $row['gender'] = DictService::getValue('gender', $row['gender']);
    }
    // Excel 中"启用" → 数据库中 1
    if (!empty($row['status']) && !is_numeric($row['status'])) {
        $row['status'] = DictService::getValue('user_status', $row['status']);
    }
}

导出时:值转文字

// 导出表头使用 Text 后缀字段
$headers = [
    'name'       => '姓名',
    'genderText' => '性别',      // 自动翻译后的字段
    'statusText' => '状态',      // 自动翻译后的字段
];

前端集成

获取字典选项

// API
export function getDictOptions(code: string) {
  return http.request({ url: `/dict/getOptions/${code}`, method: 'GET' });
}

// 使用
const genderOptions = ref([]);
onMounted(async () => {
  genderOptions.value = await getDictOptions('gender');
});

下拉框组件

<template>
  <n-select
    v-model:value="form.gender"
    :options="genderOptions"
    placeholder="请选择性别"
  />
</template>

数据库表结构

think_dict(字典主表)

字段 类型 说明 示例
id INT 主键 1
name VARCHAR(50) 字典名称 性别
code VARCHAR(50) 字典编码(唯一) gender
remark VARCHAR(500) 备注 性别字典
... 公共字段

think_dict_item(字典项表)

字段 类型 说明 示例
id INT 主键 1
dict_id INT 字典 ID(外键) 1
name VARCHAR(50) 项名称 男
value VARCHAR(50) 项值 1
sort INT 排序 1
note VARCHAR(200) 备注
... 公共字段

字典编码规范

字典编码 名称 项值 用途
gender 性别 0=女, 1=男 用户性别
user_status 用户状态 0=禁用, 1=启用 用户账号状态
article_status 文章状态 0=草稿, 1=已发布 文章状态
tenant_status 租户状态 0=禁用, 1=启用 租户状态
example_type 案例类型 0=类型一, 1=类型二 案例分类
example_status 案例状态 0=禁用, 1=启用 案例状态

缓存管理

缓存失效时机

时机 操作 说明
字典项新增/修改/删除 DictService::clearCache($code) 清除该字典的缓存
手动刷新 GET /dict/refreshCache 清除所有字典缓存
缓存过期 自动失效 1 小时 TTL

:::warning 字典数据变更后必须刷新缓存 修改字典项后,如果不刷新缓存,前端显示的可能仍是旧数据。建议在字典管理的增删改接口中自动调用 clearCache()。 :::

安全特性

特性 说明
两级缓存 请求级 + 持久缓存,减少数据库压力
空值安全 getText/getValue 对 null/空字符串返回空字符串
类型安全 值统一转为字符串比较,避免类型松散比较问题
缓存隔离 每个字典编码独立缓存,互不影响