diff --git a/ruoyi-ui/src/components/FileUpload/index.vue b/ruoyi-ui/src/components/FileUpload/index.vue
index 6e7992ad..bdbb0694 100644
--- a/ruoyi-ui/src/components/FileUpload/index.vue
+++ b/ruoyi-ui/src/components/FileUpload/index.vue
@@ -163,13 +163,14 @@ export default {
         return "";
       }
     },
-    // 对象转成分隔字符串
-    listToString(list) {
-      let files = "";
-      for (let key in list) {
-        files += list[key].url + ",";
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        strs += list[i].url + separator;
       }
-      return files.substr(0, files.length - 1);
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
     }
   }
 };
diff --git a/ruoyi-ui/src/components/ImageUpload/index.vue b/ruoyi-ui/src/components/ImageUpload/index.vue
index ce540eb8..062e27d4 100644
--- a/ruoyi-ui/src/components/ImageUpload/index.vue
+++ b/ruoyi-ui/src/components/ImageUpload/index.vue
@@ -5,33 +5,38 @@
       list-type="picture-card"
       :on-success="handleUploadSuccess"
       :before-upload="handleBeforeUpload"
+      :limit="limit"
       :on-error="handleUploadError"
+      :on-exceed="handleExceed"
       name="file"
-      :show-file-list="false"
+      :on-remove="handleRemove"
+      :show-file-list="true"
       :headers="headers"
-      style="display: inline-block; vertical-align: top"
+      :file-list="fileList"
+      :on-preview="handlePictureCardPreview"
+      :class="{hide: this.fileList.length >= this.limit}"
     >
-      
-        
-          
-        
-      
-      
+      
     
