mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	1. 增加字典数据接口
2. 前端接入全局字典数据
This commit is contained in:
		| @ -59,3 +59,11 @@ export function exportData(query) { | |||||||
|     params: query |     params: query | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 查询全部字典数据列表 | ||||||
|  | export function listSimpleDictDatas() { | ||||||
|  |   return request({ | ||||||
|  |     url: '/system/dict-data/list-all-simple', | ||||||
|  |     method: 'get', | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | |||||||
| @ -18,6 +18,8 @@ router.beforeEach((to, from, next) => { | |||||||
|       NProgress.done() |       NProgress.done() | ||||||
|     } else { |     } else { | ||||||
|       if (store.getters.roles.length === 0) { |       if (store.getters.roles.length === 0) { | ||||||
|  |         // 获取字典数据 | ||||||
|  |         store.dispatch('dict/loadDictDatas') | ||||||
|         // 判断当前用户是否已拉取完user_info信息 |         // 判断当前用户是否已拉取完user_info信息 | ||||||
|         store.dispatch('GetInfo').then(res => { |         store.dispatch('GetInfo').then(res => { | ||||||
|           // 拉取user_info |           // 拉取user_info | ||||||
|  | |||||||
| @ -12,5 +12,7 @@ const getters = { | |||||||
|   permissions: state => state.user.permissions, |   permissions: state => state.user.permissions, | ||||||
|   permission_routes: state => state.permission.routes, |   permission_routes: state => state.permission.routes, | ||||||
|   sidebarRouters:state => state.permission.sidebarRouters, |   sidebarRouters:state => state.permission.sidebarRouters, | ||||||
|  |   // 数据字典 | ||||||
|  |   dict_datas: state => state.dict.dictDatas | ||||||
| } | } | ||||||
| export default getters | export default getters | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import user from './modules/user' | |||||||
| import tagsView from './modules/tagsView' | import tagsView from './modules/tagsView' | ||||||
| import permission from './modules/permission' | import permission from './modules/permission' | ||||||
| import settings from './modules/settings' | import settings from './modules/settings' | ||||||
|  | import dict from './modules/dict' | ||||||
| import getters from './getters' | import getters from './getters' | ||||||
|  |  | ||||||
| Vue.use(Vuex) | Vue.use(Vuex) | ||||||
| @ -15,7 +16,8 @@ const store = new Vuex.Store({ | |||||||
|     user, |     user, | ||||||
|     tagsView, |     tagsView, | ||||||
|     permission, |     permission, | ||||||
|     settings |     settings, | ||||||
|  |     dict | ||||||
|   }, |   }, | ||||||
|   getters |   getters | ||||||
| }) | }) | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								ruoyi-ui/src/store/modules/dict.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								ruoyi-ui/src/store/modules/dict.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | import { listSimpleDictDatas } from '@/api/system/dict/data' | ||||||
|  |  | ||||||
|  | const state = { | ||||||
|  |   /** | ||||||
|  |    * 数据字典 MAP | ||||||
|  |    * key:数据字典大类枚举值 dictType | ||||||
|  |    * dictValue:数据字典小类数值 {dictValue: '', dictLabel: ''} 的数组 | ||||||
|  |    */ | ||||||
|  |   dictDatas: {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const mutations = { | ||||||
|  |   SET_DICT_DATAS: (state, dictDatas) => { | ||||||
|  |     state.dictDatas = dictDatas | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const actions = { | ||||||
|  |   loadDictDatas({ commit }) { | ||||||
|  |     listSimpleDictDatas().then(response => { | ||||||
|  |       // 设置数据 | ||||||
|  |       const dictDataMap = {} | ||||||
|  |       response.data.forEach(dictData => { | ||||||
|  |         // 获得 dictType 层级 | ||||||
|  |         const enumValueObj = dictDataMap[dictData.dictType] | ||||||
|  |         if (!enumValueObj) { | ||||||
|  |           dictDataMap[dictData.dictType] = [] | ||||||
|  |         } | ||||||
|  |         // 处理 dictValue 层级 | ||||||
|  |         dictDataMap[dictData.dictType].push({ | ||||||
|  |           dictValue: dictData.dictValue, | ||||||
|  |           dictLabel: dictData.dictLabel | ||||||
|  |         }) | ||||||
|  |       }) | ||||||
|  |       // 存储到 Store 中 | ||||||
|  |       commit('SET_DICT_DATAS', dictDataMap) | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   namespaced: true, | ||||||
|  |   state, | ||||||
|  |   mutations, | ||||||
|  |   actions | ||||||
|  | } | ||||||
| @ -37,6 +37,7 @@ const user = { | |||||||
|       const uuid = userInfo.uuid |       const uuid = userInfo.uuid | ||||||
|       return new Promise((resolve, reject) => { |       return new Promise((resolve, reject) => { | ||||||
|         login(username, password, code, uuid).then(res => { |         login(username, password, code, uuid).then(res => { | ||||||
|  |           res = res.data; | ||||||
|           setToken(res.token) |           setToken(res.token) | ||||||
|           commit('SET_TOKEN', res.token) |           commit('SET_TOKEN', res.token) | ||||||
|           resolve() |           resolve() | ||||||
| @ -53,7 +54,6 @@ const user = { | |||||||
|           res = res.data; // 读取 data 数据 |           res = res.data; // 读取 data 数据 | ||||||
|           const user = res.user |           const user = res.user | ||||||
|           const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; |           const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; | ||||||
|           debugger |  | ||||||
|           if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 |           if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 | ||||||
|             commit('SET_ROLES', res.roles) |             commit('SET_ROLES', res.roles) | ||||||
|             commit('SET_PERMISSIONS', res.permissions) |             commit('SET_PERMISSIONS', res.permissions) | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								ruoyi-ui/src/utils/dict.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								ruoyi-ui/src/utils/dict.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | /** | ||||||
|  |  * Created by 芋道源码 | ||||||
|  |  * | ||||||
|  |  * 数据字典工具类 | ||||||
|  |  */ | ||||||
|  | import store from '@/store' | ||||||
|  |  | ||||||
|  | export const DICT_TYPE = { | ||||||
|  |   SYS_COMMON_STATUS: 'sys_common_status' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 获取 dictType 对应的数据字典数组 | ||||||
|  |  * | ||||||
|  |  * @param dictType 数据类型 | ||||||
|  |  * @returns {*|Array} 数据字典数组 | ||||||
|  |  */ | ||||||
|  | export function getDictDatas(dictType) { | ||||||
|  |   return store.getters.dict_datas[dictType] || [] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function getDictDataLabel(dictType, value) { | ||||||
|  |   // 获取 dictType 对应的数据字典数组 | ||||||
|  |   const dictDatas = getDictDatas(dictType) | ||||||
|  |   if (!dictDatas || dictDatas.length === 0) { | ||||||
|  |     return '' | ||||||
|  |   } | ||||||
|  |   // 获取 value 对应的展示名 | ||||||
|  |   value = value + '' // 强制转换成字符串,因为 DictData 小类数值,是字符串 | ||||||
|  |   for (const dictData of dictDatas) { | ||||||
|  |     if (dictData.dictValue === value) { | ||||||
|  |       return dictData.dictLabel | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return '' | ||||||
|  | } | ||||||
| @ -99,6 +99,7 @@ export default { | |||||||
|   methods: { |   methods: { | ||||||
|     getCode() { |     getCode() { | ||||||
|       getCodeImg().then(res => { |       getCodeImg().then(res => { | ||||||
|  |         res = res.data; | ||||||
|         this.codeUrl = "data:image/gif;base64," + res.img; |         this.codeUrl = "data:image/gif;base64," + res.img; | ||||||
|         this.loginForm.uuid = res.uuid; |         this.loginForm.uuid = res.uuid; | ||||||
|       }); |       }); | ||||||
|  | |||||||
| @ -211,6 +211,8 @@ import Treeselect from "@riophae/vue-treeselect"; | |||||||
| import "@riophae/vue-treeselect/dist/vue-treeselect.css"; | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; | ||||||
| import IconSelect from "@/components/IconSelect"; | import IconSelect from "@/components/IconSelect"; | ||||||
|  |  | ||||||
|  | import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict' | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: "Menu", |   name: "Menu", | ||||||
|   components: { Treeselect, IconSelect }, |   components: { Treeselect, IconSelect }, | ||||||
| @ -255,12 +257,6 @@ export default { | |||||||
|   }, |   }, | ||||||
|   created() { |   created() { | ||||||
|     this.getList(); |     this.getList(); | ||||||
|     this.getDicts("sys_show_hide").then(response => { |  | ||||||
|       this.visibleOptions = response.data; |  | ||||||
|     }); |  | ||||||
|     this.getDicts("sys_normal_disable").then(response => { |  | ||||||
|       this.statusOptions = response.data; |  | ||||||
|     }); |  | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     // 选择图标 |     // 选择图标 | ||||||
| @ -295,19 +291,9 @@ export default { | |||||||
|         this.menuOptions.push(menu); |         this.menuOptions.push(menu); | ||||||
|       }); |       }); | ||||||
|     }, |     }, | ||||||
|     // 显示状态字典翻译 |  | ||||||
|     visibleFormat(row, column) { |  | ||||||
|       if (row.menuType == "3") { |  | ||||||
|         return ""; |  | ||||||
|       } |  | ||||||
|       return this.selectDictLabel(this.visibleOptions, row.visible); |  | ||||||
|     }, |  | ||||||
|     // 菜单状态字典翻译 |     // 菜单状态字典翻译 | ||||||
|     statusFormat(row, column) { |     statusFormat(row, column) { | ||||||
|       if (row.menuType == "3") { |       return getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, row.status) | ||||||
|         return ""; |  | ||||||
|       } |  | ||||||
|       return this.selectDictLabel(this.statusOptions, row.status); |  | ||||||
|     }, |     }, | ||||||
|     // 取消按钮 |     // 取消按钮 | ||||||
|     cancel() { |     cancel() { | ||||||
|  | |||||||
| @ -0,0 +1,3 @@ | |||||||
|  | ### 请求 /menu/list 接口 => 成功 | ||||||
|  | GET {{baseUrl}}/system/dict-data/list-all-simple | ||||||
|  | Authorization: Bearer {{token}} | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.controller.dict; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.common.pojo.CommonResult; | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.dict.vo.SysDataDictSimpleVO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; | ||||||
|  | import io.swagger.annotations.Api; | ||||||
|  | import io.swagger.annotations.ApiOperation; | ||||||
|  | import org.springframework.web.bind.annotation.GetMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
|  | import javax.annotation.Resource; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||||||
|  |  | ||||||
|  | @Api(tags = "数据字典 API") | ||||||
|  | @RestController | ||||||
|  | @RequestMapping("/system/dict-data") | ||||||
|  | public class SysDictDataController { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private SysDictDataService dictDataService; | ||||||
|  |  | ||||||
|  |     @GetMapping("/list-all-simple") | ||||||
|  |     @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地") | ||||||
|  |     // 无需添加权限认证,因为前端全局都需要 | ||||||
|  |     public CommonResult<List<SysDataDictSimpleVO>> listSimpleDictDatas() { | ||||||
|  |         List<SysDictDataDO> list = dictDataService.listDictDatas(); | ||||||
|  |         return success(SysDictDataConvert.INSTANCE.convertList(list)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.controller.dict.vo; | ||||||
|  |  | ||||||
|  | import io.swagger.annotations.ApiModel; | ||||||
|  | import io.swagger.annotations.ApiModelProperty; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | @ApiModel("数据字典精简 VO") | ||||||
|  | @Data | ||||||
|  | public class SysDataDictSimpleVO { | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "字典类型", required = true, example = "gender") | ||||||
|  |     private String dictType; | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "字典键值", required = true, example = "1") | ||||||
|  |     private String dictValue; | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "字典标签", required = true, example = "男") | ||||||
|  |     private String dictLabel; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,3 +1,3 @@ | |||||||
| ### 请求 /menu/list 接口 => 成功 | ### 请求 /menu/list 接口 => 成功 | ||||||
| GET {{baseUrl}}//menu/list | GET {{baseUrl}}/system/menu/list | ||||||
| Authorization: Bearer {{token}} | Authorization: Bearer {{token}} | ||||||
|  | |||||||
| @ -19,6 +19,9 @@ public class SysMenuRespVO extends SysMenuBaseVO { | |||||||
|     @ApiModelProperty(value = "菜单编号", required = true, example = "1024") |     @ApiModelProperty(value = "菜单编号", required = true, example = "1024") | ||||||
|     private Integer menuId; |     private Integer menuId; | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") | ||||||
|  |     private Integer status; | ||||||
|  |  | ||||||
|     @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") |     @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") | ||||||
|     private Date createTime; |     private Date createTime; | ||||||
|  |  | ||||||
|  | |||||||
| @ -0,0 +1,17 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.convert.dict; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.controller.dict.vo.SysDataDictSimpleVO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||||||
|  | import org.mapstruct.Mapper; | ||||||
|  | import org.mapstruct.factory.Mappers; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | @Mapper | ||||||
|  | public interface SysDictDataConvert { | ||||||
|  |  | ||||||
|  |     SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class); | ||||||
|  |  | ||||||
|  |     List<SysDataDictSimpleVO> convertList(List<SysDictDataDO> list); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||||||
|  | import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||||
|  | import org.apache.ibatis.annotations.Mapper; | ||||||
|  |  | ||||||
|  | @Mapper | ||||||
|  | public interface SysDictDataMapper extends BaseMapper<SysDictDataDO> { | ||||||
|  | } | ||||||
| @ -19,7 +19,7 @@ import javax.validation.constraints.Size; | |||||||
| @TableName("sys_dict_data") | @TableName("sys_dict_data") | ||||||
| @Data | @Data | ||||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||||
| public class SysDictData extends BaseDO { | public class SysDictDataDO extends BaseDO { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 字典编码 |      * 字典编码 | ||||||
| @ -31,7 +31,7 @@ public class SysDictData extends BaseDO { | |||||||
|      * 字典排序 |      * 字典排序 | ||||||
|      */ |      */ | ||||||
|     @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC) |     @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC) | ||||||
|     private Long dictSort; |     private Integer dictSort; | ||||||
|     /** |     /** | ||||||
|      * 字典标签 |      * 字典标签 | ||||||
|      */ |      */ | ||||||
| @ -48,6 +48,8 @@ public class SysDictData extends BaseDO { | |||||||
|     private String dictValue; |     private String dictValue; | ||||||
|     /** |     /** | ||||||
|      * 字典类型 |      * 字典类型 | ||||||
|  |      * | ||||||
|  |      * 外键 {@link SysDictDataDO#getDictType()} | ||||||
|      */ |      */ | ||||||
|     @Excel(name = "字典类型") |     @Excel(name = "字典类型") | ||||||
|     @NotBlank(message = "字典类型不能为空") |     @NotBlank(message = "字典类型不能为空") | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.service.dict; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 字典数据 Service 接口 | ||||||
|  |  * | ||||||
|  |  * @author ruoyi | ||||||
|  |  */ | ||||||
|  | public interface SysDictDataService { | ||||||
|  |  | ||||||
|  |     List<SysDictDataDO> listDictDatas(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | package cn.iocoder.dashboard.modules.system.service.dict.impl; | ||||||
|  |  | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict.SysDictDataMapper; | ||||||
|  | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||||||
|  | import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | import javax.annotation.Resource; | ||||||
|  | import java.util.Comparator; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 字典数据 Service 实现类 | ||||||
|  |  * | ||||||
|  |  * @author ruoyi | ||||||
|  |  */ | ||||||
|  | @Service | ||||||
|  | public class SysDictDataServiceImpl implements SysDictDataService { | ||||||
|  |  | ||||||
|  |     private static final Comparator<SysDictDataDO> COMPARATOR_TYPE_AND_SORT = Comparator | ||||||
|  |             .comparing(SysDictDataDO::getDictType) | ||||||
|  |             .thenComparingInt(SysDictDataDO::getDictSort); | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private SysDictDataMapper dictDataMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public List<SysDictDataDO> listDictDatas() { | ||||||
|  |         List<SysDictDataDO> list = dictDataMapper.selectList(null); | ||||||
|  |         list.sort(COMPARATOR_TYPE_AND_SORT); | ||||||
|  |         return list; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV