瀏覽代碼

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

YunaiV 4 年之前
父節點
當前提交
162d604644
共有 100 個文件被更改,包括 2491 次插入2244 次删除
  1. 5 25
      pom.xml
  2. 2 2
      ruoyi-ui/src/api/system/dept.js
  3. 2 2
      ruoyi-ui/src/api/system/dict/data.js
  4. 2 2
      ruoyi-ui/src/api/system/dict/type.js
  5. 2 2
      ruoyi-ui/src/api/system/menu.js
  6. 2 2
      ruoyi-ui/src/api/system/notice.js
  7. 2 2
      ruoyi-ui/src/api/system/post.js
  8. 3 3
      ruoyi-ui/src/api/system/role.js
  9. 8 8
      ruoyi-ui/src/api/system/user.js
  10. 1 1
      ruoyi-ui/src/store/modules/user.js
  11. 13 54
      ruoyi-ui/src/views/system/dept/index.vue
  12. 14 59
      ruoyi-ui/src/views/system/dict/data.vue
  13. 17 79
      ruoyi-ui/src/views/system/dict/index.vue
  14. 14 58
      ruoyi-ui/src/views/system/loginlog/index.vue
  15. 19 71
      ruoyi-ui/src/views/system/menu/index.vue
  16. 13 68
      ruoyi-ui/src/views/system/notice/index.vue
  17. 14 63
      ruoyi-ui/src/views/system/operatelog/index.vue
  18. 15 60
      ruoyi-ui/src/views/system/post/index.vue
  19. 23 94
      ruoyi-ui/src/views/system/role/index.vue
  20. 43 135
      ruoyi-ui/src/views/system/user/index.vue
  21. 9 7
      ruoyi-ui/src/views/system/user/profile/index.vue
  22. 8 8
      ruoyi-ui/src/views/system/user/profile/userInfo.vue
  23. 8 0
      sql/quartz.sql
  24. 46 339
      sql/ruoyi-vue-pro.sql
  25. 18 1
      src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java
  26. 26 0
      src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java
  27. 24 0
      src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java
  28. 1 1
      src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java
  29. 68 0
      src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java
  30. 5 16
      src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java
  31. 3 1
      src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java
  32. 88 0
      src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java
  33. 20 0
      src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java
  34. 17 1
      src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java
  35. 1 1
      src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java
  36. 1 1
      src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java
  37. 9 7
      src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java
  38. 4 4
      src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysUserSessionController.java
  39. 36 35
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysDeptController.java
  40. 37 36
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java
  41. 43 41
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java
  42. 32 31
      src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java
  43. 15 10
      src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java
  44. 11 27
      src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java
  45. 26 26
      src/main/java/cn/iocoder/dashboard/modules/system/controller/notice/SysNoticeController.java
  46. 37 49
      src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.java
  47. 43 43
      src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java
  48. 57 64
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java
  49. 49 27
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java
  50. 88 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java
  51. 24 0
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVO.java
  52. 4 17
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java
  53. 3 3
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserBaseVO.java
  54. 0 2
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java
  55. 0 37
      src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java
  56. 4 1
      src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java
  57. 12 8
      src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java
  58. 10 3
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java
  59. 10 2
      src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java
  60. 17 0
      src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java
  61. 17 0
      src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java
  62. 46 0
      src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java
  63. 46 0
      src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java
  64. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
  65. 1 1
      src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java
  66. 30 30
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java
  67. 37 24
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostService.java
  68. 44 48
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java
  69. 30 28
      src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysPostServiceImpl.java
  70. 24 24
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataService.java
  71. 22 22
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictTypeService.java
  72. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
  73. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java
  74. 4 4
      src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java
  75. 17 16
      src/main/java/cn/iocoder/dashboard/modules/system/service/notice/SysNoticeService.java
  76. 10 10
      src/main/java/cn/iocoder/dashboard/modules/system/service/notice/impl/SysNoticeServiceImpl.java
  77. 24 24
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java
  78. 2 2
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java
  79. 44 44
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleService.java
  80. 45 46
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java
  81. 34 14
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java
  82. 55 61
      src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java
  83. 71 97
      src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java
  84. 87 94
      src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java
  85. 23 0
      src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java
  86. 2 1
      src/test-integration/java/cn/iocoder/dashboard/framework/quartz/core/SchedulerManagerTest.java
  87. 63 0
      src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java
  88. 0 0
      src/test-integration/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java
  89. 0 0
      src/test-integration/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java
  90. 2 1
      src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenEngineTest.java
  91. 2 1
      src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenSQLParserTest.java
  92. 2 1
      src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenServiceImplTest.java
  93. 82 0
      src/test-integration/resources/application-integration-test.yaml
  94. 2 0
      src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java
  95. 2 0
      src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java
  96. 1 1
      src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java
  97. 173 0
      src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java
  98. 309 0
      src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java
  99. 3 4
      src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java
  100. 2 2
      src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java

+ 5 - 25
pom.xml

@@ -22,15 +22,15 @@
         <maven.compiler.target>${java.version}</maven.compiler.target>
         <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
         <!-- 统一依赖管理 -->
-        <spring.boot.version>2.4.2</spring.boot.version>
+        <spring.boot.version>2.4.4</spring.boot.version>
         <!-- Web 相关 -->
         <knife4j.version>3.0.2</knife4j.version>
         <swagger-annotations.version>1.5.22</swagger-annotations.version>
         <!-- DB 相关 -->
         <mysql-connector-java.version>5.1.46</mysql-connector-java.version>
         <druid.version>1.2.4</druid.version>
-        <mybatis-plus.version>3.4.1</mybatis-plus.version>
-        <redisson.version>3.14.1</redisson.version>
+        <mybatis-plus.version>3.4.2</mybatis-plus.version>
+        <redisson.version>3.15.1</redisson.version>
         <!-- Config 配置中心相关 -->
         <apollo.version>1.7.0</apollo.version>
         <!-- 服务保障相关 -->
@@ -42,7 +42,7 @@
         <!-- 工具类相关 -->
         <lombok.version>1.16.14</lombok.version>
         <mapstruct.version>1.4.1.Final</mapstruct.version>
-        <hutool.version>5.5.6</hutool.version>
+        <hutool.version>5.6.1</hutool.version>
         <easyexcel.verion>2.2.7</easyexcel.verion>
         <velocity.version>2.2</velocity.version>
         <screw.version>1.0.5</screw.version>
@@ -249,27 +249,7 @@
 
         <dependency>
             <groupId>cn.hutool</groupId>
