diff --git a/README.md b/README.md
index 939c913b7..b9eef10ad 100644
--- a/README.md
+++ b/README.md
@@ -1,80 +1,81 @@
-## 平台简介
-
-* 前端采用Vue、Element UI、Vue-Element-Admin。
-* 后端采用Spring Boot、Spring Security、Redis & Jwt。
-* 权限认证使用Jwt,支持多终端认证系统。
-* 支持加载动态权限菜单,多方式轻松权限控制。
-* 高效率开发,使用代码生成器可以一键生成前后端代码。
-* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
-* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
-* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
-
-## 内置功能
-
-1.  用户管理:用户是系统操作者,该功能主要完成系统用户配置。
-2.  部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
-3.  岗位管理:配置系统用户所属担任职务。
-4.  菜单管理:配置系统菜单,操作权限,按钮权限标识等。
-5.  角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
-6.  字典管理:对系统中经常使用的一些较为固定的数据进行维护。
-7.  参数管理:对系统动态配置常用参数。
-8.  通知公告:系统通知公告信息发布维护。
-9.  操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
-10. 登录日志:系统登录日志记录查询包含登录异常。
-11. 在线用户:当前系统中活跃用户状态监控。
-12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
-13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
-14. 系统接口:根据业务代码自动生成相关的api接口文档。
-15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
-16. 在线构建器:拖动表单元素生成相应的HTML代码。
-17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
-
-## 在线体验
-
-- admin/admin123  
-- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
-
-演示地址:http://vue.ruoyi.vip  
-文档地址:http://doc.ruoyi.vip
-
-## 演示图
-
-<table>
-    <tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
-    </tr>
-    <tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td>
-    </tr>
-    <tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td>
-    </tr>
-	<tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td>
-    </tr>	 
-    <tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
-    </tr>
-	<tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td>
-    </tr>
-	<tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
-    </tr>
-    <tr>
-        <td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
-        <td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
-    </tr>
-</table>
-
-
-## 若依前后端分离交流群
-
-QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) 点击按钮入群。
+## 平台简介
+
+* 前端采用Vue、Element UI。
+* 后端采用Spring Boot、Spring Security、Redis & Jwt。
+* 权限认证使用Jwt,支持多终端认证系统。
+* 支持加载动态权限菜单,多方式轻松权限控制。
+* 高效率开发,使用代码生成器可以一键生成前后端代码。
+* 提供了一个Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
+* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
+* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
+* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;
+
+## 内置功能
+
+1.  用户管理:用户是系统操作者,该功能主要完成系统用户配置。
+2.  部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
+3.  岗位管理:配置系统用户所属担任职务。
+4.  菜单管理:配置系统菜单,操作权限,按钮权限标识等。
+5.  角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
+6.  字典管理:对系统中经常使用的一些较为固定的数据进行维护。
+7.  参数管理:对系统动态配置常用参数。
+8.  通知公告:系统通知公告信息发布维护。
+9.  操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
+10. 登录日志:系统登录日志记录查询包含登录异常。
+11. 在线用户:当前系统中活跃用户状态监控。
+12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
+13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
+14. 系统接口:根据业务代码自动生成相关的api接口文档。
+15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
+16. 在线构建器:拖动表单元素生成相应的HTML代码。
+17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
+
+## 在线体验
+
+- admin/admin123  
+- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
+
+演示地址:http://vue.ruoyi.vip  
+文档地址:http://doc.ruoyi.vip
+
+## 演示图
+
+<table>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/707825ad3f29de74a8d6d02fbd73ad631ea.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/46be40cc6f01aa300eed53a19b5012bf484.jpg"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/4284796d4cea240d181b8f2201813dda710.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/3ecfac87a049f7fe36abbcaafb2c40d36cf.jpg"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/71c2d48905221a09a728df4aff4160b8607.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/c14c1ee9a64a6a9c2c22f67d43198767dbe.jpg"/></td>
+    </tr>	 
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/fdea1d8bb8625c27bf964176a2c8ebc6945.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/509d2708cfd762b6e6339364cac1cc1970c.jpg"/></td>
+    </tr>
+	<tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-f1fd681cc9d295db74e85ad6d2fe4389454.png"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
+        <td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
+    </tr>
+</table>
+
+
+## 若依前后端分离交流群
+
+QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) 点击按钮入群。
\ No newline at end of file
diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index 62c2bddb1..b41c859eb 100644
--- a/ruoyi-ui/package.json
+++ b/ruoyi-ui/package.json
@@ -1,11 +1,11 @@
 {
   "name": "ruoyi",
-  "version": "2.2.0",
+  "version": "2.3.0",
   "description": "若依管理系统",
   "author": "若依",
   "license": "MIT",
   "scripts": {
-    "dev": "vue-cli-service serve",
+    "dev": "vue-cli-service serve --open",
     "build:prod": "vue-cli-service build",
     "build:stage": "vue-cli-service build --mode staging",
     "preview": "node build/index.js --preview",
diff --git a/ruoyi-ui/public/robots.txt b/ruoyi-ui/public/robots.txt
new file mode 100644
index 000000000..c2aab7e03
--- /dev/null
+++ b/ruoyi-ui/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
\ No newline at end of file
diff --git a/ruoyi-ui/src/api/system/config.js b/ruoyi-ui/src/api/system/config.js
index 124c9812f..2221540e5 100644
--- a/ruoyi-ui/src/api/system/config.js
+++ b/ruoyi-ui/src/api/system/config.js
@@ -51,6 +51,14 @@ export function delConfig(configId) {
   })
 }
 
