浏览代码

1. 完成字典类型的迁移
2. 开始字典数据的迁移

YunaiV 4 年之前
父节点
当前提交
f6bb33863f
共有 27 个文件被更改,包括 753 次插入222 次删除
  1. 10 18
      ruoyi-ui/src/api/system/dict/type.js
  2. 56 90
      ruoyi-ui/src/views/system/dict/index.vue
  3. 0 6
      ruoyi-ui/src/views/system/post/index.vue
  4. 51 68
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java
  5. 5 5
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java
  6. 44 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java
  7. 12 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataCreateReqVO.java
  8. 30 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelRespVO.java
  9. 27 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataPageReqVO.java
  10. 25 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataRespVO.java
  11. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataSimpleVO.java
  12. 19 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataUpdateReqVO.java
  13. 5 8
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeBaseVO.java
  14. 10 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeCreateReqVO.java
  15. 20 1
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java
  16. 3 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeRespVO.java
  17. 19 2
      src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java
  18. 11 0
      src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictTypeConvert.java
  19. 30 0
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/dict/SysDictDataMapper.java
  20. 30 0
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/dict/SysDictTypeMapper.java
  21. 1 17
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictDataDO.java
  22. 4 0
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java
  23. 14 2
      src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
  24. 50 0
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java
  25. 39 3
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeService.java
  26. 100 1
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
  27. 137 0
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictTypeServiceImpl.java