-            <artifactId>hutool-core</artifactId>
-            <version>${hutool.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-extra</artifactId>
-            <version>${hutool.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-captcha</artifactId>
-            <version>${hutool.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-http</artifactId>
-            <version>${hutool.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-crypto</artifactId>
+            <artifactId>hutool-all</artifactId>
             <version>${hutool.version}</version>
         </dependency>
 

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

+ 8 - 8
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
   })
@@ -104,9 +104,9 @@ export function updateUserPwd(oldPassword, newPassword) {
     newPassword
   }
   return request({
-    url: '/system/user/profile/updatePwd',
+    url: '/system/user/profile/update-password',
     method: 'put',
-    params: data
+    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
   })
 }

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

@@ -53,7 +53,7 @@ const user = {
         getInfo(state.token).then(res => {
           res = res.data; // 读取 data 数据
           const user = res.user
-          const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
+          const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : user.avatar;
           if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
             commit('SET_ROLES', res.roles)
             commit('SET_PERMISSIONS', res.permissions)

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

+ 43 - 135
ruoyi-ui/src/views/system/user/index.vue

@@ -4,77 +4,32 @@
       <!--部门数据-->
       <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"
-          />
+          <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"
-          />
+          <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-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-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 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>
@@ -84,31 +39,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:user:add']"
-            >新增</el-button>
+            <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-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-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>
@@ -121,12 +61,7 @@
           <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>
+              <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">
@@ -134,60 +69,29 @@
               <span>{{ parseTime(scope.row.createTime) }}</span>
             </template>
           </el-table-column>
-          <el-table-column
-            label="操作"
-            align="center"
-            width="160"
-            class-name="small-padding fixed-width"
-          >
+          <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:edit']"
-              >修改</el-button>
+              <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:remove']"
-                  >删除</el-dropdown-item>
-                  <el-dropdown-item
-                    command="handleResetPwd"
-                    size="mini"
-                    type="text"
-                    icon="el-icon-key"
-                    v-hasPermi="['system:user:resetPwd']"
-                  >重置</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-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"
-        />
+        <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                    @pagination="getList"/>
       </el-col>
     </el-row>
 
@@ -203,8 +107,7 @@
           <el-col :span="12">
             <el-form-item label="归属部门" prop="deptId">
               <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true"
-                          placeholder="请选择归属部门" :normalizer="normalizer"
-              />
+                          placeholder="请选择归属部门" :normalizer="normalizer"/>
             </el-form-item>
           </el-col>
         </el-row>
@@ -236,12 +139,7 @@
           <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-option v-for="dict in sexDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
               </el-select>
             </el-form-item>
           </el-col>
@@ -333,8 +231,18 @@
 </template>
 
 <script>
-import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from "@/api/system/user";
-import { getToken } from "@/utils/auth";
+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";
 

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

@@ -13,11 +13,11 @@
             <ul class="list-group list-group-striped">
               <li class="list-group-item">
                 <svg-icon icon-class="user" />用户名称
-                <div class="pull-right">{{ user.userName }}</div>
+                <div class="pull-right">{{ user.username }}</div>
               </li>
               <li class="list-group-item">
                 <svg-icon icon-class="phone" />手机号码
-                <div class="pull-right">{{ user.phonenumber }}</div>
+                <div class="pull-right">{{ user.mobile }}</div>
               </li>
               <li class="list-group-item">
                 <svg-icon icon-class="email" />用户邮箱
@@ -25,15 +25,19 @@
               </li>
               <li class="list-group-item">
                 <svg-icon icon-class="tree" />所属部门
-                <div class="pull-right" v-if="user.dept">{{ user.dept.deptName }} / {{ postGroup }}</div>
+                <div class="pull-right" v-if="user.dept">{{ user.dept.name }}</div>
+              </li>
+              <li class="list-group-item">
+                <svg-icon icon-class="tree" />所属岗位
+                <div class="pull-right" v-if="user.posts">{{ user.posts.map(post => post.name).join(',') }}</div>
               </li>
               <li class="list-group-item">
                 <svg-icon icon-class="peoples" />所属角色
-                <div class="pull-right">{{ roleGroup }}</div>
+                <div class="pull-right">{{ user.roles.map(post => post.name).join(',') }}</div>
               </li>
               <li class="list-group-item">
                 <svg-icon icon-class="date" />创建日期
-                <div class="pull-right">{{ user.createTime }}</div>
+                <div class="pull-right">{{ parseTime(user.createTime) }}</div>
               </li>
             </ul>
           </div>
@@ -82,8 +86,6 @@ export default {
     getUser() {
       getUserProfile().then(response => {
         this.user = response.data;
-        this.roleGroup = response.roleGroup;
-        this.postGroup = response.postGroup;
       });
     }
   }

+ 8 - 8
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-form-item label="手机号码" prop="phonenumber">
-      <el-input v-model="user.phonenumber" maxlength="11" />
+      <el-input v-model="user.nickname" />
+    </el-form-item>
+    <el-form-item label="手机号码" prop="mobile">
+      <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}$/,

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

+ 46 - 339
sql/ruoyi-vue-pro.sql

@@ -11,7 +11,7 @@
  Target Server Version : 50718
  File Encoding         : 65001
 
- Date: 14/03/2021 13:12:25
+ Date: 21/03/2021 18:53:24
 */
 
 SET NAMES utf8mb4;
@@ -43,155 +43,12 @@ CREATE TABLE `inf_api_access_log` (
   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=592 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
+) ENGINE=InnoDB AUTO_INCREMENT=1318 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
 
 -- ----------------------------
 -- Records of inf_api_access_log
 -- ----------------------------
 BEGIN;
-INSERT INTO `inf_api_access_log` VALUES (449, 'f22b9b8b-baf1-4e79-9858-c5417b12d808', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:12', '2021-03-13 13:32:12', 153, 0, '', NULL, '2021-03-13 13:32:12', NULL, '2021-03-13 13:32:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (450, '0a38df74-a77c-48fd-89e5-11182a2ee6a8', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:12', '2021-03-13 13:32:12', 153, 0, '', NULL, '2021-03-13 13:32:12', NULL, '2021-03-13 13:32:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (451, 'ee2dffcd-6423-488f-bdc5-be78f6e2576d', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:12', '2021-03-13 13:32:12', 13, 0, '', NULL, '2021-03-13 13:32:12', NULL, '2021-03-13 13:32:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (452, 'a71edfed-315b-4f60-9d60-f4d65eb71934', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:12', '2021-03-13 13:32:13', 23, 0, '', NULL, '2021-03-13 13:32:13', NULL, '2021-03-13 13:32:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (453, '71d26ef0-e0ff-4d00-9e88-fcc1586b5ed7', 1, 2, 'dashboard', 'GET', '/api/system/dept/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:13', '2021-03-13 13:32:13', 32, 0, '', NULL, '2021-03-13 13:32:13', NULL, '2021-03-13 13:32:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (454, '11cbd450-214c-4217-9ab3-eebfdcc668d2', 1, 2, 'dashboard', 'GET', '/api/system/post/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:13', '2021-03-13 13:32:13', 29, 0, '', NULL, '2021-03-13 13:32:13', NULL, '2021-03-13 13:32:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (455, '9400d6b4-16f6-4a19-ade8-0e3b788e386f', 1, 2, 'dashboard', 'GET', '/api/infra/config/get-value-by-key', '{\"query\":{\"key\":\"sys.user.initPassword\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:13', '2021-03-13 13:32:13', 51, 0, '', NULL, '2021-03-13 13:32:13', NULL, '2021-03-13 13:32:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (456, '74bd4331-3765-4e57-9207-7f461c0bf4a3', 1, 2, 'dashboard', 'GET', '/api/system/user/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:12', '2021-03-13 13:32:13', 162, 0, '', NULL, '2021-03-13 13:32:13', NULL, '2021-03-13 13:32:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (457, '84877f91-7e13-4150-8cc6-1c4a2a769e85', 1, 2, 'dashboard', 'GET', '/api/infra/file/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:24', '2021-03-13 13:32:24', 37, 0, '', NULL, '2021-03-13 13:32:24', NULL, '2021-03-13 13:32:24', b'0');
-INSERT INTO `inf_api_access_log` VALUES (458, 'a50536b1-94a2-419a-9c81-2ae812cd1e26', 0, 2, 'dashboard', 'GET', '/api/infra/file/get/5e8609290e915c4fa8b08e67.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:24', '2021-03-13 13:32:24', 14, 0, '', NULL, '2021-03-13 13:32:24', NULL, '2021-03-13 13:32:24', b'0');
-INSERT INTO `inf_api_access_log` VALUES (459, '82da8546-b43b-4290-9a8e-1e7dcd9dbd1c', 0, 2, 'dashboard', 'GET', '/api/infra/file/get/427.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:24', '2021-03-13 13:32:24', 14, 0, '', NULL, '2021-03-13 13:32:24', NULL, '2021-03-13 13:32:24', b'0');
-INSERT INTO `inf_api_access_log` VALUES (460, '8886554b-d6af-4538-b3fb-51584363b567', 0, 2, 'dashboard', 'GET', '/api/infra/file/get/8448cada8c714e4ab61f521c8da21990', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:32:24', '2021-03-13 13:32:24', 12, 0, '', NULL, '2021-03-13 13:32:24', NULL, '2021-03-13 13:32:24', b'0');
-INSERT INTO `inf_api_access_log` VALUES (461, '528742f2-6311-49d9-8c15-54e1d89730bb', 1, 2, 'dashboard', 'GET', '/api/tool/codegen/table/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:35:08', '2021-03-13 13:35:08', 40, 0, '', NULL, '2021-03-13 13:35:08', NULL, '2021-03-13 13:35:08', b'0');
-INSERT INTO `inf_api_access_log` VALUES (462, 'c62d9055-d12c-4236-af7c-16753905a0dd', 1, 2, 'dashboard', 'GET', '/api/tool/codegen/preview', '{\"query\":{\"tableId\":\"33\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:35:12', '2021-03-13 13:35:12', 235, 0, '', NULL, '2021-03-13 13:35:12', NULL, '2021-03-13 13:35:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (463, '0aebc46f-2852-4300-afb6-323a97e1d45c', 1, 2, 'dashboard', 'GET', '/api/tool/codegen/detail', '{\"query\":{\"tableId\":\"33\"},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:35:48', '2021-03-13 13:35:48', 26, 0, '', NULL, '2021-03-13 13:35:48', NULL, '2021-03-13 13:35:48', b'0');
-INSERT INTO `inf_api_access_log` VALUES (464, 'ed36b980-e12d-474e-99fe-53962b4fcde7', 1, 2, 'dashboard', 'GET', '/api/system/dict-type/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:35:48', '2021-03-13 13:35:48', 20, 0, '', NULL, '2021-03-13 13:35:48', NULL, '2021-03-13 13:35:48', b'0');
-INSERT INTO `inf_api_access_log` VALUES (465, 'bac9bea3-1e07-4642-8252-469bb0c58ab8', 1, 2, 'dashboard', 'GET', '/api/system/menu/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-13 13:35:48', '2021-03-13 13:35:48', 34, 0, '', NULL, '2021-03-13 13:35:48', NULL, '2021-03-13 13:35:48', b'0');
-INSERT INTO `inf_api_access_log` VALUES (466, 'b8c6972c-0cd0-475a-8cbe-c25f965233ec', 0, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:32', '2021-03-14 00:31:32', 35, 0, '', NULL, '2021-03-14 00:31:32', NULL, '2021-03-14 00:31:32', b'0');
-INSERT INTO `inf_api_access_log` VALUES (467, '3223baf6-510b-44ac-b174-1e8f754f274e', 0, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:32', '2021-03-14 00:31:32', 35, 0, '', NULL, '2021-03-14 00:31:32', NULL, '2021-03-14 00:31:32', b'0');
-INSERT INTO `inf_api_access_log` VALUES (468, '43158144-4ea2-459d-a677-0431effdc434', 0, 2, 'dashboard', 'POST', '/api/logout', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:32', '2021-03-14 00:31:32', 4, 0, '', NULL, '2021-03-14 00:31:32', NULL, '2021-03-14 00:31:32', b'0');
-INSERT INTO `inf_api_access_log` VALUES (469, '02497e40-c460-4ba1-8b56-f0ec6d327371', 0, 2, 'dashboard', 'POST', '/api/logout', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:34', '2021-03-14 00:31:34', 2, 0, '', NULL, '2021-03-14 00:31:34', NULL, '2021-03-14 00:31:34', b'0');
-INSERT INTO `inf_api_access_log` VALUES (470, '3cfcc80d-150e-42f5-bace-472b52db4898', 0, 2, 'dashboard', 'GET', '/api/system/captcha/get-image', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:32', '2021-03-14 00:31:34', 2432, 0, '', NULL, '2021-03-14 00:31:34', NULL, '2021-03-14 00:31:34', b'0');
-INSERT INTO `inf_api_access_log` VALUES (471, 'd8d4767b-9064-4e2d-a619-08755e31758a', 0, 2, 'dashboard', 'GET', '/api/system/captcha/get-image', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:34', '2021-03-14 00:31:34', 30, 0, '', NULL, '2021-03-14 00:31:34', NULL, '2021-03-14 00:31:34', b'0');
-INSERT INTO `inf_api_access_log` VALUES (472, '5a937554-c758-4d39-8473-84078eb23708', 0, 2, 'dashboard', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"0j0pw\\\",\\\"uuid\\\":\\\"cf44d21646cb4dc4b6bd0207dec9c387\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:39', '2021-03-14 00:31:39', 55, 1002000004, '验证码不正确', NULL, '2021-03-14 00:31:39', NULL, '2021-03-14 00:31:39', b'0');
-INSERT INTO `inf_api_access_log` VALUES (473, '0b0a61ba-3b13-4f7e-8eac-d037854afbe5', 0, 2, 'dashboard', 'GET', '/api/system/captcha/get-image', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:39', '2021-03-14 00:31:39', 15, 0, '', NULL, '2021-03-14 00:31:39', NULL, '2021-03-14 00:31:39', b'0');
-INSERT INTO `inf_api_access_log` VALUES (474, '3fbef0e6-da78-408f-bf58-2b09e9316285', 0, 2, 'dashboard', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"18nyi\\\",\\\"uuid\\\":\\\"f39a9a64154c4e72a7fa4deda5b83052\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:43', '2021-03-14 00:31:43', 244, 0, '', NULL, '2021-03-14 00:31:43', NULL, '2021-03-14 00:31:43', b'0');
-INSERT INTO `inf_api_access_log` VALUES (475, '0d50b4d2-b545-44e2-9cfb-ea1961c58e9a', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:43', '2021-03-14 00:31:43', 29, 0, '', NULL, '2021-03-14 00:31:43', NULL, '2021-03-14 00:31:43', b'0');
-INSERT INTO `inf_api_access_log` VALUES (476, 'a837de17-c5bc-4223-91ac-2f9b79c536e3', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:43', '2021-03-14 00:31:43', 29, 0, '', NULL, '2021-03-14 00:31:43', NULL, '2021-03-14 00:31:43', b'0');
-INSERT INTO `inf_api_access_log` VALUES (477, 'e57342e2-7db6-4b7b-9ab5-55169ef7d042', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:43', '2021-03-14 00:31:43', 11, 0, '', NULL, '2021-03-14 00:31:43', NULL, '2021-03-14 00:31:43', b'0');
-INSERT INTO `inf_api_access_log` VALUES (478, '7bb82837-8a93-4357-a14f-f1d0856074c8', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:43', '2021-03-14 00:31:43', 4, 0, '', NULL, '2021-03-14 00:31:44', NULL, '2021-03-14 00:31:44', b'0');
-INSERT INTO `inf_api_access_log` VALUES (479, 'ee9e5588-1704-4c35-afca-f42007c17079', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:31:49', '2021-03-14 00:31:50', 549, 0, '', NULL, '2021-03-14 00:31:50', NULL, '2021-03-14 00:31:50', b'0');
-INSERT INTO `inf_api_access_log` VALUES (480, '07e9d2a7-a35d-4d46-aedf-37a899c50f77', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:32:17', '2021-03-14 00:32:17', 9, 0, '', NULL, '2021-03-14 00:32:17', NULL, '2021-03-14 00:32:17', b'0');
-INSERT INTO `inf_api_access_log` VALUES (481, '7b2e7d88-baa9-4b3a-bef9-97d1cb9a27c7', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:32:17', '2021-03-14 00:32:17', 17, 0, '', NULL, '2021-03-14 00:32:17', NULL, '2021-03-14 00:32:17', b'0');
-INSERT INTO `inf_api_access_log` VALUES (482, '0078c48a-beb9-4b34-b44e-b75ff3aa974b', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:32:17', '2021-03-14 00:32:17', 7, 0, '', NULL, '2021-03-14 00:32:17', NULL, '2021-03-14 00:32:17', b'0');
-INSERT INTO `inf_api_access_log` VALUES (483, '8d8541f4-7921-46da-9804-3922ea43ccab', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:32:18', '2021-03-14 00:32:18', 4, 0, '', NULL, '2021-03-14 00:32:18', NULL, '2021-03-14 00:32:18', b'0');
-INSERT INTO `inf_api_access_log` VALUES (484, '442c170e-7eb8-43a7-aad4-7cd10a75f64a', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:32:18', '2021-03-14 00:32:18', 132, 0, '', NULL, '2021-03-14 00:32:18', NULL, '2021-03-14 00:32:18', b'0');
-INSERT INTO `inf_api_access_log` VALUES (485, 'b3d0f1e8-e31e-4611-9463-615adca3a89e', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:15', '2021-03-14 00:34:15', 9, 0, '', NULL, '2021-03-14 00:34:15', NULL, '2021-03-14 00:34:15', b'0');
-INSERT INTO `inf_api_access_log` VALUES (486, '12040d3b-c59c-4727-b646-a9633a71a9bc', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:15', '2021-03-14 00:34:15', 14, 0, '', NULL, '2021-03-14 00:34:15', NULL, '2021-03-14 00:34:15', b'0');
-INSERT INTO `inf_api_access_log` VALUES (487, 'df248447-6cf7-4cca-be03-dd98330fbafe', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:15', '2021-03-14 00:34:15', 6, 0, '', NULL, '2021-03-14 00:34:15', NULL, '2021-03-14 00:34:15', b'0');
-INSERT INTO `inf_api_access_log` VALUES (488, '243764af-294c-47e5-aedc-529c9939a37e', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:16', '2021-03-14 00:34:16', 6, 0, '', NULL, '2021-03-14 00:34:16', NULL, '2021-03-14 00:34:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (489, '737d22fc-3d3d-4104-919a-8cec3ac5b837', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:16', '2021-03-14 00:34:16', 215, 0, '', NULL, '2021-03-14 00:34:16', NULL, '2021-03-14 00:34:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (490, '33d35537-8a07-4197-8930-e78d351f393f', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:57', '2021-03-14 00:34:57', 8, 0, '', NULL, '2021-03-14 00:34:57', NULL, '2021-03-14 00:34:57', b'0');
-INSERT INTO `inf_api_access_log` VALUES (491, '28c0cccd-0130-476b-89c6-f601f7b8b445', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:57', '2021-03-14 00:34:57', 16, 0, '', NULL, '2021-03-14 00:34:57', NULL, '2021-03-14 00:34:57', b'0');
-INSERT INTO `inf_api_access_log` VALUES (492, 'c649f830-e6b1-41db-9bdb-94bb5a7b8167', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:57', '2021-03-14 00:34:57', 4, 0, '', NULL, '2021-03-14 00:34:57', NULL, '2021-03-14 00:34:57', b'0');
-INSERT INTO `inf_api_access_log` VALUES (493, 'b66c63cf-3d74-4a74-acd6-2cd806062b62', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:57', '2021-03-14 00:34:57', 4, 0, '', NULL, '2021-03-14 00:34:57', NULL, '2021-03-14 00:34:57', b'0');
-INSERT INTO `inf_api_access_log` VALUES (494, '2d6d575f-c380-47c1-acc6-20989092060c', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:34:57', '2021-03-14 00:34:58', 225, 0, '', NULL, '2021-03-14 00:34:58', NULL, '2021-03-14 00:34:58', b'0');
-INSERT INTO `inf_api_access_log` VALUES (495, 'ffd49974-e6b7-425d-98cd-be851e38815e', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:04', '2021-03-14 00:35:04', 121, 0, '', NULL, '2021-03-14 00:35:04', NULL, '2021-03-14 00:35:04', b'0');
-INSERT INTO `inf_api_access_log` VALUES (496, '5292d11b-6981-49f5-9879-94f30cf93db4', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:10', '2021-03-14 00:35:10', 10, 0, '', NULL, '2021-03-14 00:35:10', NULL, '2021-03-14 00:35:10', b'0');
-INSERT INTO `inf_api_access_log` VALUES (497, '9e4816d7-b70a-46f5-afc5-f6fc7061fee3', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:10', '2021-03-14 00:35:10', 17, 0, '', NULL, '2021-03-14 00:35:10', NULL, '2021-03-14 00:35:10', b'0');
-INSERT INTO `inf_api_access_log` VALUES (498, 'df961948-f3f7-4fad-8d77-944820152305', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:10', '2021-03-14 00:35:10', 4, 0, '', NULL, '2021-03-14 00:35:10', NULL, '2021-03-14 00:35:10', b'0');
-INSERT INTO `inf_api_access_log` VALUES (499, 'dd5c28a0-76e1-47e6-bac7-293001d91f40', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:11', '2021-03-14 00:35:11', 4, 0, '', NULL, '2021-03-14 00:35:11', NULL, '2021-03-14 00:35:11', b'0');
-INSERT INTO `inf_api_access_log` VALUES (500, 'e15bf39c-80c8-432e-96fb-46543a892471', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:11', '2021-03-14 00:35:11', 184, 0, '', NULL, '2021-03-14 00:35:11', NULL, '2021-03-14 00:35:11', b'0');
-INSERT INTO `inf_api_access_log` VALUES (501, '564d7339-60f6-4c4e-8989-ef984a7dbe9c', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:16', '2021-03-14 00:35:16', 112, 0, '', NULL, '2021-03-14 00:35:16', NULL, '2021-03-14 00:35:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (502, '5d9562a7-ee32-4bd0-95b9-465685c4b037', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:31', '2021-03-14 00:35:31', 109, 0, '', NULL, '2021-03-14 00:35:31', NULL, '2021-03-14 00:35:31', b'0');
-INSERT INTO `inf_api_access_log` VALUES (503, '5eb9207f-4093-43af-aac4-8652d3088e7a', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:35:35', '2021-03-14 00:35:35', 102, 0, '', NULL, '2021-03-14 00:35:35', NULL, '2021-03-14 00:35:35', b'0');
-INSERT INTO `inf_api_access_log` VALUES (504, '0d7ec6da-0fb4-48c0-ac0e-d07d147970be', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:45:11', '2021-03-14 00:45:11', 21, 0, '', NULL, '2021-03-14 00:45:11', NULL, '2021-03-14 00:45:11', b'0');
-INSERT INTO `inf_api_access_log` VALUES (505, 'a9553f2b-c43b-4c65-a8bd-f62b462cd2ff', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:45:11', '2021-03-14 00:45:11', 30, 0, '', NULL, '2021-03-14 00:45:11', NULL, '2021-03-14 00:45:11', b'0');
-INSERT INTO `inf_api_access_log` VALUES (506, '850e7e9a-41fa-4321-a75b-ea74b3e0929e', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:45:11', '2021-03-14 00:45:11', 5, 0, '', NULL, '2021-03-14 00:45:11', NULL, '2021-03-14 00:45:11', b'0');
-INSERT INTO `inf_api_access_log` VALUES (507, 'd7e021f2-c943-4dd8-a47a-aabb7f0d4b98', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:45:12', '2021-03-14 00:45:12', 4, 0, '', NULL, '2021-03-14 00:45:12', NULL, '2021-03-14 00:45:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (508, '2a06b244-12b5-4ede-a1dc-487185515454', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:45:12', '2021-03-14 00:45:12', 141, 0, '', NULL, '2021-03-14 00:45:12', NULL, '2021-03-14 00:45:12', b'0');
-INSERT INTO `inf_api_access_log` VALUES (509, '1c8eeb85-895d-44b0-8872-aa80518c4644', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:22', '2021-03-14 00:46:22', 10, 0, '', NULL, '2021-03-14 00:46:22', NULL, '2021-03-14 00:46:22', b'0');
-INSERT INTO `inf_api_access_log` VALUES (510, '28d8923f-30f2-476e-9747-d6d8f5db464e', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:22', '2021-03-14 00:46:22', 6, 0, '', NULL, '2021-03-14 00:46:22', NULL, '2021-03-14 00:46:22', b'0');
-INSERT INTO `inf_api_access_log` VALUES (511, 'e16652a5-9eab-4717-945c-dfd157f71f3d', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:22', '2021-03-14 00:46:22', 4, 0, '', NULL, '2021-03-14 00:46:22', NULL, '2021-03-14 00:46:22', b'0');
-INSERT INTO `inf_api_access_log` VALUES (512, 'f8ebcae7-0292-4d54-b759-91dd0a82be05', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:23', '2021-03-14 00:46:23', 3, 0, '', NULL, '2021-03-14 00:46:23', NULL, '2021-03-14 00:46:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (513, 'a9f375d3-8da8-4459-9a22-74aad944ce43', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:23', '2021-03-14 00:46:23', 121, 0, '', NULL, '2021-03-14 00:46:23', NULL, '2021-03-14 00:46:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (514, '77043f29-8918-4d07-a7f3-30dff623607d', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:29', '2021-03-14 00:46:29', 127, 0, '', NULL, '2021-03-14 00:46:29', NULL, '2021-03-14 00:46:29', b'0');
-INSERT INTO `inf_api_access_log` VALUES (515, '8dfc5fe3-1f31-4a6a-8539-0ae3e599180b', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:35', '2021-03-14 00:46:35', 8, 0, '', NULL, '2021-03-14 00:46:35', NULL, '2021-03-14 00:46:35', b'0');
-INSERT INTO `inf_api_access_log` VALUES (516, '2fe23869-fbe2-463e-8b60-6c31b9ba4216', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:35', '2021-03-14 00:46:35', 13, 0, '', NULL, '2021-03-14 00:46:35', NULL, '2021-03-14 00:46:35', b'0');
-INSERT INTO `inf_api_access_log` VALUES (517, 'a1f78480-d3ee-4d66-aa2f-9c9ae8a410c6', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:35', '2021-03-14 00:46:35', 5, 0, '', NULL, '2021-03-14 00:46:35', NULL, '2021-03-14 00:46:35', b'0');
-INSERT INTO `inf_api_access_log` VALUES (518, '960426c8-a155-4000-8021-97463dae5f63', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:36', '2021-03-14 00:46:36', 4, 0, '', NULL, '2021-03-14 00:46:36', NULL, '2021-03-14 00:46:36', b'0');
-INSERT INTO `inf_api_access_log` VALUES (519, '6f074c2e-a508-4f62-87cb-af209d4bde98', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:36', '2021-03-14 00:46:36', 143, 0, '', NULL, '2021-03-14 00:46:36', NULL, '2021-03-14 00:46:36', b'0');
-INSERT INTO `inf_api_access_log` VALUES (520, 'efab06d5-343f-46ba-9e4f-9ba76b91b571', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:45', '2021-03-14 00:46:45', 5, 0, '', NULL, '2021-03-14 00:46:45', NULL, '2021-03-14 00:46:45', b'0');
-INSERT INTO `inf_api_access_log` VALUES (521, 'd1ee71ee-a30f-4123-8db3-7c3d885a6b50', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:45', '2021-03-14 00:46:45', 10, 0, '', NULL, '2021-03-14 00:46:45', NULL, '2021-03-14 00:46:45', b'0');
-INSERT INTO `inf_api_access_log` VALUES (522, 'e0d9c8f7-d12b-4791-8cd4-a6b8dbebc2d4', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:45', '2021-03-14 00:46:45', 5, 0, '', NULL, '2021-03-14 00:46:45', NULL, '2021-03-14 00:46:45', b'0');
-INSERT INTO `inf_api_access_log` VALUES (523, 'f17372a7-b9e1-43ce-a89a-9aef741fe679', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:46', '2021-03-14 00:46:46', 3, 0, '', NULL, '2021-03-14 00:46:46', NULL, '2021-03-14 00:46:46', b'0');
-INSERT INTO `inf_api_access_log` VALUES (524, 'e3b7d7fb-1c63-4623-aa7a-eb6931e703b3', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:46:46', '2021-03-14 00:46:46', 92, 0, '', NULL, '2021-03-14 00:46:46', NULL, '2021-03-14 00:46:46', b'0');
-INSERT INTO `inf_api_access_log` VALUES (525, 'd8e688e0-443c-4845-a666-fed7a77d5638', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:24', '2021-03-14 00:47:24', 118, 0, '', NULL, '2021-03-14 00:47:24', NULL, '2021-03-14 00:47:24', b'0');
-INSERT INTO `inf_api_access_log` VALUES (526, 'daa5a590-346c-4101-bfdf-c366e43e0714', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:25', '2021-03-14 00:47:25', 12, 0, '', NULL, '2021-03-14 00:47:25', NULL, '2021-03-14 00:47:25', b'0');
-INSERT INTO `inf_api_access_log` VALUES (527, 'dd28ff77-9d5b-4c34-a8d1-4fa6dcd68f68', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:25', '2021-03-14 00:47:25', 8, 0, '', NULL, '2021-03-14 00:47:25', NULL, '2021-03-14 00:47:25', b'0');
-INSERT INTO `inf_api_access_log` VALUES (528, '800bc255-e685-40a7-a623-ef1fc8087663', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:25', '2021-03-14 00:47:25', 6, 0, '', NULL, '2021-03-14 00:47:25', NULL, '2021-03-14 00:47:25', b'0');
-INSERT INTO `inf_api_access_log` VALUES (529, 'f3b59dce-a8d0-4b21-84b7-697498e19b63', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:26', '2021-03-14 00:47:26', 4, 0, '', NULL, '2021-03-14 00:47:26', NULL, '2021-03-14 00:47:26', b'0');
-INSERT INTO `inf_api_access_log` VALUES (530, 'ededd21f-77ef-4131-8c68-88815f9ca0bf', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:26', '2021-03-14 00:47:26', 121, 0, '', NULL, '2021-03-14 00:47:26', NULL, '2021-03-14 00:47:26', b'0');
-INSERT INTO `inf_api_access_log` VALUES (531, '17133597-d007-437b-9d5f-b04a6a412d89', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:47:28', '2021-03-14 00:47:28', 106, 0, '', NULL, '2021-03-14 00:47:28', NULL, '2021-03-14 00:47:28', b'0');
-INSERT INTO `inf_api_access_log` VALUES (532, '71daef1d-151c-48f9-9258-76210c22ecb2', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:48:56', '2021-03-14 00:48:56', 11, 0, '', NULL, '2021-03-14 00:48:56', NULL, '2021-03-14 00:48:56', b'0');
-INSERT INTO `inf_api_access_log` VALUES (533, '63d267ee-c6be-424b-a1d7-c75ef9135beb', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:48:56', '2021-03-14 00:48:56', 14, 0, '', NULL, '2021-03-14 00:48:56', NULL, '2021-03-14 00:48:56', b'0');
-INSERT INTO `inf_api_access_log` VALUES (534, '8b4be6d4-c505-4645-a46d-d74ea13b1221', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:48:56', '2021-03-14 00:48:56', 8, 0, '', NULL, '2021-03-14 00:48:56', NULL, '2021-03-14 00:48:56', b'0');
-INSERT INTO `inf_api_access_log` VALUES (535, '0d3fbb85-6d30-4e5f-a05b-c1939aca2f6b', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:48:56', '2021-03-14 00:48:56', 4, 0, '', NULL, '2021-03-14 00:48:56', NULL, '2021-03-14 00:48:56', b'0');
-INSERT INTO `inf_api_access_log` VALUES (536, '4594a8c9-95d2-4065-a5ca-6bbabb68a118', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:48:56', '2021-03-14 00:48:57', 121, 0, '', NULL, '2021-03-14 00:48:57', NULL, '2021-03-14 00:48:57', b'0');
-INSERT INTO `inf_api_access_log` VALUES (537, '6ebbcd89-38c1-4149-9238-1fa88ead86cf', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:49:40', '2021-03-14 00:49:40', 9, 0, '', NULL, '2021-03-14 00:49:40', NULL, '2021-03-14 00:49:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (538, '62931059-c92b-44d8-85fb-96ab71763ad6', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:49:40', '2021-03-14 00:49:40', 11, 0, '', NULL, '2021-03-14 00:49:40', NULL, '2021-03-14 00:49:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (539, '4f3a27de-2994-451d-b33c-048e6479aebb', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:49:40', '2021-03-14 00:49:40', 5, 0, '', NULL, '2021-03-14 00:49:40', NULL, '2021-03-14 00:49:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (540, 'f1ccb45d-ec2d-4cc5-845a-4e120d2f2aa5', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:49:41', '2021-03-14 00:49:41', 4, 0, '', NULL, '2021-03-14 00:49:41', NULL, '2021-03-14 00:49:41', b'0');
-INSERT INTO `inf_api_access_log` VALUES (541, '26359dfe-1c16-459c-a84e-24cb03e4c065', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:49:41', '2021-03-14 00:49:41', 139, 0, '', NULL, '2021-03-14 00:49:41', NULL, '2021-03-14 00:49:41', b'0');
-INSERT INTO `inf_api_access_log` VALUES (542, '7b669973-5430-4655-8800-64c0ac83b1a3', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:50:20', '2021-03-14 00:50:20', 8, 0, '', NULL, '2021-03-14 00:50:20', NULL, '2021-03-14 00:50:20', b'0');
-INSERT INTO `inf_api_access_log` VALUES (543, 'd24724d2-318a-4876-b706-58aea1ef7dc5', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:50:20', '2021-03-14 00:50:20', 8, 0, '', NULL, '2021-03-14 00:50:20', NULL, '2021-03-14 00:50:20', b'0');
-INSERT INTO `inf_api_access_log` VALUES (544, 'cd024db3-fb5e-40ff-a574-674361441bc2', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:50:20', '2021-03-14 00:50:20', 4, 0, '', NULL, '2021-03-14 00:50:20', NULL, '2021-03-14 00:50:20', b'0');
-INSERT INTO `inf_api_access_log` VALUES (545, 'd2eec64e-7a8c-498d-89fc-42e958cb8408', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:50:21', '2021-03-14 00:50:21', 4, 0, '', NULL, '2021-03-14 00:50:21', NULL, '2021-03-14 00:50:21', b'0');
-INSERT INTO `inf_api_access_log` VALUES (546, '28859271-d60e-4644-a600-a5b77538e5c4', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:50:21', '2021-03-14 00:50:21', 97, 0, '', NULL, '2021-03-14 00:50:21', NULL, '2021-03-14 00:50:21', b'0');
-INSERT INTO `inf_api_access_log` VALUES (547, '571b1d57-465a-43f2-955b-fa63d6b0181e', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:00', '2021-03-14 00:51:00', 83, 0, '', NULL, '2021-03-14 00:51:00', NULL, '2021-03-14 00:51:00', b'0');
-INSERT INTO `inf_api_access_log` VALUES (548, 'b1afa1bd-bf40-4c69-a1df-bb214853a70c', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:02', '2021-03-14 00:51:02', 7, 0, '', NULL, '2021-03-14 00:51:02', NULL, '2021-03-14 00:51:02', b'0');
-INSERT INTO `inf_api_access_log` VALUES (549, 'a7a60980-6a8b-4624-abb9-c2f8d22dbdc9', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:02', '2021-03-14 00:51:02', 8, 0, '', NULL, '2021-03-14 00:51:02', NULL, '2021-03-14 00:51:02', b'0');
-INSERT INTO `inf_api_access_log` VALUES (550, '14690b9d-ae7b-493d-994c-68b9c0b3ebf6', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:02', '2021-03-14 00:51:02', 11, 0, '', NULL, '2021-03-14 00:51:02', NULL, '2021-03-14 00:51:02', b'0');
-INSERT INTO `inf_api_access_log` VALUES (551, 'd2851315-11ee-4762-af1a-64a94c07678d', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:03', '2021-03-14 00:51:03', 3, 0, '', NULL, '2021-03-14 00:51:03', NULL, '2021-03-14 00:51:03', b'0');
-INSERT INTO `inf_api_access_log` VALUES (552, 'a9c16cb6-5549-4041-a062-4dce54466dce', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:03', '2021-03-14 00:51:03', 107, 0, '', NULL, '2021-03-14 00:51:03', NULL, '2021-03-14 00:51:03', b'0');
-INSERT INTO `inf_api_access_log` VALUES (553, 'cbaea7cc-33cf-4422-b572-be0ea36bb0ae', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:04', '2021-03-14 00:51:04', 103, 0, '', NULL, '2021-03-14 00:51:04', NULL, '2021-03-14 00:51:04', b'0');
-INSERT INTO `inf_api_access_log` VALUES (554, '5c129cb2-65f4-4590-97dd-7300169190c4', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:10', '2021-03-14 00:51:10', 76, 0, '', NULL, '2021-03-14 00:51:10', NULL, '2021-03-14 00:51:10', b'0');
-INSERT INTO `inf_api_access_log` VALUES (555, '4bc3e1e7-ed14-4ccb-8c55-72d6de7918ca', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:31', '2021-03-14 00:51:31', 82, 0, '', NULL, '2021-03-14 00:51:31', NULL, '2021-03-14 00:51:31', b'0');
-INSERT INTO `inf_api_access_log` VALUES (556, 'ee785bdd-bc34-4f32-80fc-4640b82b9ac0', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:51:51', '2021-03-14 00:51:51', 84, 0, '', NULL, '2021-03-14 00:51:51', NULL, '2021-03-14 00:51:51', b'0');
-INSERT INTO `inf_api_access_log` VALUES (557, '7e0599b4-40a0-4483-a894-3aac27433b3c', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:13', '2021-03-14 00:55:13', 18, 0, '', NULL, '2021-03-14 00:55:13', NULL, '2021-03-14 00:55:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (558, '9ba6d255-fc1f-4404-928f-7043db300fd4', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:13', '2021-03-14 00:55:13', 16, 0, '', NULL, '2021-03-14 00:55:13', NULL, '2021-03-14 00:55:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (559, 'e6666077-1657-4379-9450-d3d85d4c1258', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:13', '2021-03-14 00:55:13', 3, 0, '', NULL, '2021-03-14 00:55:13', NULL, '2021-03-14 00:55:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (560, 'b25155cf-2cd8-4ce0-87f4-71e070df815b', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:13', '2021-03-14 00:55:13', 3, 0, '', NULL, '2021-03-14 00:55:13', NULL, '2021-03-14 00:55:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (561, '2ccd65ca-69b0-4057-abd9-b1a966651fc5', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:13', '2021-03-14 00:55:13', 117, 0, '', NULL, '2021-03-14 00:55:13', NULL, '2021-03-14 00:55:13', b'0');
-INSERT INTO `inf_api_access_log` VALUES (562, '587de0ff-1252-4205-bd17-a803b74ddb2e', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:16', '2021-03-14 00:55:16', 8, 0, '', NULL, '2021-03-14 00:55:16', NULL, '2021-03-14 00:55:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (563, 'ee876570-68aa-4ded-ba7d-2165747211a5', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:16', '2021-03-14 00:55:16', 7, 0, '', NULL, '2021-03-14 00:55:16', NULL, '2021-03-14 00:55:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (564, '0369c181-f2c3-4d3b-8929-e6363adb8b2e', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:16', '2021-03-14 00:55:16', 4, 0, '', NULL, '2021-03-14 00:55:16', NULL, '2021-03-14 00:55:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (565, '2871031c-fb9c-401f-b877-37ec9ab3f4ad', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:16', '2021-03-14 00:55:16', 3, 0, '', NULL, '2021-03-14 00:55:16', NULL, '2021-03-14 00:55:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (566, '3bd22cb5-6ace-487d-82e6-50697644c317', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:16', '2021-03-14 00:55:16', 101, 0, '', NULL, '2021-03-14 00:55:16', NULL, '2021-03-14 00:55:16', b'0');
-INSERT INTO `inf_api_access_log` VALUES (567, '3a57f69f-4606-436c-9735-680089207fc5', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:30', '2021-03-14 00:55:30', 10, 0, '', NULL, '2021-03-14 00:55:30', NULL, '2021-03-14 00:55:30', b'0');
-INSERT INTO `inf_api_access_log` VALUES (568, '22f1460b-2326-47fd-9cd0-ea6df3a44914', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:30', '2021-03-14 00:55:30', 7, 0, '', NULL, '2021-03-14 00:55:30', NULL, '2021-03-14 00:55:30', b'0');
-INSERT INTO `inf_api_access_log` VALUES (569, 'c60675ce-fa92-4a7e-9cc9-d87ce3b3262a', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:30', '2021-03-14 00:55:30', 3, 0, '', NULL, '2021-03-14 00:55:30', NULL, '2021-03-14 00:55:30', b'0');
-INSERT INTO `inf_api_access_log` VALUES (570, 'a8b1a03e-5dad-4600-8e11-6d843568e408', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:31', '2021-03-14 00:55:31', 3, 0, '', NULL, '2021-03-14 00:55:31', NULL, '2021-03-14 00:55:31', b'0');
-INSERT INTO `inf_api_access_log` VALUES (571, 'c32df32a-7e50-48d8-8063-8b3a6d25f923', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:31', '2021-03-14 00:55:31', 104, 0, '', NULL, '2021-03-14 00:55:31', NULL, '2021-03-14 00:55:31', b'0');
-INSERT INTO `inf_api_access_log` VALUES (572, '752e6282-961b-4f02-901e-9433e440c5fa', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-word', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:32', '2021-03-14 00:55:32', 145, 0, '', NULL, '2021-03-14 00:55:32', NULL, '2021-03-14 00:55:32', b'0');
-INSERT INTO `inf_api_access_log` VALUES (573, 'af6920a9-d027-428a-91ac-339bff58a5cd', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:55:54', '2021-03-14 00:55:54', 89, 0, '', NULL, '2021-03-14 00:55:54', NULL, '2021-03-14 00:55:54', b'0');
-INSERT INTO `inf_api_access_log` VALUES (574, 'f69013a1-1ccc-48d4-b0d0-7cad81242e98', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:14', '2021-03-14 00:56:15', 89, 0, '', NULL, '2021-03-14 00:56:15', NULL, '2021-03-14 00:56:15', b'0');
-INSERT INTO `inf_api_access_log` VALUES (575, '57019f8e-4d4f-4e79-84d5-010e3c7cccac', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:40', '2021-03-14 00:56:40', 6, 0, '', NULL, '2021-03-14 00:56:40', NULL, '2021-03-14 00:56:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (576, '27da3255-4f47-4c77-b001-d44a7f12d09f', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:40', '2021-03-14 00:56:40', 8, 0, '', NULL, '2021-03-14 00:56:40', NULL, '2021-03-14 00:56:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (577, '58f40949-366d-4df3-8a10-ee8b88c7ac7e', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:40', '2021-03-14 00:56:40', 3, 0, '', NULL, '2021-03-14 00:56:40', NULL, '2021-03-14 00:56:40', b'0');
-INSERT INTO `inf_api_access_log` VALUES (578, 'b1d195de-c8ed-4001-b701-666dcfc6c4bb', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:41', '2021-03-14 00:56:41', 4, 0, '', NULL, '2021-03-14 00:56:41', NULL, '2021-03-14 00:56:41', b'0');
-INSERT INTO `inf_api_access_log` VALUES (579, 'b12d0c14-6251-4fad-99b7-c7a74d1e28c5', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:41', '2021-03-14 00:56:41', 183, 0, '', NULL, '2021-03-14 00:56:41', NULL, '2021-03-14 00:56:41', b'0');
-INSERT INTO `inf_api_access_log` VALUES (580, '05994cf8-30e3-443b-b9bd-defcee3c34b7', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:58', '2021-03-14 00:56:58', 7, 0, '', NULL, '2021-03-14 00:56:58', NULL, '2021-03-14 00:56:58', b'0');
-INSERT INTO `inf_api_access_log` VALUES (581, '569e9723-8f80-418d-8862-048061abd517', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:58', '2021-03-14 00:56:58', 5, 0, '', NULL, '2021-03-14 00:56:58', NULL, '2021-03-14 00:56:58', b'0');
-INSERT INTO `inf_api_access_log` VALUES (582, '84fc7483-7197-4652-96fe-eaef3fc1e72f', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:58', '2021-03-14 00:56:58', 3, 0, '', NULL, '2021-03-14 00:56:58', NULL, '2021-03-14 00:56:58', b'0');
-INSERT INTO `inf_api_access_log` VALUES (583, '022cd5b7-4b5b-48ee-ae3b-34fa5d627ff4', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:59', '2021-03-14 00:56:59', 3, 0, '', NULL, '2021-03-14 00:56:59', NULL, '2021-03-14 00:56:59', b'0');
-INSERT INTO `inf_api_access_log` VALUES (584, '8f76d7b3-5302-4f95-9158-45bd91c5a468', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:56:59', '2021-03-14 00:56:59', 97, 0, '', NULL, '2021-03-14 00:56:59', NULL, '2021-03-14 00:56:59', b'0');
-INSERT INTO `inf_api_access_log` VALUES (585, 'fb3868ea-e5f4-4e33-b1ff-277bf17d3581', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-markdown', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:00', '2021-03-14 00:57:00', 111, 0, '', NULL, '2021-03-14 00:57:00', NULL, '2021-03-14 00:57:00', b'0');
-INSERT INTO `inf_api_access_log` VALUES (586, '3ffb100a-5e77-4a9f-b2d8-6bf4e2904451', 1, 2, 'dashboard', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:23', '2021-03-14 00:57:23', 13, 0, '', NULL, '2021-03-14 00:57:23', NULL, '2021-03-14 00:57:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (587, 'cdc2e1f8-35b2-41b1-b3ba-f9ec1fa1e6d0', 1, 2, 'dashboard', 'GET', '/api/get-permission-info', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:23', '2021-03-14 00:57:23', 7, 0, '', NULL, '2021-03-14 00:57:23', NULL, '2021-03-14 00:57:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (588, 'b9815e22-5c15-429e-800c-736f52fe99a9', 1, 2, 'dashboard', 'GET', '/api/list-menus', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:23', '2021-03-14 00:57:23', 4, 0, '', NULL, '2021-03-14 00:57:23', NULL, '2021-03-14 00:57:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (589, '8da35ff9-526e-4b76-a486-c1c27c744493', 0, 2, 'dashboard', 'GET', '/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:23', '2021-03-14 00:57:23', 3, 0, '', NULL, '2021-03-14 00:57:23', NULL, '2021-03-14 00:57:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (590, '604ae467-e8a2-48cf-b19f-0c7d79aa0c9c', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-html', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:23', '2021-03-14 00:57:23', 100, 0, '', NULL, '2021-03-14 00:57:23', NULL, '2021-03-14 00:57:23', b'0');
-INSERT INTO `inf_api_access_log` VALUES (591, 'eba82a07-fcde-4566-a8db-cd4f55c42d4a', 1, 2, 'dashboard', 'GET', '/api/infra/db-doc/export-markdown', '{\"query\":{},\"body\":null}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', '2021-03-14 00:57:25', '2021-03-14 00:57:25', 87, 0, '', NULL, '2021-03-14 00:57:25', NULL, '2021-03-14 00:57:25', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -344,162 +201,12 @@ CREATE TABLE `inf_job_log` (
   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=435 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
+) ENGINE=InnoDB AUTO_INCREMENT=627 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
 
 -- ----------------------------
 -- Records of inf_job_log
 -- ----------------------------
 BEGIN;
-INSERT INTO `inf_job_log` VALUES (285, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:31:44', '2021-03-13 13:31:44', 63, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:31:44', NULL, '2021-03-13 13:31:44', b'0');
-INSERT INTO `inf_job_log` VALUES (286, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:32:00', '2021-03-13 13:32:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:32:00', NULL, '2021-03-13 13:32:00', b'0');
-INSERT INTO `inf_job_log` VALUES (287, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:33:00', '2021-03-13 13:33:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:33:00', NULL, '2021-03-13 13:33:00', b'0');
-INSERT INTO `inf_job_log` VALUES (288, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:34:00', '2021-03-13 13:34:00', 9, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:34:00', NULL, '2021-03-13 13:34:00', b'0');
-INSERT INTO `inf_job_log` VALUES (289, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:35:00', '2021-03-13 13:35:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:35:00', NULL, '2021-03-13 13:35:00', b'0');
-INSERT INTO `inf_job_log` VALUES (290, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:36:00', '2021-03-13 13:36:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:36:00', NULL, '2021-03-13 13:36:00', b'0');
-INSERT INTO `inf_job_log` VALUES (291, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:37:00', '2021-03-13 13:37:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:37:00', NULL, '2021-03-13 13:37:00', b'0');
-INSERT INTO `inf_job_log` VALUES (292, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:38:00', '2021-03-13 13:38:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:38:00', NULL, '2021-03-13 13:38:00', b'0');
-INSERT INTO `inf_job_log` VALUES (293, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:39:00', '2021-03-13 13:39:00', 9, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:39:00', NULL, '2021-03-13 13:39:00', b'0');
-INSERT INTO `inf_job_log` VALUES (294, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:40:00', '2021-03-13 13:40:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:40:00', NULL, '2021-03-13 13:40:00', b'0');
-INSERT INTO `inf_job_log` VALUES (295, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-13 13:41:00', '2021-03-13 13:41:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-13 13:41:00', NULL, '2021-03-13 13:41:00', b'0');
-INSERT INTO `inf_job_log` VALUES (296, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:31:13', '2021-03-14 00:31:13', 133, 1, '移除在线会话数量为 1 个', NULL, '2021-03-14 00:31:13', NULL, '2021-03-14 00:31:13', b'0');
-INSERT INTO `inf_job_log` VALUES (297, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:32:00', '2021-03-14 00:32:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:32:00', NULL, '2021-03-14 00:32:00', b'0');
-INSERT INTO `inf_job_log` VALUES (298, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:33:00', '2021-03-14 00:33:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:33:00', NULL, '2021-03-14 00:33:00', b'0');
-INSERT INTO `inf_job_log` VALUES (299, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:34:00', '2021-03-14 00:34:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:34:00', NULL, '2021-03-14 00:34:00', b'0');
-INSERT INTO `inf_job_log` VALUES (300, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:35:00', '2021-03-14 00:35:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:35:00', NULL, '2021-03-14 00:35:00', b'0');
-INSERT INTO `inf_job_log` VALUES (301, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:36:00', '2021-03-14 00:36:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:36:00', NULL, '2021-03-14 00:36:00', b'0');
-INSERT INTO `inf_job_log` VALUES (302, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:37:00', '2021-03-14 00:37:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:37:00', NULL, '2021-03-14 00:37:00', b'0');
-INSERT INTO `inf_job_log` VALUES (303, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:38:00', '2021-03-14 00:38:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:38:00', NULL, '2021-03-14 00:38:00', b'0');
-INSERT INTO `inf_job_log` VALUES (304, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:39:00', '2021-03-14 00:39:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:39:00', NULL, '2021-03-14 00:39:00', b'0');
-INSERT INTO `inf_job_log` VALUES (305, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:40:00', '2021-03-14 00:40:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:40:00', NULL, '2021-03-14 00:40:00', b'0');
-INSERT INTO `inf_job_log` VALUES (306, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:41:00', '2021-03-14 00:41:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:41:00', NULL, '2021-03-14 00:41:00', b'0');
-INSERT INTO `inf_job_log` VALUES (307, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:42:00', '2021-03-14 00:42:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:42:00', NULL, '2021-03-14 00:42:00', b'0');
-INSERT INTO `inf_job_log` VALUES (308, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:43:00', '2021-03-14 00:43:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:43:00', NULL, '2021-03-14 00:43:00', b'0');
-INSERT INTO `inf_job_log` VALUES (309, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:44:00', '2021-03-14 00:44:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:44:00', NULL, '2021-03-14 00:44:00', b'0');
-INSERT INTO `inf_job_log` VALUES (310, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:45:00', '2021-03-14 00:45:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:45:00', NULL, '2021-03-14 00:45:00', b'0');
-INSERT INTO `inf_job_log` VALUES (311, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:46:00', '2021-03-14 00:46:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:46:00', NULL, '2021-03-14 00:46:00', b'0');
-INSERT INTO `inf_job_log` VALUES (312, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:47:00', '2021-03-14 00:47:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:47:00', NULL, '2021-03-14 00:47:00', b'0');
-INSERT INTO `inf_job_log` VALUES (313, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:48:00', '2021-03-14 00:48:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:48:00', NULL, '2021-03-14 00:48:00', b'0');
-INSERT INTO `inf_job_log` VALUES (314, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:49:00', '2021-03-14 00:49:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:49:00', NULL, '2021-03-14 00:49:00', b'0');
-INSERT INTO `inf_job_log` VALUES (315, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:50:00', '2021-03-14 00:50:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:50:00', NULL, '2021-03-14 00:50:00', b'0');
-INSERT INTO `inf_job_log` VALUES (316, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:51:00', '2021-03-14 00:51:00', 9, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:51:00', NULL, '2021-03-14 00:51:00', b'0');
-INSERT INTO `inf_job_log` VALUES (317, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:52:00', '2021-03-14 00:52:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:52:00', NULL, '2021-03-14 00:52:00', b'0');
-INSERT INTO `inf_job_log` VALUES (318, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:53:00', '2021-03-14 00:53:00', 8, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:53:00', NULL, '2021-03-14 00:53:00', b'0');
-INSERT INTO `inf_job_log` VALUES (319, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:54:00', '2021-03-14 00:54:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:54:00', NULL, '2021-03-14 00:54:00', b'0');
-INSERT INTO `inf_job_log` VALUES (320, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:55:00', '2021-03-14 00:55:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:55:00', NULL, '2021-03-14 00:55:00', b'0');
-INSERT INTO `inf_job_log` VALUES (321, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:56:00', '2021-03-14 00:56:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:56:00', NULL, '2021-03-14 00:56:00', b'0');
-INSERT INTO `inf_job_log` VALUES (322, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:57:00', '2021-03-14 00:57:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:57:00', NULL, '2021-03-14 00:57:00', b'0');
-INSERT INTO `inf_job_log` VALUES (323, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:58:00', '2021-03-14 00:58:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:58:00', NULL, '2021-03-14 00:58:00', b'0');
-INSERT INTO `inf_job_log` VALUES (324, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 00:59:00', '2021-03-14 00:59:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 00:59:00', NULL, '2021-03-14 00:59:00', b'0');
-INSERT INTO `inf_job_log` VALUES (325, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:00:00', '2021-03-14 01:00:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:00:00', NULL, '2021-03-14 01:00:00', b'0');
-INSERT INTO `inf_job_log` VALUES (326, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:01:00', '2021-03-14 01:01:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:01:00', NULL, '2021-03-14 01:01:00', b'0');
-INSERT INTO `inf_job_log` VALUES (327, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:02:00', '2021-03-14 01:02:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:02:00', NULL, '2021-03-14 01:02:00', b'0');
-INSERT INTO `inf_job_log` VALUES (328, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:03:00', '2021-03-14 01:03:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:03:00', NULL, '2021-03-14 01:03:00', b'0');
-INSERT INTO `inf_job_log` VALUES (329, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:04:00', '2021-03-14 01:04:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:04:00', NULL, '2021-03-14 01:04:00', b'0');
-INSERT INTO `inf_job_log` VALUES (330, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:05:00', '2021-03-14 01:05:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:05:00', NULL, '2021-03-14 01:05:00', b'0');
-INSERT INTO `inf_job_log` VALUES (331, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:06:00', '2021-03-14 01:06:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:06:00', NULL, '2021-03-14 01:06:00', b'0');
-INSERT INTO `inf_job_log` VALUES (332, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:07:00', '2021-03-14 01:07:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:07:00', NULL, '2021-03-14 01:07:00', b'0');
-INSERT INTO `inf_job_log` VALUES (333, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:08:00', '2021-03-14 01:08:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:08:00', NULL, '2021-03-14 01:08:00', b'0');
-INSERT INTO `inf_job_log` VALUES (334, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:09:00', '2021-03-14 01:09:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:09:00', NULL, '2021-03-14 01:09:00', b'0');
-INSERT INTO `inf_job_log` VALUES (335, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:10:00', '2021-03-14 01:10:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:10:00', NULL, '2021-03-14 01:10:00', b'0');
-INSERT INTO `inf_job_log` VALUES (336, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:11:00', '2021-03-14 01:11:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:11:00', NULL, '2021-03-14 01:11:00', b'0');
-INSERT INTO `inf_job_log` VALUES (337, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:12:00', '2021-03-14 01:12:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:12:00', NULL, '2021-03-14 01:12:00', b'0');
-INSERT INTO `inf_job_log` VALUES (338, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:13:00', '2021-03-14 01:13:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:13:00', NULL, '2021-03-14 01:13:00', b'0');
-INSERT INTO `inf_job_log` VALUES (339, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:14:00', '2021-03-14 01:14:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:14:00', NULL, '2021-03-14 01:14:00', b'0');
-INSERT INTO `inf_job_log` VALUES (340, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:15:00', '2021-03-14 01:15:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:15:00', NULL, '2021-03-14 01:15:00', b'0');
-INSERT INTO `inf_job_log` VALUES (341, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:16:00', '2021-03-14 01:16:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:16:00', NULL, '2021-03-14 01:16:00', b'0');
-INSERT INTO `inf_job_log` VALUES (342, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:17:00', '2021-03-14 01:17:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:17:00', NULL, '2021-03-14 01:17:00', b'0');
-INSERT INTO `inf_job_log` VALUES (343, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:18:00', '2021-03-14 01:18:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:18:00', NULL, '2021-03-14 01:18:00', b'0');
-INSERT INTO `inf_job_log` VALUES (344, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:19:00', '2021-03-14 01:19:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:19:00', NULL, '2021-03-14 01:19:00', b'0');
-INSERT INTO `inf_job_log` VALUES (345, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:20:00', '2021-03-14 01:20:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:20:00', NULL, '2021-03-14 01:20:00', b'0');
-INSERT INTO `inf_job_log` VALUES (346, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:21:00', '2021-03-14 01:21:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:21:00', NULL, '2021-03-14 01:21:00', b'0');
-INSERT INTO `inf_job_log` VALUES (347, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:22:00', '2021-03-14 01:22:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:22:00', NULL, '2021-03-14 01:22:00', b'0');
-INSERT INTO `inf_job_log` VALUES (348, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:23:00', '2021-03-14 01:23:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:23:00', NULL, '2021-03-14 01:23:00', b'0');
-INSERT INTO `inf_job_log` VALUES (349, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:24:00', '2021-03-14 01:24:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:24:00', NULL, '2021-03-14 01:24:00', b'0');
-INSERT INTO `inf_job_log` VALUES (350, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:25:00', '2021-03-14 01:25:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:25:00', NULL, '2021-03-14 01:25:00', b'0');
-INSERT INTO `inf_job_log` VALUES (351, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:26:00', '2021-03-14 01:26:00', 16, 1, '移除在线会话数量为 1 个', NULL, '2021-03-14 01:26:00', NULL, '2021-03-14 01:26:00', b'0');
-INSERT INTO `inf_job_log` VALUES (352, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:27:00', '2021-03-14 01:27:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:27:00', NULL, '2021-03-14 01:27:00', b'0');
-INSERT INTO `inf_job_log` VALUES (353, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:28:00', '2021-03-14 01:28:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:28:00', NULL, '2021-03-14 01:28:00', b'0');
-INSERT INTO `inf_job_log` VALUES (354, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:29:00', '2021-03-14 01:29:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:29:00', NULL, '2021-03-14 01:29:00', b'0');
-INSERT INTO `inf_job_log` VALUES (355, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:30:00', '2021-03-14 01:30:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:30:00', NULL, '2021-03-14 01:30:00', b'0');
-INSERT INTO `inf_job_log` VALUES (356, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:31:00', '2021-03-14 01:31:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:31:00', NULL, '2021-03-14 01:31:00', b'0');
-INSERT INTO `inf_job_log` VALUES (357, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:32:00', '2021-03-14 01:32:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:32:00', NULL, '2021-03-14 01:32:00', b'0');
-INSERT INTO `inf_job_log` VALUES (358, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:33:00', '2021-03-14 01:33:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:33:00', NULL, '2021-03-14 01:33:00', b'0');
-INSERT INTO `inf_job_log` VALUES (359, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:34:00', '2021-03-14 01:34:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:34:00', NULL, '2021-03-14 01:34:00', b'0');
-INSERT INTO `inf_job_log` VALUES (360, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:35:00', '2021-03-14 01:35:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:35:00', NULL, '2021-03-14 01:35:00', b'0');
-INSERT INTO `inf_job_log` VALUES (361, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:36:00', '2021-03-14 01:36:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:36:00', NULL, '2021-03-14 01:36:00', b'0');
-INSERT INTO `inf_job_log` VALUES (362, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:37:00', '2021-03-14 01:37:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:37:00', NULL, '2021-03-14 01:37:00', b'0');
-INSERT INTO `inf_job_log` VALUES (363, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:38:00', '2021-03-14 01:38:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:38:00', NULL, '2021-03-14 01:38:00', b'0');
-INSERT INTO `inf_job_log` VALUES (364, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:39:00', '2021-03-14 01:39:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:39:00', NULL, '2021-03-14 01:39:00', b'0');
-INSERT INTO `inf_job_log` VALUES (365, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:40:00', '2021-03-14 01:40:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:40:00', NULL, '2021-03-14 01:40:00', b'0');
-INSERT INTO `inf_job_log` VALUES (366, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 01:41:00', '2021-03-14 01:41:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 01:41:00', NULL, '2021-03-14 01:41:00', b'0');
-INSERT INTO `inf_job_log` VALUES (367, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 02:30:57', '2021-03-14 02:30:57', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 02:30:57', NULL, '2021-03-14 02:30:57', b'0');
-INSERT INTO `inf_job_log` VALUES (368, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 02:31:00', '2021-03-14 02:31:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 02:31:00', NULL, '2021-03-14 02:31:00', b'0');
-INSERT INTO `inf_job_log` VALUES (369, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 02:32:00', '2021-03-14 02:32:00', 32, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 02:32:00', NULL, '2021-03-14 02:32:00', b'0');
-INSERT INTO `inf_job_log` VALUES (370, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 02:33:00', '2021-03-14 02:33:00', 18, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 02:33:00', NULL, '2021-03-14 02:33:00', b'0');
-INSERT INTO `inf_job_log` VALUES (371, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 02:34:00', '2021-03-14 02:34:00', 18, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 02:34:00', NULL, '2021-03-14 02:34:00', b'0');
-INSERT INTO `inf_job_log` VALUES (372, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 06:25:17', '2021-03-14 06:25:17', 37, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 06:25:17', NULL, '2021-03-14 06:25:17', b'0');
-INSERT INTO `inf_job_log` VALUES (373, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 06:26:00', '2021-03-14 06:26:00', 18, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 06:26:00', NULL, '2021-03-14 06:26:00', b'0');
-INSERT INTO `inf_job_log` VALUES (374, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 06:27:00', '2021-03-14 06:27:00', 17, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 06:27:00', NULL, '2021-03-14 06:27:00', b'0');
-INSERT INTO `inf_job_log` VALUES (375, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 06:28:00', '2021-03-14 06:28:00', 17, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 06:28:00', NULL, '2021-03-14 06:28:00', b'0');
-INSERT INTO `inf_job_log` VALUES (376, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 07:06:09', '2021-03-14 07:06:09', 36, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 07:06:09', NULL, '2021-03-14 07:06:09', b'0');
-INSERT INTO `inf_job_log` VALUES (377, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 07:52:11', '2021-03-14 07:52:11', 32, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 07:52:11', NULL, '2021-03-14 07:52:11', b'0');
-INSERT INTO `inf_job_log` VALUES (378, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:00:55', '2021-03-14 10:00:55', 41, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:00:55', NULL, '2021-03-14 10:00:55', b'0');
-INSERT INTO `inf_job_log` VALUES (379, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:01:00', '2021-03-14 10:01:00', 17, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:01:00', NULL, '2021-03-14 10:01:00', b'0');
-INSERT INTO `inf_job_log` VALUES (380, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:02:00', '2021-03-14 10:02:00', 16, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:02:00', NULL, '2021-03-14 10:02:00', b'0');
-INSERT INTO `inf_job_log` VALUES (381, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:03:00', '2021-03-14 10:03:00', 16, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:03:00', NULL, '2021-03-14 10:03:00', b'0');
-INSERT INTO `inf_job_log` VALUES (382, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:04:00', '2021-03-14 10:04:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:04:00', NULL, '2021-03-14 10:04:00', b'0');
-INSERT INTO `inf_job_log` VALUES (383, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:05:00', '2021-03-14 10:05:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:05:00', NULL, '2021-03-14 10:05:00', b'0');
-INSERT INTO `inf_job_log` VALUES (384, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:06:00', '2021-03-14 10:06:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:06:00', NULL, '2021-03-14 10:06:00', b'0');
-INSERT INTO `inf_job_log` VALUES (385, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:07:00', '2021-03-14 10:07:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:07:00', NULL, '2021-03-14 10:07:00', b'0');
-INSERT INTO `inf_job_log` VALUES (386, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:08:00', '2021-03-14 10:08:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:08:00', NULL, '2021-03-14 10:08:00', b'0');
-INSERT INTO `inf_job_log` VALUES (387, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:09:00', '2021-03-14 10:09:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:09:00', NULL, '2021-03-14 10:09:00', b'0');
-INSERT INTO `inf_job_log` VALUES (388, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:10:00', '2021-03-14 10:10:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:10:00', NULL, '2021-03-14 10:10:00', b'0');
-INSERT INTO `inf_job_log` VALUES (389, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:11:00', '2021-03-14 10:11:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:11:00', NULL, '2021-03-14 10:11:00', b'0');
-INSERT INTO `inf_job_log` VALUES (390, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:12:00', '2021-03-14 10:12:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:12:00', NULL, '2021-03-14 10:12:00', b'0');
-INSERT INTO `inf_job_log` VALUES (391, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:13:00', '2021-03-14 10:13:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:13:00', NULL, '2021-03-14 10:13:00', b'0');
-INSERT INTO `inf_job_log` VALUES (392, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:14:00', '2021-03-14 10:14:00', 17, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:14:00', NULL, '2021-03-14 10:14:00', b'0');
-INSERT INTO `inf_job_log` VALUES (393, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:15:00', '2021-03-14 10:15:00', 15, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:15:00', NULL, '2021-03-14 10:15:00', b'0');
-INSERT INTO `inf_job_log` VALUES (394, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:16:00', '2021-03-14 10:16:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:16:00', NULL, '2021-03-14 10:16:00', b'0');
-INSERT INTO `inf_job_log` VALUES (395, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:17:00', '2021-03-14 10:17:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:17:00', NULL, '2021-03-14 10:17:00', b'0');
-INSERT INTO `inf_job_log` VALUES (396, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:18:00', '2021-03-14 10:18:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:18:00', NULL, '2021-03-14 10:18:00', b'0');
-INSERT INTO `inf_job_log` VALUES (397, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:19:00', '2021-03-14 10:19:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:19:00', NULL, '2021-03-14 10:19:00', b'0');
-INSERT INTO `inf_job_log` VALUES (398, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:20:00', '2021-03-14 10:20:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:20:00', NULL, '2021-03-14 10:20:00', b'0');
-INSERT INTO `inf_job_log` VALUES (399, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:21:00', '2021-03-14 10:21:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:21:00', NULL, '2021-03-14 10:21:00', b'0');
-INSERT INTO `inf_job_log` VALUES (400, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:22:00', '2021-03-14 10:22:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:22:00', NULL, '2021-03-14 10:22:00', b'0');
-INSERT INTO `inf_job_log` VALUES (401, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:23:00', '2021-03-14 10:23:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:23:00', NULL, '2021-03-14 10:23:00', b'0');
-INSERT INTO `inf_job_log` VALUES (402, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:24:00', '2021-03-14 10:24:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:24:00', NULL, '2021-03-14 10:24:00', b'0');
-INSERT INTO `inf_job_log` VALUES (403, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:25:00', '2021-03-14 10:25:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:25:00', NULL, '2021-03-14 10:25:00', b'0');
-INSERT INTO `inf_job_log` VALUES (404, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:26:00', '2021-03-14 10:26:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:26:00', NULL, '2021-03-14 10:26:00', b'0');
-INSERT INTO `inf_job_log` VALUES (405, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:27:00', '2021-03-14 10:27:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:27:00', NULL, '2021-03-14 10:27:00', b'0');
-INSERT INTO `inf_job_log` VALUES (406, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:28:00', '2021-03-14 10:28:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:28:00', NULL, '2021-03-14 10:28:00', b'0');
-INSERT INTO `inf_job_log` VALUES (407, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:29:00', '2021-03-14 10:29:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:29:00', NULL, '2021-03-14 10:29:00', b'0');
-INSERT INTO `inf_job_log` VALUES (408, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:30:00', '2021-03-14 10:30:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:30:00', NULL, '2021-03-14 10:30:00', b'0');
-INSERT INTO `inf_job_log` VALUES (409, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:31:00', '2021-03-14 10:31:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:31:00', NULL, '2021-03-14 10:31:00', b'0');
-INSERT INTO `inf_job_log` VALUES (410, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:32:00', '2021-03-14 10:32:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:32:00', NULL, '2021-03-14 10:32:00', b'0');
-INSERT INTO `inf_job_log` VALUES (411, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:33:00', '2021-03-14 10:33:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:33:00', NULL, '2021-03-14 10:33:00', b'0');
-INSERT INTO `inf_job_log` VALUES (412, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:34:00', '2021-03-14 10:34:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:34:00', NULL, '2021-03-14 10:34:00', b'0');
-INSERT INTO `inf_job_log` VALUES (413, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:35:00', '2021-03-14 10:35:00', 13, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:35:00', NULL, '2021-03-14 10:35:00', b'0');
-INSERT INTO `inf_job_log` VALUES (414, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:36:00', '2021-03-14 10:36:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:36:00', NULL, '2021-03-14 10:36:00', b'0');
-INSERT INTO `inf_job_log` VALUES (415, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:37:00', '2021-03-14 10:37:00', 11, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:37:00', NULL, '2021-03-14 10:37:00', b'0');
-INSERT INTO `inf_job_log` VALUES (416, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:38:00', '2021-03-14 10:38:00', 10, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:38:00', NULL, '2021-03-14 10:38:00', b'0');
-INSERT INTO `inf_job_log` VALUES (417, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:39:00', '2021-03-14 10:39:00', 12, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:39:00', NULL, '2021-03-14 10:39:00', b'0');
-INSERT INTO `inf_job_log` VALUES (418, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:40:00', '2021-03-14 10:40:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:40:00', NULL, '2021-03-14 10:40:00', b'0');
-INSERT INTO `inf_job_log` VALUES (419, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:41:00', '2021-03-14 10:41:00', 14, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:41:00', NULL, '2021-03-14 10:41:00', b'0');
-INSERT INTO `inf_job_log` VALUES (420, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:42:00', '2021-03-14 10:42:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:42:00', NULL, '2021-03-14 10:42:00', b'0');
-INSERT INTO `inf_job_log` VALUES (421, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:43:00', '2021-03-14 10:43:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:43:00', NULL, '2021-03-14 10:43:00', b'0');
-INSERT INTO `inf_job_log` VALUES (422, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:44:00', '2021-03-14 10:44:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:44:00', NULL, '2021-03-14 10:44:00', b'0');
-INSERT INTO `inf_job_log` VALUES (423, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:45:00', '2021-03-14 10:45:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:45:00', NULL, '2021-03-14 10:45:00', b'0');
-INSERT INTO `inf_job_log` VALUES (424, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:46:00', '2021-03-14 10:46:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:46:00', NULL, '2021-03-14 10:46:00', b'0');
-INSERT INTO `inf_job_log` VALUES (425, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:47:00', '2021-03-14 10:47:00', 7, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:47:00', NULL, '2021-03-14 10:47:00', b'0');
-INSERT INTO `inf_job_log` VALUES (426, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:48:00', '2021-03-14 10:48:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:48:00', NULL, '2021-03-14 10:48:00', b'0');
-INSERT INTO `inf_job_log` VALUES (427, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:49:00', '2021-03-14 10:49:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:49:00', NULL, '2021-03-14 10:49:00', b'0');
-INSERT INTO `inf_job_log` VALUES (428, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:50:00', '2021-03-14 10:50:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:50:00', NULL, '2021-03-14 10:50:00', b'0');
-INSERT INTO `inf_job_log` VALUES (429, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:51:00', '2021-03-14 10:51:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:51:00', NULL, '2021-03-14 10:51:00', b'0');
-INSERT INTO `inf_job_log` VALUES (430, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:52:00', '2021-03-14 10:52:00', 6, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:52:00', NULL, '2021-03-14 10:52:00', b'0');
-INSERT INTO `inf_job_log` VALUES (431, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:53:00', '2021-03-14 10:53:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:53:00', NULL, '2021-03-14 10:53:00', b'0');
-INSERT INTO `inf_job_log` VALUES (432, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:54:00', '2021-03-14 10:54:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:54:00', NULL, '2021-03-14 10:54:00', b'0');
-INSERT INTO `inf_job_log` VALUES (433, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:55:00', '2021-03-14 10:55:00', 5, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:55:00', NULL, '2021-03-14 10:55:00', b'0');
-INSERT INTO `inf_job_log` VALUES (434, 3, 'sysUserSessionTimeoutJob', NULL, 1, '2021-03-14 10:56:00', '2021-03-14 10:56:00', 4, 1, '移除在线会话数量为 0 个', NULL, '2021-03-14 10:56:00', NULL, '2021-03-14 10:56:00', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -528,7 +235,7 @@ CREATE TABLE `sys_dept` (
 -- ----------------------------
 BEGIN;
 INSERT INTO `sys_dept` VALUES (100, '芋道源码', 0, 0, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-01-06 19:45:52', b'0');
-INSERT INTO `sys_dept` VALUES (101, '深圳总公司', 100, 1, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
+INSERT INTO `sys_dept` VALUES (101, '深圳总公司', 100, 1, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2021-03-14 20:26:18', b'0');
 INSERT INTO `sys_dept` VALUES (102, '长沙分公司', 100, 2, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
 INSERT INTO `sys_dept` VALUES (103, '研发部门', 101, 1, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
 INSERT INTO `sys_dept` VALUES (104, '市场部门', 101, 2, '若依', '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
@@ -679,16 +386,12 @@ CREATE TABLE `sys_login_log` (
   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
+) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
 
 -- ----------------------------
 -- Records of sys_login_log
 -- ----------------------------
 BEGIN;
-INSERT INTO `sys_login_log` VALUES (6, 201, 'f15eab42-8dc9-4da8-b231-3d3c6df5e0a6', 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 00:31:13', NULL, '2021-03-14 00:31:13', b'0');
-INSERT INTO `sys_login_log` VALUES (7, 100, '65d43b8b-9e34-45f7-9925-67e64266de11', 'admin', 31, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 00:31:39', NULL, '2021-03-14 00:31:39', b'0');
-INSERT INTO `sys_login_log` VALUES (8, 100, 'fe66aec6-4196-43dd-8653-7f06d0bdaf7d', 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 00:31:43', NULL, '2021-03-14 00:31:43', b'0');
-INSERT INTO `sys_login_log` VALUES (9, 201, '2b1a614d-1073-48b9-9bf3-502382af432c', 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 01:26:00', NULL, '2021-03-14 01:26:00', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -723,13 +426,13 @@ INSERT INTO `sys_menu` VALUES (2, '基础设施', '', 1, 2, 0, '/infra', 'monito
 INSERT INTO `sys_menu` VALUES (3, '研发工具', '', 1, 3, 0, '/tool', 'tool', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 12:44:42', b'0');
 INSERT INTO `sys_menu` VALUES (4, '若依官网', '', 1, 4, 0, 'http://ruoyi.vip', 'guide', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 21:54:28', b'1');
 INSERT INTO `sys_menu` VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'user', 'system/user/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (101, '角色管理', 'system:role:list', 2, 2, 1, 'role', 'peoples', 'system/role/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (102, '菜单管理', 'system:menu:list', 2, 3, 1, 'menu', 'tree-table', 'system/menu/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (103, '部门管理', 'system:dept:list', 2, 4, 1, 'dept', 'tree', 'system/dept/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (104, '岗位管理', 'system:post:list', 2, 5, 1, 'post', 'post', 'system/post/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (105, '字典管理', 'system:dict:list', 2, 6, 1, 'dict', 'dict', 'system/dict/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
+INSERT INTO `sys_menu` VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'peoples', 'system/role/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:49', b'0');
+INSERT INTO `sys_menu` VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'tree-table', 'system/menu/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:28', b'0');
+INSERT INTO `sys_menu` VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'tree', 'system/dept/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:19', b'0');
+INSERT INTO `sys_menu` VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'post', 'system/post/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:23', b'0');
+INSERT INTO `sys_menu` VALUES (105, '字典管理', '', 2, 6, 1, 'dict', 'dict', 'system/dict/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:16:58', b'0');
 INSERT INTO `sys_menu` VALUES (106, '配置管理', '', 2, 1, 2, 'config', 'edit', 'infra/config/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:10', b'0');
-INSERT INTO `sys_menu` VALUES (107, '通知公告', 'system:notice:list', 2, 8, 1, 'notice', 'message', 'system/notice/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
+INSERT INTO `sys_menu` VALUES (107, '通知公告', '', 2, 8, 1, 'notice', 'message', 'system/notice/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:39', b'0');
 INSERT INTO `sys_menu` VALUES (108, '日志管理', '', 1, 9, 1, 'log', 'log', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:34:28', b'0');
 INSERT INTO `sys_menu` VALUES (109, '在线用户', 'system:user-session:list', 2, 10, 1, 'user-session', 'online', 'system/session/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:21:20', b'0');
 INSERT INTO `sys_menu` VALUES (110, '定时任务', '', 2, 2, 2, 'job', 'job', 'infra/job/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:25:51', b'0');
@@ -739,37 +442,37 @@ INSERT INTO `sys_menu` VALUES (113, 'Redis 监控', '', 2, 5, 2, 'redis', 'redis
 INSERT INTO `sys_menu` VALUES (114, '表单构建', 'tool:build:list', 2, 1, 3, 'build', 'build', 'tool/build/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
 INSERT INTO `sys_menu` VALUES (115, '代码生成', 'tool:codegen:query', 2, 0, 3, 'codegen', 'code', 'tool/codegen/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-06 03:43:14', b'0');
 INSERT INTO `sys_menu` VALUES (116, '系统接口', 'tool:swagger:list', 2, 3, 3, 'swagger', 'swagger', 'tool/swagger/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0');
-INSERT INTO `sys_menu` VALUES (500, '操作日志', 'system:operate-log:list', 2, 1, 108, 'operate-log', 'form', 'system/operatelog/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:25:45', b'0');
-INSERT INTO `sys_menu` VALUES (501, '登录日志', 'system:login-log:list', 2, 2, 108, 'login-log', 'logininfor', 'system/loginlog/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:58', b'0');
+INSERT INTO `sys_menu` VALUES (500, '操作日志', '', 2, 1, 108, 'operate-log', 'form', 'system/operatelog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:42:56', b'0');
+INSERT INTO `sys_menu` VALUES (501, '登录日志', '', 2, 2, 108, 'login-log', 'logininfor', 'system/loginlog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:39:23', b'0');
 INSERT INTO `sys_menu` VALUES (1001, '用户查询', 'system:user:query', 3, 1, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1002, '用户新增', 'system:user:add', 3, 2, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1003, '用户修改', 'system:user:edit', 3, 3, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1004, '用户删除', 'system:user:remove', 3, 4, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1002, '用户新增', 'system:user:create', 3, 2, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:47', b'0');
+INSERT INTO `sys_menu` VALUES (1003, '用户修改', 'system:user:update', 3, 3, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:54', b'0');
+INSERT INTO `sys_menu` VALUES (1004, '用户删除', 'system:user:delete', 3, 4, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:22:03', b'0');
 INSERT INTO `sys_menu` VALUES (1005, '用户导出', 'system:user:export', 3, 5, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
 INSERT INTO `sys_menu` VALUES (1006, '用户导入', 'system:user:import', 3, 6, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1007, '重置密码', 'system:user:resetPwd', 3, 7, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1007, '重置密码', 'system:user:update-password', 3, 7, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:20:55', b'0');
 INSERT INTO `sys_menu` VALUES (1008, '角色查询', 'system:role:query', 3, 1, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1009, '角色新增', 'system:role:add', 3, 2, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1010, '角色修改', 'system:role:edit', 3, 3, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1011, '角色删除', 'system:role:remove', 3, 4, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1009, '角色新增', 'system:role:create', 3, 2, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:24', b'0');
+INSERT INTO `sys_menu` VALUES (1010, '角色修改', 'system:role:update', 3, 3, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:14', b'0');
+INSERT INTO `sys_menu` VALUES (1011, '角色删除', 'system:role:delete', 3, 4, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:05', b'0');
 INSERT INTO `sys_menu` VALUES (1012, '角色导出', 'system:role:export', 3, 5, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
 INSERT INTO `sys_menu` VALUES (1013, '菜单查询', 'system:menu:query', 3, 1, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1014, '菜单新增', 'system:menu:add', 3, 2, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1015, '菜单修改', 'system:menu:edit', 3, 3, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1016, '菜单删除', 'system:menu:remove', 3, 4, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1014, '菜单新增', 'system:menu:create', 3, 2, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:36', b'0');
+INSERT INTO `sys_menu` VALUES (1015, '菜单修改', 'system:menu:update', 3, 3, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:30', b'0');
+INSERT INTO `sys_menu` VALUES (1016, '菜单删除', 'system:menu:delete', 3, 4, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:45', b'0');
 INSERT INTO `sys_menu` VALUES (1017, '部门查询', 'system:dept:query', 3, 1, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1018, '部门新增', 'system:dept:add', 3, 2, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1019, '部门修改', 'system:dept:edit', 3, 3, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1020, '部门删除', 'system:dept:remove', 3, 4, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1018, '部门新增', 'system:dept:create', 3, 2, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:30', b'0');
+INSERT INTO `sys_menu` VALUES (1019, '部门修改', 'system:dept:update', 3, 3, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:37', b'0');
+INSERT INTO `sys_menu` VALUES (1020, '部门删除', 'system:dept:delete', 3, 4, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:43', b'0');
 INSERT INTO `sys_menu` VALUES (1021, '岗位查询', 'system:post:query', 3, 1, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1022, '岗位新增', 'system:post:add', 3, 2, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1023, '岗位修改', 'system:post:edit', 3, 3, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1024, '岗位删除', 'system:post:remove', 3, 4, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1022, '岗位新增', 'system:post:create', 3, 2, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:34', b'0');
+INSERT INTO `sys_menu` VALUES (1023, '岗位修改', 'system:post:update', 3, 3, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:41', b'0');
+INSERT INTO `sys_menu` VALUES (1024, '岗位删除', 'system:post:delete', 3, 4, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:48', b'0');
 INSERT INTO `sys_menu` VALUES (1025, '岗位导出', 'system:post:export', 3, 5, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
 INSERT INTO `sys_menu` VALUES (1026, '字典查询', 'system:dict:query', 3, 1, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1027, '字典新增', 'system:dict:add', 3, 2, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1028, '字典修改', 'system:dict:edit', 3, 3, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1029, '字典删除', 'system:dict:remove', 3, 4, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1027, '字典新增', 'system:dict:create', 3, 2, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:29', b'0');
+INSERT INTO `sys_menu` VALUES (1028, '字典修改', 'system:dict:update', 3, 3, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:36', b'0');
+INSERT INTO `sys_menu` VALUES (1029, '字典删除', 'system:dict:delete', 3, 4, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:45', b'0');
 INSERT INTO `sys_menu` VALUES (1030, '字典导出', 'system:dict:export', 3, 5, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
 INSERT INTO `sys_menu` VALUES (1031, '配置查询', 'infra:config:query', 3, 1, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:00', b'0');
 INSERT INTO `sys_menu` VALUES (1032, '配置新增', 'infra:config:create', 3, 2, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:18', b'0');
@@ -777,9 +480,9 @@ INSERT INTO `sys_menu` VALUES (1033, '配置修改', 'infra:config:update', 3, 3
 INSERT INTO `sys_menu` VALUES (1034, '配置删除', 'infra:config:delete', 3, 4, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:36', b'0');
 INSERT INTO `sys_menu` VALUES (1035, '配置导出', 'infra:config:export', 3, 5, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:19', b'0');
 INSERT INTO `sys_menu` VALUES (1036, '公告查询', 'system:notice:query', 3, 1, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1037, '公告新增', 'system:notice:add', 3, 2, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1038, '公告修改', 'system:notice:edit', 3, 3, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
-INSERT INTO `sys_menu` VALUES (1039, '公告删除', 'system:notice:remove', 3, 4, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0');
+INSERT INTO `sys_menu` VALUES (1037, '公告新增', 'system:notice:create', 3, 2, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:48', b'0');
+INSERT INTO `sys_menu` VALUES (1038, '公告修改', 'system:notice:update', 3, 3, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:55', b'0');
+INSERT INTO `sys_menu` VALUES (1039, '公告删除', 'system:notice:delete', 3, 4, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:52:01', b'0');
 INSERT INTO `sys_menu` VALUES (1040, '操作查询', 'system:operate-log:query', 3, 1, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:10', b'0');
 INSERT INTO `sys_menu` VALUES (1042, '日志导出', 'system:operate-log:export', 3, 2, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:23', b'0');
 INSERT INTO `sys_menu` VALUES (1043, '登录查询', 'system:login-log:query', 3, 1, 501, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:26', b'0');
@@ -886,7 +589,7 @@ CREATE TABLE `sys_operate_log` (
   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
   PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
+) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
 
 -- ----------------------------
 -- Records of sys_operate_log
@@ -917,8 +620,8 @@ CREATE TABLE `sys_post` (
 -- Records of sys_post
 -- ----------------------------
 BEGIN;
-INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
-INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
+INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:39:03', b'0');
+INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:39:05', b'0');
 INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
 INSERT INTO `sys_post` VALUES (4, 'user', '普通员工', 4, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0');
 INSERT INTO `sys_post` VALUES (5, 'test', '测试岗位', 0, 1, '132', '', '2021-01-07 15:07:44', '', '2021-01-07 15:10:35', b'1');
@@ -952,7 +655,7 @@ CREATE TABLE `sys_role` (
 BEGIN;
 INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 12:40:20', b'0');
 INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 11:46:58', b'0');
-INSERT INTO `sys_role` VALUES (101, '测试账号', 'test', 0, 2, '[104]', 0, 2, '132', '', '2021-01-06 13:49:35', '', '2021-01-21 02:15:26', b'0');
+INSERT INTO `sys_role` VALUES (101, '测试账号', 'test', 0, 2, '[104]', 0, 2, '132', '', '2021-01-06 13:49:35', '1', '2021-03-14 22:17:20', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -1162,11 +865,11 @@ CREATE TABLE `sys_user` (
 -- Records of sys_user
 -- ----------------------------
 BEGIN;
-INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '管理员', 103, '[1]', 'ry@163.com', '15888888888', 1, 'http://127.0.0.1:8080/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-01-13 17:51:06', b'0');
+INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:8080/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '1', '2021-03-21 18:16:16', b'0');
 INSERT INTO `sys_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '测试员', 105, '[2]', 'ry@qq.com', '15666666666', 1, '', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
-INSERT INTO `sys_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 100, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '', '2021-01-13 23:53:12', b'0');
+INSERT INTO `sys_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 100, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '1', '2021-03-14 22:35:17', b'0');
 INSERT INTO `sys_user` VALUES (103, 'yuanma', '', '源码', NULL, 100, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '', NULL, '', '2021-01-13 23:50:35', '', '2021-01-13 23:50:35', b'0');
-INSERT INTO `sys_user` VALUES (104, 'test', '$2a$10$wTJ.1LVmhxcujss2NR2SMeBo8AaFsjkoDfDafHYsdHmitAiwmnvce', '测试号', NULL, 100, '[]', '', '15601691200', 1, '', 0, '', NULL, '', '2021-01-21 02:13:53', '', '2021-01-21 02:14:13', b'0');
+INSERT INTO `sys_user` VALUES (104, 'test', '$2a$10$.TOFpaIiI3PzEwkGrNq0Eu6Cc3rOqJMxTb1DqeSEM8StxaGPBRKoi', '测试号', NULL, 100, '[]', '', '15601691200', 1, '', 0, '', NULL, '', '2021-01-21 02:13:53', '1', '2021-03-14 22:36:38', b'0');
 COMMIT;
 
 -- ----------------------------
@@ -1224,6 +927,10 @@ BEGIN;
 INSERT INTO `sys_user_session` VALUES ('505b4e7d8b0d4b40aa23bf540da81234', 1, '2021-03-14 01:25:13', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 00:31:43', NULL, '2021-03-13 07:35:26', b'1');
 INSERT INTO `sys_user_session` VALUES ('5a7248bf87d14e7e9f0578b05969986c', 1, '2021-03-13 10:42:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-13 09:37:36', NULL, '2021-03-12 19:53:07', b'1');
 INSERT INTO `sys_user_session` VALUES ('9ae27346d8b7491aad1385f51e8aa196', 1, '2021-03-13 14:02:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-13 10:43:06', NULL, '2021-03-13 06:40:35', b'1');
+INSERT INTO `sys_user_session` VALUES ('ae9ee7452ee54e4b983d658188c15c4d', 1, '2021-03-14 21:32:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 20:25:00', NULL, '2021-03-13 15:19:10', b'1');
+INSERT INTO `sys_user_session` VALUES ('d0adf48f82914212b947e5ab04d9fb65', 1, '2021-03-21 19:16:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 18:13:37', NULL, '2021-03-21 18:46:28', b'0');
+INSERT INTO `sys_user_session` VALUES ('e8872f5192584440a548641b83c877ef', 1, '2021-03-21 18:36:01', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 17:51:48', NULL, '2021-03-15 03:54:20', b'1');
+INSERT INTO `sys_user_session` VALUES ('f1ab99b09b5a475795579ff99d60ac78', 1, '2021-03-14 23:04:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 21:12:44', NULL, '2021-03-15 03:32:38', b'1');
 INSERT INTO `sys_user_session` VALUES ('f853b50d064340a581e9a49bba9411fc', 1, '2021-03-10 01:55:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-10 01:11:53', NULL, '2021-03-12 18:37:05', b'1');
 COMMIT;
 

+ 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) {

+ 68 - 0
src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java

@@ -1,14 +1,21 @@
 package cn.iocoder.dashboard.framework.redis.config;
 
+import cn.hutool.system.SystemUtil;
 import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener;
+import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.stream.Consumer;
+import org.springframework.data.redis.connection.stream.ObjectRecord;
+import org.springframework.data.redis.connection.stream.ReadOffset;
+import org.springframework.data.redis.connection.stream.StreamOffset;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.listener.ChannelTopic;
 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
 import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.stream.StreamMessageListenerContainer;
 
 import java.util.List;
 
@@ -19,6 +26,9 @@ import java.util.List;
 @Slf4j
 public class RedisConfig {
 
+    /**
+     * 创建 RedisTemplate Bean,使用 JSON 序列化方式
+     */
     @Bean
     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
         // 创建 RedisTemplate 对象
@@ -27,11 +37,16 @@ public class RedisConfig {
         template.setConnectionFactory(factory);
         // 使用 String 序列化方式,序列化 KEY 。
         template.setKeySerializer(RedisSerializer.string());
+        template.setHashKeySerializer(RedisSerializer.string());
         // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
         template.setValueSerializer(RedisSerializer.json());
+        template.setHashValueSerializer(RedisSerializer.json());
         return template;
     }
 
+    /**
+     * 创建 Redis Pub/Sub 广播消费的容器
+     */
     @Bean
     public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory factory,
                                                                        List<AbstractChannelMessageListener<?>> listeners) {
@@ -48,4 +63,57 @@ public class RedisConfig {
         return container;
     }
 
+    /**
+     * 创建 Redis Stream 集群消费的容器
+     *
+     * Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html
+     */
+    @Bean(initMethod = "start", destroyMethod = "stop")
+    public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(RedisTemplate<String, Object> redisTemplate,
+                                                                                                                    List<AbstractStreamMessageListener<?>> listeners) {
+        // 第一步,创建 StreamMessageListenerContainer 容器
+        // 创建 options 配置
+        StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
+                StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
+                        .batchSize(10) // 一次性最多拉取多少条消息
+                        .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化
+                        .build();
+        // 创建 container 对象
+        StreamMessageListenerContainer<String, ObjectRecord<String, String>> container = StreamMessageListenerContainer.create(
+                redisTemplate.getRequiredConnectionFactory(), containerOptions);
+
+        // 第二步,注册监听器,消费对应的 Stream 主题
+        String consumerName = buildConsumerName();
+//        String consumerName = "110";
+        listeners.forEach(listener -> {
+            // 创建 listener 对应的消费者分组
+            try {
+                redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup());
+            } catch (Exception ignore) {}
+            // 设置 listener 对应的 redisTemplate
+            listener.setRedisTemplate(redisTemplate);
+            // 创建 Consumer 对象
+            Consumer consumer = Consumer.from(listener.getGroup(), consumerName);
+            // 设置 Consumer 消费进度,以最小消费进度为准
+            StreamOffset<String> streamOffset = StreamOffset.create(listener.getStreamKey(), ReadOffset.lastConsumed());
+            // 设置 Consumer 监听
+            StreamMessageListenerContainer.StreamReadRequestBuilder<String> builder = StreamMessageListenerContainer.StreamReadRequest
+                    .builder(streamOffset).consumer(consumer)
+                    .autoAcknowledge(false) // 不自动 ack
+                    .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false
+            container.register(builder.build(), listener);
+        });
+        return container;
+    }
+
+    /**
+     * 构建消费者名字,使用本地 IP + 进程编号的方式。
+     * 参考自 RocketMQ clientId 的实现
+     *
+     * @return 消费者名字
+     */
+    private static String buildConsumerName() {
+        return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
+    }
+
 }

+ 5 - 16
src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/AbstractChannelMessageListener.java

@@ -1,11 +1,10 @@
 package cn.iocoder.dashboard.framework.redis.core.pubsub;
 
-import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.TypeUtil;
 import cn.iocoder.dashboard.util.json.JsonUtils;
 import lombok.SneakyThrows;
 import org.springframework.data.redis.connection.Message;
 import org.springframework.data.redis.connection.MessageListener;
-import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
 
 import java.lang.reflect.Type;
 
@@ -62,21 +61,11 @@ public abstract class AbstractChannelMessageListener<T extends ChannelMessage> i
      */
     @SuppressWarnings("unchecked")
     private Class<T> getMessageClass() {
-        Class<?> targetClass = getClass();
-        while (targetClass.getSuperclass() != null) {
-            // 如果不是 AbstractMessageListener 父类,继续向上查找
-            if (targetClass.getSuperclass() != AbstractChannelMessageListener.class) {
-                targetClass = targetClass.getSuperclass();
-                continue;
-            }
-            // 如果是 AbstractMessageListener 父类,则解析泛型
-            Type[] types = ((ParameterizedTypeImpl) targetClass.getGenericSuperclass()).getActualTypeArguments();
-            if (ArrayUtil.isEmpty(types)) {
-                throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
-            }
-            return (Class<T>) types[0];
+        Type type = TypeUtil.getTypeArgument(getClass(), 0);
+        if (type == null) {
+            throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
         }
-        throw new IllegalStateException(String.format("类型(%s) 找不到 AbstractMessageListener 父类", getClass().getName()));
+        return (Class<T>) type;
     }
 
 }

+ 3 - 1
src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java

@@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 
 /**
  * Redis Channel Message 接口
+ *
+ * @author 芋道源码
  */
 public interface ChannelMessage {
 
@@ -12,7 +14,7 @@ public interface ChannelMessage {
      *
      * @return Channel
      */
-    @JsonIgnore // 必须序列化
+    @JsonIgnore // 避免序列化
     String getChannel();
 
 }

+ 88 - 0
src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/AbstractStreamMessageListener.java

@@ -0,0 +1,88 @@
+package cn.iocoder.dashboard.framework.redis.core.stream;
+
+import cn.hutool.core.util.TypeUtil;
+import cn.iocoder.dashboard.util.json.JsonUtils;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.connection.stream.ObjectRecord;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.stream.StreamListener;
+
+import java.lang.reflect.Type;
+
+/**
+ * Redis Stream 监听器抽象类,用于实现集群消费
+ *
+ * @param <T> 消息类型。一定要填写噢,不然会报错
+ *
+ * @author 芋道源码
+ */
+public abstract class AbstractStreamMessageListener<T extends StreamMessage>
+        implements StreamListener<String, ObjectRecord<String, String>> {
+
+    /**
+     * 消息类型
+     */
+    private final Class<T> messageType;
+    /**
+     * Redis Channel
+     */
+    @Getter
+    private final String streamKey;
+
+    /**
+     * Redis 消费者分组,默认使用 spring.application.name 名字
+     */
+    @Value("${spring.application.name}")
+    @Getter
+    private String group;
+    /**
+     *
+     */
+    @Setter
+    private RedisTemplate<String, ?> redisTemplate;
+
+    @SneakyThrows
+    protected AbstractStreamMessageListener() {
+        this.messageType = getMessageClass();
+        this.streamKey = messageType.newInstance().getStreamKey();
+    }
+
+    @Override
+    public void onMessage(ObjectRecord<String, String> message) {
+        // 消费消息
+        T messageObj = JsonUtils.parseObject(message.getValue(), messageType);
+        this.onMessage(messageObj);
+        // ack 消息消费完成
+        redisTemplate.opsForStream().acknowledge(group, message);
+        // TODO 芋艿:需要额外考虑以下几个点:
+        // 1. 处理异常的情况
+        // 2. 发送日志;以及事务的结合
+        // 3. 消费日志;以及通用的幂等性
+        // 4. 消费失败的重试,https://zhuanlan.zhihu.com/p/60501638
+    }
+
+    /**
+     * 处理消息
+     *
+     * @param message 消息
+     */
+    public abstract void onMessage(T message);
+
+    /**
+     * 通过解析类上的泛型,获得消息类型
+     *
+     * @return 消息类型
+     */
+    @SuppressWarnings("unchecked")
+    private Class<T> getMessageClass() {
+        Type type = TypeUtil.getTypeArgument(getClass(), 0);
+        if (type == null) {
+            throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
+        }
+        return (Class<T>) type;
+    }
+
+}

+ 20 - 0
src/main/java/cn/iocoder/dashboard/framework/redis/core/stream/StreamMessage.java

@@ -0,0 +1,20 @@
+package cn.iocoder.dashboard.framework.redis.core.stream;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * Redis Stream Message 接口
+ *
+ * @author 芋道源码
+ */
+public interface StreamMessage {
+
+    /**
+     * 获得 Redis Stream Key
+     *
+     * @return Channel
+     */
+    @JsonIgnore // 避免序列化
+    String getStreamKey();
+
+}

+ 17 - 1
src/main/java/cn/iocoder/dashboard/framework/redis/core/util/RedisMessageUtils.java

@@ -1,7 +1,10 @@
 package cn.iocoder.dashboard.framework.redis.core.util;
 
 import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage;
+import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage;
 import cn.iocoder.dashboard.util.json.JsonUtils;
+import org.springframework.data.redis.connection.stream.RecordId;
+import org.springframework.data.redis.connection.stream.StreamRecords;
 import org.springframework.data.redis.core.RedisTemplate;
 
 /**
@@ -17,8 +20,21 @@ public class RedisMessageUtils {
      * @param redisTemplate Redis 操作模板
      * @param message 消息
      */
-    public static <T extends ChannelMessage>  void sendChannelMessage(RedisTemplate<?, ?> redisTemplate, T message) {
+    public static <T extends ChannelMessage> void sendChannelMessage(RedisTemplate<?, ?> redisTemplate, T message) {
         redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message));
     }
 
+    /**
+     * 发送 Redis 消息,基于 Redis Stream 实现
+     *
+     * @param redisTemplate Redis 操作模板
+     * @param message 消息
+     * @return 消息记录的编号对象
+     */
+    public static <T extends StreamMessage> RecordId sendStreamMessage(RedisTemplate<String, ?> redisTemplate, T message) {
+        return redisTemplate.opsForStream().add(StreamRecords.newRecord()
+                .ofObject(JsonUtils.toJsonString(message)) // 设置内容
+                .withStreamKey(message.getStreamKey())); // 设置 stream key
+    }
+
 }

+ 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 芋艿:等后续优化
     }
 

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

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

+ 11 - 27
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,33 +38,19 @@ 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) {
-        PageResult<SysOperateLogDO> pageResult = operateLogService.pageOperateLog(reqVO);
+    @ApiOperation("查看操作日志分页列表")
+    @PreAuthorize("@ss.hasPermission('system:operate-log:query')")
+    public CommonResult<PageResult<SysOperateLogRespVO>> pageOperateLog(@Valid SysOperateLogPageReqVO reqVO) {
+        PageResult<SysOperateLogDO> pageResult = operateLogService.getOperateLogPage(reqVO);
 
         // 获得拼接需要的数据
         Collection<Long> userIds = CollectionUtils.convertList(pageResult.getList(), SysOperateLogDO::getUserId);
@@ -82,11 +68,10 @@ 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 {
-        List<SysOperateLogDO> list = operateLogService.listOperateLogs(reqVO);
+    public void exportOperateLog(HttpServletResponse response, @Valid SysOperateLogExportReqVO reqVO) throws IOException {
+        List<SysOperateLogDO> list = operateLogService.getOperateLogs(reqVO);
 
         // 获得拼接需要的数据
         Collection<Long> userIds = CollectionUtils.convertList(list, SysOperateLogDO::getUserId);
@@ -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);
     }
 
 }

+ 57 - 64
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,12 +44,53 @@ public class SysUserController {
     @Resource
     private SysDeptService deptService;
 
+    @PostMapping("/create")
+    @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("修改用户")
+    @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)
+    @PreAuthorize("@ss.hasPermission('system:user:delete')")
+    public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
+        userService.deleteUser(id);
+        return success(true);
+    }
+
+    @PutMapping("/update-password")
+    @ApiOperation("重置用户密码")
+    @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("修改用户状态")
+    @PreAuthorize("@ss.hasPermission('system:user:update')")
+    public CommonResult<Boolean> updateUserStatus(@Valid @RequestBody SysUserUpdateStatusReqVO reqVO) {
+        userService.updateUserStatus(reqVO.getId(), reqVO.getStatus());
+        return success(true);
+    }
+
     @GetMapping("/page")
     @ApiOperation("获得用户分页列表")
     @PreAuthorize("@ss.hasPermission('system:user:list')")
-    public CommonResult<PageResult<SysUserPageItemRespVO>> pageUsers(@Validated SysUserPageReqVO reqVO) {
+    public CommonResult<PageResult<SysUserPageItemRespVO>> getUserPage(@Valid SysUserPageReqVO reqVO) {
         // 获得用户分页列表
-        PageResult<SysUserDO> pageResult = userService.pageUsers(reqVO);
+        PageResult<SysUserDO> pageResult = userService.getUserPage(reqVO);
         if (CollUtil.isEmpty(pageResult.getList())) {
             return success(new PageResult<>(pageResult.getTotal())); // 返回空
         }
@@ -63,71 +108,22 @@ public class SysUserController {
         return success(new PageResult<>(userList, pageResult.getTotal()));
     }
 
-    /**
-     * 根据用户编号获取详细信息
-     */
     @GetMapping("/get")
     @ApiOperation("获得用户详情")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-//    @PreAuthorize("@ss.hasPermi('system:user:query')")
+    @PreAuthorize("@ss.hasPermission('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) {
-        Long id = userService.createUser(reqVO);
-        return success(id);
-    }
-
-    @ApiOperation("修改用户")
-    @PostMapping("update")
-//    @PreAuthorize("@ss.hasPermi('system:user:edit')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUser(@Validated @RequestBody SysUserUpdateReqVO reqVO) {
-        userService.updateUser(reqVO);
-        return success(true);
-    }
-
-    @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)
-    public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
-        userService.deleteUser(id);
-        return success(true);
-    }
-
-    @ApiOperation("重置用户密码")
-    @PostMapping("/update-password")
-//    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUserPassword(@Validated @RequestBody SysUserUpdatePasswordReqVO reqVO) {
-        userService.updateUserPassword(reqVO.getId(), reqVO.getPassword());
-        return success(true);
-    }
-
-    @ApiOperation("修改用户状态")
-    @PostMapping("/update-status")
-//    @PreAuthorize("@ss.hasPermi('system:user:edit')")
-//    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    public CommonResult<Boolean> updateUserStatus(@Validated @RequestBody SysUserUpdateStatusReqVO reqVO) {
-        userService.updateUserStatus(reqVO.getId(), reqVO.getStatus());
-        return success(true);
-    }
-
-    @ApiOperation("导出用户")
     @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));
     }

+ 49 - 27
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java

@@ -1,49 +1,54 @@
 package cn.iocoder.dashboard.modules.system.controller.user;
 
+import cn.hutool.core.collection.CollUtil;
 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.user.SysUserProfileRespVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO;
-import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
+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.user.SysUserConvert;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO;
 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.dept.SysDeptService;
+import cn.iocoder.dashboard.modules.system.service.dept.SysPostService;
 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.PostMapping;
-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.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 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.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_IS_EMPTY;
 
 /**
  * @author niudehua
  */
+@Api(tags = "用户个人中心")
 @RestController
 @RequestMapping("/system/user/profile")
-@Api(tags = "用户个人中心")
+@Validated
 @Slf4j
 public class SysUserProfileController {
 
     @Resource
     private SysUserService userService;
     @Resource
+    private SysDeptService deptService;
+    @Resource
+    private SysPostService postService;
+    @Resource
     private SysPermissionService permissionService;
     @Resource
     private SysRoleService roleService;
@@ -51,30 +56,47 @@ public class SysUserProfileController {
     @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.listRolesFromCache(permissionService.listUserRoleIs(userId));
-        userProfileRespVO.setRoles(CollectionUtils.convertSet(userRoles, SysUserConvert.INSTANCE::convert));
-        return success(userProfileRespVO);
+        // 获得用户基本信息
+        SysUserDO user = userService.getUser(getLoginUserId());
+        SysUserProfileRespVO resp = SysUserConvert.INSTANCE.convert03(user);
+        // 获得用户角色
+        List<SysRoleDO> userRoles = roleService.getRolesFromCache(permissionService.listUserRoleIs(user.getId()));
+        resp.setRoles(SysUserConvert.INSTANCE.convertList(userRoles));
+        // 获得部门信息
+        if (user.getDeptId() != null) {
+            SysDeptDO dept = deptService.getDept(user.getDeptId());
+            resp.setDept(SysUserConvert.INSTANCE.convert02(dept));
+        }
+        // 获得岗位信息
+        if (CollUtil.isNotEmpty(user.getPostIds())) {
+            List<SysPostDO> posts = postService.getPosts(user.getPostIds());
+            resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts));
+        }
+        return success(resp);
     }
 
-    @PostMapping("/update")
+    @PutMapping("/update")
     @ApiOperation("修改用户个人信息")
-    public CommonResult<Boolean> updateProfile(@RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) {
-        userService.updateUserProfile(reqVO);
-        SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request);
+    public CommonResult<Boolean> updateUserProfile(@Valid @RequestBody SysUserProfileUpdateReqVO reqVO) {
+        userService.updateUserProfile(getLoginUserId(), reqVO);
         return success(true);
     }
 
-    @PostMapping("/upload-avatar")
+    @PutMapping("/update-password")
+    @ApiOperation("修改用户个人密码")
+    public CommonResult<Boolean> updateUserProfilePassword(@Valid @RequestBody SysUserProfileUpdatePasswordReqVO reqVO) {
+        userService.updateUserPassword(getLoginUserId(), reqVO);
+        return success(true);
+    }
+
+    @PutMapping("/upload-avatar")
     @ApiOperation("上传用户个人头像")
-    public CommonResult<Boolean> uploadAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
+    public CommonResult<Boolean> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
         if (file.isEmpty()) {
             throw ServiceExceptionUtil.exception(FILE_IS_EMPTY);
         }
-        userService.updateAvatar(SecurityFrameworkUtils.getLoginUserId(), file.getInputStream());
+        userService.updateUserAvatar(getLoginUserId(), file.getInputStream());
         return success(true);
     }
+
 }

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

@@ -0,0 +1,88 @@
+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.List;
+
+
+@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;
+
+    /**
+     * 所属角色
+     */
+    private List<Role> roles;
+
+    /**
+     * 所在部门
+     */
+    private Dept dept;
+
+    /**
+     * 所属岗位数组
+     */
+    private List<Post> posts;
+
+    @ApiModel("角色")
+    @Data
+    public static class Role {
+
+        @ApiModelProperty(value = "角色编号", required = true, example = "1")
+        private Long id;
+
+        @ApiModelProperty(value = "角色名称", required = true, example = "普通角色")
+        private String name;
+
+    }
+
+    @ApiModel("部门")
+    @Data
+    public static class Dept {
+
+        @ApiModelProperty(value = "部门编号", required = true, example = "1")
+        private Long id;
+
+        @ApiModelProperty(value = "部门名称", required = true, example = "研发部")
+        private String name;
+
+    }
+
+    @ApiModel("岗位")
+    @Data
+    public static class Post {
+
+        @ApiModelProperty(value = "岗位编号", required = true, example = "1")
+        private Long id;
+
+        @ApiModelProperty(value = "岗位名称", required = true, example = "开发")
+        private String name;
+
+    }
+
+}

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

@@ -0,0 +1,24 @@
+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;
+
+@ApiModel("用户个人中心更新密码 Request VO")
+@Data
+public class SysUserProfileUpdatePasswordReqVO {
+
+    @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;
+
+}

+ 4 - 17
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java → src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java

@@ -1,44 +1,31 @@
-package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
+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个字符")
+    @Size(max = 50, message = "邮箱长度不能超过 50 个字符")
     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 枚举类")
     private Integer sex;
 
-    @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png")
-    private String avatar;
-
-    @ApiModelProperty(value = "旧密码", required = true, example = "123456")
-    private String oldPassword;
-
-    @ApiModelProperty(value = "新密码", required = true, example = "654321")
-    private String newPassword;
-
 }

+ 3 - 3
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;
 
@@ -35,11 +36,11 @@ public class SysUserBaseVO {
 
     @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
     @Email(message = "邮箱格式不正确")
-    @Size(max = 50, message = "邮箱长度不能超过50个字符")
+    @Size(max = 50, message = "邮箱长度不能超过 50 个字符")
     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;
 
-
 }

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

@@ -1,6 +1,5 @@
 package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -18,7 +17,6 @@ public class SysUserPageItemRespVO extends SysUserRespVO {
     /**
      * 所在部门
      */
-    @JsonIgnore
     private Dept dept;
 
     @ApiModel("部门")

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

@@ -1,37 +0,0 @@
-package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
-
-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.Set;
-
-
-@ApiModel("用户个人中心信息 Response VO")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-public class SysUserProfileRespVO extends SysUserRespVO {
-
-    /**
-     * 所属角色
-     */
-    @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;
-
-    }
-}

+ 4 - 1
src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java

@@ -3,7 +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.user.SysUserProfileUpdateReqVO;
+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;
@@ -41,6 +42,8 @@ public interface SysAuthConvert {
 
     LoginUser convert(SysUserProfileUpdateReqVO reqVO);
 
+    LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO);
+
     /**
      * 将菜单列表,构建成菜单树
      *

+ 12 - 8
src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java

@@ -1,18 +1,18 @@
 package cn.iocoder.dashboard.modules.system.convert.user;
 
-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.SysUserProfileRespVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
+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.*;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO;
 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;
 
+import java.util.List;
+
 @Mapper
 public interface SysUserConvert {
 
@@ -32,10 +32,14 @@ public interface SysUserConvert {
 
     SysUserProfileRespVO convert03(SysUserDO bean);
 
-    SysUserProfileRespVO.Role convert(SysRoleDO bean);
+    List<SysUserProfileRespVO.Role> convertList(List<SysRoleDO> list);
+
+    SysUserProfileRespVO.Dept convert02(SysDeptDO bean);
 
     SysUserDO convert(SysUserProfileUpdateReqVO bean);
 
+    SysUserDO convert(SysUserProfileUpdatePasswordReqVO bean);
 
+    List<SysUserProfileRespVO.Post> convertList02(List<SysPostDO> list);
 
 }

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

@@ -4,6 +4,7 @@ import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleMenuDO;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
 
 import java.util.Collection;
 import java.util.Date;
@@ -32,10 +33,16 @@ 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 boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
-        return selectOne(new QueryWrapper<SysRoleMenuDO>().select("id")
-                .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
+    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));
+    }
+
 }

+ 17 - 0
src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/mail/SysMailSendConsumer.java

@@ -0,0 +1,17 @@
+package cn.iocoder.dashboard.modules.system.mq.consumer.mail;
+
+import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
+import cn.iocoder.dashboard.modules.system.mq.message.mail.SysMailSendMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class SysMailSendConsumer extends AbstractStreamMessageListener<SysMailSendMessage> {
+
+    @Override
+    public void onMessage(SysMailSendMessage message) {
+        log.info("[onMessage][消息内容({})]", message);
+    }
+
+}

+ 17 - 0
src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java

@@ -0,0 +1,17 @@
+package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
+
+import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
+import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+@Component
+@Slf4j
+public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
+
+    @Override
+    public void onMessage(SysSmsSendMessage message) {
+        log.info("[onMessage][消息内容({})]", message);
+    }
+
+}

+ 46 - 0
src/main/java/cn/iocoder/dashboard/modules/system/mq/message/mail/SysMailSendMessage.java

@@ -0,0 +1,46 @@
+package cn.iocoder.dashboard.modules.system.mq.message.mail;
+
+import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+/**
+ * 邮箱发送消息
+ *
+ * @author 芋道源码
+ */
+@Data
+public class SysMailSendMessage implements StreamMessage {
+
+    /**
+     * 邮箱地址
+     */
+    @NotNull(message = "邮箱地址不能为空")
+    private String address;
+    /**
+     * 短信模板编号
+     */
+    @NotNull(message = "短信模板编号不能为空")
+    private String templateCode;
+    /**
+     * 短信模板参数
+     */
+    private Map<String, Object> templateParams;
+
+    /**
+     * 用户编号,允许空
+     */
+    private Integer userId;
+    /**
+     * 用户类型,允许空
+     */
+    private Integer userType;
+
+    @Override
+    public String getStreamKey() {
+        return "system.mail.send";
+    }
+
+}

+ 46 - 0
src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java

@@ -0,0 +1,46 @@
+package cn.iocoder.dashboard.modules.system.mq.message.sms;
+
+import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+/**
+ * 短信发送消息
+ *
+ * @author 芋道源码
+ */
+@Data
+public class SysSmsSendMessage implements StreamMessage {
+
+    /**
+     * 手机号
+     */
+    @NotNull(message = "手机号不能为空")
+    private String mobile;
+    /**
+     * 短信模板编号
+     */
+    @NotNull(message = "短信模板编号不能为空")
+    private String templateCode;
+    /**
+     * 短信模板参数
+     */
+    private Map<String, Object> templateParams;
+
+    /**
+     * 用户编号,允许空
+     */
+    private Integer userId;
+    /**
+     * 用户类型,允许空
+     */
+    private Integer userType;
+
+    @Override
+    public String getStreamKey() {
+        return "system.sms.send";
+    }
+
+}

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

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

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

@@ -1,5 +1,6 @@
 package cn.iocoder.dashboard.modules.system.service.dept;
 
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExportReqVO;
@@ -11,6 +12,8 @@ import org.springframework.lang.Nullable;
 import java.util.Collection;
 import java.util.List;
 
+import static cn.iocoder.dashboard.util.collection.SetUtils.asSet;
+
 /**
  * 岗位 Service 接口
  *
@@ -19,58 +22,68 @@ import java.util.List;
 public interface SysPostService {
 
     /**
-     * 获得符合条件的岗位列表
+     * 创建岗位
      *
-     * @param ids 岗位编号数组。如果为空,不进行筛选
-     * @param statuses 状态数组。如果为空,不进行筛选
-     * @return 部门列表
+     * @param reqVO 岗位信息
+     * @return 岗位编号
      */
-    List<SysPostDO> listPosts(@Nullable Collection<Long> ids, @Nullable Collection<Integer> statuses);
+    Long createPost(SysPostCreateReqVO reqVO);
 
     /**
-     * 获得岗位分页列表
+     * 更新岗位
      *
-     * @param reqVO 分页条件
-     * @return 部门分页列表
+     * @param reqVO 岗位信息
+     */
+    void updatePost(SysPostUpdateReqVO reqVO);
+
+    /**
+     * 删除岗位信息
+     *
+     * @param id 岗位编号
      */
-    PageResult<SysPostDO> pagePosts(SysPostPageReqVO reqVO);
+    void deletePost(Long id);
 
     /**
      * 获得岗位列表
      *
-     * @param reqVO 查询条件
+     * @param ids 岗位编号数组。如果为空,不进行筛选
      * @return 部门列表
      */
-    List<SysPostDO> listPosts(SysPostExportReqVO reqVO);
+    default List<SysPostDO> getPosts(@Nullable Collection<Long> ids) {
+        return getPosts(ids, asSet(CommonStatusEnum.ENABLE.getStatus(), CommonStatusEnum.DISABLE.getStatus()));
+    }
 
     /**
-     * 获得岗位信息
+     * 获得符合条件的岗位列表
      *
-     * @param id 岗位编号
-     * @return 岗位信息
+     * @param ids 岗位编号数组。如果为空,不进行筛选
+     * @param statuses 状态数组。如果为空,不进行筛选
+     * @return 部门列表
      */
-    SysPostDO getPost(Long id);
+    List<SysPostDO> getPosts(@Nullable Collection<Long> ids, @Nullable Collection<Integer> statuses);
 
     /**
-     * 创建岗位
+     * 获得岗位分页列表
      *
-     * @param reqVO 岗位信息
-     * @return 岗位编号
+     * @param reqVO 分页条件
+     * @return 部门分页列表
      */
-    Long createPost(SysPostCreateReqVO reqVO);
+    PageResult<SysPostDO> getPostPage(SysPostPageReqVO reqVO);
 
     /**
-     * 更新岗位
+     * 获得岗位列表
      *
-     * @param reqVO 岗位信息
+     * @param reqVO 查询条件
+     * @return 部门列表
      */
-    void updatePost(SysPostUpdateReqVO reqVO);
+    List<SysPostDO> getPosts(SysPostExportReqVO reqVO);
 
     /**
-     * 删除岗位信息
+     * 获得岗位信息
      *
      * @param id 岗位编号
+     * @return 岗位信息
      */
-    void deletePost(Long id);
+    SysPostDO getPost(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/SysOperateLogService.java

@@ -19,7 +19,7 @@ public interface SysOperateLogService extends OperateLogFrameworkService {
      * @param reqVO 分页条件
      * @return 操作日志分页列表
      */
-    PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO);
+    PageResult<SysOperateLogDO> getOperateLogPage(SysOperateLogPageReqVO reqVO);
 
     /**
      * 获得操作日志列表
@@ -27,6 +27,6 @@ public interface SysOperateLogService extends OperateLogFrameworkService {
      * @param reqVO 列表条件
      * @return 日志列表
      */
-    List<SysOperateLogDO> listOperateLogs(SysOperateLogExportReqVO reqVO);
+    List<SysOperateLogDO> getOperateLogs(SysOperateLogExportReqVO reqVO);
 
 }

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

@@ -55,11 +55,11 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
     }
 
     @Override
-    public PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO) {
+    public PageResult<SysOperateLogDO> getOperateLogPage(SysOperateLogPageReqVO reqVO) {
         // 处理基于用户昵称的查询
         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();
             }
@@ -69,11 +69,11 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
     }
 
     @Override
-    public List<SysOperateLogDO> listOperateLogs(SysOperateLogExportReqVO reqVO) {
+    public List<SysOperateLogDO> getOperateLogs(SysOperateLogExportReqVO reqVO) {
         // 处理基于用户昵称的查询
         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);
 
 }

+ 45 - 46
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java

@@ -15,6 +15,7 @@ import cn.iocoder.dashboard.modules.system.redis.mq.producer.permission.SysMenuP
 import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
 import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.dashboard.util.collection.CollectionUtils;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
@@ -127,46 +128,6 @@ public class SysMenuServiceImpl implements SysMenuService {
         return menuMapper.selectList();
     }
 
-    @Override
-    public List<SysMenuDO> listMenus() {
-        return menuMapper.selectList();
-    }
-
-    @Override
-    public List<SysMenuDO> listMenus(SysMenuListReqVO reqVO) {
-        return menuMapper.selectList(reqVO);
-    }
-
-    @Override
-    public List<SysMenuDO> listMenusFromCache(Collection<Integer> menuTypes, Collection<Integer> menusStatuses) {
-        // 任一一个参数为空,则返回空
-        if (CollectionUtils.isAnyEmpty(menuTypes, menusStatuses)) {
-            return Collections.emptyList();
-        }
-        // 创建新数组,避免缓存被修改
-        return menuCache.values().stream().filter(menu -> menuTypes.contains(menu.getType())
-                && menusStatuses.contains(menu.getStatus()))
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public List<SysMenuDO> listMenusFromCache(Collection<Long> menuIds, Collection<Integer> menuTypes,
-                                              Collection<Integer> menusStatuses) {
-        // 任一一个参数为空,则返回空
-        if (CollectionUtils.isAnyEmpty(menuIds, menuTypes, menusStatuses)) {
-            return Collections.emptyList();
-        }
-        return menuCache.values().stream().filter(menu -> menuIds.contains(menu.getId())
-                && menuTypes.contains(menu.getType())
-                && menusStatuses.contains(menu.getStatus()))
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public List<SysMenuDO> getMenuListByPermissionFromCache(String permission) {
-        return new ArrayList<>(permissionMenuCache.get(permission));
-    }
-
     @Override
     public Long createMenu(SysMenuCreateReqVO reqVO) {
         // 校验父菜单存在
@@ -208,10 +169,6 @@ public class SysMenuServiceImpl implements SysMenuService {
      */
     @Transactional(rollbackFor = Exception.class)
     public void deleteMenu(Long menuId) {
-        // 校验更新的菜单是否存在
-        if (menuMapper.selectById(menuId) == null) {
-            throw ServiceExceptionUtil.exception(MENU_NOT_EXISTS);
-        }
         // 校验是否还有子菜单
         if (menuMapper.selectCountByParentId(menuId) > 0) {
             throw ServiceExceptionUtil.exception(MENU_EXISTS_CHILDREN);
@@ -235,6 +192,46 @@ public class SysMenuServiceImpl implements SysMenuService {
         });
     }
 
+    @Override
+    public List<SysMenuDO> getMenus() {
+        return menuMapper.selectList();
+    }
+
+    @Override
+    public List<SysMenuDO> getMenus(SysMenuListReqVO reqVO) {
+        return menuMapper.selectList(reqVO);
+    }
+
+    @Override
+    public List<SysMenuDO> listMenusFromCache(Collection<Integer> menuTypes, Collection<Integer> menusStatuses) {
+        // 任一一个参数为空,则返回空
+        if (CollectionUtils.isAnyEmpty(menuTypes, menusStatuses)) {
+            return Collections.emptyList();
+        }
+        // 创建新数组,避免缓存被修改
+        return menuCache.values().stream().filter(menu -> menuTypes.contains(menu.getType())
+                && menusStatuses.contains(menu.getStatus()))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<SysMenuDO> listMenusFromCache(Collection<Long> menuIds, Collection<Integer> menuTypes,
+                                              Collection<Integer> menusStatuses) {
+        // 任一一个参数为空,则返回空
+        if (CollectionUtils.isAnyEmpty(menuIds, menuTypes, menusStatuses)) {
+            return Collections.emptyList();
+        }
+        return menuCache.values().stream().filter(menu -> menuIds.contains(menu.getId())
+                && menuTypes.contains(menu.getType())
+                && menusStatuses.contains(menu.getStatus()))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<SysMenuDO> getMenuListByPermissionFromCache(String permission) {
+        return new ArrayList<>(permissionMenuCache.get(permission));
+    }
+
     @Override
     public SysMenuDO getMenu(Long id) {
         return menuMapper.selectById(id);
@@ -250,7 +247,8 @@ public class SysMenuServiceImpl implements SysMenuService {
      * @param parentId 父菜单编号
      * @param childId 当前菜单编号
      */
-    private void checkParentResource(Long parentId, Long childId) {
+    @VisibleForTesting
+    public void checkParentResource(Long parentId, Long childId) {
         if (parentId == null || MenuIdEnum.ROOT.getId().equals(parentId)) {
             return;
         }
@@ -279,7 +277,8 @@ public class SysMenuServiceImpl implements SysMenuService {
      * @param parentId 父菜单编号
      * @param id 菜单编号
      */
-    private void checkResource(Long parentId, String name, Long id) {
+    @VisibleForTesting
+    public void checkResource(Long parentId, String name, Long id) {
         SysMenuDO menu = menuMapper.selectByParentIdAndName(parentId, name);
         if (menu == null) {
             return;

+ 34 - 14
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java

@@ -86,6 +86,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
     @Override
     @PostConstruct
     public void initLocalCache() {
+        Date now = new Date();
         // 获取角色与菜单的关联列表,如果有更新
         List<SysRoleMenuDO> roleMenuList = this.loadRoleMenuIfUpdate(maxUpdateTime);
         if (CollUtil.isEmpty(roleMenuList)) {
@@ -102,7 +103,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
         roleMenuCache = roleMenuCacheBuilder.build();
         menuRoleCache = menuRoleCacheBuilder.build();
         assert roleMenuList.size() > 0; // 断言,避免告警
-        maxUpdateTime = roleMenuList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime();
+        maxUpdateTime = now;
         log.info("[initLocalCache][初始化角色与菜单的关联数量为 {}]", roleMenuList.size());
     }
 
@@ -123,7 +124,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
         if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
             log.info("[loadRoleMenuIfUpdate][首次加载全量角色与菜单的关联]");
         } else { // 判断数据库中是否有更新的角色与菜单的关联
-            if (!roleMenuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
+            if (Objects.isNull(roleMenuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime))) {
                 return null;
             }
             log.info("[loadRoleMenuIfUpdate][增量加载全量角色与菜单的关联]");
@@ -133,14 +134,14 @@ public class SysPermissionServiceImpl implements SysPermissionService {
     }
 
     @Override
-    public List<SysMenuDO> listRoleMenusFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes,
-                                                  Collection<Integer> menusStatuses) {
+    public List<SysMenuDO> getRoleMenusFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes,
+                                                 Collection<Integer> menusStatuses) {
         // 任一一个参数为空时,不返回任何菜单
         if (CollectionUtils.isAnyEmpty(roleIds, menusStatuses, menusStatuses)) {
             return Collections.emptyList();
         }
         // 判断角色是否包含管理员
-        List<SysRoleDO> roleList = roleService.listRolesFromCache(roleIds);
+        List<SysRoleDO> roleList = roleService.getRolesFromCache(roleIds);
         boolean hasAdmin = roleService.hasAnyAdmin(roleList);
         // 获得角色拥有的菜单关联
         if (hasAdmin) { // 管理员,获取到全部
@@ -168,7 +169,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
         // 如果是管理员的情况下,获取全部菜单编号
         SysRoleDO role = roleService.getRole(roleId);
         if (roleService.hasAnyAdmin(Collections.singletonList(role))) {
-            return CollectionUtils.convertSet(menuService.listMenus(), SysMenuDO::getId);
+            return CollectionUtils.convertSet(menuService.getMenus(), SysMenuDO::getId);
         }
         // 如果是非管理员的情况下,获得拥有的菜单编号
         return CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId),
@@ -231,22 +232,41 @@ public class SysPermissionServiceImpl implements SysPermissionService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void processRoleDeleted(Long roleId) {
-        // TODO 实现我
-//        // 标记删除 RoleResource
-//        roleResourceMapper.deleteByRoleId(roleId);
-//        // 标记删除 AdminRole
-//        adminRoleMapper.deleteByRoleId(roleId);
+        // 标记删除 UserRole
+        userRoleMapper.deleteListByRoleId(roleId);
+        // 标记删除 RoleMenu
+        roleMenuMapper.deleteListByRoleId(roleId);
+        // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+
+            @Override
+            public void afterCommit() {
+                permissionProducer.sendRoleMenuRefreshMessage();
+            }
+
+        });
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void processMenuDeleted(Long menuId) {
-        // TODO 实现我
+        roleMenuMapper.deleteListByMenuId(menuId);
+        // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+
+            @Override
+            public void afterCommit() {
+                permissionProducer.sendRoleMenuRefreshMessage();
+            }
+
+        });
     }
 
     @Override
     public void processUserDeleted(Long userId) {
-        // TODO 实现我
+        userRoleMapper.deleteListByUserId(userId);
     }
 
     @Override
@@ -305,7 +325,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
         if (roleService.hasAnyAdmin(roleIds)) {
             return true;
         }
-        Set<String> userRoles = CollectionUtils.convertSet(roleService.listRolesFromCache(roleIds),
+        Set<String> userRoles = CollectionUtils.convertSet(roleService.getRolesFromCache(roleIds),
                 SysRoleDO::getCode);
         return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
     }

+ 55 - 61
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java

@@ -118,33 +118,6 @@ public class SysRoleServiceImpl implements SysRoleService {
         return roleMapper.selectList();
     }
 
-    @Override
-    public SysRoleDO getRoleFromCache(Long id) {
-        return roleCache.get(id);
-    }
-
-    @Override
-    public List<SysRoleDO> listRoles(@Nullable Collection<Integer> statuses) {
-        return roleMapper.selectListByStatus(statuses);
-    }
-
-    @Override
-    public List<SysRoleDO> listRolesFromCache(Collection<Long> ids) {
-        if (CollectionUtil.isEmpty(ids)) {
-            return Collections.emptyList();
-        }
-        return roleCache.values().stream().filter(roleDO -> ids.contains(roleDO.getId()))
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public boolean hasAnyAdmin(Collection<SysRoleDO> roleList) {
-        if (CollectionUtil.isEmpty(roleList)) {
-            return false;
-        }
-        return roleList.stream().anyMatch(roleDO -> RoleCodeEnum.ADMIN.getKey().equals(roleDO.getCode()));
-    }
-
     @Override
     public Long createRole(SysRoleCreateReqVO reqVO) {
         // 校验角色
@@ -173,6 +146,33 @@ public class SysRoleServiceImpl implements SysRoleService {
         roleProducer.sendRoleRefreshMessage();
     }
 
+    @Override
+    public void updateRoleStatus(Long id, Integer status) {
+        // 校验是否可以更新
+        this.checkUpdateRole(id);
+        // 更新状态
+        SysRoleDO updateObject = new SysRoleDO();
+        updateObject.setId(id);
+        updateObject.setStatus(status);
+        roleMapper.updateById(updateObject);
+        // 发送刷新消息
+        roleProducer.sendRoleRefreshMessage();
+    }
+
+    @Override
+    public void updateRoleDataScope(Long id, Integer dataScope, Set<Long> dataScopeDeptIds) {
+        // 校验是否可以更新
+        checkUpdateRole(id);
+        // 更新数据范围
+        SysRoleDO updateObject = new SysRoleDO();
+        updateObject.setId(id);
+        updateObject.setDataScope(dataScope);
+        updateObject.setDataScopeDeptIds(dataScopeDeptIds);
+        roleMapper.updateById(updateObject);
+        // 发送刷新消息
+        roleProducer.sendRoleRefreshMessage();
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteRole(Long id) {
@@ -194,45 +194,45 @@ public class SysRoleServiceImpl implements SysRoleService {
     }
 
     @Override
-    public SysRoleDO getRole(Long id) {
-        return roleMapper.selectById(id);
+    public SysRoleDO getRoleFromCache(Long id) {
+        return roleCache.get(id);
     }
 
     @Override
-    public PageResult<SysRoleDO> pageRole(SysRolePageReqVO reqVO) {
-        return roleMapper.selectPage(reqVO);
+    public List<SysRoleDO> getRoles(@Nullable Collection<Integer> statuses) {
+        return roleMapper.selectListByStatus(statuses);
     }
 
     @Override
-    public List<SysRoleDO> listRoles(SysRoleExportReqVO reqVO) {
-        return roleMapper.listRoles(reqVO);
+    public List<SysRoleDO> getRolesFromCache(Collection<Long> ids) {
+        if (CollectionUtil.isEmpty(ids)) {
+            return Collections.emptyList();
+        }
+        return roleCache.values().stream().filter(roleDO -> ids.contains(roleDO.getId()))
+                .collect(Collectors.toList());
     }
 
     @Override
-    public void updateRoleStatus(Long id, Integer status) {
-        // 校验是否可以更新
-        this.checkUpdateRole(id);
-        // 更新状态
-        SysRoleDO updateObject = new SysRoleDO();
-        updateObject.setId(id);
-        updateObject.setStatus(status);
-        roleMapper.updateById(updateObject);
-        // 发送刷新消息
-        roleProducer.sendRoleRefreshMessage();
+    public boolean hasAnyAdmin(Collection<SysRoleDO> roleList) {
+        if (CollectionUtil.isEmpty(roleList)) {
+            return false;
+        }
+        return roleList.stream().anyMatch(roleDO -> RoleCodeEnum.ADMIN.getKey().equals(roleDO.getCode()));
     }
 
     @Override
-    public void updateRoleDataScope(Long id, Integer dataScope, Set<Long> dataScopeDeptIds) {
-        // 校验是否可以更新
-        checkUpdateRole(id);
-        // 更新数据范围
-        SysRoleDO updateObject = new SysRoleDO();
-        updateObject.setId(id);
-        updateObject.setDataScope(dataScope);
-        updateObject.setDataScopeDeptIds(dataScopeDeptIds);
-        roleMapper.updateById(updateObject);
-        // 发送刷新消息
-        roleProducer.sendRoleRefreshMessage();
+    public SysRoleDO getRole(Long id) {
+        return roleMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<SysRoleDO> getRolePage(SysRolePageReqVO reqVO) {
+        return roleMapper.selectPage(reqVO);
+    }
+
+    @Override
+    public List<SysRoleDO> getRoles(SysRoleExportReqVO reqVO) {
+        return roleMapper.listRoles(reqVO);
     }
 
     /**
@@ -278,16 +278,10 @@ public class SysRoleServiceImpl implements SysRoleService {
         }
     }
 
-
-//    /**
-//     * 根据条件分页查询角色数据
-//     *
-//     * @param role 角色信息
-//     * @return 角色数据集合信息
-//     */
 //    @Override
 //    @DataScope(deptAlias = "d")
 //    public List<SysRole> selectRoleList(SysRole role) {
 //        return roleMapper.selectRoleList(role);
 //    }
+
 }

+ 71 - 97
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java

@@ -2,12 +2,13 @@ package cn.iocoder.dashboard.modules.system.service.user;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.dashboard.common.pojo.PageResult;
+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.SysUserExportReqVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportRespVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.dashboard.util.collection.CollectionUtils;
@@ -25,13 +26,75 @@ import java.util.Map;
  */
 public interface SysUserService {
 
+    /**
+     * 创建用户
+     *
+     * @param reqVO 用户信息
+     * @return 用户编号
+     */
+    Long createUser(SysUserCreateReqVO reqVO);
+
+    /**
+     * 修改用户
+     *
+     * @param reqVO 用户信息
+     */
+    void updateUser(SysUserUpdateReqVO reqVO);
+
+    /**
+     * 修改用户个人信息
+     *
+     * @param id 用户编号
+     * @param reqVO 用户个人信息
+     */
+    void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO);
+
+    /**
+     * 修改用户个人密码
+     *
+     * @param id 用户编号
+     * @param reqVO 更新用户个人密码
+     */
+    void updateUserPassword(Long id, SysUserProfileUpdatePasswordReqVO reqVO);
+
+    /**
+     * 更新用户头像
+     *
+     * @param id         用户 id
+     * @param avatarFile 头像文件
+     */
+    void updateUserAvatar(Long id, InputStream avatarFile);
+
+    /**
+     * 修改密码
+     *
+     * @param id       用户编号
+     * @param password 密码
+     */
+    void updateUserPassword(Long id, String password);
+
+    /**
+     * 修改密码
+     *
+     * @param id     用户编号
+     * @param status 状态
+     */
+    void updateUserStatus(Long id, Integer status);
+
+    /**
+     * 删除用户
+     *
+     * @param id 用户编号
+     */
+    void deleteUser(Long id);
+
     /**
      * 通过用户名查询用户
      *
      * @param username 用户名
      * @return 用户对象信息
      */
-    SysUserDO getUserByUserName(String username);
+    SysUserDO getUserByUsername(String username);
 
     /**
      * 通过用户 ID 查询用户
@@ -47,7 +110,7 @@ public interface SysUserService {
      * @param reqVO 分页条件
      * @return 分页列表
      */
-    PageResult<SysUserDO> pageUsers(SysUserPageReqVO reqVO);
+    PageResult<SysUserDO> getUserPage(SysUserPageReqVO reqVO);
 
     /**
      * 获得用户列表
@@ -55,7 +118,7 @@ public interface SysUserService {
      * @param reqVO 列表请求
      * @return 用户列表
      */
-    List<SysUserDO> listUsers(SysUserExportReqVO reqVO);
+    List<SysUserDO> getUsers(SysUserExportReqVO reqVO);
 
     /**
      * 获得用户列表
@@ -63,7 +126,7 @@ public interface SysUserService {
      * @param ids 用户编号数组
      * @return 用户列表
      */
-    List<SysUserDO> listUsers(Collection<Long> ids);
+    List<SysUserDO> getUsers(Collection<Long> ids);
 
     /**
      * 获得用户 Map
@@ -75,7 +138,7 @@ public interface SysUserService {
         if (CollUtil.isEmpty(ids)) {
             return new HashMap<>();
         }
-        return CollectionUtils.convertMap(listUsers(ids), SysUserDO::getId);
+        return CollectionUtils.convertMap(getUsers(ids), SysUserDO::getId);
     }
 
     /**
@@ -84,7 +147,7 @@ public interface SysUserService {
      * @param nickname 昵称
      * @return 用户列表
      */
-    List<SysUserDO> listUsersByNickname(String nickname);
+    List<SysUserDO> getUsersByNickname(String nickname);
 
     /**
      * 获得用户列表,基于用户账号模糊匹配
@@ -92,53 +155,7 @@ public interface SysUserService {
      * @param username 用户账号
      * @return 用户列表
      */
-    List<SysUserDO> listUsersByUsername(String username);
-
-    /**
-     * 创建用户
-     *
-     * @param reqVO 用户信息
-     * @return 用户编号
-     */
-    Long createUser(SysUserCreateReqVO reqVO);
-
-    /**
-     * 修改用户
-     *
-     * @param reqVO 用户信息
-     */
-    void updateUser(SysUserUpdateReqVO reqVO);
-
-    /**
-     * 修改用户个人信息
-     *
-     * @param reqVO 用户个人信息
-     * @return 修改结果
-     */
-    void updateUserProfile(SysUserProfileUpdateReqVO reqVO);
-
-    /**
-     * 删除用户
-     *
-     * @param id 用户编号
-     */
-    void deleteUser(Long id);
-
-    /**
-     * 修改密码
-     *
-     * @param id       用户编号
-     * @param password 密码
-     */
-    void updateUserPassword(Long id, String password);
-
-    /**
-     * 修改密码
-     *
-     * @param id     用户编号
-     * @param status 状态
-     */
-    void updateUserStatus(Long id, Integer status);
+    List<SysUserDO> getUsersByUsername(String username);
 
     /**
      * 批量导入用户
@@ -149,47 +166,4 @@ public interface SysUserService {
      */
     SysUserImportRespVO importUsers(List<SysUserImportExcelVO> importUsers, boolean isUpdateSupport);
 
-    /**
-     * 更新用户头像
-     *
-     * @param id         用户 id
-     * @param avatarFile 头像文件
-     */
-    void updateAvatar(Long id, InputStream avatarFile);
-
-//
-//    /**
-//     * 修改用户基本信息
-//     *
-//     * @param user 用户信息
-//     * @return 结果
-//     */
-//    public int updateUserProfile(SysUser user);
-//
-//    /**
-//     * 修改用户头像
-//     *
-//     * @param userName 用户名
-//     * @param avatar 头像地址
-//     * @return 结果
-//     */
-//    public boolean updateUserAvatar(String userName, String avatar);
-//
-//    /**
-//     * 重置用户密码
-//     *
-//     * @param user 用户信息
-//     * @return 结果
-//     */
-//    public int resetPwd(SysUser user);
-//
-//    /**
-//     * 重置用户密码
-//     *
-//     * @param userName 用户名
-//     * @param password 密码
-//     * @return 结果
-//     */
-//    public int resetUserPwd(String userName, String password);
-
 }

+ 87 - 94
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java

@@ -9,12 +9,13 @@ import cn.iocoder.dashboard.common.exception.ServiceException;
 import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.modules.infra.service.file.InfFileService;
+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.SysUserExportReqVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportRespVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO;
-import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
@@ -61,64 +62,11 @@ public class SysUserServiceImpl implements SysUserService {
     private SysPostService postService;
     @Resource
     private SysPermissionService permissionService;
-
     @Resource
     private PasswordEncoder passwordEncoder;
-
     @Resource
     private InfFileService fileService;
 
-    @Override
-    public SysUserDO getUserByUserName(String username) {
-        return userMapper.selectByUsername(username);
-    }
-
-    @Override
-    public SysUserDO getUser(Long id) {
-        return userMapper.selectById(id);
-    }
-
-    @Override
-    public PageResult<SysUserDO> pageUsers(SysUserPageReqVO reqVO) {
-        return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
-    }
-
-    @Override
-    public List<SysUserDO> listUsers(SysUserExportReqVO reqVO) {
-        return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
-    }
-
-    @Override
-    public List<SysUserDO> listUsers(Collection<Long> ids) {
-        return userMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public List<SysUserDO> listUsersByNickname(String nickname) {
-        return userMapper.selectListByNickname(nickname);
-    }
-
-    @Override
-    public List<SysUserDO> listUsersByUsername(String username) {
-        return userMapper.selectListByUsername(username);
-    }
-
-    /**
-     * 获得部门条件:查询指定部门的子部门编号们,包括自身
-     *
-     * @param deptId 部门编号
-     * @return 部门编号集合
-     */
-    private Set<Long> getDeptCondition(Long deptId) {
-        if (deptId == null) {
-            return Collections.emptySet();
-        }
-        Set<Long> deptIds = CollectionUtils.convertSet(deptService.listDeptsByParentIdFromCache(
-            deptId, true), SysDeptDO::getId);
-        deptIds.add(deptId); // 包括自身
-        return deptIds;
-    }
-
     @Override
     public Long createUser(SysUserCreateReqVO reqVO) {
         // 校验正确性
@@ -143,30 +91,35 @@ public class SysUserServiceImpl implements SysUserService {
     }
 
     @Override
-    public void updateUserProfile(SysUserProfileUpdateReqVO reqVO) {
+    public void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO) {
         // 校验正确性
-        this.checkUserExists(reqVO.getId());
-        this.checkEmailUnique(reqVO.getId(), reqVO.getEmail());
-        this.checkMobileUnique(reqVO.getId(), reqVO.getMobile());
-        // 校验填写密码
-        String encode = null;
-        if (this.checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) {
-            // 更新密码
-            encode = passwordEncoder.encode(reqVO.getNewPassword());
-        }
-        SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO);
-        if (StrUtil.isNotBlank(encode)) {
-            updateObj.setPassword(encode);
-        }
+        this.checkUserExists(id);
+        this.checkEmailUnique(id, reqVO.getEmail());
+        this.checkMobileUnique(id, reqVO.getMobile());
+        // 执行更新
+        userMapper.updateById(SysUserConvert.INSTANCE.convert(reqVO).setId(id));
+    }
+
+    @Override
+    public void updateUserPassword(Long id, SysUserProfileUpdatePasswordReqVO reqVO) {
+        // 校验旧密码密码
+        this.checkOldPassword(id, reqVO.getOldPassword());
+        // 执行更新
+        SysUserDO updateObj = new SysUserDO().setId(id);
+        updateObj.setPassword(passwordEncoder.encode(reqVO.getNewPassword())); // 加密密码
         userMapper.updateById(updateObj);
     }
 
     @Override
-    public void deleteUser(Long id) {
-        // 校验用户存在
+    public void updateUserAvatar(Long id, InputStream avatarFile) {
         this.checkUserExists(id);
-        // 删除用户
-        userMapper.deleteById(id);
+        // 存储文件
+        String avatar = fileService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile));
+        // 更新路径
+        SysUserDO sysUserDO = new SysUserDO();
+        sysUserDO.setId(id);
+        sysUserDO.setAvatar(avatar);
+        userMapper.updateById(sysUserDO);
     }
 
     @Override
@@ -193,6 +146,65 @@ public class SysUserServiceImpl implements SysUserService {
         permissionService.processUserDeleted(id);
     }
 
+    @Override
+    public void deleteUser(Long id) {
+        // 校验用户存在
+        this.checkUserExists(id);
+        // 删除用户
+        userMapper.deleteById(id);
+    }
+
+    @Override
+    public SysUserDO getUserByUsername(String username) {
+        return userMapper.selectByUsername(username);
+    }
+
+    @Override
+    public SysUserDO getUser(Long id) {
+        return userMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<SysUserDO> getUserPage(SysUserPageReqVO reqVO) {
+        return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
+    }
+
+    @Override
+    public List<SysUserDO> getUsers(SysUserExportReqVO reqVO) {
+        return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
+    }
+
+    @Override
+    public List<SysUserDO> getUsers(Collection<Long> ids) {
+        return userMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<SysUserDO> getUsersByNickname(String nickname) {
+        return userMapper.selectListByNickname(nickname);
+    }
+
+    @Override
+    public List<SysUserDO> getUsersByUsername(String username) {
+        return userMapper.selectListByUsername(username);
+    }
+
+    /**
+     * 获得部门条件:查询指定部门的子部门编号们,包括自身
+     *
+     * @param deptId 部门编号
+     * @return 部门编号集合
+     */
+    private Set<Long> getDeptCondition(Long deptId) {
+        if (deptId == null) {
+            return Collections.emptySet();
+        }
+        Set<Long> deptIds = CollectionUtils.convertSet(deptService.getDeptsByParentIdFromCache(
+            deptId, true), SysDeptDO::getId);
+        deptIds.add(deptId); // 包括自身
+        return deptIds;
+    }
+
     private void checkCreateOrUpdate(Long id, String username, String mobile, String email,
                                      Long deptId, Set<Long> postIds) {
         // 校验用户存在
@@ -287,7 +299,7 @@ public class SysUserServiceImpl implements SysUserService {
         if (CollUtil.isEmpty(postIds)) { // 允许不选择
             return;
         }
-        List<SysPostDO> posts = postService.listPosts(postIds, null);
+        List<SysPostDO> posts = postService.getPosts(postIds, null);
         if (CollUtil.isEmpty(posts)) {
             throw ServiceExceptionUtil.exception(POST_NOT_FOUND);
         }
@@ -304,26 +316,19 @@ public class SysUserServiceImpl implements SysUserService {
     }
 
     /**
-     * 校验旧密码、新密码
+     * 校验旧密码
      *
      * @param id          用户 id
      * @param oldPassword 旧密码
-     * @param newPassword 新密码
-     * @return 校验结果
      */
-    private boolean checkOldPassword(Long id, String oldPassword, String newPassword) {
-        if (id == null || StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword)) {
-            return false;
-        }
+    private void checkOldPassword(Long id, String oldPassword) {
         SysUserDO user = userMapper.selectById(id);
         if (user == null) {
             throw ServiceExceptionUtil.exception(USER_NOT_EXISTS);
         }
-
         if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
             throw ServiceExceptionUtil.exception(USER_PASSWORD_FAILED);
         }
-        return true;
     }
 
     @Override
@@ -364,16 +369,4 @@ public class SysUserServiceImpl implements SysUserService {
         return respVO;
     }
 
-    @Override
-    public void updateAvatar(Long id, InputStream avatarFile) {
-        this.checkUserExists(id);
-        // 存储文件
-        String avatar = fileService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile));
-        // 更新路径
-        SysUserDO sysUserDO = new SysUserDO();
-        sysUserDO.setId(id);
-        sysUserDO.setAvatar(avatar);
-        userMapper.updateById(sysUserDO);
-    }
-
 }

+ 23 - 0
src/test-integration/java/cn/iocoder/dashboard/BaseRedisIntegrationTest.java

@@ -0,0 +1,23 @@
+package cn.iocoder.dashboard;
+
+import cn.iocoder.dashboard.framework.redis.config.RedisConfig;
+import org.redisson.spring.starter.RedissonAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.ActiveProfiles;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class)
+@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件
+public class BaseRedisIntegrationTest {
+
+    @Import({
+            // Redis 配置类
+            RedisAutoConfiguration.class, // Spring Redis 自动配置类
+            RedisConfig.class, // 自己的 Redis 配置类
+            RedissonAutoConfiguration.class, // Redisson 自动高配置类
+    })
+    public static class Application {
+    }
+
+}

+ 2 - 1
src/test/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManagerTest.java → src/test-integration/java/cn/iocoder/dashboard/framework/quartz/core/SchedulerManagerTest.java

@@ -1,7 +1,8 @@
-package cn.iocoder.dashboard.framework.quartz.core.scheduler;
+package cn.iocoder.dashboard.framework.quartz.core;
 
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager;
 import cn.iocoder.dashboard.modules.system.job.auth.SysUserSessionTimeoutJob;
 import org.junit.jupiter.api.Test;
 import org.quartz.SchedulerException;

+ 63 - 0
src/test-integration/java/cn/iocoder/dashboard/framework/redis/core/stream/RedisStreamTest.java

@@ -0,0 +1,63 @@
+package cn.iocoder.dashboard.framework.redis.core.stream;
+
+import cn.hutool.core.thread.ThreadUtil;
+import cn.iocoder.dashboard.BaseRedisIntegrationTest;
+import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils;
+import cn.iocoder.dashboard.modules.system.mq.consumer.mail.SysMailSendConsumer;
+import cn.iocoder.dashboard.modules.system.mq.consumer.sms.SysSmsSendConsumer;
+import cn.iocoder.dashboard.modules.system.mq.message.mail.SysMailSendMessage;
+import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
+public class RedisStreamTest  {
+
+    @Import({SysSmsSendConsumer.class, SysMailSendConsumer.class})
+    @Disabled
+    public static class ConsumerTest extends BaseRedisIntegrationTest {
+
+        @Test
+        public void testConsumer() {
+            ThreadUtil.sleep(1, TimeUnit.DAYS);
+        }
+
+    }
+
+    @Disabled
+    public static class ProducerTest extends BaseRedisIntegrationTest {
+
+        @Resource
+        private StringRedisTemplate stringRedisTemplate;
+
+        @Resource
+        private RedisTemplate<String, Object> redisTemplate;
+
+        @Test
+        public void testProducer01() {
+            for (int i = 0; i < 100; i++) {
+                // 创建消息
+                SysSmsSendMessage message = new SysSmsSendMessage();
+                message.setMobile("15601691300").setTemplateCode("test:" + i);
+                // 发送消息
+                RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
+            }
+        }
+
+        @Test
+        public void testProducer02() {
+            // 创建消息
+            SysMailSendMessage message = new SysMailSendMessage();
+            message.setAddress("fangfang@mihayou.com").setTemplateCode("test");
+            // 发送消息
+            RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
+        }
+
+    }
+
+}

+ 0 - 0
src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java → src/test-integration/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java


+ 0 - 0
src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java → src/test-integration/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java


+ 2 - 1
src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java → src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenEngineTest.java

@@ -1,10 +1,11 @@
-package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+package cn.iocoder.dashboard.modules.tool.service.codegen;
 
 import cn.iocoder.dashboard.BaseDbUnitTest;
 import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO;
 import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO;
 import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolCodegenColumnMapper;
 import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolCodegenTableMapper;
+import cn.iocoder.dashboard.modules.tool.service.codegen.impl.ToolCodegenEngine;
 import org.junit.jupiter.api.Test;
 
 import javax.annotation.Resource;

+ 2 - 1
src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenSQLParserTest.java → src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenSQLParserTest.java

@@ -1,6 +1,7 @@
-package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+package cn.iocoder.dashboard.modules.tool.service.codegen;
 
 import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.modules.tool.service.codegen.impl.ToolCodegenSQLParser;
 import org.junit.jupiter.api.Test;
 
 public class ToolCodegenSQLParserTest extends BaseDbUnitTest {

+ 2 - 1
src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java → src/test-integration/java/cn/iocoder/dashboard/modules/tool/service/codegen/ToolCodegenServiceImplTest.java

@@ -1,6 +1,7 @@
-package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+package cn.iocoder.dashboard.modules.tool.service.codegen;
 
 import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.modules.tool.service.codegen.impl.ToolCodegenServiceImpl;
 import org.junit.jupiter.api.Test;
 
 import javax.annotation.Resource;

+ 82 - 0
src/test-integration/resources/application-integration-test.yaml

@@ -0,0 +1,82 @@
+spring:
+  main:
+    lazy-initialization: true # 开启懒加载,加快速度
+    banner-mode: off # 单元测试,禁用 Banner
+
+--- #################### 数据库相关配置 ####################
+
+spring:
+  # 数据源配置项
+  datasource:
+    name: ruoyi-vue-pro
+    url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
+    driver-class-name: org.h2.Driver
+    username: sa
+    password:
+    schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具
+    druid:
+      async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
+      initial-size: 1 # 单元测试,配置为 1,提升启动速度
+
+  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
+  redis:
+    host: 127.0.0.1 # 地址
+    port: 6379 # 端口(单元测试,使用 16379 端口)
+    database: 0 # 数据库索引
+
+mybatis:
+  lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
+
+--- #################### 定时任务相关配置 ####################
+
+--- #################### 配置中心相关配置 ####################
+
+--- #################### 服务保障相关配置 ####################
+
+# Lock4j 配置项(单元测试,禁用 Lock4j)
+
+# Resilience4j 配置项
+resilience4j:
+  ratelimiter:
+    instances:
+      backendA:
+        limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
+        limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
+        timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
+        register-health-indicator: true # 是否注册到健康监测
+
+--- #################### 监控相关配置 ####################
+
+--- #################### 芋道相关配置 ####################
+
+# 芋道配置项,设置当前项目所有自定义的配置
+yudao:
+  info:
+    version: 1.0.0
+    base-package: cn.iocoder.dashboard
+  web:
+    api-prefix: /api
+    controller-package: ${yudao.info.base-package}
+  security:
+    token-header: Authorization
+    token-secret: abcdefghijklmnopqrstuvwxyz
+    token-timeout: 1d
+    session-timeout: 30m
+    mock-enable: true
+    mock-secret: test
+  swagger:
+    enable: false # 单元测试,禁用 Swagger
+  captcha:
+    timeout: 5m
+    width: 160
+    height: 60
+  file:
+    base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/
+  codegen:
+    base-package: ${yudao.info.base-package}.modules
+    db-schemas: ${spring.datasource.name}
+  xss:
+    enable: false
+    exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系
+      - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
+      - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求

+ 2 - 0
src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
 import org.redisson.spring.starter.RedissonAutoConfiguration;
 import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.Import;
 import org.springframework.test.context.ActiveProfiles;
@@ -30,6 +31,7 @@ public class BaseDbAndRedisUnitTest {
             // DB 配置类
             DataSourceConfiguration.class, // 自己的 DB 配置类
             DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
             DruidDataSourceAutoConfigure.class, // Druid 自动配置类
             // MyBatis 配置类
             MybatisConfiguration.class, // 自己的 MyBatis 配置类

+ 2 - 0
src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java

@@ -5,6 +5,7 @@ import cn.iocoder.dashboard.framework.mybatis.config.MybatisConfiguration;
 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.Import;
 import org.springframework.test.context.ActiveProfiles;
@@ -26,6 +27,7 @@ public class BaseDbUnitTest {
             // DB 配置类
             DataSourceConfiguration.class, // 自己的 DB 配置类
             DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
             DruidDataSourceAutoConfigure.class, // Druid 自动配置类
             // MyBatis 配置类
             MybatisConfiguration.class, // 自己的 MyBatis 配置类

+ 1 - 1
src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java

@@ -17,7 +17,7 @@ public class RedisTestConfiguration {
     /**
      * 创建模拟的 Redis Server 服务器
      */
-    @Bean(destroyMethod = "stop")
+    @Bean
     public RedisServer redisServer(RedisProperties properties) throws IOException {
         RedisServer redisServer = new RedisServer(properties.getPort());
         // TODO 芋艿:一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样,就导致端口被占用,无法启动。。。

+ 173 - 0
src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogServiceTest.java

@@ -0,0 +1,173 @@
+package cn.iocoder.dashboard.modules.infra.service.job;
+
+import static cn.hutool.core.util.RandomUtil.randomEle;
+import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.dashboard.util.RandomUtils.randomLongId;
+import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
+import static cn.iocoder.dashboard.util.RandomUtils.randomString;
+import static cn.iocoder.dashboard.util.date.DateUtils.buildTime;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
+import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper;
+import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum;
+import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobLogServiceImpl;
+import cn.iocoder.dashboard.util.object.ObjectUtils;
+
+/**
+ * {@link InfJobLogServiceImpl} 的单元测试
+ *
+ * @author neilz
+ */
+@Import(InfJobLogServiceImpl.class)
+public class InfJobLogServiceTest extends BaseDbUnitTest {
+
+    @Resource
+    private InfJobLogServiceImpl jobLogService;
+    @Resource
+    private InfJobLogMapper jobLogMapper;
+
+    @Test
+    public void testCreateJobLog_success() {
+        // 准备参数
+        InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> {
+            o.setExecuteIndex(1);
+        });
+        // 调用
+        Long jobLogId = jobLogService.createJobLog(reqVO.getJobId(), reqVO.getBeginTime(), reqVO.getHandlerName(), reqVO.getHandlerParam(), reqVO.getExecuteIndex());
+        // 断言
+        assertNotNull(jobLogId);
+        // 校验记录的属性是否正确
+        InfJobLogDO job = jobLogMapper.selectById(jobLogId);
+        assertEquals(InfJobLogStatusEnum.RUNNING.getStatus(), job.getStatus());
+    }
+
+    @Test
+    public void testUpdateJobLogResultAsync_success() {
+        // 准备参数
+        InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> {
+            o.setExecuteIndex(1);
+        });
+        InfJobLogDO log = InfJobLogDO.builder().jobId(reqVO.getJobId()).handlerName(reqVO.getHandlerName()).handlerParam(reqVO.getHandlerParam()).executeIndex(reqVO.getExecuteIndex())
+                .beginTime(reqVO.getBeginTime()).status(InfJobLogStatusEnum.RUNNING.getStatus()).build();
+        jobLogMapper.insert(log);
+        // 调用
+        jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), true,reqVO.getResult());
+        // 校验记录的属性是否正确
+        InfJobLogDO job = jobLogMapper.selectById(log.getId());
+        assertEquals(InfJobLogStatusEnum.SUCCESS.getStatus(), job.getStatus());
+
+        // 调用
+        jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), false,reqVO.getResult());
+        // 校验记录的属性是否正确
+        InfJobLogDO job2 = jobLogMapper.selectById(log.getId());
+        assertEquals(InfJobLogStatusEnum.FAILURE.getStatus(), job2.getStatus());
+    }
+
+    @Test
+    public void testGetJobLogListByIds_success() {
+        // mock 数据
+        InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> {
+            o.setExecuteIndex(1);
+            o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围
+        });
+        InfJobLogDO cloneJobLog = ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString()));
+        jobLogMapper.insert(dbJobLog);
+        // 测试 handlerName 不匹配
+        jobLogMapper.insert(cloneJobLog);
+        // 准备参数
+        ArrayList ids = new ArrayList<>();
+        ids.add(dbJobLog.getId());
+        ids.add(cloneJobLog.getId());
+        // 调用
+        List<InfJobLogDO> list = jobLogService.getJobLogList(ids);
+        // 断言
+        assertEquals(2, list.size());
+        assertPojoEquals(dbJobLog, list.get(0));
+    }
+
+    @Test
+    public void testGetJobPage_success() {
+        // mock 数据
+        InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> {
+            o.setExecuteIndex(1);
+            o.setHandlerName("handlerName 单元测试");
+            o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus());
+            o.setBeginTime(buildTime(2021, 1, 8));
+            o.setEndTime(buildTime(2021, 1, 8));
+        });
+        jobLogMapper.insert(dbJobLog);
+        // 测试 jobId 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
+        // 测试 handlerName 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
+        // 测试 beginTime 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
+        // 测试 endTime 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
+        // 测试 status 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
+        // 准备参数
+        InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO();
+        reqVo.setJobId(dbJobLog.getJobId());
+        reqVo.setHandlerName("单元");
+        reqVo.setBeginTime(dbJobLog.getBeginTime());
+        reqVo.setEndTime(dbJobLog.getEndTime());
+        reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus());
+        // 调用
+        PageResult<InfJobLogDO> pageResult = jobLogService.getJobLogPage(reqVo);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbJobLog, pageResult.getList().get(0));
+    }
+
+    @Test
+    public void testGetJobListForExport_success() {
+        // mock 数据
+        InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> {
+            o.setExecuteIndex(1);
+            o.setHandlerName("handlerName 单元测试");
+            o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus());
+            o.setBeginTime(buildTime(2021, 1, 8));
+            o.setEndTime(buildTime(2021, 1, 8));
+        });
+        jobLogMapper.insert(dbJobLog);
+        // 测试 jobId 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
+        // 测试 handlerName 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
+        // 测试 beginTime 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
+        // 测试 endTime 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
+        // 测试 status 不匹配
+        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
+        // 准备参数
+        InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO();
+        reqVo.setJobId(dbJobLog.getJobId());
+        reqVo.setHandlerName("单元");
+        reqVo.setBeginTime(dbJobLog.getBeginTime());
+        reqVo.setEndTime(dbJobLog.getEndTime());
+        reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus());
+        // 调用
+        List<InfJobLogDO> list = jobLogService.getJobLogList(reqVo);
+        // 断言
+        assertEquals(1, list.size());
+        assertPojoEquals(dbJobLog, list.get(0));
+    }
+
+}

+ 309 - 0
src/test/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobServiceTest.java

@@ -0,0 +1,309 @@
+package cn.iocoder.dashboard.modules.infra.service.job;
+
+import static cn.hutool.core.util.RandomUtil.randomEle;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_EQUALS;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_INVALID;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_CRON_EXPRESSION_VALID;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_HANDLER_EXISTS;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_NOT_EXISTS;
+import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.JOB_UPDATE_ONLY_NORMAL_STATUS;
+import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
+import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
+import static cn.iocoder.dashboard.util.RandomUtils.randomString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.junit.jupiter.api.Test;
+import org.quartz.SchedulerException;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+
+import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.quartz.core.scheduler.SchedulerManager;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobCreateReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobExportReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobPageReqVO;
+import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.InfJobUpdateReqVO;
+import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
+import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
+import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobMapper;
+import cn.iocoder.dashboard.modules.infra.enums.job.InfJobStatusEnum;
+import cn.iocoder.dashboard.modules.infra.service.job.impl.InfJobServiceImpl;
+import cn.iocoder.dashboard.util.object.ObjectUtils;
+
+/**
+ * {@link InfJobServiceImpl} 的单元测试
+ *
+ * @author neilz
+ */
+@Import(InfJobServiceImpl.class)
+public class InfJobServiceTest extends BaseDbUnitTest {
+
+    @Resource
+    private InfJobServiceImpl jobService;
+    @Resource
+    private InfJobMapper jobMapper;
+    @MockBean
+    private SchedulerManager schedulerManager;
+
+    @Test
+    public void testCreateJob_cronExpressionValid() {
+        // 准备参数。Cron 表达式为 String 类型,默认随机字符串。
+        InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class);
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.createJob(reqVO), JOB_CRON_EXPRESSION_VALID);
+    }
+
+    @Test
+    public void testCreateJob_jobHandlerExists() throws SchedulerException {
+        // 准备参数 指定 Cron 表达式
+        InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        // 调用
+        jobService.createJob(reqVO);
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.createJob(reqVO), JOB_HANDLER_EXISTS);
+    }
+
+    @Test
+    public void testCreateJob_success() throws SchedulerException {
+        // 准备参数 指定 Cron 表达式
+        InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        // 调用
+        Long jobId = jobService.createJob(reqVO);
+        // 断言
+        assertNotNull(jobId);
+        // 校验记录的属性是否正确
+        InfJobDO job = jobMapper.selectById(jobId);
+        assertPojoEquals(reqVO, job);
+        assertEquals(InfJobStatusEnum.NORMAL.getStatus(), job.getStatus());
+        // 校验调用
+        verify(schedulerManager, times(1)).addJob(eq(job.getId()), eq(job.getHandlerName()), eq(job.getHandlerParam()), eq(job.getCronExpression()),
+                eq(reqVO.getRetryCount()), eq(reqVO.getRetryInterval()));
+    }
+
+    @Test
+    public void testUpdateJob_jobNotExists(){
+        // 准备参数
+        InfJobUpdateReqVO reqVO = randomPojo(InfJobUpdateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.updateJob(reqVO), JOB_NOT_EXISTS);
+    }
+
+    @Test
+    public void testUpdateJob_onlyNormalStatus(){
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.INIT.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 准备参数
+        InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> {
+            o.setId(job.getId());
+            o.setName(createReqVO.getName());
+            o.setCronExpression(createReqVO.getCronExpression());
+        });
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.updateJob(updateReqVO), JOB_UPDATE_ONLY_NORMAL_STATUS);
+    }
+
+    @Test
+    public void testUpdateJob_success() throws SchedulerException {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.NORMAL.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 准备参数
+        InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> {
+            o.setId(job.getId());
+            o.setName(createReqVO.getName());
+            o.setCronExpression(createReqVO.getCronExpression());
+        });
+        // 调用
+        jobService.updateJob(updateReqVO);
+        // 校验记录的属性是否正确
+        InfJobDO updateJob = jobMapper.selectById(updateReqVO.getId());
+        assertPojoEquals(updateReqVO, updateJob);
+        // 校验调用
+        verify(schedulerManager, times(1)).updateJob(eq(job.getHandlerName()), eq(updateReqVO.getHandlerParam()), eq(updateReqVO.getCronExpression()),
+                eq(updateReqVO.getRetryCount()), eq(updateReqVO.getRetryInterval()));
+    }
+
+    @Test
+    public void testUpdateJobStatus_changeStatusInvalid() {
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.updateJobStatus(1l, InfJobStatusEnum.INIT.getStatus()), JOB_CHANGE_STATUS_INVALID);
+    }
+
+    @Test
+    public void testUpdateJobStatus_changeStatusEquals() {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.NORMAL.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 调用,并断言异常
+        assertServiceException(() -> jobService.updateJobStatus(job.getId(), job.getStatus()), JOB_CHANGE_STATUS_EQUALS);
+    }
+
+    @Test
+    public void testUpdateJobStatus_NormalToStop_success() throws SchedulerException {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.NORMAL.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 调用
+        jobService.updateJobStatus(job.getId(), InfJobStatusEnum.STOP.getStatus());
+        // 校验记录的属性是否正确
+        InfJobDO updateJob = jobMapper.selectById(job.getId());
+        assertEquals(InfJobStatusEnum.STOP.getStatus(), updateJob.getStatus());
+        // 校验调用
+        verify(schedulerManager, times(1)).pauseJob(eq(job.getHandlerName()));
+    }
+
+    @Test
+    public void testUpdateJobStatus_StopToNormal_success() throws SchedulerException {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.STOP.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 调用
+        jobService.updateJobStatus(job.getId(), InfJobStatusEnum.NORMAL.getStatus());
+        // 校验记录的属性是否正确
+        InfJobDO updateJob = jobMapper.selectById(job.getId());
+        assertEquals(InfJobStatusEnum.NORMAL.getStatus(), updateJob.getStatus());
+        // 校验调用
+        verify(schedulerManager, times(1)).resumeJob(eq(job.getHandlerName()));
+    }
+
+    @Test
+    public void testTriggerJob_success() throws SchedulerException {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.NORMAL.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 调用
+        jobService.triggerJob(job.getId());
+        // 校验调用
+        verify(schedulerManager, times(1)).triggerJob(eq(job.getId()), eq(job.getHandlerName()), eq(job.getHandlerParam()));
+    }
+
+    @Test
+    public void testDeleteJob_success() throws SchedulerException {
+        // mock 数据
+        InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *"));
+        InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO);
+        job.setStatus(InfJobStatusEnum.NORMAL.getStatus());
+        fillJobMonitorTimeoutEmpty(job);
+        jobMapper.insert(job);
+        // 调用 UPDATE inf_job SET deleted=1 WHERE id=? AND deleted=0
+        jobService.deleteJob(job.getId());
+        // 校验数据不存在了  WHERE id=? AND deleted=0 查询为空正常
+        assertNull(jobMapper.selectById(job.getId()));
+        // 校验调用
+        verify(schedulerManager, times(1)).deleteJob(eq(job.getHandlerName()));
+    }
+
+    @Test
+    public void testGetJobListByIds_success() {
+        // mock 数据
+        InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
+            o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围
+        });
+        InfJobDO cloneJob = ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString()));
+        jobMapper.insert(dbJob);
+        // 测试 handlerName 不匹配
+        jobMapper.insert(cloneJob);
+        // 准备参数
+        ArrayList ids = new ArrayList<>();
+        ids.add(dbJob.getId());
+        ids.add(cloneJob.getId());
+        // 调用
+        List<InfJobDO> list = jobService.getJobList(ids);
+        // 断言
+        assertEquals(2, list.size());
+        assertPojoEquals(dbJob, list.get(0));
+    }
+
+    @Test
+    public void testGetJobPage_success() {
+        // mock 数据
+        InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
+            o.setName("定时任务测试");
+            o.setHandlerName("handlerName 单元测试");
+            o.setStatus(InfJobStatusEnum.INIT.getStatus());
+        });
+        jobMapper.insert(dbJob);
+        // 测试 name 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
+        // 测试 status 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
+        // 测试 handlerName 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
+        // 准备参数
+        InfJobPageReqVO reqVo = new InfJobPageReqVO();
+        reqVo.setName("定时");
+        reqVo.setStatus(InfJobStatusEnum.INIT.getStatus());
+        reqVo.setHandlerName("单元");
+        // 调用
+        PageResult<InfJobDO> pageResult = jobService.getJobPage(reqVo);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbJob, pageResult.getList().get(0));
+    }
+
+    @Test
+    public void testGetJobListForExport_success() {
+        // mock 数据
+        InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
+            o.setName("定时任务测试");
+            o.setHandlerName("handlerName 单元测试");
+            o.setStatus(InfJobStatusEnum.INIT.getStatus());
+        });
+        jobMapper.insert(dbJob);
+        // 测试 name 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
+        // 测试 status 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
+        // 测试 handlerName 不匹配
+        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
+        // 准备参数
+        InfJobExportReqVO reqVo = new InfJobExportReqVO();
+        reqVo.setName("定时");
+        reqVo.setStatus(InfJobStatusEnum.INIT.getStatus());
+        reqVo.setHandlerName("单元");
+        // 调用
+        List<InfJobDO> list = jobService.getJobList(reqVo);
+        // 断言
+        assertEquals(1, list.size());
+        assertPojoEquals(dbJob, list.get(0));
+    }
+
+    private static void fillJobMonitorTimeoutEmpty(InfJobDO job) {
+        if (job.getMonitorTimeout() == null) {
+            job.setMonitorTimeout(0);
+        }
+    }
+
+}

+ 3 - 4
src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java

@@ -38,7 +38,6 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
     @Resource
     private InfApiAccessLogMapper infApiAccessLogMapper;
 
-
     @Test
     public void testCreateApiAccessLogAsync() throws Exception {
         ApiAccessLogCreateDTO createDTO = RandomUtils.randomPojo(
@@ -59,13 +58,12 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
         assertPojoEquals(createDTO, infApiAccessLogDO);
     }
 
-
     @Test
     public void testGetApiAccessLogPage() {
         // 构造测试数据
         long userId = 2233L;
         int userType = UserTypeEnum.ADMIN.getValue();
-        String applicationName = "ruoyi-test";
+        String applicationName = "yudao-test";
         String requestUrl = "foo";
         Date beginTime = buildTime(2021, 3, 13);
         int duration = 1000;
@@ -123,7 +121,7 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
         // 构造测试数据
         long userId = 2233L;
         int userType = UserTypeEnum.ADMIN.getValue();
-        String applicationName = "ruoyi-test";
+        String applicationName = "yudao-test";
         String requestUrl = "foo";
         Date beginTime = buildTime(2021, 3, 13);
         int duration = 1000;
@@ -174,4 +172,5 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
         assertEquals(1, list.size());
         assertPojoEquals(infApiAccessLogDO, list.get(0));
     }
+
 }

+ 2 - 2
src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java

@@ -68,7 +68,7 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
         // 构造测试数据
         long userId = 2233L;
         int userType = UserTypeEnum.ADMIN.getValue();
-        String applicationName = "ruoyi-test";
+        String applicationName = "yudao-test";
         String requestUrl = "foo";
         Date beginTime = buildTime(2021, 3, 13);
         int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus();
@@ -121,7 +121,7 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
         // 构造测试数据
         long userId = 2233L;
         int userType = UserTypeEnum.ADMIN.getValue();
-        String applicationName = "ruoyi-test";
+        String applicationName = "yudao-test";
         String requestUrl = "foo";
         Date beginTime = buildTime(2021, 3, 13);
         int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus();

部分文件因文件數量過多而無法顯示