+// 清理参数缓存
+export function clearCache() {
+  return request({
+    url: '/system/config/clearCache',
+    method: 'delete'
+  })
+}
+
 // 导出参数
 export function exportConfig(query) {
   return request({
diff --git a/ruoyi-ui/src/api/system/dict/data.js b/ruoyi-ui/src/api/system/dict/data.js
index 6a3f4186b..d3f8c2f20 100644
--- a/ruoyi-ui/src/api/system/dict/data.js
+++ b/ruoyi-ui/src/api/system/dict/data.js
@@ -20,7 +20,7 @@ export function getData(dictCode) {
 // 根据字典类型查询字典数据信息
 export function getDicts(dictType) {
   return request({
-    url: '/system/dict/data/dictType/' + dictType,
+    url: '/system/dict/data/type/' + dictType,
     method: 'get'
   })
 }
diff --git a/ruoyi-ui/src/api/system/dict/type.js b/ruoyi-ui/src/api/system/dict/type.js
index 4b45a355e..d392f5042 100644
--- a/ruoyi-ui/src/api/system/dict/type.js
+++ b/ruoyi-ui/src/api/system/dict/type.js
@@ -43,6 +43,14 @@ export function delType(dictId) {
   })
 }
 
+// 清理参数缓存
+export function clearCache() {
+  return request({
+    url: '/system/dict/type/clearCache',
+    method: 'delete'
+  })
+}
+
 // 导出字典类型
 export function exportType(query) {
   return request({
diff --git a/ruoyi-ui/src/assets/styles/element-variables.scss b/ruoyi-ui/src/assets/styles/element-variables.scss
index bc7697eff..039d1e480 100644
--- a/ruoyi-ui/src/assets/styles/element-variables.scss
+++ b/ruoyi-ui/src/assets/styles/element-variables.scss
@@ -6,7 +6,7 @@
 /* theme color */
 $--color-primary: #1890ff;
 $--color-success: #13ce66;
-$--color-warning: #FFBA00;
+$--color-warning: #ffba00;
 $--color-danger: #ff4949;
 // $--color-info: #1E1E1E;
 
diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss
index b6c40ac9f..18dff3afe 100644
--- a/ruoyi-ui/src/assets/styles/ruoyi.scss
+++ b/ruoyi-ui/src/assets/styles/ruoyi.scss
@@ -57,12 +57,16 @@
 	margin-top: 6vh !important;
 }
 
-.el-table .el-table__header-wrapper th {
-	word-break: break-word;
-	background-color: #f8f8f9;
-	color: #515a6e;
-	height: 40px;
-	font-size: 13px;
+.el-table {
+	.el-table__header-wrapper, .el-table__fixed-header-wrapper {
+		th {
+			word-break: break-word;
+			background-color: #f8f8f9;
+			color: #515a6e;
+			height: 40px;
+			font-size: 13px;
+		}
+	}
 }
 
 /** 表单布局 **/
diff --git a/ruoyi-ui/src/components/HeaderSearch/index.vue b/ruoyi-ui/src/components/HeaderSearch/index.vue
index 8974171cb..6fe5fd651 100644
--- a/ruoyi-ui/src/components/HeaderSearch/index.vue
+++ b/ruoyi-ui/src/components/HeaderSearch/index.vue
@@ -70,7 +70,12 @@ export default {
       this.show = false
     },
     change(val) {
-      this.$router.push(val.path)
+      if(this.ishttp(val.path)) {
+        // http(s):// 路径新窗口打开
+        window.open(val.path, "_blank");
+      } else {
+        this.$router.push(val.path)
+      }
       this.search = ''
       this.options = []
       this.$nextTick(() => {
@@ -104,7 +109,7 @@ export default {
         if (router.hidden) { continue }
 
         const data = {
-          path: path.resolve(basePath, router.path),
+          path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
           title: [...prefixTitle]
         }
 
@@ -134,6 +139,9 @@ export default {
       } else {
         this.options = []
       }
+    },
+    ishttp(url) {
+      return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
     }
   }
 }
diff --git a/ruoyi-ui/src/components/IconSelect/index.vue b/ruoyi-ui/src/components/IconSelect/index.vue
index ea4c1b66e..a7512b2d6 100644
--- a/ruoyi-ui/src/components/IconSelect/index.vue
+++ b/ruoyi-ui/src/components/IconSelect/index.vue
@@ -25,10 +25,9 @@ export default {
   },
   methods: {
     filterIcons() {
+      this.iconList = icons
       if (this.name) {
         this.iconList = this.iconList.filter(item => item.includes(this.name))
-      } else {
-        this.iconList = icons
       }
     },
     selectedIcon(name) {
diff --git a/ruoyi-ui/src/components/SvgIcon/index.vue b/ruoyi-ui/src/components/SvgIcon/index.vue
index 6cd3ab928..340ace45c 100644
--- a/ruoyi-ui/src/components/SvgIcon/index.vue
+++ b/ruoyi-ui/src/components/SvgIcon/index.vue
@@ -1,7 +1,7 @@
 <template>
   <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
   <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
-    <use :href="iconName" />
+    <use :xlink:href="iconName" />
   </svg>
 </template>
 
diff --git a/ruoyi-ui/src/layout/components/Sidebar/Link.vue b/ruoyi-ui/src/layout/components/Sidebar/Link.vue
index 6cd6e2c0c..d235d10b6 100644
--- a/ruoyi-ui/src/layout/components/Sidebar/Link.vue
+++ b/ruoyi-ui/src/layout/components/Sidebar/Link.vue
@@ -1,7 +1,5 @@
-
 <template>
-  <!-- eslint-disable vue/require-component-is -->
-  <component v-bind="linkProps(to)">
+  <component :is="type" v-bind="linkProps(to)">
     <slot />
   </component>
 </template>
@@ -16,19 +14,28 @@ export default {
       required: true
     }
   },
+  computed: {
+    isExternal() {
+      return isExternal(this.to)
+    },
+    type() {
+      if (this.isExternal) {
+        return 'a'
+      }
+      return 'router-link'
+    }
+  },
   methods: {
-    linkProps(url) {
-      if (isExternal(url)) {
+    linkProps(to) {
+      if (this.isExternal) {
         return {
-          is: 'a',
-          href: url,
+          href: to,
           target: '_blank',
           rel: 'noopener'
         }
       }
       return {
-        is: 'router-link',
-        to: url
+        to: to
       }
     }
   }
diff --git a/ruoyi-ui/src/layout/components/Sidebar/index.vue b/ruoyi-ui/src/layout/components/Sidebar/index.vue
index 342dbbed6..1004f53a0 100644
--- a/ruoyi-ui/src/layout/components/Sidebar/index.vue
+++ b/ruoyi-ui/src/layout/components/Sidebar/index.vue
@@ -13,8 +13,8 @@
                 mode="vertical"
             >
                 <sidebar-item
-                    v-for="route in permission_routes"
-                    :key="route.path"
+                    v-for="(route, index) in permission_routes"
+                    :key="route.path  + index"
                     :item="route"
                     :base-path="route.path"
                 />
diff --git a/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue b/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue
index 8be9c0170..dd4b77f95 100644
--- a/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue
+++ b/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue
@@ -19,12 +19,21 @@ export default {
       return this.$refs.scrollContainer.$refs.wrap
     }
   },
+  mounted() {
+    this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
+  },
+  beforeDestroy() {
+    this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
+  },
   methods: {
     handleScroll(e) {
       const eventDelta = e.wheelDelta || -e.deltaY * 40
       const $scrollWrapper = this.scrollWrapper
       $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
     },
+    emitScroll() {
+      this.$emit('scroll')
+    },
     moveToTarget(currentTag) {
       const $container = this.$refs.scrollContainer.$el
       const $containerWidth = $container.offsetWidth
diff --git a/ruoyi-ui/src/layout/components/TagsView/index.vue b/ruoyi-ui/src/layout/components/TagsView/index.vue
index 543231817..529090a74 100644
--- a/ruoyi-ui/src/layout/components/TagsView/index.vue
+++ b/ruoyi-ui/src/layout/components/TagsView/index.vue
@@ -1,318 +1,303 @@
 <template>
-    <div id="tags-view-container" class="tags-view-container">
-        <scroll-pane ref="scrollPane" class="tags-view-wrapper">
-            <router-link
-                v-for="tag in visitedViews"
-                ref="tag"
-                :key="tag.path"
-                :class="isActive(tag)?'active':''"
-                :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
-                tag="span"
-                class="tags-view-item"
-                :style="activeStyle(tag)"
-                @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
-                @contextmenu.prevent.native="openMenu(tag,$event)"
-            >
-                {{ tag.title }}
-                <span
-                    v-if="!isAffix(tag)"
-                    class="el-icon-close"
-                    @click.prevent.stop="closeSelectedTag(tag)"
-                />
-            </router-link>
-        </scroll-pane>
-        <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
-            <li @click="refreshSelectedTag(selectedTag)">刷新页面</li>
-            <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭当前</li>
-            <li @click="closeOthersTags">关闭其他</li>
-            <li @click="closeAllTags(selectedTag)">关闭所有</li>
-        </ul>
-    </div>
+  <div id="tags-view-container" class="tags-view-container">
+    <scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll">
+      <router-link
+        v-for="tag in visitedViews"
+        ref="tag"
+        :key="tag.path"
+        :class="isActive(tag)?'active':''"
+        :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
+        tag="span"
+        class="tags-view-item"
+        :style="activeStyle(tag)"
+        @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
+        @contextmenu.prevent.native="openMenu(tag,$event)"
+      >
+        {{ tag.title }}
+        <span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
+      </router-link>
+    </scroll-pane>
+    <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
+      <li @click="refreshSelectedTag(selectedTag)">刷新页面</li>
+      <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭当前</li>
+      <li @click="closeOthersTags">关闭其他</li>
+      <li @click="closeAllTags(selectedTag)">关闭所有</li>
+    </ul>
+  </div>
 </template>
 
 <script>
-import ScrollPane from "./ScrollPane";
-import path from "path";
+import ScrollPane from './ScrollPane'
+import path from 'path'
 
 export default {
-    components: { ScrollPane },
-    data() {
-        return {
-            visible: false,
-            top: 0,
-            left: 0,
-            selectedTag: {},
-            affixTags: []
-        };
-    },
-    computed: {
-        visitedViews() {
-            return this.$store.state.tagsView.visitedViews;
-        },
-        routes() {
-            return this.$store.state.permission.routes;
-        },
-        theme() {
-            return this.$store.state.settings.theme;
-        }
-    },
-    watch: {
-        $route() {
-            this.addTags();
-            this.moveToCurrentTag();
-        },
-        visible(value) {
-            if (value) {
-                document.body.addEventListener("click", this.closeMenu);
-            } else {
-                document.body.removeEventListener("click", this.closeMenu);
-            }
-        }
-    },
-    mounted() {
-        this.initTags();
-        this.addTags();
-    },
-    methods: {
-        isActive(route) {
-            return route.path === this.$route.path;
-        },
-        activeStyle(tag) {
-            if (!this.isActive(tag)) return {};
-            return {
-                "background-color": this.theme,
-                "border-color": this.theme
-            };
-        },
-        isAffix(tag) {
-            return tag.meta && tag.meta.affix;
-        },
-        filterAffixTags(routes, basePath = "/") {
-            let tags = [];
-            routes.forEach(route => {
-                if (route.meta && route.meta.affix) {
-                    const tagPath = path.resolve(basePath, route.path);
-                    tags.push({
-                        fullPath: tagPath,
-                        path: tagPath,
-                        name: route.name,
-                        meta: { ...route.meta }
-                    });
-                }
-                if (route.children) {
-                    const tempTags = this.filterAffixTags(
-                        route.children,
-                        route.path
-                    );
-                    if (tempTags.length >= 1) {
-                        tags = [...tags, ...tempTags];
-                    }
-                }
-            });
-            return tags;
-        },
-        initTags() {
-            const affixTags = (this.affixTags = this.filterAffixTags(
-                this.routes
-            ));
-            for (const tag of affixTags) {
-                // Must have tag name
-                if (tag.name) {
-                    this.$store.dispatch("tagsView/addVisitedView", tag);
-                }
-            }
-        },
-        addTags() {
-            const { name } = this.$route;
-            if (name) {
-                this.$store.dispatch("tagsView/addView", this.$route);
-            }
-            return false;
-        },
-        moveToCurrentTag() {
-            const tags = this.$refs.tag;
-            this.$nextTick(() => {
-                for (const tag of tags) {
-                    if (tag.to.path === this.$route.path) {
-                        this.$refs.scrollPane.moveToTarget(tag);
-                        // when query is different then update
-                        if (tag.to.fullPath !== this.$route.fullPath) {
-                            this.$store.dispatch(
-                                "tagsView/updateVisitedView",
-                                this.$route
-                            );
-                        }
-                        break;
-                    }
-                }
-            });
-        },
-        refreshSelectedTag(view) {
-            this.$store.dispatch("tagsView/delCachedView", view).then(() => {
-                const { fullPath } = view;
-                this.$nextTick(() => {
-                    this.$router.replace({
-                        path: "/redirect" + fullPath
-                    });
-                });
-            });
-        },
-        closeSelectedTag(view) {
-            this.$store
-                .dispatch("tagsView/delView", view)
-                .then(({ visitedViews }) => {
-                    if (this.isActive(view)) {
-                        this.toLastView(visitedViews, view);
-                    }
-                });
-        },
-        closeOthersTags() {
-            this.$router.push(this.selectedTag);
-            this.$store
-                .dispatch("tagsView/delOthersViews", this.selectedTag)
-                .then(() => {
-                    this.moveToCurrentTag();
-                });
-        },
-        closeAllTags(view) {
-            this.$store
-                .dispatch("tagsView/delAllViews")
-                .then(({ visitedViews }) => {
-                    if (this.affixTags.some(tag => tag.path === view.path)) {
-                        return;
-                    }
-                    this.toLastView(visitedViews, view);
-                });
-        },
-        toLastView(visitedViews, view) {
-            const latestView = visitedViews.slice(-1)[0];
-            if (latestView) {
-                this.$router.push(latestView.fullPath);
-            } else {
-                // now the default is to redirect to the home page if there is no tags-view,
-                // you can adjust it according to your needs.
-                if (view.name === "Dashboard") {
-                    // to reload home page
-                    this.$router.replace({ path: "/redirect" + view.fullPath });
-                } else {
-                    this.$router.push("/");
-                }
-            }
-        },
-        openMenu(tag, e) {
-            const menuMinWidth = 105;
-            const offsetLeft = this.$el.getBoundingClientRect().left; // container margin left
-            const offsetWidth = this.$el.offsetWidth; // container width
-            const maxLeft = offsetWidth - menuMinWidth; // left boundary
-            const left = e.clientX - offsetLeft + 15; // 15: margin right
-
-            if (left > maxLeft) {
-                this.left = maxLeft;
-            } else {
-                this.left = left;
-            }
-
-            this.top = e.clientY;
-            this.visible = true;
-            this.selectedTag = tag;
-        },
-        closeMenu() {
-            this.visible = false;
-        }
+  components: { ScrollPane },
+  data() {
+    return {
+      visible: false,
+      top: 0,
+      left: 0,
+      selectedTag: {},
+      affixTags: []
     }
-};
+  },
+  computed: {
+    visitedViews() {
+      return this.$store.state.tagsView.visitedViews
+    },
+    routes() {
+      return this.$store.state.permission.routes
+    },
+    theme() {
+      return this.$store.state.settings.theme;
+    }
+  },
+  watch: {
+    $route() {
+      this.addTags()
+      this.moveToCurrentTag()
+    },
+    visible(value) {
+      if (value) {
+        document.body.addEventListener('click', this.closeMenu)
+      } else {
+        document.body.removeEventListener('click', this.closeMenu)
+      }
+    }
+  },
+  mounted() {
+    this.initTags()
+    this.addTags()
+  },
+  methods: {
+    isActive(route) {
+      return route.path === this.$route.path
+    },
+    activeStyle(tag) {
+      if (!this.isActive(tag)) return {};
+      return {
+        "background-color": this.theme,
+        "border-color": this.theme
+      };
+    },
+    isAffix(tag) {
+      return tag.meta && tag.meta.affix
+    },
+    filterAffixTags(routes, basePath = '/') {
+      let tags = []
+      routes.forEach(route => {
+        if (route.meta && route.meta.affix) {
+          const tagPath = path.resolve(basePath, route.path)
+          tags.push({
+            fullPath: tagPath,
+            path: tagPath,
+            name: route.name,
+            meta: { ...route.meta }
+          })
+        }
+        if (route.children) {
+          const tempTags = this.filterAffixTags(route.children, route.path)
+          if (tempTags.length >= 1) {
+            tags = [...tags, ...tempTags]
+          }
+        }
+      })
+      return tags
+    },
+    initTags() {
+      const affixTags = this.affixTags = this.filterAffixTags(this.routes)
+      for (const tag of affixTags) {
+        // Must have tag name
+        if (tag.name) {
+          this.$store.dispatch('tagsView/addVisitedView', tag)
+        }
+      }
+    },
+    addTags() {
+      const { name } = this.$route
+      if (name) {
+        this.$store.dispatch('tagsView/addView', this.$route)
+      }
+      return false
+    },
+    moveToCurrentTag() {
+      const tags = this.$refs.tag
+      this.$nextTick(() => {
+        for (const tag of tags) {
+          if (tag.to.path === this.$route.path) {
+            this.$refs.scrollPane.moveToTarget(tag)
+            // when query is different then update
+            if (tag.to.fullPath !== this.$route.fullPath) {
+              this.$store.dispatch('tagsView/updateVisitedView', this.$route)
+            }
+            break
+          }
+        }
+      })
+    },
+    refreshSelectedTag(view) {
+      this.$store.dispatch('tagsView/delCachedView', view).then(() => {
+        const { fullPath } = view
+        this.$nextTick(() => {
+          this.$router.replace({
+            path: '/redirect' + fullPath
+          })
+        })
+      })
+    },
+    closeSelectedTag(view) {
+      this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
+        if (this.isActive(view)) {
+          this.toLastView(visitedViews, view)
+        }
+      })
+    },
+    closeOthersTags() {
+      this.$router.push(this.selectedTag)
+      this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
+        this.moveToCurrentTag()
+      })
+    },
+    closeAllTags(view) {
+      this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
+        if (this.affixTags.some(tag => tag.path === view.path)) {
+          return
+        }
+        this.toLastView(visitedViews, view)
+      })
+    },
+    toLastView(visitedViews, view) {
+      const latestView = visitedViews.slice(-1)[0]
+      if (latestView) {
+        this.$router.push(latestView.fullPath)
+      } else {
+        // now the default is to redirect to the home page if there is no tags-view,
+        // you can adjust it according to your needs.
+        if (view.name === 'Dashboard') {
+          // to reload home page
+          this.$router.replace({ path: '/redirect' + view.fullPath })
+        } else {
+          this.$router.push('/')
+        }
+      }
+    },
+    openMenu(tag, e) {
+      const menuMinWidth = 105
+      const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
+      const offsetWidth = this.$el.offsetWidth // container width
+      const maxLeft = offsetWidth - menuMinWidth // left boundary
+      const left = e.clientX - offsetLeft + 15 // 15: margin right
+
+      if (left > maxLeft) {
+        this.left = maxLeft
+      } else {
+        this.left = left
+      }
+
+      this.top = e.clientY
+      this.visible = true
+      this.selectedTag = tag
+    },
+    closeMenu() {
+      this.visible = false
+    },
+    handleScroll() {
+      this.closeMenu()
+    }
+  }
+}
 </script>
 
 <style lang="scss" scoped>
 .tags-view-container {
-    height: 34px;
-    width: 100%;
+  height: 34px;
+  width: 100%;
+  background: #fff;
+  border-bottom: 1px solid #d8dce5;
+  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+  .tags-view-wrapper {
+    .tags-view-item {
+      display: inline-block;
+      position: relative;
+      cursor: pointer;
+      height: 26px;
+      line-height: 26px;
+      border: 1px solid #d8dce5;
+      color: #495060;
+      background: #fff;
+      padding: 0 8px;
+      font-size: 12px;
+      margin-left: 5px;
+      margin-top: 4px;
+      &:first-of-type {
+        margin-left: 15px;
+      }
+      &:last-of-type {
+        margin-right: 15px;
+      }
+      &.active {
+        background-color: #42b983;
+        color: #fff;
+        border-color: #42b983;
+        &::before {
+          content: '';
+          background: #fff;
+          display: inline-block;
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: relative;
+          margin-right: 2px;
+        }
+      }
+    }
+  }
+  .contextmenu {
+    margin: 0;
     background: #fff;
-    border-bottom: 1px solid #d8dce5;
-    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
-    .tags-view-wrapper {
-        .tags-view-item {
-            display: inline-block;
-            position: relative;
-            cursor: pointer;
-            height: 26px;
-            line-height: 26px;
-            border: 1px solid #d8dce5;
-            color: #495060;
-            background: #fff;
-            padding: 0 8px;
-            font-size: 12px;
-            margin-left: 5px;
-            margin-top: 4px;
-            &:first-of-type {
-                margin-left: 15px;
-            }
-            &:last-of-type {
-                margin-right: 15px;
-            }
-            &.active {
-                background-color: #42b983;
-                color: #fff;
-                border-color: #42b983;
-                &::before {
-                    content: "";
-                    background: #fff;
-                    display: inline-block;
-                    width: 8px;
-                    height: 8px;
-                    border-radius: 50%;
-                    position: relative;
-                    margin-right: 2px;
-                }
-            }
-        }
-    }
-    .contextmenu {
-        margin: 0;
-        background: #fff;
-        z-index: 3000;
-        position: absolute;
-        list-style-type: none;
-        padding: 5px 0;
-        border-radius: 4px;
-        font-size: 12px;
-        font-weight: 400;
-        color: #333;
-        box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
-        li {
-            margin: 0;
-            padding: 7px 16px;
-            cursor: pointer;
-            &:hover {
-                background: #eee;
-            }
-        }
+    z-index: 3000;
+    position: absolute;
+    list-style-type: none;
+    padding: 5px 0;
+    border-radius: 4px;
+    font-size: 12px;
+    font-weight: 400;
+    color: #333;
+    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+    li {
+      margin: 0;
+      padding: 7px 16px;
+      cursor: pointer;
+      &:hover {
+        background: #eee;
+      }
     }
+  }
 }
 </style>
 
 <style lang="scss">
 //reset element css of el-icon-close
 .tags-view-wrapper {
-    .tags-view-item {
-        .el-icon-close {
-            width: 16px;
-            height: 16px;
-            vertical-align: 2px;
-            border-radius: 50%;
-            text-align: center;
-            transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
-            transform-origin: 100% 50%;
-            &:before {
-                transform: scale(0.6);
-                display: inline-block;
-                vertical-align: -3px;
-            }
-            &:hover {
-                background-color: #b4bccc;
-                color: #fff;
-            }
-        }
+  .tags-view-item {
+    .el-icon-close {
+      width: 16px;
+      height: 16px;
+      vertical-align: 2px;
+      border-radius: 50%;
+      text-align: center;
+      transition: all .3s cubic-bezier(.645, .045, .355, 1);
+      transform-origin: 100% 50%;
+      &:before {
+        transform: scale(.6);
+        display: inline-block;
+        vertical-align: -3px;
+      }
+      &:hover {
+        background-color: #b4bccc;
+        color: #fff;
+      }
     }
+  }
 }
 </style>
diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js
index 1813f429f..17e5b3d54 100644
--- a/ruoyi-ui/src/permission.js
+++ b/ruoyi-ui/src/permission.js
@@ -53,7 +53,7 @@ router.beforeEach((to, from, next) => {
       // 在免登录白名单,直接进入
       next()
     } else {
-      next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
+      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
       NProgress.done()
     }
   }
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index acebbd0ea..59238d96e 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -111,7 +111,7 @@ export const constantRoutes = [
     hidden: true,
     children: [
       {
-        path: 'edit',
+        path: 'edit/:tableId(\\d+)',
         component: (resolve) => require(['@/views/tool/gen/editTable'], resolve),
         name: 'GenEdit',
         meta: { title: '修改生成配置' }
diff --git a/ruoyi-ui/src/views/monitor/job/index.vue b/ruoyi-ui/src/views/monitor/job/index.vue
index 499ab2600..3a35e85b2 100644
--- a/ruoyi-ui/src/views/monitor/job/index.vue
+++ b/ruoyi-ui/src/views/monitor/job/index.vue
@@ -133,7 +133,7 @@
 
     <!-- 添加或修改定时任务对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
         <el-row>
           <el-col :span="12">
             <el-form-item label="任务名称" prop="jobName">
@@ -438,8 +438,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -448,8 +446,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/monitor/job/log.vue b/ruoyi-ui/src/views/monitor/job/log.vue
index d9f79b51f..254f48618 100644
--- a/ruoyi-ui/src/views/monitor/job/log.vue
+++ b/ruoyi-ui/src/views/monitor/job/log.vue
@@ -87,7 +87,7 @@
           icon="el-icon-download"
           size="mini"
           @click="handleExport"
-          v-hasPermi="['monitor:jobLog:export']"
+          v-hasPermi="['monitor:job:export']"
         >导出</el-button>
       </el-col>
     </el-row>
@@ -196,9 +196,7 @@ export default {
         jobName: undefined,
         jobGroup: undefined,
         status: undefined
-      },
-      // 表单参数
-      form: {}
+      }
     };
   },
   created() {
diff --git a/ruoyi-ui/src/views/monitor/online/index.vue b/ruoyi-ui/src/views/monitor/online/index.vue
index 72c4a5303..1f5a50f2f 100644
--- a/ruoyi-ui/src/views/monitor/online/index.vue
+++ b/ruoyi-ui/src/views/monitor/online/index.vue
@@ -39,7 +39,7 @@
       <el-table-column label="登录名称" align="center" prop="userName" :show-overflow-tooltip="true" />
       <el-table-column label="部门名称" align="center" prop="deptName" />
       <el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-      <el-table-column label="登录地点" align="center" prop="loginLocation" />
+      <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
       <el-table-column label="浏览器" align="center" prop="browser" />
       <el-table-column label="操作系统" align="center" prop="os" />
       <el-table-column label="登录时间" align="center" prop="loginTime" width="180">
diff --git a/ruoyi-ui/src/views/system/config/index.vue b/ruoyi-ui/src/views/system/config/index.vue
index c2a68f903..83b77b93e 100644
--- a/ruoyi-ui/src/views/system/config/index.vue
+++ b/ruoyi-ui/src/views/system/config/index.vue
@@ -88,6 +88,15 @@
           v-hasPermi="['system:config:export']"
         >导出</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-refresh"
+          size="mini"
+          @click="handleClearCache"
+          v-hasPermi="['system:config:remove']"
+        >清理缓存</el-button>
+      </el-col>
     </el-row>
 
     <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange">
@@ -165,7 +174,7 @@
 </template>
 
 <script>
-import { listConfig, getConfig, delConfig, addConfig, updateConfig, exportConfig } from "@/api/system/config";
+import { listConfig, getConfig, delConfig, addConfig, updateConfig, exportConfig, clearCache } from "@/api/system/config";
 
 export default {
   name: "Config",
@@ -296,8 +305,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -306,8 +313,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -340,6 +345,14 @@ export default {
         }).then(response => {
           this.download(response.msg);
         }).catch(function() {});
+    },
+    /** 清理缓存按钮操作 */
+    handleClearCache() {
+      clearCache().then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("清理成功");
+        }
+      });
     }
   }
 };
diff --git a/ruoyi-ui/src/views/system/dept/index.vue b/ruoyi-ui/src/views/system/dept/index.vue
index ac6d66319..4d4d97882 100644
--- a/ruoyi-ui/src/views/system/dept/index.vue
+++ b/ruoyi-ui/src/views/system/dept/index.vue
@@ -281,8 +281,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -291,8 +289,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/dict/data.vue b/ruoyi-ui/src/views/system/dict/data.vue
index 49c4058d7..f5eb63eab 100644
--- a/ruoyi-ui/src/views/system/dict/data.vue
+++ b/ruoyi-ui/src/views/system/dict/data.vue
@@ -305,8 +305,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -315,8 +313,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/dict/index.vue b/ruoyi-ui/src/views/system/dict/index.vue
index 9c3f64732..779c173a1 100644
--- a/ruoyi-ui/src/views/system/dict/index.vue
+++ b/ruoyi-ui/src/views/system/dict/index.vue
@@ -94,6 +94,15 @@
           v-hasPermi="['system:dict:export']"
         >导出</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-refresh"
+          size="mini"
+          @click="handleClearCache"
+          v-hasPermi="['system:dict:remove']"
+        >清理缓存</el-button>
+      </el-col>
     </el-row>
 
     <el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
@@ -173,7 +182,7 @@
 </template>
 
 <script>
-import { listType, getType, delType, addType, updateType, exportType } from "@/api/system/dict/type";
+import { listType, getType, delType, addType, updateType, exportType, clearCache } from "@/api/system/dict/type";
 
 export default {
   name: "Dict",
@@ -300,8 +309,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -310,8 +317,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -344,6 +349,14 @@ export default {
         }).then(response => {
           this.download(response.msg);
         }).catch(function() {});
+    },
+    /** 清理缓存按钮操作 */
+    handleClearCache() {
+      clearCache().then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("清理成功");
+        }
+      });
     }
   }
 };