+ 10 - 18
ruoyi-ui/src/api/system/dict/type.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 查询字典类型列表
 export function listType(query) {
   return request({
-    url: '/system/dict/type/list',
+    url: '/system/dict-type/page',
     method: 'get',
     params: query
   })
@@ -12,7 +12,7 @@ export function listType(query) {
 // 查询字典类型详细
 export function getType(dictId) {
   return request({
-    url: '/system/dict/type/' + dictId,
+    url: '/system/dict-type/get?id=' + dictId,
     method: 'get'
   })
 }
@@ -20,7 +20,7 @@ export function getType(dictId) {
 // 新增字典类型
 export function addType(data) {
   return request({
-    url: '/system/dict/type',
+    url: '/system/dict-type/create',
     method: 'post',
     data: data
   })
@@ -29,8 +29,8 @@ export function addType(data) {
 // 修改字典类型
 export function updateType(data) {
   return request({
-    url: '/system/dict/type',
-    method: 'put',
+    url: '/system/dict-type/update',
+    method: 'post',
     data: data
   })
 }
@@ -38,23 +38,15 @@ export function updateType(data) {
 // 删除字典类型
 export function delType(dictId) {
   return request({
-    url: '/system/dict/type/' + dictId,
-    method: 'delete'
-  })
-}
-
-// 清理参数缓存
-export function clearCache() {
-  return request({
-    url: '/system/dict/type/clearCache',
-    method: 'delete'
+    url: '/system/dict-type/delete?id=' + dictId,
+    method: 'post'
   })
 }
 
 // 导出字典类型
 export function exportType(query) {
   return request({
-    url: '/system/dict/type/export',
+    url: '/system/dict-type/export',
     method: 'get',
     params: query
   })
@@ -63,7 +55,7 @@ export function exportType(query) {
 // 获取字典选择框列表
 export function optionselect() {
   return request({
-    url: '/system/dict/type/optionselect',
+    url: '/system/dict-type/optionselect',
     method: 'get'
   })
-}
+}

+ 56 - 90
ruoyi-ui/src/views/system/dict/index.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="字典名称" prop="dictName">
+      <el-form-item label="字典名称" prop="name">
         <el-input
-          v-model="queryParams.dictName"
+          v-model="queryParams.name"
           placeholder="请输入字典名称"
           clearable
           size="small"
@@ -11,9 +11,9 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="字典类型" prop="dictType">
+      <el-form-item label="字典类型" prop="type">
         <el-input
-          v-model="queryParams.dictType"
+          v-model="queryParams.type"
           placeholder="请输入字典类型"
           clearable
           size="small"
@@ -30,10 +30,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+              v-for="dict in statusDictDatas"
+              :key="parseInt(dict.value)"
+              :label="dict.label"
+              :value="parseInt(dict.value)"
           />
         </el-select>
       </el-form-item>
@@ -65,26 +65,6 @@
           v-hasPermi="['system:dict:add']"
         >新增</el-button>
       </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="success"
-          icon="el-icon-edit"
-          size="mini"
-          :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['system:dict:edit']"
-        >修改</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="danger"
-          icon="el-icon-delete"
-          size="mini"
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['system:dict:remove']"
-        >删除</el-button>
-      </el-col>
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -94,26 +74,16 @@
           v-hasPermi="['system:dict:export']"
         >导出</el-button>
       </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="danger"
-          icon="el-icon-refresh"
-          size="mini"
-          @click="handleClearCache"
-          v-hasPermi="['system:dict:remove']"
-        >清理缓存</el-button>
-      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="字典编号" align="center" prop="dictId" />
-      <el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
+    <el-table v-loading="loading" :data="typeList">
+      <el-table-column label="字典编号" align="center" prop="id" />
+      <el-table-column label="字典名称" align="center" prop="name" :show-overflow-tooltip="true" />
       <el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
         <template slot-scope="scope">
-          <router-link :to="'/dict/type/data/' + scope.row.dictId" class="link-type">
-            <span>{{ scope.row.dictType }}</span>
+          <router-link :to="'/dict/type/data/' + scope.row.id" class="link-type">
+            <span>{{ scope.row.type }}</span>
           </router-link>
         </template>
       </el-table-column>
@@ -147,7 +117,7 @@
     <pagination
       v-show="total>0"
       :total="total"
-      :page.sync="queryParams.pageNum"
+      :page.sync="queryParams.pageNo"
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
@@ -155,19 +125,19 @@
     <!-- 添加或修改参数配置对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="字典名称" prop="dictName">
-          <el-input v-model="form.dictName" placeholder="请输入字典名称" />
+        <el-form-item label="字典名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入字典名称" />
         </el-form-item>
-        <el-form-item label="字典类型" prop="dictType">
-          <el-input v-model="form.dictType" placeholder="请输入字典类型" />
+        <el-form-item label="字典类型" prop="type">
+          <el-input v-model="form.type" placeholder="请输入字典类型" />
         </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-radio-group v-model="form.status">
             <el-radio
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+                v-for="dict in statusDictDatas"
+                :key="parseInt(dict.value)"
+                :label="parseInt(dict.value)"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="备注" prop="remark">
@@ -183,7 +153,10 @@
 </template>
 
 <script>
-import { listType, getType, delType, addType, updateType, exportType, clearCache } from "@/api/system/dict/type";
+import { listType, getType, delType, addType, updateType, exportType } from "@/api/system/dict/type";
+
+import { SysCommonStatusEnum } from '@/utils/constants'
+import { getDictDataLabel, getDictDatas, DICT_TYPE } from '@/utils/dict'
 
 export default {
   name: "Dict",
@@ -191,12 +164,6 @@ export default {
     return {
       // 遮罩层
       loading: true,
-      // 选中数组
-      ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
       // 显示搜索条件
       showSearch: true,
       // 总条数
@@ -213,45 +180,50 @@ export default {
       dateRange: [],
       // 查询参数
       queryParams: {
-        pageNum: 1,
+        pageNo: 1,
         pageSize: 10,
-        dictName: undefined,
-        dictType: undefined,
+        name: undefined,
+        type: undefined,
         status: undefined
       },
       // 表单参数
       form: {},
       // 表单校验
       rules: {
-        dictName: [
+        name: [
           { required: true, message: "字典名称不能为空", trigger: "blur" }
         ],
-        dictType: [
+        type: [
           { required: true, message: "字典类型不能为空", trigger: "blur" }
         ]
-      }
+      },
+
+      // 枚举
+      CommonStatusEnum: SysCommonStatusEnum,
+      // 数据字典
+      statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)
     };
   },
   created() {
     this.getList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 查询字典类型列表 */
     getList() {
       this.loading = true;
-      listType(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
-          this.typeList = response.rows;
-          this.total = response.total;
+      listType(this.addDateRange(this.queryParams, [
+        this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
+        this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
+      ])).then(response => {
+          this.typeList = response.data.list;
+          this.total = response.data.total;
           this.loading = false;
         }
       );
     },
     // 字典状态字典翻译
     statusFormat(row, column) {
-      return this.selectDictLabel(this.statusOptions, row.status);
+      return getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, row.status)
     },
     // 取消按钮
     cancel() {
@@ -261,17 +233,17 @@ export default {
     // 表单重置
     reset() {
       this.form = {
-        dictId: undefined,
-        dictName: undefined,
-        dictType: undefined,
-        status: "0",
+        id: undefined,
+        name: undefined,
+        type: undefined,
+        status: SysCommonStatusEnum.ENABLE,
         remark: undefined
       };
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      this.queryParams.pageNum = 1;
+      this.queryParams.pageNo = 1;
       this.getList();
     },
     /** 重置按钮操作 */
@@ -286,17 +258,11 @@ export default {
       this.open = true;
       this.title = "添加字典类型";
     },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.dictId)
-      this.single = selection.length!=1
-      this.multiple = !selection.length
-    },
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      const dictId = row.dictId || this.ids
-      getType(dictId).then(response => {
+      const id = row.id;
+      getType(id).then(response => {
         this.form = response.data;
         this.open = true;
         this.title = "修改字典类型";
@@ -306,7 +272,7 @@ export default {
     submitForm: function() {
       this.$refs["form"].validate(valid => {
         if (valid) {
-          if (this.form.dictId != undefined) {
+          if (this.form.id !== undefined) {
             updateType(this.form).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
@@ -324,13 +290,13 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
-      const dictIds = row.dictId || this.ids;
-      this.$confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?', "警告", {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除字典编号为"' + ids + '"的数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"
         }).then(function() {
-          return delType(dictIds);
+          return delType(ids);
         }).then(() => {
           this.getList();
           this.msgSuccess("删除成功");
@@ -357,4 +323,4 @@ export default {
     }
   }
 };
-</script>
+</script>

+ 0 - 6
ruoyi-ui/src/views/system/post/index.vue

@@ -141,12 +141,6 @@ export default {
     return {
       // 遮罩层
       loading: true,
-      // 选中数组
-      ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
       // 显示搜索条件
       showSearch: true,
       // 总条数

+ 51 - 68
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java

@@ -1,15 +1,16 @@
 package cn.iocoder.dashboard.modules.system.controller.dict;
 
 import cn.iocoder.dashboard.common.pojo.CommonResult;
-import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDataDictSimpleVO;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.*;
 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.ApiImplicitParam;
 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 org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.List;
@@ -27,79 +28,61 @@ public class SysDictDataController {
     @GetMapping("/list-all-simple")
     @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
     // 无需添加权限认证,因为前端全局都需要
-    public CommonResult<List<SysDataDictSimpleVO>> listSimpleDictDatas() {
+    public CommonResult<List<SysDictDataSimpleVO>> listSimpleDictDatas() {
         List<SysDictDataDO> list = dictDataService.listDictDatas();
         return success(SysDictDataConvert.INSTANCE.convertList(list));
     }
 
+    @ApiOperation("/获得字典类型的分页列表")
+    @GetMapping("/page")
 //    @PreAuthorize("@ss.hasPermi('system:dict:list')")
-//    @GetMapping("/list")
-//    public TableDataInfo list(SysDictData dictData) {
-//        startPage();
-//        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
-//        return getDataTable(list);
-//    }
-//
-//    @Log(title = "字典数据", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:dict:export')")
-//    @GetMapping("/export")
-//    public AjaxResult export(SysDictData dictData) {
-//        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
-//        ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
-//        return util.exportExcel(list, "字典数据");
-//    }
-//
-//    /**
-//     * 查询字典数据详细
-//     */
+    public CommonResult<PageResult<SysDictDataRespVO>> pageDictTypes(@Validated SysDictDataPageReqVO reqVO) {
+        return success(SysDictDataConvert.INSTANCE.convertPage(dictDataService.pageDictDatas(reqVO)));
+    }
+
+    @ApiOperation("/查询字典数据详细")
+    @ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
+    @GetMapping(value = "/get")
 //    @PreAuthorize("@ss.hasPermi('system:dict:query')")
-//    @GetMapping(value = "/{dictCode}")
-//    public AjaxResult getInfo(@PathVariable Long dictCode) {
-//        return AjaxResult.success(dictDataService.selectDictDataById(dictCode));
-//    }
-//
-//    /**
-//     * 根据字典类型查询字典数据信息
-//     */
-//    @GetMapping(value = "/type/{dictType}")
-//    public AjaxResult dictType(@PathVariable String dictType) {
-//        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
-//        if (StringUtils.isNull(data)) {
-//            data = new ArrayList<SysDictData>();
-//        }
-//        return AjaxResult.success(data);
-//    }
-//
-//    /**
-//     * 新增字典类型
-//     */
+    public CommonResult<SysDictDataRespVO> getDictData(@RequestParam("id") Long id) {
+        return success(SysDictDataConvert.INSTANCE.convert(dictDataService.getDictData(id)));
+    }
+
+    @ApiOperation("新增字典数据")
+    @PostMapping("/create")
 //    @PreAuthorize("@ss.hasPermi('system:dict:add')")
-//    @Log(title = "字典数据", businessType = BusinessType.INSERT)
-//    @PostMapping
-//    public AjaxResult add(@Validated @RequestBody SysDictData dict) {
-//        dict.setCreateBy(SecurityUtils.getUsername());
-//        return toAjax(dictDataService.insertDictData(dict));
-//    }
-//
-//    /**
-//     * 修改保存字典类型
-//     */
+//    @Log(title = "字典数据", businessData = BusinessData.INSERT)
+    public CommonResult<Long> createDictData(@Validated @RequestBody SysDictDataCreateReqVO reqVO) {
+        Long dictDataId = dictDataService.createDictData(reqVO);
+        return success(dictDataId);
+    }
+
+    @ApiOperation("修改字典数据")
+    @PostMapping("update")
 //    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
-//    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
-//    @PutMapping
-//    public AjaxResult edit(@Validated @RequestBody SysDictData dict) {
-//        dict.setUpdateBy(SecurityUtils.getUsername());
-//        return toAjax(dictDataService.updateDictData(dict));
-//    }
-//
-//    /**
-//     * 删除字典类型
-//     */
+//    @Log(title = "字典数据", businessData = BusinessData.UPDATE)
+    public CommonResult<Boolean> updateDictData(@Validated @RequestBody SysDictDataUpdateReqVO reqVO) {
+        dictDataService.updateDictData(reqVO);
+        return success(true);
+    }
+
+    @ApiOperation("删除字典数据")
+    @ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
+    @PostMapping("/delete")
 //    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
-//    @Log(title = "字典类型", businessType = BusinessType.DELETE)
-//    @DeleteMapping("/{dictCodes}")
-//    public AjaxResult remove(@PathVariable Long[] dictCodes) {
-//        return toAjax(dictDataService.deleteDictDataByIds(dictCodes));
+    public CommonResult<Boolean> deleteDictData(Long id) {
+        dictDataService.deleteDictData(id);
+        return success(true);
+    }
+
+    //
+//    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
+//    @PreAuthorize("@ss.hasPermi('system:dict:export')")
+//    @GetMapping("/export")
+//    public AjaxResult export(SysDictType dictType) {
+//        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+//        ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
+//        return util.exportExcel(list, "字典类型");
 //    }
 
 }

+ 5 - 5
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java

@@ -5,7 +5,7 @@ import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypePageReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeRespVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.convert.dict.SysDictTypeConvert;
 import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
 import io.swagger.annotations.Api;
@@ -26,14 +26,14 @@ public class SysDictTypeController {
     @Resource
     private SysDictTypeService dictTypeService;
 
-    @ApiOperation("/page")
-    @GetMapping("/list")
+    @ApiOperation("/获得字典类型的分页列表")
+    @GetMapping("/page")
 //    @PreAuthorize("@ss.hasPermi('system:dict:list')")
     public CommonResult<PageResult<SysDictTypeRespVO>> pageDictTypes(@Validated SysDictTypePageReqVO reqVO) {
         return success(SysDictTypeConvert.INSTANCE.convertPage(dictTypeService.pageDictTypes(reqVO)));
     }
 
-    @ApiOperation("/查询字典详细")
+    @ApiOperation("/查询字典类型详细")
     @ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
     @GetMapping(value = "/get")
 //    @PreAuthorize("@ss.hasPermi('system:dict:query')")
@@ -54,7 +54,7 @@ public class SysDictTypeController {
     @PostMapping("update")
 //    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
 //    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateDictType(@Validated @RequestBody SysUserUpdateReqVO reqVO) {
+    public CommonResult<Boolean> updateDictType(@Validated @RequestBody SysDictTypeUpdateReqVO reqVO) {
         dictTypeService.updateDictType(reqVO);
         return success(true);
     }

+ 44 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * 字典数据 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+public class SysDictDataBaseVO {
+
+    @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
+    @NotBlank(message = "显示顺序不能为空")
+    private String sort;
+
+    @ApiModelProperty(value = "字典标签", required = true, example = "芋道")
+    @NotBlank(message = "字典标签不能为空")
+    @Size(max = 100, message = "字典标签长度不能超过100个字符")
+    private String label;
+
+    @ApiModelProperty(value = "字典值", required = true, example = "iocoder")
+    @NotBlank(message = "字典键值不能为空")
+    @Size(max = 100, message = "字典键值长度不能超过100个字符")
+    private String value;
+
+    @ApiModelProperty(value = "字典类型", required = true, example = "sys_common_sex")
+    @NotBlank(message = "字典类型不能为空")
+    @Size(max = 100, message = "字典类型长度不能超过100个字符")
+    private String dictType;
+
+    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举")
+    @NotNull(message = "状态不能为空")
+//    @InEnum(value = SysCommonStatusEnum.class, message = "修改状态必须是 {value}")
+    private Integer status;
+
+    @ApiModelProperty(value = "备注", example = "我是一个角色")
+    private String remark;
+
+}

+ 12 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataCreateReqVO.java

@@ -0,0 +1,12 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@ApiModel("字典数据创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SysDictDataCreateReqVO extends SysDictDataBaseVO {
+
+}

+ 30 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataExcelRespVO.java

@@ -0,0 +1,30 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import cn.iocoder.dashboard.framework.excel.Excel;
+import lombok.Data;
+
+/**
+ * 字典数据 Excel 导出响应 VO
+ */
+@Data
+public class SysDictDataExcelRespVO {
+
+    @Excel(name = "字典编码", cellType = Excel.ColumnType.NUMERIC)
+    private Long id;
+
+    @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC)
+    private Integer sort;
+
+    @Excel(name = "字典标签")
+    private String label;
+
+    @Excel(name = "字典键值")
+    private String value;
+
+    @Excel(name = "字典类型")
+    private String dictType;
+
+    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+    private Integer status;
+
+}

+ 27 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataPageReqVO.java

@@ -0,0 +1,27 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import cn.iocoder.dashboard.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.Size;
+
+@ApiModel("字典类型分页列表 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SysDictDataPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "字典标签", example = "芋道")
+    @Size(max = 100, message = "字典标签长度不能超过100个字符")
+    private String label;
+
+    @ApiModelProperty(value = "字典类型", example = "sys_common_sex", notes = "模糊匹配")
+    @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
+    private String dictType;
+
+    @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
+    private Integer status;
+
+}

+ 25 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataRespVO.java

@@ -0,0 +1,25 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@ApiModel("字典数据信息 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SysDictDataRespVO extends SysDictDataBaseVO {
+
+    @ApiModelProperty(value = "字典数据编号", required = true, example = "1024")
+    private Integer id;
+
+    @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
+    private Date createTime;
+
+}

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDataDictSimpleVO.java → src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataSimpleVO.java

@@ -6,7 +6,7 @@ import lombok.Data;
 
 @ApiModel("数据字典精简 VO")
 @Data
-public class SysDataDictSimpleVO {
+public class SysDictDataSimpleVO {
 
     @ApiModelProperty(value = "字典类型", required = true, example = "gender")
     private String dictType;

+ 19 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataUpdateReqVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.dashboard.modules.system.controller.dict.vo.data;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotNull;
+
+@ApiModel("字典数据更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SysDictDataUpdateReqVO extends SysDictDataBaseVO {
+
+    @ApiModelProperty(value = "字典数据编号", required = true, example = "1024")
+    @NotNull(message = "字典数据编号不能为空")
+    private Long id;
+
+}

+ 5 - 8
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeBaseVO.java

@@ -1,10 +1,10 @@
 package cn.iocoder.dashboard.modules.system.controller.dict.vo.type;
 
-import cn.iocoder.dashboard.framework.excel.Excel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 
 /**
@@ -19,14 +19,11 @@ public class SysDictTypeBaseVO {
     @Size(max = 100, message = "字典类型名称长度不能超过100个字符")
     private String name;
 
-    @ApiModelProperty(value = "字典类型", required = true, example = "sys_common_sex")
-    @NotBlank(message = "字典类型不能为空")
-    @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
-    private String type;
-
     @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类")
-    @NotBlank(message = "状态不能为空")
-    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+    @NotNull(message = "状态不能为空")
     private Integer status;
 
+    @ApiModelProperty(value = "备注", example = "快乐的备注")
+    private String remark;
+
 }

+ 10 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeCreateReqVO.java

@@ -1,11 +1,21 @@
 package cn.iocoder.dashboard.modules.system.controller.dict.vo.type;
 
 import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
 @ApiModel("字典类型创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class SysDictTypeCreateReqVO extends SysDictTypeBaseVO {
+
+    @ApiModelProperty(value = "字典类型", required = true, example = "sys_common_sex")
+    @NotNull(message = "字典类型不能为空")
+    @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
+    private String type;
+
 }

+ 20 - 1
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java

@@ -1,17 +1,36 @@
 package cn.iocoder.dashboard.modules.system.controller.dict.vo.type;
 
+import cn.iocoder.dashboard.common.pojo.PageParam;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.Size;
+import java.util.Date;
+
+import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
 @ApiModel("字典类型分页列表 Request VO")
 @Data
-public class SysDictTypePageReqVO {
+public class SysDictTypePageReqVO extends PageParam {
 
     @ApiModelProperty(value = "字典类型名称", example = "芋道", notes = "模糊匹配")
     private String name;
 
+    @ApiModelProperty(value = "字典类型", example = "sys_common_sex", notes = "模糊匹配")
+    @Size(max = 100, message = "字典类型类型长度不能超过100个字符")
+    private String type;
+
     @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
     private Integer status;
 
+    @ApiModelProperty(value = "开始时间", example = "2020-10-24")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private Date beginTime;
+
+    @ApiModelProperty(value = "结束时间", example = "2020-10-24")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private Date endTime;
+
 }

+ 3 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/type/SysDictTypeRespVO.java

@@ -19,6 +19,9 @@ public class SysDictTypeRespVO extends SysDictTypeBaseVO {
     @ApiModelProperty(value = "字典类型编号", required = true, example = "1024")
     private Integer id;
 
+    @ApiModelProperty(value = "字典类型", required = true, example = "sys_common_sex")
+    private String type;
+
     @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
     private Date createTime;
 

+ 19 - 2
src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictDataConvert.java

@@ -1,8 +1,14 @@
 package cn.iocoder.dashboard.modules.system.convert.dict;
 
-import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDataDictSimpleVO;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataRespVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataSimpleVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
@@ -12,6 +18,17 @@ public interface SysDictDataConvert {
 
     SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
 
-    List<SysDataDictSimpleVO> convertList(List<SysDictDataDO> list);
+    List<SysDictDataSimpleVO> convertList(List<SysDictDataDO> list);
+
+    SysDictDataRespVO convert(SysDictDataDO bean);
+
+    PageResult<SysDictDataRespVO> convertPage(PageResult<SysDictDataDO> page);
+
+    SysDictDataDO convert(SysDictDataUpdateReqVO bean);
+
+    SysDictDataDO convert(SysDictDataCreateReqVO bean);
+
+    @Mapping(source = "records", target = "list")
+    PageResult<SysDictDataDO> convertPage02(IPage<SysDictDataDO> page);
 
 }

+ 11 - 0
src/main/java/cn/iocoder/dashboard/modules/system/convert/dict/SysDictTypeConvert.java

@@ -1,9 +1,13 @@
 package cn.iocoder.dashboard.modules.system.convert.dict;
 
 import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeRespVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 
 @Mapper
@@ -15,4 +19,11 @@ public interface SysDictTypeConvert {
 
     SysDictTypeRespVO convert(SysDictTypeDO bean);
 
+    @Mapping(source = "records", target = "list")
+    PageResult<SysDictTypeDO> convertPage02(IPage<SysDictTypeDO> page);
+
+    SysDictTypeDO convert(SysDictTypeCreateReqVO bean);
+
+    SysDictTypeDO convert(SysDictTypeUpdateReqVO bean);
+
 }

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

@@ -1,9 +1,39 @@
 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict;
 
+import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
+import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+
+import static com.baomidou.mybatisplus.core.metadata.OrderItem.asc;
+
 @Mapper
 public interface SysDictDataMapper extends BaseMapper<SysDictDataDO> {
+
+    default SysDictDataDO selectByLabel(String label) {
+        return selectOne(new QueryWrapper<SysDictDataDO>().eq("label", label));
+    }
+
+    default int selectCountByDictType(String dictType) {
+        return selectCount(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType));
+    }
+
+    default IPage<SysDictDataDO> selectList(SysDictDataPageReqVO reqVO) {
+        return selectPage(MyBatisUtils.buildPage(reqVO),
+                new QueryWrapperX<SysDictDataDO>().likeIfPresent("label", reqVO.getLabel())
+                        .likeIfPresent("dict_type", reqVO.getDictType())
+                        .eqIfPresent("status", reqVO.getStatus()))
+                .addOrder(asc("dict_type"), asc("sort"));
+    }
+
+    default List<SysDictDataDO> selectList() {
+        return selectList(new QueryWrapper<>());
+    }
+
 }

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

@@ -0,0 +1,30 @@
+package cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict;
+
+import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
+import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypePageReqVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SysDictTypeMapper extends BaseMapper<SysDictTypeDO> {
+
+    default IPage<SysDictTypeDO> selectList(SysDictTypePageReqVO reqVO) {
+        return selectPage(MyBatisUtils.buildPage(reqVO),
+                new QueryWrapperX<SysDictTypeDO>().likeIfPresent("name", reqVO.getName())
+                        .likeIfPresent("dict_type", reqVO.getType())
+                        .eqIfPresent("status", reqVO.getStatus())
+                        .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
+    }
+
+    default SysDictTypeDO selectByType(String type) {
+        return selectOne(new QueryWrapperX<SysDictTypeDO>().eq("dict_type", type));
+    }
+
+    default SysDictTypeDO selectByName(String name) {
+        return selectOne(new QueryWrapperX<SysDictTypeDO>().eq("name", name));
+    }
+
+}

+ 1 - 17
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictDataDO.java

@@ -1,16 +1,12 @@
 package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict;
 
 import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
-import cn.iocoder.dashboard.framework.excel.Excel;
 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
-
 /**
  * 字典数据表
  *
@@ -22,45 +18,33 @@ import javax.validation.constraints.Size;
 public class SysDictDataDO extends BaseDO {
 
     /**
-     * 字典编码
+     * 字典数据编号
      */
     @TableId
-    @Excel(name = "字典编码", cellType = Excel.ColumnType.NUMERIC)
     private Long id;
     /**
      * 字典排序
      */
-    @Excel(name = "字典排序", cellType = Excel.ColumnType.NUMERIC)
     private Integer sort;
     /**
      * 字典标签
      */
-    @Excel(name = "字典标签")
-    @NotBlank(message = "字典标签不能为空")
-    @Size(max = 100, message = "字典标签长度不能超过100个字符")
     private String label;
     /**
      * 字典值
      */
-    @Excel(name = "字典键值")
-    @NotBlank(message = "字典键值不能为空")
-    @Size(max = 100, message = "字典键值长度不能超过100个字符")
     private String value;
     /**
      * 字典类型
      *
      * 冗余 {@link SysDictDataDO#getDictType()}
      */
-    @Excel(name = "字典类型")
-    @NotBlank(message = "字典类型不能为空")
-    @Size(max = 100, message = "字典类型长度不能超过100个字符")
     private String dictType;
     /**
      * 状态
      *
      * 枚举 {@link CommonStatusEnum}
      */
-    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
     private Integer status;
     /**
      * 备注

+ 4 - 0
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java

@@ -38,5 +38,9 @@ public class SysDictTypeDO extends BaseDO {
      * 枚举 {@link CommonStatusEnum}
      */
     private Integer status;
+    /**
+     * 备注
+     */
+    private String remark;
 
 }

+ 14 - 2
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java

@@ -51,7 +51,19 @@ public interface SysErrorCodeConstants {
     // ========== 岗位模块 1002005000 ==========
     ErrorCode POST_NOT_FOUND = new ErrorCode(1002005001, "当前岗位不存在");
     ErrorCode POST_NOT_ENABLE = new ErrorCode(1002005002, "岗位({}) 不处于开启状态,不允许选择");
-    ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1002004001, "已经存在该名字的岗位");
-    ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1002004001, "已经存在该标识的岗位");
+    ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1002005001, "已经存在该名字的岗位");
+    ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1002005001, "已经存在该标识的岗位");
+
+    // ========== 字典类型 1002006000 ==========
+    ErrorCode DICT_TYPE_NOT_FOUND = new ErrorCode(1002006001, "当前字典类型不存在");
+    ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1002006002, "字典类型不处于开启状态,不允许选择");
+    ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1002006003, "已经存在该名字的字典类型");
+    ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1002006004, "已经存在该类型的字典类型");
+    ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1002006004, "无法删除,该字典类型还有字典数据");
+
+    // ========== 字典数据 1002007000 ==========
+    ErrorCode DICT_DATA_NOT_FOUND = new ErrorCode(1002007001, "当前字典数据不存在");
+    ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1002007002, "字典数据不处于开启状态,不允许选择");
+    ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1002007003, "已经存在该值的字典数据");
 
 }

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

@@ -1,5 +1,9 @@
 package cn.iocoder.dashboard.modules.system.service.dict;
 
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
 
 import java.util.List;
@@ -13,4 +17,50 @@ public interface SysDictDataService {
 
     List<SysDictDataDO> listDictDatas();
 
+    /**
+     * 获得字典数据分页列表
+     *
+     * @param reqVO 分页请求
+     * @return 字典数据分页列表
+     */
+    PageResult<SysDictDataDO> pageDictDatas(SysDictDataPageReqVO reqVO);
+
+    /**
+     * 获得字典数据详情
+     *
+     * @param id 字典数据编号
+     * @return 字典数据
+     */
+    SysDictDataDO getDictData(Long id);
+
+    /**
+     * 创建字典数据
+     *
+     * @param reqVO 字典数据信息
+     * @return 字典数据编号
+     */
+    Long createDictData(SysDictDataCreateReqVO reqVO);
+
+    /**
+     * 更新字典数据
+     *
+     * @param reqVO 字典数据信息
+     */
+    void updateDictData(SysDictDataUpdateReqVO reqVO);
+
+    /**
+     * 删除字典数据
+     *
+     * @param id 字典数据编号
+     */
+    void deleteDictData(Long id);
+
+    /**
+     * 获得指定字典类型的数据数量
+     *
+     * @param dictType 字典类型
+     * @return 数据数量
+     */
+    int countByDictType(String dictType);
+
 }

+ 39 - 3
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeService.java

@@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.dict;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypePageReqVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
 
 /**
@@ -13,14 +13,50 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictType
  */
 public interface SysDictTypeService {
 
+    /**
+     * 获得字典类型分页列表
+     *
+     * @param reqVO 分页请求
+     * @return 字典类型分页列表
+     */
     PageResult<SysDictTypeDO> pageDictTypes(SysDictTypePageReqVO reqVO);
 
+    /**
+     * 获得字典类型详情
+     *
+     * @param id 字典类型编号
+     * @return 字典类型
+     */
     SysDictTypeDO getDictType(Long id);
 
+    /**
+     * 获得字典类型详情
+     *
+     * @param type 字典类型
+     * @return 字典类型详情
+     */
+    SysDictTypeDO getDictType(String type);
+
+    /**
+     * 创建字典类型
+     *
+     * @param reqVO 字典类型信息
+     * @return 字典类型编号
+     */
     Long createDictType(SysDictTypeCreateReqVO reqVO);
 
-    void updateDictType(SysUserUpdateReqVO reqVO);
-
+    /**
+     * 更新字典类型
+     *
+     * @param reqVO 字典类型信息
+     */
+    void updateDictType(SysDictTypeUpdateReqVO reqVO);
+
+    /**
+     * 删除字典类型
+     *
+     * @param id 字典类型编号
+     */
     void deleteDictType(Long id);
 
 }

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

@@ -1,14 +1,25 @@
 package cn.iocoder.dashboard.modules.system.service.dict.impl;
 
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
+import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert;
 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.dal.mysql.dataobject.dict.SysDictTypeDO;
 import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
+import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.Comparator;
 import java.util.List;
 
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
+
 /**
  * 字典数据 Service 实现类
  *
@@ -21,14 +32,102 @@ public class SysDictDataServiceImpl implements SysDictDataService {
             .comparing(SysDictDataDO::getDictType)
             .thenComparingInt(SysDictDataDO::getSort);
 
+    @Resource
+    private SysDictTypeService dictTypeService;
+
     @Resource
     private SysDictDataMapper dictDataMapper;
 
     @Override
     public List<SysDictDataDO> listDictDatas() {
-        List<SysDictDataDO> list = dictDataMapper.selectList(null);
+        List<SysDictDataDO> list = dictDataMapper.selectList();
         list.sort(COMPARATOR_TYPE_AND_SORT);
         return list;
     }
 
+    @Override
+    public PageResult<SysDictDataDO> pageDictDatas(SysDictDataPageReqVO reqVO) {
+        return SysDictDataConvert.INSTANCE.convertPage02(dictDataMapper.selectList(reqVO));
+    }
+
+    @Override
+    public SysDictDataDO getDictData(Long id) {
+        return dictDataMapper.selectById(id);
+    }
+
+    @Override
+    public Long createDictData(SysDictDataCreateReqVO reqVO) {
+        // 校验正确性
+        this.checkCreateOrUpdate(null, reqVO.getLabel(), reqVO.getDictType());
+        // 插入字典类型
+        SysDictDataDO dictData = SysDictDataConvert.INSTANCE.convert(reqVO);
+        dictDataMapper.insert(dictData);
+        return dictData.getId();
+    }
+
+    @Override
+    public void updateDictData(SysDictDataUpdateReqVO reqVO) {
+        // 校验正确性
+        this.checkCreateOrUpdate(reqVO.getId(), reqVO.getLabel(), reqVO.getDictType());
+        // 更新字典类型
+        SysDictDataDO updateObj = SysDictDataConvert.INSTANCE.convert(reqVO);
+        dictDataMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteDictData(Long id) {
+        // 校验是否存在
+        this.checkDictDataExists(id);
+        // 删除字典数据
+        dictDataMapper.deleteById(id);
+    }
+
+    @Override
+    public int countByDictType(String dictType) {
+        return dictDataMapper.selectCountByDictType(dictType);
+    }
+
+    private void checkCreateOrUpdate(Long id, String label, String dictType) {
+        // 校验自己存在
+        checkDictDataExists(id);
+        // 校验字典数据的值的唯一性
+        checkDictDataValueUnique(id, label);
+        // 校验字典类型有效
+        checkDictTypeValid(dictType);
+    }
+
+    private void checkDictDataValueUnique(Long id, String label) {
+        SysDictDataDO dictData = dictDataMapper.selectByLabel(label);
+        if (dictData == null) {
+            return;
+        }
+        // 如果 id 为空,说明不用比较是否为相同 id 的字典数据
+        if (id == null) {
+            throw ServiceExceptionUtil.exception(DICT_DATA_VALUE_DUPLICATE);
+        }
+        if (!dictData.getId().equals(id)) {
+            throw ServiceExceptionUtil.exception(DICT_DATA_VALUE_DUPLICATE);
+        }
+    }
+
+    private void checkDictDataExists(Long id) {
+        if (id == null) {
+            return;
+        }
+        SysDictDataDO dictData = dictDataMapper.selectById(id);
+        if (dictData == null) {
+            throw ServiceExceptionUtil.exception(DICT_DATA_NOT_FOUND);
+        }
+    }
+
+    private void checkDictTypeValid(String type) {
+        SysDictTypeDO dictType = dictTypeService.getDictType(type);
+        if (dictType == null) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_NOT_FOUND);
+        }
+        if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_NOT_ENABLE);
+        }
+    }
+
 }

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

@@ -0,0 +1,137 @@
+package cn.iocoder.dashboard.modules.system.service.dict.impl;
+
+import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypePageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.convert.dict.SysDictTypeConvert;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dao.dict.SysDictTypeMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
+import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
+import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
+
+/**
+ * 字典类型 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+public class SysDictTypeServiceImpl implements SysDictTypeService {
+
+    @Resource
+    private SysDictTypeServiceImpl self;
+    @Resource
+    private SysDictDataService dictDataService;
+
+    @Resource
+    private SysDictTypeMapper dictTypeMapper;
+
+    @Override
+    public PageResult<SysDictTypeDO> pageDictTypes(SysDictTypePageReqVO reqVO) {
+        return SysDictTypeConvert.INSTANCE.convertPage02(dictTypeMapper.selectList(reqVO));
+    }
+
+    @Override
+    public SysDictTypeDO getDictType(Long id) {
+        return dictTypeMapper.selectById(id);
+    }
+
+    @Override
+    public SysDictTypeDO getDictType(String type) {
+        return dictTypeMapper.selectByType(type);
+    }
+
+    @Override
+    public Long createDictType(SysDictTypeCreateReqVO reqVO) {
+        // 校验正确性
+        this.checkCreateOrUpdate(null, reqVO.getName(), reqVO.getType());
+        // 插入字典类型
+        SysDictTypeDO dictType = SysDictTypeConvert.INSTANCE.convert(reqVO);
+        dictTypeMapper.insert(dictType);
+        return dictType.getId();
+    }
+
+    @Override
+    public void updateDictType(SysDictTypeUpdateReqVO reqVO) {
+        // 校验正确性
+        this.checkCreateOrUpdate(reqVO.getId(), reqVO.getName(), null);
+        // 更新字典类型
+        SysDictTypeDO updateObj = SysDictTypeConvert.INSTANCE.convert(reqVO);
+        dictTypeMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteDictType(Long id) {
+        // 执行删除
+        self.deleteDictType0(id);
+        // TODO 发送 MQ 消息
+    }
+
+    @Transactional
+    public void deleteDictType0(Long id) {
+        // 校验是否存在
+        SysDictTypeDO dictType = this.checkDictTypeExists(id);
+        // 校验是否有字典数据
+        if (dictDataService.countByDictType(dictType.getType()) > 0) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_HAS_CHILDREN);
+        }
+        // 删除字典类型
+        dictTypeMapper.deleteById(id);
+    }
+
+    private void checkCreateOrUpdate(Long id, String name, String type) {
+        // 校验自己存在
+        checkDictTypeExists(id);
+        // 校验字典类型的名字的唯一性
+        checkDictTypeNameUnique(id, name);
+        // 校验字典类型的类型的唯一性
+        checkDictTypeUnique(id, type);
+    }
+
+    private void checkDictTypeNameUnique(Long id, String type) {
+        SysDictTypeDO dictType = dictTypeMapper.selectByName(type);
+        if (dictType == null) {
+            return;
+        }
+        // 如果 id 为空,说明不用比较是否为相同 id 的字典类型
+        if (id == null) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_NAME_DUPLICATE);
+        }
+        if (!dictType.getId().equals(id)) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_NAME_DUPLICATE);
+        }
+    }
+
+    private void checkDictTypeUnique(Long id, String type) {
+        SysDictTypeDO dictType = dictTypeMapper.selectByType(type);
+        if (dictType == null) {
+            return;
+        }
+        // 如果 id 为空,说明不用比较是否为相同 id 的字典类型
+        if (id == null) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_TYPE_DUPLICATE);
+        }
+        if (!dictType.getId().equals(id)) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_TYPE_DUPLICATE);
+        }
+    }
+
+    private SysDictTypeDO checkDictTypeExists(Long id) {
+        if (id == null) {
+            return null;
+        }
+        SysDictTypeDO dictType = dictTypeMapper.selectById(id);
+        if (dictType == null) {
+            throw ServiceExceptionUtil.exception(DICT_TYPE_NOT_FOUND);
+        }
+        return dictType;
+    }
+
+}