From 5f866906d1d14b2b3f2123a49270458c12fecf7e Mon Sep 17 00:00:00 2001
From: 疯狂的狮子li <15040126243@163.com>
Date: 星期一, 01 六月 2020 13:34:08 +0800
Subject: [PATCH] Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue

---
 ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java                          |   10 
 ruoyi-ui/src/api/system/dict/data.js                                                  |    2 
 ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java      |   12 
 ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java         |   22 
 ruoyi-ui/src/views/system/role/index.vue                                              |    8 
 ruoyi/pom.xml                                                                         |    4 
 ruoyi/src/main/java/com/ruoyi/common/utils/DictUtils.java                             |   64 +++
 ruoyi-ui/src/views/system/menu/index.vue                                              |   20 
 ruoyi-ui/src/views/system/user/index.vue                                              |    6 
 ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java           |   13 
 ruoyi-ui/src/assets/styles/element-variables.scss                                     |    2 
 ruoyi/src/main/resources/vm/sql/sql.vm                                                |   10 
 ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java |   90 +++
 ruoyi-ui/src/views/system/dict/index.vue                                              |   25 
 ruoyi-ui/package.json                                                                 |    4 
 ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java    |   12 
 ruoyi-ui/src/api/system/dict/type.js                                                  |   10 
 ruoyi-ui/src/layout/components/Sidebar/Link.vue                                       |   25 
 ruoyi/src/main/resources/vm/vue/index.vue.vm                                          |    4 
 ruoyi/src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java         |   16 
 ruoyi-ui/src/views/system/user/profile/userAvatar.vue                                 |    4 
 ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java   |   87 +++
 ruoyi-ui/src/layout/components/TagsView/index.vue                                     |  577 +++++++++++++--------------
 ruoyi-ui/src/views/system/user/profile/userInfo.vue                                   |    4 
 ruoyi-ui/src/views/system/post/index.vue                                              |    8 
 ruoyi-ui/src/views/system/dict/data.vue                                               |    6 
 ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue                                |    9 
 ruoyi-ui/src/layout/components/Sidebar/index.vue                                      |    4 
 ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java |   46 -
 ruoyi-ui/src/views/system/user/profile/resetPwd.vue                                   |    2 
 ruoyi-ui/src/views/system/notice/index.vue                                            |    6 
 ruoyi/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java    |    8 
 ruoyi/src/main/resources/vm/vue/index-tree.vue.vm                                     |    4 
 ruoyi-ui/vue.config.js                                                                |    6 
 ruoyi-ui/src/views/system/dept/index.vue                                              |   22 
 ruoyi-ui/src/views/monitor/job/index.vue                                              |    6 
 README.md                                                                             |    1 
 ruoyi-ui/src/views/system/config/index.vue                                            |   25 
 ruoyi-ui/src/api/system/config.js                                                     |   10 
 ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java     |   19 
 ruoyi-ui/src/components/SvgIcon/index.vue                                             |    2 
 ruoyi/src/main/java/com/ruoyi/common/utils/StringUtils.java                           |    6 
 ruoyi/src/main/resources/application.yml                                              |    2 
 43 files changed, 715 insertions(+), 508 deletions(-)

diff --git a/README.md b/README.md
index c32ef90..b51fe78 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
 * 鏉冮檺璁よ瘉浣跨敤Jwt锛屾敮鎸佸缁堢璁よ瘉绯荤粺銆�
 * 鏀寔鍔犺浇鍔ㄦ�佹潈闄愯彍鍗曪紝澶氭柟寮忚交鏉炬潈闄愭帶鍒躲��
 * 楂樻晥鐜囧紑鍙戯紝浣跨敤浠g爜鐢熸垚鍣ㄥ彲浠ヤ竴閿敓鎴愬墠鍚庣浠g爜銆�
+* 鎻愪緵浜嗕竴涓狾racle鐗堟湰[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;
diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index 344ee37..e4396f9 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/src/api/system/config.js b/ruoyi-ui/src/api/system/config.js
index f2e792c..aff093d 100644
--- a/ruoyi-ui/src/api/system/config.js
+++ b/ruoyi-ui/src/api/system/config.js
@@ -51,6 +51,14 @@
   })
 }
 