diff --git a/ruoyi-ui/src/views/system/menu/index.vue b/ruoyi-ui/src/views/system/menu/index.vue
index 74b43786c..1e36780b5 100644
--- a/ruoyi-ui/src/views/system/menu/index.vue
+++ b/ruoyi-ui/src/views/system/menu/index.vue
@@ -340,8 +340,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -350,8 +348,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/notice/index.vue b/ruoyi-ui/src/views/system/notice/index.vue
index 50dcd3ebd..828dd3e4c 100644
--- a/ruoyi-ui/src/views/system/notice/index.vue
+++ b/ruoyi-ui/src/views/system/notice/index.vue
@@ -308,8 +308,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -318,8 +316,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/post/index.vue b/ruoyi-ui/src/views/system/post/index.vue
index 42a66b434..046ef220d 100644
--- a/ruoyi-ui/src/views/system/post/index.vue
+++ b/ruoyi-ui/src/views/system/post/index.vue
@@ -277,8 +277,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -287,8 +285,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue
index 42e3d828a..658efc617 100644
--- a/ruoyi-ui/src/views/system/role/index.vue
+++ b/ruoyi-ui/src/views/system/role/index.vue
@@ -482,8 +482,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -493,8 +491,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -510,8 +506,6 @@ export default {
             this.msgSuccess("修改成功");
             this.openDataScope = false;
             this.getList();
-          } else {
-            this.msgError(response.msg);
           }
         });
       }
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 582e7464e..51c262731 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -133,7 +133,7 @@
         </el-row>
 
         <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
