Browse Source

fix: upload 支持多张图片预览

lilinsen 5 years ago
parent
commit
eb9f554cca
6 changed files with 237 additions and 258 deletions
  1. 1 1
      package.json
  2. 4 46
      scripts/mdToVue.js
  3. 12 12
      src/packages/uploader/demo.vue
  4. 11 11
      src/packages/uploader/doc.md
  5. 185 180
      src/packages/uploader/uploader.vue
  6. 24 8
      src/utils/uploader.js

+ 1 - 1
package.json

@@ -25,7 +25,7 @@
         "build:disp": "cross-env NODE_ENV=production PROD_TYPE=disp webpack --hide-modules --progress --config build/webpack.prod.disperse.conf.js",
         "build": "npm run build:prod && npm run build:prodmin && npm run build:disp",
         "clear": "node scripts/clearCache.js",
-        "eslint": "eslint src/packages/**/*.{js,vue}",
+        "eslint": "eslint --format table --fix  --ext  src/packages/**/*.{js,vue}",
         "add": "node scripts/createCptTpl.js",
         "test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text  mocha-webpack --webpack-config build/webpack.test.conf.js --require test/setup.js src/packages/*/__test__/**.spec.js",
         "coveralls": "cat ./coverage/lcov.info | coveralls",

+ 4 - 46
scripts/mdToVue.js

@@ -69,25 +69,11 @@ class mdVue{
         });
         let log = console.dir.bind(console);
         let watchAction = function({event, eventPath}){      
-            // 这里进行文件更改后的操作
-            // fileReadStar(eventPath,(res)=>{           
-            //     createdFile(param.output + res.mdName + '.vue', res.html, param.needCode)
-            // })
-            console.log(path.join(__dirname,JSON.stringify(eventPath)))
+            // 这里进行文件更改后的操作                      
             if(/\.md$/.test(eventPath)){
                 _that.vueDesWrite(eventPath)
-            }            
-            // "d:\workplace\nutui\docs\international.md"
-            // _that.read(eventPath).then(res=>{
-            //     _that.headHandle();
-            //     _that.markHandle();
-            //     let html = _that.marked(res);                                
-            //     _that.write({
-            //         outsrc:_that.options.output,
-            //         name:fileName + '.vue',
-            //         html:html
-            //     });
-            // }) 
+            }           
+           
         }
         watcher.on('change', path => watchAction({event: 'change', eventPath: path}))
         .on('unlink', path => watchAction({event: 'remove', eventPath: path}));
@@ -103,35 +89,7 @@ class mdVue{
             nodeFilelist.read([_that.options.entry],{"ext":'md'}, res => {                  
                 res.map((item,index) =>{   
                     _that.vueDesWrite(item.path)             
-                    // let fileSplits = item.path.split(path.sep);
-                    // let fileName = fileSplits.pop();
-                    // if(_that.isDoc(fileName)){
-                    //         fileName = fileSplits.pop();
-                    // }else{
-                    //     fileName = fileName.replace(/\.md/,'');
-                    // }
-                    // if(_that.needHandleFiles[fileName]){                   
-                    //     // _that.read(item.path).then(res=>{
-                    //     //     _that.headHandle();
-                    //     //     _that.markHandle();
-                    //     //     let html = _that.marked(res);                                
-                    //     //     _that.write({
-                    //     //         outsrc:_that.options.output,
-                    //     //         name:fileName + '.vue',
-                    //     //         html:html
-                    //     //     });
-                    //     // })
-                    // }
-                    // _that.read(item.path).then(res=>{
-                    //     _that.headHandle();
-                    //     _that.markHandle();
-                    //     let html = _that.marked(res);                                
-                    //     _that.write({
-                    //         outsrc:_that.options.output,
-                    //         name:fileName + '.vue',
-                    //         html:html
-                    //     });
-                    // })               
+                      
                 });
             });
         })

+ 12 - 12
src/packages/uploader/demo.vue

@@ -84,8 +84,7 @@
             :headers="headers"
             :attach="formData"
             @success="demoSuccess"
-            @fail="demoFail"
-            @preview="preview"
+            @fail="demoFail"           
             @showMsg="showMsg1"
           >
             <nut-button small>上传</nut-button>
@@ -96,6 +95,14 @@
     </div>
 
     <p>预览上传图片</p>
+    <transition name="fade">
+      <div v-if="previewImg">
+        <div class="img-outbox" v-for="(item,index) in previewImg" :key="index">
+          <img class="img-box" v-if="item" :src="item" alt>
+        </div>
+      </div>
+      
+    </transition>
     <div>
       <nut-cell>
         <span slot="title">
@@ -108,6 +115,7 @@
             @fail="demoFail"
             @preview="preview"
             @showMsg="showMsg1"