+// 娓呯悊鍙傛暟缂撳瓨
+export function clearCache() {
+  return request({
+    url: '/system/config/clearCache',
+    method: 'delete'
+  })
+}
+
 // 瀵煎嚭鍙傛暟
 export function exportConfig(query) {
   return request({
@@ -58,4 +66,4 @@
     method: 'get',
     params: query
   })
-}
\ No newline at end of file
+}
diff --git a/ruoyi-ui/src/api/system/dict/data.js b/ruoyi-ui/src/api/system/dict/data.js
index 5597204..d7aca89 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 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 b8d974e..37034d2 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 clearCache() {
+  return request({
+    url: '/system/dict/type/clearCache',
+    method: 'delete'
+  })
+}
+
 // 瀵煎嚭瀛楀吀绫诲瀷
 export function exportType(query) {
   return request({
@@ -58,4 +66,4 @@
     url: '/system/dict/type/optionselect',
     method: 'get'
   })
-}
\ No newline at end of file
+}
diff --git a/ruoyi-ui/src/assets/styles/element-variables.scss b/ruoyi-ui/src/assets/styles/element-variables.scss
index 30a0e6b..8b7a48e 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/components/SvgIcon/index.vue b/ruoyi-ui/src/components/SvgIcon/index.vue
index dbca903..e4bf5ad 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 eb4dd10..530b3d5 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 @@
       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 3b69584..c030aa1 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 0ec76e7..34a7e55 100644
--- a/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue
+++ b/ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue
@@ -19,12 +19,21 @@
       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 ccccc71..19a2011 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;
-                }
-            }
-        }
+    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;
+      }
     }
-    .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;
-            }
-        }
-    }
+  }
 }
 </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/views/monitor/job/index.vue b/ruoyi-ui/src/views/monitor/job/index.vue
index 3a69360..c5f2f40 100644
--- a/ruoyi-ui/src/views/monitor/job/index.vue
+++ b/ruoyi-ui/src/views/monitor/job/index.vue
@@ -438,8 +438,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -448,8 +446,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -485,4 +481,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/config/index.vue b/ruoyi-ui/src/views/system/config/index.vue
index 035ec82..dffe611 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 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -306,8 +313,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -340,7 +345,15 @@
         }).then(response => {
           this.download(response.msg);
         }).catch(function() {});
+    },
+    /** 娓呯悊缂撳瓨鎸夐挳鎿嶄綔 */
+    handleClearCache() {
+      clearCache().then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("娓呯悊鎴愬姛");
+        }
+      });
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/dept/index.vue b/ruoyi-ui/src/views/system/dept/index.vue
index b503d85..c1e5d47 100644
--- a/ruoyi-ui/src/views/system/dept/index.vue
+++ b/ruoyi-ui/src/views/system/dept/index.vue
@@ -56,17 +56,17 @@
       </el-table-column>
       <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button 
-            size="mini" 
-            type="text" 
-            icon="el-icon-edit" 
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['system:dept:edit']"
           >淇敼</el-button>
-          <el-button 
-            size="mini" 
-            type="text" 
-            icon="el-icon-plus" 
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
             @click="handleAdd(scope.row)"
             v-hasPermi="['system:dept:add']"
           >鏂板</el-button>
@@ -281,8 +281,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -291,8 +289,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -314,4 +310,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/dict/data.vue b/ruoyi-ui/src/views/system/dict/data.vue
index f0407c4..7108e32 100644
--- a/ruoyi-ui/src/views/system/dict/data.vue
+++ b/ruoyi-ui/src/views/system/dict/data.vue
@@ -305,8 +305,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -315,8 +313,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -352,4 +348,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/dict/index.vue b/ruoyi-ui/src/views/system/dict/index.vue
index cdc849c..c2a4f0f 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 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -310,8 +317,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -344,7 +349,15 @@
         }).then(response => {
           this.download(response.msg);
         }).catch(function() {});
+    },
+    /** 娓呯悊缂撳瓨鎸夐挳鎿嶄綔 */
+    handleClearCache() {
+      clearCache().then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("娓呯悊鎴愬姛");
+        }
+      });
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/menu/index.vue b/ruoyi-ui/src/views/system/menu/index.vue
index 61a22e5..e9b8c9e 100644
--- a/ruoyi-ui/src/views/system/menu/index.vue
+++ b/ruoyi-ui/src/views/system/menu/index.vue
@@ -49,16 +49,16 @@
       </el-table-column>
       <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button size="mini" 
