Browse Source

Merge branch 'master' of gitee.com:zhijiantianya/ruoyi-vue-pro into master

dxyx 4 years ago
parent
commit
bec7167524
100 changed files with 3269 additions and 2362 deletions
  1. 1 1
      README.md
  2. 4 0
      lombok.config
  3. 6 0
      pom.xml
  4. 16 0
      ruoyi-ui/src/api/infra/dbDoc.js
  5. 18 0
      ruoyi-ui/src/api/infra/file.js
  6. 2 2
      ruoyi-ui/src/api/system/dept.js
  7. 2 2
      ruoyi-ui/src/api/system/dict/data.js
  8. 2 2
      ruoyi-ui/src/api/system/dict/type.js
  9. 2 2
      ruoyi-ui/src/api/system/menu.js
  10. 2 2
      ruoyi-ui/src/api/system/notice.js
  11. 2 2
      ruoyi-ui/src/api/system/post.js
  12. 3 3
      ruoyi-ui/src/api/system/role.js
  13. 6 6
      ruoyi-ui/src/api/system/user.js
  14. 7 1
      ruoyi-ui/src/main.js
  15. 15 0
      ruoyi-ui/src/utils/ruoyi.js
  16. 202 0
      ruoyi-ui/src/views/infra/file/index.vue
  17. 13 54
      ruoyi-ui/src/views/system/dept/index.vue
  18. 14 59
      ruoyi-ui/src/views/system/dict/data.vue
  19. 17 79
      ruoyi-ui/src/views/system/dict/index.vue
  20. 14 58
      ruoyi-ui/src/views/system/loginlog/index.vue
  21. 19 71
      ruoyi-ui/src/views/system/menu/index.vue
  22. 13 68
      ruoyi-ui/src/views/system/notice/index.vue
  23. 14 63
      ruoyi-ui/src/views/system/operatelog/index.vue
  24. 15 60
      ruoyi-ui/src/views/system/post/index.vue
  25. 23 94
      ruoyi-ui/src/views/system/role/index.vue
  26. 665 715
      ruoyi-ui/src/views/system/user/index.vue
  27. 7 7
      ruoyi-ui/src/views/system/user/profile/userInfo.vue
  28. 37 5
      ruoyi-ui/src/views/tool/dbDoc/index.vue
  29. 8 0
      sql/quartz.sql
  30. 754 78
      sql/ruoyi-vue-pro.sql
  31. 2 2
      src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java
  32. 18 1
      src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java
  33. 26 0
      src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java
  34. 24 0
      src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java
  35. 1 1
      src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java
  36. 3 1
      src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java
  37. 3 1
      src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java
  38. 1 1
      src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java
  39. 1 1
      src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java
  40. 1 1
      src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java
  41. 63 19
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java
  42. 36 11
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java
  43. 35 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java
  44. 22 0
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFileRespVO.java
  45. 1 1
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java
  46. 1 1
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java
  47. 2 2
      src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java
  48. 18 0
      src/main/java/cn/iocoder/dashboard/modules/infra/convert/file/InfFileConvert.java
  49. 43 0
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/file/InfFileDO.java
  50. 1 1
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java
  51. 2 2
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
  52. 25 0
      src/main/java/cn/iocoder/dashboard/modules/infra/dal/mysql/file/InfFileMapper.java
  53. 3 0
      src/main/java/cn/iocoder/dashboard/modules/infra/enums/InfErrorCodeConstants.java
  54. 46 0
      src/main/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileService.java
  55. 72 0
      src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java
  56. 4 4
      src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java
  57. 5 3
      src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java
  58. 6 3
      src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java
  59. 9 7
      src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java
  60. 4 4
      src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java
  61. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java
  62. 36 35
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysDeptController.java
  63. 37 36
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java
  64. 43 41
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java
  65. 32 31
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java
  66. 15 10
      src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java
  67. 9 25
      src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java
  68. 26 26
      src/main/java/cn/iocoder/dashboard/modules/system/controller/notice/SysNoticeController.java
  69. 37 49
      src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.java
  70. 43 43
      src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java
  71. 58 65
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java
  72. 85 86
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java
  73. 53 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java
  74. 36 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVo.java
  75. 39 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java
  76. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserBaseVO.java
  77. 19 8
      src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java
  78. 18 1
      src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java
  79. 0 30
      src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/common/SysFileDO.java
  80. 0 15
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/common/SysFileMapper.java
  81. 8 0
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java
  82. 10 2
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java
  83. 3 0
      src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
  84. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
  85. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java
  86. 0 29
      src/main/java/cn/iocoder/dashboard/modules/system/service/common/SysFileService.java
  87. 0 47
      src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysFileServiceImpl.java
  88. 30 30
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java
  89. 25 25
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java
  90. 44 48
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java
  91. 30 28
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysPostServiceImpl.java
  92. 24 24
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java
  93. 22 22
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeService.java
  94. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
  95. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java
  96. 17 16
      src/main/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeService.java
  97. 10 10
      src/main/java/cn/iocoder/dashboard/modules/system/service/notice/impl/SysNoticeServiceImpl.java
  98. 24 24
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java
  99. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java
  100. 44 44
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleService.java

+ 1 - 1
README.md

@@ -50,6 +50,7 @@
 | --- | --- | --- |
 | 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
 | | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
+| 🚀 | 文件服务 | 支持本地文件存储,同时支持兼容 Amazon S3 协议的云服务、开源组件 | 
 | 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
 |  | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
 | | Redis 监控 |监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
@@ -64,7 +65,6 @@
 计划新增:
 * 工作流
 * 错误码
-* 文件服务
 
 ### 研发工具
 

+ 4 - 0
lombok.config

@@ -0,0 +1,4 @@
+config.stopBubbling = true
+lombok.tostring.callsuper=true
+lombok.equalsandhashcode.callsuper=true
+lombok.accessors.chain=true

+ 6 - 0
pom.xml

@@ -235,6 +235,12 @@
             <artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
             <version>${mapstruct.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct-processor</artifactId>
+            <version>${mapstruct.version}</version>
+            <optional>true</optional>
+        </dependency>
         <dependency>
             <groupId>org.mapstruct</groupId>
             <artifactId>mapstruct-jdk8</artifactId>

+ 16 - 0
ruoyi-ui/src/api/infra/dbDoc.js

@@ -8,3 +8,19 @@ export function exportHtml() {
     responseType: 'blob'
   })
 }
+
+export function exportWord() {
+  return request({
+    url: '/infra/db-doc/export-word',
+    method: 'get',
+    responseType: 'blob'
+  })
+}
+
+export function exportMarkdown() {
+  return request({
+    url: '/infra/db-doc/export-markdown',
+    method: 'get',
+    responseType: 'blob'
+  })
+}

+ 18 - 0
ruoyi-ui/src/api/infra/file.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// 删除文件
+export function deleteFile(id) {
+  return request({
+    url: '/infra/file/delete?id=' + id,
+    method: 'delete'
+  })
+}
+
+// 获得文件分页
+export function getFilePage(query) {
+  return request({
+    url: '/infra/file/page',
+    method: 'get',
+    params: query
+  })
+}

+ 2 - 2
ruoyi-ui/src/api/system/dept.js

