22 Component: UploadImgs
33 Describe: 多图片上传组件, 附有预览, 排序, 验证等功能
44
5- todo: 文档编写
6- todo: jsDoc 编写
7- todo: 图像验证支持是否动图验证
85todo: 使用中间件模式优化信息装载和验证功能
96todo: 文件判断使用 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+
127110const ONE_KB = 1024
128111const 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