GoWind 开源生态GoWind 开源生态
首页
框架
GoWind Admin
GoWind CMS
GoWind IM
GoWind UBA
GoWind IoT
GoWind Toolkit
GoWind Quant
GitHub
首页
框架
GoWind Admin
GoWind CMS
GoWind IM
GoWind UBA
GoWind IoT
GoWind Toolkit
GoWind Quant
GitHub
  • 介绍

    • GoWind CMS 产品介绍
    • GoWind CMS 安装指南
  • 后端文档

    • CMS 后端架构总览
    • CMS 后端模块总览
    • CMS Protobuf API 定义
    • CMS 配置与部署指南
    • 后端扩展机制指南
  • 前端文档

    • CMS 前端架构
    • CMS 前端模块总览
  • 入门教程

    • 新增内容类型全栈实战教程
    • 多端 API 客户端代码生成教程
  • 核心教程

    • 内容多语言翻译实战教程
    • 内容发布工作流实战教程
    • 区块编辑器实战教程
    • Headless API 对接多端实战教程
    • 前台应用开发实战教程
  • 进阶教程

    • 多站点管理实战教程
    • 媒体资源管理实战教程
    • 评论系统实战教程
    • 事件总线架构实战教程
    • Lua 脚本扩展实战教程
  • 高阶教程

    • 权限系统实战教程
    • 双端登录安全实战教程
    • 加密与安全工具实战教程
    • 全文搜索实战教程
    • 任务调度实战教程
    • 实时消息推送实战教程
    • 性能监控实战教程
    • 字典管理系统实战教程
  • 综合教程

    • 全栈集成实战教程
    • 三服务部署实战教程

字典管理系统实战教程

GoWind CMS 内置完整的数据字典管理功能,支持字典大类和子项的层级管理,可用于内容状态、文章类型、优先级等枚举数据的统一维护。本教程讲解字典系统的架构和使用。

前置条件

  • 已阅读 CMS 后端架构总览

一、字典系统架构

1.1 什么是数据字典

数据字典用于管理系统中的枚举值和常量配置,避免在代码中硬编码:

1.2 字典 vs 枚举

对比项枚举数据字典
定义位置代码中数据库
修改成本需编译运行时
国际化需硬编码支持翻译
排序固定可调整
扩展需改代码管理后台直接增

二、数据模型

2.1 DictType(字典大类)

// dict/service/v1/dict_type.proto
message DictType {
  optional uint32 id = 1;
  optional string name = 2 [json_name = "name"];         // 字典名称
  optional string code = 3 [json_name = "code"];         // 字典编码(唯一)
  optional string description = 4 [json_name = "description"];
  optional Status status = 5;
  enum Status {
    DICT_TYPE_STATUS_ACTIVE = 0;
    DICT_TYPE_STATUS_INACTIVE = 1;
  }
  optional google.protobuf.Timestamp created_at = 100;
}

2.2 DictEntry(字典子项)

// dict/service/v1/dict_entry.proto
message DictEntry {
  optional uint32 id = 1;
  optional uint32 dict_type_id = 2 [json_name = "dictTypeId"];
  optional string label = 3;           // 显示名称
  optional string value = 4;           // 字典值
  optional uint32 sort = 5;            // 排序
  optional string css_class = 6 [json_name = "cssClass"]; // CSS 样式
  optional bool is_default = 7 [json_name = "isDefault"]; // 是否默认值
  optional Status status = 8;
  repeated DictEntryI18n i18n = 20 [json_name = "i18n"];  // 国际化
}

// 字典子项国际化
message DictEntryI18n {
  optional uint32 id = 1;
  optional uint32 dict_entry_id = 2 [json_name = "dictEntryId"];
  optional string language_code = 3 [json_name = "languageCode"];
  optional string label = 4;           // 翻译后显示名称
}

三、Admin API

3.1 字典大类接口

# 获取字典大类列表
GET /admin/v1/dict-types?page=1&pageSize=20

# 创建字典大类
POST /admin/v1/dict-types
{
  "name": "文章状态",
  "code": "post_status",
  "description": "文章发布状态"
}

