From 2f18d0d7094b10e169b77a0ea741bd101dbbf1f8 Mon Sep 17 00:00:00 2001
From: 疯狂的狮子li <15040126243@163.com>
Date: 星期六, 18 九月 2021 16:01:52 +0800
Subject: [PATCH] Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue into dev

---
 ruoyi-ui/src/views/monitor/job/log.vue                                    |   31 -
 ruoyi-ui/src/views/system/role/index.vue                                  |   22 
 ruoyi-ui/src/views/system/menu/index.vue                                  |   37 +-
 ruoyi-ui/src/views/system/user/index.vue                                  |   37 +-
 ruoyi-ui/src/utils/dict/DictMeta.js                                       |   38 ++
 ruoyi-ui/src/views/system/dict/index.vue                                  |   24 -
 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java |   26 +
 ruoyi-ui/src/main.js                                                      |    3 
 ruoyi-ui/src/utils/dict/Dict.js                                           |   82 +++++
 ruoyi-ui/src/views/monitor/logininfor/index.vue                           |   16 
 ruoyi-ui/src/views/system/post/index.vue                                  |   24 -
 ruoyi-ui/src/views/system/dict/data.vue                                   |   26 -
 ruoyi-ui/src/views/system/role/selectUser.vue                             |   10 
 ruoyi-ui/src/utils/ruoyi.js                                               |   20 +
 ruoyi-ui/src/views/system/role/authUser.vue                               |    8 
 ruoyi-ui/src/components/DictTag/index.vue                                 |   20 
 ruoyi-ui/src/views/system/notice/index.vue                                |   39 +-
 ruoyi-generator/src/main/resources/vm/vue/index.vue.vm                    |   57 +--
 ruoyi-ui/src/views/system/dept/index.vue                                  |   24 -
 ruoyi-ui/src/views/monitor/job/index.vue                                  |   47 +--
 ruoyi-ui/src/views/monitor/operlog/index.vue                              |   33 -
 ruoyi-ui/src/views/system/config/index.vue                                |   24 -
 ruoyi-ui/src/utils/dict/DictConverter.js                                  |   17 +
 ruoyi-ui/src/utils/dict/index.js                                          |   33 ++
 ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm               |   55 +--
 ruoyi-ui/src/utils/dict/DictOptions.js                                    |   51 +++
 ruoyi-ui/src/components/DictData/index.js                                 |   21 +
 ruoyi-ui/src/utils/dict/DictData.js                                       |   13 
 28 files changed, 508 insertions(+), 330 deletions(-)

diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
index 098a918..3876227 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
@@ -16,7 +16,7 @@
 
 /**
  * 妯℃澘澶勭悊宸ュ叿绫�
- *
+ * 
  * @author ruoyi
  */
 public class VelocityUtils
@@ -61,6 +61,7 @@
         velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
         velocityContext.put("columns", genTable.getColumns());
         velocityContext.put("table", genTable);
+        velocityContext.put("dicts", getDicts(genTable));
         setMenuVelocityContext(velocityContext, genTable);
         if (GenConstants.TPL_TREE.equals(tplCategory))
         {
@@ -245,7 +246,7 @@
 
     /**
      * 鏍规嵁鍒楃被鍨嬭幏鍙栧鍏ュ寘
-     *
+     * 
      * @param genTable 涓氬姟琛ㄥ璞�
      * @return 杩斿洖闇�瑕佸鍏ョ殑鍖呭垪琛�
      */
@@ -274,6 +275,27 @@
     }
 
     /**
+     * 鏍规嵁鍒楃被鍨嬭幏鍙栧瓧鍏哥粍
+     *
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 杩斿洖瀛楀吀缁�
+     */
+    public static String getDicts(GenTable genTable)
+    {
+        List<GenTableColumn> columns = genTable.getColumns();
+        List<String> dicts = new ArrayList<String>();
+        for (GenTableColumn column : columns)
+        {
+            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
+                    column.getHtmlType(), new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO }))
+            {
+                dicts.add("'" + column.getDictType() + "'");
+            }
+        }
+        return StringUtils.join(dicts, ", ");
+    }
+
+    /**
      * 鑾峰彇鏉冮檺鍓嶇紑
      *
      * @param moduleName 妯″潡鍚嶇О
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
index 8985250..0d83a3c 100644
--- a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
+++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
@@ -25,10 +25,10 @@
       <el-form-item label="${comment}" prop="${column.javaField}">
         <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
           <el-option
-            v-for="dict in ${column.javaField}Options"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -108,7 +108,7 @@
 #elseif($column.list && $column.dictType && "" != $column.dictType)
       <el-table-column label="${comment}" align="center" prop="${javaField}">
         <template slot-scope="scope">
-          <dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
         </template>
       </el-table-column>
 #elseif($column.list && "" != $javaField)
@@ -183,10 +183,10 @@
         <el-form-item label="${comment}" prop="${field}">
           <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
             <el-option
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              :label="dict.dictLabel"
-              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
 
             ></el-option>
           </el-select>
@@ -201,10 +201,10 @@
         <el-form-item label="${comment}">
           <el-checkbox-group v-model="form.${field}">
             <el-checkbox
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              :label="dict.dictValue">
-              {{dict.dictLabel}}
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
             </el-checkbox>
           </el-checkbox-group>
         </el-form-item>
@@ -218,11 +218,11 @@
         <el-form-item label="${comment}">
           <el-radio-group v-model="form.${field}">
             <el-radio
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
 
-            >{{dict.dictLabel}}</el-radio>
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
 #elseif($column.htmlType == "radio" && $dictType)
@@ -263,6 +263,9 @@
 
 export default {
   name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
   components: {
     Treeselect
   },
@@ -283,16 +286,7 @@
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
 #foreach ($column in $columns)
-#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
-#if($parentheseIndex != -1)
-#set($comment=$column.columnComment.substring(0, $parentheseIndex))
-#else
-#set($comment=$column.columnComment)
-#end
-#if(${column.dictType} && ${column.dictType} != '')
-      // $comment瀛楀吀
-      ${column.javaField}Options: [],
-#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
 #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
       // $comment鏃堕棿鑼冨洿
       daterange${AttrName}: [],
@@ -330,13 +324,6 @@
   },
   created() {
     this.getList();
-#foreach ($column in $columns)
-#if(${column.dictType} && ${column.dictType} != '')
-    this.getDicts("${column.dictType}").then(response => {
-      this.${column.javaField}Options = response.data;
-    });
-#end
-#end
   },
   methods: {
     /** 鏌ヨ${functionName}鍒楄〃 */
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
index 4b055fa..7e67021 100644
--- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
+++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
@@ -25,10 +25,10 @@
       <el-form-item label="${comment}" prop="${column.javaField}">
         <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
           <el-option
