Commit bc400cf6466031bc159d3eed0da5d0b55b4c1c2c

Authored by YunaiV
1 parent 4f5964f2

v3.6.0 ImageUpload组件支持多图片上传

yudao-ui-admin/src/components/FileUpload/index.vue
... ... @@ -163,13 +163,14 @@ export default {
163 163 return "";
164 164 }
165 165 },
166   - // 对象转成分隔字符串
167   - listToString(list) {
168   - let files = "";
169   - for (let key in list) {
170   - files += list[key].url + ",";
  166 + // 对象转成指定字符串分隔
  167 + listToString(list, separator) {
  168 + let strs = "";
  169 + separator = separator || ",";
  170 + for (let i in list) {
  171 + strs += list[i].url + separator;
171 172 }
172   - return files.substr(0, files.length - 1);
  173 + return strs != '' ? strs.substr(0, strs.length - 1) : '';
173 174 }
174 175 }
175 176 };
... ...
yudao-ui-admin/src/components/ImageUpload/index.vue
... ... @@ -5,33 +5,38 @@
5 5 list-type="picture-card"
6 6 :on-success="handleUploadSuccess"
7 7 :before-upload="handleBeforeUpload"
  8 + :limit="limit"
8 9 :on-error="handleUploadError"
  10 + :on-exceed="handleExceed"
9 11 name="file"
10   - :show-file-list="false"
  12 + :on-remove="handleRemove"
  13 + :show-file-list="true"
11 14 :headers="headers"
12   - style="display: inline-block; vertical-align: top"
  15 + :file-list="fileList"
  16 + :on-preview="handlePictureCardPreview"
  17 + :class="{hide: this.fileList.length >= this.limit}"
13 18 >
14   - <el-image v-if="!value" :src="value">
15   - <div slot="error" class="image-slot">
16   - <i class="el-icon-plus" />
17   - </div>
18   - </el-image>
19   - <div v-else class="image">
20   - <el-image :src="value" :style="`width:150px;height:150px;`" fit="fill"/>
21   - <div class="mask">
22   - <div class="actions">
23   - <span title="预览" @click.stop="dialogVisible = true">
24   - <i class="el-icon-zoom-in" />
25   - </span>
26   - <span title="移除" @click.stop="removeImage">
27   - <i class="el-icon-delete" />
28   - </span>
29   - </div>
30   - </div>
31   - </div>
  19 + <i class="el-icon-plus"></i>
32 20 </el-upload>
33   - <el-dialog :visible.sync="dialogVisible" title="预览" width="800" append-to-body>
34   - <img :src="value" style="display: block; max-width: 100%; margin: 0 auto;">
  21 +
  22 + <!-- 上传提示 -->
  23 + <div class="el-upload__tip" slot="tip" v-if="showTip">
  24 + 请上传
  25 + <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
  26 + <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
  27 + 的文件
  28 + </div>
  29 +
  30 + <el-dialog
  31 + :visible.sync="dialogVisible"
  32 + title="预览"
  33 + width="800"
  34 + append-to-body
  35 + >
  36 + <img
  37 + :src="dialogImageUrl"
  38 + style="display: block; max-width: 100%; margin: 0 auto"
  39 + />
