Ver código fonte

组件fileUpload支持多文件同时选择上传

RuoYi 4 anos atrás
pai
commit
04706403d3

+ 50 - 1
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java

@@ -478,4 +478,53 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
478
     {
478
     {
479
         return (T) obj;
479
         return (T) obj;
480
     }
480
     }
481
-}
481
+
482
+    /**
483
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
484
+     * 
485
+     * @param num 数字对象
486
+     * @param size 字符串指定长度
487
+     * @return 返回数字的字符串格式,该字符串为指定长度。
488
+     */
489
+    public static final String padl(final Number num, final int size)
490
+    {
491
+        return padl(num.toString(), size, '0');
492
+    }
493
+
494
+    /**
495
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
496
+     * 
497
+     * @param s 原始字符串
498
+     * @param size 字符串指定长度
499
+     * @param c 用于补齐的字符
500
+     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
501
+     */
502
+    public static final String padl(final String s, final int size, final char c)
503
+    {
504
+        final StringBuilder sb = new StringBuilder(size);
505
+        if (s != null)
506
+        {
507
+            final int len = s.length();
508
+            if (s.length() <= size)
509
+            {
510
+                for (int i = size - len; i > 0; i--)
511
+                {
512
+                    sb.append(c);
513
+                }
514
+                sb.append(s);
515
+            }
516
+            else
517
+            {
518
+                return s.substring(len - size, len);
519
+            }
520
+        }
521
+        else
522
+        {
523
+            for (int i = size; i > 0; i--)
524
+            {
525
+                sb.append(c);
526
+            }
527
+        }
528
+        return sb.toString();
529
+    }
530
+}

+ 1 - 3
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/IdUtils.java

@@ -1,6 +1,4 @@
1
-package com.ruoyi.common.core.utils;
2
-
3
-import com.ruoyi.common.core.text.UUID;
1
+package com.ruoyi.common.core.utils.uuid;
4
 
2
 
5
 /**
3
 /**
6
  * ID生成器工具类
4
  * ID生成器工具类

+ 86 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/uuid/Seq.java

@@ -0,0 +1,86 @@
1
+package com.ruoyi.common.core.utils.uuid;
2
+
3
+import java.util.concurrent.atomic.AtomicInteger;
4
+import com.ruoyi.common.core.utils.DateUtils;
5
+import com.ruoyi.common.core.utils.StringUtils;
6
+
7
+/**
8
+ * @author ruoyi 序列生成类
9
+ */
10
+public class Seq
11
+{
12
+    // 通用序列类型
13
+    public static final String commSeqType = "COMMON";
14
+
15
+    // 上传序列类型
16
+    public static final String uploadSeqType = "UPLOAD";
17
+
18
+    // 通用接口序列数
19
+    private static AtomicInteger commSeq = new AtomicInteger(1);
20
+
21
+    // 上传接口序列数
22
+    private static AtomicInteger uploadSeq = new AtomicInteger(1);
23
+
24
+    // 机器标识
25
+    private static String machineCode = "A";
26
+
27
+    /**
28
+     * 获取通用序列号
29
+     * 
30
+     * @return 序列值
31
+     */
32
+    public static String getId()
33
+    {
34
+        return getId(commSeqType);
35
+    }
36
+    
37
+    /**
38
+     * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
39
+     * 
40
+     * @return 序列值
41
+     */
42
+    public static String getId(String type)
43
+    {
44
+        AtomicInteger atomicInt = commSeq;
45
+        if (uploadSeqType.equals(type))
46
+        {
47
+            atomicInt = uploadSeq;
48
+        }
49
+        return getId(atomicInt, 3);
50
+    }
51
+
52
+    /**
53
+     * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
54
+     * 
55
+     * @param atomicInt 序列数
56
+     * @param length 数值长度
57
+     * @return 序列值
58
+     */
59
+    public static String getId(AtomicInteger atomicInt, int length)
60
+    {
61
+        String result = DateUtils.dateTimeNow();
62
+        result += machineCode;
63
+        result += getSeq(atomicInt, length);
64
+        return result;
65
+    }
66
+
67
+    /**
68
+     * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
69
+     * 
70
+     * @return 序列值
71
+     */
72
+    private synchronized static String getSeq(AtomicInteger atomicInt, int length)
73
+    {
74
+        // 先取值再+1
75
+        int value = atomicInt.getAndIncrement();
76
+
77
+        // 如果更新后值>=10 的 (length)幂次方则重置为1
78
+        int maxSeq = (int) Math.pow(10, length);
79
+        if (atomicInt.get() >= maxSeq)
80
+        {
81
+            atomicInt.set(1);
82
+        }
83
+        // 转字符串,用0左补齐
84
+        return StringUtils.padl(value, length);
85
+    }
86
+}