-            v-for="dict in ${column.javaField}Options"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -137,7 +137,7 @@
 #elseif($column.list && $column.dictType && "" != $column.dictType)
       <el-table-column label="${comment}" align="center" prop="${javaField}">
         <template slot-scope="scope">
-          <dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
         </template>
       </el-table-column>
 #elseif($column.list && "" != $javaField)
@@ -163,7 +163,7 @@
         </template>
       </el-table-column>
     </el-table>
-
+    
     <pagination
       v-show="total>0"
       :total="total"
@@ -205,10 +205,10 @@
         <el-form-item label="${comment}" prop="${field}">
           <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
             <el-option
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              :label="dict.dictLabel"
-              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
 
             ></el-option>
           </el-select>
@@ -223,10 +223,10 @@
         <el-form-item label="${comment}">
           <el-checkbox-group v-model="form.${field}">
             <el-checkbox
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              :label="dict.dictValue">
-              {{dict.dictLabel}}
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
             </el-checkbox>
           </el-checkbox-group>
         </el-form-item>
@@ -240,11 +240,11 @@
         <el-form-item label="${comment}">
           <el-radio-group v-model="form.${field}">
             <el-radio
-              v-for="dict in ${field}Options"
-              :key="dict.dictValue"
-              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
 
-            >{{dict.dictLabel}}</el-radio>
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
 #elseif($column.htmlType == "radio" && $dictType)
