Skip to content

Commit 7f57858

Browse files
committed
feat(imgUpload): 支持动图检测规则, 新增reset方法等
1 parent 02babdc commit 7f57858

File tree

1 file changed

+66
-52
lines changed

1 file changed

+66
-52
lines changed

src/components/base/upload-imgs/index.vue

Lines changed: 66 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
Component: UploadImgs
33
Describe: 多图片上传组件, 附有预览, 排序, 验证等功能
44
5-
todo: 文档编写
6-
todo: jsDoc 编写
7-
todo: 图像验证支持是否动图验证
85
todo: 使用中间件模式优化信息装载和验证功能
96
todo: 文件判断使用 serveWorker 优化性能
107
-->
@@ -24,18 +21,10 @@ todo: 文件判断使用 serveWorker 优化性能
2421
:fit="fit"
2522
style="width: 100%; height: 100%;"></el-image>
2623
<div class="info">
27-
<i
28-
v-if="item.file"
29-
class="el-icon-upload wait-upload"
30-
@click.prevent.stop="delItem(item.id)"
31-
title="等待上传"></i>
24+
<i v-if="item.file" class="el-icon-upload wait-upload" @click.prevent.stop="delItem(item.id)" title="等待上传"></i>
3225
</div>
3326
<div class="control">
34-
<i
35-
v-if="!disabled"
36-
class="el-icon-close del"
37-
@click.prevent.stop="delItem(item.id)"
38-
title="删除"></i>
27+
<i v-if="!disabled" class="el-icon-close del" @click.prevent.stop="delItem(item.id)" title="删除"></i>
3928
<div
4029
v-if="!disabled"
4130
class="preview"
@@ -44,24 +33,9 @@ todo: 文件判断使用 serveWorker 优化性能
4433
<i class="el-icon-edit"></i>
4534
</div>
4635
<div class="control-bottom" v-if="sortable || preview">
47-
<i
48-
v-if="sortable && !disabled"
49-
title="前移"
50-
class="control-bottom-btn el-icon-back"
51-
:class="{disabled: (i === 0)}"
52-
@click.stop="move(item.id, -1)"></i>
53-
<i
54-
v-if="preview"
55-
class="control-bottom-btn el-icon-view"
56-
title="预览"
57-
style="cursor: pointer;"
58-
@click.stop="previewImg(item, i)"></i>
59-
<i
60-
v-if="sortable && !disabled"
61-
title="后移"
62-
class="control-bottom-btn el-icon-right"
63-
:class="{disabled: (i === (itemList.length - 1))}"
64-
@click.stop="move(item.id, 1)"></i>
36+
<i v-if="sortable && !disabled" title="前移" class="control-bottom-btn el-icon-back" :class="{disabled: (i === 0)}" @click.stop="move(item.id, -1)"></i>
37+
<i v-if="preview" class="control-bottom-btn el-icon-view" title="预览" style="cursor: pointer;" @click.stop="previewImg(item, i)"></i>
38+
<i v-if="sortable && !disabled" title="后移" class="control-bottom-btn el-icon-right" :class="{disabled: (i === (itemList.length - 1))}" @click.stop="move(item.id, 1)"></i>
6539
</div>
6640
</div>
6741
</div>
@@ -79,13 +53,7 @@ todo: 文件判断使用 serveWorker 优化性能
7953
</div>
8054
</template>
8155
</template>
82-
<input
83-
class="upload-imgs__input"
84-
type="file"
85-
ref="input"
86-
@change="handleChange"
87-
:multiple="multiple"
88-
:accept="accept" />
56+
<input class="upload-imgs__input" type="file" ref="input" @change="handleChange" :multiple="multiple" :accept="accept" />
8957
</div>
9058
</template>
9159

