浏览代码

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

RuoYi 4 年之前
父节点
当前提交
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 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 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 3
 import java.security.MessageDigest;
4 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 8
 import org.springframework.stereotype.Component;
9 9
 import com.ruoyi.common.core.constant.CacheConstants;
10 10
 import com.ruoyi.common.core.constant.SecurityConstants;
11
-import com.ruoyi.common.core.utils.IdUtils;
12 11
 import com.ruoyi.common.core.utils.JwtUtils;
13 12
 import com.ruoyi.common.core.utils.ServletUtils;
14 13
 import com.ruoyi.common.core.utils.StringUtils;
15 14
 import com.ruoyi.common.core.utils.ip.IpUtils;
15
+import com.ruoyi.common.core.utils.uuid.IdUtils;
16 16
 import com.ruoyi.common.redis.service.RedisService;
17 17
 import com.ruoyi.common.security.utils.SecurityUtils;
18 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 11
 import com.google.code.kaptcha.Producer;
12 12
 import com.ruoyi.common.core.constant.Constants;
13 13
 import com.ruoyi.common.core.exception.CaptchaException;
14
-import com.ruoyi.common.core.utils.IdUtils;
15 14
 import com.ruoyi.common.core.utils.StringUtils;
16 15
 import com.ruoyi.common.core.utils.sign.Base64;
16
+import com.ruoyi.common.core.utils.uuid.IdUtils;
17 17
 import com.ruoyi.common.core.web.domain.AjaxResult;
18 18
 import com.ruoyi.common.redis.service.RedisService;
19 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 9
 import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
10 10
 import com.ruoyi.common.core.exception.file.InvalidExtensionException;
11 11
 import com.ruoyi.common.core.utils.DateUtils;
12
-import com.ruoyi.common.core.utils.IdUtils;
13 12
 import com.ruoyi.common.core.utils.StringUtils;
14 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 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 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 1
 <template>
2 2
   <div class="upload-file">
3 3
     <el-upload
4
+      multiple
4 5
       :action="uploadFileUrl"
5 6
       :before-upload="handleBeforeUpload"
6 7
       :file-list="fileList"
@@ -69,6 +70,8 @@ export default {
69 70
   },
70 71
   data() {
71 72
     return {
73
+      number: 0,
74
+      uploadList: [],
72 75
       uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
73 76
       headers: {
74 77
         Authorization: "Bearer " + getToken(),
@@ -121,7 +124,7 @@ export default {
121 124
           return false;
122 125
         });
123 126
         if (!isTypeOk) {
124
-          this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
127
+          this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
125 128
           return false;
126 129
         }
127 130
       }
@@ -129,25 +132,33 @@ export default {
129 132
       if (this.fileSize) {
130 133
         const isLt = file.size / 1024 / 1024 < this.fileSize;
131 134
         if (!isLt) {
132
-          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
135
+          this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
133 136
           return false;
134 137
         }
135 138
       }
139
+      this.$modal.loading("正在上传文件,请稍候...");
140
+      this.number++;
136 141
       return true;
137 142
     },
138 143
     // 文件个数超出
139 144
     handleExceed() {
140
-      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
145
+      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
141 146
     },
142 147
     // 上传失败
143 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 164
     handleDelete(index) {
@@ -157,7 +168,7 @@ export default {
157 168
     // 获取文件名称
158 169
     getFileName(name) {
159 170
       if (name.lastIndexOf("/") > -1) {
160
-        return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
171
+        return name.slice(name.lastIndexOf("/") + 1);
161 172
       } else {
162 173
         return "";
163 174
       }

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

@@ -128,7 +128,7 @@ export default {
128 128
         this.uploadList = [];
129 129
         this.number = 0;
130 130
         this.$emit("input", this.listToString(this.fileList));
131
-        this.loading.close();
131
+        this.$modal.closeLoading();
132 132
       }
133 133
     },
134 134
     // 上传前loading加载
@@ -149,36 +149,27 @@ export default {
149 149
       }
150 150
 
151 151
       if (!isImg) {
152
-        this.$message.error(
153
-          `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
154
-        );
152
+        this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);
155 153
         return false;
156 154
       }
157 155
       if (this.fileSize) {
158 156
         const isLt = file.size / 1024 / 1024 < this.fileSize;
159 157
         if (!isLt) {
160
-          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
158
+          this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
161 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 163
       this.number++;
170 164
     },
171 165
     // 文件个数超出
172 166
     handleExceed() {
173
-      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
167
+      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
174 168
     },
175 169
     // 上传失败
176 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 175
     handlePictureCardPreview(file) {

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

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