@@ -315,6 +315,9 @@
 
 export default {
   name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
   data() {
     return {
       // 鎸夐挳loading
@@ -348,16 +351,7 @@
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
 #foreach ($column in $columns)
-#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
-#if($parentheseIndex != -1)
-#set($comment=$column.columnComment.substring(0, $parentheseIndex))
-#else
-#set($comment=$column.columnComment)
-#end
-#if(${column.dictType} && ${column.dictType} != '')
-      // $comment瀛楀吀
-      ${column.javaField}Options: [],
-#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
 #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
       // $comment鏃堕棿鑼冨洿
       daterange${AttrName}: [],
@@ -397,13 +391,6 @@
   },
   created() {
     this.getList();
-#foreach ($column in $columns)
-#if(${column.dictType} && ${column.dictType} != '')
-    this.getDicts("${column.dictType}").then(response => {
-      this.${column.javaField}Options = response.data;
-    });
-#end
-#end
   },
   methods: {
     /** 鏌ヨ${functionName}鍒楄〃 */
diff --git a/ruoyi-ui/src/components/DictData/index.js b/ruoyi-ui/src/components/DictData/index.js
new file mode 100644
index 0000000..24e3e9c
--- /dev/null
+++ b/ruoyi-ui/src/components/DictData/index.js
@@ -0,0 +1,21 @@
+import Vue from 'vue'
+import DataDict from '@/utils/dict'
+import { getDicts as getDicts } from '@/api/system/dict/data'
+
+function install() {
+  Vue.use(DataDict, {
+    metas: {
+      '*': {
+        labelField: 'dictLabel',
+        valueField: 'dictValue',
+        request(dictMeta) {
+          return getDicts(dictMeta.type).then(res => res.data)
+        },
+      },
+    },
+  })
+}
+
+export default {
+  install,
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/components/DictTag/index.vue b/ruoyi-ui/src/components/DictTag/index.vue
index b0484bc..4c196c4 100644
--- a/ruoyi-ui/src/components/DictTag/index.vue
+++ b/ruoyi-ui/src/components/DictTag/index.vue
@@ -1,23 +1,23 @@
 <template>
   <div>
     <template v-for="(item, index) in options">
-      <template v-if="values.includes(item.dictValue)">
+      <template v-if="values.includes(item.value)">
         <span
-          v-if="item.listClass == 'default' || item.listClass == ''"
-          :key="item.dictValue"
+          v-if="item.raw.listClass == 'default' || item.raw.listClass == ''"
+          :key="item.value"
           :index="index"
-          :class="item.cssClass"
-          >{{ item.dictLabel }}</span
+          :class="item.raw.cssClass"
+          >{{ item.label }}</span
         >
         <el-tag
           v-else
           :disable-transitions="true"
-          :key="item.dictValue"
+          :key="item.value"
           :index="index"
-          :type="item.listClass == 'primary' ? '' : item.listClass"
-          :class="item.cssClass"
+          :type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
+          :class="item.raw.cssClass"
         >
-          {{ item.dictLabel }}
+          {{ item.label }}
         </el-tag>
       </template>
     </template>
@@ -49,4 +49,4 @@
 .el-tag + .el-tag {
   margin-left: 10px;
 }
-</style>
+</style>
\ No newline at end of file
diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js
index a5cc674..b1862cf 100644
--- a/ruoyi-ui/src/main.js
+++ b/ruoyi-ui/src/main.js
@@ -31,6 +31,8 @@
 import DictTag from '@/components/DictTag'
 // 澶撮儴鏍囩缁勪欢
 import VueMeta from 'vue-meta'
+// 瀛楀吀鏁版嵁缁勪欢
+import DictData from '@/components/DictData'
 
 // 鍏ㄥ眬鏂规硶鎸傝浇
 Vue.prototype.getDicts = getDicts
@@ -65,6 +67,7 @@
 
 Vue.use(directive)
 Vue.use(VueMeta)
+DictData.install()
 
 /**
  * If you don't want to use mock-server
diff --git a/ruoyi-ui/src/utils/dict/Dict.js b/ruoyi-ui/src/utils/dict/Dict.js
new file mode 100644
index 0000000..22db32f
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/Dict.js
@@ -0,0 +1,82 @@
+import Vue from 'vue'
+import { mergeRecursive } from "@/utils/ruoyi";
+import DictMeta from './DictMeta'
+import DictData from './DictData'
+
+const DEFAULT_DICT_OPTIONS = {
+  types: [],
+}
+
+/**
+ * @classdesc 瀛楀吀
+ * @property {Object} label 鏍囩瀵硅薄锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉�
+ * @property {Object} dict 瀛楁鏁扮粍锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉�
+ * @property {Array.<DictMeta>} _dictMetas 瀛楀吀鍏冩暟鎹暟缁�
+ */
+export default class Dict {
+  constructor() {
+    this.owner = null
+    this.label = {}
+    this.type = {}
+  }
+
+  init(options) {
+    if (options instanceof Array) {
+      options = { types: options }
+    }
+    const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
+    if (opts.types === undefined) {
+      throw new Error('need dict types')
+    }
+    const ps = []
+    this._dictMetas = opts.types.map(t => DictMeta.parse(t))
+    this._dictMetas.forEach(dictMeta => {
+      const type = dictMeta.type
+      Vue.set(this.label, type, {})
+      Vue.set(this.type, type, [])
+      if (dictMeta.lazy) {
+        return
+      }
+      ps.push(loadDict(this, dictMeta))
+    })
+    return Promise.all(ps)
+  }
+
+  /**
+   * 閲嶆柊鍔犺浇瀛楀吀
+   * @param {String} type 瀛楀吀绫诲瀷
+   */
+  reloadDict(type) {
+    const dictMeta = this._dictMetas.find(e => e.type === type)
+    if (dictMeta === undefined) {
+      return Promise.reject(`the dict meta of ${type} was not found`)
+    }
+    return loadDict(this, dictMeta)
+  }
+}
+
+/**
+ * 鍔犺浇瀛楀吀
+ * @param {Dict} dict 瀛楀吀
+ * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹�
+ * @returns {Promise}
+ */
+function loadDict(dict, dictMeta) {
+  return dictMeta.request(dictMeta)
+    .then(response => {
+      const type = dictMeta.type
+      let dicts = dictMeta.responseConverter(response, dictMeta)
+      if (!(dicts instanceof Array)) {
+        console.error('the return of responseConverter must be Array.<DictData>')
+        dicts = []
+      } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
+        console.error('the type of elements in dicts must be DictData')
+        dicts = []
+      }
+      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
+      dicts.forEach(d => {
+        Vue.set(dict.label[type], d.value, d.label)
+      })
+      return dicts
+    })
+}
diff --git a/ruoyi-ui/src/utils/dict/DictConverter.js b/ruoyi-ui/src/utils/dict/DictConverter.js
new file mode 100644
index 0000000..576ff54
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/DictConverter.js
@@ -0,0 +1,17 @@
+import DictOptions from './DictOptions'
+import DictData from './DictData'
+
+export default function(dict, dictMeta) {
+  const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
+  const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
+  return new DictData(dict[label], dict[value], dict)
+}
+
+/**
+ * 纭畾瀛楀吀瀛楁
+ * @param {DictData} dict
+ * @param  {...String} fields
+ */
+function determineDictField(dict, ...fields) {
+  return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
+}
diff --git a/ruoyi-ui/src/utils/dict/DictData.js b/ruoyi-ui/src/utils/dict/DictData.js
new file mode 100644
index 0000000..37a60d5
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/DictData.js
@@ -0,0 +1,13 @@
+/**
+ * @classdesc 瀛楀吀鏁版嵁
+ * @property {String} label 鏍囩
+ * @property {*} value 鏍囩
+ * @property {Object} raw 鍘熷鏁版嵁
+ */
+export default class DictData {
+  constructor(label, value, raw) {
+    this.label = label
+    this.value = value
+    this.raw = raw
+  }
+}
diff --git a/ruoyi-ui/src/utils/dict/DictMeta.js b/ruoyi-ui/src/utils/dict/DictMeta.js
new file mode 100644
index 0000000..8ae6133
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/DictMeta.js
@@ -0,0 +1,38 @@
+import { mergeRecursive } from "@/utils/ruoyi";
+import DictOptions from './DictOptions'
+
+/**
+ * @classdesc 瀛楀吀鍏冩暟鎹�
+ * @property {String} type 绫诲瀷
+ * @property {Function} request 璇锋眰
+ * @property {String} label 鏍囩瀛楁
+ * @property {String} value 鍊煎瓧娈�
+ */
+export default class DictMeta {
+  constructor(options) {
+    this.type = options.type
+    this.request = options.request,
+    this.responseConverter = options.responseConverter
+    this.labelField = options.labelField
+    this.valueField = options.valueField
+    this.lazy = options.lazy === true
+  }
+}
+
+
+/**
+ * 瑙f瀽瀛楀吀鍏冩暟鎹�
+ * @param {Object} options
+ * @returns {DictMeta}
+ */
+DictMeta.parse= function(options) {
+  let opts = null
+  if (typeof options === 'string') {
+    opts = DictOptions.metas[options] || {}
+    opts.type = options
+  } else if (typeof options === 'object') {
+    opts = options
+  }
+  opts = mergeRecursive(DictOptions.metas['*'], opts)
+  return new DictMeta(opts)
+}
diff --git a/ruoyi-ui/src/utils/dict/DictOptions.js b/ruoyi-ui/src/utils/dict/DictOptions.js
new file mode 100644
index 0000000..5e1cc41
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/DictOptions.js
@@ -0,0 +1,51 @@
+import { mergeRecursive } from "@/utils/ruoyi";
+import dictConverter from './DictConverter'
+
+export const options = {
+  metas: {
+    '*': {
+      /**
+       * 瀛楀吀璇锋眰锛屾柟娉曠鍚嶄负function(dictMeta: DictMeta): Promise
+       */
+      request: (dictMeta) => {
+        console.log(`load dict ${dictMeta.type}`)
+        return Promise.resolve([])
+      },
+      /**
+       * 瀛楀吀鍝嶅簲鏁版嵁杞崲鍣紝鏂规硶绛惧悕涓篺unction(response: Object, dictMeta: DictMeta): DictData
+       */
+      responseConverter,
+      labelField: 'label',
+      valueField: 'value',
+    },
+  },
+  /**
+   * 榛樿鏍囩瀛楁
+   */
+  DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
+  /**
+   * 榛樿鍊煎瓧娈�
+   */
+  DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
+}
+
+/**
+ * 鏄犲皠瀛楀吀
+ * @param {Object} response 瀛楀吀鏁版嵁
+ * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹�
+ * @returns {DictData}
+ */
+function responseConverter(response, dictMeta) {
+  const dicts = response.content instanceof Array ? response.content : response
+  if (dicts === undefined) {
+    console.warn(`no dict data of "${dictMeta.type}" found in the response`)
+    return []
+  }
+  return dicts.map(d => dictConverter(d, dictMeta))
+}
+
+export function mergeOptions(src) {
+  mergeRecursive(options, src)
+}
+
+export default options
diff --git a/ruoyi-ui/src/utils/dict/index.js b/ruoyi-ui/src/utils/dict/index.js
new file mode 100644
index 0000000..66ddfef
--- /dev/null
+++ b/ruoyi-ui/src/utils/dict/index.js
@@ -0,0 +1,33 @@
+import Dict from './Dict'
+import { mergeOptions } from './DictOptions'
+
+export default function(Vue, options) {
+  mergeOptions(options)
+  Vue.mixin({
+    data() {
+      if (this.$options.dicts === undefined || this.$options.dicts === null) {
+        return {}
+      }
+      const dict = new Dict()
+      dict.owner = this
+      return {
+        dict
+      }
+    },
+    created() {
+      if (!(this.dict instanceof Dict)) {
+        return
+      }
+      options.onCreated && options.onCreated(this.dict)
+      this.dict.init(this.$options.dicts).then(() => {
+        options.onReady && options.onReady(this.dict)
+        this.$nextTick(() => {
+          this.$emit('dictReady', this.dict)
+          if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
+            this.$options.methods.onDictReady.call(this, this.dict)
+          }
+        })
+      })
+    },
+  })
+}
diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js
index 68fb6bb..10533e7 100644
--- a/ruoyi-ui/src/utils/ruoyi.js
+++ b/ruoyi-ui/src/utils/ruoyi.js
@@ -72,8 +72,8 @@
 export function selectDictLabel(datas, value) {
 	var actions = [];
 	Object.keys(datas).some((key) => {
-		if (datas[key].dictValue == ('' + value)) {
-			actions.push(datas[key].dictLabel);
+		if (datas[key].value == ('' + value)) {
+			actions.push(datas[key].label);
 			return true;
 		}
 	})
@@ -117,6 +117,22 @@
 	return str;
 }
 
+// 鏁版嵁鍚堝苟
+export function mergeRecursive(source, target) {
+    for (var p in target) {
+        try {
+            if (target[p].constructor == Object) {
+                source[p] = mergeRecursive(source[p], target[p]);
+            } else {
+                source[p] = target[p];
+            }
+        } catch(e) {
+            source[p] = target[p];
+        }
+    }
+    return source;
+};
+
 /**
  * 鏋勯�犳爲鍨嬬粨鏋勬暟鎹�
  * @param {*} data 鏁版嵁婧�
diff --git a/ruoyi-ui/src/views/monitor/job/index.vue b/ruoyi-ui/src/views/monitor/job/index.vue
index 73bb375..f19a597 100644
--- a/ruoyi-ui/src/views/monitor/job/index.vue
+++ b/ruoyi-ui/src/views/monitor/job/index.vue
@@ -13,20 +13,20 @@
       <el-form-item label="浠诲姟缁勫悕" prop="jobGroup">
         <el-select v-model="queryParams.jobGroup" placeholder="璇烽�夋嫨浠诲姟缁勫悕" clearable size="small">
           <el-option
-            v-for="dict in jobGroupOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_job_group"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
       <el-form-item label="浠诲姟鐘舵��" prop="status">
         <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨浠诲姟鐘舵��" clearable size="small">
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_job_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -99,7 +99,7 @@
       <el-table-column label="浠诲姟鍚嶇О" align="center" prop="jobName" :show-overflow-tooltip="true" />
       <el-table-column label="浠诲姟缁勫悕" align="center" prop="jobGroup">
         <template slot-scope="scope">
-          <dict-tag :options="jobGroupOptions" :value="scope.row.jobGroup"/>
+          <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup"/>
         </template>
       </el-table-column>
       <el-table-column label="璋冪敤鐩爣瀛楃涓�" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
@@ -168,10 +168,10 @@
             <el-form-item label="浠诲姟鍒嗙粍" prop="jobGroup">
               <el-select v-model="form.jobGroup" placeholder="璇烽�夋嫨">
                 <el-option
-                  v-for="dict in jobGroupOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel"
-                  :value="dict.dictValue"
+                  v-for="dict in dict.type.sys_job_group"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
                 ></el-option>
               </el-select>
             </el-form-item>
@@ -225,10 +225,10 @@
             <el-form-item label="鐘舵��">
               <el-radio-group v-model="form.status">
                 <el-radio
-                  v-for="dict in statusOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_job_status"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -301,6 +301,7 @@
 export default {
   components: { Crontab },
   name: "Job",
+  dicts: ['sys_job_group', 'sys_job_status'],
   data() {
     return {
       // 閬僵灞�
@@ -329,10 +330,6 @@
       openCron: false,
       // 浼犲叆鐨勮〃杈惧紡
       expression: "",
-      // 浠诲姟缁勫悕瀛楀吀
-      jobGroupOptions: [],
-      // 鐘舵�佸瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -359,12 +356,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_job_group").then(response => {
-      this.jobGroupOptions = response.data;
-    });
-    this.getDicts("sys_job_status").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ瀹氭椂浠诲姟鍒楄〃 */
@@ -378,7 +369,7 @@
     },
     // 浠诲姟缁勫悕瀛楀吀缈昏瘧
     jobGroupFormat(row, column) {
-      return this.selectDictLabel(this.jobGroupOptions, row.jobGroup);
+      return this.selectDictLabel(this.dict.type.sys_job_group, row.jobGroup);
     },
     // 鍙栨秷鎸夐挳
     cancel() {
diff --git a/ruoyi-ui/src/views/monitor/job/log.vue b/ruoyi-ui/src/views/monitor/job/log.vue
index 7e4dffe..db943d1 100644
--- a/ruoyi-ui/src/views/monitor/job/log.vue
+++ b/ruoyi-ui/src/views/monitor/job/log.vue
@@ -20,10 +20,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in jobGroupOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_job_group"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -36,10 +36,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -112,14 +112,14 @@
       <el-table-column label="浠诲姟鍚嶇О" align="center" prop="jobName" :show-overflow-tooltip="true" />
       <el-table-column label="浠诲姟缁勫悕" align="center" prop="jobGroup" :show-overflow-tooltip="true">
         <template slot-scope="scope">
-          <dict-tag :options="jobGroupOptions" :value="scope.row.jobGroup"/>
+          <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup"/>
         </template>
       </el-table-column>
       <el-table-column label="璋冪敤鐩爣瀛楃涓�" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
       <el-table-column label="鏃ュ織淇℃伅" align="center" prop="jobMessage" :show-overflow-tooltip="true" />
       <el-table-column label="鎵ц鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鎵ц鏃堕棿" align="center" prop="createTime" width="180">
@@ -190,6 +190,7 @@
 
 export default {
   name: "JobLog",
+  dicts: ['sys_common_status', 'sys_job_group'],
   data() {
     return {
       // 閬僵灞�
@@ -212,10 +213,6 @@
       dateRange: [],
       // 琛ㄥ崟鍙傛暟
       form: {},
-      // 鎵ц鐘舵�佸瓧鍏�
-      statusOptions: [],
-      // 浠诲姟缁勫悕瀛楀吀
-      jobGroupOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -237,12 +234,6 @@
     } else {
       this.getList();
     }
-    this.getDicts("sys_common_status").then(response => {
-      this.statusOptions = response.data;
-    });
-    this.getDicts("sys_job_group").then(response => {
-      this.jobGroupOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ璋冨害鏃ュ織鍒楄〃 */
diff --git a/ruoyi-ui/src/views/monitor/logininfor/index.vue b/ruoyi-ui/src/views/monitor/logininfor/index.vue
index 778492b..576cef2 100644
--- a/ruoyi-ui/src/views/monitor/logininfor/index.vue
+++ b/ruoyi-ui/src/views/monitor/logininfor/index.vue
@@ -30,10 +30,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -101,7 +101,7 @@
       <el-table-column label="鎿嶄綔绯荤粺" align="center" prop="os" />
       <el-table-column label="鐧诲綍鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鎿嶄綔淇℃伅" align="center" prop="msg" />
@@ -127,6 +127,7 @@
 
 export default {
   name: "Logininfor",
+  dicts: ['sys_common_status'],
   data() {
     return {
       // 閬僵灞�
@@ -143,8 +144,6 @@
       total: 0,
       // 琛ㄦ牸鏁版嵁
       list: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏃ユ湡鑼冨洿
       dateRange: [],
       // 榛樿鎺掑簭
@@ -161,9 +160,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_common_status").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 */
diff --git a/ruoyi-ui/src/views/monitor/operlog/index.vue b/ruoyi-ui/src/views/monitor/operlog/index.vue
index fbce6dd..b4d7a0f 100644
--- a/ruoyi-ui/src/views/monitor/operlog/index.vue
+++ b/ruoyi-ui/src/views/monitor/operlog/index.vue
@@ -30,10 +30,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in typeOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_oper_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -46,10 +46,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_common_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -113,7 +113,7 @@
       <el-table-column label="绯荤粺妯″潡" align="center" prop="title" />
       <el-table-column label="鎿嶄綔绫诲瀷" align="center" prop="businessType">
         <template slot-scope="scope">
-          <dict-tag :options="typeOptions" :value="scope.row.businessType"/>
+          <dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/>
         </template>
       </el-table-column>
       <el-table-column label="璇锋眰鏂瑰紡" align="center" prop="requestMethod" />
@@ -122,7 +122,7 @@
       <el-table-column label="鎿嶄綔鍦扮偣" align="center" prop="operLocation" :show-overflow-tooltip="true" />
       <el-table-column label="鎿嶄綔鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
@@ -200,6 +200,7 @@
 
 export default {
   name: "Operlog",
+  dicts: ['sys_oper_type', 'sys_common_status'],
   data() {
     return {
       // 閬僵灞�
@@ -218,10 +219,6 @@
       list: [],
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
-      // 绫诲瀷鏁版嵁瀛楀吀
-      typeOptions: [],
-      // 绫诲瀷鏁版嵁瀛楀吀
-      statusOptions: [],
       // 鏃ユ湡鑼冨洿
       dateRange: [],
       // 榛樿鎺掑簭
@@ -241,12 +238,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_oper_type").then(response => {
-      this.typeOptions = response.data;
-    });
-    this.getDicts("sys_common_status").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ鐧诲綍鏃ュ織 */
@@ -261,7 +252,7 @@
     },
     // 鎿嶄綔鏃ュ織绫诲瀷瀛楀吀缈昏瘧
     typeFormat(row, column) {
-      return this.selectDictLabel(this.typeOptions, row.businessType);
+      return this.selectDictLabel(this.dict.type.sys_oper_type, row.businessType);
     },
     /** 鎼滅储鎸夐挳鎿嶄綔 */
     handleQuery() {
diff --git a/ruoyi-ui/src/views/system/config/index.vue b/ruoyi-ui/src/views/system/config/index.vue
index 04384bb..e2cfb1a 100644
--- a/ruoyi-ui/src/views/system/config/index.vue
+++ b/ruoyi-ui/src/views/system/config/index.vue
@@ -24,10 +24,10 @@
       <el-form-item label="绯荤粺鍐呯疆" prop="configType">
         <el-select v-model="queryParams.configType" placeholder="绯荤粺鍐呯疆" clearable size="small">
           <el-option
-            v-for="dict in typeOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_yes_no"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -114,7 +114,7 @@
       <el-table-column label="鍙傛暟閿��" align="center" prop="configValue" />
       <el-table-column label="绯荤粺鍐呯疆" align="center" prop="configType">
         <template slot-scope="scope">
-          <dict-tag :options="typeOptions" :value="scope.row.configType"/>
+          <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/>
         </template>
       </el-table-column>
       <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
@@ -166,10 +166,10 @@
         <el-form-item label="绯荤粺鍐呯疆" prop="configType">
           <el-radio-group v-model="form.configType">
             <el-radio
-              v-for="dict in typeOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+              v-for="dict in dict.type.sys_yes_no"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="澶囨敞" prop="remark">
@@ -189,6 +189,7 @@
 
 export default {
   name: "Config",
+  dicts: ['sys_yes_no'],
   data() {
     return {
       // 閬僵灞�
@@ -211,8 +212,6 @@
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
-      // 绫诲瀷鏁版嵁瀛楀吀
-      typeOptions: [],
       // 鏃ユ湡鑼冨洿
       dateRange: [],
       // 鏌ヨ鍙傛暟
@@ -241,9 +240,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_yes_no").then(response => {
-      this.typeOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ鍙傛暟鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/dept/index.vue b/ruoyi-ui/src/views/system/dept/index.vue
index 037c998..591ba75 100644
--- a/ruoyi-ui/src/views/system/dept/index.vue
+++ b/ruoyi-ui/src/views/system/dept/index.vue
@@ -13,10 +13,10 @@
       <el-form-item label="鐘舵��" prop="status">
         <el-select v-model="queryParams.status" placeholder="閮ㄩ棬鐘舵��" clearable size="small">
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -61,7 +61,7 @@
       <el-table-column prop="orderNum" label="鎺掑簭" width="200"></el-table-column>
       <el-table-column prop="status" label="鐘舵��" width="100">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200">
@@ -135,10 +135,10 @@
             <el-form-item label="閮ㄩ棬鐘舵��">
               <el-radio-group v-model="form.status">
                 <el-radio
-                  v-for="dict in statusOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -159,6 +159,7 @@
 
 export default {
   name: "Dept",
+  dicts: ['sys_normal_disable'],
   components: { Treeselect },
   data() {
     return {
@@ -180,8 +181,6 @@
       refreshTable: true,
       // 鏄惁灞曞紑
       expand: false,
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         deptName: undefined,
@@ -219,9 +218,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ閮ㄩ棬鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/dict/data.vue b/ruoyi-ui/src/views/system/dict/data.vue
index 3b8ec4b..6b17756 100644
--- a/ruoyi-ui/src/views/system/dict/data.vue
+++ b/ruoyi-ui/src/views/system/dict/data.vue
@@ -23,10 +23,10 @@
       <el-form-item label="鐘舵��" prop="status">
         <el-select v-model="queryParams.status" placeholder="鏁版嵁鐘舵��" clearable size="small">
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -96,7 +96,7 @@
       <el-table-column label="瀛楀吀鎺掑簭" align="center" prop="dictSort" />
       <el-table-column label="鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
@@ -164,10 +164,10 @@
         <el-form-item label="鐘舵��" prop="status">
           <el-radio-group v-model="form.status">
             <el-radio
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="澶囨敞" prop="remark">
@@ -188,6 +188,7 @@
 
 export default {
   name: "Data",
+  dicts: ['sys_normal_disable'],
   data() {
     return {
       // 閬僵灞�
@@ -239,8 +240,6 @@
           label: "鍗遍櫓"
         }
       ],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 绫诲瀷鏁版嵁瀛楀吀
       typeOptions: [],
       // 鏌ヨ鍙傛暟
@@ -271,9 +270,6 @@
     const dictId = this.$route.params && this.$route.params.dictId;
     this.getType(dictId);
     this.getTypeList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ瀛楀吀绫诲瀷璇︾粏 */
@@ -392,4 +388,4 @@
     }
   }
 };
-</script>
+</script>
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/system/dict/index.vue b/ruoyi-ui/src/views/system/dict/index.vue
index 0bce088..a8dd1e6 100644
--- a/ruoyi-ui/src/views/system/dict/index.vue
+++ b/ruoyi-ui/src/views/system/dict/index.vue
@@ -30,10 +30,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -125,7 +125,7 @@
       </el-table-column>
       <el-table-column label="鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" />
@@ -174,10 +174,10 @@
         <el-form-item label="鐘舵��" prop="status">
           <el-radio-group v-model="form.status">
             <el-radio
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="澶囨敞" prop="remark">
@@ -197,6 +197,7 @@
 
 export default {
   name: "Dict",
+  dicts: ['sys_normal_disable'],
   data() {
     return {
       // 閬僵灞�
@@ -219,8 +220,6 @@
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏃ユ湡鑼冨洿
       dateRange: [],
       // 鏌ヨ鍙傛暟
@@ -246,9 +245,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/menu/index.vue b/ruoyi-ui/src/views/system/menu/index.vue
index 0f4296c..d7d4c0f 100644
--- a/ruoyi-ui/src/views/system/menu/index.vue
+++ b/ruoyi-ui/src/views/system/menu/index.vue
@@ -13,10 +13,10 @@
       <el-form-item label="鐘舵��" prop="status">
         <el-select v-model="queryParams.status" placeholder="鑿滃崟鐘舵��" clearable size="small">
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -68,7 +68,7 @@
       <el-table-column prop="component" label="缁勪欢璺緞" :show-overflow-tooltip="true"></el-table-column>
       <el-table-column prop="status" label="鐘舵��" width="80">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime">
@@ -240,10 +240,10 @@
               </span>
               <el-radio-group v-model="form.visible">
                 <el-radio
-                  v-for="dict in visibleOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_show_hide"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -257,10 +257,10 @@
               </span>
               <el-radio-group v-model="form.status">
                 <el-radio
-                  v-for="dict in statusOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -282,6 +282,7 @@
 
 export default {
   name: "Menu",
+  dicts: ['sys_show_hide', 'sys_normal_disable'],
   components: { Treeselect, IconSelect },
   data() {
     return {
@@ -301,10 +302,6 @@
       isExpandAll: false,
       // 閲嶆柊娓叉煋琛ㄦ牸鐘舵��
       refreshTable: true,
-      // 鏄剧ず鐘舵�佹暟鎹瓧鍏�
-      visibleOptions: [],
-      // 鑿滃崟鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         menuName: undefined,
@@ -328,12 +325,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_show_hide").then(response => {
-      this.visibleOptions = response.data;
-    });
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     // 閫夋嫨鍥炬爣
diff --git a/ruoyi-ui/src/views/system/notice/index.vue b/ruoyi-ui/src/views/system/notice/index.vue
index b90168c..7b65e9e 100644
--- a/ruoyi-ui/src/views/system/notice/index.vue
+++ b/ruoyi-ui/src/views/system/notice/index.vue
@@ -22,10 +22,10 @@
       <el-form-item label="绫诲瀷" prop="noticeType">
         <el-select v-model="queryParams.noticeType" placeholder="鍏憡绫诲瀷" clearable size="small">
           <el-option
-            v-for="dict in typeOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_notice_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -82,12 +82,12 @@
       />
       <el-table-column label="鍏憡绫诲瀷" align="center" prop="noticeType" width="100">
         <template slot-scope="scope">
-          <dict-tag :options="typeOptions" :value="scope.row.noticeType"/>
+          <dict-tag :options="dict.type.sys_notice_type" :value="scope.row.noticeType"/>
         </template>
       </el-table-column>
       <el-table-column label="鐘舵��" align="center" prop="status" width="100">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_notice_status" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鍒涘缓鑰�" align="center" prop="createBy" width="100" />
@@ -137,10 +137,10 @@
             <el-form-item label="鍏憡绫诲瀷" prop="noticeType">
               <el-select v-model="form.noticeType" placeholder="璇烽�夋嫨">
                 <el-option
-                  v-for="dict in typeOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel"
-                  :value="dict.dictValue"
+                  v-for="dict in dict.type.sys_notice_type"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
                 ></el-option>
               </el-select>
             </el-form-item>
@@ -149,10 +149,10 @@
             <el-form-item label="鐘舵��">
               <el-radio-group v-model="form.status">
                 <el-radio
-                  v-for="dict in statusOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_notice_status"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -176,6 +176,7 @@
 
 export default {
   name: "Notice",
+  dicts: ['sys_notice_status', 'sys_notice_type'],
   data() {
     return {
       // 閬僵灞�
@@ -196,10 +197,6 @@
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
-      // 绫诲瀷鏁版嵁瀛楀吀
-      statusOptions: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      typeOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -223,12 +220,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_notice_status").then(response => {
-      this.statusOptions = response.data;
-    });
-    this.getDicts("sys_notice_type").then(response => {
-      this.typeOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ鍏憡鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/post/index.vue b/ruoyi-ui/src/views/system/post/index.vue
index 735d616..3f6874b 100644
--- a/ruoyi-ui/src/views/system/post/index.vue
+++ b/ruoyi-ui/src/views/system/post/index.vue
@@ -22,10 +22,10 @@
       <el-form-item label="鐘舵��" prop="status">
         <el-select v-model="queryParams.status" placeholder="宀椾綅鐘舵��" clearable size="small">
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -90,7 +90,7 @@
       <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" />
       <el-table-column label="鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
@@ -141,10 +141,10 @@
         <el-form-item label="宀椾綅鐘舵��" prop="status">
           <el-radio-group v-model="form.status">
             <el-radio
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="澶囨敞" prop="remark">
@@ -164,6 +164,7 @@
 
 export default {
   name: "Post",
+  dicts: ['sys_normal_disable'],
   data() {
     return {
       // 閬僵灞�
@@ -186,8 +187,6 @@
       title: "",
       // 鏄惁鏄剧ず寮瑰嚭灞�
       open: false,
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -214,9 +213,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ宀椾綅鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/role/authUser.vue b/ruoyi-ui/src/views/system/role/authUser.vue
index a65ccbf..661c369 100644
--- a/ruoyi-ui/src/views/system/role/authUser.vue
+++ b/ruoyi-ui/src/views/system/role/authUser.vue
@@ -69,7 +69,7 @@
       <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" />
       <el-table-column label="鐘舵��" align="center" prop="status">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+          <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
         </template>
       </el-table-column>
       <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
@@ -107,6 +107,7 @@
 
 export default {
   name: "AuthUser",
+  dicts: ['sys_normal_disable'],
   components: { selectUser },
   data() {
     return {
@@ -122,8 +123,6 @@
       total: 0,
       // 鐢ㄦ埛琛ㄦ牸鏁版嵁
       userList: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -139,9 +138,6 @@
     if (roleId) {
       this.queryParams.roleId = roleId;
       this.getList();
-      this.getDicts("sys_normal_disable").then(response => {
-        this.statusOptions = response.data;
-      });
     }
   },
   methods: {
diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue
index b86bc55..1aee567 100644
--- a/ruoyi-ui/src/views/system/role/index.vue
+++ b/ruoyi-ui/src/views/system/role/index.vue
@@ -30,10 +30,10 @@
           style="width: 240px"
         >
           <el-option
-            v-for="dict in statusOptions"
-            :key="dict.dictValue"
-            :label="dict.dictLabel"
-            :value="dict.dictValue"
+            v-for="dict in dict.type.sys_normal_disable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -183,10 +183,10 @@
         <el-form-item label="鐘舵��">
           <el-radio-group v-model="form.status">
             <el-radio
-              v-for="dict in statusOptions"
-              :key="dict.dictValue"
-              :label="dict.dictValue"
-            >{{dict.dictLabel}}</el-radio>
+              v-for="dict in dict.type.sys_normal_disable"
+              :key="dict.value"
+              :label="dict.value"
+            >{{dict.label}}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="鑿滃崟鏉冮檺">
@@ -265,6 +265,7 @@
 
 export default {
   name: "Role",
+  dicts: ['sys_normal_disable'],
   data() {
     return {
       // 閬僵灞�
@@ -295,8 +296,6 @@
       deptNodeAll: false,
       // 鏃ユ湡鑼冨洿
       dateRange: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏁版嵁鑼冨洿閫夐」
       dataScopeOptions: [
         {
@@ -354,9 +353,6 @@
   },
   created() {
     this.getList();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     /** 鏌ヨ瑙掕壊鍒楄〃 */
diff --git a/ruoyi-ui/src/views/system/role/selectUser.vue b/ruoyi-ui/src/views/system/role/selectUser.vue
index 5a97095..3229462 100644
--- a/ruoyi-ui/src/views/system/role/selectUser.vue
+++ b/ruoyi-ui/src/views/system/role/selectUser.vue
@@ -34,7 +34,7 @@
         <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" />
         <el-table-column label="鐘舵��" align="center" prop="status">
           <template slot-scope="scope">
-            <dict-tag :options="statusOptions" :value="scope.row.status"/>
+            <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
           </template>
         </el-table-column>
         <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
@@ -61,6 +61,7 @@
 <script>
 import { unallocatedUserList, authUserSelectAll } from "@/api/system/role";
 export default {
+  dicts: ['sys_normal_disable'],
   props: {
     // 瑙掕壊缂栧彿
     roleId: {
@@ -77,8 +78,6 @@
       total: 0,
       // 鏈巿鏉冪敤鎴锋暟鎹�
       userList: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
       // 鏌ヨ鍙傛暟
       queryParams: {
         pageNum: 1,
@@ -88,11 +87,6 @@
         phonenumber: undefined
       }
     };
-  },
-  created() {
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
   },
   methods: {
     // 鏄剧ず寮规
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index d06d500..eb63770 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -57,10 +57,10 @@
               style="width: 240px"
             >
               <el-option
-                v-for="dict in statusOptions"
-                :key="dict.dictValue"
-                :label="dict.dictLabel"
-                :value="dict.dictValue"
+                v-for="dict in dict.type.sys_normal_disable"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
               />
             </el-select>
           </el-form-item>
@@ -251,10 +251,10 @@
             <el-form-item label="鐢ㄦ埛鎬у埆">
               <el-select v-model="form.sex" placeholder="璇烽�夋嫨">
                 <el-option
-                  v-for="dict in sexOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel"
-                  :value="dict.dictValue"
+                  v-for="dict in dict.type.sys_user_sex"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
                 ></el-option>
               </el-select>
             </el-form-item>
@@ -263,10 +263,10 @@
             <el-form-item label="鐘舵��">
               <el-radio-group v-model="form.status">
                 <el-radio
-                  v-for="dict in statusOptions"
-                  :key="dict.dictValue"
-                  :label="dict.dictValue"
-                >{{dict.dictLabel}}</el-radio>
+                  v-for="dict in dict.type.sys_normal_disable"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{dict.label}}</el-radio>
               </el-radio-group>
             </el-form-item>
           </el-col>
@@ -354,6 +354,7 @@
 
 export default {
   name: "User",
+  dicts: ['sys_normal_disable', 'sys_user_sex'],
   components: { Treeselect },
   data() {
     return {
@@ -385,10 +386,6 @@
       initPassword: undefined,
       // 鏃ユ湡鑼冨洿
       dateRange: [],
-      // 鐘舵�佹暟鎹瓧鍏�
-      statusOptions: [],
-      // 鎬у埆鐘舵�佸瓧鍏�
-      sexOptions: [],
       // 宀椾綅閫夐」
       postOptions: [],
       // 瑙掕壊閫夐」
@@ -472,12 +469,6 @@
   created() {
     this.getList();
     this.getTreeselect();
-    this.getDicts("sys_normal_disable").then(response => {
-      this.statusOptions = response.data;
-    });
-    this.getDicts("sys_user_sex").then(response => {
-      this.sexOptions = response.data;
-    });
     this.getConfigKey("sys.user.initPassword").then(response => {
       this.initPassword = response.msg;
     });
@@ -689,4 +680,4 @@
     }
   }
 };
-</script>
+</script>
\ No newline at end of file

--
Gitblit v1.9.3