+ 1 - 1
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/text/UUID.java

@@ -1,4 +1,4 @@
1
-package com.ruoyi.common.core.text;
1
+package com.ruoyi.common.core.utils.uuid;
2
 
2
 
3
 import java.security.MessageDigest;
3
 import java.security.MessageDigest;
4
 import java.security.NoSuchAlgorithmException;
4
 import java.security.NoSuchAlgorithmException;

+ 1 - 1
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java

@@ -8,11 +8,11 @@ import org.springframework.beans.factory.annotation.Autowired;
8
 import org.springframework.stereotype.Component;
8
 import org.springframework.stereotype.Component;
9
 import com.ruoyi.common.core.constant.CacheConstants;
9
 import com.ruoyi.common.core.constant.CacheConstants;
10
 import com.ruoyi.common.core.constant.SecurityConstants;
10
 import com.ruoyi.common.core.constant.SecurityConstants;
11
-import com.ruoyi.common.core.utils.IdUtils;
12
 import com.ruoyi.common.core.utils.JwtUtils;
11
 import com.ruoyi.common.core.utils.JwtUtils;
13
 import com.ruoyi.common.core.utils.ServletUtils;
12
 import com.ruoyi.common.core.utils.ServletUtils;
14
 import com.ruoyi.common.core.utils.StringUtils;
13
 import com.ruoyi.common.core.utils.StringUtils;
15
 import com.ruoyi.common.core.utils.ip.IpUtils;
14
 import com.ruoyi.common.core.utils.ip.IpUtils;
15
+import com.ruoyi.common.core.utils.uuid.IdUtils;
16
 import com.ruoyi.common.redis.service.RedisService;
16
 import com.ruoyi.common.redis.service.RedisService;
17
 import com.ruoyi.common.security.utils.SecurityUtils;
17
 import com.ruoyi.common.security.utils.SecurityUtils;
18
 import com.ruoyi.system.api.model.LoginUser;
18
 import com.ruoyi.system.api.model.LoginUser;

+ 1 - 1
ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java

@@ -11,9 +11,9 @@ import org.springframework.util.FastByteArrayOutputStream;
11
 import com.google.code.kaptcha.Producer;
11
 import com.google.code.kaptcha.Producer;
12
 import com.ruoyi.common.core.constant.Constants;
12
 import com.ruoyi.common.core.constant.Constants;
13
 import com.ruoyi.common.core.exception.CaptchaException;
13
 import com.ruoyi.common.core.exception.CaptchaException;
14
-import com.ruoyi.common.core.utils.IdUtils;
15
 import com.ruoyi.common.core.utils.StringUtils;
14
 import com.ruoyi.common.core.utils.StringUtils;
16
 import com.ruoyi.common.core.utils.sign.Base64;
15
 import com.ruoyi.common.core.utils.sign.Base64;
16
+import com.ruoyi.common.core.utils.uuid.IdUtils;
17
 import com.ruoyi.common.core.web.domain.AjaxResult;
17
 import com.ruoyi.common.core.web.domain.AjaxResult;
18
 import com.ruoyi.common.redis.service.RedisService;