# 更新
PUT /admin/v1/dict-types/1

# 删除
DELETE /admin/v1/dict-types/1

3.2 字典子项接口

# 获取子项列表(按大类筛选)
GET /admin/v1/dict-entries?dictTypeId=1

# 创建子项
POST /admin/v1/dict-entries
{
  "dictTypeId": 1,
  "label": "待审核",
  "value": "3",
  "sort": 1,
  "isDefault": false,
  "i18n": [
    { "languageCode": "zh-CN", "label": "待审核" },
    { "languageCode": "en-US", "label": "Pending Review" }
  ]
}

四、CMS 常用字典

字典编码说明子项示例
post_status文章状态草稿/待审核/已发布/已下架
comment_status评论状态待审核/已通过/已拒绝
media_type媒体类型图片/视频/音频/文档
site_theme站点主题亮色/暗色/极简/杂志
nav_type导航类型顶部导航/页脚/侧边栏
priority优先级高/中/低

五、管理后台

5.1 字典管理页面

<!-- views/system/dict/index.vue -->
<script setup lang="ts">
const activeTab = ref('types');
const selectedType = ref(null);
</script>

<template>
  <Page title="字典管理">
    <Tabs v-model:activeKey="activeTab">
      <!-- 字典大类管理 -->
      <TabPane key="types" tab="字典大类">
        <Table :data="dictTypes">
          <TableColumn title="名称" data-index="name" />
          <TableColumn title="编码" data-index="code" />
          <TableColumn title="描述" data-index="description" />
          <TableColumn title="操作">
            <template #default="{ record }">
              <Button @click="selectedType = record; activeTab = 'entries'">管理子项</Button>
            </template>
          </TableColumn>
        </Table>
      </TabPane>

      <!-- 字典子项管理 -->
      <TabPane key="entries" tab="字典子项" :disabled="!selectedType">
        <DictEntryManager :dict-type="selectedType" />
      </TabPane>
    </Tabs>
  </Page>
</template>

5.2 前端使用字典

// composable:获取字典
export function useDict(code: string, locale?: string) {
  return useQuery({
    queryKey: ['dict', code, locale],
    queryFn: () => apiClient.dictService.GetByCode({ code, locale }),
    staleTime: 5 * 60 * 1000, // 5分钟缓存
  });
}

// 组件中使用
const { data: postStatusDict } = useDict('post_status', 'zh-CN');
// postStatusDict.items = [{ label: '草稿', value: '0' }, ...]

六、缓存优化

// 字典数据变化不频繁,使用 Redis 缓存
func (s *DictService) GetByCode(ctx context.Context, code string) ([]*dictV1.DictEntry, error) {
    cacheKey := fmt.Sprintf("dict:%s", code)

    // 尝试缓存
    if cached, err := s.redis.Get(ctx, cacheKey).Result(); err == nil {
        var entries []*dictV1.DictEntry
        json.Unmarshal([]byte(cached), &entries)
        return entries, nil
    }

    // 查询数据库
    entries, err := s.dictRepo.GetByCode(ctx, code)
    if err != nil {
        return nil, err
    }

    // 写入缓存
    data, _ := json.Marshal(entries)
    s.redis.Set(ctx, cacheKey, data, 30*time.Minute)

    return entries, nil
}

// 字典更新时清除缓存
func (s *DictService) UpdateEntry(ctx context.Context, req *dictV1.UpdateDictEntryRequest) error {
    if err := s.dictRepo.UpdateEntry(ctx, req); err != nil {
        return err
    }
    s.redis.Del(ctx, fmt.Sprintf("dict:%s", req.DictTypeCode))
    return nil
}

七、检查清单

检查项说明
DictType Schema字典大类
DictEntry Schema字典子项 + 国际化
Admin API大类 + 子项 CRUD
前端页面大类管理 + 子项管理
字典使用useDict composable
缓存Redis 缓存

相关文档

  • CMS 后端架构总览
  • CMS 后端模块总览
  • 内容多语言翻译实战
Edit this page
Last Updated:: 6/21/26, 8:19 PM
Contributors: Bobo
Prev
性能监控实战教程