Commit dba723b8fc265ee875fb8d74a986712c237e06e6
1 parent
74daab06
1. 增加字典数据接口
2. 前端接入全局字典数据
Showing
19 changed files
with
245 additions
and
23 deletions
ruoyi-ui/src/api/system/dict/data.js
| @@ -58,4 +58,12 @@ export function exportData(query) { | @@ -58,4 +58,12 @@ export function exportData(query) { | ||
| 58 | method: 'get', | 58 | method: 'get', |
| 59 | params: query | 59 | params: query |
| 60 | }) | 60 | }) |
| 61 | -} | ||
| 62 | \ No newline at end of file | 61 | \ No newline at end of file |
| 62 | +} | ||
| 63 | + | ||
| 64 | +// 查询全部字典数据列表 | ||
| 65 | +export function listSimpleDictDatas() { | ||
| 66 | + return request({ | ||
| 67 | + url: '/system/dict-data/list-all-simple', | ||
| 68 | + method: 'get', | ||
| 69 | + }) | ||
| 70 | +} |
ruoyi-ui/src/permission.js
| @@ -18,6 +18,8 @@ router.beforeEach((to, from, next) => { | @@ -18,6 +18,8 @@ router.beforeEach((to, from, next) => { | ||
| 18 | NProgress.done() | 18 | NProgress.done() |
| 19 | } else { | 19 | } else { |
| 20 | if (store.getters.roles.length === 0) { | 20 | if (store.getters.roles.length === 0) { |
| 21 | + // 获取字典数据 | ||
| 22 | + store.dispatch('dict/loadDictDatas') | ||
| 21 | // 判断当前用户是否已拉取完user_info信息 | 23 | // 判断当前用户是否已拉取完user_info信息 |
| 22 | store.dispatch('GetInfo').then(res => { | 24 | store.dispatch('GetInfo').then(res => { |
| 23 | // 拉取user_info | 25 | // 拉取user_info |
ruoyi-ui/src/store/getters.js
| @@ -12,5 +12,7 @@ const getters = { | @@ -12,5 +12,7 @@ const getters = { | ||
| 12 | permissions: state => state.user.permissions, | 12 | permissions: state => state.user.permissions, |
| 13 | permission_routes: state => state.permission.routes, | 13 | permission_routes: state => state.permission.routes, |
| 14 | sidebarRouters:state => state.permission.sidebarRouters, | 14 | sidebarRouters:state => state.permission.sidebarRouters, |
| 15 | + // 数据字典 | ||
| 16 | + dict_datas: state => state.dict.dictDatas | ||
| 15 | } | 17 | } |
| 16 | export default getters | 18 | export default getters |
ruoyi-ui/src/store/index.js
| @@ -5,6 +5,7 @@ import user from './modules/user' | @@ -5,6 +5,7 @@ import user from './modules/user' | ||
| 5 | import tagsView from './modules/tagsView' | 5 | import tagsView from './modules/tagsView' |
| 6 | import permission from './modules/permission' | 6 | import permission from './modules/permission' |
| 7 | import settings from './modules/settings' | 7 | import settings from './modules/settings' |
| 8 | +import dict from './modules/dict' | ||
| 8 | import getters from './getters' | 9 | import getters from './getters' |
| 9 | 10 | ||
| 10 | Vue.use(Vuex) | 11 | Vue.use(Vuex) |
| @@ -15,7 +16,8 @@ const store = new Vuex.Store({ | @@ -15,7 +16,8 @@ const store = new Vuex.Store({ | ||
| 15 | user, | 16 | user, |
| 16 | tagsView, | 17 | tagsView, |
| 17 | permission, | 18 | permission, |
| 18 | - settings | 19 | + settings, |
| 20 | + dict | ||
| 19 | }, | 21 | }, |
| 20 | getters | 22 | getters |
| 21 | }) | 23 | }) |
ruoyi-ui/src/store/modules/dict.js
0 → 100644
| 1 | +import { listSimpleDictDatas } from '@/api/system/dict/data' | ||
| 2 | + | ||
| 3 | +const state = { | ||
| 4 | + /** | ||
| 5 | + * 数据字典 MAP | ||
| 6 | + * key:数据字典大类枚举值 dictType | ||
| 7 | + * dictValue:数据字典小类数值 {dictValue: '', dictLabel: ''} 的数组 | ||
| 8 | + */ | ||
| 9 | + dictDatas: {} | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +const mutations = { | ||
| 13 | + SET_DICT_DATAS: (state, dictDatas) => { | ||
| 14 | + state.dictDatas = dictDatas | ||
| 15 | + } | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +const actions = { | ||
| 19 | + loadDictDatas({ commit }) { | ||
| 20 | + listSimpleDictDatas().then(response => { | ||
| 21 | + // 设置数据 | ||
| 22 | + const dictDataMap = {} | ||
| 23 | + response.data.forEach(dictData => { | ||
| 24 | + // 获得 dictType 层级 | ||
| 25 | + const enumValueObj = dictDataMap[dictData.dictType] | ||
| 26 | + if (!enumValueObj) { | ||
| 27 | + dictDataMap[dictData.dictType] = [] | ||
| 28 | + } | ||
| 29 | + // 处理 dictValue 层级 | ||
| 30 | + dictDataMap[dictData.dictType].push({ | ||
| 31 | + dictValue: dictData.dictValue, | ||
| 32 | + dictLabel: dictData.dictLabel | ||
| 33 | + }) | ||
| 34 | + }) | ||
| 35 | + // 存储到 Store 中 | ||
| 36 | + commit('SET_DICT_DATAS', dictDataMap) | ||
| 37 | + }) | ||
| 38 | + } | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +export default { | ||
| 42 | + namespaced: true, | ||
| 43 | + state, | ||
| 44 | + mutations, | ||
| 45 | + actions | ||
| 46 | +} |
ruoyi-ui/src/store/modules/user.js
| @@ -37,6 +37,7 @@ const user = { | @@ -37,6 +37,7 @@ const user = { | ||
| 37 | const uuid = userInfo.uuid | 37 | const uuid = userInfo.uuid |
| 38 | return new Promise((resolve, reject) => { | 38 | return new Promise((resolve, reject) => { |
| 39 | login(username, password, code, uuid).then(res => { | 39 | login(username, password, code, uuid).then(res => { |
| 40 | + res = res.data; | ||
| 40 | setToken(res.token) | 41 | setToken(res.token) |
| 41 | commit('SET_TOKEN', res.token) | 42 | commit('SET_TOKEN', res.token) |
| 42 | resolve() | 43 | resolve() |
| @@ -53,7 +54,6 @@ const user = { | @@ -53,7 +54,6 @@ const user = { | ||
| 53 | res = res.data; // 读取 data 数据 | 54 | res = res.data; // 读取 data 数据 |
| 54 | const user = res.user | 55 | const user = res.user |
| 55 | const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; | 56 | const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; |
| 56 | - debugger | ||
| 57 | if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 | 57 | if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 |
| 58 | commit('SET_ROLES', res.roles) | 58 | commit('SET_ROLES', res.roles) |
| 59 | commit('SET_PERMISSIONS', res.permissions) | 59 | commit('SET_PERMISSIONS', res.permissions) |
ruoyi-ui/src/utils/dict.js
0 → 100644
| 1 | +/** | ||
| 2 | + * Created by 芋道源码 | ||
| 3 | + * | ||
| 4 | + * 数据字典工具类 | ||
| 5 | + */ | ||
| 6 | +import store from '@/store' | ||
| 7 | + | ||
| 8 | +export const DICT_TYPE = { | ||
| 9 | + SYS_COMMON_STATUS: 'sys_common_status' | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 获取 dictType 对应的数据字典数组 | ||
| 14 | + * | ||
| 15 | + * @param dictType 数据类型 | ||
| 16 | + * @returns {*|Array} 数据字典数组 | ||
| 17 | + */ | ||
| 18 | +export function getDictDatas(dictType) { | ||
| 19 | + return store.getters.dict_datas[dictType] || [] | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +export function getDictDataLabel(dictType, value) { | ||
| 23 | + // 获取 dictType 对应的数据字典数组 | ||
| 24 | + const dictDatas = getDictDatas(dictType) | ||
| 25 | + if (!dictDatas || dictDatas.length === 0) { | ||
| 26 | + return '' | ||
| 27 | + } | ||
| 28 | + // 获取 value 对应的展示名 | ||
| 29 | + value = value + '' // 强制转换成字符串,因为 DictData 小类数值,是字符串 | ||
| 30 | + for (const dictData of dictDatas) { | ||
| 31 | + if (dictData.dictValue === value) { | ||
| 32 | + return dictData.dictLabel | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | + return '' | ||
| 36 | +} |
ruoyi-ui/src/views/login.vue
| @@ -99,6 +99,7 @@ export default { | @@ -99,6 +99,7 @@ export default { | ||
| 99 | methods: { | 99 | methods: { |
| 100 | getCode() { | 100 | getCode() { |
| 101 | getCodeImg().then(res => { | 101 | getCodeImg().then(res => { |
| 102 | + res = res.data; | ||
| 102 | this.codeUrl = "data:image/gif;base64," + res.img; | 103 | this.codeUrl = "data:image/gif;base64," + res.img; |
| 103 | this.loginForm.uuid = res.uuid; | 104 | this.loginForm.uuid = res.uuid; |
| 104 | }); | 105 | }); |
ruoyi-ui/src/views/system/menu/index.vue
| @@ -211,6 +211,8 @@ import Treeselect from "@riophae/vue-treeselect"; | @@ -211,6 +211,8 @@ import Treeselect from "@riophae/vue-treeselect"; | ||
| 211 | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; | 211 | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
| 212 | import IconSelect from "@/components/IconSelect"; | 212 | import IconSelect from "@/components/IconSelect"; |
| 213 | 213 | ||
| 214 | +import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict' | ||
| 215 | + | ||
| 214 | export default { | 216 | export default { |
| 215 | name: "Menu", | 217 | name: "Menu", |
| 216 | components: { Treeselect, IconSelect }, | 218 | components: { Treeselect, IconSelect }, |
| @@ -255,12 +257,6 @@ export default { | @@ -255,12 +257,6 @@ export default { | ||
| 255 | }, | 257 | }, |
| 256 | created() { | 258 | created() { |
| 257 | this.getList(); | 259 | this.getList(); |
| 258 | - this.getDicts("sys_show_hide").then(response => { | ||
| 259 | - this.visibleOptions = response.data; | ||
| 260 | - }); | ||
| 261 | - this.getDicts("sys_normal_disable").then(response => { | ||
| 262 | - this.statusOptions = response.data; | ||
| 263 | - }); | ||
| 264 | }, | 260 | }, |
| 265 | methods: { | 261 | methods: { |
| 266 | // 选择图标 | 262 | // 选择图标 |
| @@ -295,19 +291,9 @@ export default { | @@ -295,19 +291,9 @@ export default { | ||
| 295 | this.menuOptions.push(menu); | 291 | this.menuOptions.push(menu); |
| 296 | }); | 292 | }); |
| 297 | }, | 293 | }, |
| 298 | - // 显示状态字典翻译 | ||
| 299 | - visibleFormat(row, column) { | ||
| 300 | - if (row.menuType == "3") { | ||
| 301 | - return ""; | ||
| 302 | - } | ||
| 303 | - return this.selectDictLabel(this.visibleOptions, row.visible); | ||
| 304 | - }, | ||
| 305 | // 菜单状态字典翻译 | 294 | // 菜单状态字典翻译 |
| 306 | statusFormat(row, column) { | 295 | statusFormat(row, column) { |
| 307 | - if (row.menuType == "3") { | ||
| 308 | - return ""; | ||
| 309 | - } | ||
| 310 | - return this.selectDictLabel(this.statusOptions, row.status); | 296 | + return getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, row.status) |
| 311 | }, | 297 | }, |
| 312 | // 取消按钮 | 298 | // 取消按钮 |
| 313 | cancel() { | 299 | cancel() { |
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.http
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.dict; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.controller.dict.vo.SysDataDictSimpleVO; | ||
| 5 | +import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert; | ||
| 6 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||
| 7 | +import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; | ||
| 8 | +import io.swagger.annotations.Api; | ||
| 9 | +import io.swagger.annotations.ApiOperation; | ||
| 10 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 11 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 12 | +import org.springframework.web.bind.annotation.RestController; | ||
| 13 | + | ||
| 14 | +import javax.annotation.Resource; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||
| 18 | + | ||
| 19 | +@Api(tags = "数据字典 API") | ||
| 20 | +@RestController | ||
| 21 | +@RequestMapping("/system/dict-data") | ||
| 22 | +public class SysDictDataController { | ||
| 23 | + | ||
| 24 | + @Resource | ||
| 25 | + private SysDictDataService dictDataService; | ||
| 26 | + | ||
| 27 | + @GetMapping("/list-all-simple") | ||
| 28 | + @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地") | ||
| 29 | + // 无需添加权限认证,因为前端全局都需要 | ||
| 30 | + public CommonResult<List<SysDataDictSimpleVO>> listSimpleDictDatas() { | ||
| 31 | + List<SysDictDataDO> list = dictDataService.listDictDatas(); | ||
| 32 | + return success(SysDictDataConvert.INSTANCE.convertList(list)); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/SysDataDictSimpleVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.dict.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@ApiModel("数据字典精简 VO") | ||
| 8 | +@Data | ||
| 9 | +public class SysDataDictSimpleVO { | ||
| 10 | + | ||
| 11 | + @ApiModelProperty(value = "字典类型", required = true, example = "gender") | ||
| 12 | + private String dictType; | ||
| 13 | + | ||
| 14 | + @ApiModelProperty(value = "字典键值", required = true, example = "1") | ||
| 15 | + private String dictValue; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "字典标签", required = true, example = "男") | ||
| 18 | + private String dictLabel; | ||
| 19 | + | ||
| 20 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.http
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/SysMenuRespVO.java
| @@ -19,6 +19,9 @@ public class SysMenuRespVO extends SysMenuBaseVO { | @@ -19,6 +19,9 @@ public class SysMenuRespVO extends SysMenuBaseVO { | ||
| 19 | @ApiModelProperty(value = "菜单编号", required = true, example = "1024") | 19 | @ApiModelProperty(value = "菜单编号", required = true, example = "1024") |
| 20 | private Integer menuId; | 20 | private Integer menuId; |
| 21 | 21 | ||
| 22 | + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") | ||
| 23 | + private Integer status; | ||
| 24 | + | ||
| 22 | @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") | 25 | @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") |
| 23 | private Date createTime; | 26 | private Date createTime; |
| 24 | 27 |
src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.convert.dict; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.controller.dict.vo.SysDataDictSimpleVO; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||
| 5 | +import org.mapstruct.Mapper; | ||
| 6 | +import org.mapstruct.factory.Mappers; | ||
| 7 | + | ||
| 8 | +import java.util.List; | ||
| 9 | + | ||
| 10 | +@Mapper | ||
| 11 | +public interface SysDictDataConvert { | ||
| 12 | + | ||
| 13 | + SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class); | ||
| 14 | + | ||
| 15 | + List<SysDataDictSimpleVO> convertList(List<SysDictDataDO> list); | ||
| 16 | + | ||
| 17 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/dict/SysDictDataMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||
| 4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 5 | +import org.apache.ibatis.annotations.Mapper; | ||
| 6 | + | ||
| 7 | +@Mapper | ||
| 8 | +public interface SysDictDataMapper extends BaseMapper<SysDictDataDO> { | ||
| 9 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictData.java renamed to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictDataDO.java
| @@ -19,7 +19,7 @@ import javax.validation.constraints.Size; | @@ -19,7 +19,7 @@ import javax.validation.constraints.Size; | ||
| 19 | @TableName("sys_dict_data") | 19 | @TableName("sys_dict_data") |
| 20 | @Data | 20 | @Data |
| 21 | @EqualsAndHashCode(callSuper = true) | 21 | @EqualsAndHashCode(callSuper = true) |
| 22 | -public class SysDictData extends BaseDO { | 22 | +public class SysDictDataDO extends BaseDO { |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * 字典编码 | 25 | * 字典编码 |
| @@ -31,7 +31,7 @@ public class SysDictData extends BaseDO { | @@ -31,7 +31,7 @@ public class SysDictData extends BaseDO { | ||
| 31 | * 字典排序 | 31 | * 字典排序 |
| 32 | */ | 32 | */ |
| 33 | @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC) | 33 | @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC) |
| 34 | - private Long dictSort; | 34 | + private Integer dictSort; |
| 35 | /** | 35 | /** |
| 36 | * 字典标签 | 36 | * 字典标签 |
| 37 | */ | 37 | */ |
| @@ -48,6 +48,8 @@ public class SysDictData extends BaseDO { | @@ -48,6 +48,8 @@ public class SysDictData extends BaseDO { | ||
| 48 | private String dictValue; | 48 | private String dictValue; |
| 49 | /** | 49 | /** |
| 50 | * 字典类型 | 50 | * 字典类型 |
| 51 | + * | ||
| 52 | + * 外键 {@link SysDictDataDO#getDictType()} | ||
| 51 | */ | 53 | */ |
| 52 | @Excel(name = "字典类型") | 54 | @Excel(name = "字典类型") |
| 53 | @NotBlank(message = "字典类型不能为空") | 55 | @NotBlank(message = "字典类型不能为空") |
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.dict; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||
| 4 | + | ||
| 5 | +import java.util.List; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 字典数据 Service 接口 | ||
| 9 | + * | ||
| 10 | + * @author ruoyi | ||
| 11 | + */ | ||
| 12 | +public interface SysDictDataService { | ||
| 13 | + | ||
| 14 | + List<SysDictDataDO> listDictDatas(); | ||
| 15 | + | ||
| 16 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.service.dict.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict.SysDictDataMapper; | ||
| 4 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO; | ||
| 5 | +import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; | ||
| 6 | +import org.springframework.stereotype.Service; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | +import java.util.Comparator; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 字典数据 Service 实现类 | ||
| 14 | + * | ||
| 15 | + * @author ruoyi | ||
| 16 | + */ | ||
| 17 | +@Service | ||
| 18 | +public class SysDictDataServiceImpl implements SysDictDataService { | ||
| 19 | + | ||
| 20 | + private static final Comparator<SysDictDataDO> COMPARATOR_TYPE_AND_SORT = Comparator | ||
| 21 | + .comparing(SysDictDataDO::getDictType) | ||
| 22 | + .thenComparingInt(SysDictDataDO::getDictSort); | ||
| 23 | + | ||
| 24 | + @Resource | ||
| 25 | + private SysDictDataMapper dictDataMapper; | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public List<SysDictDataDO> listDictDatas() { | ||
| 29 | + List<SysDictDataDO> list = dictDataMapper.selectList(null); | ||
| 30 | + list.sort(COMPARATOR_TYPE_AND_SORT); | ||
| 31 | + return list; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | +} |