-          <el-table-column type="selection" width="40" align="center" />
+          <el-table-column type="selection" width="50" align="center" />
           <el-table-column label="用户编号" align="center" prop="userId" />
           <el-table-column label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
           <el-table-column label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
@@ -208,9 +208,11 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="归属部门" prop="deptId">
-              <treeselect v-model="form.deptId" :options="deptOptions" placeholder="请选择归属部门" />
+              <treeselect v-model="form.deptId" :options="deptOptions" :disable-branch-nodes="true" :show-count="true" placeholder="请选择归属部门" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12">
             <el-form-item label="手机号码" prop="phonenumber">
               <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
@@ -221,6 +223,8 @@
               <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12">
             <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
               <el-input v-model="form.userName" placeholder="请输入用户名称" />
@@ -231,6 +235,8 @@
               <el-input v-model="form.password" placeholder="请输入用户密码" type="password" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12">
             <el-form-item label="用户性别">
               <el-select v-model="form.sex" placeholder="请选择">
@@ -254,7 +260,8 @@
               </el-radio-group>
             </el-form-item>
           </el-col>
-
+        </el-row>
+        <el-row>
           <el-col :span="12">
             <el-form-item label="岗位">
               <el-select v-model="form.postIds" multiple placeholder="请选择">
@@ -281,6 +288,8 @@
               </el-select>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="24">
             <el-form-item label="备注">
               <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
@@ -572,8 +581,6 @@ export default {
           resetUserPwd(row.userId, value).then(response => {
             if (response.code === 200) {
               this.msgSuccess("修改成功,新密码是:" + value);
-            } else {
-              this.msgError(response.msg);
             }
           });
         }).catch(() => {});
@@ -588,8 +595,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -598,8 +603,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi-ui/src/views/system/user/profile/resetPwd.vue b/ruoyi-ui/src/views/system/user/profile/resetPwd.vue
index 380e16865..e39948e34 100644
--- a/ruoyi-ui/src/views/system/user/profile/resetPwd.vue
+++ b/ruoyi-ui/src/views/system/user/profile/resetPwd.vue
@@ -59,8 +59,6 @@ export default {
             response => {
               if (response.code === 200) {
                 this.msgSuccess("修改成功");
-              } else {
-                this.msgError(response.msg);
               }
             }
           );
diff --git a/ruoyi-ui/src/views/system/user/profile/userAvatar.vue b/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
index 5446ab5d9..8f60085d4 100644
--- a/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
+++ b/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
@@ -1,7 +1,7 @@
 <template>
   <div>
     <img v-bind:src="options.img" @click="editCropper()" title="点击上传头像" class="img-circle img-lg" />
-    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
+    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened">
       <el-row>
         <el-col :xs="24" :md="12" :style="{height: '350px'}">
           <vue-cropper
@@ -13,6 +13,7 @@
             :autoCropHeight="options.autoCropHeight"
             :fixedBox="options.fixedBox"
             @realTime="realTime"
+            v-if="visible"
           />
         </el-col>
         <el-col :xs="24" :md="12" :style="{height: '350px'}">
@@ -67,6 +68,8 @@ export default {
     return {
       // 是否显示弹出层
       open: false,
+      // 是否显示cropper
+      visible: false,
       // 弹出层标题
       title: "修改头像",
       options: {
@@ -84,6 +87,10 @@ export default {
     editCropper() {
       this.open = true;
     },
+    // 打开弹出层结束时的回调
+    modalOpened() {
+      this.visible = true;
+    },
     // 覆盖默认的上传行为
     requestUpload() {
     },
@@ -121,11 +128,10 @@ export default {
           if (response.code === 200) {
             this.open = false;
             this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
+            store.commit('SET_AVATAR', this.options.img);
             this.msgSuccess("修改成功");
-          } else {
-            this.msgError(response.msg);
           }
-          this.$refs.cropper.clearCrop();
+          this.visible = false;
         });
       });
     },
diff --git a/ruoyi-ui/src/views/system/user/profile/userInfo.vue b/ruoyi-ui/src/views/system/user/profile/userInfo.vue
index 2e8ef99d9..0b1780d9b 100644
--- a/ruoyi-ui/src/views/system/user/profile/userInfo.vue
+++ b/ruoyi-ui/src/views/system/user/profile/userInfo.vue
@@ -64,8 +64,6 @@ export default {
           updateUserProfile(this.user).then(response => {
             if (response.code === 200) {
               this.msgSuccess("修改成功");
-            } else {
-              this.msgError(response.msg);
             }
           });
         }
diff --git a/ruoyi-ui/src/views/tool/gen/editTable.vue b/ruoyi-ui/src/views/tool/gen/editTable.vue
index 5f88c1a3d..fb1bba1c5 100644
--- a/ruoyi-ui/src/views/tool/gen/editTable.vue
+++ b/ruoyi-ui/src/views/tool/gen/editTable.vue
@@ -147,8 +147,8 @@ export default {
       info: {}
     };
   },