18
 import com.ruoyi.common.redis.service.RedisService;
19
 import com.ruoyi.gateway.config.properties.CaptchaProperties;
19
 import com.ruoyi.gateway.config.properties.CaptchaProperties;

+ 3 - 2
ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java

@@ -9,9 +9,9 @@ import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException
9
 import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
9
 import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
10
 import com.ruoyi.common.core.exception.file.InvalidExtensionException;
10
 import com.ruoyi.common.core.exception.file.InvalidExtensionException;
11
 import com.ruoyi.common.core.utils.DateUtils;
11
 import com.ruoyi.common.core.utils.DateUtils;
12
-import com.ruoyi.common.core.utils.IdUtils;
13
 import com.ruoyi.common.core.utils.StringUtils;
12
 import com.ruoyi.common.core.utils.StringUtils;
14
 import com.ruoyi.common.core.utils.file.MimeTypeUtils;
13
 import com.ruoyi.common.core.utils.file.MimeTypeUtils;
14
+import com.ruoyi.common.core.utils.uuid.Seq;
15
 
15
 
16
 /**
16
 /**
17
  * 文件上传工具类
17
  * 文件上传工具类
@@ -86,7 +86,8 @@ public class FileUploadUtils
86
      */
86
      */
87
     public static final String extractFilename(MultipartFile file)
87
     public static final String extractFilename(MultipartFile file)
88
     {
88
     {
89
-        return DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + getExtension(file);
89
+        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
90
+                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
90
     }
91
     }
91
 
92
 
92
     private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
93
     private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException

+ 20 - 9
ruoyi-ui/src/components/FileUpload/index.vue

@@ -1,6 +1,7 @@
1
 <template>
1
 <template>
2
   <div class="upload-file">
2
   <div class="upload-file">
3
     <el-upload
3
     <el-upload
4
+      multiple
4
       :action="uploadFileUrl"
5
       :action="uploadFileUrl"
5
       :before-upload="handleBeforeUpload"
6
       :before-upload="handleBeforeUpload"
6
       :file-list="fileList"
7
       :file-list="fileList"
@@ -69,6 +70,8 @@ export default {
69
   },
70
   },
70
   data() {
71
   data() {
71
     return {
72
     return {
73
+      number: 0,
74
+      uploadList: [],
72
       uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
75
       uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
73
       headers: {
76
       headers: {
74
         Authorization: "Bearer " + getToken(),
77
         Authorization: "Bearer " + getToken(),
@@ -121,7 +124,7 @@ export default {
121
           return false;
124
           return false;
122
         });
125
         });
123
         if (!isTypeOk) {
126
         if (!isTypeOk) {
124
-          this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
127
+          this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
125
           return false;
128
           return false;
126
         }
129
         }
127
       }
130
       }
@@ -129,25 +132,33 @@ export default {
129
       if (this.fileSize) {
132
       if (this.fileSize) {
130
         const isLt = file.size / 1024 / 1024 < this.fileSize;
133
         const isLt = file.size / 1024 / 1024 < this.fileSize;
131
         if (!isLt) {
134
         if (!isLt) {
132
-          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
135
+          this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
133
           return false;
136
           return false;
134
         }
137
         }
135
       }
138
       }
139
+      this.$modal.loading("正在上传文件,请稍候...");
140
+      this.number++;
136
       return true;
141
       return true;
137
     },
142
     },
138
     // 文件个数超出
143
     // 文件个数超出
139
     handleExceed() {
144
     handleExceed() {
140
-      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
145
+      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
141
     },
146
     },
142
     // 上传失败
147
     // 上传失败
143
     handleUploadError(err) {
148
     handleUploadError(err) {
144
-      this.$message.error("上传失败, 请重试");
149
+      this.$modal.msgError("上传图片失败,请重试");
150
+      this.$modal.closeLoading()
145
     },
151
     },
146
     // 上传成功回调
152
     // 上传成功回调