-            type="text" 
-            icon="el-icon-edit" 
+          <el-button size="mini"
+            type="text"
+            icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['system:menu:edit']"
           >淇敼</el-button>
-          <el-button 
-            size="mini" 
-            type="text" 
-            icon="el-icon-plus" 
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
             @click="handleAdd(scope.row)"
             v-hasPermi="['system:menu:add']"
           >鏂板</el-button>
@@ -340,8 +340,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -350,8 +348,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -373,4 +369,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/notice/index.vue b/ruoyi-ui/src/views/system/notice/index.vue
index a67d978..9af05ff 100644
--- a/ruoyi-ui/src/views/system/notice/index.vue
+++ b/ruoyi-ui/src/views/system/notice/index.vue
@@ -308,8 +308,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -318,8 +316,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -342,4 +338,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/post/index.vue b/ruoyi-ui/src/views/system/post/index.vue
index 2a489ab..77c916f 100644
--- a/ruoyi-ui/src/views/system/post/index.vue
+++ b/ruoyi-ui/src/views/system/post/index.vue
@@ -107,7 +107,7 @@
         </template>
       </el-table-column>
     </el-table>
-    
+
     <pagination
       v-show="total>0"
       :total="total"
@@ -277,8 +277,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -287,8 +285,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -324,4 +320,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue
index fa2a9b2..c9389fd 100644
--- a/ruoyi-ui/src/views/system/role/index.vue
+++ b/ruoyi-ui/src/views/system/role/index.vue
@@ -482,8 +482,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -493,8 +491,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }
@@ -510,8 +506,6 @@
             this.msgSuccess("淇敼鎴愬姛");
             this.openDataScope = false;
             this.getList();
-          } else {
-            this.msgError(response.msg);
           }
         });
       }
@@ -545,4 +539,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 0bfa88a..ec0a789 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -572,8 +572,6 @@
           resetUserPwd(row.userId, value).then(response => {
             if (response.code === 200) {
               this.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value);
-            } else {
-              this.msgError(response.msg);
             }
           });
         }).catch(() => {});
@@ -588,8 +586,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -598,8 +594,6 @@
                 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 3de5dfd..0ff3435 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 @@
             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 2fd78e2..9bb5d4a 100644
--- a/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
+++ b/ruoyi-ui/src/views/system/user/profile/userAvatar.vue
@@ -122,8 +122,6 @@
             this.open = false;
             this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
             this.msgSuccess("淇敼鎴愬姛");
-          } else {
-            this.msgError(response.msg);
           }
           this.$refs.cropper.clearCrop();
         });
@@ -135,4 +133,4 @@
     }
   }
 };
-</script>
\ No newline at end of file
+</script>
diff --git a/ruoyi-ui/src/views/system/user/profile/userInfo.vue b/ruoyi-ui/src/views/system/user/profile/userInfo.vue
index e50198f..48b8537 100644
--- a/ruoyi-ui/src/views/system/user/profile/userInfo.vue
+++ b/ruoyi-ui/src/views/system/user/profile/userInfo.vue
@@ -2,7 +2,7 @@
   <el-form ref="form" :model="user" :rules="rules" label-width="80px">
     <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
       <el-input v-model="user.nickName" />
-    </el-form-item> 
+    </el-form-item>
     <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
       <el-input v-model="user.phonenumber" maxlength="11" />
     </el-form-item>
@@ -64,8 +64,6 @@
           updateUserProfile(this.user).then(response => {
             if (response.code === 200) {
               this.msgSuccess("淇敼鎴愬姛");
-            } else {
-              this.msgError(response.msg);
             }
           });
         }
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index b62fbbf..4cf5f28 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -83,12 +83,6 @@
       .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 => {
           config
diff --git a/ruoyi/pom.xml b/ruoyi/pom.xml
index 7de0512..982e7b3 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/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
index 81f14ef..1f7b996 100644
--- a/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -110,6 +110,16 @@
     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:";
+
+    /**
      * 璧勬簮鏄犲皠璺緞 鍓嶇紑
      */
     public static final String RESOURCE_PREFIX = "/profile";
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 0000000..0c1ee5d
--- /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 缂撳瓨閿甼ey
+     */
+    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 e32daa5..7e3969f 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 @@
         }
         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/project/system/controller/SysConfigController.java b/ruoyi/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