-  beforeCreate() {
-    const { tableId } = this.$route.query;
+  created() {
+    const tableId = this.$route.params && this.$route.params.tableId;
     if (tableId) {
       // 获取表详细信息
       getGenTable(tableId).then(res => {
diff --git a/ruoyi-ui/src/views/tool/gen/index.vue b/ruoyi-ui/src/views/tool/gen/index.vue
index f32c7d4f1..a819f51e0 100644
--- a/ruoyi-ui/src/views/tool/gen/index.vue
+++ b/ruoyi-ui/src/views/tool/gen/index.vue
@@ -270,7 +270,7 @@ export default {
     /** 修改按钮操作 */
     handleEditTable(row) {
       const tableId = row.tableId || this.ids[0];
-      this.$router.push({ path: "/gen/edit", query: { tableId: tableId } });
+      this.$router.push("/gen/edit/" + tableId);
     },
     /** 删除按钮操作 */
     handleDelete(row) {
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index 5dce8d694..b7f16f3e8 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -82,12 +82,6 @@ module.exports = {
       })
       .end()
 
-    config
-      // https://webpack.js.org/configuration/devtool/#development
-      .when(process.env.NODE_ENV === 'development',
-        config => config.devtool('cheap-source-map')
-      )
-
     config
       .when(process.env.NODE_ENV !== 'development',
         config => {
@@ -123,7 +117,11 @@ module.exports = {
                 }
               }
             })
-          config.optimization.runtimeChunk('single')
+          config.optimization.runtimeChunk('single'),
+          {
+             from: path.resolve(__dirname, './public/robots.txt'),//防爬虫文件
+             to:'./',//到根目录下
+          }
         }
       )
   }
diff --git a/ruoyi/pom.xml b/ruoyi/pom.xml
index 2afc4193f..bd9af4845 100644
--- a/ruoyi/pom.xml
+++ b/ruoyi/pom.xml
@@ -5,7 +5,7 @@
 
 	<groupId>com.ruoyi</groupId>
 	<artifactId>ruoyi</artifactId>
-	<version>2.2.0</version>
+	<version>2.3.0</version>
 	<packaging>jar</packaging>
 
 	<name>ruoyi</name>
@@ -25,7 +25,7 @@
 		<java.version>1.8</java.version>
 		<mybatis.spring.boot.starter.version>1.3.2</mybatis.spring.boot.starter.version>
 		<pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version>
-		<fastjson.version>1.2.68</fastjson.version>
+		<fastjson.version>1.2.70</fastjson.version>
 		<druid.version>1.1.14</druid.version>
 		<commons.io.version>2.5</commons.io.version>
 		<commons.fileupload.version>1.3.3</commons.fileupload.version>
diff --git a/ruoyi/sql/ry_20200415.sql b/ruoyi/sql/ry_20200629.sql
similarity index 98%
rename from ruoyi/sql/ry_20200415.sql
rename to ruoyi/sql/ry_20200629.sql
index cf5124726..7c8e8c87a 100644
--- a/ruoyi/sql/ry_20200415.sql
+++ b/ruoyi/sql/ry_20200629.sql
@@ -120,8 +120,8 @@ create table sys_role (
 -- ----------------------------
 -- 初始化-角色信息表数据
 -- ----------------------------
-insert into sys_role values('1', '管理员',   'admin',  1, 1, '0', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
-insert into sys_role values('2', '普通角色', 'common', 2, 2, '0', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '普通角色');
+insert into sys_role values('1', '系统管理员',  'admin',  1, 1, '0', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '系统管理员');
+insert into sys_role values('2', '普通角色',    'common', 2, 2, '0', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '普通角色');
 
 
 -- ----------------------------
diff --git a/ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java
index f1ad924bf..e3c56ee54 100644
--- a/ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -14,7 +14,7 @@ public class RuoYiApplication
 {
     public static void main(String[] args)
     {
-        System.setProperty("spring.devtools.restart.enabled", "false");
+        // System.setProperty("spring.devtools.restart.enabled", "false");
         SpringApplication.run(RuoYiApplication.class, args);
         System.out.println("(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  \n" +
                 " .-------.       ____     __        \n" +
diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
index 768bc24be..fe8afc003 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -109,6 +109,16 @@ public class Constants
      */
     public static final String JWT_AUTHORITIES = "authorities";
 
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
     /**
      * 资源映射路径 前缀
      */
diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java
index ffdb56d0d..77a479b3c 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/constant/HttpStatus.java
@@ -5,7 +5,7 @@ package com.ruoyi.common.constant;
  * 
  * @author ruoyi
  */
-public interface HttpStatus
+public class HttpStatus
 {
     /**
      * 操作成功
diff --git a/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
index 005e17623..62ad81545 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
@@ -5,7 +5,7 @@ package com.ruoyi.common.constant;
  * 
  * @author ruoyi
  */
-public interface ScheduleConstants
+public class ScheduleConstants
 {
     public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
 
diff --git a/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java b/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java
index 9e1bbeb32..fa7429774 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/core/lang/UUID.java
@@ -376,6 +376,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
      *
      * @return UUID 的哈希码值。
      */
+    @Override
     public int hashCode()
     {
         long hilo = mostSigBits ^ leastSigBits;
@@ -391,6 +392,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
      *
      * @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
      */
+    @Override
     public boolean equals(Object obj)
     {
         if ((null == obj) || (obj.getClass() != UUID.class))
@@ -414,6 +416,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
      * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
      *
      */
+    @Override
     public int compareTo(UUID val)
     {
         // The ordering is intentionally set up so that the UUIDs
diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java
new file mode 100644
index 000000000..0c1ee5dba
--- /dev/null
+++ b/ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java
@@ -0,0 +1,64 @@
+package com.ruoyi.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.redis.RedisCache;
+import com.ruoyi.project.system.domain.SysDictData;
+
+/**
+ * 字典工具类
+ * 
+ * @author ruoyi
+ */
+public class DictUtils
+{
+    /**
+     * 设置字典缓存
+     * 
+     * @param key 参数键
+     * @param dictDatas 字典数据列表
+     */
+    public static void setDictCache(String key, List<SysDictData> dictDatas)
+    {
+        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+    }
+
+    /**
+     * 获取字典缓存
+     * 
+     * @param key 参数键
+     * @return dictDatas 字典数据列表
+     */
+    public static List<SysDictData> getDictCache(String key)
+    {
+        Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+        if (StringUtils.isNotNull(cacheObj))
+        {
+            List<SysDictData> DictDatas = StringUtils.cast(cacheObj);
+            return DictDatas;
+        }
+        return null;
+    }
+
+    /**
+     * 清空字典缓存
+     */
+    public static void clearDictCache()
+    {
+        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(Constants.SYS_DICT_KEY + "*");
+        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+    }
+
+    /**
+     * 设置cache key
+     * 
+     * @param configKey 参数键
+     * @return 缓存键key
+     */
+    public static String getCacheKey(String configKey)
+    {
+        return Constants.SYS_DICT_KEY + configKey;
+    }
+}
diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
index a865c35d1..36b3e0983 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -450,4 +450,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
         }
         return sb.toString();
     }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
 }
\ No newline at end of file
diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java b/ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
index 80b8c84fe..04171810f 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java
@@ -139,10 +139,12 @@ public class VerifyCodeUtils
 
     private static Color getRandColor(int fc, int bc)
     {
-        if (fc > 255)
+        if (fc > 255) {
             fc = 255;
-        if (bc > 255)
+        }
+        if (bc > 255) {
             bc = 255;
+        }
         int r = fc + random.nextInt(bc - fc);
         int g = fc + random.nextInt(bc - fc);
         int b = fc + random.nextInt(bc - fc);
diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
index 20782404f..5e92cde8f 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -118,7 +118,7 @@ public class HttpUtils
         StringBuilder result = new StringBuilder();
         try
         {
-            String urlNameString = url + "?" + param;
+            String urlNameString = url;
             log.info("sendPost - {}", urlNameString);
             URL realUrl = new URL(urlNameString);
             URLConnection conn = realUrl.openConnection();
diff --git a/ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
index 9e050e9f7..771e3f840 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
@@ -4,6 +4,7 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import javax.servlet.http.HttpServletRequest;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
 
 /**
  * 获取IP方法
@@ -40,8 +41,7 @@ public class IpUtils
         {
             ip = request.getRemoteAddr();
         }
-
-        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip);
     }
 
     public static boolean internalIp(String ip)
@@ -110,8 +110,9 @@ public class IpUtils
             {
                 case 1:
                     l = Long.parseLong(elements[0]);
-                    if ((l < 0L) || (l > 4294967295L))
+                    if ((l < 0L) || (l > 4294967295L)) {
                         return null;
+                    }
                     bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                     bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                     bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
@@ -119,12 +120,14 @@ public class IpUtils
                     break;
                 case 2:
                     l = Integer.parseInt(elements[0]);
-                    if ((l < 0L) || (l > 255L))
+                    if ((l < 0L) || (l > 255L)) {
                         return null;
+                    }
                     bytes[0] = (byte) (int) (l & 0xFF);
                     l = Integer.parseInt(elements[1]);
-                    if ((l < 0L) || (l > 16777215L))
+                    if ((l < 0L) || (l > 16777215L)) {
                         return null;
+                    }
                     bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                     bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                     bytes[3] = (byte) (int) (l & 0xFF);
@@ -133,13 +136,15 @@ public class IpUtils
                     for (i = 0; i < 2; ++i)
                     {
                         l = Integer.parseInt(elements[i]);
-                        if ((l < 0L) || (l > 255L))
+                        if ((l < 0L) || (l > 255L)) {
                             return null;
+                        }
                         bytes[i] = (byte) (int) (l & 0xFF);
                     }
                     l = Integer.parseInt(elements[2]);
-                    if ((l < 0L) || (l > 65535L))
+                    if ((l < 0L) || (l > 65535L)) {
                         return null;
+                    }
                     bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                     bytes[3] = (byte) (int) (l & 0xFF);
                     break;
@@ -147,8 +152,9 @@ public class IpUtils
                     for (i = 0; i < 4; ++i)
                     {
                         l = Integer.parseInt(elements[i]);
-                        if ((l < 0L) || (l > 255L))
+                        if ((l < 0L) || (l > 255L)) {
                             return null;
+                        }
                         bytes[i] = (byte) (int) (l & 0xFF);
                     }
                     break;
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
index 634f0ed69..e28e9680c 100644
--- a/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
+++ b/ruoyi/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -52,6 +52,11 @@ public class DataScopeAspect
      */
     public static final String DATA_SCOPE_SELF = "5";
 
+    /**
+     * 数据权限过滤关键字
+     */
+    public static final String DATA_SCOPE = "dataScope";
+
     // 配置织入点
     @Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.DataScope)")
     public void dataScopePointCut()
@@ -138,7 +143,7 @@ public class DataScopeAspect
         if (StringUtils.isNotBlank(sqlString.toString()))
         {
             BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0];
-            baseEntity.setDataScope(" AND (" + sqlString.substring(4) + ")");
+            baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
         }
     }
 
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java
index b623cae59..56bbdbfab 100644
--- a/ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java
+++ b/ruoyi/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java
@@ -36,6 +36,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
         this.clazz = clazz;
     }
 
+    @Override
     public byte[] serialize(T t) throws SerializationException
     {
         if (t == null)
@@ -45,6 +46,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
         return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
     }
 
+    @Override
     public T deserialize(byte[] bytes) throws SerializationException
     {
         if (bytes == null || bytes.length <= 0)
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java b/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java
index 6ed760cbf..08f4f9027 100644
--- a/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java
+++ b/ruoyi/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java
@@ -36,9 +36,6 @@ public class BaseEntity implements Serializable
     /** 备注 */
     private String remark;
 
-    /** 数据权限 */
-    private String dataScope;
-
     /** 开始时间 */
     @JsonIgnore
     private String beginTime;
@@ -110,16 +107,6 @@ public class BaseEntity implements Serializable
         this.remark = remark;
     }
 
-    public String getDataScope()
-    {
-        return dataScope;
-    }
-
-    public void setDataScope(String dataScope)
-    {
-        this.dataScope = dataScope;
-    }
-
     public String getBeginTime()
     {
         return beginTime;
diff --git a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
index 65193dd89..954bc08f7 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
@@ -47,6 +47,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService
      * @param operIds 需要删除的操作日志ID
      * @return 结果
      */
+    @Override
     public int deleteOperLogByIds(Long[] operIds)
     {
         return operLogMapper.deleteOperLogByIds(operIds);
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
index 1d59084d7..9a832cb59 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
@@ -118,4 +118,16 @@ public class SysConfigController extends BaseController
     {
         return toAjax(configService.deleteConfigByIds(configIds));
     }
+
+    /**
+     * 清空缓存
+     */
+    @PreAuthorize("@ss.hasPermi('system:config:remove')")
+    @Log(title = "参数管理", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clearCache")
+    public AjaxResult clearCache()
+    {
+        configService.clearCache();
+        return AjaxResult.success();
+    }
 }
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
index 60becb14a..8b3b394e5 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
@@ -21,6 +21,7 @@ import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.page.TableDataInfo;
 import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.service.ISysDictDataService;
+import com.ruoyi.project.system.service.ISysDictTypeService;
 
 /**
  * 数据字典信息
@@ -34,6 +35,9 @@ public class SysDictDataController extends BaseController
     @Autowired
     private ISysDictDataService dictDataService;
 
+    @Autowired
+    private ISysDictTypeService dictTypeService;
+
     @PreAuthorize("@ss.hasPermi('system:dict:list')")
     @GetMapping("/list")
     public TableDataInfo list(SysDictData dictData)
@@ -66,10 +70,10 @@ public class SysDictDataController extends BaseController
     /**
      * 根据字典类型查询字典数据信息
      */
-    @GetMapping(value = "/dictType/{dictType}")
+    @GetMapping(value = "/type/{dictType}")
     public AjaxResult dictType(@PathVariable String dictType)
     {
-        return AjaxResult.success(dictDataService.selectDictDataByType(dictType));
+        return AjaxResult.success(dictTypeService.selectDictDataByType(dictType));
     }
 
     /**
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
index 423620664..816d5438a 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
@@ -107,6 +107,18 @@ public class SysDictTypeController extends BaseController
         return toAjax(dictTypeService.deleteDictTypeByIds(dictIds));
     }
 
+    /**
+     * 清空缓存
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clearCache")
+    public AjaxResult clearCache()
+    {
+        dictTypeService.clearCache();
+        return AjaxResult.success();
+    }
+
     /**
      * 获取字典选择框列表
      */
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
index 6871d836a..df8231781 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
@@ -42,10 +42,7 @@ public class SysLoginController
     /**
      * 登录方法
      * 
-     * @param username 用户名
-     * @param password 密码
-     * @param captcha 验证码
-     * @param uuid 唯一标识
+     * @param loginBody 登陆信息
      * @return 结果
      */
     @PostMapping("/login")
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
index f40f7693d..0c30ef798 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
@@ -48,7 +48,7 @@ public class SysPostController extends BaseController
     }
     
     @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
-    @PreAuthorize("@ss.hasPermi('system:config:export')")
+    @PreAuthorize("@ss.hasPermi('system:post:export')")
     @GetMapping("/export")
     public AjaxResult export(SysPost post)
     {
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
index b93e8eb24..5c6857008 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -1,6 +1,7 @@
 package com.ruoyi.project.system.controller;
 
 import java.util.List;
+import java.util.stream.Collectors;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -25,6 +26,7 @@ import com.ruoyi.framework.security.service.TokenService;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.domain.SysRole;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysPostService;
 import com.ruoyi.project.system.service.ISysRoleService;
@@ -101,7 +103,8 @@ public class SysUserController extends BaseController
     public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
     {
         AjaxResult ajax = AjaxResult.success();
-        ajax.put("roles", roleService.selectRoleAll());
+        List<SysRole> roles = roleService.selectRoleAll();
+        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
         ajax.put("posts", postService.selectPostAll());
         if (StringUtils.isNotNull(userId))
         {
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java
index ca33e32d1..677c2e461 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/domain/SysRole.java
@@ -178,6 +178,7 @@ public class SysRole extends BaseEntity
         this.deptIds = deptIds;
     }
     
+    @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
             .append("roleId", getRoleId())
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java
index 9fa70fcda..4d95ee7e9 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java
@@ -50,14 +50,6 @@ public interface ISysConfigService
      */
     public int updateConfig(SysConfig config);
 
-    /**
-     * 删除参数配置信息
-     * 
-     * @param configId 参数ID
-     * @return 结果
-     */
-    public int deleteConfigById(Long configId);
-
     /**
      * 批量删除参数信息
      * 
@@ -66,6 +58,11 @@ public interface ISysConfigService
      */
     public int deleteConfigByIds(Long[] configIds);
 
+    /**
+     * 清空缓存数据
+     */
+    public void clearCache();
+
     /**
      * 校验参数键名是否唯一
      * 
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java
index 870f35792..65693d119 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java
@@ -18,14 +18,6 @@ public interface ISysDictDataService
      */
     public List<SysDictData> selectDictDataList(SysDictData dictData);
 
-    /**
-     * 根据字典类型查询字典数据
-     * 
-     * @param dictType 字典类型
-     * @return 字典数据集合信息
-     */
-    public List<SysDictData> selectDictDataByType(String dictType);
-
     /**
      * 根据字典类型和字典键值查询字典数据信息
      * 
@@ -43,14 +35,6 @@ public interface ISysDictDataService
      */
     public SysDictData selectDictDataById(Long dictCode);
 
-    /**
-     * 通过字典ID删除字典数据信息
-     * 
-     * @param dictCode 字典数据ID
-     * @return 结果
-     */
-    public int deleteDictDataById(Long dictCode);
-
     /**
      * 批量删除字典数据信息
      * 
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java
index 326beb757..c6708d32e 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.project.system.service;
 
 import java.util.List;
+import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.domain.SysDictType;
 
 /**
@@ -25,6 +26,14 @@ public interface ISysDictTypeService
      */
     public List<SysDictType> selectDictTypeAll();
 
+    /**
+     * 根据字典类型查询字典数据
+     * 
+     * @param dictType 字典类型
+     * @return 字典数据集合信息
+     */
+    public List<SysDictData> selectDictDataByType(String dictType);
+
     /**
      * 根据字典类型ID查询信息
      * 
@@ -41,14 +50,6 @@ public interface ISysDictTypeService
      */
     public SysDictType selectDictTypeByType(String dictType);
 
-    /**
-     * 通过字典ID删除字典信息
-     * 
-     * @param dictId 字典ID
-     * @return 结果
-     */
-    public int deleteDictTypeById(Long dictId);
-
     /**
      * 批量删除字典信息
      * 
@@ -57,6 +58,11 @@ public interface ISysDictTypeService
      */
     public int deleteDictTypeByIds(Long[] dictIds);
 
+    /**
+     * 清空缓存数据
+     */
+    public void clearCache();
+
     /**
      * 新增保存字典类型信息
      * 
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
index fa54a6b3c..88f5475d6 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
@@ -1,10 +1,15 @@
 package com.ruoyi.project.system.service.impl;
 
+import java.util.Collection;
 import java.util.List;
+import javax.annotation.PostConstruct;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.redis.RedisCache;
 import com.ruoyi.project.system.domain.SysConfig;
 import com.ruoyi.project.system.mapper.SysConfigMapper;
 import com.ruoyi.project.system.service.ISysConfigService;
@@ -20,6 +25,22 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Autowired
     private SysConfigMapper configMapper;
 
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 项目启动时,初始化参数到缓存
+     */
+    @PostConstruct
+    public void init()
+    {
+        List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
+        for (SysConfig config : configsList)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+    }
+
     /**
      * 查询参数配置信息
      * 
@@ -43,10 +64,20 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Override
     public String selectConfigByKey(String configKey)
     {
+        String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
+        if (StringUtils.isNotEmpty(configValue))
+        {
+            return configValue;
+        }
         SysConfig config = new SysConfig();
         config.setConfigKey(configKey);
         SysConfig retConfig = configMapper.selectConfig(config);
-        return StringUtils.isNotNull(retConfig) ? retConfig.getConfigValue() : "";
+        if (StringUtils.isNotNull(retConfig))
+        {
+            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
+            return retConfig.getConfigValue();
+        }
+        return StringUtils.EMPTY;
     }
 
     /**
@@ -70,7 +101,12 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Override
     public int insertConfig(SysConfig config)
     {
-        return configMapper.insertConfig(config);
+        int row = configMapper.insertConfig(config);
+        if (row > 0)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+        return row;
     }
 
     /**
@@ -82,19 +118,12 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Override
     public int updateConfig(SysConfig config)
     {
-        return configMapper.updateConfig(config);
-    }
-
-    /**
-     * 删除参数配置信息
-     * 
-     * @param configId 参数ID
-     * @return 结果
-     */
-    @Override
-    public int deleteConfigById(Long configId)
-    {
-        return configMapper.deleteConfigById(configId);
+        int row = configMapper.updateConfig(config);
+        if (row > 0)
+        {
+            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+        }
+        return row;
     }
 
     /**
@@ -106,7 +135,23 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Override
     public int deleteConfigByIds(Long[] configIds)
     {
-        return configMapper.deleteConfigByIds(configIds);
+        int count = configMapper.deleteConfigByIds(configIds);
+        if (count > 0)
+        {
+            Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
+            redisCache.deleteObject(keys);
+        }
+        return count;
+    }
+
+    /**
+     * 清空缓存数据
+     */
+    @Override
+    public void clearCache()
+    {
+        Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
+        redisCache.deleteObject(keys);
     }
 
     /**
@@ -126,4 +171,15 @@ public class SysConfigServiceImpl implements ISysConfigService
         }
         return UserConstants.UNIQUE;
     }
+
+    /**
+     * 设置cache key
+     * 
+     * @param configKey 参数键
+     * @return 缓存键key
+     */
+    private String getCacheKey(String configKey)
+    {
+        return Constants.SYS_CONFIG_KEY + configKey;
+    }
 }
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
index e8475dc4a..065a2ce80 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
@@ -3,6 +3,7 @@ package com.ruoyi.project.system.service.impl;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.mapper.SysDictDataMapper;
 import com.ruoyi.project.system.service.ISysDictDataService;
@@ -30,18 +31,6 @@ public class SysDictDataServiceImpl implements ISysDictDataService
         return dictDataMapper.selectDictDataList(dictData);
     }
 
-    /**
-     * 根据字典类型查询字典数据
-     * 
-     * @param dictType 字典类型
-     * @return 字典数据集合信息
-     */
-    @Override
-    public List<SysDictData> selectDictDataByType(String dictType)
-    {
-        return dictDataMapper.selectDictDataByType(dictType);
-    }
-
     /**
      * 根据字典类型和字典键值查询字典数据信息
      * 
@@ -67,27 +56,21 @@ public class SysDictDataServiceImpl implements ISysDictDataService
         return dictDataMapper.selectDictDataById(dictCode);
     }
 
-    /**
-     * 通过字典ID删除字典数据信息
-     * 
-     * @param dictCode 字典数据ID
-     * @return 结果
-     */
-    @Override
-    public int deleteDictDataById(Long dictCode)
-    {
-        return dictDataMapper.deleteDictDataById(dictCode);
-    }
-
     /**
      * 批量删除字典数据信息
      * 
      * @param dictCodes 需要删除的字典数据ID
      * @return 结果
      */
+    @Override
     public int deleteDictDataByIds(Long[] dictCodes)
     {
-        return dictDataMapper.deleteDictDataByIds(dictCodes);
+        int row = dictDataMapper.deleteDictDataByIds(dictCodes);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -99,7 +82,12 @@ public class SysDictDataServiceImpl implements ISysDictDataService
     @Override
     public int insertDictData(SysDictData dictData)
     {
-        return dictDataMapper.insertDictData(dictData);
+        int row = dictDataMapper.insertDictData(dictData);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -111,6 +99,11 @@ public class SysDictDataServiceImpl implements ISysDictDataService
     @Override
     public int updateDictData(SysDictData dictData)
     {
-        return dictDataMapper.updateDictData(dictData);
+        int row = dictDataMapper.updateDictData(dictData);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 }
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
index 2cf5f19c1..10fe23bcb 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
@@ -1,11 +1,15 @@
 package com.ruoyi.project.system.service.impl;
 
 import java.util.List;
+import javax.annotation.PostConstruct;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.exception.CustomException;
+import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.domain.SysDictType;
 import com.ruoyi.project.system.mapper.SysDictDataMapper;
 import com.ruoyi.project.system.mapper.SysDictTypeMapper;
@@ -25,6 +29,20 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
     @Autowired
     private SysDictDataMapper dictDataMapper;
 
+    /**
+     * 项目启动时,初始化字典到缓存
+     */
+    @PostConstruct
+    public void init()
+    {
+        List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll();
+        for (SysDictType dictType : dictTypeList)
+        {
+            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
+            DictUtils.setDictCache(dictType.getDictType(), dictDatas);
+        }
+    }
+
     /**
      * 根据条件分页查询字典类型
      * 
@@ -48,6 +66,29 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
         return dictTypeMapper.selectDictTypeAll();
     }
 
+    /**
+     * 根据字典类型查询字典数据
+     * 
+     * @param dictType 字典类型
+     * @return 字典数据集合信息
+     */
+    @Override
+    public List<SysDictData> selectDictDataByType(String dictType)
+    {
+        List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
+        if (StringUtils.isNotNull(dictDatas))
+        {
+            return dictDatas;
+        }
+        dictDatas = dictDataMapper.selectDictDataByType(dictType);
+        if (StringUtils.isNotNull(dictDatas))
+        {
+            DictUtils.setDictCache(dictType, dictDatas);
+            return dictDatas;
+        }
+        return null;
+    }
+
     /**
      * 根据字典类型ID查询信息
      * 
@@ -66,32 +107,44 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
      * @param dictType 字典类型
      * @return 字典类型
      */
+    @Override
     public SysDictType selectDictTypeByType(String dictType)
     {
         return dictTypeMapper.selectDictTypeByType(dictType);
     }
 
-    /**
-     * 通过字典ID删除字典信息
-     * 
-     * @param dictId 字典ID
-     * @return 结果
-     */
-    @Override
-    public int deleteDictTypeById(Long dictId)
-    {
-        return dictTypeMapper.deleteDictTypeById(dictId);
-    }
-
     /**
      * 批量删除字典类型信息
      * 
      * @param dictIds 需要删除的字典ID
      * @return 结果
      */
+    @Override
     public int deleteDictTypeByIds(Long[] dictIds)
     {
-        return dictTypeMapper.deleteDictTypeByIds(dictIds);
+        for (Long dictId : dictIds)
+        {
+            SysDictType dictType = selectDictTypeById(dictId);
+            if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0)
+            {
+                throw new CustomException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
+            }
+        }
+        int count = dictTypeMapper.deleteDictTypeByIds(dictIds);
+        if (count > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return count;
+    }
+
+    /**
+     * 清空缓存数据
+     */
+    @Override
+    public void clearCache()
+    {
+        DictUtils.clearDictCache();
     }
 
     /**
@@ -103,7 +156,12 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
     @Override
     public int insertDictType(SysDictType dictType)
     {
-        return dictTypeMapper.insertDictType(dictType);
+        int row = dictTypeMapper.insertDictType(dictType);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -118,7 +176,12 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
     {
         SysDictType oldDict = dictTypeMapper.selectDictTypeById(dictType.getDictId());
         dictDataMapper.updateDictDataType(oldDict.getDictType(), dictType.getDictType());
-        return dictTypeMapper.updateDictType(dictType);
+        int row = dictTypeMapper.updateDictType(dictType);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
index d8562a351..e5dda00f9 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
@@ -121,6 +121,7 @@ public class SysMenuServiceImpl implements ISysMenuService
      * @param roleId 角色ID
      * @return 选中菜单列表
      */
+    @Override
     public List<Integer> selectMenuListByRoleId(Long roleId)
     {
         return menuMapper.selectMenuListByRoleId(roleId);
@@ -140,7 +141,7 @@ public class SysMenuServiceImpl implements ISysMenuService
         {
             RouterVo router = new RouterVo();
             router.setHidden("1".equals(menu.getVisible()));
-            router.setName(StringUtils.capitalize(menu.getPath()));
+            router.setName(getRouteName(menu));
             router.setPath(getRouterPath(menu));
             router.setComponent(getComponent(menu));
             router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
@@ -299,6 +300,23 @@ public class SysMenuServiceImpl implements ISysMenuService
         return UserConstants.UNIQUE;
     }
 
+    /**
+     * 获取路由名称
+     * 
+     * @param menu 菜单信息
+     * @return 路由名称
+     */
+    public String getRouteName(SysMenu menu)
+    {
+        String routerName = StringUtils.capitalize(menu.getPath());
+        // 非外链并且是一级目录(类型为目录)
+        if (isMeunFrame(menu))
+        {
+            routerName = StringUtils.EMPTY;
+        }
+        return routerName;
+    }
+
     /**
      * 获取路由地址
      * 
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
index 8d0f372f6..2b0191d4a 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -84,6 +84,7 @@ public class SysNoticeServiceImpl implements ISysNoticeService
      * @param noticeIds 需要删除的公告ID
      * @return 结果
      */
+    @Override
     public int deleteNoticeByIds(Long[] noticeIds)
     {
         return noticeMapper.deleteNoticeByIds(noticeIds);
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
index e60dc0684..b013cbb2e 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
@@ -66,6 +66,7 @@ public class SysPostServiceImpl implements ISysPostService
      * @param userId 用户ID
      * @return 选中岗位ID列表
      */
+    @Override
     public List<Integer> selectPostListByUserId(Long userId)
     {
         return postMapper.selectPostListByUserId(userId);
@@ -138,6 +139,7 @@ public class SysPostServiceImpl implements ISysPostService
      * @return 结果
      * @throws Exception 异常
      */
+    @Override
     public int deletePostByIds(Long[] postIds)
     {
         for (Long postId : postIds)
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
index 077d1ac92..71f3c6684 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
@@ -81,6 +81,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * 
      * @return 角色列表
      */
+    @Override
     public List<SysRole> selectRoleAll()
     {
         return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
@@ -92,6 +93,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * @param userId 用户ID
      * @return 选中角色ID列表
      */
+    @Override
     public List<Integer> selectRoleListByUserId(Long userId)
     {
         return roleMapper.selectRoleListByUserId(userId);
@@ -103,6 +105,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * @param roleId 角色ID
      * @return 角色对象信息
      */
+    @Override
     public SysRole selectRoleById(Long roleId)
     {
         return roleMapper.selectRoleById(roleId);
@@ -149,6 +152,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * 
      * @param role 角色信息
      */
+    @Override
     public void checkRoleAllowed(SysRole role)
     {
         if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
@@ -207,6 +211,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * @param role 角色信息
      * @return 结果
      */
+    @Override
     public int updateRoleStatus(SysRole role)
     {
         return roleMapper.updateRole(role);
@@ -296,6 +301,7 @@ public class SysRoleServiceImpl implements ISysRoleService
      * @param roleIds 需要删除的角色ID
      * @return 结果
      */
+    @Override
     public int deleteRoleByIds(Long[] roleIds)
     {
         for (Long roleId : roleIds)
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java
index 756b20ef2..fb45b8017 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java
@@ -72,6 +72,7 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
      * @param user 用户信息
      * @return 在线用户
      */
+    @Override
     public SysUserOnline loginUserToUserOnline(LoginUser user)
     {
         if (StringUtils.isNull(user) && StringUtils.isNull(user.getUser()))
diff --git a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
index 77affcb80..28788e4df 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
@@ -192,6 +192,7 @@ public class SysUserServiceImpl implements ISysUserService
      * 
      * @param user 用户信息
      */
+    @Override
     public void checkUserAllowed(SysUser user)
     {
         if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
@@ -268,10 +269,11 @@ public class SysUserServiceImpl implements ISysUserService
     /**
      * 修改用户头像
      * 
-     * @param userId 用户ID
+     * @param userName 用户名
      * @param avatar 头像地址
      * @return 结果
      */
+    @Override
     public boolean updateUserAvatar(String userName, String avatar)
     {
         return userMapper.updateUserAvatar(userName, avatar) > 0;
@@ -376,6 +378,7 @@ public class SysUserServiceImpl implements ISysUserService
      * @param userIds 需要删除的用户ID
      * @return 结果
      */
+    @Override
     public int deleteUserByIds(Long[] userIds)
     {
         for (Long userId : userIds)
diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
index 38c6359f4..61ae55e3a 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
@@ -21,7 +21,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService
 	/**
      * 查询业务字段列表
      * 
-     * @param genTableColumn 业务字段编号
+     * @param tableId 业务字段编号
      * @return 业务字段集合
      */
 	@Override
diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
index c9fda50dd..b10c54946 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
@@ -80,6 +80,7 @@ public class GenTableServiceImpl implements IGenTableService
      * @param genTable 业务信息
      * @return 数据库表集合
      */
+    @Override
     public List<GenTable> selectDbTableList(GenTable genTable)
     {
         return genTableMapper.selectDbTableList(genTable);
@@ -91,6 +92,7 @@ public class GenTableServiceImpl implements IGenTableService
      * @param tableNames 表名称组
      * @return 数据库表集合
      */
+    @Override
     public List<GenTable> selectDbTableListByNames(String[] tableNames)
     {
         return genTableMapper.selectDbTableListByNames(tableNames);
@@ -121,7 +123,7 @@ public class GenTableServiceImpl implements IGenTableService
     /**
      * 删除业务对象
      * 
-     * @param ids 需要删除的数据ID
+     * @param tableIds 需要删除的数据ID
      * @return 结果
      */
     @Override
@@ -142,9 +144,9 @@ public class GenTableServiceImpl implements IGenTableService
     public void importGenTable(List<GenTable> tableList)
     {
         String operName = SecurityUtils.getUsername();
-        for (GenTable table : tableList)
+        try
         {
-            try
+            for (GenTable table : tableList)
             {
                 String tableName = table.getTableName();
                 GenUtils.initTable(table, operName);
@@ -160,10 +162,10 @@ public class GenTableServiceImpl implements IGenTableService
                     }
                 }
             }
-            catch (Exception e)
-            {
-                log.error("表名 " + table.getTableName() + " 导入失败:", e);
-            }
+        }
+        catch (Exception e)
+        {
+            throw new CustomException("导入失败:" + e.getMessage());
         }
     }
 
@@ -173,6 +175,7 @@ public class GenTableServiceImpl implements IGenTableService
      * @param tableId 表编号
      * @return 预览数据列表
      */
+    @Override
     public Map<String, String> previewCode(Long tableId)
     {
         Map<String, String> dataMap = new LinkedHashMap<>();
@@ -277,6 +280,7 @@ public class GenTableServiceImpl implements IGenTableService
      * 
      * @param genTable 业务信息
      */
+    @Override
     public void validateEdit(GenTable genTable)
     {
         if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
@@ -301,7 +305,7 @@ public class GenTableServiceImpl implements IGenTableService
     /**
      * 设置主键列信息
      * 
-     * @param genTable 业务表信息
+     * @param table 业务表信息
      * @param columns 业务字段列表
      */
     public void setPkColumn(GenTable table, List<GenTableColumn> columns)
diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java
index d74c3e7c3..a2c7fc288 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java
@@ -13,7 +13,7 @@ public interface IGenTableColumnService
     /**
      * 查询业务字段列表
      * 
-     * @param genTableColumn 业务字段编号
+     * @param tableId 业务字段编号
      * @return 业务字段集合
      */
     public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
diff --git a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java
index 047cd2d5a..29a840dd6 100644
--- a/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java
+++ b/ruoyi/src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java
@@ -58,11 +58,11 @@ public class GenUtils
         {
             column.setHtmlType(GenConstants.HTML_INPUT);
 
-            // 如果是浮点型
+            // 如果是浮点型 统一用BigDecimal
             String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
             if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
             {
-                column.setJavaType(GenConstants.TYPE_DOUBLE);
+                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
             }
             // 如果是整形
             else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
diff --git a/ruoyi/src/main/resources/META-INF/spring-devtools.properties b/ruoyi/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 000000000..2b23f85a3
--- /dev/null
+++ b/ruoyi/src/main/resources/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson.*.jar
\ No newline at end of file
diff --git a/ruoyi/src/main/resources/application.yml b/ruoyi/src/main/resources/application.yml
index 89ea4a60a..cf23b8e06 100644
--- a/ruoyi/src/main/resources/application.yml
+++ b/ruoyi/src/main/resources/application.yml
@@ -3,7 +3,7 @@ ruoyi:
   # 名称
   name: RuoYi
   # 版本
-  version: 2.2.0
+  version: 2.3.0
   # 版权年份
   copyrightYear: 2019
   # 实例演示开关
@@ -79,7 +79,7 @@ spring:
 token:
     # 令牌自定义标识
     header: Authorization
-    # 令牌秘钥
+    # 令牌密钥
     secret: abcdefghijklmnopqrstuvwxyz
     # 令牌有效期(默认30分钟)
     expireTime: 30
diff --git a/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml b/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml
index c546dee17..333804636 100644
--- a/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml
+++ b/ruoyi/src/main/resources/mybatis/system/SysDeptMapper.xml
@@ -40,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			AND status = #{status}
 		</if>
 		<!-- 数据范围过滤 -->
-		${dataScope}
+		${params.dataScope}
 		order by d.parent_id, d.order_num
     </select>
     
diff --git a/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml b/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml
index b610053a8..cc15a5141 100644
--- a/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml
+++ b/ruoyi/src/main/resources/mybatis/system/SysDictDataMapper.xml
@@ -38,6 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 				AND status = #{status}
 			</if>
 		</where>
+		order by dict_sort asc
 	</select>
 	
 	<select id="selectDictDataByType" parameterType="SysDictData" resultMap="SysDictDataResult">
@@ -73,7 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	<update id="updateDictData" parameterType="SysDictData">
  		update sys_dict_data
  		<set>
- 			<if test="dictSort != null and dictSort != ''">dict_sort = #{dictSort},</if>
+ 			<if test="dictSort != null">dict_sort = #{dictSort},</if>
  			<if test="dictLabel != null and dictLabel != ''">dict_label = #{dictLabel},</if>
  			<if test="dictValue != null and dictValue != ''">dict_value = #{dictValue},</if>
  			<if test="dictType != null and dictType != ''">dict_type = #{dictType},</if>
@@ -94,7 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  	
  	<insert id="insertDictData" parameterType="SysDictData">
  		insert into sys_dict_data(
- 			<if test="dictSort != null and dictSort != ''">dict_sort,</if>
+ 			<if test="dictSort != null">dict_sort,</if>
  			<if test="dictLabel != null and dictLabel != ''">dict_label,</if>
  			<if test="dictValue != null and dictValue != ''">dict_value,</if>
  			<if test="dictType != null and dictType != ''">dict_type,</if>
@@ -106,7 +107,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="createBy != null and createBy != ''">create_by,</if>
  			create_time
  		)values(
- 		    <if test="dictSort != null and dictSort != ''">#{dictSort},</if>
+ 		    <if test="dictSort != null">#{dictSort},</if>
  		    <if test="dictLabel != null and dictLabel != ''">#{dictLabel},</if>
  			<if test="dictValue != null and dictValue != ''">#{dictValue},</if>
  			<if test="dictType != null and dictType != ''">#{dictType},</if>
diff --git a/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml b/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml
index a5e7be0b7..82524b823 100644
--- a/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml
+++ b/ruoyi/src/main/resources/mybatis/system/SysRoleMapper.xml
@@ -47,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
 		</if>
 		<!-- 数据范围过滤 -->
-		${dataScope}
+		${params.dataScope}
 		order by r.role_sort
 	</select>
     
diff --git a/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml b/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml
index 2e6969cb7..99c0d50e0 100644
--- a/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml
+++ b/ruoyi/src/main/resources/mybatis/system/SysUserMapper.xml
@@ -78,7 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET (#{deptId},ancestors) ))
 		</if>
 		<!-- 数据范围过滤 -->
-		${dataScope}
+		${params.dataScope}
 	</select>
 	
 	<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
diff --git a/ruoyi/src/main/resources/vm/sql/sql.vm b/ruoyi/src/main/resources/vm/sql/sql.vm
index c553476f4..ab17d1bee 100644
--- a/ruoyi/src/main/resources/vm/sql/sql.vm
+++ b/ruoyi/src/main/resources/vm/sql/sql.vm
@@ -6,17 +6,17 @@ values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${business
 SELECT @parentId := LAST_INSERT_ID();
 
 -- 按钮 SQL
-insert into sys_menu  (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values('${functionName}查询', @parentId, '1',  '#', '', 1,  'F', '0',  '0', '${permissionPrefix}:query',        '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
-insert into sys_menu  (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values('${functionName}新增', @parentId, '2',  '#', '', 1,  'F', '0',  '0', '${permissionPrefix}:add',          '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
-insert into sys_menu  (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values('${functionName}修改', @parentId, '3',  '#', '', 1,  'F', '0',  '0', '${permissionPrefix}:edit',         '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
-insert into sys_menu  (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values('${functionName}删除', @parentId, '4',  '#', '', 1,  'F', '0',  '0', '${permissionPrefix}:remove',       '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
-insert into sys_menu  (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values('${functionName}导出', @parentId, '5',  '#', '', 1,  'F', '0',  '0', '${permissionPrefix}:export',       '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
\ No newline at end of file
diff --git a/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
index 1a74fca67..fb10ed6dd 100644
--- a/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
+++ b/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
@@ -146,7 +146,7 @@
               v-for="dict in ${field}Options"
               :key="dict.dictValue"
               :label="dict.dictLabel"
-              #if($column.javaType == "Integer"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
 
             ></el-option>
           </el-select>
@@ -163,7 +163,7 @@
             <el-radio
               v-for="dict in ${field}Options"
               :key="dict.dictValue"
-              #if($column.javaType == "Integer"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
 
             >{{dict.dictLabel}}</el-radio>
           </el-radio-group>
@@ -375,8 +375,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -385,8 +383,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi/src/main/resources/vm/vue/index.vue.vm b/ruoyi/src/main/resources/vm/vue/index.vue.vm
index 7c19a3aab..0b64a0c85 100644
--- a/ruoyi/src/main/resources/vm/vue/index.vue.vm
+++ b/ruoyi/src/main/resources/vm/vue/index.vue.vm
@@ -174,7 +174,7 @@
               v-for="dict in ${field}Options"
               :key="dict.dictValue"
               :label="dict.dictLabel"
-              #if($column.javaType == "Integer"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
 
             ></el-option>
           </el-select>
@@ -191,7 +191,7 @@
             <el-radio
               v-for="dict in ${field}Options"
               :key="dict.dictValue"
-              #if($column.javaType == "Integer"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
 
             >{{dict.dictLabel}}</el-radio>
           </el-radio-group>
@@ -392,8 +392,6 @@ export default {
                 this.msgSuccess("修改成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -402,8 +400,6 @@ export default {
                 this.msgSuccess("新增成功");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
diff --git a/ruoyi/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi/src/main/resources/vm/xml/mapper.xml.vm
index ef9d682b8..6c490a4b4 100644
--- a/ruoyi/src/main/resources/vm/xml/mapper.xml.vm
+++ b/ruoyi/src/main/resources/vm/xml/mapper.xml.vm
@@ -56,14 +56,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="(" suffix=")" suffixOverrides=",">
 #foreach($column in $columns)
 #if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
-            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">$column.columnName,</if>
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName,</if>
 #end
 #end
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
 #foreach($column in $columns)
 #if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
-            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">#{$column.javaField},</if>
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">#{$column.javaField},</if>
 #end
 #end
          </trim>
@@ -74,7 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="SET" suffixOverrides=",">
 #foreach($column in $columns)
 #if($column.columnName != $pkColumn.columnName)
-            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
+            <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
 #end
 #end
         </trim>