-    
-      ![]() +    
+    
+
+    
+    
+    
+      请上传
+       大小不超过 {{ fileSize }}MB 
+       格式为 {{ fileType.join("/") }} 
+      的文件
+    
+
+    
+      ![]() @@ -40,36 +45,128 @@
 import { getToken } from "@/utils/auth";
 
 export default {
+  props: {
+    value: [String, Object, Array],
+    // 图片数量限制
+    limit: {
+      type: Number,
+      default: 5,
+    },
+    // 大小限制(MB)
+    fileSize: {
+       type: Number,
+      default: 5,
+    },
+    // 文件类型, 例如['png', 'jpg', 'jpeg']
+    fileType: {
+      type: Array,
+      default: () => ["png", "jpg", "jpeg"],
+    },
+    // 是否显示提示
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
   data() {
     return {
+      dialogImageUrl: "",
       dialogVisible: false,
+      hideUpload: false,
+      baseUrl: process.env.VUE_APP_BASE_API,
       uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
       headers: {
         Authorization: "Bearer " + getToken(),
       },
+      fileList: []
     };
   },
-  props: {
+  watch: {
     value: {
-      type: String,
-      default: "",
+      handler(val) {
+        if (val) {
+          // 首先将值转为数组
+          const list = Array.isArray(val) ? val : this.value.split(',');
+          // 然后将数组转为对象数组
+          this.fileList = list.map(item => {
+            if (typeof item === "string") {
+              if (item.indexOf(this.baseUrl) === -1) {
+                  item = { name: this.baseUrl + item, url: this.baseUrl + item };
+              } else {
+                  item = { name: item, url: item };
+              }
+            }
+            return item;
+          });
+        } else {
+          this.fileList = [];
+          return [];
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 是否显示提示
+    showTip() {
+      return this.isShowTip && (this.fileType || this.fileSize);
     },
   },
   methods: {
-    removeImage() {
-      this.$emit("input", "");
+    // 删除图片
+    handleRemove(file, fileList) {
+      const findex = this.fileList.indexOf(file.name);
+      this.fileList.splice(findex, 1);
+      this.$emit("input", this.listToString(this.fileList));
     },
+    // 上传成功回调
     handleUploadSuccess(res) {
-      this.$emit("input", res.url);
+      this.fileList.push({ name: res.fileName, url: res.fileName });
+      this.$emit("input", this.listToString(this.fileList));
       this.loading.close();
     },
-    handleBeforeUpload() {
+    // 上传前loading加载
+    handleBeforeUpload(file) {
+      let isImg = false;
+      if (this.fileType.length) {
+        let fileExtension = "";
+        if (file.name.lastIndexOf(".") > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
+        }
+        isImg = this.fileType.some(type => {
+          if (file.type.indexOf(type) > -1) return true;
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
+          return false;
+        });
+      } else {
+        isImg = file.type.indexOf("image") > -1;
+      }
+
+      if (!isImg) {
+        this.$message.error(
+          `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
+        );
+        return false;
+      }
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
       this.loading = this.$loading({
         lock: true,
         text: "上传中",
         background: "rgba(0, 0, 0, 0.7)",
       });
     },
+    // 文件个数超出
+    handleExceed() {
+      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
+    },
+    // 上传失败
     handleUploadError() {
       this.$message({
         type: "error",
@@ -77,24 +174,37 @@ export default {
       });
       this.loading.close();
     },
-  },
-  watch: {},
+    // 预览
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        strs += list[i].url + separator;
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
 };
 
-
 
\ No newline at end of file
+// 去掉动画效果
+::v-deep .el-list-enter-active,
+::v-deep .el-list-leave-active {
+    transition: all 0s;
+}
+
+::v-deep .el-list-enter, .el-list-leave-active {
+    opacity: 0;
+    transform: translateY(0);
+}
+
+
diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue
index d89930a8..c8837f2a 100644
--- a/ruoyi-ui/src/components/TopNav/index.vue
+++ b/ruoyi-ui/src/components/TopNav/index.vue
@@ -73,9 +73,9 @@ export default {
             if(router.path === "/") {
               router.children[item].path = "/redirect/" + router.children[item].path;
             } else {
-			  if(!this.ishttp(router.children[item].path)) {
+              if(!this.ishttp(router.children[item].path)) {
                 router.children[item].path = router.path + "/" + router.children[item].path;
-			  }
+              }
             }
             router.children[item].parentPath = router.path;
           }
     
   
 
@@ -40,36 +45,128 @@
 import { getToken } from "@/utils/auth";
 
 export default {
+  props: {
+    value: [String, Object, Array],
+    // 图片数量限制
+    limit: {
+      type: Number,
+      default: 5,
+    },
+    // 大小限制(MB)
+    fileSize: {
+       type: Number,
+      default: 5,
+    },
+    // 文件类型, 例如['png', 'jpg', 'jpeg']
+    fileType: {
+      type: Array,
+      default: () => ["png", "jpg", "jpeg"],
+    },
+    // 是否显示提示
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
   data() {
     return {
+      dialogImageUrl: "",
       dialogVisible: false,
+      hideUpload: false,
+      baseUrl: process.env.VUE_APP_BASE_API,
       uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
       headers: {
         Authorization: "Bearer " + getToken(),
       },
+      fileList: []
     };
   },
-  props: {
+  watch: {
     value: {
-      type: String,
-      default: "",
+      handler(val) {
+        if (val) {
+          // 首先将值转为数组
+          const list = Array.isArray(val) ? val : this.value.split(',');
+          // 然后将数组转为对象数组
+          this.fileList = list.map(item => {
+            if (typeof item === "string") {
+              if (item.indexOf(this.baseUrl) === -1) {
+                  item = { name: this.baseUrl + item, url: this.baseUrl + item };
+              } else {
+                  item = { name: item, url: item };
+              }
+            }
+            return item;
+          });
+        } else {
+          this.fileList = [];
+          return [];
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 是否显示提示
+    showTip() {
+      return this.isShowTip && (this.fileType || this.fileSize);
     },
   },
   methods: {
-    removeImage() {
-      this.$emit("input", "");
+    // 删除图片
+    handleRemove(file, fileList) {
+      const findex = this.fileList.indexOf(file.name);
+      this.fileList.splice(findex, 1);
+      this.$emit("input", this.listToString(this.fileList));
     },
+    // 上传成功回调
     handleUploadSuccess(res) {
-      this.$emit("input", res.url);
+      this.fileList.push({ name: res.fileName, url: res.fileName });
+      this.$emit("input", this.listToString(this.fileList));
       this.loading.close();
     },
-    handleBeforeUpload() {
+    // 上传前loading加载
+    handleBeforeUpload(file) {
+      let isImg = false;
+      if (this.fileType.length) {
+        let fileExtension = "";
+        if (file.name.lastIndexOf(".") > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
+        }
+        isImg = this.fileType.some(type => {
+          if (file.type.indexOf(type) > -1) return true;
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
+          return false;
+        });
+      } else {
+        isImg = file.type.indexOf("image") > -1;
+      }
+
+      if (!isImg) {
+        this.$message.error(
+          `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
+        );
+        return false;
+      }
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
       this.loading = this.$loading({
         lock: true,
         text: "上传中",
         background: "rgba(0, 0, 0, 0.7)",
       });
     },
+    // 文件个数超出
+    handleExceed() {
+      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
+    },
+    // 上传失败
     handleUploadError() {
       this.$message({
         type: "error",
@@ -77,24 +174,37 @@ export default {
       });
       this.loading.close();
     },
-  },
-  watch: {},
+    // 预览
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        strs += list[i].url + separator;
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
 };
 
-
 
\ No newline at end of file
+// 去掉动画效果
+::v-deep .el-list-enter-active,
+::v-deep .el-list-leave-active {
+    transition: all 0s;
+}
+
+::v-deep .el-list-enter, .el-list-leave-active {
+    opacity: 0;
+    transform: translateY(0);
+}
+
+
diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue
index d89930a8..c8837f2a 100644
--- a/ruoyi-ui/src/components/TopNav/index.vue
+++ b/ruoyi-ui/src/components/TopNav/index.vue
@@ -73,9 +73,9 @@ export default {
             if(router.path === "/") {
               router.children[item].path = "/redirect/" + router.children[item].path;
             } else {
-			  if(!this.ishttp(router.children[item].path)) {
+              if(!this.ishttp(router.children[item].path)) {
                 router.children[item].path = router.path + "/" + router.children[item].path;
-			  }
+              }
             }
             router.children[item].parentPath = router.path;
           }