index db95669..0f32e76 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 @@
     {
         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 3fa53d5..9648785 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.page.TableDataInfo;
 import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.service.ISysDictDataService;
+import com.ruoyi.project.system.service.ISysDictTypeService;
 
 /**
  * 鏁版嵁瀛楀吀淇℃伅
@@ -33,6 +34,9 @@
 {
     @Autowired
     private ISysDictDataService dictDataService;
+
+    @Autowired
+    private ISysDictTypeService dictTypeService;
 
     @PreAuthorize("@ss.hasPermi('system:dict:list')")
     @GetMapping("/list")
@@ -66,10 +70,10 @@
     /**
      * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
      */
-    @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 82d93d9..bda8748 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
@@ -108,6 +108,18 @@
     }
 
     /**
+     * 娓呯┖缂撳瓨
+     */
+    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clearCache")
+    public AjaxResult clearCache()
+    {
+        dictTypeService.clearCache();
+        return AjaxResult.success();
+    }
+
+    /**
      * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
      */
     @GetMapping("/optionselect")
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 ec24110..f5aa2f0 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
@@ -51,14 +51,6 @@
     public int updateConfig(SysConfig config);
 
     /**
-     * 鍒犻櫎鍙傛暟閰嶇疆淇℃伅
-     * 
-     * @param configId 鍙傛暟ID
-     * @return 缁撴灉
-     */
-    public int deleteConfigById(Long configId);
-
-    /**
      * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
      * 
      * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
@@ -67,6 +59,11 @@
     public int deleteConfigByIds(Long[] configIds);
 
     /**
+     * 娓呯┖缂撳瓨鏁版嵁
+     */
+    public void clearCache();
+
+    /**
      * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
      * 
      * @param config 鍙傛暟淇℃伅
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 8330365..f34bef1 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
@@ -19,14 +19,6 @@
     public List<SysDictData> selectDictDataList(SysDictData dictData);
 
     /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
-     * 
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    public List<SysDictData> selectDictDataByType(String dictType);
-
-    /**
      * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
      * 
      * @param dictType 瀛楀吀绫诲瀷
@@ -42,14 +34,6 @@
      * @return 瀛楀吀鏁版嵁
      */
     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 7c650db..9b69411 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;
 
 /**
@@ -26,6 +27,14 @@
     public List<SysDictType> selectDictTypeAll();
 
     /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    public List<SysDictData> selectDictDataByType(String dictType);
+
+    /**
      * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
      * 
      * @param dictId 瀛楀吀绫诲瀷ID
@@ -42,14 +51,6 @@
     public SysDictType selectDictTypeByType(String dictType);
 
     /**
-     * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀淇℃伅
-     * 
-     * @param dictId 瀛楀吀ID
-     * @return 缁撴灉
-     */
-    public int deleteDictTypeById(Long dictId);
-
-    /**
      * 鎵归噺鍒犻櫎瀛楀吀淇℃伅
      * 
      * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
@@ -58,6 +59,11 @@
     public int deleteDictTypeByIds(Long[] dictIds);
 
     /**
+     * 娓呯┖缂撳瓨鏁版嵁
+     */
+    public void clearCache();
+
+    /**
      * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
      * 
      * @param dictType 瀛楀吀绫诲瀷淇℃伅
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 6843388..fcb26d4 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;
@@ -19,6 +24,22 @@
 {
     @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 @@
     @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 @@
     @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 @@
     @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,22 @@
     @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;
+    }
+
+    /**
+     * 娓呯┖缂撳瓨鏁版嵁
+     */
+    public void clearCache()
+    {
+        Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
+        redisCache.deleteObject(keys);
     }
 
     /**
@@ -126,4 +170,15 @@
         }
         return UserConstants.UNIQUE;
     }
+
+    /**
+     * 璁剧疆cache key
+     *
+     * @param configKey 鍙傛暟閿�
+     * @return 缂撳瓨閿甼ey
+     */
+    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 d3ac0bf..0f531b7 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 @@
 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;
@@ -31,18 +32,6 @@
     }
 
     /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