147
-    handleUploadSuccess(res, file) {
148
-      this.$message.success("上传成功");
149
-      this.fileList.push({ name: res.data.url, url: res.data.url });
150
-      this.$emit("input", this.listToString(this.fileList));
153
+    handleUploadSuccess(res) {
154
+      this.uploadList.push({ name: res.data.url, url: res.data.url });
155
+      if (this.uploadList.length === this.number) {
156
+        this.fileList = this.fileList.concat(this.uploadList);
157
+        this.uploadList = [];
158
+        this.number = 0;
159
+        this.$emit("input", this.listToString(this.fileList));
160
+        this.$modal.closeLoading();
161
+      }
151
     },
162
     },
152
     // 删除文件
163
     // 删除文件
153
     handleDelete(index) {
164
     handleDelete(index) {
@@ -157,7 +168,7 @@ export default {
157
     // 获取文件名称
168
     // 获取文件名称
158
     getFileName(name) {
169
     getFileName(name) {
159
       if (name.lastIndexOf("/") > -1) {
170
       if (name.lastIndexOf("/") > -1) {
160
-        return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
171
+        return name.slice(name.lastIndexOf("/") + 1);
161
       } else {
172
       } else {
162
         return "";
173
         return "";
163
       }
174
       }

+ 7 - 16
ruoyi-ui/src/components/ImageUpload/index.vue

@@ -128,7 +128,7 @@ export default {
128
         this.uploadList = [];
128
         this.uploadList = [];
129
         this.number = 0;
129
         this.number = 0;
130
         this.$emit("input", this.listToString(this.fileList));
130
         this.$emit("input", this.listToString(this.fileList));
131
-        this.loading.close();
131
+        this.$modal.closeLoading();
132
       }
132
       }
133
     },
133
     },
134
     // 上传前loading加载
134
     // 上传前loading加载
@@ -149,36 +149,27 @@ export default {
149
       }
149
       }
150
 
150
 
151
       if (!isImg) {
151
       if (!isImg) {
152
-        this.$message.error(
153
-          `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
154
-        );
152
+        this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);
155
         return false;
153
         return false;
156
       }
154
       }
157
       if (this.fileSize) {
155
       if (this.fileSize) {
158
         const isLt = file.size / 1024 / 1024 < this.fileSize;
156
         const isLt = file.size / 1024 / 1024 < this.fileSize;
159
         if (!isLt) {
157
         if (!isLt) {
160
-          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
158
+          this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
161
           return false;
159
           return false;
162
         }
160
         }
163
       }
161
       }
164
-      this.loading = this.$loading({
165
-        lock: true,
166
-        text: "上传中",
167
-        background: "rgba(0, 0, 0, 0.7)",
168
-      });
162
+      this.$modal.loading("正在上传图片,请稍候...");
169
       this.number++;
163
       this.number++;
170
     },
164
     },
171
     // 文件个数超出
165
     // 文件个数超出
172
     handleExceed() {
166
     handleExceed() {
173
-      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
167
+      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
174
     },
168
     },
175
     // 上传失败
169
     // 上传失败
176
     handleUploadError() {
170
     handleUploadError() {
177
-      this.$message({
178
-        type: "error",
179
-        message: "上传失败",
180
-      });
181
-      this.loading.close();
171
+      this.$modal.msgError("上传图片失败,请重试");
172
+      this.$modal.closeLoading();
182
     },
173
     },
183
     // 预览
174
     // 预览
184
     handlePictureCardPreview(file) {
175
     handlePictureCardPreview(file) {

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

@@ -443,7 +443,7 @@ export default {
443
         email: [
443
         email: [
444
           {
444
           {
445
             type: "email",
445
             type: "email",
446
-            message: "'请输入正确的邮箱地址",
446
+            message: "请输入正确的邮箱地址",
447
             trigger: ["blur", "change"]
447
             trigger: ["blur", "change"]
448
           }
448
           }
449
         ],
449
         ],