33 Describe: 多图片上传组件, 附有预览, 排序, 验证等功能
44
55todo: 支持 before-upload
6- todo: 图像验证支持验证是否是动图
76todo: 文档编写
87todo: jsDoc 编写
98todo: 文件判断使用 serveWorker 优化性能
@@ -98,7 +97,8 @@ import {
9897} from ' ./utils'
9998
10099/**
101- * @typedef {Object<string, number, any>} LocalFileInfo 本地图像通过验证后构造的信息对象
100+ * 本地图像通过验证后构造的信息对象
101+ * @typedef {Object<string, number, any>} LocalFileInfo
102102 * @property {string} localSrc 本地图像预览地址
103103 * @property {File} file 本地图像文件
104104 * @property {number} width 宽
@@ -110,15 +110,17 @@ import {
110110 */
111111
112112/**
113- * @typedef {Object<string, number, any>} PreviewItem 本地图像通过验证后构造的信息对象
114- * @property {string} localSrc 本地图像预览地址
115- * @property {File} file 本地图像文件
116- * @property {number} width 宽
113+ * 返回数据对象
114+ * @typedef {Object<string, number>} ReturnItem
115+ * @property {number|string} id 本地图像预览地址
116+ * @property {number|string} imgId 宽
117+ * @property {string} src 文件相对路径
118+ * @property {string} display 文件完整路径
117119 * @property {number} height 高
118- * @property {string} name 文件名
119- * @property {number} size 文件大小
120- * @property {string} type 文件的媒体类型 (MIME)
121- * @property {Date} lastModified 文件最后修改时间
120+ * @property {number} width 宽
121+ * @property {string} fileName 文件名
122+ * @property {string} fileType 文件的媒体类型 (MIME), 针对部分文件类型做了检测
123+ * @property {boolean} isAnimated 是否是动态图, 如果不进行检测则为 null
122124 */
123125
124126const ONE_KB = 1024
@@ -285,12 +287,12 @@ export default {
285287 },
286288 /** 上传前插入方法, 属于高级用法 */
287289 beforeUpload: {
288- type: Promise ,
290+ type: Function ,
289291 default: null ,
290292 },
291293 /** 重写上传方法, 如果重写则覆盖组件内上传方法 */
292294 remoteFuc: {
293- type: [ Function , Promise ] ,
295+ type: Function ,
294296 default: null ,
295297 },
296298 /** 图像显示模式 */
@@ -536,38 +538,70 @@ export default {
536538 }
537539 // eslint-disable-next-line
538540 item .loading = true
539- // 如果是用户自定义方法
540- // 出于简化 api 的考虑, 只允许单个文件上传
541- if ( this . remoteFuc ) {
542- // 回调函数模式
543- if ( typeof this . remoteFuc === ' function ' ) {
544- return new Promise (( resolve ) => {
545- const a = this . remoteFuc ( item . file , ( data ) => {
546- reduceResult (item, data )
547- if ( ! data) {
548- this . $message . error ( ' 执行自定义上传出错 ' )
549- resolve ( false )
550- } else {
551- resolve (item)
552- }
553- })
541+ if ( this . beforeUpload && typeof this . beforeUpload === ' function ' ) {
542+ if ( typeof this . beforeUpload === ' function ' ) {
543+ const result = await new Promise (( resolve ) => {
544+ let a
545+ try {
546+ a = this . beforeUpload (item, ( data ) => {
547+ if ( ! data) {
548+ resolve ( false )
549+ } else {
550+ resolve ( true )
551+ }
552+ })
553+ } catch (err) {
554+ resolve ( false )
555+ }
554556 // promise 模式
555557 if (a != null && typeof a .then === ' function' ) {
556558 a .then ((remoteData ) => {
557- reduceResult (item, remoteData)
558559 if (! remoteData) {
559560 resolve (false )
560561 }
561- resolve (item )
562+ resolve (true )
562563 })
563564 }
564565 })
566+ if (! result) {
567+ reduceResult (item, false )
568+ return false
569+ }
565570 }
566571
567572 // 除 promise 和 函数回调外其他形式都不支持
568573 this .$message .error (' 执行自定义上传出错, 检查远程方法是否是promise或者函数' )
569574 return false
570575 }
576+ // 如果是用户自定义方法
577+ // 出于简化 api 的考虑, 只允许单个文件上传
578+ if (this .remoteFuc && typeof this .remoteFuc === ' function' ) {
579+ return new Promise ((resolve ) => {
580+ const a = this .remoteFuc (item .file , (data ) => {
581+ reduceResult (item, data)
582+ if (! data) {
583+ this .$message .error (' 执行自定义上传出错' )
584+ resolve (false )
585+ } else {
586+ resolve (item)
587+ }
588+ })
589+ // promise 模式
590+ if (a != null && typeof a .then === ' function' ) {
591+ a .then ((remoteData ) => {
592+ reduceResult (item, remoteData)
593+ if (! remoteData) {
594+ resolve (false )
595+ }
596+ resolve (item)
597+ })
598+ }
599+ })
600+
601+ // 除 promise 和 函数回调外其他形式都不支持
602+ this .$message .error (' 执行自定义上传出错, 检查远程方法是否是promise或者函数' )
603+ return false
604+ }
571605
572606 // 使用内置上传
573607 return new Promise ((resolve ) => {
@@ -623,12 +657,24 @@ export default {
623657 }
624658
625659 // 如无错误, 表示图像都以上传, 开始构造数据
626- const result = imgInfoList .map (item => ({
627- id: item .status === ' new' ? ' ' : item .id ,
628- imgId: item .imgId ,
629- src: item .src ,
630- display: item .display ,
631- }))
660+ /**
661+ * @type {array<ReturnItem>}
662+ */
663+ const result = imgInfoList .map ((item ) => {
664+ /** @type {ReturnItem} */
665+ const val = {
666+ id: item .status === ' new' ? ' ' : item .id ,
667+ imgId: item .imgId ,
668+ src: item .src ,
669+ display: item .display ,
670+ width: item .width ,
671+ height: item .height ,
672+ fileName: item .name ,
673+ fileType: item .type ,
674+ isAnimated: item .isAnimated ,
675+ }
676+ return val
677+ })
632678 // 获取数据成功后发出
633679 this .$emit (' upload' , result)
634680 return result
@@ -850,7 +896,7 @@ export default {
850896 }
851897 }
852898 } else {
853- const empty = max - itemList .length + 1
899+ const empty = max - itemList .length
854900 if (max && l > empty) {
855901 l = empty
856902 }
@@ -945,7 +991,7 @@ export default {
945991 image .src = localSrc
946992 image .onload = () => {
947993 /**
948- * @type LocalFileInfo
994+ * @type { LocalFileInfo}
949995 */
950996 const localFileInfo = {
951997 localSrc,
@@ -958,7 +1004,6 @@ export default {
9581004 lastModified: file .lastModified ,
9591005 isAnimated,
9601006 }
961- console .log (localFileInfo)
9621007 resolve (localFileInfo)
9631008 image = null
9641009 }
0 commit comments