-     * 
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysDictData> selectDictDataByType(String dictType)
-    {
-        return dictDataMapper.selectDictDataByType(dictType);
-    }
-
-    /**
      * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
      * 
      * @param dictType 瀛楀吀绫诲瀷
@@ -68,18 +57,6 @@
     }
 
     /**
-     * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀鏁版嵁淇℃伅
-     * 
-     * @param dictCode 瀛楀吀鏁版嵁ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteDictDataById(Long dictCode)
-    {
-        return dictDataMapper.deleteDictDataById(dictCode);
-    }
-
-    /**
      * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
      * 
      * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
@@ -87,7 +64,12 @@
      */
     public int deleteDictDataByIds(Long[] dictCodes)
     {
-        return dictDataMapper.deleteDictDataByIds(dictCodes);
+        int row = dictDataMapper.deleteDictDataByIds(dictCodes);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -99,7 +81,12 @@
     @Override
     public int insertDictData(SysDictData dictData)
     {
-        return dictDataMapper.insertDictData(dictData);
+        int row = dictDataMapper.insertDictData(dictData);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -111,6 +98,11 @@
     @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 8249dca..41ce43f 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;
@@ -24,6 +28,20 @@
 
     @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);
+        }
+    }
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
@@ -46,6 +64,29 @@
     public List<SysDictType> selectDictTypeAll()
     {
         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;
     }
 
     /**
@@ -72,18 +113,6 @@
     }
 
     /**
-     * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀淇℃伅
-     * 
-     * @param dictId 瀛楀吀ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteDictTypeById(Long dictId)
-    {
-        return dictTypeMapper.deleteDictTypeById(dictId);
-    }
-
-    /**
      * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
      * 
      * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
@@ -91,7 +120,28 @@
      */
     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;
+    }
+
+    /**
+     * 娓呯┖缂撳瓨鏁版嵁
+     */
+    public void clearCache()
+    {
+        DictUtils.clearDictCache();
     }
 
     /**
@@ -103,7 +153,12 @@
     @Override
     public int insertDictType(SysDictType dictType)
     {
-        return dictTypeMapper.insertDictType(dictType);
+        int row = dictTypeMapper.insertDictType(dictType);
+        if (row > 0)
+        {
+            DictUtils.clearDictCache();
+        }
+        return row;
     }
 
     /**
@@ -118,7 +173,12 @@
     {
         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 46ed878..f248229 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
@@ -140,7 +140,7 @@
         {
             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()));
@@ -300,6 +300,23 @@
     }
 
     /**
+     * 鑾峰彇璺敱鍚嶇О
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 璺敱鍚嶇О
+     */
+    public String getRouteName(SysMenu menu)
+    {
+        String routerName = StringUtils.capitalize(menu.getPath());
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+        if (isMeunFrame(menu))
+        {
+            routerName = StringUtils.EMPTY;
+        }
+        return routerName;
+    }
+
+    /**
      * 鑾峰彇璺敱鍦板潃
      * 
      * @param menu 鑿滃崟淇℃伅
diff --git a/ruoyi/src/main/resources/application.yml b/ruoyi/src/main/resources/application.yml
index c569e0e..764e0c6 100644
--- a/ruoyi/src/main/resources/application.yml
+++ b/ruoyi/src/main/resources/application.yml
@@ -3,7 +3,7 @@
   # 鍚嶇О
   name: RuoYi
   # 鐗堟湰
-  version: 2.2.0
+  version: 2.3.0
   # 鐗堟潈骞翠唤
   copyrightYear: 2019
   # 瀹炰緥婕旂ず寮�鍏�
diff --git a/ruoyi/src/main/resources/vm/sql/sql.vm b/ruoyi/src/main/resources/vm/sql/sql.vm
index 36a485d..5ceea08 100644
--- a/ruoyi/src/main/resources/vm/sql/sql.vm
+++ b/ruoyi/src/main/resources/vm/sql/sql.vm
@@ -6,17 +6,17 @@
 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 1a74fca..ffea736 100644
--- a/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
+++ b/ruoyi/src/main/resources/vm/vue/index-tree.vue.vm
@@ -375,8 +375,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -385,8 +383,6 @@
                 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 003aae6..8cf19f4 100644
--- a/ruoyi/src/main/resources/vm/vue/index.vue.vm
+++ b/ruoyi/src/main/resources/vm/vue/index.vue.vm
@@ -392,8 +392,6 @@
                 this.msgSuccess("淇敼鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           } else {
@@ -402,8 +400,6 @@
                 this.msgSuccess("鏂板鎴愬姛");
                 this.open = false;
                 this.getList();
-              } else {
-                this.msgError(response.msg);
               }
             });
           }

--
Gitblit v1.9.3