Browse Source

1. 增加字典数据接口
2. 前端接入全局字典数据

YunaiV 4 years ago
parent
commit
dba723b8fc

+ 9 - 1
ruoyi-ui/src/api/system/dict/data.js

@@ -58,4 +58,12 @@ export function exportData(query) {
     method: 'get',
     params: query
   })
-}
+}
+
+// 查询全部字典数据列表
+export function listSimpleDictDatas() {
+  return request({
+    url: '/system/dict-data/list-all-simple',
+    method: 'get',
+  })
+}

+ 2 - 0
ruoyi-ui/src/permission.js

@@ -18,6 +18,8 @@ router.beforeEach((to, from, next) => {
       NProgress.done()
     } else {
       if (store.getters.roles.length === 0) {
+        // 获取字典数据
+        store.dispatch('dict/loadDictDatas')
         // 判断当前用户是否已拉取完user_info信息
         store.dispatch('GetInfo').then(res => {
           // 拉取user_info

+ 2 - 0
ruoyi-ui/src/store/getters.js

@@ -12,5 +12,7 @@ const getters = {
   permissions: state => state.user.permissions,
   permission_routes: state => state.permission.routes,
   sidebarRouters:state => state.permission.sidebarRouters,
+  // 数据字典
+  dict_datas: state => state.dict.dictDatas
 }
 export default getters

+ 3 - 1
ruoyi-ui/src/store/index.js

@@ -5,6 +5,7 @@ import user from './modules/user'
 import tagsView from './modules/tagsView'
 import permission from './modules/permission'
 import settings from './modules/settings'
+import dict from './modules/dict'
 import getters from './getters'
 
 Vue.use(Vuex)
@@ -15,7 +16,8 @@ const store = new Vuex.Store({
     user,
     tagsView,
     permission,
-    settings
+    settings,
+    dict
   },
   getters
 })

+ 46 - 0
ruoyi-ui/src/store/modules/dict.js

@@ -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
+}

+ 1 - 1
ruoyi-ui/src/store/modules/user.js

@@ -37,6 +37,7 @@ const user = {
       const uuid = userInfo.uuid
       return new Promise((resolve, reject) => {
         login(username, password, code, uuid).then(res => {
+          res = res.data;
           setToken(res.token)
           commit('SET_TOKEN', res.token)
           resolve()
@@ -53,7 +54,6 @@ const user = {
           res = res.data; // 读取 data 数据
           const user = res.user
           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是否是一个非空数组
             commit('SET_ROLES', res.roles)
             commit('SET_PERMISSIONS', res.permissions)

+ 36 - 0
ruoyi-ui/src/utils/dict.js

@@ -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 ''
+}

+ 1 - 0
ruoyi-ui/src/views/login.vue

@@ -99,6 +99,7 @@ export default {
   methods: {
     getCode() {
       getCodeImg().then(res => {
+        res = res.data;
         this.codeUrl = "data:image/gif;base64," + res.img;
         this.loginForm.uuid = res.uuid;
       });

+ 3 - 17
ruoyi-ui/src/views/system/menu/index.vue

@@ -211,6 +211,8 @@ import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import IconSelect from "@/components/IconSelect";
 
+import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict'
+
 export default {
   name: "Menu",
   components: { Treeselect, IconSelect },
@@ -255,12 +257,6 @@ export default {
   },
   created() {
     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: {
     // 选择图标
@@ -295,19 +291,9 @@ export default {
         this.menuOptions.push(menu);
       });
     },
-    // 显示状态字典翻译
-    visibleFormat(row, column) {
-      if (row.menuType == "3") {
-        return "";
-      }
-      return this.selectDictLabel(this.visibleOptions, row.visible);
-    },
     // 菜单状态字典翻译
     statusFormat(row, column) {
-      if (row.menuType == "3") {
-        return "";
-      }
-      return this.selectDictLabel(this.statusOptions, row.status);
+      return getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, row.status)
     },
     // 取消按钮
     cancel() {

+ 3 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.http

@@ -0,0 +1,3 @@
+### 请求 /menu/list 接口 => 成功
+GET {{baseUrl}}/system/dict-data/list-all-simple
+Authorization: Bearer {{token}}

+ 35 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java

@@ -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));
+    }
+
+}

+ 20 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/SysDataDictSimpleVO.java

@@ -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 - 1
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.http

@@ -1,3 +1,3 @@
 ### 请求 /menu/list 接口 => 成功
-GET {{baseUrl}}//menu/list
+GET {{baseUrl}}/system/menu/list
 Authorization: Bearer {{token}}

+ 3 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/SysMenuRespVO.java

@@ -19,6 +19,9 @@ public class SysMenuRespVO extends SysMenuBaseVO {
     @ApiModelProperty(value = "菜单编号", required = true, example = "1024")
     private Integer menuId;
 
+    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类")
+    private Integer status;
+
     @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
     private Date createTime;
 

+ 17 - 0
src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java

@@ -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);
+
+}

+ 9 - 0
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/dict/SysDictDataMapper.java

@@ -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> {
+}

+ 4 - 2
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictData.java → src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictDataDO.java

@@ -19,7 +19,7 @@ import javax.validation.constraints.Size;
 @TableName("sys_dict_data")
 @Data
 @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)
-    private Long dictSort;
+    private Integer dictSort;
     /**
      * 字典标签
      */
@@ -48,6 +48,8 @@ public class SysDictData extends BaseDO {
     private String dictValue;
     /**
      * 字典类型
+     *
+     * 外键 {@link SysDictDataDO#getDictType()}
      */
     @Excel(name = "字典类型")
     @NotBlank(message = "字典类型不能为空")

+ 16 - 0
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java

@@ -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();
+
+}

+ 34 - 0
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java

@@ -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;
+    }
+
+}