字典枚举 (Dictionary & Enum System)
概述
字典枚举系统是ruoyi-plus-uniapp中的一个重要设计模式,用于管理系统中的各种状态值、类型码和选项数据。该系统通过枚举类的方式提供类型安全、易于维护的字典数据管理,同时支持前端组件的数据绑定和国际化。
设计理念
核心原则
- 类型安全: 使用枚举替代魔法字符串和数字
- 统一规范: 所有字典都遵循相同的设计模式
- 易于维护: 集中管理,便于修改和扩展
- 前端友好: 提供标准的标签-值对结构
- 国际化支持: 配合国际化系统使用
设计模式
所有字典枚举都遵循统一的设计模式:
java
@Getter
@AllArgsConstructor
public enum DictXxx {
ITEM1("value1", "标签1"),
ITEM2("value2", "标签2");
public static final String DICT_TYPE = "dict_type_code";
private final String value;
private final String label;
// 标准方法
public static DictXxx getByValue(String value) { }
public static DictXxx getByLabel(String label) { }
public static boolean isXxx(String value) { }
}
系统内置字典
1. 用户相关字典
用户性别 (DictUserGender)
java
@Getter
@AllArgsConstructor
public enum DictUserGender {
FEMALE("0", "女"),
MALE("1", "男"),
UNKNOWN("2", "未知");
public static final String DICT_TYPE = "sys_user_gender";
private final String value;
private final String label;
}
使用场景:
- 用户注册/编辑性别选择
- 用户列表性别显示
- 统计报表性别分组
用户类型 (UserType)
java
@Getter
@AllArgsConstructor
public enum UserType {
PC_USER("pc", "pc_user", 43200, 604800),
MOBILE_USER("mobile", "mobile_user", 172800, 2592000);
private final String deviceType;
private final String userType;
private final int activeTimeout;
private final int timeout;
}
特点:
- 针对不同设备类型的用户体系
- 包含会话超时配置
- 支持多端登录管理
2. 状态相关字典
启用状态 (DictEnableStatus)
java
@Getter
@AllArgsConstructor
public enum DictEnableStatus {
ENABLE("1", "启用"),
DISABLED("0", "禁用");
public static final String DICT_TYPE = "sys_enable_status";
// 便捷方法
public static boolean isEnabled(String value) {
return ENABLE.getValue().equals(value);
}
public static boolean isDisabled(String value) {
return DISABLED.getValue().equals(value);
}
}
显示设置 (DictDisplaySetting)
java
@Getter
@AllArgsConstructor
public enum DictDisplaySetting {
SHOW("1", "显示"),
HIDE("0", "隐藏");
public static boolean isShow(String value) {
return SHOW.getValue().equals(value);
}
public static boolean isHide(String value) {
return HIDE.getValue().equals(value);
}
}
逻辑标志 (DictBooleanFlag)
java
@Getter
@AllArgsConstructor
public enum DictBooleanFlag {
YES("1", "是"),
NO("0", "否");
public static boolean isYes(String value) {
return YES.getValue().equals(value);
}
public static boolean isNo(String value) {
return NO.getValue().equals(value);
}
}
3. 业务流程字典
审核状态 (DictAuditStatus)
java
@Getter
@AllArgsConstructor
public enum DictAuditStatus {
PENDING("0", "待审核"),
APPROVED("1", "通过"),
REJECTED("2", "驳回"),
DENIED("3", "拒绝");
public static final String DICT_TYPE = "sys_audit_status";
public static boolean isApproved(String value) {
return APPROVED.getValue().equals(value);
}
public static boolean isPending(String value) {
return PENDING.getValue().equals(value);
}
}
订单状态 (DictOrderStatus)
java
@Getter
@AllArgsConstructor
public enum DictOrderStatus {
PENDING("pending", "待支付"),
PAID("paid", "已支付"),
DELIVERED("delivered", "已发货"),
COMPLETED("completed", "已完成"),
CANCELLED("cancelled", "已取消"),
REFUNDED("refunded", "已退款");
// 业务逻辑方法
public boolean canPay() {
return this == PENDING;
}
public boolean canCancel() {
return this == PENDING;
}
public boolean canDeliver() {
return this == PAID;
}
public boolean canComplete() {
return this == DELIVERED;
}
public boolean canRefund() {
return this == PAID || this == DELIVERED;
}
public boolean isFinished() {
return this == COMPLETED || this == CANCELLED || this == REFUNDED;
}
}
4. 支付相关字典
支付方式 (DictPaymentMethod)
java
@Getter
@AllArgsConstructor
public enum DictPaymentMethod {
WECHAT("wechat", "微信支付"),
ALIPAY("alipay", "支付宝"),
UNIONPAY("unionpay", "银联"),
BALANCE("balance", "余额支付"),
POINTS("points", "积分抵扣");
public static final String DICT_TYPE = "sys_payment_method";
public static boolean isOnlinePayment(String value) {
return WECHAT.getValue().equals(value) ||
ALIPAY.getValue().equals(value) ||
UNIONPAY.getValue().equals(value);
}
}
5. 平台相关字典
平台类型 (DictPlatformType)
java
@Getter
@AllArgsConstructor
public enum DictPlatformType {
MP_WEIXIN("mp-weixin", "微信小程序"),
MP_OFFICIAL_ACCOUNT("mp-official-account", "微信公众号"),
MP_QQ("mp-qq", "QQ小程序"),
MP_ALIPAY("mp-alipay", "支付宝小程序"),
MP_JD("mp-jd", "京东小程序"),
MP_KUAISHOU("mp-kuaishou", "快手小程序"),
MP_LARK("mp-lark", "飞书小程序"),
MP_BAIDU("mp-baidu", "百度小程序"),
MP_TOUTIAO("mp-toutiao", "头条小程序"),
MP_XHS("mp-xhs", "小红书小程序");
public static boolean isWechatPlatform(String value) {
return MP_WEIXIN.getValue().equals(value) ||
MP_OFFICIAL_ACCOUNT.getValue().equals(value);
}
}
消息类型 (DictMessageType)
java
@Getter
@AllArgsConstructor
public enum DictMessageType {
SYSTEM("system", "系统通知"),
ACTIVITY("activity", "活动通知"),
AUDIT("audit", "审核通知"),
ACCOUNT("account", "账户通知"),
PRIVATE("private", "私信");
public static boolean isSystemLevel(String value) {
return SYSTEM.getValue().equals(value) ||
AUDIT.getValue().equals(value) ||
ACCOUNT.getValue().equals(value);
}
}
6. 系统操作字典
操作类型 (DictOperType)
java
@Getter
@AllArgsConstructor
public enum DictOperType {
INSERT("1", "新增"),
UPDATE("2", "修改"),
DELETE("3", "删除"),
GRANT("4", "授权"),
EXPORT("5", "导出"),
IMPORT("6", "导入"),
FORCE("7", "强退"),
GENCODE("8", "生成代码"),
CLEAN("9", "清空数据"),
OTHER("99", "其他");
public static final String DICT_TYPE = "sys_oper_type";
}
操作结果 (DictOperResult)
java
@Getter
@AllArgsConstructor
public enum DictOperResult {
SUCCESS("1", "成功"),
FAIL("0", "失败");
public static final String DICT_TYPE = "sys_oper_result";
}
7. 文件相关字典
文件类型 (DictFileType)
java
@Getter
@AllArgsConstructor
public enum DictFileType {
IMAGE("image", "图片"),
DOCUMENT("document", "文档"),
VIDEO("video", "视频"),
AUDIO("audio", "音频"),
ARCHIVE("archive", "压缩包"),
OTHER("other", "其他");
public static boolean isMediaFile(String value) {
return IMAGE.getValue().equals(value) ||
VIDEO.getValue().equals(value) ||
AUDIO.getValue().equals(value);
}
}
8. 通知相关字典
通知类型 (DictNoticeType)
java
@Getter
@AllArgsConstructor
public enum DictNoticeType {
NOTICE("1", "通知"),
ANNOUNCEMENT("2", "公告");
public static boolean isNotice(String value) {
return NOTICE.getValue().equals(value);
}
public static boolean isAnnouncement(String value) {
return ANNOUNCEMENT.getValue().equals(value);
}
}
通知状态 (DictNoticeStatus)
java
@Getter
@AllArgsConstructor
public enum DictNoticeStatus {
SEND_IMMEDIATELY("1", "立即发送"),
SAVE_AS_DRAFT("0", "保存为草稿");
public static boolean isSendImmediately(String value) {
return SEND_IMMEDIATELY.getValue().equals(value);
}
public static boolean isDraft(String value) {
return SAVE_AS_DRAFT.getValue().equals(value);
}
}
认证类型枚举
认证类型 (AuthType)
java
@Getter
@AllArgsConstructor
public enum AuthType {
PASSWORD(I18nKeys.User.PASSWORD_RETRY_LOCKED, I18nKeys.User.PASSWORD_RETRY_COUNT),
SMS(I18nKeys.VerifyCode.SMS_RETRY_LOCKED, I18nKeys.VerifyCode.SMS_RETRY_COUNT),
EMAIL(I18nKeys.VerifyCode.EMAIL_RETRY_LOCKED, I18nKeys.VerifyCode.EMAIL_RETRY_COUNT),
MINIAPP("", ""),
MP("", ""),
SOCIAL("", "");
private final String retryLimitExceed;
private final String retryLimitCount;
}
特点:
- 与国际化系统集成
- 包含重试限制配置
- 支持多种认证方式
配合校验使用
字典值校验注解
java
@DictPattern(dictType = "sys_user_sex", message = "性别字典值无效")
private String gender;
@DictPattern(dictType = "sys_user_status", separator = ";", message = "状态值无效")
private String statusList;
枚举值校验注解
java
@EnumPattern(type = DictUserGender.class, fieldName = "value", message = "性别值无效")
private String gender;
@EnumPattern(type = DictOrderStatus.class, fieldName = "value")
private String orderStatus;
前端使用
Vue组件绑定
vue
<template>
<el-select v-model="form.gender" placeholder="请选择性别">
<el-option
v-for="item in genderOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script>
export default {
data() {
return {
genderOptions: [
{ value: '0', label: '女' },
{ value: '1', label: '男' },
{ value: '2', label: '未知' }
]
}
}
}
</script>
字典标签组件
vue
<template>
<el-tag
:type="getTagType(status)"
:class="getTagClass(status)"
>
{{ getDictLabel('sys_user_status', status) }}
</el-tag>
</template>
最佳实践
1. 命名规范
java
// 字典枚举类命名
DictXxx // 通用字典
Dict + 业务域 + 类型名
// 示例
DictUserGender // 用户性别
DictOrderStatus // 订单状态
DictPaymentMethod // 支付方式
2. 结构规范
java
@Getter
@AllArgsConstructor
public enum DictExample {
// 枚举项定义
ITEM1("value1", "标签1"),
ITEM2("value2", "标签2");
// 字典类型常量
public static final String DICT_TYPE = "dict_type_code";
// 基础字段
private final String value;
private final String label;
// 标准查找方法
public static DictExample getByValue(String value) {
for (DictExample item : values()) {
if (item.getValue().equals(value)) {
return item;
}
}
return DEFAULT_VALUE; // 或抛出异常
}
public static DictExample getByLabel(String label) {
for (DictExample item : values()) {
if (item.getLabel().equals(label)) {
return item;
}
}
return DEFAULT_VALUE;
}
// 业务判断方法
public static boolean isSpecialType(String value) {
return ITEM1.getValue().equals(value);
}
}
3. 异常处理策略
策略一:返回默认值
java
public static DictUserGender getByValue(String value) {
for (DictUserGender gender : values()) {
if (gender.getValue().equals(value)) {
return gender;
}
}
return UNKNOWN; // 返回默认值
}
策略二:抛出异常
java
public static DictPaymentMethod getByValue(String value) {
for (DictPaymentMethod method : values()) {
if (method.getValue().equals(value)) {
return method;
}
}
throw new ServiceException(StringUtils.format("不支持的支付类型:{}", value));
}
4. 业务逻辑集成
java
// 在枚举中包含业务逻辑
public enum DictOrderStatus {
// ...枚举定义
// 业务状态判断
public boolean canPay() {
return this == PENDING;
}
// 状态流转验证
public boolean canTransitionTo(DictOrderStatus target) {
return switch (this) {
case PENDING -> target == PAID || target == CANCELLED;
case PAID -> target == DELIVERED || target == REFUNDED;
case DELIVERED -> target == COMPLETED;
default -> false;
};
}
}
5. 缓存优化
java
// 使用静态缓存提高查找性能
public enum DictExample {
// 枚举定义...
private static final Map<String, DictExample> VALUE_MAP =
Arrays.stream(values())
.collect(Collectors.toMap(DictExample::getValue, Function.identity()));
public static DictExample getByValue(String value) {
return VALUE_MAP.getOrDefault(value, DEFAULT_VALUE);
}
}
扩展字典
1. 添加新字典
java
@Getter
@AllArgsConstructor
public enum DictCustomType {
TYPE1("1", "类型1"),
TYPE2("2", "类型2");
public static final String DICT_TYPE = "custom_type";
private final String value;
private final String label;
// 实现标准方法...
}
2. 复杂字典支持
java
@Getter
@AllArgsConstructor
public enum DictComplexType {
ITEM1("value1", "标签1", "描述1", "#ff0000"),
ITEM2("value2", "标签2", "描述2", "#00ff00");
private final String value;
private final String label;
private final String description;
private final String color;
// 扩展查找方法
public static List<DictComplexType> getByColor(String color) {
return Arrays.stream(values())
.filter(item -> item.getColor().equals(color))
.collect(Collectors.toList());
}
}
3. 分组字典
java
@Getter
@AllArgsConstructor
public enum DictGroupedType {
GROUP1_ITEM1("g1_i1", "组1项1", "group1"),
GROUP1_ITEM2("g1_i2", "组1项2", "group1"),
GROUP2_ITEM1("g2_i1", "组2项1", "group2");
private final String value;
private final String label;
private final String group;
// 按组查找
public static List<DictGroupedType> getByGroup(String group) {
return Arrays.stream(values())
.filter(item -> item.getGroup().equals(group))
.collect(Collectors.toList());
}
}
国际化支持
1. 标签国际化
java
@Getter
@AllArgsConstructor
public enum DictI18nType {
ITEM1("value1", "dict.i18n.type.item1"),
ITEM2("value2", "dict.i18n.type.item2");
private final String value;
private final String labelKey; // 国际化键
public String getLocalizedLabel() {
return MessageUtils.message(labelKey);
}
}
2. 配置文件
properties
# messages_zh_CN.properties
dict.i18n.type.item1=项目1
dict.i18n.type.item2=项目2
# messages_en_US.properties
dict.i18n.type.item1=Item 1
dict.i18n.type.item2=Item 2
数据库同步
1. 字典数据初始化
sql
-- 初始化字典类型
INSERT INTO sys_dict_type (dict_type, dict_name, status)
VALUES ('sys_user_gender', '用户性别', '0');
-- 初始化字典数据
INSERT INTO sys_dict_data (dict_type, dict_label, dict_value, dict_sort, status)
VALUES
('sys_user_gender', '男', '1', 1, '0'),
('sys_user_gender', '女', '0', 2, '0'),
('sys_user_gender', '未知', '2', 3, '0');
2. 同步脚本
java
@Component
public class DictSyncService {
public void syncEnumToDatabase() {
// 遍历所有字典枚举
for (DictUserGender gender : DictUserGender.values()) {
// 同步到数据库
syncDictData(DictUserGender.DICT_TYPE,
gender.getValue(),
gender.getLabel());
}
}
}
注意事项
1. 性能考虑
- 使用静态缓存Map提高查找性能
- 避免在循环中频繁调用getByValue方法
- 考虑使用枚举序号进行比较
2. 兼容性
- 新增枚举项时考虑向后兼容
- 删除枚举项需要检查现有数据
- 修改枚举值需要同步更新数据库
3. 维护性
- 保持枚举命名的一致性
- 及时更新相关文档
- 定期检查未使用的枚举项
4. 测试覆盖
java
@Test
public void testDictUserGender() {
// 测试值查找
assertEquals(DictUserGender.MALE, DictUserGender.getByValue("1"));
assertEquals(DictUserGender.UNKNOWN, DictUserGender.getByValue("invalid"));
// 测试标签查找
assertEquals(DictUserGender.FEMALE, DictUserGender.getByLabel("女"));
// 测试业务方法
assertTrue(DictUserGender.MALE.getValue().equals("1"));
}
总结
字典枚举系统为ruoyi-plus-uniapp提供了统一、类型安全的字典数据管理方案,通过规范的设计模式和丰富的内置字典,大大提高了开发效率和代码质量。合理使用字典枚举可以有效避免魔法字符串,提升代码的可读性和维护性。