@@ -46,7 +46,7 @@ export function addDept(data) {
 export function updateDept(data) {
   return request({
     url: '/system/dept/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -55,6 +55,6 @@ export function updateDept(data) {
 export function delDept(id) {
   return request({
     url: '/system/dept/delete?id=' + id,
-    method: 'post'
+    method: 'delete'
   })
 }

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

@@ -38,7 +38,7 @@ export function addData(data) {
 export function updateData(data) {
   return request({
     url: '/system/dict-data/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -47,7 +47,7 @@ export function updateData(data) {
 export function delData(dictCode) {
   return request({
     url: '/system/dict-data/delete?id=' + dictCode,
-    method: 'post'
+    method: 'delete'
   })
 }
 

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

@@ -30,7 +30,7 @@ export function addType(data) {
 export function updateType(data) {
   return request({
     url: '/system/dict-type/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -39,7 +39,7 @@ export function updateType(data) {
 export function delType(dictId) {
   return request({
     url: '/system/dict-type/delete?id=' + dictId,
-    method: 'post'
+    method: 'delete'
   })
 }
 

+ 2 - 2
ruoyi-ui/src/api/system/menu.js

@@ -38,7 +38,7 @@ export function addMenu(data) {
 export function updateMenu(data) {
   return request({
     url: '/system/menu/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -47,6 +47,6 @@ export function updateMenu(data) {
 export function delMenu(id) {
   return request({
     url: '/system/menu/delete?id=' + id,
-    method: 'post'
+    method: 'delete'
   })
 }

+ 2 - 2
ruoyi-ui/src/api/system/notice.js

@@ -30,7 +30,7 @@ export function addNotice(data) {
 export function updateNotice(data) {
   return request({
     url: '/system/notice/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -39,6 +39,6 @@ export function updateNotice(data) {
 export function delNotice(noticeId) {
   return request({
     url: '/system/notice/delete?id=' + noticeId,
-    method: 'post'
+    method: 'delete'
   })
 }

+ 2 - 2
ruoyi-ui/src/api/system/post.js

@@ -38,7 +38,7 @@ export function addPost(data) {
 export function updatePost(data) {
   return request({
     url: '/system/post/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -47,7 +47,7 @@ export function updatePost(data) {
 export function delPost(postId) {
   return request({
     url: '/system/post/delete?id=' + postId,
-    method: 'post'
+    method: 'delete'
   })
 }
 

+ 3 - 3
ruoyi-ui/src/api/system/role.js

@@ -38,7 +38,7 @@ export function addRole(data) {
 export function updateRole(data) {
   return request({
     url: '/system/role/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -51,7 +51,7 @@ export function changeRoleStatus(id, status) {
   }
   return request({
     url: '/system/role/update-status',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -60,7 +60,7 @@ export function changeRoleStatus(id, status) {
 export function delRole(roleId) {
   return request({
     url: '/system/role/delete?id=' + roleId,
-    method: 'post'
+    method: 'delete'
   })
 }
 

+ 6 - 6
ruoyi-ui/src/api/system/user.js

@@ -31,7 +31,7 @@ export function addUser(data) {
 export function updateUser(data) {
   return request({
     url: '/system/user/update',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -62,7 +62,7 @@ export function resetUserPwd(id, password) {
   }
   return request({
     url: '/system/user/update-password',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -75,7 +75,7 @@ export function changeUserStatus(id, status) {
   }
   return request({
     url: '/system/user/update-status',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }
@@ -83,7 +83,7 @@ export function changeUserStatus(id, status) {
 // 查询用户个人信息
 export function getUserProfile() {
   return request({
-    url: '/system/user/profile',
+    url: '/system/user/profile/get',
     method: 'get'
   })
 }
@@ -91,7 +91,7 @@ export function getUserProfile() {
 // 修改用户个人信息
 export function updateUserProfile(data) {
   return request({
-    url: '/system/user/profile',
+    url: '/system/user/profile/update',
     method: 'put',
     data: data
   })
@@ -114,7 +114,7 @@ export function updateUserPwd(oldPassword, newPassword) {
 export function uploadAvatar(data) {
   return request({
     url: '/system/user/profile/avatar',
-    method: 'post',
+    method: 'put',
     data: data
   })
 }

+ 7 - 1
ruoyi-ui/src/main.js

@@ -25,7 +25,10 @@ import {
   download,
   handleTree,
   downloadExcel,
-  downloadZip
+  downloadWord,
+  downloadZip,
+  downloadHtml,
+  downloadMarkdown,
 } from "@/utils/ruoyi";
 import Pagination from "@/components/Pagination";
 // 自定义表格工具扩展
@@ -48,6 +51,9 @@ Vue.prototype.getDictDataLabel = getDictDataLabel
 Vue.prototype.DICT_TYPE = DICT_TYPE
 Vue.prototype.download = download
 Vue.prototype.downloadExcel = downloadExcel
+Vue.prototype.downloadWord = downloadWord
+Vue.prototype.downloadHtml = downloadHtml
+Vue.prototype.downloadMarkdown = downloadMarkdown
 Vue.prototype.downloadZip = downloadZip
 Vue.prototype.handleTree = handleTree
 

+ 15 - 0
ruoyi-ui/src/utils/ruoyi.js

@@ -120,11 +120,26 @@ export function downloadExcel(data, fileName) {
   download0(data, fileName, 'application/vnd.ms-excel');
 }
 
+// 下载 Word 方法
+export function downloadWord(data, fileName) {
+  download0(data, fileName, 'application/msword');
+}
+
 // 下载 Zip 方法
 export function downloadZip(data, fileName) {
   download0(data, fileName, 'application/zip');
 }
 
+// 下载 Html 方法
+export function downloadHtml(data, fileName) {
+  download0(data, fileName, 'text/html');
+}
+
+// 下载 Markdown 方法
+export function downloadMarkdown(data, fileName) {
+  download0(data, fileName, 'text/markdown');
+}
+
 function download0(data, fileName, mineType) {
   // 创建 blob
   let blob = new Blob([data], {type: mineType});

+ 202 - 0
ruoyi-ui/src/views/infra/file/index.vue

@@ -0,0 +1,202 @@
+<template>
+  <div class="app-container">
+
+    <!-- 搜索工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="文件路径" prop="id">
+        <el-input v-model="queryParams.id" placeholder="请输入文件路径" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="文件类型" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择文件类型" clearable size="small">
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作工具栏 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">上传文件</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <!-- 列表 -->
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="文件路径" align="center" prop="id" width="300" />
+      <el-table-column label="文件类型" align="center" prop="type" width="80" />
+      <el-table-column label="文件内容" align="center" prop="content">
+        <template slot-scope="scope">
+          <img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'"
+               width="200px" :src="getFileUrl + scope.row.id">
+          <i v-else>非图片,无法预览</i>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['infra:file:delete']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页组件 -->
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
+
+    <!-- 对话框(添加 / 修改) -->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload ref="upload" :limit="1" accept=".jpg, .png, .gif" :auto-upload="false" drag
+                 :headers="upload.headers" :action="upload.url" :data="upload.data" :disabled="upload.isUploading"
+                 :on-change="handleFileChange"
+                 :on-progress="handleFileUploadProgress"
+                 :on-success="handleFileSuccess">
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          将文件拖到此处,或 <em>点击上传</em>
+        </div>
+        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入 jpg、png、gif 格式文件!</div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button @click="upload.open = false">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import { deleteFile, getFilePage } from "@/api/infra/file";
+import {getToken} from "@/utils/auth";
+
+export default {
+  name: "File",
+  data() {
+    return {
+      getFileUrl: process.env.VUE_APP_BASE_API + '/api/infra/file/get/',
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 文件列表
+      list: [],
+      // 弹出层标题
+      title: "",
+      dateRangeCreateTime: [],
+      // 查询参数
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        id: null,
+        type: null,
+      },
+      // 用户导入参数
+      upload: {
+        open: false, // 是否显示弹出层
+        title: "", // 弹出层标题
+        isUploading: false, // 是否禁用上传
+        url: process.env.VUE_APP_BASE_API + '/api/' + "/infra/file/upload", // 请求地址
+        headers: { Authorization: "Bearer " + getToken() }, // 设置上传的请求头部
+        data: {} // 上传的额外数据,用于文件名
+      },
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询列表 */
+    getList() {
+      this.loading = true;
+      // 处理查询参数
+      let params = {...this.queryParams};
+      this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
+      // 执行查询
+      getFilePage(params).then(response => {
+        this.list = response.data.list;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    /** 取消按钮 */
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        content: undefined,
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRangeCreateTime = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.upload.open = true;
+      this.upload.title = "上传文件";
+    },
+    /** 处理上传的文件发生变化 */
+    handleFileChange(file, fileList) {
+      this.upload.data.path = file.name;
+    },
+    /** 处理文件上传中 */
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true; // 禁止修改
+    },
+    /** 发起文件上窜 */
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
+    /** 文件上传成功处理 */
+    handleFileSuccess(response, file, fileList) {
+      // 清理
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      // 提示成功,并刷新
+      this.msgSuccess("上传成功");
+      this.getList();
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const id = row.id;
+      this.$confirm('是否确认删除文件编号为"' + id + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return deleteFile(id);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      })
+    },
+  }
+};
+</script>

+ 13 - 54
ruoyi-ui/src/views/system/dept/index.vue

@@ -2,22 +2,11 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
       <el-form-item label="部门名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入部门名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.name" placeholder="请输入部门名称" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="菜单状态" clearable size="small">
-          <el-option
-              v-for="dict in statusDictDatas"
-              :key="parseInt(dict.value)"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-          />
+          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -28,24 +17,13 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:dept:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:dept:create']">新增</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table
-      v-loading="loading"
-      :data="deptList"
-      row-key="id"
-      default-expand-all
-      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
-    >
+    <el-table v-loading="loading" :data="deptList" row-key="id" default-expand-all
+              :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
       <el-table-column prop="name" label="部门名称" width="260"></el-table-column>
       <el-table-column prop="sort" label="排序" width="200"></el-table-column>
       <el-table-column prop="status" label="状态" :formatter="statusFormat" width="100"></el-table-column>
@@ -56,28 +34,12 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:dept:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-plus"
-            @click="handleAdd(scope.row)"
-            v-hasPermi="['system:dept:add']"
-          >新增</el-button>
-          <el-button
-            v-if="scope.row.parentId !== 0"
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:dept:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:dept:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)"
+                     v-hasPermi="['system:dept:create']">新增</el-button>
+          <el-button v-if="scope.row.parentId !== 0" size="mini" type="text" icon="el-icon-delete"
+                     @click="handleDelete(scope.row)" v-hasPermi="['system:dept:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -119,11 +81,8 @@
           <el-col :span="12">
             <el-form-item label="部门状态" prop="status">
               <el-radio-group v-model="form.status">
-                <el-radio
-                    v-for="dict in statusDictDatas"
-                    :key="parseInt(dict.value)"
-                    :label="parseInt(dict.value)"
-                >{{dict.label}}</el-radio>
+                <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-col>

+ 14 - 59
ruoyi-ui/src/views/system/dict/data.vue

@@ -3,31 +3,15 @@
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="字典名称" prop="dictType">
         <el-select v-model="queryParams.dictType" size="small">
-          <el-option
-            v-for="item in typeOptions"
-            :key="item.id"
-            :label="item.name"
-            :value="item.type"
-          />
+          <el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.type"/>
         </el-select>
       </el-form-item>
       <el-form-item label="字典标签" prop="label">
-        <el-input
-          v-model="queryParams.label"
-          placeholder="请输入字典标签"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.label" placeholder="请输入字典标签" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="数据状态" clearable size="small">
-          <el-option
-            v-for="dict in statusOptions"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in statusOptions" :key="dict.value" :label="dict.label" :value="dict.value"/>
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -38,22 +22,12 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:dict:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:dict:create']">新增</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:dict:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:dict:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -72,31 +46,16 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:dict:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:dict:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:dict:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:dict:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNo"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
 
     <!-- 添加或修改参数配置对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@@ -115,11 +74,7 @@
         </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-radio-group v-model="form.status">
-            <el-radio
-                v-for="dict in statusDictDatas"
-                :key="parseInt(dict.value)"
-                :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
+            <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">

+ 17 - 79
ruoyi-ui/src/views/system/dict/index.vue

@@ -2,52 +2,19 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="字典名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入字典名称"
-          clearable
-          size="small"
-          style="width: 240px"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.name" placeholder="请输入字典名称" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="字典类型" prop="type">
-        <el-input
-          v-model="queryParams.type"
-          placeholder="请输入字典类型"
-          clearable
-          size="small"
-          style="width: 240px"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.type" placeholder="请输入字典类型" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select
-          v-model="queryParams.status"
-          placeholder="字典状态"
-          clearable
-          size="small"
-          style="width: 240px"
-        >
-          <el-option
-              v-for="dict in statusDictDatas"
-              :key="parseInt(dict.value)"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-          />
+        <el-select v-model="queryParams.status" placeholder="字典状态" clearable size="small" style="width: 240px">
+          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间">
-        <el-date-picker
-          v-model="dateRangeCreateTime"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
+        <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
       </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -57,22 +24,12 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:dict:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:dict:create']">新增</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:dict:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:dict:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -96,31 +53,16 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:dict:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:dict:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:dict:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:dict:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNo"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
 
     <!-- 添加或修改参数配置对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@@ -133,11 +75,7 @@
         </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-radio-group v-model="form.status">
-            <el-radio
-                v-for="dict in statusDictDatas"
-                :key="parseInt(dict.value)"
-                :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
+            <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">

+ 14 - 58
ruoyi-ui/src/views/system/loginlog/index.vue

@@ -2,56 +2,22 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="登录地址" prop="userIp">
-        <el-input
-          v-model="queryParams.userIp"
-          placeholder="请输入登录地址"
-          clearable
-          style="width: 240px;"
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.userIp" placeholder="请输入登录地址" clearable style="width: 240px;" size="small"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="用户名称" prop="username">
-        <el-input
-          v-model="queryParams.username"
-          placeholder="请输入用户名称"
-          clearable
-          style="width: 240px;"
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.username" placeholder="请输入用户名称" clearable style="width: 240px;" size="small"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select
-          v-model="queryParams.status"
-          placeholder="结果"
-          clearable
-          size="small"
-          style="width: 240px"
-        >
-          <el-option
-              :key="true"
-              label="成功"
-              :value="true"
-          />
-          <el-option
-              :key="false"
-              label="失败"
-              :value="false"
-          />
+        <el-select v-model="queryParams.status" placeholder="结果" clearable size="small" style="width: 240px">
+          <el-option :key="true" label="成功" :value="true"/>
+          <el-option :key="false" label="失败" :value="false"/>
         </el-select>
       </el-form-item>
       <el-form-item label="登录时间">
-        <el-date-picker
-          v-model="dateRange"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
+        <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+          type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
       </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -61,13 +27,8 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:login-log:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:login-log:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -76,7 +37,7 @@
       <el-table-column label="访问编号" align="center" prop="id" />
       <el-table-column label="日志类型" align="center" prop="logType">
         <template slot-scope="scope">
-          <span>{{ scope.row.logType === 1 ? '登录' : '退出' }}</span>
+          <span>{{ scope.row.logType === 100 ? '登录' : '退出' }}</span>
         </template>
       </el-table-column>
       <el-table-column label="用户名称" align="center" prop="username" />
@@ -95,13 +56,8 @@
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNo"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
   </div>
 </template>
 

+ 19 - 71
ruoyi-ui/src/views/system/menu/index.vue

@@ -2,22 +2,11 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
       <el-form-item label="菜单名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入菜单名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.name" placeholder="请输入菜单名称" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="菜单状态" clearable size="small">
-          <el-option
-            v-for="dict in statusDictDatas"
-            :key="parseInt(dict.value)"
-            :label="dict.label"
-            :value="parseInt(dict.value)"
-          />
+          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -28,23 +17,14 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:menu:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:menu:create']">新增</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table
-      v-loading="loading"
-      :data="menuList"
-      row-key="id"
-      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
-    >
+    <el-table v-loading="loading" :data="menuList" row-key="id"
+              :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
       <el-table-column prop="name" label="菜单名称" :show-overflow-tooltip="true" width="200"></el-table-column>
       <el-table-column prop="icon" label="图标" align="center" width="100">
         <template slot-scope="scope">
@@ -62,26 +42,12 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:menu:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-plus"
-            @click="handleAdd(scope.row)"
-            v-hasPermi="['system:menu:add']"
-          >新增</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:menu:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:menu:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)"
+                     v-hasPermi="['system:menu:create']">新增</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:menu:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -92,43 +58,25 @@
         <el-row>
           <el-col :span="24">
             <el-form-item label="上级菜单">
-              <treeselect
-                v-model="form.parentId"
-                :options="menuOptions"
-                :normalizer="normalizer"
-                :show-count="true"
-                placeholder="选择上级菜单"
-              />
+              <treeselect v-model="form.parentId" :options="menuOptions" :normalizer="normalizer" :show-count="true"
+                          placeholder="选择上级菜单"/>
             </el-form-item>
           </el-col>
           <el-col :span="24">
             <el-form-item label="菜单类型" prop="type">
               <el-radio-group v-model="form.type">
-                <el-radio
-                    v-for="dict in menuTypeDictDatas"
-                    :key="parseInt(dict.value)"
-                    :label="parseInt(dict.value)"
-                >{{dict.label}}</el-radio>
+                <el-radio v-for="dict in menuTypeDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
+                  {{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
           <el-col :span="24">
             <el-form-item v-if="form.type != '3'" label="菜单图标">
-              <el-popover
-                placement="bottom-start"
-                width="460"
-                trigger="click"
-                @show="$refs['iconSelect'].reset()"
-              >
+              <el-popover placement="bottom-start" width="460" trigger="click" @show="$refs['iconSelect'].reset()">
                 <IconSelect ref="iconSelect" @selected="selected" />
                 <el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
-                  <svg-icon
-                    v-if="form.icon"
-                    slot="prefix"
-                    :icon-class="form.icon"
-                    class="el-input__icon"
-                    style="height: 32px;width: 16px;"
-                  />
+                  <svg-icon v-if="form.icon" slot="prefix" :icon-class="form.icon" class="el-input__icon"
+                            style="height: 32px;width: 16px;"/>
                   <i v-else slot="prefix" class="el-icon-search el-input__icon" />
                 </el-input>
               </el-popover>

+ 13 - 68
ruoyi-ui/src/views/system/notice/index.vue

@@ -2,31 +2,14 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="公告标题" prop="title">
-        <el-input
-          v-model="queryParams.title"
-          placeholder="请输入公告标题"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.title" placeholder="请输入公告标题" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="操作人员" prop="createBy">
-        <el-input
-          v-model="queryParams.createBy"
-          placeholder="请输入操作人员"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.createBy" placeholder="请输入操作人员" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="类型" prop="type">
         <el-select v-model="queryParams.type" placeholder="公告类型" clearable size="small">
-          <el-option
-              v-for="dict in noticeTypeDictDatas"
-              :key="parseInt(dict.value)"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-          />
+          <el-option v-for="dict in noticeTypeDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -37,39 +20,16 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:notice:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:notice:create']"s>新增</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
     <el-table v-loading="loading" :data="noticeList">
       <el-table-column label="序号" align="center" prop="id" width="100" />
-      <el-table-column
-        label="公告标题"
-        align="center"
-        prop="title"
-        :show-overflow-tooltip="true"
-      />
-      <el-table-column
-        label="公告类型"
-        align="center"
-        prop="type"
-        :formatter="typeFormat"
-        width="100"
-      />
-      <el-table-column
-        label="状态"
-        align="center"
-        prop="status"
-        :formatter="statusFormat"
-        width="100"
-      />
+      <el-table-column label="公告标题" align="center" prop="title" :show-overflow-tooltip="true"/>
+      <el-table-column label="公告类型" align="center" prop="type" :formatter="typeFormat" width="100"/>
+      <el-table-column label="状态" align="center" prop="status" :formatter="statusFormat" width="100"/>
       <el-table-column label="创建者" align="center" prop="createBy" width="100" />
       <el-table-column label="创建时间" align="center" prop="createTime" width="100">
         <template slot-scope="scope">
@@ -78,31 +38,16 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:notice:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:notice:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:notice:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:notice:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNo"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
 
     <!-- 添加或修改公告对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body>

+ 14 - 63
ruoyi-ui/src/views/system/operatelog/index.vue

@@ -2,72 +2,28 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="系统模块" prop="title">
-        <el-input
-          v-model="queryParams.title"
-          placeholder="请输入系统模块"
-          clearable
-          style="width: 240px;"
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable style="width: 240px;" size="small"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="操作人员" prop="operName">
-        <el-input
-          v-model="queryParams.operName"
-          placeholder="请输入操作人员"
-          clearable
-          style="width: 240px;"
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.operName" placeholder="请输入操作人员" clearable style="width: 240px;" size="small"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="类型" prop="type">
-        <el-select
-          v-model="queryParams.type"
-          placeholder="操作类型"
-          clearable
-          size="small"
-          style="width: 240px"
-        >
-          <el-option
-            v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)"
-            :key="parseInt(dict.value)"
-            :label="dict.label"
-            :value="parseInt(dict.value)"
-          />
+        <el-select v-model="queryParams.type" placeholder="操作类型" clearable size="small" style="width: 240px">
+          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)" :key="parseInt(dict.value)"
+                     :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select
-          v-model="queryParams.success"
-          placeholder="操作状态"
-          clearable
-          size="small"
-          style="width: 240px"
-        >
-          <el-option
-              :key="true"
-              label="成功"
-              :value="true"
-          />
-          <el-option
-              :key="false"
-              label="失败"
-              :value="false"
-          />
+        <el-select v-model="queryParams.success" placeholder="操作状态" clearable size="small" style="width: 240px">
+          <el-option :key="true" label="成功" :value="true"/>
+          <el-option :key="false" label="失败" :value="false"/>
         </el-select>
       </el-form-item>
       <el-form-item label="操作时间">
-        <el-date-picker
-          v-model="dateRange"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
+        <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+          type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
       </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -77,13 +33,8 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:config:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:operate-log:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>

+ 15 - 60
ruoyi-ui/src/views/system/post/index.vue

@@ -2,31 +2,14 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="岗位编码" prop="code">
-        <el-input
-          v-model="queryParams.code"
-          placeholder="请输入岗位编码"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.code" placeholder="请输入岗位编码" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="岗位名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入岗位名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.name" placeholder="请输入岗位名称" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="岗位状态" clearable size="small">
-          <el-option
-              v-for="dict in statusDictDatas"
-              :key="parseInt(dict.value)"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-          />
+          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -37,22 +20,12 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:post:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:post:create']">新增</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:post:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:post:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -70,31 +43,16 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:post:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:post:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:post:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:post:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNo"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
 
     <!-- 添加或修改岗位对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@@ -110,11 +68,8 @@
         </el-form-item>
         <el-form-item label="岗位状态" prop="status">
           <el-radio-group v-model="form.status">
-            <el-radio
-                v-for="dict in statusDictDatas"
-                :key="parseInt(dict.value)"
-                :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
+            <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">

+ 23 - 94
ruoyi-ui/src/views/system/role/index.vue

@@ -2,52 +2,21 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" v-show="showSearch" :inline="true">
       <el-form-item label="角色名称" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入角色名称"
-          clearable
-          size="small"
-          style="width: 240px"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.name" placeholder="请输入角色名称" clearable size="small" style="width: 240px"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="角色标识" prop="code">
-        <el-input
-          v-model="queryParams.code"
-          placeholder="请输入角色标识"
-          clearable
-          size="small"
-          style="width: 240px"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.code" placeholder="请输入角色标识" clearable size="small" style="width: 240px"
+                  @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="状态" prop="status">
-        <el-select
-          v-model="queryParams.status"
-          placeholder="角色状态"
-          clearable
-          size="small"
-          style="width: 240px"
-        >
-          <el-option
-              v-for="dict in statusDictDatas"
-              :key="parseInt(dict.value)"
-              :label="dict.label"
-              :value="parseInt(dict.value)"
-          />
+        <el-select v-model="queryParams.status" placeholder="角色状态" clearable size="small" style="width: 240px">
+          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
         </el-select>
       </el-form-item>
       <el-form-item label="创建时间">
-        <el-date-picker
-          v-model="dateRange"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
+        <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
       </el-form-item>
       <el-form-item>
         <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -57,22 +26,12 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['system:role:add']"
-        >新增</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:role:create']">新增</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['system:role:export']"
-        >导出</el-button>
+        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:role:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -85,12 +44,7 @@
       <el-table-column label="显示顺序" prop="sort" width="100" />
       <el-table-column label="状态" align="center" width="100">
         <template slot-scope="scope">
-          <el-switch
-            v-model="scope.row.status"
-            :active-value="0"
-            :inactive-value="1"
-            @change="handleStatusChange(scope.row)"
-          ></el-switch>
+          <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
         </template>
       </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" width="180">
@@ -100,45 +54,20 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:role:edit']"
-          >修改</el-button>
-          <el-button
-              size="mini"
-              type="text"
-              icon="el-icon-circle-check"
-              @click="handleMenu(scope.row)"
-              v-hasPermi="['system:permission:assign-role-menu']"
-          >菜单权限</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-circle-check"
-            @click="handleDataScope(scope.row)"
-            v-hasPermi="['system:permission:assign-role-data-scope']"
-          >数据权限</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['system:role:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:role:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-circle-check" @click="handleMenu(scope.row)"
+                     v-hasPermi="['system:permission:assign-role-menu']">菜单权限</el-button>
+          <el-button size="mini" type="text" icon="el-icon-circle-check" @click="handleDataScope(scope.row)"
+                     v-hasPermi="['system:permission:assign-role-data-scope']">数据权限</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:role:delete']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNum"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
 
     <!-- 添加或修改角色配置对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>

+ 665 - 715
ruoyi-ui/src/views/system/user/index.vue

@@ -1,715 +1,665 @@
-<template>
-  <div class="app-container">
-    <el-row :gutter="20">
-      <!--部门数据-->
-      <el-col :span="4" :xs="24">
-        <div class="head-container">
-          <el-input
-            v-model="deptName"
-            placeholder="请输入部门名称"
-            clearable
-            size="small"
-            prefix-icon="el-icon-search"
-            style="margin-bottom: 20px"
-          />
-        </div>
-        <div class="head-container">
-          <el-tree
-            :data="deptOptions"
-            :props="defaultProps"
-            :expand-on-click-node="false"
-            :filter-node-method="filterNode"
-            ref="tree"
-            default-expand-all
-            @node-click="handleNodeClick"
-          />
-        </div>
-      </el-col>
-      <!--用户数据-->
-      <el-col :span="20" :xs="24">
-        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-          <el-form-item label="用户名称" prop="username">
-            <el-input
-              v-model="queryParams.username"
-              placeholder="请输入用户名称"
-              clearable
-              size="small"
-              style="width: 240px"
-              @keyup.enter.native="handleQuery"
-            />
-          </el-form-item>
-          <el-form-item label="手机号码" prop="mobile">
-            <el-input
-              v-model="queryParams.mobile"
-              placeholder="请输入手机号码"
-              clearable
-              size="small"
-              style="width: 240px"
-              @keyup.enter.native="handleQuery"
-            />
-          </el-form-item>
-          <el-form-item label="状态" prop="status">
-            <el-select
-              v-model="queryParams.status"
-              placeholder="用户状态"
-              clearable
-              size="small"
-              style="width: 240px"
-            >
-              <el-option
-                  v-for="dict in statusDictDatas"
-                  :key="parseInt(dict.value)"
-                  :label="dict.label"
-                  :value="parseInt(dict.value)"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="创建时间">
-            <el-date-picker
-              v-model="dateRange"
-              size="small"
-              style="width: 240px"
-              value-format="yyyy-MM-dd"
-              type="daterange"
-              range-separator="-"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
-            ></el-date-picker>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
-
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button
-              type="primary"
-              icon="el-icon-plus"
-              size="mini"
-              @click="handleAdd"
-              v-hasPermi="['system:user:add']"
-            >新增</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button
-              type="info"
-              icon="el-icon-upload2"
-              size="mini"
-              @click="handleImport"
-              v-hasPermi="['system:user:import']"
-            >导入</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button
-              type="warning"
-              icon="el-icon-download"
-              size="mini"
-              @click="handleExport"
-              v-hasPermi="['system:user:export']"
-            >导出</el-button>
-          </el-col>
-          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-
-        <el-table v-loading="loading" :data="userList">
-          <el-table-column label="用户编号" align="center" prop="id" />
-          <el-table-column label="用户名称" align="center" prop="username" :show-overflow-tooltip="true" />
-          <el-table-column label="用户昵称" align="center" prop="nickname" :show-overflow-tooltip="true" />
-          <el-table-column label="部门" align="center" prop="dept.name" :show-overflow-tooltip="true" />
-          <el-table-column label="手机号码" align="center" prop="mobile" width="120" />
-          <el-table-column label="状态" align="center">
-            <template slot-scope="scope">
-              <el-switch
-                  v-model="scope.row.status"
-                  :active-value="0"
-                  :inactive-value="1"
-                  @change="handleStatusChange(scope.row)"
-              ></el-switch>
-            </template>
-          </el-table-column>
-          <el-table-column label="创建时间" align="center" prop="createTime" width="160">
-            <template slot-scope="scope">
-              <span>{{ parseTime(scope.row.createTime) }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column
-            label="操作"
-            align="center"
-            width="160"
-            class-name="small-padding fixed-width"
-          >
-            <template slot-scope="scope">
-              <el-button
-                size="mini"
-                type="text"
-                icon="el-icon-edit"
-                @click="handleUpdate(scope.row)"
-                v-hasPermi="['system:user:edit']"
-              >修改</el-button>
-              <el-button
-                v-if="scope.row.id !== 1"
-                size="mini"
-                type="text"
-                icon="el-icon-delete"
-                @click="handleDelete(scope.row)"
-                v-hasPermi="['system:user:remove']"
-              >删除</el-button>
-              <el-button
-                size="mini"
-                type="text"
-                icon="el-icon-key"
-                @click="handleResetPwd(scope.row)"
-                v-hasPermi="['system:user:resetPwd']"
-              >重置</el-button>
-              <el-button
-                  size="mini"
-                  type="text"
-                  icon="el-icon-circle-check"
-                  @click="handleRole(scope.row)"
-                  v-hasPermi="['system:permission:assign-user-role']"
-              >分配角色</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-
-        <pagination
-          v-show="total>0"
-          :total="total"
-          :page.sync="queryParams.pageNo"
-          :limit.sync="queryParams.pageSize"
-          @pagination="getList"
-        />
-      </el-col>
-    </el-row>
-
-    <!-- 添加或修改参数配置对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="用户昵称" prop="nickname">
-              <el-input v-model="form.nickname" placeholder="请输入用户昵称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="归属部门" prop="deptId">
-              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true"
-                          placeholder="请选择归属部门" :normalizer="normalizer"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="手机号码" prop="mobile">
-              <el-input v-model="form.mobile" placeholder="请输入手机号码" maxlength="11" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="邮箱" prop="email">
-              <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item v-if="form.id === undefined" label="用户名称" prop="username">
-              <el-input v-model="form.username" placeholder="请输入用户名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item v-if="form.id === undefined" label="用户密码" prop="password">
-              <el-input v-model="form.password" placeholder="请输入用户密码" type="password" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="用户性别">
-              <el-select v-model="form.sex" placeholder="请选择">
-                <el-option
-                  v-for="dict in sexDictDatas"
-                  :key="parseInt(dict.value)"
-                  :label="dict.label"
-                  :value="parseInt(dict.value)"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="岗位">
-              <el-select v-model="form.postIds" multiple placeholder="请选择">
-                <el-option
-                    v-for="item in postOptions"
-                    :key="item.id"
-                    :label="item.name"
-                    :value="item.id"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="备注">
-              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 用户导入对话框 -->
-    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
-      <el-upload
-        ref="upload"
-        :limit="1"
-        accept=".xlsx, .xls"
-        :headers="upload.headers"
-        :action="upload.url + '?updateSupport=' + upload.updateSupport"
-        :disabled="upload.isUploading"
-        :on-progress="handleFileUploadProgress"
-        :on-success="handleFileSuccess"
-        :auto-upload="false"
-        drag
-      >
-        <i class="el-icon-upload"></i>
-        <div class="el-upload__text">
-          将文件拖到此处,或
-          <em>点击上传</em>
-        </div>
-        <div class="el-upload__tip" slot="tip">
-          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
-          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
-        </div>
-        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
-      </el-upload>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitFileForm">确 定</el-button>
-        <el-button @click="upload.open = false">取 消</el-button>
-      </div>
-    </el-dialog>
-
-    <!-- 分配角色 -->
-    <el-dialog title="分配角色" :visible.sync="openRole" width="500px" append-to-body>
-      <el-form :model="form" label-width="80px">
-        <el-form-item label="用户名称">
-          <el-input v-model="form.username" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="用户昵称">
-          <el-input v-model="form.nickname" :disabled="true" />
-        </el-form-item>
-        <el-form-item label="角色">
-          <el-select v-model="form.roleIds" multiple placeholder="请选择">
-            <el-option
-                v-for="item in roleOptions"
-                :key="parseInt(item.id)"
-                :label="item.name"
-                :value="parseInt(item.id)"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitRole">确 定</el-button>
-        <el-button @click="cancelRole">取 消</el-button>
-      </div>
-    </el-dialog>
-
-  </div>
-</template>
-
-<script>
-import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from "@/api/system/user";
-import { getToken } from "@/utils/auth";
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-
-import {listSimpleDepts} from "@/api/system/dept";
-import {listSimplePosts} from "@/api/system/post";
-
-import {SysCommonStatusEnum} from "@/utils/constants";
-import {DICT_TYPE, getDictDatas} from "@/utils/dict";
-import {assignUserRole, listUserRoles} from "@/api/system/permission";
-import {listSimpleRoles} from "@/api/system/role";
-
-export default {
-  name: "User",
-  components: { Treeselect },
-  data() {
-    return {
-      // 遮罩层
-      loading: true,
-      // 显示搜索条件
-      showSearch: true,
-      // 总条数
-      total: 0,
-      // 用户表格数据
-      userList: null,
-      // 弹出层标题
-      title: "",
-      // 部门树选项
-      deptOptions: undefined,
-      // 是否显示弹出层
-      open: false,
-      // 部门名称
-      deptName: undefined,
-      // 默认密码
-      initPassword: undefined,
-      // 日期范围
-      dateRange: [],
-      // 状态数据字典
-      statusOptions: [],
-      // 性别状态字典
-      sexOptions: [],
-      // 岗位选项
-      postOptions: [],
-      // 角色选项
-      roleOptions: [],
-      // 表单参数
-      form: {},
-      defaultProps: {
-        children: "children",
-        label: "name"
-      },
-      // 用户导入参数
-      upload: {
-        // 是否显示弹出层(用户导入)
-        open: false,
-        // 弹出层标题(用户导入)
-        title: "",
-        // 是否禁用上传
-        isUploading: false,
-        // 是否更新已经存在的用户数据
-        updateSupport: 0,
-        // 设置上传的请求头部
-        headers: { Authorization: "Bearer " + getToken() },
-        // 上传的地址
-        url: process.env.VUE_APP_BASE_API + '/api/' + "/system/user/import"
-      },
-      // 查询参数
-      queryParams: {
-        pageNo: 1,
-        pageSize: 10,
-        username: undefined,
-        mobile: undefined,
-        status: undefined,
-        deptId: undefined
-      },
-      // 表单校验
-      rules: {
-        username: [
-          { required: true, message: "用户名称不能为空", trigger: "blur" }
-        ],
-        nickname: [
-          { required: true, message: "用户昵称不能为空", trigger: "blur" }
-        ],
-        password: [
-          { required: true, message: "用户密码不能为空", trigger: "blur" }
-        ],
-        email: [
-          {
-            type: "email",
-            message: "'请输入正确的邮箱地址",
-            trigger: ["blur", "change"]
-          }
-        ],
-        mobile: [
-          {
-            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
-            message: "请输入正确的手机号码",
-            trigger: "blur"
-          }
-        ]
-      },
-      // 是否显示弹出层(角色权限)
-      openRole: false,
-
-      // 枚举
-      SysCommonStatusEnum: SysCommonStatusEnum,
-      // 数据字典
-      statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
-      sexDictDatas: getDictDatas(DICT_TYPE.SYS_USER_SEX),
-    };
-  },
-  watch: {
-    // 根据名称筛选部门树
-    deptName(val) {
-      this.$refs.tree.filter(val);
-    }
-  },
-  created() {
-    this.getList();
-    this.getTreeselect();
-    this.getConfigKey("sys.user.initPassword").then(response => {
-      this.initPassword = response.msg;
-    });
-  },
-  methods: {
-    /** 查询用户列表 */
-    getList() {
-      this.loading = true;
-      listUser(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.userList = response.data.list;
-          this.total = response.data.total;
-          this.loading = false;
-        }
-      );
-    },
-    /** 查询部门下拉树结构 + 岗位下拉 */
-    getTreeselect() {
-      listSimpleDepts().then(response => {
-        // 处理 deptOptions 参数
-        this.deptOptions = [];
-        this.deptOptions.push(...this.handleTree(response.data, "id"));
-      });
-      listSimplePosts().then(response => {
-        // 处理 postOptions 参数
-        this.postOptions = [];
-        this.postOptions.push(...response.data);
-      });
-    },
-    // 筛选节点
-    filterNode(value, data) {
-      if (!value) return true;
-      return data.name.indexOf(value) !== -1;
-    },
-    // 节点单击事件
-    handleNodeClick(data) {
-      this.queryParams.deptId = data.id;
-      this.getList();
-    },
-    // 用户状态修改
-    handleStatusChange(row) {
-      let text = row.status === SysCommonStatusEnum.ENABLE ? "启用" : "停用";
-      this.$confirm('确认要"' + text + '""' + row.username + '"用户吗?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return changeUserStatus(row.id, row.status);
-        }).then(() => {
-          this.msgSuccess(text + "成功");
-        }).catch(function() {
-          row.status = row.status === SysCommonStatusEnum.ENABLE ? SysCommonStatusEnum.DISABLE
-              : SysCommonStatusEnum.ENABLE;
-        });
-    },
-    // 取消按钮
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    // 取消按钮(角色权限)
-    cancelRole() {
-      this.openRole = false;
-      this.reset();
-    },
-    // 表单重置
-    reset() {
-      this.form = {
-        id: undefined,
-        deptId: undefined,
-        username: undefined,
-        nickname: undefined,
-        password: undefined,
-        mobile: undefined,
-        email: undefined,
-        sex: undefined,
-        status: "0",
-        remark: undefined,
-        postIds: [],
-        roleIds: []
-      };
-      this.resetForm("form");
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.queryParams.pageNo = 1;
-      this.getList();
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.dateRange = [];
-      this.resetForm("queryForm");
-      this.handleQuery();
-    },
-    /** 新增按钮操作 */
-    handleAdd() {
-      this.reset();
-      // 获得下拉数据
-      this.getTreeselect();
-      // 打开表单,并设置初始化
-      this.open = true;
-      this.title = "添加用户";
-      this.form.password = this.initPassword;
-    },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      this.getTreeselect();
-      const id = row.id;
-      getUser(id).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.title = "修改用户";
-        this.form.password = "";
-      });
-    },
-    /** 重置密码按钮操作 */
-    handleResetPwd(row) {
-      this.$prompt('请输入"' + row.username + '"的新密码', "提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消"
-      }).then(({ value }) => {
-          resetUserPwd(row.id, value).then(response => {
-            this.msgSuccess("修改成功,新密码是:" + value);
-          });
-        }).catch(() => {});
-    },
-    /** 分配用户角色操作 */
-    handleRole(row) {
-      this.reset();
-      const id = row.id
-      // 处理了 form 的用户 username 和 nickname 的展示
-      this.form.id = id;
-      this.form.username = row.username;
-      this.form.nickname = row.nickname;
-      // 打开弹窗
-      this.openRole = true;
-      // 获得角色列表
-      listSimpleRoles().then(response => {
-        // 处理 roleOptions 参数
-        this.roleOptions = [];
-        this.roleOptions.push(...response.data);
-      });
-      // 获得角色拥有的菜单集合
-      listUserRoles(id).then(response => {
-        // 设置选中
-        this.form.roleIds = response.data;
-      })
-    },
-    /** 提交按钮 */
-    submitForm: function() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.id !== undefined) {
-            updateUser(this.form).then(response => {
-              this.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            addUser(this.form).then(response => {
-              this.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
-          }
-        }
-      });
-    },
-    /** 提交按钮(角色权限) */
-    submitRole: function() {
-      if (this.form.id !== undefined) {
-        assignUserRole({
-          userId: this.form.id,
-          roleIds: this.form.roleIds,
-        }).then(response => {
-          this.msgSuccess("分配角色成功");
-          this.openRole = false;
-          this.getList();
-        });
-      }
-    },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const ids = row.id || this.ids;
-      this.$confirm('是否确认删除用户编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delUser(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        })
-    },
-    /** 导出按钮操作 */
-    handleExport() {
-      const queryParams = this.addDateRange(this.queryParams, [
-        this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
-        this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
-      ]);
-      this.$confirm('是否确认导出所有用户数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return exportUser(queryParams);
-        }).then(response => {
-          this.downloadExcel(response, '用户数据.xls');
-        })
-    },
-    /** 导入按钮操作 */
-    handleImport() {
-      this.upload.title = "用户导入";
-      this.upload.open = true;
-    },
-    /** 下载模板操作 */
-    importTemplate() {
-      importTemplate().then(response => {
-        this.downloadExcel(response, '用户导入模板.xls');
-      });
-    },
-    // 文件上传中处理
-    handleFileUploadProgress(event, file, fileList) {
-      this.upload.isUploading = true;
-    },
-    // 文件上传成功处理
-    handleFileSuccess(response, file, fileList) {
-      this.upload.open = false;
-      this.upload.isUploading = false;
-      this.$refs.upload.clearFiles();
-      // 拼接提示语
-      let data = response.data;
-      let text = '创建成功数量:' + data.createUsernames.length;
-      for (const username of data.createUsernames) {
-        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username;
-      }
-      text += '<br />更新成功数量:' + data.updateUsernames.length;
-      for (const username of data.updateUsernames) {
-        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username;
-      }
-      text += '<br />更新失败数量:' + Object.keys(data.failureUsernames).length;
-      for (const username in data.failureUsernames) {
-        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username + ':' + data.failureUsernames[username];
-      }
-      this.$alert(text, "导入结果", { dangerouslyUseHTMLString: true });
-      this.getList();
-    },
-    // 提交上传文件
-    submitFileForm() {
-      this.$refs.upload.submit();
-    },
-    // 格式化部门的下拉框
-    normalizer(node) {
-      return {
-        id: node.id,
-        label: node.name,
-        children: node.children
-      }
-    }
-  }
-};
-</script>
+<template>
+  <div class="app-container">
+    <el-row :gutter="20">
+      <!--部门数据-->
+      <el-col :span="4" :xs="24">
+        <div class="head-container">
+          <el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px"/>
+        </div>
+        <div class="head-container">
+          <el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false" :filter-node-method="filterNode"
+                   ref="tree" default-expand-all @node-click="handleNodeClick"/>
+        </div>
+      </el-col>
+      <!--用户数据-->
+      <el-col :span="20" :xs="24">
+        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+          <el-form-item label="用户名称" prop="username">
+            <el-input v-model="queryParams.username" placeholder="请输入用户名称" clearable size="small" style="width: 240px"
+                      @keyup.enter.native="handleQuery"/>
+          </el-form-item>
+          <el-form-item label="手机号码" prop="mobile">
+            <el-input v-model="queryParams.mobile" placeholder="请输入手机号码" clearable size="small" style="width: 240px"
+                      @keyup.enter.native="handleQuery"/>
+          </el-form-item>
+          <el-form-item label="状态" prop="status">
+            <el-select v-model="queryParams.status" placeholder="用户状态" clearable size="small" style="width: 240px">
+              <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="创建时间">
+            <el-date-picker v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+              range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+          </el-form-item>
+        </el-form>
+
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
+                       v-hasPermi="['system:user:create']">新增</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="info" icon="el-icon-upload2" size="mini" @click="handleImport"
+                       v-hasPermi="['system:user:import']">导入</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
+                       v-hasPermi="['system:user:export']">导出</el-button>
+          </el-col>
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table v-loading="loading" :data="userList">
+          <el-table-column label="用户编号" align="center" prop="id" />
+          <el-table-column label="用户名称" align="center" prop="username" :show-overflow-tooltip="true" />
+          <el-table-column label="用户昵称" align="center" prop="nickname" :show-overflow-tooltip="true" />
+          <el-table-column label="部门" align="center" prop="dept.name" :show-overflow-tooltip="true" />
+          <el-table-column label="手机号码" align="center" prop="mobile" width="120" />
+          <el-table-column label="状态" align="center">
+            <template slot-scope="scope">
+              <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)" />
+            </template>
+          </el-table-column>
+          <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.createTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button size="large" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                         v-hasPermi="['system:role:update']">修改</el-button>
+              <el-dropdown  @command="(command) => handleCommand(command, scope.$index, scope.row)">
+                    <span class="el-dropdown-link">
+                      更多操作<i class="el-icon-arrow-down el-icon--right"></i>
+                    </span>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item command="handleDelete" v-if="scope.row.id !== 1" size="mini" type="text" icon="el-icon-delete"
+                                    v-hasPermi="['system:user:delete']">删除</el-dropdown-item>
+                  <el-dropdown-item command="handleResetPwd" size="mini" type="text" icon="el-icon-key"
+                                    v-hasPermi="['system:user:update-password']">重置密码</el-dropdown-item>
+                  <el-dropdown-item command="handleRole" size="mini" type="text" icon="el-icon-circle-check"
+                                    v-hasPermi="['system:permission:assign-user-role']">分配角色</el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                    @pagination="getList"/>
+      </el-col>
+    </el-row>
+
+    <!-- 添加或修改参数配置对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="用户昵称" prop="nickname">
+              <el-input v-model="form.nickname" placeholder="请输入用户昵称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="归属部门" prop="deptId">
+              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true"
+                          placeholder="请选择归属部门" :normalizer="normalizer"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="手机号码" prop="mobile">
+              <el-input v-model="form.mobile" placeholder="请输入手机号码" maxlength="11" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="邮箱" prop="email">
+              <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item v-if="form.id === undefined" label="用户名称" prop="username">
+              <el-input v-model="form.username" placeholder="请输入用户名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item v-if="form.id === undefined" label="用户密码" prop="password">
+              <el-input v-model="form.password" placeholder="请输入用户密码" type="password" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="用户性别">
+              <el-select v-model="form.sex" placeholder="请选择">
+                <el-option
+                  v-for="dict in sexDictDatas"
+                  :key="parseInt(dict.value)"
+                  :label="dict.label"
+                  :value="parseInt(dict.value)"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="岗位">
+              <el-select v-model="form.postIds" multiple placeholder="请选择">
+                <el-option
+                    v-for="item in postOptions"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="备注">
+              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 用户导入对话框 -->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload
+        ref="upload"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">
+          将文件拖到此处,或
+          <em>点击上传</em>
+        </div>
+        <div class="el-upload__tip" slot="tip">
+          <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
+          <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+        </div>
+        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button @click="upload.open = false">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 分配角色 -->
+    <el-dialog title="分配角色" :visible.sync="openRole" width="500px" append-to-body>
+      <el-form :model="form" label-width="80px">
+        <el-form-item label="用户名称">
+          <el-input v-model="form.username" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="用户昵称">
+          <el-input v-model="form.nickname" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="角色">
+          <el-select v-model="form.roleIds" multiple placeholder="请选择">
+            <el-option
+                v-for="item in roleOptions"
+                :key="parseInt(item.id)"
+                :label="item.name"
+                :value="parseInt(item.id)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitRole">确 定</el-button>
+        <el-button @click="cancelRole">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {
+  addUser,
+  changeUserStatus,
+  delUser,
+  exportUser,
+  getUser,
+  importTemplate,
+  listUser,
+  resetUserPwd,
+  updateUser
+} from "@/api/system/user";
+import {getToken} from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+import {listSimpleDepts} from "@/api/system/dept";
+import {listSimplePosts} from "@/api/system/post";
+
+import {SysCommonStatusEnum} from "@/utils/constants";
+import {DICT_TYPE, getDictDatas} from "@/utils/dict";
+import {assignUserRole, listUserRoles} from "@/api/system/permission";
+import {listSimpleRoles} from "@/api/system/role";
+
+export default {
+  name: "User",
+  components: { Treeselect },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 用户表格数据
+      userList: null,
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      // 是否显示弹出层
+      open: false,
+      // 部门名称
+      deptName: undefined,
+      // 默认密码
+      initPassword: undefined,
+      // 日期范围
+      dateRange: [],
+      // 状态数据字典
+      statusOptions: [],
+      // 性别状态字典
+      sexOptions: [],
+      // 岗位选项
+      postOptions: [],
+      // 角色选项
+      roleOptions: [],
+      // 表单参数
+      form: {},
+      defaultProps: {
+        children: "children",
+        label: "name"
+      },
+      // 用户导入参数
+      upload: {
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + '/api/' + "/system/user/import"
+      },
+      // 查询参数
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        username: undefined,
+        mobile: undefined,
+        status: undefined,
+        deptId: undefined
+      },
+      // 表单校验
+      rules: {
+        username: [
+          { required: true, message: "用户名称不能为空", trigger: "blur" }
+        ],
+        nickname: [
+          { required: true, message: "用户昵称不能为空", trigger: "blur" }
+        ],
+        password: [
+          { required: true, message: "用户密码不能为空", trigger: "blur" }
+        ],
+        email: [
+          {
+            type: "email",
+            message: "'请输入正确的邮箱地址",
+            trigger: ["blur", "change"]
+          }
+        ],
+        mobile: [
+          {
+            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+            message: "请输入正确的手机号码",
+            trigger: "blur"
+          }
+        ]
+      },
+      // 是否显示弹出层(角色权限)
+      openRole: false,
+
+      // 枚举
+      SysCommonStatusEnum: SysCommonStatusEnum,
+      // 数据字典
+      statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
+      sexDictDatas: getDictDatas(DICT_TYPE.SYS_USER_SEX),
+    };
+  },
+  watch: {
+    // 根据名称筛选部门树
+    deptName(val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  created() {
+    this.getList();
+    this.getTreeselect();
+    this.getConfigKey("sys.user.initPassword").then(response => {
+      this.initPassword = response.msg;
+    });
+  },
+  methods: {
+    // 更多操作
+    handleCommand(command, index, row) {
+      switch (command) {
+        case 'handleUpdate':
+          this.handleUpdate(row);//修改客户信息
+          break;
+        case 'handleDelete':
+          this.handleDelete(row);//红号变更
+          break;
+        case 'handleResetPwd':
+          this.handleResetPwd(row);
+          break;
+        case 'handleRole':
+          this.handleRole(row);
+          break;
+        default:
+          break;
+      }
+    },
+    /** 查询用户列表 */
+    getList() {
+      this.loading = true;
+      listUser(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.userList = response.data.list;
+          this.total = response.data.total;
+          this.loading = false;
+        }
+      );
+    },
+    /** 查询部门下拉树结构 + 岗位下拉 */
+    getTreeselect() {
+      listSimpleDepts().then(response => {
+        // 处理 deptOptions 参数
+        this.deptOptions = [];
+        this.deptOptions.push(...this.handleTree(response.data, "id"));
+      });
+      listSimplePosts().then(response => {
+        // 处理 postOptions 参数
+        this.postOptions = [];
+        this.postOptions.push(...response.data);
+      });
+    },
+    // 筛选节点
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.name.indexOf(value) !== -1;
+    },
+    // 节点单击事件
+    handleNodeClick(data) {
+      this.queryParams.deptId = data.id;
+      this.getList();
+    },
+    // 用户状态修改
+    handleStatusChange(row) {
+      let text = row.status === SysCommonStatusEnum.ENABLE ? "启用" : "停用";
+      this.$confirm('确认要"' + text + '""' + row.username + '"用户吗?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return changeUserStatus(row.id, row.status);
+        }).then(() => {
+          this.msgSuccess(text + "成功");
+        }).catch(function() {
+          row.status = row.status === SysCommonStatusEnum.ENABLE ? SysCommonStatusEnum.DISABLE
+              : SysCommonStatusEnum.ENABLE;
+        });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 取消按钮(角色权限)
+    cancelRole() {
+      this.openRole = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: undefined,
+        deptId: undefined,
+        username: undefined,
+        nickname: undefined,
+        password: undefined,
+        mobile: undefined,
+        email: undefined,
+        sex: undefined,
+        status: "0",
+        remark: undefined,
+        postIds: [],
+        roleIds: []
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      // 获得下拉数据
+      this.getTreeselect();
+      // 打开表单,并设置初始化
+      this.open = true;
+      this.title = "添加用户";
+      this.form.password = this.initPassword;
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      this.getTreeselect();
+      const id = row.id;
+      getUser(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改用户";
+        this.form.password = "";
+      });
+    },
+    /** 重置密码按钮操作 */
+    handleResetPwd(row) {
+      this.$prompt('请输入"' + row.username + '"的新密码', "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消"
+      }).then(({ value }) => {
+          resetUserPwd(row.id, value).then(response => {
+            this.msgSuccess("修改成功,新密码是:" + value);
+          });
+        }).catch(() => {});
+    },
+    /** 分配用户角色操作 */
+    handleRole(row) {
+      this.reset();
+      const id = row.id
+      // 处理了 form 的用户 username 和 nickname 的展示
+      this.form.id = id;
+      this.form.username = row.username;
+      this.form.nickname = row.nickname;
+      // 打开弹窗
+      this.openRole = true;
+      // 获得角色列表
+      listSimpleRoles().then(response => {
+        // 处理 roleOptions 参数
+        this.roleOptions = [];
+        this.roleOptions.push(...response.data);
+      });
+      // 获得角色拥有的菜单集合
+      listUserRoles(id).then(response => {
+        // 设置选中
+        this.form.roleIds = response.data;
+      })
+    },
+    /** 提交按钮 */
+    submitForm: function() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id !== undefined) {
+            updateUser(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUser(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 提交按钮(角色权限) */
+    submitRole: function() {
+      if (this.form.id !== undefined) {
+        assignUserRole({
+          userId: this.form.id,
+          roleIds: this.form.roleIds,
+        }).then(response => {
+          this.msgSuccess("分配角色成功");
+          this.openRole = false;
+          this.getList();
+        });
+      }
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除用户编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUser(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.addDateRange(this.queryParams, [
+        this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
+        this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
+      ]);
+      this.$confirm('是否确认导出所有用户数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportUser(queryParams);
+        }).then(response => {
+          this.downloadExcel(response, '用户数据.xls');
+        })
+    },
+    /** 导入按钮操作 */
+    handleImport() {
+      this.upload.title = "用户导入";
+      this.upload.open = true;
+    },
+    /** 下载模板操作 */
+    importTemplate() {
+      importTemplate().then(response => {
+        this.downloadExcel(response, '用户导入模板.xls');
+      });
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      // 拼接提示语
+      let data = response.data;
+      let text = '创建成功数量:' + data.createUsernames.length;
+      for (const username of data.createUsernames) {
+        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username;
+      }
+      text += '<br />更新成功数量:' + data.updateUsernames.length;
+      for (const username of data.updateUsernames) {
+        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username;
+      }
+      text += '<br />更新失败数量:' + Object.keys(data.failureUsernames).length;
+      for (const username in data.failureUsernames) {
+        text += '<br />&nbsp;&nbsp;&nbsp;&nbsp;' + username + ':' + data.failureUsernames[username];
+      }
+      this.$alert(text, "导入结果", { dangerouslyUseHTMLString: true });
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
+    // 格式化部门的下拉框
+    normalizer(node) {
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      }
+    }
+  }
+};
+</script>
+<style>
+  .el-dropdown-link {
+    cursor: pointer;
+    color: #1890ff;
+    margin-left: 5px;
+  }
+  .el-icon-arrow-down {
+    font-size: 14px;
+  }
+</style>

+ 7 - 7
ruoyi-ui/src/views/system/user/profile/userInfo.vue

@@ -1,18 +1,18 @@
 <template>
   <el-form ref="form" :model="user" :rules="rules" label-width="80px">
     <el-form-item label="用户昵称" prop="nickName">
-      <el-input v-model="user.nickName" />
-    </el-form-item> 
+      <el-input v-model="user.nickname" />
+    </el-form-item>
     <el-form-item label="手机号码" prop="phonenumber">
-      <el-input v-model="user.phonenumber" maxlength="11" />
+      <el-input v-model="user.mobile" maxlength="11" />
     </el-form-item>
     <el-form-item label="邮箱" prop="email">
       <el-input v-model="user.email" maxlength="50" />
     </el-form-item>
     <el-form-item label="性别">
       <el-radio-group v-model="user.sex">
-        <el-radio label="0">男</el-radio>
-        <el-radio label="1">女</el-radio>
+        <el-radio :label="1">男</el-radio>
+        <el-radio :label="2">女</el-radio>
       </el-radio-group>
     </el-form-item>
     <el-form-item>
@@ -35,7 +35,7 @@ export default {
     return {
       // 表单校验
       rules: {
-        nickName: [
+        nickname: [
           { required: true, message: "用户昵称不能为空", trigger: "blur" }
         ],
         email: [
@@ -46,7 +46,7 @@ export default {
             trigger: ["blur", "change"]
           }
         ],
-        phonenumber: [
+        mobile: [
           { required: true, message: "手机号码不能为空", trigger: "blur" },
           {
             pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,

+ 37 - 5
ruoyi-ui/src/views/tool/dbDoc/index.vue

@@ -1,10 +1,21 @@
 <template>
-  <div v-loading="loading" :style="'height:'+ height">
-    <iframe :src="src" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" />
+  <div class="app-container">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportHtml">导出 HTML</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportWord">导出 Word</el-button>
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportMarkdown">导出 Markdown</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 展示文档 -->
+    <div v-loading="loading" :style="'height:'+ height">
+      <iframe :src="src" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" />
+    </div>
   </div>
 </template>
 <script>
-import {exportHtml} from "@/api/infra/dbDoc";
+import { exportHtml, exportWord, exportMarkdown} from "@/api/infra/dbDoc";
 
 export default {
   name: "DBDoc",
@@ -25,10 +36,31 @@ export default {
     };
   },
   created() {
+    // 加载 Html,进行预览
     exportHtml().then(response => {
-      // var blob = new Blob(['<a id="a"><b id="b">hey!</b></a>'], {type : 'text/html'});
-      this.src = window.URL.createObjectURL(response);
+      let blob = new Blob([response], {type : 'text/html'});
+      this.src = window.URL.createObjectURL(blob);
     })
   },
+  methods: {
+    /** 处理导出 HTML */
+    handleExportHtml() {
+      exportHtml().then(response => {
+        this.downloadHtml(response, '数据库文档.html');
+      })
+    },
+    /** 处理导出 Word */
+    handleExportWord() {
+      exportWord().then(response => {
+        this.downloadWord(response, '数据库文档.doc');
+      })
+    },
+    /** 处理导出 Markdown */
+    handleExportMarkdown() {
+      exportMarkdown().then(response => {
+        this.downloadMarkdown(response, '数据库文档.md');
+      })
+    }
+  }
 };
 </script>

+ 8 - 0
sql/quartz.sql

@@ -178,3 +178,11 @@ CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIG
 CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
 
 commit;
+
+-- 初始化默认任务 用户 Session 超时 Job
+INSERT INTO QRTZ_JOB_DETAILS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 'cn.iocoder.dashboard.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000047400104A4F425F48414E444C45525F4E414D457400187379735573657253657373696F6E54696D656F75744A6F627800);
+commit;
+INSERT INTO QRTZ_TRIGGERS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 1615706340000, 1615706280000, 5, 'WAITING', 'CRON', 1615706125000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000007D074000F4A4F425F52455452595F434F554E547371007E0009000000037800);
+commit;
+INSERT INTO QRTZ_CRON_TRIGGERS VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', '0 * * * * ? *', 'Asia/Shanghai');
+commit;

File diff suppressed because it is too large
+ 754 - 78
sql/ruoyi-vue-pro.sql


+ 2 - 2
src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java

@@ -1,6 +1,6 @@
 package cn.iocoder.dashboard.framework.file.config;
 
-import cn.iocoder.dashboard.modules.system.controller.common.SysFileController;
+import cn.iocoder.dashboard.modules.infra.controller.file.InfFileController;
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.validation.annotation.Validated;
@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
 public class FileProperties {
 
     /**
-     * 对应 {@link SysFileController#}
+     * 对应 {@link InfFileController#}
      */
     @NotNull(message = "基础文件路径不能为空")
     private String basePath;

+ 18 - 1
src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java

@@ -1,18 +1,35 @@
 package cn.iocoder.dashboard.framework.jackson.config;
 
+import cn.iocoder.dashboard.framework.jackson.deser.LocalDateTimeDeserializer;
+import cn.iocoder.dashboard.framework.jackson.ser.LocalDateTimeSerializer;
 import cn.iocoder.dashboard.util.json.JsonUtils;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import java.time.LocalDateTime;
+
 @Configuration
 public class JacksonConfig {
 
     @Bean
     @SuppressWarnings("InstantiationOfUtilityClass")
     public JsonUtils jsonUtils(ObjectMapper objectMapper) {
+        SimpleModule simpleModule = new SimpleModule();
+        /*
+         * 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型
+         * 2. 新增LocalDateTime序列化、反序列化规则
+         */
+        simpleModule
+//                .addSerializer(Long.class, ToStringSerializer.instance)
+//                    .addSerializer(Long.TYPE, ToStringSerializer.instance)
+                    .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
+                    .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
+
+        objectMapper.registerModules(simpleModule);
+
         JsonUtils.init(objectMapper);
         return new JsonUtils();
     }
-
 }

+ 26 - 0
src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java

@@ -0,0 +1,26 @@
+package cn.iocoder.dashboard.framework.jackson.deser;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+/**
+ * LocalDateTime反序列化规则
+ * <p>
+ * 会将毫秒级时间戳反序列化为LocalDateTime
+ */
+public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
+
+    public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer();
+
+    @Override
+    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+        return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
+    }
+}

+ 24 - 0
src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java

@@ -0,0 +1,24 @@
+package cn.iocoder.dashboard.framework.jackson.ser;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+/**
+ * LocalDateTime序列化规则
+ * <p>
+ * 会将LocalDateTime序列化为毫秒级时间戳
+ */
+public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
+
+    public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer();
+
+    @Override
+    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+    }
+}

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java

@@ -81,7 +81,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
                                       Map<String, String> queryString, String requestBody, Exception ex) {
         // 处理用户信息
         accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
-        accessLog.setUserType(WebFrameworkUtils.getUesrType(request));
+        accessLog.setUserType(WebFrameworkUtils.getUserType(request));
         // 设置访问结果
         CommonResult<?> result = WebFrameworkUtils.getCommonResult(request);
         if (result != null) {

+ 3 - 1
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.logger.apilog.core.service;
 import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO;
 
 import javax.validation.Valid;
+import java.util.concurrent.Future;
 
 /**
  * API 访问日志 Framework Service 接口
@@ -15,7 +16,8 @@ public interface ApiAccessLogFrameworkService {
      * 创建 API 访问日志
      *
      * @param createDTO 创建信息
+     * @return 是否创建成功
      */
-    void createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO);
+    Future<Boolean> createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO);
 
 }

+ 3 - 1
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.logger.apilog.core.service;
 import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO;
 
 import javax.validation.Valid;
+import java.util.concurrent.Future;
 
 /**
  * API 错误日志 Framework Service 接口
@@ -15,7 +16,8 @@ public interface ApiErrorLogFrameworkService {
      * 创建 API 错误日志
      *
      * @param createDTO 创建信息
+     * @return 是否创建成功
      */
-    void createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO);
+    Future<Boolean> createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO);
 
 }

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java

@@ -134,7 +134,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
                     // 静态资源,可匿名访问
                     .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
                     // 文件的获取接口,可匿名访问
-                    .antMatchers(webProperties.getApiPrefix() + "/system/file/get/**").anonymous()
+                    .antMatchers(webProperties.getApiPrefix() + "/infra/file/get/**").anonymous()
                     // Swagger 接口文档
                     .antMatchers("/swagger-ui.html").anonymous()
                     .antMatchers("/swagger-resources/**").anonymous()

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java

@@ -269,7 +269,7 @@ public class GlobalExceptionHandler {
     private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) {
         // 处理用户信息
         errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
-        errorLog.setUserType(WebFrameworkUtils.getUesrType(request));
+        errorLog.setUserType(WebFrameworkUtils.getUserType(request));
         // 设置异常字段
         errorLog.setExceptionName(e.getClass().getName());
         errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java

@@ -31,7 +31,7 @@ public class WebFrameworkUtils {
         return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID);
     }
 
-    public static Integer getUesrType(HttpServletRequest request) {
+    public static Integer getUserType(HttpServletRequest request) {
         return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化
     }
 

+ 63 - 19
src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java

@@ -1,6 +1,8 @@
 package cn.iocoder.dashboard.modules.infra.controller.doc;
 
-import cn.hutool.extra.servlet.ServletUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.iocoder.dashboard.util.servlet.ServletUtils;
 import cn.smallbun.screw.core.Configuration;
 import cn.smallbun.screw.core.engine.EngineConfig;
 import cn.smallbun.screw.core.engine.EngineFileType;
@@ -10,18 +12,18 @@ import cn.smallbun.screw.core.process.ProcessConfig;
 import com.zaxxer.hikari.HikariConfig;
 import com.zaxxer.hikari.HikariDataSource;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
-import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
-import javax.sql.DataSource;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.Collections;
 
 @Api(tags = "数据库文档")
@@ -34,34 +36,77 @@ public class InfDbDocController {
 
     private static final String FILE_OUTPUT_DIR = System.getProperty("java.io.tmpdir") + File.separator
             + "db-doc";
-    private static final EngineFileType FILE_OUTPUT_TYPE = EngineFileType.HTML; // 可以设置 Word 或者 Markdown 格式
     private static final String DOC_FILE_NAME = "数据库文档";
     private static final String DOC_VERSION = "1.0.0";
     private static final String DOC_DESCRIPTION = "文档描述";
 
-    @Resource
-    private DataSource dataSource;
-
     @GetMapping("/export-html")
-    public synchronized void exportHtml(HttpServletResponse response) throws FileNotFoundException {
+    @ApiOperation("导出 html 格式的数据文档")
+    @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class)
+    public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile,
+                           HttpServletResponse response) throws IOException {
+        doExportFile(EngineFileType.HTML, deleteFile, response);
+    }
+
+    @GetMapping("/export-word")
+    @ApiOperation("导出 word 格式的数据文档")
+    @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class)
+    public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile,
+                           HttpServletResponse response) throws IOException {
+        doExportFile(EngineFileType.WORD, deleteFile, response);
+    }
+
+    @GetMapping("/export-markdown")
+    @ApiOperation("导出 markdown 格式的数据文档")
+    @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class)
+    public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile,
+                               HttpServletResponse response) throws IOException {
+        doExportFile(EngineFileType.MD, deleteFile, response);
+    }
+
+    private void doExportFile(EngineFileType fileOutputType, Boolean deleteFile,
+                              HttpServletResponse response) throws IOException {
+        String docFileName = DOC_FILE_NAME + "_" + IdUtil.fastSimpleUUID();
+        String filePath = doExportFile(fileOutputType, docFileName);
+        String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名
+        try {
+            // 读取,返回
+            ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath));
+        } finally {
+            handleDeleteFile(deleteFile, filePath);
+        }
+    }
+
+    /**
+     * 输出文件,返回文件路径
+     *
+     * @param fileOutputType 文件类型
+     * @param fileName       文件名, 无需 ".docx" 等文件后缀
+     * @return 生成的文件所在路径
+     */
+    private String doExportFile(EngineFileType fileOutputType, String fileName) {
         try (HikariDataSource dataSource = buildDataSource()) {
             // 创建 screw 的配置
             Configuration config = Configuration.builder()
                     .version(DOC_VERSION)  // 版本
                     .description(DOC_DESCRIPTION) // 描述
                     .dataSource(dataSource) // 数据源
-                    .engineConfig(buildEngineConfig()) // 引擎配置
+                    .engineConfig(buildEngineConfig(fileOutputType, fileName)) // 引擎配置
                     .produceConfig(buildProcessConfig()) // 处理配置
                     .build();
 
             // 执行 screw,生成数据库文档
             new DocumentationExecute(config).execute();
 
-            // 读取,返回
-            ServletUtil.write(response,
-                    new FileInputStream(FILE_OUTPUT_DIR + File.separator + DOC_FILE_NAME + FILE_OUTPUT_TYPE.getFileSuffix()),
-                    MediaType.TEXT_HTML_VALUE);
+            return FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix();
+        }
+    }
+
+    private void handleDeleteFile(Boolean deleteFile, String filePath) {
+        if (!deleteFile) {
+            return;
         }
+        FileUtil.del(filePath);
     }
 
     /**
@@ -71,7 +116,6 @@ public class InfDbDocController {
     private HikariDataSource buildDataSource() {
         // 创建 HikariConfig 配置类
         HikariConfig hikariConfig = new HikariConfig();
-//        hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
         hikariConfig.setJdbcUrl(dataSourceProperties.getUrl());
         hikariConfig.setUsername(dataSourceProperties.getUsername());
         hikariConfig.setPassword(dataSourceProperties.getPassword());
@@ -83,13 +127,13 @@ public class InfDbDocController {
     /**
      * 创建 screw 的引擎配置
      */
-    private static EngineConfig buildEngineConfig() {
+    private static EngineConfig buildEngineConfig(EngineFileType fileOutputType, String docFileName) {
         return EngineConfig.builder()
                 .fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径
                 .openOutputDir(false) // 打开目录
-                .fileType(FILE_OUTPUT_TYPE) // 文件类型
+                .fileType(fileOutputType) // 文件类型
                 .produceType(EngineTemplateType.freemarker) // 文件类型
-                .fileName(DOC_FILE_NAME) // 自定义文件名称
+                .fileName(docFileName) // 自定义文件名称
                 .build();
     }
 

+ 36 - 11
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysFileController.java → src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/InfFileController.java

@@ -1,9 +1,13 @@
-package cn.iocoder.dashboard.modules.system.controller.common;
+package cn.iocoder.dashboard.modules.infra.controller.file;
 
 import cn.hutool.core.io.IoUtil;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
-import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
-import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFileRespVO;
+import cn.iocoder.dashboard.modules.infra.convert.file.InfFileConvert;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
+import cn.iocoder.dashboard.modules.infra.service.file.InfFileService;
 import cn.iocoder.dashboard.util.servlet.ServletUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -11,40 +15,53 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 
 @Api(tags = "文件存储")
 @RestController
-@RequestMapping("/system/file")
+@RequestMapping("/infra/file")
+@Validated
 @Slf4j
-public class SysFileController {
+public class InfFileController {
 
     @Resource
-    private SysFileService fileService;
+    private InfFileService fileService;
 
+    @PostMapping("/upload")
     @ApiOperation("上传文件")
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
-            @ApiImplicitParam(name = "path", value = "文件路径", required = true, example = "yudaoyuanma.png", dataTypeClass = Long.class)
+            @ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
+            @ApiImplicitParam(name = "path", value = "文件路径", required = false, example = "yudaoyuanma.png", dataTypeClass = String.class)
     })
-    @PostMapping("/upload")
     public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
                                            @RequestParam("path") String path) throws IOException {
         return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
     }
 
+    @DeleteMapping("/delete")
+    @ApiOperation("删除文件")
+    @ApiImplicitParam(name = "id", value = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('infra:file:delete')")
+    public CommonResult<Boolean> deleteFile(@RequestParam("id") String id) {
+        fileService.deleteFile(id);
+        return success(true);
+    }
+
+    @GetMapping("/get/{path}")
     @ApiOperation("下载文件")
     @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
-    @GetMapping("/get/{path}")
     public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
-        SysFileDO file = fileService.getFile(path);
+        InfFileDO file = fileService.getFile(path);
         if (file == null) {
             log.warn("[getFile][path({}) 文件不存在]", path);
             response.setStatus(HttpStatus.NOT_FOUND.value());
@@ -53,4 +70,12 @@ public class SysFileController {
         ServletUtils.writeAttachment(response, path, file.getContent());
     }
 
+    @GetMapping("/page")
+    @ApiOperation("获得文件分页")
+    @PreAuthorize("@ss.hasPermission('infra:file:query')")
+    public CommonResult<PageResult<InfFileRespVO>> getFilePage(@Valid InfFilePageReqVO pageVO) {
+        PageResult<InfFileDO> pageResult = fileService.getFilePage(pageVO);
+        return success(InfFileConvert.INSTANCE.convertPage(pageResult));
+    }
+
 }

+ 35 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFilePageReqVO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.dashboard.modules.infra.controller.file.vo;
+
+import cn.iocoder.dashboard.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("文件分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InfFilePageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配")
+    private String id;
+
+    @ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配")
+    private String type;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 22 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/controller/file/vo/InfFileRespVO.java

@@ -0,0 +1,22 @@
+package cn.iocoder.dashboard.modules.infra.controller.file.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@ApiModel(value = "文件 Response VO", description = "不返回 content 字段,太大")
+@Data
+public class InfFileRespVO {
+
+    @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg")
+    private String id;
+
+    @ApiModelProperty(value = "文件类型", required = true, example = "jpg")
+    private String type;
+
+    @ApiModelProperty(value = "创建时间", required = true)
+    private Date createTime;
+
+}

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java

@@ -14,7 +14,7 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU
 public class InfApiErrorLogExportReqVO {
 
     @ApiModelProperty(value = "用户编号", example = "666")
-    private Integer userId;
+    private Long userId;
 
     @ApiModelProperty(value = "用户类型", example = "1")
     private Integer userType;

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java

@@ -19,7 +19,7 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU
 public class InfApiErrorLogPageReqVO extends PageParam {
 
     @ApiModelProperty(value = "用户编号", example = "666")
-    private Integer userId;
+    private Long userId;
 
     @ApiModelProperty(value = "用户类型", example = "1")
     private Integer userType;

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/infra/controller/redis/RedisController.java

@@ -30,9 +30,9 @@ public class RedisController {
     @Resource
     private StringRedisTemplate stringRedisTemplate;
 
+    @GetMapping("/get-monitor-info")
     @ApiOperation("获得 Redis 监控信息")
     @PreAuthorize("@ss.hasPermission('infra:redis:get-monitor-info')")
-    @GetMapping("/get-monitor-info")
     public CommonResult<InfRedisMonitorRespVO> getRedisMonitorInfo() {
         // 获得 Redis 统计信息
         Properties info = stringRedisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
@@ -44,9 +44,9 @@ public class RedisController {
         return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats));
     }
 
+    @GetMapping("/get-key-list")
     @ApiOperation("获得 Redis Key 列表")
     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
-    @GetMapping("/get-key-list")
     public CommonResult<List<InfRedisKeyRespVO>> getKeyList() {
         List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list();
         return success(RedisConvert.INSTANCE.convertList(keyDefines));

+ 18 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/convert/file/InfFileConvert.java

@@ -0,0 +1,18 @@
+package cn.iocoder.dashboard.modules.infra.convert.file;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFileRespVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+@Mapper
+public interface InfFileConvert {
+
+    InfFileConvert INSTANCE = Mappers.getMapper(InfFileConvert.class);
+
+    InfFileRespVO convert(InfFileDO bean);
+
+    PageResult<InfFileRespVO> convertPage(PageResult<InfFileDO> page);
+
+}

+ 43 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/file/InfFileDO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.dashboard.modules.infra.dal.dataobject.file;
+
+import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.io.InputStream;
+
+/**
+ * 文件表
+ *
+ * @author 芋道源码
+ */
+@Data
+@TableName("inf_file")
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class InfFileDO extends BaseDO {
+
+    /**
+     * 文件路径
+     */
+    @TableId(type = IdType.INPUT)
+    private String id;
+    /**
+     * 文件类型
+     *
+     * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
+     */
+    @TableField(value = "`type`")
+    private String type;
+    /**
+     * 文件内容
+     */
+    private byte[] content;
+
+}

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java

@@ -37,7 +37,7 @@ public class InfApiAccessLogDO extends BaseDO {
     /**
      * 用户编号
      */
-    private Integer userId;
+    private Long userId;
     /**
      * 用户类型
      *

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java

@@ -30,7 +30,7 @@ public class InfApiErrorLogDO extends BaseDO {
     /**
      * 用户编号
      */
-    private Integer userId;
+    private Long userId;
     /**
      * 链路追踪编号
      *
@@ -148,6 +148,6 @@ public class InfApiErrorLogDO extends BaseDO {
      *
      * 关联 {@link SysUserDO#getId()}
      */
-    private Integer processUserId;
+    private Long processUserId;
 
 }

+ 25 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/dal/mysql/file/InfFileMapper.java

@@ -0,0 +1,25 @@
+package cn.iocoder.dashboard.modules.infra.dal.mysql.file;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface InfFileMapper extends BaseMapperX<InfFileDO> {
+
+    default Integer selectCountById(String id) {
+        return selectCount("id", id);
+    }
+
+    default PageResult<InfFileDO> selectPage(InfFilePageReqVO reqVO) {
+        return selectPage(reqVO, new QueryWrapperX<InfFileDO>()
+                .likeIfPresent("id", reqVO.getId())
+                .likeIfPresent("type", reqVO.getType())
+                .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc("create_time"));
+    }
+
+}

+ 3 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/enums/InfErrorCodeConstants.java

@@ -27,4 +27,7 @@ public interface InfErrorCodeConstants {
     ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");
     ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");
 
+    // ========== 文件 1001003000 ==========
+    ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003000, "文件不存在");
+
 }

+ 46 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileService.java

@@ -0,0 +1,46 @@
+package cn.iocoder.dashboard.modules.infra.service.file;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
+
+/**
+ * 文件 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface InfFileService {
+
+    /**
+     * 保存文件,并返回文件的访问路径
+     *
+     * @param path 文件路径
+     * @param content 文件内容
+     * @return 文件路径
+     */
+    String createFile(String path, byte[] content);
+
+    /**
+     * 删除文件
+     *
+     * @param id 编号
+     */
+    void deleteFile(String id);
+
+    /**
+     * 获得文件
+     *
+     * @param path 文件路径
+     * @return 文件
+     */
+    InfFileDO getFile(String path);
+
+    /**
+     * 获得文件分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 文件分页
+     */
+    PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO);
+
+}

+ 72 - 0
src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java

@@ -0,0 +1,72 @@
+package cn.iocoder.dashboard.modules.infra.service.file.impl;
+
+import cn.hutool.core.io.FileTypeUtil;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.file.config.FileProperties;
+import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
+import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper;
+import cn.iocoder.dashboard.modules.infra.service.file.InfFileService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.io.ByteArrayInputStream;
+
+import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.FILE_NOT_EXISTS;
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
+
+/**
+ * 文件 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+public class InfFileServiceImpl implements InfFileService {
+
+    @Resource
+    private InfFileMapper fileMapper;
+
+    @Resource
+    private FileProperties fileProperties;
+
+    @Override
+    public String createFile(String path, byte[] content) {
+        if (fileMapper.selectCountById(path) > 0) {
+            throw exception(FILE_PATH_EXISTS);
+        }
+        // 保存到数据库
+        InfFileDO file = new InfFileDO();
+        file.setId(path);
+        file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));
+        file.setContent(content);
+        fileMapper.insert(file);
+        // 拼接路径返回
+        return fileProperties.getBasePath() + path;
+    }
+
+    @Override
+    public void deleteFile(String id) {
+        // 校验存在
+        this.validateFileExists(id);
+        // 更新
+        fileMapper.deleteById(id);
+    }
+
+    private void validateFileExists(String id) {
+        if (fileMapper.selectById(id) == null) {
+            throw exception(FILE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public InfFileDO getFile(String path) {
+        return fileMapper.selectById(path);
+    }
+
+    @Override
+    public PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO) {
+        return fileMapper.selectPage(pageReqVO);
+    }
+
+}

+ 4 - 4
src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java

@@ -41,7 +41,7 @@ public class InfJobServiceImpl implements InfJobService {
     private SchedulerManager schedulerManager;
 
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public Long createJob(InfJobCreateReqVO createReqVO) throws SchedulerException {
         validateCronExpression(createReqVO.getCronExpression());
         // 校验唯一性
@@ -66,7 +66,7 @@ public class InfJobServiceImpl implements InfJobService {
     }
 
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void updateJob(InfJobUpdateReqVO updateReqVO) throws SchedulerException {
         validateCronExpression(updateReqVO.getCronExpression());
         // 校验存在
@@ -86,7 +86,7 @@ public class InfJobServiceImpl implements InfJobService {
     }
 
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void updateJobStatus(Long id, Integer status) throws SchedulerException {
         // 校验 status
         if (!containsAny(status, InfJobStatusEnum.NORMAL.getStatus(), InfJobStatusEnum.STOP.getStatus())) {
@@ -120,7 +120,7 @@ public class InfJobServiceImpl implements InfJobService {
     }
 
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void deleteJob(Long id) throws SchedulerException {
         // 校验存在
         InfJobDO job = this.validateJobExists(id);

+ 5 - 3
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java

@@ -9,12 +9,13 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogD
 import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiAccessLogMapper;
 import cn.iocoder.dashboard.modules.infra.service.logger.InfApiAccessLogService;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import javax.validation.Valid;
 import java.util.List;
+import java.util.concurrent.Future;
 
 /**
  * API 访问日志 Service 实现类
@@ -30,10 +31,11 @@ public class InfApiAccessLogServiceImpl implements InfApiAccessLogService {
 
     @Override
     @Async
-    public void createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) {
+    public Future<Boolean> createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) {
         // 插入
         InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO);
-        apiAccessLogMapper.insert(apiAccessLog);
+        int insert = apiAccessLogMapper.insert(apiAccessLog);
+        return new AsyncResult<>(insert == 1);
     }
 
     @Override

+ 6 - 3
src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java

@@ -10,12 +10,14 @@ import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
 import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
 import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.Future;
 
 import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
@@ -35,10 +37,11 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService {
 
     @Override
     @Async
-    public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) {
+    public Future<Boolean> createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) {
         InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO);
         apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus());
-        apiErrorLogMapper.insert(apiErrorLog);
+        int insert = apiErrorLogMapper.insert(apiErrorLog);
+        return new AsyncResult<>(insert == 1);
     }
 
     @Override
@@ -62,7 +65,7 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService {
         }
         // 标记处理
         apiErrorLogMapper.updateById(InfApiErrorLogDO.builder().id(id).processStatus(processStatus)
-                .processUserId(processStatus).processTime(new Date()).build());
+                .processUserId(processUserId).processTime(new Date()).build());
     }
 
 }

+ 9 - 7
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java

@@ -19,6 +19,7 @@ import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
 import cn.iocoder.dashboard.util.collection.SetUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -34,6 +35,7 @@ import static cn.iocoder.dashboard.util.servlet.ServletUtils.getUserAgent;
 @Api(tags = "认证")
 @RestController
 @RequestMapping("/")
+@Validated
 public class SysAuthController {
 
     @Resource
@@ -45,8 +47,8 @@ public class SysAuthController {
     @Resource
     private SysPermissionService permissionService;
 
-    @ApiOperation("使用账号密码登录")
     @PostMapping("/login")
+    @ApiOperation("使用账号密码登录")
     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
     public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
         String token = authService.login(reqVO, getClientIP(), getUserAgent());
@@ -54,8 +56,8 @@ public class SysAuthController {
         return success(SysAuthLoginRespVO.builder().token(token).build());
     }
 
-    @ApiOperation("获取登陆用户的权限信息")
     @GetMapping("/get-permission-info")
+    @ApiOperation("获取登陆用户的权限信息")
     public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
         // 获得用户信息
         SysUserDO user = userService.getUser(getLoginUserId());
@@ -63,9 +65,9 @@ public class SysAuthController {
             return null;
         }
         // 获得角色列表
-        List<SysRoleDO> roleList = roleService.listRolesFromCache(getLoginUserRoleIds());
+        List<SysRoleDO> roleList = roleService.getRolesFromCache(getLoginUserRoleIds());
         // 获得菜单列表
-        List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(
+        List<SysMenuDO> menuList = permissionService.getRoleMenusFromCache(
                 getLoginUserRoleIds(), // 注意,基于登陆的角色,因为后续的权限判断也是基于它
                 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
                 SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
@@ -73,11 +75,11 @@ public class SysAuthController {
         return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList));
     }
 
-    @ApiOperation("获得登陆用户的菜单列表")
     @GetMapping("list-menus")
-    public CommonResult<List<SysAuthMenuRespVO>> listMenus() {
+    @ApiOperation("获得登陆用户的菜单列表")
+    public CommonResult<List<SysAuthMenuRespVO>> getMenus() {
         // 获得用户拥有的菜单列表
-        List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(
+        List<SysMenuDO> menuList = permissionService.getRoleMenusFromCache(
                 getLoginUserRoleIds(), // 注意,基于登陆的角色,因为后续的权限判断也是基于它
                 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
                 SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的

+ 4 - 4
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java

@@ -39,9 +39,9 @@ public class SysUserSessionController {
     @Resource
     private SysDeptService deptService;
 
+    @GetMapping("/page")
     @ApiOperation("获得 Session 分页列表")
     @PreAuthorize("@ss.hasPermission('system:user-session:page')")
-    @GetMapping("/page")
     public CommonResult<PageResult<SysUserSessionPageItemRespVO>> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) {
         // 获得 Session 分页
         PageResult<SysUserSessionDO> pageResult = userSessionService.getUserSessionPage(reqVO);
@@ -66,12 +66,12 @@ public class SysUserSessionController {
         return success(new PageResult<>(sessionList, pageResult.getTotal()));
     }
 
-    @ApiOperation("删除 Session")
-    @PreAuthorize("@ss.hasPermission('system:user-session:delete')")
     @DeleteMapping("/delete")
+    @ApiOperation("删除 Session")
     @ApiImplicitParam(name = "id", value = "Session 编号", required = true, dataTypeClass = String.class,
             example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
-    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
+    @PreAuthorize("@ss.hasPermission('system:user-session:delete')")
+    public CommonResult<Boolean> deleteUserSession(@RequestParam("id") String id) {
         userSessionService.deleteUserSession(id);
         return success(true);
     }

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java

@@ -21,8 +21,8 @@ public class SysCaptchaController {
     @Resource
     private SysCaptchaService captchaService;
 
-    @ApiOperation("生成图片验证码")
     @GetMapping("/get-image")
+    @ApiOperation("生成图片验证码")
     public CommonResult<SysCaptchaImageRespVO> getCaptchaImage() {
         return success(captchaService.getCaptchaImage());
     }

+ 36 - 35
src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysDeptController.java

@@ -9,10 +9,12 @@ import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.validation.Valid;
 import java.util.Comparator;
 import java.util.List;
 
@@ -21,65 +23,64 @@ import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 @Api(tags = "部门")
 @RestController
 @RequestMapping("/system/dept")
+@Validated
 public class SysDeptController {
 
     @Resource
     private SysDeptService deptService;
 
-    @ApiOperation("获取部门列表")
-//    @PreAuthorize("@ss.hasPermi('system:dept:list')")
+    @PostMapping("create")
+    @ApiOperation("创建部门")
+    @PreAuthorize("@ss.hasPermission('system:dept:create')")
+    public CommonResult<Long> createDept(@Valid @RequestBody SysDeptCreateReqVO reqVO) {
+        Long deptId = deptService.createDept(reqVO);
+        return success(deptId);
+    }
+
+    @PutMapping("update")
+    @ApiOperation("更新部门")
+    @PreAuthorize("@ss.hasPermission('system:dept:update')")
+    public CommonResult<Boolean> updateDept(@Valid @RequestBody SysDeptUpdateReqVO reqVO) {
+        deptService.updateDept(reqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("delete")
+    @ApiOperation("删除部门")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:dept:delete')")
+    public CommonResult<Boolean> deleteDept(@RequestParam("id") Long id) {
+        deptService.deleteDept(id);
+        return success(true);
+    }
+
     @GetMapping("/list")
+    @ApiOperation("获取部门列表")
+    @PreAuthorize("@ss.hasPermission('system:dept:query')")
     public CommonResult<List<SysDeptRespVO>> listDepts(SysDeptListReqVO reqVO) {
-        List<SysDeptDO> list = deptService.listDepts(reqVO);
+        List<SysDeptDO> list = deptService.getSimpleDepts(reqVO);
         list.sort(Comparator.comparing(SysDeptDO::getSort));
         return success(SysDeptConvert.INSTANCE.convertList(list));
     }
 
-    @ApiOperation(value = "获取部门精简信息列表", notes = "只包含被开启的部门,主要用于前端的下拉选项")
     @GetMapping("/list-all-simple")
-    public CommonResult<List<SysDeptSimpleRespVO>> listSimpleDepts() {
+    @ApiOperation(value = "获取部门精简信息列表", notes = "只包含被开启的部门,主要用于前端的下拉选项")
+    public CommonResult<List<SysDeptSimpleRespVO>> getSimpleDepts() {
         // 获得部门列表,只要开启状态的
         SysDeptListReqVO reqVO = new SysDeptListReqVO();
         reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        List<SysDeptDO> list = deptService.listDepts(reqVO);
+        List<SysDeptDO> list = deptService.getSimpleDepts(reqVO);
         // 排序后,返回给前端
         list.sort(Comparator.comparing(SysDeptDO::getSort));
         return success(SysDeptConvert.INSTANCE.convertList02(list));
     }
 
+    @GetMapping("/get")
     @ApiOperation("获得部门信息")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:dept:query')")
-    @GetMapping("/get")
+    @PreAuthorize("@ss.hasPermission('system:dept:query')")
     public CommonResult<SysDeptRespVO> getDept(@RequestParam("id") Long id) {
         return success(SysDeptConvert.INSTANCE.convert(deptService.getDept(id)));
     }
 
-    @ApiOperation("新增部门")
-    @PostMapping("create")
-//    @PreAuthorize("@ss.hasPermi('system:dept:add')")
-//    @Log(title = "部门管理", businessType = BusinessType.INSERT)
-    public CommonResult<Long> createDept(@Validated @RequestBody SysDeptCreateReqVO reqVO) {
-        Long deptId = deptService.createDept(reqVO);
-        return success(deptId);
-    }
-
-    @ApiOperation("修改部门")
-    @PostMapping("update")
-//    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
-//    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateDept(@Validated @RequestBody SysDeptUpdateReqVO reqVO) {
-        deptService.updateDept(reqVO);
-        return success(true);
-    }
-
-    @ApiOperation("删除部门")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PostMapping("delete")
-//    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
-//    @Log(title = "部门管理", businessType = BusinessType.DELETE)
-    public CommonResult<Boolean> deleteDept(@RequestParam("id") Long id) {
-        deptService.deleteDept(id);
-        return success(true);
-    }
 }

+ 37 - 36
src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java

@@ -4,6 +4,7 @@ import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*;
 import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO;
@@ -11,88 +12,88 @@ import cn.iocoder.dashboard.modules.system.service.dept.SysPostService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "岗位")
 @RestController
 @RequestMapping("/system/post")
+@Valid
 public class SysPostController {
 
     @Resource
     private SysPostService postService;
 
-    @ApiOperation(value = "获取岗位精简信息列表", notes = "只包含被开启的岗位,主要用于前端的下拉选项")
-    @GetMapping("/list-all-simple")
-    public CommonResult<List<SysPostSimpleRespVO>> listSimplePosts() {
-        // 获得岗位列表,只要开启状态的
-        List<SysPostDO> list = postService.listPosts(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
-        // 排序后,返回给前端
-        list.sort(Comparator.comparing(SysPostDO::getSort));
-        return success(SysPostConvert.INSTANCE.convertList02(list));
-    }
-
-    @ApiOperation("获得岗位分页列表")
-    @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:post:list')")
-    public CommonResult<PageResult<SysPostRespVO>> pagePosts(@Validated SysPostPageReqVO reqVO) {
-        return success(SysPostConvert.INSTANCE.convertPage(postService.pagePosts(reqVO)));
-    }
-
-    @ApiOperation("新增岗位")
     @PostMapping("/create")
-//    @PreAuthorize("@ss.hasPermi('system:post:add')")
-//    @Log(title = "岗位管理", businessType = BusinessType.INSERT)
-    public CommonResult<Long> createPost(@Validated @RequestBody SysPostCreateReqVO reqVO) {
+    @ApiOperation("创建岗位")
+    @PreAuthorize("@ss.hasPermission('system:post:create')")
+    public CommonResult<Long> createPost(@Valid @RequestBody SysPostCreateReqVO reqVO) {
         Long postId = postService.createPost(reqVO);
         return success(postId);
     }
 
+    @PutMapping("/update")
     @ApiOperation("修改岗位")
-    @PostMapping("/update")
-//    @PreAuthorize("@ss.hasPermi('system:post:edit')")
-//    @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updatePost(@Validated @RequestBody SysPostUpdateReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:post:update')")
+    public CommonResult<Boolean> updatePost(@Valid @RequestBody SysPostUpdateReqVO reqVO) {
         postService.updatePost(reqVO);
         return success(true);
     }
 
+    @DeleteMapping("/delete")
     @ApiOperation("删除岗位")
-    @PostMapping("/delete")
-//    @PreAuthorize("@ss.hasPermi('system:post:remove')")
-//    @Log(title = "岗位管理", businessType = BusinessType.DELETE)
+    @PreAuthorize("@ss.hasPermission('system:post:delete')")
     public CommonResult<Boolean> deletePost(@RequestParam("id") Long id) {
         postService.deletePost(id);
         return success(true);
     }
 
+    @GetMapping(value = "/get")
     @ApiOperation("获得岗位信息")
     @ApiImplicitParam(name = "id", value = "岗位编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:post:query')")
-    @GetMapping(value = "/get")
+    @PreAuthorize("@ss.hasPermission('system:post:query')")
     public CommonResult<SysPostRespVO> getPost(@RequestParam("id") Long id) {
         return success(SysPostConvert.INSTANCE.convert(postService.getPost(id)));
     }
 
+    @GetMapping("/list-all-simple")
+    @ApiOperation(value = "获取岗位精简信息列表", notes = "只包含被开启的岗位,主要用于前端的下拉选项")
+    public CommonResult<List<SysPostSimpleRespVO>> getSimplePosts() {
+        // 获得岗位列表,只要开启状态的
+        List<SysPostDO> list = postService.getPosts(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
+        // 排序后,返回给前端
+        list.sort(Comparator.comparing(SysPostDO::getSort));
+        return success(SysPostConvert.INSTANCE.convertList02(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得岗位分页列表")
+    @PreAuthorize("@ss.hasPermission('system:post:query')")
+    public CommonResult<PageResult<SysPostRespVO>> getPostPage(@Validated SysPostPageReqVO reqVO) {
+        return success(SysPostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO)));
+    }
+
     @GetMapping("/export")
     @ApiOperation("岗位管理")
-//    @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:post:export')")
+    @PreAuthorize("@ss.hasPermission('system:post:export')")
+    @OperateLog(type = EXPORT)
     public void export(HttpServletResponse response, @Validated SysPostExportReqVO reqVO) throws IOException {
-        List<SysPostDO> posts = postService.listPosts(reqVO);
-        List<SysPostExcelVO> excelDataList = SysPostConvert.INSTANCE.convertList03(posts);
+        List<SysPostDO> posts = postService.getPosts(reqVO);
+        List<SysPostExcelVO> data = SysPostConvert.INSTANCE.convertList03(posts);
         // 输出
-        ExcelUtils.write(response, "岗位数据.xls", "岗位列表",
-                SysPostExcelVO.class, excelDataList);
+        ExcelUtils.write(response, "岗位数据.xls", "岗位列表", SysPostExcelVO.class, data);
     }
 
 }

+ 43 - 41
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 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.dataobject.dict.SysDictDataDO;
@@ -10,84 +11,85 @@ 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.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.List;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "字典数据")
 @RestController
 @RequestMapping("/system/dict-data")
+@Validated
 public class SysDictDataController {
 
     @Resource
     private SysDictDataService dictDataService;
 
-    @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
-    @GetMapping("/list-all-simple")
-    // 无需添加权限认证,因为前端全局都需要
-    public CommonResult<List<SysDictDataSimpleVO>> listSimpleDictDatas() {
-        List<SysDictDataDO> list = dictDataService.getDictDataList();
-        return success(SysDictDataConvert.INSTANCE.convertList(list));
-    }
-
-    @ApiOperation("/获得字典类型的分页列表")
-    @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:dict:list')")
-    public CommonResult<PageResult<SysDictDataRespVO>> pageDictTypes(@Validated SysDictDataPageReqVO reqVO) {
-        return success(SysDictDataConvert.INSTANCE.convertPage(dictDataService.getDictDataPage(reqVO)));
-    }
-
-    @ApiOperation("/查询字典数据详细")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @GetMapping(value = "/get")
-//    @PreAuthorize("@ss.hasPermi('system:dict:query')")
-    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 = "字典数据", businessData = BusinessData.INSERT)
-    public CommonResult<Long> createDictData(@Validated @RequestBody SysDictDataCreateReqVO reqVO) {
+    @ApiOperation("新增字典数据")
+    @PreAuthorize("@ss.hasPermission('system:dict:create')")
+    public CommonResult<Long> createDictData(@Valid @RequestBody SysDictDataCreateReqVO reqVO) {
         Long dictDataId = dictDataService.createDictData(reqVO);
         return success(dictDataId);
     }
 
+    @PutMapping("update")
     @ApiOperation("修改字典数据")
-    @PostMapping("update")
-//    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
-//    @Log(title = "字典数据", businessData = BusinessData.UPDATE)
-    public CommonResult<Boolean> updateDictData(@Validated @RequestBody SysDictDataUpdateReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:dict:update')")
+    public CommonResult<Boolean> updateDictData(@Valid @RequestBody SysDictDataUpdateReqVO reqVO) {
         dictDataService.updateDictData(reqVO);
         return success(true);
     }
 
+    @DeleteMapping("/delete")
     @ApiOperation("删除字典数据")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PostMapping("/delete")
-//    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @PreAuthorize("@ss.hasPermission('system:dict:delete')")
     public CommonResult<Boolean> deleteDictData(Long id) {
         dictDataService.deleteDictData(id);
         return success(true);
     }
 
-    @ApiOperation("导出字典数据")
+    @GetMapping("/list-all-simple")
+    @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
+    // 无需添加权限认证,因为前端全局都需要
+    public CommonResult<List<SysDictDataSimpleVO>> getSimpleDictDatas() {
+        List<SysDictDataDO> list = dictDataService.getDictDatas();
+        return success(SysDictDataConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("/获得字典类型的分页列表")
+    @PreAuthorize("@ss.hasPermission('system:dict:query')")
+    public CommonResult<PageResult<SysDictDataRespVO>> getDictTypePage(@Valid SysDictDataPageReqVO reqVO) {
+        return success(SysDictDataConvert.INSTANCE.convertPage(dictDataService.getDictDataPage(reqVO)));
+    }
+
+    @GetMapping(value = "/get")
+    @ApiOperation("/查询字典数据详细")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:dict:query')")
+    public CommonResult<SysDictDataRespVO> getDictData(@RequestParam("id") Long id) {
+        return success(SysDictDataConvert.INSTANCE.convert(dictDataService.getDictData(id)));
+    }
+
     @GetMapping("/export")
-//    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:dict:export')")
-    public void export(HttpServletResponse response, @Validated SysDictDataExportReqVO reqVO) throws IOException {
-        List<SysDictDataDO> list = dictDataService.getDictDataList(reqVO);
-        List<SysDictDataExcelVO> excelDataList = SysDictDataConvert.INSTANCE.convertList02(list);
+    @ApiOperation("导出字典数据")
+    @PreAuthorize("@ss.hasPermission('system:dict:export')")
+    @OperateLog(type = EXPORT)
+    public void export(HttpServletResponse response, @Valid SysDictDataExportReqVO reqVO) throws IOException {
+        List<SysDictDataDO> list = dictDataService.getDictDatas(reqVO);
+        List<SysDictDataExcelVO> data = SysDictDataConvert.INSTANCE.convertList02(list);
         // 输出
-        ExcelUtils.write(response, "字典数据.xls", "数据列表",
-                SysDictDataExcelVO.class, excelDataList);
+        ExcelUtils.write(response, "字典数据.xls", "数据列表", SysDictDataExcelVO.class, data);
     }
 
 }

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

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.*;
 import cn.iocoder.dashboard.modules.system.convert.dict.SysDictTypeConvert;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO;
@@ -10,66 +11,67 @@ import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.List;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "字典类型")
 @RestController
 @RequestMapping("/system/dict-type")
+@Validated
 public class SysDictTypeController {
 
     @Resource
     private SysDictTypeService dictTypeService;
 
-    @ApiOperation("/获得字典类型的分页列表")
-    @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:dict:list')")
-    public CommonResult<PageResult<SysDictTypeRespVO>> pageDictTypes(@Validated SysDictTypePageReqVO reqVO) {
-        return success(SysDictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO)));
-    }
-
-    @ApiOperation("/查询字典类型详细")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @GetMapping(value = "/get")
-//    @PreAuthorize("@ss.hasPermi('system:dict:query')")
-    public CommonResult<SysDictTypeRespVO> getDictType(@RequestParam("id") Long id) {
-        return success(SysDictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id)));
-    }
-
-    @ApiOperation("新增字典类型")
     @PostMapping("/create")
-//    @PreAuthorize("@ss.hasPermi('system:dict:add')")
-//    @Log(title = "字典类型", businessType = BusinessType.INSERT)
-    public CommonResult<Long> createDictType(@Validated @RequestBody SysDictTypeCreateReqVO reqVO) {
+    @ApiOperation("创建字典类型")
+    @PreAuthorize("@ss.hasPermission('system:dict:create')")
+    public CommonResult<Long> createDictType(@Valid @RequestBody SysDictTypeCreateReqVO reqVO) {
         Long dictTypeId = dictTypeService.createDictType(reqVO);
         return success(dictTypeId);
     }
 
-    @ApiOperation("修改字典类型")
     @PostMapping("update")
-//    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
-//    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateDictType(@Validated @RequestBody SysDictTypeUpdateReqVO reqVO) {
+    @ApiOperation("修改字典类型")
+    @PreAuthorize("@ss.hasPermission('system:dict:update')")
+    public CommonResult<Boolean> updateDictType(@Valid @RequestBody SysDictTypeUpdateReqVO reqVO) {
         dictTypeService.updateDictType(reqVO);
         return success(true);
     }
 
+    @DeleteMapping("/delete")
     @ApiOperation("删除字典类型")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PostMapping("/delete")
-//    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @PreAuthorize("@ss.hasPermission('system:dict:delete')")
     public CommonResult<Boolean> deleteDictType(Long id) {
         dictTypeService.deleteDictType(id);
         return success(true);
     }
 
+    @ApiOperation("/获得字典类型的分页列表")
+    @GetMapping("/page")
+    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    public CommonResult<PageResult<SysDictTypeRespVO>> pageDictTypes(@Valid SysDictTypePageReqVO reqVO) {
+        return success(SysDictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO)));
+    }
+
+    @ApiOperation("/查询字典类型详细")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @GetMapping(value = "/get")
+    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    public CommonResult<SysDictTypeRespVO> getDictType(@RequestParam("id") Long id) {
+        return success(SysDictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id)));
+    }
 
     @GetMapping("/list-all-simple")
     @ApiOperation(value = "获得全部字典类型列表", notes = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项")
@@ -81,14 +83,13 @@ public class SysDictTypeController {
 
     @ApiOperation("导出数据类型")
     @GetMapping("/export")
-//    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:dict:export')")
-    public void export(HttpServletResponse response, @Validated SysDictTypeExportReqVO reqVO) throws IOException {
+    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    @OperateLog(type = EXPORT)
+    public void export(HttpServletResponse response, @Valid SysDictTypeExportReqVO reqVO) throws IOException {
         List<SysDictTypeDO> list = dictTypeService.getDictTypeList(reqVO);
-        List<SysDictTypeExcelVO> excelTypeList = SysDictTypeConvert.INSTANCE.convertList02(list);
+        List<SysDictTypeExcelVO> data = SysDictTypeConvert.INSTANCE.convertList02(list);
         // 输出
-        ExcelUtils.write(response, "字典类型.xls", "类型列表",
-                SysDictTypeExcelVO.class, excelTypeList);
+        ExcelUtils.write(response, "字典类型.xls", "类型列表", SysDictTypeExcelVO.class, data);
     }
 
 }

+ 15 - 10
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java

@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
@@ -12,6 +13,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysLoginLogDO;
 import cn.iocoder.dashboard.modules.system.service.logger.SysLoginLogService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -19,36 +21,39 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.List;
 
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
 @Api(tags = "登陆日志")
 @RestController
 @RequestMapping("/system/login-log")
+@Validated
 public class SysLoginLogController {
 
     @Resource
     private SysLoginLogService loginLogService;
 
-    @ApiOperation("获得登陆日志分页列表")
     @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:login-log:query')")
-    public CommonResult<PageResult<SysLoginLogRespVO>> getLoginLogPage(@Validated SysLoginLogPageReqVO reqVO) {
+    @ApiOperation("获得登陆日志分页列表")
+    @PreAuthorize("@ss.hasPermission('system:login-log:query')")
+    public CommonResult<PageResult<SysLoginLogRespVO>> getLoginLogPage(@Valid SysLoginLogPageReqVO reqVO) {
         PageResult<SysLoginLogDO> page = loginLogService.getLoginLogPage(reqVO);
         return CommonResult.success(SysLoginLogConvert.INSTANCE.convertPage(page));
     }
 
-    @ApiOperation("导出登陆日志 Excel")
     @GetMapping("/export")
-//    @Log(title = "登录日志", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
-    public void exportLoginLog(HttpServletResponse response, @Validated SysLoginLogExportReqVO reqVO) throws IOException {
+    @ApiOperation("导出登陆日志 Excel")
+    @PreAuthorize("@ss.hasPermission('system:login-log:export')")
+    @OperateLog(type = EXPORT)
+    public void exportLoginLog(HttpServletResponse response, @Valid SysLoginLogExportReqVO reqVO) throws IOException {
         List<SysLoginLogDO> list = loginLogService.getLoginLogList(reqVO);
         // 拼接数据
-        List<SysLoginLogExcelVO> excelDataList = SysLoginLogConvert.INSTANCE.convertList(list);
+        List<SysLoginLogExcelVO> data = SysLoginLogConvert.INSTANCE.convertList(list);
         // 输出
-        ExcelUtils.write(response, "登陆日志.xls", "数据列表",
-                SysLoginLogExcelVO.class, excelDataList);
+        ExcelUtils.write(response, "登陆日志.xls", "数据列表", SysLoginLogExcelVO.class, data);
     }
 
 }

+ 9 - 25
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java

@@ -4,8 +4,6 @@ import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
-import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum;
-import cn.iocoder.dashboard.framework.logger.operatelog.core.util.OperateLogUtils;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO;
@@ -19,6 +17,7 @@ import cn.iocoder.dashboard.util.collection.CollectionUtils;
 import cn.iocoder.dashboard.util.collection.MapUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -26,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -38,32 +38,18 @@ import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.Operat
 @Api(tags = "操作日志")
 @RestController
 @RequestMapping("/system/operate-log")
+@Validated
 public class SysOperateLogController {
 
     @Resource
     private SysOperateLogService operateLogService;
-
     @Resource
     private SysUserService userService;
 
-    @ApiOperation("示例")
-    @OperateLog(type = OperateTypeEnum.OTHER)
-    @GetMapping("/demo")
-    public CommonResult<Boolean> demo() {
-        // 这里可以调用业务逻辑
-
-        // 补全操作日志的明细
-        OperateLogUtils.setContent("将编号 1 的数据,xxx 字段修改成了 yyyy");
-        OperateLogUtils.addExt("orderId", 1);
-
-        // 响应
-        return success(true);
-    }
-
-    @ApiOperation("查看操作日志分页列表")
     @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:operate-log:query')")
-    public CommonResult<PageResult<SysOperateLogRespVO>> pageOperateLog(@Validated SysOperateLogPageReqVO reqVO) {
+    @ApiOperation("查看操作日志分页列表")
+    @PreAuthorize("@ss.hasPermission('system:operate-log:query')")
+    public CommonResult<PageResult<SysOperateLogRespVO>> pageOperateLog(@Valid SysOperateLogPageReqVO reqVO) {
         PageResult<SysOperateLogDO> pageResult = operateLogService.pageOperateLog(reqVO);
 
         // 获得拼接需要的数据
@@ -82,10 +68,9 @@ public class SysOperateLogController {
 
     @ApiOperation("导出操作日志")
     @GetMapping("/export")
+    @PreAuthorize("@ss.hasPermission('system:operate-log:export')")
     @OperateLog(type = EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:operate-log:export')")
-    public void exportOperateLog(HttpServletResponse response, @Validated SysOperateLogExportReqVO reqVO)
-            throws IOException {
+    public void exportOperateLog(HttpServletResponse response, @Valid SysOperateLogExportReqVO reqVO) throws IOException {
         List<SysOperateLogDO> list = operateLogService.listOperateLogs(reqVO);
 
         // 获得拼接需要的数据
@@ -94,8 +79,7 @@ public class SysOperateLogController {
         // 拼接数据
         List<SysOperateLogExcelVO> excelDataList = SysOperateLogConvert.INSTANCE.convertList(list, userMap);
         // 输出
-        ExcelUtils.write(response, "操作日志.xls", "数据列表",
-                SysOperateLogExcelVO.class, excelDataList);
+        ExcelUtils.write(response, "操作日志.xls", "数据列表", SysOperateLogExcelVO.class, excelDataList);
     }
 
 }

+ 26 - 26
src/main/java/cn/iocoder/dashboard/modules/system/controller/notice/SysNoticeController.java

@@ -11,62 +11,62 @@ import cn.iocoder.dashboard.modules.system.service.notice.SysNoticeService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.validation.Valid;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 
 @Api(tags = "通知公告")
 @RestController
 @RequestMapping("/system/notice")
+@Validated
 public class SysNoticeController {
 
     @Resource
     private SysNoticeService noticeService;
 
-    @ApiOperation("获取通知公告列表")
-    @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:notice:list')")
-    public CommonResult<PageResult<SysNoticeRespVO>> pageNotices(@Validated SysNoticePageReqVO reqVO) {
-        return success(SysNoticeConvert.INSTANCE.convertPage(noticeService.pageNotices(reqVO)));
-    }
-
-    @ApiOperation("获得通知公告")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:notice:query')")
-    @GetMapping(value = "/get")
-    public CommonResult<SysNoticeRespVO> getNotice(@RequestParam("id") Long id) {
-        return success(SysNoticeConvert.INSTANCE.convert(noticeService.getNotice(id)));
-    }
-
-    @ApiOperation("新增通知公告")
-//    @PreAuthorize("@ss.hasPermi('system:notice:add')")
-//    @Log(title = "通知公告", businessType = BusinessType.INSERT)
     @PostMapping("/create")
-    public CommonResult<Long> createNotice(@Validated @RequestBody SysNoticeCreateReqVO reqVO) {
+    @ApiOperation("创建通知公告")
+    @PreAuthorize("@ss.hasPermission('system:notice:create')")
+    public CommonResult<Long> createNotice(@Valid @RequestBody SysNoticeCreateReqVO reqVO) {
         Long noticeId = noticeService.createNotice(reqVO);
         return success(noticeId);
     }
 
+    @PutMapping("/update")
     @ApiOperation("修改通知公告")
-//    @PreAuthorize("@ss.hasPermi('system:notice:edit')")
-//    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
-    @PostMapping("/update")
-    public CommonResult<Boolean> updateNotice(@Validated @RequestBody SysNoticeUpdateReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:notice:update')")
+    public CommonResult<Boolean> updateNotice(@Valid @RequestBody SysNoticeUpdateReqVO reqVO) {
         noticeService.updateNotice(reqVO);
         return success(true);
     }
 
+    @DeleteMapping("/delete")
     @ApiOperation("删除通知公告")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
-//    @Log(title = "通知公告", businessType = BusinessType.DELETE)
-    @PostMapping("/delete")
+    @PreAuthorize("@ss.hasPermission('system:notice:delete')")
     public CommonResult<Boolean> deleteNotice(@RequestParam("id") Long id) {
         noticeService.deleteNotice(id);
         return success(true);
     }
 
+    @GetMapping("/page")
+    @ApiOperation("获取通知公告列表")
+    @PreAuthorize("@ss.hasPermission('system:notice:quey')")
+    public CommonResult<PageResult<SysNoticeRespVO>> pageNotices(@Validated SysNoticePageReqVO reqVO) {
+        return success(SysNoticeConvert.INSTANCE.convertPage(noticeService.pageNotices(reqVO)));
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得通知公告")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:notice:quey')")
+    public CommonResult<SysNoticeRespVO> getNotice(@RequestParam("id") Long id) {
+        return success(SysNoticeConvert.INSTANCE.convert(noticeService.getNotice(id)));
+    }
+
 }

+ 37 - 49
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.java

@@ -9,10 +9,12 @@ import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.validation.Valid;
 import java.util.Comparator;
 import java.util.List;
 
@@ -21,78 +23,64 @@ import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
 @Api(tags = "菜单")
 @RestController
 @RequestMapping("/system/menu")
+@Validated
 public class SysMenuController {
 
     @Resource
     private SysMenuService menuService;
 
-    @ApiOperation("获取菜单列表")
-//    @PreAuthorize("@ss.hasPermi('system:menu:list')")
+    @PostMapping("/create")
+    @ApiOperation("创建菜单")
+    @PreAuthorize("@ss.hasPermission('system:menu:create')")
+    public CommonResult<Long> createMenu(@Valid @RequestBody SysMenuCreateReqVO reqVO) {
+        Long menuId = menuService.createMenu(reqVO);
+        return success(menuId);
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("修改菜单")
+    @PreAuthorize("@ss.hasPermission('system:menu:update')")
+    public CommonResult<Boolean> updateMenu(@Valid @RequestBody SysMenuUpdateReqVO reqVO) {
+        menuService.updateMenu(reqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除菜单")
+    @ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:menu:delete')")
+    public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
+        menuService.deleteMenu(id);
+        return success(true);
+    }
+
     @GetMapping("/list")
-    public CommonResult<List<SysMenuRespVO>> listMenus(SysMenuListReqVO reqVO) {
-        List<SysMenuDO> list = menuService.listMenus(reqVO);
+    @ApiOperation("获取菜单列表")
+    @PreAuthorize("@ss.hasPermission('system:menu:query')")
+    public CommonResult<List<SysMenuRespVO>> getMenus(SysMenuListReqVO reqVO) {
+        List<SysMenuDO> list = menuService.getMenus(reqVO);
         list.sort(Comparator.comparing(SysMenuDO::getSort));
         return success(SysMenuConvert.INSTANCE.convertList(list));
     }
 
-    @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,主要用于前端的下拉选项")
     @GetMapping("/list-all-simple")
-    public CommonResult<List<SysMenuSimpleRespVO>> listSimpleMenus() {
+    @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,主要用于前端的下拉选项")
+    public CommonResult<List<SysMenuSimpleRespVO>> getSimpleMenus() {
         // 获得菜单列表,只要开启状态的
         SysMenuListReqVO reqVO = new SysMenuListReqVO();
         reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        List<SysMenuDO> list = menuService.listMenus(reqVO);
+        List<SysMenuDO> list = menuService.getMenus(reqVO);
         // 排序后,返回个诶前端
         list.sort(Comparator.comparing(SysMenuDO::getSort));
         return success(SysMenuConvert.INSTANCE.convertList02(list));
     }
 
-    @ApiOperation("获取菜单信息")
     @GetMapping("/get")
-//    @PreAuthorize("@ss.hasPermi('system:menu:query')")
+    @ApiOperation("获取菜单信息")
+    @PreAuthorize("@ss.hasPermission('system:menu:query')")
     public CommonResult<SysMenuRespVO> getMenu(Long id) {
         SysMenuDO menu = menuService.getMenu(id);
         return success(SysMenuConvert.INSTANCE.convert(menu));
     }
 
-//    /**
-//     * 加载对应角色菜单列表树
-//     */
-//    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
-//    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
-//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-//        List<SysMenu> menus = menuService.selectMenuList(loginUser.getUser().getUserId());
-//        AjaxResult ajax = AjaxResult.success();
-//        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
-//        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
-//        return ajax;
-//    }
-
-    @ApiOperation("创建菜单")
-//    @PreAuthorize("@ss.hasPermi('system:menu:add')")
-//    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
-    @PostMapping("/create")
-    public CommonResult<Long> createMenu(@Validated @RequestBody SysMenuCreateReqVO reqVO) {
-        Long menuId = menuService.createMenu(reqVO);
-        return success(menuId);
-    }
-
-    @ApiOperation("修改菜单")
-//    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
-//    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
-    @PostMapping("/update")
-    public CommonResult<Boolean> updateMenu(@Validated @RequestBody SysMenuUpdateReqVO reqVO) {
-        menuService.updateMenu(reqVO);
-        return success(true);
-    }
-
-    @ApiOperation("删除菜单")
-    @PostMapping("/delete")
-    @ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024", dataTypeClass = Long.class)
-//    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
-    public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
-        menuService.deleteMenu(id);
-        return success(true);
-    }
-
 }

+ 43 - 43
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java

@@ -4,6 +4,7 @@ import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.*;
 import cn.iocoder.dashboard.modules.system.convert.permission.SysRoleConvert;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO;
@@ -11,96 +12,95 @@ import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "角色")
 @RestController
 @RequestMapping("/system/role")
+@Validated
 public class SysRoleController {
 
     @Resource
     private SysRoleService roleService;
 
-    @ApiOperation("获得角色分页")
-    @GetMapping("/page")
-//    @PreAuthorize("@ss.hasPermi('system:role:list')")
-    public CommonResult<PageResult<SysRoleDO>> list(SysRolePageReqVO reqVO) {
-        return success(roleService.pageRole(reqVO));
-    }
-
-    @ApiOperation(value = "获取角色精简信息列表", notes = "只包含被开启的角色,主要用于前端的下拉选项")
-    @GetMapping("/list-all-simple")
-    public CommonResult<List<SysRoleSimpleRespVO>> listSimpleRoles() {
-        // 获得角色列表,只要开启状态的
-        List<SysRoleDO> list = roleService.listRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
-        // 排序后,返回个诶前端
-        list.sort(Comparator.comparing(SysRoleDO::getSort));
-        return success(SysRoleConvert.INSTANCE.convertList02(list));
-    }
-
-    @ApiOperation("创建角色")
     @PostMapping("/create")
-//    @PreAuthorize("@ss.hasPermi('system:role:add')")
-//    @Log(title = "角色管理", businessType = BusinessType.INSERT)
-    public CommonResult<Long> add(@Validated @RequestBody SysRoleCreateReqVO reqVO) {
+    @ApiOperation("创建角色")
+    @PreAuthorize("@ss.hasPermission('system:role:create')")
+    public CommonResult<Long> createRole(@Valid @RequestBody SysRoleCreateReqVO reqVO) {
         return success(roleService.createRole(reqVO));
     }
 
+    @PutMapping("/update")
     @ApiOperation("修改角色")
-//    @PreAuthorize("@ss.hasPermi('system:role:edit')")
-//    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
-    @PostMapping("/update")
-    public CommonResult<Boolean> update(@Validated @RequestBody SysRoleUpdateReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:role:update')")
+    public CommonResult<Boolean> updateRole(@Valid @RequestBody SysRoleUpdateReqVO reqVO) {
         roleService.updateRole(reqVO);
         return success(true);
     }
 
+    @PutMapping("/update-status")
+    @ApiOperation("修改角色状态")
+    @PreAuthorize("@ss.hasPermission('system:role:update')")
+    public CommonResult<Boolean> updateRoleStatus(@Valid @RequestBody SysRoleUpdateStatusReqVO reqVO) {
+        roleService.updateRoleStatus(reqVO.getId(), reqVO.getStatus());
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
     @ApiOperation("删除角色")
-    @PostMapping("/delete")
     @ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:role:remove')")
-//    @Log(title = "角色管理", businessType = BusinessType.DELETE)
+    @PreAuthorize("@ss.hasPermission('system:role:delete')")
     public CommonResult<Boolean> deleteRole(@RequestParam("id") Long id) {
         roleService.deleteRole(id);
         return success(true);
     }
 
-    @ApiOperation("获得角色信息")
     @GetMapping("/get")
-//    @PreAuthorize("@ss.hasPermi('system:role:query')")
+    @ApiOperation("获得角色信息")
+    @PreAuthorize("@ss.hasPermission('system:role:query')")
     public CommonResult<SysRoleRespVO> getRole(@RequestParam("id") Long id) {
         SysRoleDO role = roleService.getRole(id);
         return success(SysRoleConvert.INSTANCE.convert(role));
     }
 
-    @ApiOperation("修改角色状态")
-    @PostMapping("/update-status")
-//    @PreAuthorize("@ss.hasPermi('system:role:edit')")
-//    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateRoleStatus(@Validated @RequestBody SysRoleUpdateStatusReqVO reqVO) {
-        roleService.updateRoleStatus(reqVO.getId(), reqVO.getStatus());
-        return success(true);
+    @GetMapping("/page")
+    @ApiOperation("获得角色分页")
+    @PreAuthorize("@ss.hasPermission('system:role:query')")
+    public CommonResult<PageResult<SysRoleDO>> getRolePage(SysRolePageReqVO reqVO) {
+        return success(roleService.getRolePage(reqVO));
+    }
+
+    @GetMapping("/list-all-simple")
+    @ApiOperation(value = "获取角色精简信息列表", notes = "只包含被开启的角色,主要用于前端的下拉选项")
+    public CommonResult<List<SysRoleSimpleRespVO>> getSimpleRoles() {
+        // 获得角色列表,只要开启状态的
+        List<SysRoleDO> list = roleService.getRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
+        // 排序后,返回个诶前端
+        list.sort(Comparator.comparing(SysRoleDO::getSort));
+        return success(SysRoleConvert.INSTANCE.convertList02(list));
     }
 
     @GetMapping("/export")
-//    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
-//    @PreAuthorize("@ss.hasPermi('system:role:export')")
+    @OperateLog(type = EXPORT)
+    @PreAuthorize("@ss.hasPermission('system:role:export')")
     public void export(HttpServletResponse response, @Validated SysRoleExportReqVO reqVO) throws IOException {
-        List<SysRoleDO> list = roleService.listRoles(reqVO);
-        List<SysRoleExcelVO> excelDataList = SysRoleConvert.INSTANCE.convertList03(list);
+        List<SysRoleDO> list = roleService.getRoles(reqVO);
+        List<SysRoleExcelVO> data = SysRoleConvert.INSTANCE.convertList03(list);
         // 输出
-        ExcelUtils.write(response, "角色数据.xls", "角色列表",
-                SysRoleExcelVO.class, excelDataList);
+        ExcelUtils.write(response, "角色数据.xls", "角色列表", SysRoleExcelVO.class, data);
     }
 
 }

+ 58 - 65
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java

@@ -5,6 +5,7 @@ import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 import cn.iocoder.dashboard.common.pojo.CommonResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*;
 import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
@@ -25,14 +26,17 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.*;
 
 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
 @Api(tags = "用户")
 @RestController
 @RequestMapping("/system/user")
+@Validated
 public class SysUserController {
 
     @Resource
@@ -40,94 +44,86 @@ public class SysUserController {
     @Resource
     private SysDeptService deptService;
 
-    @ApiOperation("获得用户分页列表")
-    @GetMapping("/page")
-    @PreAuthorize("@ss.hasPermission('system:user:list')")
-    public CommonResult<PageResult<SysUserPageItemRespVO>> pageUsers(@Validated SysUserPageReqVO reqVO) {
-        // 获得用户分页列表
-        PageResult<SysUserDO> pageResult = userService.pageUsers(reqVO);
-        if (CollUtil.isEmpty(pageResult.getList())) {
-            return success(new PageResult<>(pageResult.getTotal())); // 返回空
-        }
-
-        // 获得拼接需要的数据
-        Collection<Long> deptIds = CollectionUtils.convertList(pageResult.getList(), SysUserDO::getDeptId);
-        Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(deptIds);
-        // 拼接结果返回
-        List<SysUserPageItemRespVO> userList = new ArrayList<>(pageResult.getList().size());
-        pageResult.getList().forEach(user -> {
-            SysUserPageItemRespVO respVO = SysUserConvert.INSTANCE.convert(user);
-            respVO.setDept(SysUserConvert.INSTANCE.convert(deptMap.get(user.getDeptId())));
-            userList.add(respVO);
-        });
-        return success(new PageResult<>(userList, pageResult.getTotal()));
-    }
-
-    /**
-     * 根据用户编号获取详细信息
-     */
-    @ApiOperation("获得用户详情")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @GetMapping("/get")
-//    @PreAuthorize("@ss.hasPermi('system:user:query')")
-    public CommonResult<SysUserRespVO> getInfo(@RequestParam("id") Long id) {
-        return success(SysUserConvert.INSTANCE.convert(userService.getUser(id)));
-    }
-
-    @ApiOperation("新增用户")
     @PostMapping("/create")
-//    @PreAuthorize("@ss.hasPermi('system:user:add')")
-//    @Log(title = "用户管理", businessType = BusinessType.INSERT)
-    public CommonResult<Long> createUser(@Validated @RequestBody SysUserCreateReqVO reqVO) {
+    @ApiOperation("新增用户")
+    @PreAuthorize("@ss.hasPermission('system:user:create')")
+    public CommonResult<Long> createUser(@Valid @RequestBody SysUserCreateReqVO reqVO) {
         Long id = userService.createUser(reqVO);
         return success(id);
     }
 
+    @PutMapping("update")
     @ApiOperation("修改用户")
-    @PostMapping("update")
-//    @PreAuthorize("@ss.hasPermi('system:user:edit')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUser(@Validated @RequestBody SysUserUpdateReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:user:update')")
+    public CommonResult<Boolean> updateUser(@Valid @RequestBody SysUserUpdateReqVO reqVO) {
         userService.updateUser(reqVO);
         return success(true);
     }
 
+    @DeleteMapping("/delete")
     @ApiOperation("删除用户")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PostMapping("/delete")
-//    @PreAuthorize("@ss.hasPermi('system:user:remove')")
-//    @Log(title = "用户管理", businessType = BusinessType.DELETE)
+    @PreAuthorize("@ss.hasPermission('system:user:delete')")
     public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
         userService.deleteUser(id);
         return success(true);
     }
 
+    @PutMapping("/update-password")
     @ApiOperation("重置用户密码")
-    @PostMapping("/update-password")
-//    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUserPassword(@Validated @RequestBody SysUserUpdatePasswordReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:user:update-password')")
+    public CommonResult<Boolean> updateUserPassword(@Valid @RequestBody SysUserUpdatePasswordReqVO reqVO) {
         userService.updateUserPassword(reqVO.getId(), reqVO.getPassword());
         return success(true);
     }
 
+    @PutMapping("/update-status")
     @ApiOperation("修改用户状态")
-    @PostMapping("/update-status")
-//    @PreAuthorize("@ss.hasPermi('system:user:edit')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUserStatus(@Validated @RequestBody SysUserUpdateStatusReqVO reqVO) {
+    @PreAuthorize("@ss.hasPermission('system:user:update')")
+    public CommonResult<Boolean> updateUserStatus(@Valid @RequestBody SysUserUpdateStatusReqVO reqVO) {
         userService.updateUserStatus(reqVO.getId(), reqVO.getStatus());
         return success(true);
     }
 
-    @ApiOperation("导出用户")
+    @GetMapping("/page")
+    @ApiOperation("获得用户分页列表")
+    @PreAuthorize("@ss.hasPermission('system:user:list')")
+    public CommonResult<PageResult<SysUserPageItemRespVO>> getUserPage(@Valid SysUserPageReqVO reqVO) {
+        // 获得用户分页列表
+        PageResult<SysUserDO> pageResult = userService.getUserPage(reqVO);
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return success(new PageResult<>(pageResult.getTotal())); // 返回空
+        }
+
+        // 获得拼接需要的数据
+        Collection<Long> deptIds = CollectionUtils.convertList(pageResult.getList(), SysUserDO::getDeptId);
+        Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(deptIds);
+        // 拼接结果返回
+        List<SysUserPageItemRespVO> userList = new ArrayList<>(pageResult.getList().size());
+        pageResult.getList().forEach(user -> {
+            SysUserPageItemRespVO respVO = SysUserConvert.INSTANCE.convert(user);
+            respVO.setDept(SysUserConvert.INSTANCE.convert(deptMap.get(user.getDeptId())));
+            userList.add(respVO);
+        });
+        return success(new PageResult<>(userList, pageResult.getTotal()));
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得用户详情")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:user:query')")
+    public CommonResult<SysUserRespVO> getInfo(@RequestParam("id") Long id) {
+        return success(SysUserConvert.INSTANCE.convert(userService.getUser(id)));
+    }
+
     @GetMapping("/export")
-//    @PreAuthorize("@ss.hasPermi('system:user:export')") , @Validated SysUserExportReqVO reqVO
-//    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
+    @ApiOperation("导出用户")
+    @PreAuthorize("@ss.hasPermission('system:user:export')")
+    @OperateLog(type = EXPORT)
     public void exportUsers(@Validated SysUserExportReqVO reqVO,
                             HttpServletResponse response) throws IOException {
         // 获得用户列表
-        List<SysUserDO> users = userService.listUsers(reqVO);
+        List<SysUserDO> users = userService.getUsers(reqVO);
 
         // 获得拼接需要的数据
         Collection<Long> deptIds = CollectionUtils.convertList(users, SysUserDO::getDeptId);
@@ -147,8 +143,8 @@ public class SysUserController {
         ExcelUtils.write(response, "用户数据.xls", "用户列表", SysUserExcelVO.class, excelUsers);
     }
 
-    @ApiOperation("获得导入用户模板")
     @GetMapping("/get-import-template")
+    @ApiOperation("获得导入用户模板")
     public void importTemplate(HttpServletResponse response) throws IOException {
         // 手动创建导出 demo
         List<SysUserImportExcelVO> list = Arrays.asList(
@@ -159,21 +155,18 @@ public class SysUserController {
         );
 
         // 输出
-        ExcelUtils.write(response, "用户导入模板.xls", "用户列表",
-                SysUserImportExcelVO.class, list);
-
+        ExcelUtils.write(response, "用户导入模板.xls", "用户列表", SysUserImportExcelVO.class, list);
     }
 
+    @PostMapping("/import")
     @ApiOperation("导入用户")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "file", value = "Excel 文件", required = true, dataTypeClass = MultipartFile.class),
             @ApiImplicitParam(name = "updateSupport", value = "是否支持更新,默认为 false", example = "true", dataTypeClass = Boolean.class)
     })
-    @PostMapping("/import")
-//    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
-//    @PreAuthorize("@ss.hasPermi('system:user:import')")
+    @PreAuthorize("@ss.hasPermission('system:user:import')")
     public CommonResult<SysUserImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
-                                                         @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
+             @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
         List<SysUserImportExcelVO> list = ExcelUtils.raed(file, SysUserImportExcelVO.class);
         return success(userService.importUsers(list, updateSupport));
     }

+ 85 - 86
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java

@@ -1,92 +1,91 @@
 package cn.iocoder.dashboard.modules.system.controller.user;
 
+import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.dashboard.common.pojo.CommonResult;
+import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileRespVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVo;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
+import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
+import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
+import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
+import cn.iocoder.dashboard.util.collection.CollectionUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_IS_EMPTY;
+
+/**
+ * @author niudehua
+ */
+@RestController
+@RequestMapping("/system/user/profile")
+@Api(tags = "用户个人中心")
+@Slf4j
 public class SysUserProfileController {
 
-//    /**
-//     * 个人信息
-//     */
-//    @GetMapping
-//    public AjaxResult profile()
-//    {
-//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-//        SysUser user = loginUser.getUser();
-//        AjaxResult ajax = AjaxResult.success(user);
-//        ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
-//        ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
-//        return ajax;
-//    }
-//
-//    /**
-//     * 修改用户
-//     */
-//    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
-//    @PutMapping
-//    public AjaxResult updateProfile(@RequestBody SysUser user)
-//    {
-//        if (userService.updateUserProfile(user) > 0)
-//        {
-//            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-//            // 更新缓存用户信息
-//            loginUser.getUser().setNickName(user.getNickName());
-//            loginUser.getUser().setPhonenumber(user.getPhonenumber());
-//            loginUser.getUser().setEmail(user.getEmail());
-//            loginUser.getUser().setSex(user.getSex());
-//            tokenService.setLoginUser(loginUser);
-//            return AjaxResult.success();
-//        }
-//        return AjaxResult.error("修改个人信息异常,请联系管理员");
-//    }
-//
-//    /**
-//     * 重置密码
-//     */
-//    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
-//    @PutMapping("/updatePwd")
-//    public AjaxResult updatePwd(String oldPassword, String newPassword)
-//    {
-//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-//        String userName = loginUser.getUsername();
-//        String password = loginUser.getPassword();
-//        if (!SecurityUtils.matchesPassword(oldPassword, password))
-//        {
-//            return AjaxResult.error("修改密码失败,旧密码错误");
-//        }
-//        if (SecurityUtils.matchesPassword(newPassword, password))
-//        {
-//            return AjaxResult.error("新密码不能与旧密码相同");
-//        }
-//        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
-//        {
-//            // 更新缓存用户密码
-//            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
-//            tokenService.setLoginUser(loginUser);
-//            return AjaxResult.success();
-//        }
-//        return AjaxResult.error("修改密码异常,请联系管理员");
-//    }
-//
-//    /**
-//     * 头像上传
-//     */
-//    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
-//    @PostMapping("/avatar")
-//    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException
-//    {
-//        if (!file.isEmpty())
-//        {
-//            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-//            String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file);
-//            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
-//            {
-//                AjaxResult ajax = AjaxResult.success();
-//                ajax.put("imgUrl", avatar);
-//                // 更新缓存用户头像
-//                loginUser.getUser().setAvatar(avatar);
-//                tokenService.setLoginUser(loginUser);
-//                return ajax;
-//            }
-//        }
-//        return AjaxResult.error("上传图片异常,请联系管理员");
-//    }
+    @Resource
+    private SysUserService userService;
+    @Resource
+    private SysPermissionService permissionService;
+    @Resource
+    private SysRoleService roleService;
+
+    @GetMapping("/get")
+    @ApiOperation("获得登录用户信息")
+    public CommonResult<SysUserProfileRespVO> profile() {
+        // 获取用户信息
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        SysUserDO user = userService.getUser(userId);
+        SysUserProfileRespVO userProfileRespVO = SysUserConvert.INSTANCE.convert03(user);
+        List<SysRoleDO> userRoles = roleService.getRolesFromCache(permissionService.listUserRoleIs(userId));
+        userProfileRespVO.setRoles(CollectionUtils.convertSet(userRoles, SysUserConvert.INSTANCE::convert));
+        return success(userProfileRespVO);
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("修改用户个人信息")
+    public CommonResult<Boolean> updateUserProfile(@Valid @RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) {
+        userService.updateUserProfile(reqVO);
+        SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request);
+        return success(true);
+    }
+
+    @PutMapping("/update-password")
+    @ApiOperation("修改用户个人密码")
+    public CommonResult<Boolean> updateUserProfilePassword(@Valid @RequestBody SysUserProfileUpdatePasswordReqVo reqVO, HttpServletRequest request) {
+        userService.updateUserPassword(reqVO);
+        SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request);
+        return success(true);
+    }
+
+    @PutMapping("/upload-avatar")
+    @ApiOperation("上传用户个人头像")
+    public CommonResult<Boolean> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
+        if (file.isEmpty()) {
+            throw ServiceExceptionUtil.exception(FILE_IS_EMPTY);
+        }
+        userService.updateUserAvatar(SecurityFrameworkUtils.getLoginUserId(), file.getInputStream());
+        return success(true);
+    }
 
 }

+ 53 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java

@@ -0,0 +1,53 @@
+package cn.iocoder.dashboard.modules.system.controller.user.vo.profile;
+
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserBaseVO;
+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;
+import java.util.Set;
+
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("用户个人中心信息 Response VO")
+public class SysUserProfileRespVO extends SysUserBaseVO {
+    @ApiModelProperty(value = "用户编号", required = true, example = "1")
+    private Long id;
+
+    @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
+    private Integer status;
+
+    @ApiModelProperty(value = "最后登陆 IP", required = true, example = "192.168.1.1")
+    private String loginIp;
+
+    @ApiModelProperty(value = "最后登录时间", required = true, example = "时间戳格式")
+    private Date loginDate;
+
+    @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
+    private Date createTime;
+
+    /**
+     * 所属角色
+     */
+    @ApiModelProperty(value = "所属角色", required = true, example = "123456")
+    private Set<Role> roles;
+
+    @ApiModel("角色")
+    @Data
+    public static class Role {
+
+        @ApiModelProperty(value = "角色编号", required = true, example = "1")
+        private Long id;
+
+        @ApiModelProperty(value = "角色名称", required = true, example = "普通角色")
+        private String name;
+
+    }
+}

+ 36 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVo.java

@@ -0,0 +1,36 @@
+package cn.iocoder.dashboard.modules.system.controller.user.vo.profile;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 类名称:SysUserUpdatePersonalPasswordReqVo
+ * ***********************
+ * <p>
+ * 类描述:更新用户个人密码
+ *
+ * @author deng on 2021/3/15 22:04
+ */
+@ApiModel("用户个人中心更新密码 Response VO")
+@Data
+public class SysUserProfileUpdatePasswordReqVo {
+
+    @ApiModelProperty(value = "用户编号", required = true, example = "1024")
+    @NotNull(message = "用户编号不能为空")
+    private Long id;
+
+    @ApiModelProperty(value = "旧密码", required = true, example = "123456")
+    @NotEmpty(message = "旧密码不能为空")
+    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
+    private String oldPassword;
+
+    @ApiModelProperty(value = "新密码", required = true, example = "654321")
+    @NotEmpty(message = "新密码不能为空")
+    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
+    private String newPassword;
+}

+ 39 - 0
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.dashboard.modules.system.controller.user.vo.profile;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+@ApiModel("用户个人信息更新 Request VO")
+@Data
+public class SysUserProfileUpdateReqVO {
+
+    @ApiModelProperty(value = "用户编号", required = true, example = "1024")
+    @NotNull(message = "用户编号不能为空")
+    private Long id;
+
+    @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
+    @Size(max = 30, message = "用户昵称长度不能超过30个字符")
+    private String nickname;
+
+    @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
+    @Email(message = "邮箱格式不正确")
+    @Size(max = 50, message = "邮箱长度不能超过50个字符")
+    private String email;
+
+    @ApiModelProperty(value = "手机号码", example = "15601691300")
+    @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
+    private String mobile;
+
+    @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类")
+    private Integer sex;
+
+    @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png")
+    private String avatar;
+
+}

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserBaseVO.java

@@ -5,6 +5,7 @@ import lombok.Data;
 
 import javax.validation.constraints.Email;
 import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
 import javax.validation.constraints.Size;
 import java.util.Set;
 
@@ -39,7 +40,7 @@ public class SysUserBaseVO {
     private String email;
 
     @ApiModelProperty(value = "手机号码", example = "15601691300")
-    @Size(max = 11, message = "手机号码长度不能超过11个字符")
+    @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
     private String mobile;
 
     @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类")
@@ -48,5 +49,4 @@ public class SysUserBaseVO {
     @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png")
     private String avatar;
 
-
 }

+ 19 - 8
src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java

@@ -3,6 +3,8 @@ package cn.iocoder.dashboard.modules.system.convert.auth;
 import cn.iocoder.dashboard.framework.security.core.LoginUser;
 import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO;
 import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVo;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysMenuDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
@@ -13,26 +15,35 @@ import org.mapstruct.Mapping;
 import org.mapstruct.factory.Mappers;
 import org.slf4j.LoggerFactory;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 @Mapper
 public interface SysAuthConvert {
 
     SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class);
 
-    @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略
+    @Mapping(source = "updateTime", target = "updateTime", ignore = true)
+        // 字段相同,但是含义不同,忽略
     LoginUser convert(SysUserDO bean);
 
     default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) {
         return SysAuthPermissionInfoRespVO.builder()
-                .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build())
-                .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode))
-                .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission))
-                .build();
+            .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build())
+            .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode))
+            .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission))
+            .build();
     }
 
     SysAuthMenuRespVO convertTreeNode(SysMenuDO menu);
 
+    LoginUser convert(SysUserProfileUpdateReqVO reqVO);
+
+    LoginUser convert(SysUserProfileUpdatePasswordReqVo reqVO);
+
     /**
      * 将菜单列表,构建成菜单树
      *
@@ -47,12 +58,12 @@ public interface SysAuthConvert {
         Map<Long, SysAuthMenuRespVO> treeNodeMap = new LinkedHashMap<>();
         menuList.forEach(menu -> treeNodeMap.put(menu.getId(), SysAuthConvert.INSTANCE.convertTreeNode(menu)));
         // 处理父子关系
-        treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach((childNode) -> {
+        treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach(childNode -> {
             // 获得父节点
             SysAuthMenuRespVO parentNode = treeNodeMap.get(childNode.getParentId());
             if (parentNode == null) {
                 LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]",
-                        childNode.getId(), childNode.getParentId());
+                    childNode.getId(), childNode.getParentId());
                 return;
             }
             // 将自己添加到父节点中

+ 18 - 1
src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java

@@ -1,7 +1,15 @@
 package cn.iocoder.dashboard.modules.system.convert.user;
 
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileRespVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVo;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExcelVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -23,4 +31,13 @@ public interface SysUserConvert {
 
     SysUserDO convert(SysUserImportExcelVO bean);
 
+    SysUserProfileRespVO convert03(SysUserDO bean);
+
+    SysUserProfileRespVO.Role convert(SysRoleDO bean);
+
+    SysUserDO convert(SysUserProfileUpdateReqVO bean);
+
+    SysUserDO convert(SysUserProfileUpdatePasswordReqVo bean);
+
+
 }

+ 0 - 30
src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/common/SysFileDO.java

@@ -1,30 +0,0 @@
-package cn.iocoder.dashboard.modules.system.dal.dataobject.common;
-
-import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 文件表
- *
- * @author 芋道源码
- */
-@Data
-@TableName("sys_file")
-@EqualsAndHashCode(callSuper = true)
-public class SysFileDO extends BaseDO {
-
-    /**
-     * 文件路径
-     */
-    @TableId(type = IdType.INPUT)
-    private String id;
-    /**
-     * 文件内容
-     */
-    private byte[] content;
-
-}

+ 0 - 15
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/common/SysFileMapper.java

@@ -1,15 +0,0 @@
-package cn.iocoder.dashboard.modules.system.dal.mysql.common;
-
-import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SysFileMapper extends BaseMapper<SysFileDO> {
-
-    default Integer selectCountById(String id) {
-        return selectCount(new QueryWrapper<SysFileDO>().eq("id", id));
-    }
-
-}

+ 8 - 0
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java

@@ -33,6 +33,14 @@ public interface SysRoleMenuMapper extends BaseMapperX<SysRoleMenuDO> {
         delete(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId)
                 .in("menu_id", menuIds));
     }
+    
+    default void deleteListByMenuId(Long menuId) {
+        delete(new QueryWrapper<SysRoleMenuDO>().eq("menu_id", menuId));
+    }
+
+    default void deleteListByRoleId(Long roleId) {
+        delete(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId));
+    }
 
     @Select("SELECT id FROM sys_role_menu WHERE update_time > #{maxUpdateTime} LIMIT 1")
     Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);

+ 10 - 2
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java

@@ -1,8 +1,8 @@
 package cn.iocoder.dashboard.modules.system.dal.mysql.permission;
 
+import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysUserRoleDO;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.Collection;
@@ -10,7 +10,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Mapper
-public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
+public interface SysUserRoleMapper extends BaseMapperX<SysUserRoleDO> {
 
     default List<SysUserRoleDO> selectListByUserId(Long userId) {
         return selectList(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
@@ -32,4 +32,12 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
                 .in("role_id", roleIds));
     }
 
+    default void deleteListByUserId(Long userId) {
+        delete(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
+    }
+
+    default void deleteListByRoleId(Long roleId) {
+        delete(new QueryWrapper<SysUserRoleDO>().eq("role_id", roleId));
+    }
+
 }

+ 3 - 0
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java

@@ -40,6 +40,7 @@ public interface SysErrorCodeConstants {
     ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1002004002, "邮箱已经存在");
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1002004003, "用户不存在");
     ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002004004, "导入用户数据不能为空!");
+    ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002004005, "用户密码校验失败");
 
     // ========== 部门模块 1002005000 ==========
     ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004001, "已经存在该名字的部门");
@@ -74,5 +75,7 @@ public interface SysErrorCodeConstants {
 
     // ========== 文件 1002009000 ==========
     ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在");
+    ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败");
+    ErrorCode FILE_IS_EMPTY= new ErrorCode(1002009003, "文件为空");
 
 }

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -61,7 +61,7 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         // 获取 username 对应的 SysUserDO
-        SysUserDO user = userService.getUserByUserName(username);
+        SysUserDO user = userService.getUserByUsername(username);
         if (user == null) {
             throw new UsernameNotFoundException(username);
         }

+ 1 - 1
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java

@@ -101,7 +101,7 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
         // 处理基于用户昵称的查询
         Collection<Long> userIds = null;
         if (StrUtil.isNotEmpty(reqVO.getUsername())) {
-            userIds = convertSet(userService.listUsersByUsername(reqVO.getUsername()), SysUserDO::getId);
+            userIds = convertSet(userService.getUsersByUsername(reqVO.getUsername()), SysUserDO::getId);
             if (CollUtil.isEmpty(userIds)) {
                 return PageResult.empty();
             }

+ 0 - 29
src/main/java/cn/iocoder/dashboard/modules/system/service/common/SysFileService.java

@@ -1,29 +0,0 @@
-package cn.iocoder.dashboard.modules.system.service.common;
-
-import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
-
-/**
- * 文件 Service 接口
- *
- * @author 芋道源码
- */
-public interface SysFileService {
-
-    /**
-     * 保存文件,并返回文件的访问路径
-     *
-     * @param path 文件路径
-     * @param content 文件内容
-     * @return 文件路径
-     */
-    String createFile(String path, byte[] content);
-
-    /**
-     * 获得文件
-     *
-     * @param path 文件路径
-     * @return 文件
-     */
-    SysFileDO getFile(String path);
-
-}

+ 0 - 47
src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysFileServiceImpl.java

@@ -1,47 +0,0 @@
-package cn.iocoder.dashboard.modules.system.service.common.impl;
-
-import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
-import cn.iocoder.dashboard.framework.file.config.FileProperties;
-import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
-import cn.iocoder.dashboard.modules.system.dal.mysql.common.SysFileMapper;
-import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-
-import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
-
-/**
- * 文件 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-public class SysFileServiceImpl implements SysFileService {
-
-    @Resource
-    private SysFileMapper fileMapper;
-
-    @Resource
-    private FileProperties fileProperties;
-
-    @Override
-    public String createFile(String path, byte[] content) {
-        if (fileMapper.selectCountById(path) > 0) {
-            throw ServiceExceptionUtil.exception(FILE_PATH_EXISTS);
-        }
-        // 保存到数据库
-        SysFileDO file = new SysFileDO();
-        file.setId(path);
-        file.setContent(content);
-        fileMapper.insert(file);
-        // 拼接路径返回
-        return fileProperties.getBasePath() + path;
-    }
-
-    @Override
-    public SysFileDO getFile(String path) {
-        return fileMapper.selectById(path);
-    }
-
-}

+ 30 - 30
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java

@@ -24,13 +24,35 @@ public interface SysDeptService {
      */
     void initLocalCache();
 
+    /**
+     * 创建部门
+     *
+     * @param reqVO 部门信息
+     * @return 部门编号
+     */
+    Long createDept(SysDeptCreateReqVO reqVO);
+
+    /**
+     * 更新部门
+     *
+     * @param reqVO 部门信息
+     */
+    void updateDept(SysDeptUpdateReqVO reqVO);
+
+    /**
+     * 删除部门
+     *
+     * @param id 部门编号
+     */
+    void deleteDept(Long id);
+
     /**
      * 获得指定编号的部门列表
      *
      * @param ids 部门编号数组
      * @return 部门列表
      */
-    List<SysDeptDO> listDepts(Collection<Long> ids);
+    List<SysDeptDO> getSimpleDepts(Collection<Long> ids);
 
     /**
      * 获得指定编号的部门 Map
@@ -42,7 +64,7 @@ public interface SysDeptService {
         if (CollUtil.isEmpty(ids)) {
             return Collections.emptyMap();
         }
-        List<SysDeptDO> list = listDepts(ids);
+        List<SysDeptDO> list = getSimpleDepts(ids);
         return CollectionUtils.convertMap(list, SysDeptDO::getId);
     }
 
@@ -52,16 +74,7 @@ public interface SysDeptService {
      * @param reqVO 筛选条件请求 VO
      * @return 部门列表
      */
-    List<SysDeptDO> listDepts(SysDeptListReqVO reqVO);
-
-    /**
-     * 获得所有子部门,从缓存中
-     *
-     * @param parentId 部门编号
-     * @param recursive 是否递归获取所有
-     * @return 子部门列表
-     */
-    List<SysDeptDO> listDeptsByParentIdFromCache(Long parentId, boolean recursive);
+    List<SysDeptDO> getSimpleDepts(SysDeptListReqVO reqVO);
 
     /**
      * 获得部门信息
@@ -72,25 +85,12 @@ public interface SysDeptService {
     SysDeptDO getDept(Long id);
 
     /**
-     * 创建部门
-     *
-     * @param reqVO 部门信息
-     * @return 部门编号
-     */
-    Long createDept(SysDeptCreateReqVO reqVO);
-
-    /**
-     * 更新部门
-     *
-     * @param reqVO 部门信息
-     */
-    void updateDept(SysDeptUpdateReqVO reqVO);
-
-    /**
-     * 删除部门
+     * 获得所有子部门,从缓存中
      *
-     * @param id 部门编号
+     * @param parentId 部门编号
+     * @param recursive 是否递归获取所有
+     * @return 子部门列表
      */
-    void deleteDept(Long id);
+    List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive);
 
 }

+ 25 - 25
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java

@@ -18,6 +18,28 @@ import java.util.List;
  */
 public interface SysPostService {
 
+    /**
+     * 创建岗位
+     *
+     * @param reqVO 岗位信息
+     * @return 岗位编号
+     */
+    Long createPost(SysPostCreateReqVO reqVO);
+
+    /**
+     * 更新岗位
+     *
+     * @param reqVO 岗位信息
+     */
+    void updatePost(SysPostUpdateReqVO reqVO);
+
+    /**
+     * 删除岗位信息
+     *
+     * @param id 岗位编号
+     */
+    void deletePost(Long id);
+
     /**
      * 获得符合条件的岗位列表
      *
@@ -25,7 +47,7 @@ public interface SysPostService {
      * @param statuses 状态数组。如果为空,不进行筛选
      * @return 部门列表
      */
-    List<SysPostDO> listPosts(@Nullable Collection<Long> ids, @Nullable Collection<Integer> statuses);
+    List<SysPostDO> getPosts(@Nullable Collection<Long> ids, @Nullable Collection<Integer> statuses);
 
     /**
      * 获得岗位分页列表
@@ -33,7 +55,7 @@ public interface SysPostService {
      * @param reqVO 分页条件
      * @return 部门分页列表
      */
-    PageResult<SysPostDO> pagePosts(SysPostPageReqVO reqVO);
+    PageResult<SysPostDO> getPostPage(SysPostPageReqVO reqVO);
 
     /**
      * 获得岗位列表
@@ -41,7 +63,7 @@ public interface SysPostService {
      * @param reqVO 查询条件
      * @return 部门列表
      */
-    List<SysPostDO> listPosts(SysPostExportReqVO reqVO);
+    List<SysPostDO> getPosts(SysPostExportReqVO reqVO);
 
     /**
      * 获得岗位信息
@@ -51,26 +73,4 @@ public interface SysPostService {
      */
     SysPostDO getPost(Long id);
 
-    /**
-     * 创建岗位
-     *
-     * @param reqVO 岗位信息
-     * @return 岗位编号
-     */
-    Long createPost(SysPostCreateReqVO reqVO);
-
-    /**
-     * 更新岗位
-     *
-     * @param reqVO 岗位信息
-     */
-    void updatePost(SysPostUpdateReqVO reqVO);
-
-    /**
-     * 删除岗位信息
-     *
-     * @param id 岗位编号
-     */
-    void deletePost(Long id);
-
 }

+ 44 - 48
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java

@@ -19,6 +19,7 @@ import com.google.common.collect.Multimap;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
@@ -32,6 +33,7 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
  * @author 芋道源码
  */
 @Service
+@Validated
 @Slf4j
 public class SysDeptServiceImpl implements SysDeptService {
 
@@ -47,6 +49,7 @@ public class SysDeptServiceImpl implements SysDeptService {
      *
      * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
      */
+    @SuppressWarnings("FieldCanBeLocal")
     private volatile Map<Long, SysDeptDO> deptCache;
     /**
      * 父部门缓存
@@ -118,17 +121,54 @@ public class SysDeptServiceImpl implements SysDeptService {
     }
 
     @Override
-    public List<SysDeptDO> listDepts(Collection<Long> ids) {
+    public Long createDept(SysDeptCreateReqVO reqVO) {
+        // 校验正确性
+        checkCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName());
+        // 插入部门
+        SysDeptDO dept = SysDeptConvert.INSTANCE.convert(reqVO);
+        deptMapper.insert(dept);
+        // 发送刷新消息
+        deptProducer.sendDeptRefreshMessage();
+        return dept.getId();
+    }
+
+    @Override
+    public void updateDept(SysDeptUpdateReqVO reqVO) {
+        // 校验正确性
+        checkCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName());
+        // 更新部门
+        SysDeptDO updateObj = SysDeptConvert.INSTANCE.convert(reqVO);
+        deptMapper.updateById(updateObj);
+        // 发送刷新消息
+        deptProducer.sendDeptRefreshMessage();
+    }
+
+    @Override
+    public void deleteDept(Long id) {
+        // 校验是否存在
+        checkDeptExists(id);
+        // 校验是否有子部门
+        if (deptMapper.selectCountByParentId(id) > 0) {
+            throw ServiceExceptionUtil.exception(DEPT_EXITS_CHILDREN);
+        }
+        // 删除部门
+        deptMapper.deleteById(id);
+        // 发送刷新消息
+        deptProducer.sendDeptRefreshMessage();
+    }
+
+    @Override
+    public List<SysDeptDO> getSimpleDepts(Collection<Long> ids) {
         return deptMapper.selectBatchIds(ids);
     }
 
     @Override
-    public List<SysDeptDO> listDepts(SysDeptListReqVO reqVO) {
+    public List<SysDeptDO> getSimpleDepts(SysDeptListReqVO reqVO) {
         return deptMapper.selectList(reqVO);
     }
 
     @Override
-    public List<SysDeptDO> listDeptsByParentIdFromCache(Long parentId, boolean recursive) {
+    public List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive) {
         List<SysDeptDO> result = new ArrayList<>();
         // 递归,简单粗暴
         this.listDeptsByParentIdFromCache(result, parentId,
@@ -167,44 +207,6 @@ public class SysDeptServiceImpl implements SysDeptService {
         return deptMapper.selectById(id);
     }
 
-    @Override
-    public Long createDept(SysDeptCreateReqVO reqVO) {
-        // 校验正确性
-        checkCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName());
-        // 插入部门
-        SysDeptDO dept = SysDeptConvert.INSTANCE.convert(reqVO);
-        deptMapper.insert(dept);
-        // 发送刷新消息
-        deptProducer.sendDeptRefreshMessage();
-        return dept.getId();
-    }
-
-    @Override
-    public void updateDept(SysDeptUpdateReqVO reqVO) {
-        // 校验正确性
-        checkCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName());
-        // 更新部门
-        SysDeptDO updateObj = SysDeptConvert.INSTANCE.convert(reqVO);
-        deptMapper.updateById(updateObj);
-        // 发送刷新消息
-        deptProducer.sendDeptRefreshMessage();
-    }
-
-    @Override
-    public void deleteDept(Long id) {
-        // 校验是否存在
-        checkDeptExists(id);
-        // 校验是否有子部门
-        if (deptMapper.selectCountByParentId(id) > 0) {
-            throw ServiceExceptionUtil.exception(DEPT_EXITS_CHILDREN);
-        }
-        // 删除部门
-        deptMapper.deleteById(id);
-        // TODO 需要处理下与角色的数据权限关联,等做数据权限一起处理下
-        // 发送刷新消息
-        deptProducer.sendDeptRefreshMessage();
-    }
-
     private void checkCreateOrUpdate(Long id, Long parentId, String name) {
         // 校验自己存在
         checkDeptExists(id);
@@ -232,7 +234,7 @@ public class SysDeptServiceImpl implements SysDeptService {
             throw ServiceExceptionUtil.exception(DEPT_NOT_ENABLE);
         }
         // 父部门不能是原来的子部门
-        List<SysDeptDO> children = this.listDeptsByParentIdFromCache(id, true);
+        List<SysDeptDO> children = this.getDeptsByParentIdFromCache(id, true);
         if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) {
             throw ServiceExceptionUtil.exception(DEPT_PARENT_IS_CHILD);
         }
@@ -262,12 +264,6 @@ public class SysDeptServiceImpl implements SysDeptService {
         }
     }
 
-//    /**
-//     * 查询部门管理数据
-//     *
-//     * @param dept 部门信息
-//     * @return 部门信息集合
-//     */
 //    @Override
 //    @DataScope(deptAlias = "d")
 //    public List<SysDept> selectDeptList(SysDept dept)

+ 30 - 28
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysPostServiceImpl.java

@@ -11,6 +11,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dept.SysPostMapper;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO;
 import cn.iocoder.dashboard.modules.system.service.dept.SysPostService;
 import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.util.Collection;
@@ -24,31 +25,12 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
  * @author 芋道源码
  */
 @Service
+@Validated
 public class SysPostServiceImpl implements SysPostService {
 
     @Resource
     private SysPostMapper postMapper;
 
-    @Override
-    public List<SysPostDO> listPosts(Collection<Long> ids, Collection<Integer> statuses) {
-        return postMapper.selectList(ids, statuses);
-    }
-
-    @Override
-    public PageResult<SysPostDO> pagePosts(SysPostPageReqVO reqVO) {
-        return postMapper.selectPage(reqVO);
-    }
-
-    @Override
-    public List<SysPostDO> listPosts(SysPostExportReqVO reqVO) {
-        return postMapper.selectList(reqVO);
-    }
-
-    @Override
-    public SysPostDO getPost(Long id) {
-        return postMapper.selectById(id);
-    }
-
     @Override
     public Long createPost(SysPostCreateReqVO reqVO) {
         // 校验正确性
@@ -68,6 +50,34 @@ public class SysPostServiceImpl implements SysPostService {
         postMapper.updateById(updateObj);
     }
 
+    @Override
+    public void deletePost(Long id) {
+        // 校验是否存在
+        this.checkPostExists(id);
+        // 删除部门
+        postMapper.deleteById(id);
+    }
+
+    @Override
+    public List<SysPostDO> getPosts(Collection<Long> ids, Collection<Integer> statuses) {
+        return postMapper.selectList(ids, statuses);
+    }
+
+    @Override
+    public PageResult<SysPostDO> getPostPage(SysPostPageReqVO reqVO) {
+        return postMapper.selectPage(reqVO);
+    }
+
+    @Override
+    public List<SysPostDO> getPosts(SysPostExportReqVO reqVO) {
+        return postMapper.selectList(reqVO);
+    }
+
+    @Override
+    public SysPostDO getPost(Long id) {
+        return postMapper.selectById(id);
+    }
+
     private void checkCreateOrUpdate(Long id, String name, String code) {
         // 校验自己存在
         checkPostExists(id);
@@ -105,14 +115,6 @@ public class SysPostServiceImpl implements SysPostService {
         }
     }
 
-    @Override
-    public void deletePost(Long id) {
-        // 校验是否存在
-        this.checkPostExists(id);
-        // 删除部门
-        postMapper.deleteById(id);
-    }
-
     private void checkPostExists(Long id) {
         if (id == null) {
             return;

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

@@ -23,57 +23,57 @@ public interface SysDictDataService extends DictDataFrameworkService {
     void initLocalCache();
 
     /**
-     * 获得字典数据列表
+     * 创建字典数据
      *
-     * @return 字典数据全列表
+     * @param reqVO 字典数据信息
+     * @return 字典数据编号
      */
-    List<SysDictDataDO> getDictDataList();
+    Long createDictData(SysDictDataCreateReqVO reqVO);
 
     /**
-     * 获得字典数据分页列表
+     * 更新字典数据
      *
-     * @param reqVO 分页请求
-     * @return 字典数据分页列表
+     * @param reqVO 字典数据信息
      */
-    PageResult<SysDictDataDO> getDictDataPage(SysDictDataPageReqVO reqVO);
+    void updateDictData(SysDictDataUpdateReqVO reqVO);
 
     /**
-     * 获得字典数据列表
+     * 删除字典数据
      *
-     * @param reqVO 列表请求
-     * @return 字典数据列表
+     * @param id 字典数据编号
      */
-    List<SysDictDataDO> getDictDataList(SysDictDataExportReqVO reqVO);
+    void deleteDictData(Long id);
 
     /**
-     * 获得字典数据详情
+     * 获得字典数据列表
      *
-     * @param id 字典数据编号
-     * @return 字典数据
+     * @return 字典数据全列表
      */
-    SysDictDataDO getDictData(Long id);
+    List<SysDictDataDO> getDictDatas();
 
     /**
-     * 创建字典数据
+     * 获得字典数据分页列表
      *
-     * @param reqVO 字典数据信息
-     * @return 字典数据编号
+     * @param reqVO 分页请求
+     * @return 字典数据分页列表
      */
-    Long createDictData(SysDictDataCreateReqVO reqVO);
+    PageResult<SysDictDataDO> getDictDataPage(SysDictDataPageReqVO reqVO);
 
     /**
-     * 更新字典数据
+     * 获得字典数据列表
      *
-     * @param reqVO 字典数据信息
+     * @param reqVO 列表请求
+     * @return 字典数据列表
      */
-    void updateDictData(SysDictDataUpdateReqVO reqVO);
+    List<SysDictDataDO> getDictDatas(SysDictDataExportReqVO reqVO);
 
     /**
-     * 删除字典数据
+     * 获得字典数据详情
      *
      * @param id 字典数据编号
+     * @return 字典数据
      */
-    void deleteDictData(Long id);
+    SysDictDataDO getDictData(Long id);
 
     /**
      * 获得指定字典类型的数据数量

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

@@ -16,6 +16,28 @@ import java.util.List;
  */
 public interface SysDictTypeService {
 
+    /**
+     * 创建字典类型
+     *
+     * @param reqVO 字典类型信息
+     * @return 字典类型编号
+     */
+    Long createDictType(SysDictTypeCreateReqVO reqVO);
+
+    /**
+     * 更新字典类型
+     *
+     * @param reqVO 字典类型信息
+     */
+    void updateDictType(SysDictTypeUpdateReqVO reqVO);
+
+    /**
+     * 删除字典类型
+     *
+     * @param id 字典类型编号
+     */
+    void deleteDictType(Long id);
+
     /**
      * 获得字典类型分页列表
      *
@@ -48,28 +70,6 @@ public interface SysDictTypeService {
      */
     SysDictTypeDO getDictType(String type);
 
-    /**
-     * 创建字典类型
-     *
-     * @param reqVO 字典类型信息
-     * @return 字典类型编号
-     */
-    Long createDictType(SysDictTypeCreateReqVO reqVO);
-
-    /**
-     * 更新字典类型
-     *
-     * @param reqVO 字典类型信息
-     */
-    void updateDictType(SysDictTypeUpdateReqVO reqVO);
-
-    /**
-     * 删除字典类型
-     *
-     * @param id 字典类型编号
-     */
-    void deleteDictType(Long id);
-
     /**
      * 获得全部字典类型列表
      *

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

@@ -131,7 +131,7 @@ public class SysDictDataServiceImpl implements SysDictDataService {
     }
 
     @Override
-    public List<SysDictDataDO> getDictDataList() {
+    public List<SysDictDataDO> getDictDatas() {
         List<SysDictDataDO> list = dictDataMapper.selectList();
         list.sort(COMPARATOR_TYPE_AND_SORT);
         return list;
@@ -143,7 +143,7 @@ public class SysDictDataServiceImpl implements SysDictDataService {
     }
 
     @Override
-    public List<SysDictDataDO> getDictDataList(SysDictDataExportReqVO reqVO) {
+    public List<SysDictDataDO> getDictDatas(SysDictDataExportReqVO reqVO) {
         List<SysDictDataDO> list = dictDataMapper.selectList(reqVO);
         list.sort(COMPARATOR_TYPE_AND_SORT);
         return list;

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java

@@ -59,7 +59,7 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
         // 处理基于用户昵称的查询
         Collection<Long> userIds = null;
         if (StrUtil.isNotEmpty(reqVO.getUserNickname())) {
-            userIds = convertSet(userService.listUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
+            userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
             if (CollUtil.isEmpty(userIds)) {
                 return PageResult.empty();
             }
@@ -73,7 +73,7 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
         // 处理基于用户昵称的查询
         Collection<Long> userIds = null;
         if (StrUtil.isNotEmpty(reqVO.getUserNickname())) {
-            userIds = convertSet(userService.listUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
+            userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
             if (CollUtil.isEmpty(userIds)) {
                 return Collections.emptyList();
             }

+ 17 - 16
src/main/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeService.java

@@ -11,22 +11,6 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.notice.SysNoticeDO;
  */
 public interface SysNoticeService {
 
-    /**
-     * 获得岗位公告公告分页列表
-     *
-     * @param reqVO 分页条件
-     * @return 部门分页列表
-     */
-    PageResult<SysNoticeDO> pageNotices(SysNoticePageReqVO reqVO);
-
-    /**
-     * 获得岗位公告公告信息
-     *
-     * @param id 岗位公告公告编号
-     * @return 岗位公告公告信息
-     */
-    SysNoticeDO getNotice(Long id);
-
     /**
      * 创建岗位公告公告
      *
@@ -48,4 +32,21 @@ public interface SysNoticeService {
      * @param id 岗位公告公告编号
      */
     void deleteNotice(Long id);
+
+    /**
+     * 获得岗位公告公告分页列表
+     *
+     * @param reqVO 分页条件
+     * @return 部门分页列表
+     */
+    PageResult<SysNoticeDO> pageNotices(SysNoticePageReqVO reqVO);
+
+    /**
+     * 获得岗位公告公告信息
+     *
+     * @param id 岗位公告公告编号
+     * @return 岗位公告公告信息
+     */
+    SysNoticeDO getNotice(Long id);
+
 }

+ 10 - 10
src/main/java/cn/iocoder/dashboard/modules/system/service/notice/impl/SysNoticeServiceImpl.java

@@ -27,16 +27,6 @@ public class SysNoticeServiceImpl implements SysNoticeService {
     @Resource
     private SysNoticeMapper noticeMapper;
 
-    @Override
-    public PageResult<SysNoticeDO> pageNotices(SysNoticePageReqVO reqVO) {
-        return noticeMapper.selectPage(reqVO);
-    }
-
-    @Override
-    public SysNoticeDO getNotice(Long id) {
-        return noticeMapper.selectById(id);
-    }
-
     @Override
     public Long createNotice(SysNoticeCreateReqVO reqVO) {
         SysNoticeDO notice = SysNoticeConvert.INSTANCE.convert(reqVO);
@@ -61,6 +51,16 @@ public class SysNoticeServiceImpl implements SysNoticeService {
         noticeMapper.deleteById(id);
     }
 
+    @Override
+    public PageResult<SysNoticeDO> pageNotices(SysNoticePageReqVO reqVO) {
+        return noticeMapper.selectPage(reqVO);
+    }
+
+    @Override
+    public SysNoticeDO getNotice(Long id) {
+        return noticeMapper.selectById(id);
+    }
+
     @VisibleForTesting
     public void checkNoticeExists(Long id) {
         if (id == null) {

+ 24 - 24
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java

@@ -20,12 +20,34 @@ public interface SysMenuService {
      */
     void initLocalCache();
 
+    /**
+     * 创建菜单
+     *
+     * @param reqVO 菜单信息
+     * @return 创建出来的菜单编号
+     */
+    Long createMenu(SysMenuCreateReqVO reqVO);
+
+    /**
+     * 更新菜单
+     *
+     * @param reqVO 菜单信息
+     */
+    void updateMenu(SysMenuUpdateReqVO reqVO);
+
+    /**
+     * 删除菜单
+     *
+     * @param id 菜单编号
+     */
+    void deleteMenu(Long id);
+
     /**
      * 获得所有菜单列表
      *
      * @return 菜单列表
      */
-    List<SysMenuDO> listMenus();
+    List<SysMenuDO> getMenus();
 
     /**
      * 筛选菜单列表
@@ -33,7 +55,7 @@ public interface SysMenuService {
      * @param reqVO 筛选条件请求 VO
      * @return 菜单列表
      */
-    List<SysMenuDO> listMenus(SysMenuListReqVO reqVO);
+    List<SysMenuDO> getMenus(SysMenuListReqVO reqVO);
 
     /**
      * 获得所有菜单,从缓存中
@@ -67,28 +89,6 @@ public interface SysMenuService {
      */
     List<SysMenuDO> getMenuListByPermissionFromCache(String permission);
 
-    /*
-     * 创建菜单
-     *
-     * @param reqVO 菜单信息
-     * @return 创建出来的菜单编号
-     */
-    Long createMenu(SysMenuCreateReqVO reqVO);
-
-    /**
-     * 更新菜单
-     *
-     * @param reqVO 菜单信息
-     */
-    void updateMenu(SysMenuUpdateReqVO reqVO);
-
-    /**
-     * 删除菜单
-     *
-     * @param id 菜单编号
-     */
-    void deleteMenu(Long id);
-
     /**
      * 获得菜单
      *

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java

@@ -32,8 +32,8 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService
      * @param menusStatuses 菜单状态数组
      * @return 菜单列表
      */
-    List<SysMenuDO> listRoleMenusFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes,
-                                           Collection<Integer> menusStatuses);
+    List<SysMenuDO> getRoleMenusFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes,
+                                          Collection<Integer> menusStatuses);
 
     /**
      * 获得用户拥有的角色编号集合

+ 44 - 44
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleService.java

@@ -24,6 +24,45 @@ public interface SysRoleService {
      */
     void initLocalCache();
 
+    /**
+     * 创建角色
+     *
+     * @param reqVO 创建角色信息
+     * @return 角色编号
+     */
+    Long createRole(SysRoleCreateReqVO reqVO);
+
+    /**
+     * 更新角色
+     *
+     * @param reqVO 更新角色信息
+     */
+    void updateRole(SysRoleUpdateReqVO reqVO);
+
+    /**
+     * 删除角色
+     *
+     * @param id 角色编号
+     */
+    void deleteRole(Long id);
+
+    /**
+     * 更新角色状态
+     *
+     * @param id 角色编号
+     * @param status 状态
+     */
+    void updateRoleStatus(Long id, Integer status);
+
+    /**
+     * 设置角色的数据权限
+     *
+     * @param id 角色编号
+     * @param dataScope 数据范围
+     * @param dataScopeDeptIds 部门编号数组
+     */
+    void updateRoleDataScope(Long id, Integer dataScope, Set<Long> dataScopeDeptIds);
+
     /**
      * 获得角色,从缓存中
      *
@@ -38,7 +77,7 @@ public interface SysRoleService {
      * @param statuses 筛选的状态。允许空,空时不筛选
      * @return 角色列表
      */
-    List<SysRoleDO> listRoles(@Nullable Collection<Integer> statuses);
+    List<SysRoleDO> getRoles(@Nullable Collection<Integer> statuses);
 
     /**
      * 获得角色数组,从缓存中
@@ -46,7 +85,7 @@ public interface SysRoleService {
      * @param ids 角色编号数组
      * @return 角色数组
      */
-    List<SysRoleDO> listRolesFromCache(Collection<Long> ids);
+    List<SysRoleDO> getRolesFromCache(Collection<Long> ids);
 
     /**
      * 判断角色数组中,是否有管理员
@@ -63,31 +102,9 @@ public interface SysRoleService {
      * @return 是否有管理员
      */
     default boolean hasAnyAdmin(Set<Long> ids) {
-        return hasAnyAdmin(listRolesFromCache(ids));
+        return hasAnyAdmin(getRolesFromCache(ids));
     }
 
-    /**
-     * 创建角色
-     *
-     * @param reqVO 创建角色信息
-     * @return 角色编号
-     */
-    Long createRole(SysRoleCreateReqVO reqVO);
-
-    /**
-     * 更新角色
-     *
-     * @param reqVO 更新角色信息
-     */
-    void updateRole(SysRoleUpdateReqVO reqVO);
-
-    /**
-     * 删除角色
-     *
-     * @param id 角色编号
-     */
-    void deleteRole(Long id);
-
     /**
      * 获得角色
      *
@@ -102,7 +119,7 @@ public interface SysRoleService {
      * @param reqVO 角色分页查询
      * @return 角色分页结果
      */
-    PageResult<SysRoleDO> pageRole(SysRolePageReqVO reqVO);
+    PageResult<SysRoleDO> getRolePage(SysRolePageReqVO reqVO);
 
     /**
      * 获得角色列表
@@ -110,23 +127,6 @@ public interface SysRoleService {
      * @param reqVO 列表查询
      * @return 角色列表
      */
-    List<SysRoleDO> listRoles(SysRoleExportReqVO reqVO);
-
-    /**
-     * 更新角色状态
-     *
-     * @param id 角色编号
-     * @param status 状态
-     */
-    void updateRoleStatus(Long id, Integer status);
-
-    /**
-     * 设置角色的数据权限
-     *
-     * @param id 角色编号
-     * @param dataScope 数据范围
-     * @param dataScopeDeptIds 部门编号数组
-     */
-    void updateRoleDataScope(Long id, Integer dataScope, Set<Long> dataScopeDeptIds);
+    List<SysRoleDO> getRoles(SysRoleExportReqVO reqVO);
 
 }

Some files were not shown because too many files changed in this diff