+            :multiple="true"
           >
             <nut-button small>上传</nut-button>
           </nut-uploader>
@@ -149,11 +157,7 @@
         </span>
         <div slot="desc"></div>
       </nut-cell>
-    <transition name="fade">
-      <div class="img-outbox">
-        <img class="img-box" v-if="previewImg" :src="previewImg" alt>
-      </div>
-    </transition>
+    
   </div>
 </template>
 
@@ -179,11 +183,7 @@ export default {
         f2:'test1'
       },
       progressNum: 0,
-      previewImg: null,
-      previewImg2: null,
-      progressNum2: null,
-      upOver: false,
-      demo3Type: ["application/zip"]
+      previewImg: null     
     };
   },
   methods: {

+ 11 - 11
src/packages/uploader/doc.md

@@ -210,19 +210,19 @@ test($ev){
 |----- | ----- | ----- | ----- 
 | name | input name的名称 | String | ""
 | url | 上传服务器的接口地址 | String | -
-| isPreview | 是否需要预览 | Boolean | false
-| clearInput | 是否需要清空input内容,设为true支持重复选择上传同一个文件 | Boolean | false
-| maxSize | 可以设定最大上传文件的大小(字节) | Number | 5242880
-| acceptType | 可以上传文件的类型 | Array | ['image/jpeg', 'image/png', 'image/gif', 'image/bmp']
+| is-preview | 是否需要预览 | Boolean | false
+| clear-input | 是否需要清空input内容,设为 true 支持重复选择上传同一个文件 | Boolean | false
+| max-size | 可以设定最大上传文件的大小(字节) | Number | 5242880
+| accept-type | 可以上传文件的类型 | Array | ['image/jpeg', 'image/png', 'image/gif', 'image/bmp']
 | attach | 附加上传的信息formData | Object | {}
 | headers | 自定义headers | Object | {}
-| xhrState | 接口响应的成功状态(status)值 | Number | 200
-| typeError | 文件类型错误提示文案 | String | "不支持上传该类型文件"
-| limitError | 文件大小超过限制提示文案 | String | "文件大小超过限制"
-| xmlError | 浏览器不支持本组件时的提示文案 | String | "对不起,您的浏览器不支持本组件!"
-| withCredentials | 支持发送 cookie 凭证信息 | Boolean | fasle
-| beforeUpload | 上传前的函数需要返回一个对象  | Function | {event:$event} $event为点击事件必传
-| selfData | 自定义增加上传的数据 | Object | {}
+| xhr-state | 接口响应的成功状态(status)值 | Number | 200
+| type-error | 文件类型错误提示文案 | String | "不支持上传该类型文件"
+| limit-error | 文件大小超过限制提示文案 | String | "文件大小超过限制"
+| xml-error | 浏览器不支持本组件时的提示文案 | String | "对不起,您的浏览器不支持本组件!"
+| with-credentials | 支持发送 cookie 凭证信息 | Boolean | fasle
+| before-upload | 上传前的函数需要返回一个对象  | Function | {event:$event} $event为点击事件必传
+| self-data | 自定义增加上传的数据 | Object | {}
 
 ## Event
 

+ 185 - 180
src/packages/uploader/uploader.vue

@@ -1,193 +1,198 @@
 <template>
-  <div class="nut-uploader">
-    <slot></slot>
-    <input type="file" :name="name" @change="upload($event)" class="uploader" :multiple="multiple">
-  </div>
+    <div class="nut-uploader">
+        <slot></slot>
+        <input
+            type="file"
+            :name="name"
+            @change="upload($event)"
+            class="uploader"
+            :multiple="multiple"
+			:disabled="disabled"
+			:accept="acceptType"
+        />
+    </div>
 </template>
 <script>
 import Uploader from "../../utils/uploader.js";
 import locale from "../../mixins/locale";
 export default {
-  name: "nut-uploader",
-  mixins: [locale],
-  props: {
-    name: {
-      type: String,
-      default: ""
-    },
-    url: {
-      type: String,
-      default: ""
-    },
-    multiple: {
-      type: Boolean,
-      default: false
-    },
-    isPreview: {
-      type: Boolean,
-      default: false
-    },
-    maxSize: {
-      type: Number,
-      default: 5242880
-    },
-    acceptType: {
-      type: Array,
-      default() {
-        return ["image/jpeg", "image/png", "image/gif", "image/bmp"];
-      }
-    },
-    selfData:{
-      type:Object,
-      default(){
-        return {}
-      }
-    },
-    attach: {
-      type: Object,
-      default() {
-        return {};
-      }
+    name: "nut-uploader",
+    mixins: [locale],
+    props: {
+        name: {
+            type: String,
+            default: "file"
+        },
+        url: {
+            type: String,
+            default: ""
+        },
+        multiple: {
+            type: Boolean,
+            default: false
+		},
+		disabled: {
+			type: Boolean,
+            default: false
+		},
+        isPreview: {
+            type: Boolean,
+            default: false
+        },
+        maxSize: {
+            type: Number,
+            default: 5242880
+        },
+        acceptType: {
+            type: Array,
+            default() {
+                return ["image/jpeg", "image/png", "image/gif", "image/bmp"];
+            }
+        },
+        selfData: {
+            type: Object,
+            default() {
+                return {};
+            }
+        },
+        attach: {
+            type: Object,
+            default() {
+                return {};
+            }
+        },
+        headers: {
+            type: Object,
+            default() {
+                return {};
+            }
+        },
+        beforeUpload: {
+            type: Function
+        },
+        xhrState: {
+            type: Number,
+            default: 200
+        },
+        clearInput: {
+            type: Boolean,
+            default: false
+        },
+        xmlError: {
+            type: String,
+            default: ""
+        },
+        typeError: {
+            type: String,
+            default: "不支持上传该类型文件"
+        },
+        limitError: {
+            type: String,
+            default: "对不起,您的浏览器不支持本组件"
+        },
+        withCredentials: {
+            type: Boolean,
+            default: false
+        }
     },
-    headers:{
-      type: Object,
-      default() {
+    data() {
         return {};
-      }
-    },
-    changeEvtCallback: {
-      type: Function
-	},
-	beforeUpload:{
-		type: Function
-	},
-    xhrState: {
-      type: Number,
-      default: 200
-    },
-    clearInput: {
-      type: Boolean,
-      default: false
-    },
-    xmlError: {
-      type: String,
-      default: ''
-    },
-    typeError: {
-      type: String,
-      default: ''
-    },
-    limitError: {
-      type: String,
-      default: ''
-    },
-    withCredentials: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {};
-  },
-  methods: {
-    createUploaderOpts() {
-      const _this = this;
-      return {
-        $el: {},
-        url: this.url, //图片上传地址
-        formData: null,
-        headers: {}, //自定义headers
-        isPreview: this.isPreview, //是否开启本地预览
-        previewData: null,
-        maxSize: this.maxSize, //允许上传的文件最大字节
-        acceptType: this.acceptType, //允许上传的文件类型
-        xhrState: this.xhrState,
-        clearInput: this.clearInput,
-        withCredentials: this.withCredentials,//支持发送 cookie 凭证信息
-        xmlError: this.xmlError || this.nutTranslate('lang.uploader.xmlError'),
-        typeError: this.typeError || this.nutTranslate('lang.uploader.typeError'),
-        limitError: this.limitError || this.nutTranslate('lang.uploader.limitError'),
-        onStart() {
-          _this.$emit("start");
-        },
-        onProgress(file, loaded, total) {
-          _this.$emit("progress", file, loaded, total);
-        },
-        onPreview(previewFile) {
-          _this.$emit("preview", previewFile);
-        },
-        onSuccess(file, responseTxt) {
-          _this.$emit("success", file, responseTxt);
-        },
-        onFailure(file, responseTxt) {
-          _this.$emit("failure", file, responseTxt);
-        }
-      };
     },
-    uploadData($event,selfData={}){
-      const tar = $event.target;
-      if (!this.url) {
-        this.$emit("showMsg", "请先配置上传url");
-        this.$emit("afterChange", tar, $event);
-        return;
-      }
-      const formData = new FormData();
-      const opt = this.createUploaderOpts();
-      opt.$el = tar;
-      if (this.isPreview) {
-        opt.previewData = tar.files[0];
-      }
-      if (this.multiple) {
-        for (let i = 0; i < tar.files.length; i++) {
-          if (tar.files[i]) {
-            if (this.acceptType.indexOf(tar.files[i].type) == -1) {
-              this.$emit("showMsg", opt.typeError);
-              return;
+    methods: {
+        createUploaderOpts() {
+            const _this = this;
+            return {
+                $el: {},
+                url: this.url, //图片上传地址
+                formData: null,
+                headers: {}, //自定义headers
+                isPreview: this.isPreview, //是否开启本地预览
+                previewData: null,
+                maxSize: this.maxSize, //允许上传的文件最大字节
+                acceptType: this.acceptType, //允许上传的文件类型
+                xhrState: this.xhrState,
+                clearInput: this.clearInput,
+                withCredentials: this.withCredentials, //支持发送 cookie 凭证信息
+                xmlError:
+                    this.xmlError ||
+                    this.nutTranslate("lang.uploader.xmlError"),
+                typeError:
+                    this.typeError ||
+                    this.nutTranslate("lang.uploader.typeError"),
+                limitError:
+                    this.limitError ||
+                    this.nutTranslate("lang.uploader.limitError"),
+                onStart() {
+                    _this.$emit("start");
+                },
+                onProgress(file, loaded, total) {
+                    _this.$emit("progress", file, loaded, total);
+                },
+                onPreview(previewFile) {
+					debugger
+                    _this.$emit("preview", previewFile);
+                },
+                onSuccess(file, responseTxt) {
+                    _this.$emit("success", file, responseTxt);
+                },
+                onFailure(file, responseTxt) {
+                    _this.$emit("failure", file, responseTxt);
+                }
+            };
+        },
+        uploadData($event, selfData = {}) {
+            const tar = $event.target;
+            if (!this.url) {
+                this.$emit("showMsg", "请先配置上传url");
+                this.$emit("afterChange", tar, $event);
+                return;
+            }
+            const formData = new FormData();
+            const opt = this.createUploaderOpts();
+            opt.$el = tar;
+            if (this.isPreview) {
+				debugger
+                opt.previewData = tar.files;
+			}
+			let len = this.multiple ? tar.files.length : 1;     
+            formData.append(tar.name, tar.files[0]);
+            for (const key of Object.keys(this.attach)) {
+                formData.append(key, this.attach[key]);
+            }
+            const finialyOutData = Object.assign(this.selfData, selfData);
+            if (finialyOutData) {
+                for (const key in finialyOutData) {
+                    formData.append(key, finialyOutData[key]);
+                }
+            }
+            opt.formData = formData;
+            opt.headers = this.headers || {};
+            opt.showMsgFn = (msg) => {
+                this.$emit("showMsg", msg);
+            };
+            new Uploader(opt);
+            this.$emit("afterChange", tar, $event);
+        },
+        async upload($event) {
+            if (typeof this.beforeUpload === "function") {
+                const promise = new Promise((reslove, reject) => {
+                    reslove(this.beforeUpload($event));
+                });
+                const resData = await promise;
+                if (
+                    typeof resData === "object" &&
+                    typeof resData.event === "object"
+                ) {
+                    this.uploadData(resData.event, resData.data);
+                } else {
+                    console.warn(
+                        "resData: 必须包含 event字段且为input $event 的事件对象"
+                    );
+                }
+            } else {
+                this.uploadData($event);
             }
-          }
-        }
-      } else {
-        if (tar.files[0]) {
-          if (this.acceptType.indexOf(tar.files[0].type) == -1) {
-            this.$emit("showMsg", opt.typeError);
-            return;
-          }
-        }
-      }
-      formData.append(tar.name, tar.files[0]);
-      for (let key of Object.keys(this.attach)) {
-        formData.append(key, this.attach[key]);
-      }
-      let finialyOutData = Object.assign(this.selfData,selfData);
-      if(finialyOutData){
-        for(let key in finialyOutData){
-          formData.append(key, finialyOutData[key]);
-        }
-      }
-      opt.formData = formData;
-      opt.headers = this.headers || {};
-      opt.showMsgFn = msg => {
-        this.$emit("showMsg", msg);
-      };
-      new Uploader(opt);
-      this.$emit("afterChange", tar, $event);
-    },
-    async upload($event) {	
-      if(typeof this.beforeUpload === 'function'){	  		
-        let promise =new Promise((reslove,reject)=>{
-          reslove(this.beforeUpload($event))
-        })
-        let resData = await promise;        
-        if(typeof resData === 'object' && typeof  resData.event === 'object'){
-          this.uploadData(resData.event,resData.data)			
-        }else{
-          console.warn('resData: 必须包含 event字段且为input $event 的事件对象')
         }
-        
-      }else{
-		    this.uploadData($event)
-      }      
     }
-  }
 };
-</script>
+</script>

+ 24 - 8
src/utils/uploader.js

@@ -65,14 +65,30 @@ class IdaUploader {
        return true;
    }
    preview () {  
-       const file = this.options.previewData;    
-       if (!this.check(file)) return;
-       const reader = new FileReader();       
-       reader.onload = (e) => {
-        this.uploader();
-           this.triggerFunc.call(this.options, this.options.onPreview)(e.target.result);           
-       }
-       reader.readAsDataURL(file);       
+       const file = Array.from(this.options.previewData);   
+        if (!this.check(file)) return;
+        let promArray = []
+        file.map(item=>{             
+            let temp  = new Promise((resolve,reject)=>{
+                const reader = new FileReader(); 
+                reader.readAsDataURL(item);
+                reader.onload = (e) => {                
+                    this.uploader();
+                    resolve(e)
+                }  
+            })
+            promArray.push(temp)   
+        });
+        Promise.all(promArray).then(res=>{
+            console.log(res)
+            let out = [];
+            if(res){
+                res.map(item=>{
+                    out.push(item.target.result) 
+                })
+            }
+            this.triggerFunc.call(this.options, this.options.onPreview)(out); 
+        }) 
    }
    uploader () {
        const xhr = new XMLHttpRequest();