35 40 </el-dialog>
36 41 </div>
37 42 </template>
... ... @@ -40,36 +45,128 @@
40 45 import { getToken } from "@/utils/auth";
41 46  
42 47 export default {
  48 + props: {
  49 + value: [String, Object, Array],
  50 + // 图片数量限制
  51 + limit: {
  52 + type: Number,
  53 + default: 5,
  54 + },
  55 + // 大小限制(MB)
  56 + fileSize: {
  57 + type: Number,
  58 + default: 5,
  59 + },
  60 + // 文件类型, 例如['png', 'jpg', 'jpeg']
  61 + fileType: {
  62 + type: Array,
  63 + default: () => ["png", "jpg", "jpeg"],
  64 + },
  65 + // 是否显示提示
  66 + isShowTip: {
  67 + type: Boolean,
  68 + default: true
  69 + }
  70 + },
43 71 data() {
44 72 return {
  73 + dialogImageUrl: "",
45 74 dialogVisible: false,
  75 + hideUpload: false,
  76 + baseUrl: process.env.VUE_APP_BASE_API,
46 77 uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
47 78 headers: {
48 79 Authorization: "Bearer " + getToken(),
49 80 },
  81 + fileList: []
50 82 };
51 83 },
52   - props: {
  84 + watch: {
53 85 value: {
54   - type: String,
55   - default: "",
  86 + handler(val) {
  87 + if (val) {
  88 + // 首先将值转为数组
  89 + const list = Array.isArray(val) ? val : this.value.split(',');
  90 + // 然后将数组转为对象数组
  91 + this.fileList = list.map(item => {
  92 + if (typeof item === "string") {
  93 + if (item.indexOf(this.baseUrl) === -1) {
  94 + item = { name: this.baseUrl + item, url: this.baseUrl + item };
  95 + } else {
  96 + item = { name: item, url: item };
  97 + }
  98 + }
  99 + return item;
  100 + });
  101 + } else {
  102 + this.fileList = [];
  103 + return [];
  104 + }
  105 + },
  106 + deep: true,
  107 + immediate: true
  108 + }
  109 + },
  110 + computed: {
  111 + // 是否显示提示
  112 + showTip() {
  113 + return this.isShowTip && (this.fileType || this.fileSize);
56 114 },
57 115 },
58 116 methods: {
59   - removeImage() {
60   - this.$emit("input", "");
  117 + // 删除图片
  118 + handleRemove(file, fileList) {
  119 + const findex = this.fileList.indexOf(file.name);
  120 + this.fileList.splice(findex, 1);
  121 + this.$emit("input", this.listToString(this.fileList));
61 122 },
  123 + // 上传成功回调
62 124 handleUploadSuccess(res) {
63   - this.$emit("input", res.url);
  125 + this.fileList.push({ name: res.fileName, url: res.fileName });
  126 + this.$emit("input", this.listToString(this.fileList));
64 127 this.loading.close();
65 128 },
66   - handleBeforeUpload() {
  129 + // 上传前loading加载
  130 + handleBeforeUpload(file) {
  131 + let isImg = false;
  132 + if (this.fileType.length) {
  133 + let fileExtension = "";
  134 + if (file.name.lastIndexOf(".") > -1) {
  135 + fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
  136 + }
  137 + isImg = this.fileType.some(type => {
  138 + if (file.type.indexOf(type) > -1) return true;
  139 + if (fileExtension && fileExtension.indexOf(type) > -1) return true;
  140 + return false;
  141 + });
  142 + } else {
  143 + isImg = file.type.indexOf("image") > -1;
  144 + }
  145 +
  146 + if (!isImg) {
  147 + this.$message.error(
  148 + `文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
  149 + );
  150 + return false;
  151 + }
  152 + if (this.fileSize) {
  153 + const isLt = file.size / 1024 / 1024 < this.fileSize;
  154 + if (!isLt) {
  155 + this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
  156 + return false;
  157 + }
  158 + }
67 159 this.loading = this.$loading({
68 160 lock: true,
69 161 text: "上传中",
70 162 background: "rgba(0, 0, 0, 0.7)",
71 163 });
72 164 },
  165 + // 文件个数超出
  166 + handleExceed() {
  167 + this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
  168 + },
  169 + // 上传失败
73 170 handleUploadError() {
74 171 this.$message({
75 172 type: "error",
... ... @@ -77,24 +174,37 @@ export default {
77 174 });
78 175 this.loading.close();
79 176 },
80   - },
81   - watch: {},
  177 + // 预览
  178 + handlePictureCardPreview(file) {
  179 + this.dialogImageUrl = file.url;
  180 + this.dialogVisible = true;
  181 + },
  182 + // 对象转成指定字符串分隔
  183 + listToString(list, separator) {
  184 + let strs = "";
  185 + separator = separator || ",";
  186 + for (let i in list) {
  187 + strs += list[i].url + separator;
  188 + }
  189 + return strs != '' ? strs.substr(0, strs.length - 1) : '';
  190 + }
  191 + }
82 192 };
83 193 </script>
84   -
85 194 <style scoped lang="scss">
86   -.image {
87   - position: relative;
88   - .mask {
89   - opacity: 0;
90   - position: absolute;
91   - top: 0;
92   - width: 100%;
93   - background-color: rgba(0, 0, 0, 0.5);
94   - transition: all 0.3s;
95   - }
96   - &:hover .mask {
97   - opacity: 1;
98   - }
  195 +// .el-upload--picture-card 控制加号部分
  196 +::v-deep.hide .el-upload--picture-card {
  197 + display: none;
  198 +}
  199 +// 去掉动画效果
  200 +::v-deep .el-list-enter-active,
  201 +::v-deep .el-list-leave-active {
  202 + transition: all 0s;
99 203 }
100   -</style>
101 204 \ No newline at end of file
  205 +
  206 +::v-deep .el-list-enter, .el-list-leave-active {
  207 + opacity: 0;
  208 + transform: translateY(0);
  209 +}
  210 +</style>
  211 +
... ...