@@ -108,22 +76,37 @@ import {
10876
* @property {number} size 文件大小
10977
* @property {string} type 文件的媒体类型 (MIME)
11078
* @property {Date} lastModified 文件最后修改时间
79+
* @property {boolean} isAnimated 是否是动态图, 如果不进行检测则为 null
11180
*/
11281
11382
/**
11483
* 返回数据对象
84+
* 初始化的图片如果没有传入字段, 则值为空 null
11585
* @typedef {Object<string, number>} ReturnItem
116-
* @property {number|string} id 本地图像预览地址
117-
* @property {number|string} imgId
86+
* @property {number|string} id 初始化数据的 id
87+
* @property {number|string} imgId 图像资源 id
11888
* @property {string} src 文件相对路径
119-
* @property {string} display 文件完整路径
89+
* @property {string} display 图像完整地址
12090
* @property {number} height
12191
* @property {number} width
12292
* @property {string} fileName 文件名
12393
* @property {string} fileType 文件的媒体类型 (MIME), 针对部分文件类型做了检测
12494
* @property {boolean} isAnimated 是否是动态图, 如果不进行检测则为 null
12595
*/
12696
97+
/**
98+
* 返回数据对象
99+
* @typedef {Object} ValidateRule
100+
* @property {array|number} ratio 比例 [宽,高], 或者 宽/高 的数值
101+
* @property {number} width 宽度必需等于
102+
* @property {number} height 高度必需等于
103+
* @property {number} minWidth 最小宽
104+
* @property {number} minHeight 最小高
105+
* @property {number} minSize 最小 size(Mb)
106+
* @property {number} maxSize 最大 size(Mb)
107+
* @property {number} allowAnimated 是否允许上传动图, 0 不检测, 1 不允许动图, 2 只允许动图. 要检查此项, 需设置属性 animated-check 为 true
108+
*/
109+
127110
const ONE_KB = 1024
128111
const ONE_MB = ONE_KB * 1024
129112
@@ -279,7 +262,9 @@ export default {
279262
/** 图像验证规则 */
280263
rules: {
281264
type: [Object, Function],
282-
default: () => {},
265+
default: () => ({
266+
maxSize: 2,
267+
}),
283268
},
284269
/** 是否禁用, 禁用后只可展示 不可进行编辑操作, 包括: 新增, 修改, 删除, 改变顺序 */
285270
disabled: {
@@ -388,7 +373,7 @@ export default {
388373
basicRule = {}
389374
}
390375
} else {
391-
basicRule = rules
376+
basicRule = rules || {}
392377
}
393378
394379
// 宽高限制提示语
@@ -419,6 +404,15 @@ export default {
419404
tips.push(getRangeTip('文件大小', basicRule.minSize, basicRule.maxSize, 'Mb'))
420405
}
421406
407+
// 是否动态图
408+
if (basicRule.allowAnimated && basicRule.allowAnimated > 0) {
409+
if (basicRule.allowAnimated === 1) {
410+
tips.push('不允许上传动图')
411+
} else if (basicRule.allowAnimated === 1) {
412+
tips.push('只允许上传动图')
413+
}
414+
}
415+
422416
return tips
423417
},
424418
},
@@ -526,7 +520,7 @@ export default {
526520
// eslint-disable-next-line
527521
imgItem.display = res.url
528522
// eslint-disable-next-line
529-
imgItem.src = res.url
523+
imgItem.src = res.path
530524
// eslint-disable-next-line
531525
imgItem.imgId = res.id
532526
// eslint-disable-next-line
@@ -655,14 +649,15 @@ export default {
655649
/** @type {ReturnItem} */
656650
const val = {
657651
id: item.status === 'new' ? '' : item.id,
658-
imgId: item.imgId,
659-
src: item.src,
652+
imgId: item.imgId || null,
653+
src: item.src || null,
660654
display: item.display,
661-
width: item.width,
662-
height: item.height,
663-
fileName: item.name,
664-
fileType: item.type,
665-
isAnimated: item.isAnimated,
655+
width: item.width || null,
656+
height: item.height || null,
657+
fileSize: item.size || null,
658+
fileName: item.name || null,
659+
fileType: item.type || null,
660+
isAnimated: item.isAnimated || null,
666661
}
667662
return val
668663
})
@@ -738,10 +733,11 @@ export default {
738733
},
739734
/**
740735
* 验证上传的图像是否符合要求
741-
* @param {Object} 图像信息, 包括文件名, 宽高
736+
* @param {LocalFileInfo} imgInfo 图像信息, 包括文件名, 宽高
742737
*/
743738
async validateImg(imgInfo) {
744739
const { rules } = this
740+
/** @type ValidateRule */
745741
let rule
746742
// 针对动态规则模式, 获取输入为空时的规则
747743
// 动态规则 rule 为函数, 当选择图片后根据选择的图片生成校验规则
@@ -754,6 +750,20 @@ export default {
754750
} else {
755751
rule = rules
756752
}
753+
754+
if (rule.allowAnimated && rule.allowAnimated > 0) {
755+
if (imgInfo.isAnimated === null) {
756+
this.$message.error('要进行是否动图验证需要配置 "animated-check" 属性为 true')
757+
} else {
758+
if (rule.allowAnimated === 1 && imgInfo.isAnimated) {
759+
throw new Error(`"${imgInfo.name}"为动态图, 不允许上传`)
760+
}
761+
if (rule.allowAnimated === 2 && !imgInfo.isAnimated) {
762+
throw new Error(`"${imgInfo.name}"为静态图, 只允许上传动态图`)
763+
}
764+
}
765+
}
766+
757767
// 宽高限制
758768
if (rule.width) {
759769
if (imgInfo.width !== rule.width) {
@@ -1009,6 +1019,10 @@ export default {
10091019
this.initItemList([])
10101020
this.getValue()
10111021
},
1022+
/** 重置图片数据传入属性 */
1023+
reset() {
1024+
this.initItemList(this.value)
1025+
},
10121026
},
10131027
}
10141028
</script>

0 commit comments

Comments
 (0)