You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							668 lines
						
					
					
						
							18 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							668 lines
						
					
					
						
							18 KiB
						
					
					
				
								<!-- 文件上传,基于 upload-file 和 upload-image 实现 -->
							 | 
						|
								<template>
							 | 
						|
								  <view class="uni-file-picker">
							 | 
						|
								    <view v-if="title" class="uni-file-picker__header">
							 | 
						|
								      <text class="file-title">{{ title }}</text>
							 | 
						|
								      <text class="file-count">{{ filesList.length }}/{{ limitLength }}</text>
							 | 
						|
								    </view>
							 | 
						|
								    <view v-if="subtitle" class="file-subtitle">
							 | 
						|
								      <view>{{ subtitle }}</view>
							 | 
						|
								    </view>
							 | 
						|
								    <upload-image
							 | 
						|
								      v-if="fileMediatype === 'image' && showType === 'grid'"
							 | 
						|
								      :readonly="readonly"
							 | 
						|
								      :image-styles="imageStyles"
							 | 
						|
								      :files-list="url"
							 | 
						|
								      :limit="limitLength"
							 | 
						|
								      :disablePreview="disablePreview"
							 | 
						|
								      :delIcon="delIcon"
							 | 
						|
								      @uploadFiles="uploadFiles"
							 | 
						|
								      @choose="choose"
							 | 
						|
								      @delFile="delFile"
							 | 
						|
								    >
							 | 
						|
								      <slot>
							 | 
						|
								        <view class="is-add">
							 | 
						|
								          <image :src="imgsrc" class="add-icon"></image>
							 | 
						|
								        </view>
							 | 
						|
								      </slot>
							 | 
						|
								    </upload-image>
							 | 
						|
								    <upload-file
							 | 
						|
								      v-if="fileMediatype !== 'image' || showType !== 'grid'"
							 | 
						|
								      :readonly="readonly"
							 | 
						|
								      :list-styles="listStyles"
							 | 
						|
								      :files-list="filesList"
							 | 
						|
								      :showType="showType"
							 | 
						|
								      :delIcon="delIcon"
							 | 
						|
								      @uploadFiles="uploadFiles"
							 | 
						|
								      @choose="choose"
							 | 
						|
								      @delFile="delFile"
							 | 
						|
								    >
							 | 
						|
								      <slot><button type="primary" size="mini">选择文件</button></slot>
							 | 
						|
								    </upload-file>
							 | 
						|
								  </view>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script>
							 | 
						|
								  import { chooseAndUploadFile, uploadCloudFiles } from './choose-and-upload-file.js';
							 | 
						|
								  import { get_extname, get_files_and_is_max, get_file_data } from './utils.js';
							 | 
						|
								  import uploadImage from './upload-image.vue';
							 | 
						|
								  import uploadFile from './upload-file.vue';
							 | 
						|
								  import sheep from '@/sheep';
							 | 
						|
								  let fileInput = null;
							 | 
						|
								  /**
							 | 
						|
								   * FilePicker 文件选择上传
							 | 
						|
								   * @description 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
							 | 
						|
								   * @tutorial https://ext.dcloud.net.cn/plugin?id=4079
							 | 
						|
								   * @property {Object|Array}	value	组件数据,通常用来回显 ,类型由return-type属性决定
							 | 
						|
								   * @property {String|Array}	url	  url数据
							 | 
						|
								   * @property {Boolean}	disabled = [true|false]	组件禁用
							 | 
						|
								   * 	@value true 	禁用
							 | 
						|
								   * 	@value false 	取消禁用
							 | 
						|
								   * @property {Boolean}	readonly = [true|false]	组件只读,不可选择,不显示进度,不显示删除按钮
							 | 
						|
								   * 	@value true 	只读
							 | 
						|
								   * 	@value false 	取消只读
							 | 
						|
								   * @property {Boolean}	disable-preview = [true|false]	禁用图片预览,仅 mode:grid 时生效
							 | 
						|
								   * 	@value true 	禁用图片预览
							 | 
						|
								   * 	@value false 	取消禁用图片预览
							 | 
						|
								   * @property {Boolean}	del-icon = [true|false]	是否显示删除按钮
							 | 
						|
								   * 	@value true 	显示删除按钮
							 | 
						|
								   * 	@value false 	不显示删除按钮
							 | 
						|
								   * @property {Boolean}	auto-upload = [true|false]	是否自动上传,值为true则只触发@select,可自行上传
							 | 
						|
								   * 	@value true 	自动上传
							 | 
						|
								   * 	@value false 	取消自动上传
							 | 
						|
								   * @property {Number|String}	limit	最大选择个数 ,h5 会自动忽略多选的部分
							 | 
						|
								   * @property {String}	title	组件标题,右侧显示上传计数
							 | 
						|
								   * @property {String}	mode = [list|grid]	选择文件后的文件列表样式
							 | 
						|
								   * 	@value list 	列表显示
							 | 
						|
								   * 	@value grid 	宫格显示
							 | 
						|
								   * @property {String}	file-mediatype = [image|video|all]	选择文件类型
							 | 
						|
								   * 	@value image	只选择图片
							 | 
						|
								   * 	@value video	只选择视频
							 | 
						|
								   * 	@value all		选择所有文件
							 | 
						|
								   * @property {Array}	file-extname	选择文件后缀,根据 file-mediatype 属性而不同
							 | 
						|
								   * @property {Object}	list-style	mode:list 时的样式
							 | 
						|
								   * @property {Object}	image-styles	选择文件后缀,根据 file-mediatype 属性而不同
							 | 
						|
								   * @event {Function} select 	选择文件后触发
							 | 
						|
								   * @event {Function} progress 文件上传时触发
							 | 
						|
								   * @event {Function} success 	上传成功触发
							 | 
						|
								   * @event {Function} fail 		上传失败触发
							 | 
						|
								   * @event {Function} delete 	文件从列表移除时触发
							 | 
						|
								   */
							 | 
						|
								  export default {
							 | 
						|
								    name: 'sUploader',
							 | 
						|
								    components: {
							 | 
						|
								      uploadImage,
							 | 
						|
								      uploadFile,
							 | 
						|
								    },
							 | 
						|
								    options: {
							 | 
						|
								      virtualHost: true,
							 | 
						|
								    },
							 | 
						|
								    emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'update:url'],
							 | 
						|
								    props: {
							 | 
						|
								      modelValue: {
							 | 
						|
								        type: [Array, Object],
							 | 
						|
								        default() {
							 | 
						|
								          return [];
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      url: {
							 | 
						|
								        type: [Array, String],
							 | 
						|
								        default() {
							 | 
						|
								          return [];
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      disabled: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: false,
							 | 
						|
								      },
							 | 
						|
								      disablePreview: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: false,
							 | 
						|
								      },
							 | 
						|
								      delIcon: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: true,
							 | 
						|
								      },
							 | 
						|
								      // 自动上传
							 | 
						|
								      autoUpload: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: true,
							 | 
						|
								      },
							 | 
						|
								      // 最大选择个数 ,h5只能限制单选或是多选
							 | 
						|
								      limit: {
							 | 
						|
								        type: [Number, String],
							 | 
						|
								        default: 9,
							 | 
						|
								      },
							 | 
						|
								      // 列表样式 grid | list | list-card
							 | 
						|
								      mode: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: 'grid',
							 | 
						|
								      },
							 | 
						|
								      // 选择文件类型  image/video/all
							 | 
						|
								      fileMediatype: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: 'image',
							 | 
						|
								      },
							 | 
						|
								      // 文件类型筛选
							 | 
						|
								      fileExtname: {
							 | 
						|
								        type: [Array, String],
							 | 
						|
								        default() {
							 | 
						|
								          return [];
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      title: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      listStyles: {
							 | 
						|
								        type: Object,
							 | 
						|
								        default() {
							 | 
						|
								          return {
							 | 
						|
								            // 是否显示边框
							 | 
						|
								            border: true,
							 | 
						|
								            // 是否显示分隔线
							 | 
						|
								            dividline: true,
							 | 
						|
								            // 线条样式
							 | 
						|
								            borderStyle: {},
							 | 
						|
								          };
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      imageStyles: {
							 | 
						|
								        type: Object,
							 | 
						|
								        default() {
							 | 
						|
								          return {
							 | 
						|
								            width: 'auto',
							 | 
						|
								            height: 'auto',
							 | 
						|
								          };
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      readonly: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: false,
							 | 
						|
								      },
							 | 
						|
								      sizeType: {
							 | 
						|
								        type: Array,
							 | 
						|
								        default() {
							 | 
						|
								          return ['original', 'compressed'];
							 | 
						|
								        },
							 | 
						|
								      },
							 | 
						|
								      driver: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: 'local', // local=本地 | oss | unicloud
							 | 
						|
								      },
							 | 
						|
								      subtitle: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								    data() {
							 | 
						|
								      return {
							 | 
						|
								        files: [],
							 | 
						|
								        localValue: [],
							 | 
						|
								        imgsrc: sheep.$url.static('/static/img/shop/upload-camera.png'),
							 | 
						|
								      };
							 | 
						|
								    },
							 | 
						|
								    watch: {
							 | 
						|
								      modelValue: {
							 | 
						|
								        handler(newVal, oldVal) {
							 | 
						|
								          this.setValue(newVal, oldVal);
							 | 
						|
								        },
							 | 
						|
								        immediate: true,
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								    computed: {
							 | 
						|
								      returnType() {
							 | 
						|
								        if (this.limit > 1) {
							 | 
						|
								          return 'array';
							 | 
						|
								        }
							 | 
						|
								        return 'object';
							 | 
						|
								      },
							 | 
						|
								      filesList() {
							 | 
						|
								        let files = [];
							 | 
						|
								        this.files.forEach((v) => {
							 | 
						|
								          files.push(v);
							 | 
						|
								        });
							 | 
						|
								        return files;
							 | 
						|
								      },
							 | 
						|
								      showType() {
							 | 
						|
								        if (this.fileMediatype === 'image') {
							 | 
						|
								          return this.mode;
							 | 
						|
								        }
							 | 
						|
								        return 'list';
							 | 
						|
								      },
							 | 
						|
								      limitLength() {
							 | 
						|
								        if (this.returnType === 'object') {
							 | 
						|
								          return 1;
							 | 
						|
								        }
							 | 
						|
								        if (!this.limit) {
							 | 
						|
								          return 1;
							 | 
						|
								        }
							 | 
						|
								        if (this.limit >= 9) {
							 | 
						|
								          return 9;
							 | 
						|
								        }
							 | 
						|
								        return this.limit;
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								    created() {
							 | 
						|
								      if (this.driver === 'local') {
							 | 
						|
								        uniCloud.chooseAndUploadFile = chooseAndUploadFile;
							 | 
						|
								      }
							 | 
						|
								      this.form = this.getForm('uniForms');
							 | 
						|
								      this.formItem = this.getForm('uniFormsItem');
							 | 
						|
								      if (this.form && this.formItem) {
							 | 
						|
								        if (this.formItem.name) {
							 | 
						|
								          this.rename = this.formItem.name;
							 | 
						|
								          this.form.inputChildrens.push(this);
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								    methods: {
							 | 
						|
								      /**
							 | 
						|
								       * 公开用户使用,清空文件
							 | 
						|
								       * @param {Object} index
							 | 
						|
								       */
							 | 
						|
								      clearFiles(index) {
							 | 
						|
								        if (index !== 0 && !index) {
							 | 
						|
								          this.files = [];
							 | 
						|
								          this.$nextTick(() => {
							 | 
						|
								            this.setEmit();
							 | 
						|
								          });
							 | 
						|
								        } else {
							 | 
						|
								          this.files.splice(index, 1);
							 | 
						|
								        }
							 | 
						|
								        this.$nextTick(() => {
							 | 
						|
								          this.setEmit();
							 | 
						|
								        });
							 | 
						|
								      },
							 | 
						|
								      /**
							 | 
						|
								       * 公开用户使用,继续上传
							 | 
						|
								       */
							 | 
						|
								      upload() {
							 | 
						|
								        let files = [];
							 | 
						|
								        this.files.forEach((v, index) => {
							 | 
						|
								          if (v.status === 'ready' || v.status === 'error') {
							 | 
						|
								            files.push(Object.assign({}, v));
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								        return this.uploadFiles(files);
							 | 
						|
								      },
							 | 
						|
								      async setValue(newVal, oldVal) {
							 | 
						|
								        const newData = async (v) => {
							 | 
						|
								          const reg = /cloud:\/\/([\w.]+\/?)\S*/;
							 | 
						|
								          let url = '';
							 | 
						|
								          if (v.fileID) {
							 | 
						|
								            url = v.fileID;
							 | 
						|
								          } else {
							 | 
						|
								            url = v.url;
							 | 
						|
								          }
							 | 
						|
								          if (reg.test(url)) {
							 | 
						|
								            v.fileID = url;
							 | 
						|
								            v.url = await this.getTempFileURL(url);
							 | 
						|
								          }
							 | 
						|
								          if (v.url) v.path = v.url;
							 | 
						|
								          return v;
							 | 
						|
								        };
							 | 
						|
								        if (this.returnType === 'object') {
							 | 
						|
								          if (newVal) {
							 | 
						|
								            await newData(newVal);
							 | 
						|
								          } else {
							 | 
						|
								            newVal = {};
							 | 
						|
								          }
							 | 
						|
								        } else {
							 | 
						|
								          if (!newVal) newVal = [];
							 | 
						|
								          for (let i = 0; i < newVal.length; i++) {
							 | 
						|
								            let v = newVal[i];
							 | 
						|
								            await newData(v);
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								        this.localValue = newVal;
							 | 
						|
								        if (this.form && this.formItem && !this.is_reset) {
							 | 
						|
								          this.is_reset = false;
							 | 
						|
								          this.formItem.setValue(this.localValue);
							 | 
						|
								        }
							 | 
						|
								        let filesData = Object.keys(newVal).length > 0 ? newVal : [];
							 | 
						|
								        this.files = [].concat(filesData);
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 选择文件
							 | 
						|
								       */
							 | 
						|
								      choose() {
							 | 
						|
								        if (this.disabled) return;
							 | 
						|
								        if (
							 | 
						|
								          this.files.length >= Number(this.limitLength) &&
							 | 
						|
								          this.showType !== 'grid' &&
							 | 
						|
								          this.returnType === 'array'
							 | 
						|
								        ) {
							 | 
						|
								          uni.showToast({
							 | 
						|
								            title: `您最多选择 ${this.limitLength} 个文件`,
							 | 
						|
								            icon: 'none',
							 | 
						|
								          });
							 | 
						|
								          return;
							 | 
						|
								        }
							 | 
						|
								        this.chooseFiles();
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 选择文件并上传
							 | 
						|
								       */
							 | 
						|
								      async chooseFiles() {
							 | 
						|
								        const _extname = get_extname(this.fileExtname);
							 | 
						|
								        // 获取后缀
							 | 
						|
								        await chooseAndUploadFile({
							 | 
						|
								          type: this.fileMediatype,
							 | 
						|
								          compressed: false,
							 | 
						|
								          sizeType: this.sizeType,
							 | 
						|
								          // TODO 如果为空,video 有问题
							 | 
						|
								          extension: _extname.length > 0 ? _extname : undefined,
							 | 
						|
								          count: this.limitLength - this.files.length, //默认9
							 | 
						|
								          onChooseFile: this.chooseFileCallback,
							 | 
						|
								          onUploadProgress: (progressEvent) => {
							 | 
						|
								            this.setProgress(progressEvent, progressEvent.index);
							 | 
						|
								          },
							 | 
						|
								        })
							 | 
						|
								          .then((result) => {
							 | 
						|
								            this.setSuccessAndError(result);
							 | 
						|
								          })
							 | 
						|
								          .catch((err) => {
							 | 
						|
								            console.log('选择失败', err);
							 | 
						|
								          });
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 选择文件回调
							 | 
						|
								       * @param {Object} res
							 | 
						|
								       */
							 | 
						|
								      async chooseFileCallback(res) {
							 | 
						|
								        const _extname = get_extname(this.fileExtname);
							 | 
						|
								        const is_one =
							 | 
						|
								          (Number(this.limitLength) === 1 && this.disablePreview && !this.disabled) ||
							 | 
						|
								          this.returnType === 'object';
							 | 
						|
								        // 如果这有一个文件 ,需要清空本地缓存数据
							 | 
						|
								        if (is_one) {
							 | 
						|
								          this.files = [];
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        let { filePaths, files } = get_files_and_is_max(res, _extname);
							 | 
						|
								        if (!(_extname && _extname.length > 0)) {
							 | 
						|
								          filePaths = res.tempFilePaths;
							 | 
						|
								          files = res.tempFiles;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        let currentData = [];
							 | 
						|
								        for (let i = 0; i < files.length; i++) {
							 | 
						|
								          if (this.limitLength - this.files.length <= 0) break;
							 | 
						|
								          files[i].uuid = Date.now();
							 | 
						|
								          let filedata = await get_file_data(files[i], this.fileMediatype);
							 | 
						|
								          filedata.progress = 0;
							 | 
						|
								          filedata.status = 'ready';
							 | 
						|
								          this.files.push(filedata);
							 | 
						|
								          currentData.push({
							 | 
						|
								            ...filedata,
							 | 
						|
								            file: files[i],
							 | 
						|
								          });
							 | 
						|
								        }
							 | 
						|
								        this.$emit('select', {
							 | 
						|
								          tempFiles: currentData,
							 | 
						|
								          tempFilePaths: filePaths,
							 | 
						|
								        });
							 | 
						|
								        res.tempFiles = files;
							 | 
						|
								        // 停止自动上传
							 | 
						|
								        if (!this.autoUpload) {
							 | 
						|
								          res.tempFiles = [];
							 | 
						|
								        }
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 批传
							 | 
						|
								       * @param {Object} e
							 | 
						|
								       */
							 | 
						|
								      uploadFiles(files) {
							 | 
						|
								        files = [].concat(files);
							 | 
						|
								        return uploadCloudFiles
							 | 
						|
								          .call(this, files, 5, (res) => {
							 | 
						|
								            this.setProgress(res, res.index, true);
							 | 
						|
								          })
							 | 
						|
								          .then((result) => {
							 | 
						|
								            this.setSuccessAndError(result);
							 | 
						|
								            return result;
							 | 
						|
								          })
							 | 
						|
								          .catch((err) => {
							 | 
						|
								            console.log(err);
							 | 
						|
								          });
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 成功或失败
							 | 
						|
								       */
							 | 
						|
								      async setSuccessAndError(res, fn) {
							 | 
						|
								        let successData = [];
							 | 
						|
								        let errorData = [];
							 | 
						|
								        let tempFilePath = [];
							 | 
						|
								        let errorTempFilePath = [];
							 | 
						|
								        for (let i = 0; i < res.length; i++) {
							 | 
						|
								          const item = res[i];
							 | 
						|
								          const index = item.uuid ? this.files.findIndex((p) => p.uuid === item.uuid) : item.index;
							 | 
						|
								
							 | 
						|
								          if (index === -1 || !this.files) break;
							 | 
						|
								          if (item.errMsg === 'request:fail') {
							 | 
						|
								            this.files[index].url = item.url;
							 | 
						|
								            this.files[index].status = 'error';
							 | 
						|
								            this.files[index].errMsg = item.errMsg;
							 | 
						|
								            // this.files[index].progress = -1
							 | 
						|
								            errorData.push(this.files[index]);
							 | 
						|
								            errorTempFilePath.push(this.files[index].url);
							 | 
						|
								          } else {
							 | 
						|
								            this.files[index].errMsg = '';
							 | 
						|
								            this.files[index].fileID = item.url;
							 | 
						|
								            const reg = /cloud:\/\/([\w.]+\/?)\S*/;
							 | 
						|
								            if (reg.test(item.url)) {
							 | 
						|
								              this.files[index].url = await this.getTempFileURL(item.url);
							 | 
						|
								            } else {
							 | 
						|
								              this.files[index].url = item.url;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            this.files[index].status = 'success';
							 | 
						|
								            this.files[index].progress += 1;
							 | 
						|
								            successData.push(this.files[index]);
							 | 
						|
								            tempFilePath.push(this.files[index].fileID);
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if (successData.length > 0) {
							 | 
						|
								          this.setEmit();
							 | 
						|
								          // 状态改变返回
							 | 
						|
								          this.$emit('success', {
							 | 
						|
								            tempFiles: this.backObject(successData),
							 | 
						|
								            tempFilePaths: tempFilePath,
							 | 
						|
								          });
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if (errorData.length > 0) {
							 | 
						|
								          this.$emit('fail', {
							 | 
						|
								            tempFiles: this.backObject(errorData),
							 | 
						|
								            tempFilePaths: errorTempFilePath,
							 | 
						|
								          });
							 | 
						|
								        }
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 获取进度
							 | 
						|
								       * @param {Object} progressEvent
							 | 
						|
								       * @param {Object} index
							 | 
						|
								       * @param {Object} type
							 | 
						|
								       */
							 | 
						|
								      setProgress(progressEvent, index, type) {
							 | 
						|
								        const fileLenth = this.files.length;
							 | 
						|
								        const percentNum = (index / fileLenth) * 100;
							 | 
						|
								        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
							 | 
						|
								        let idx = index;
							 | 
						|
								        if (!type) {
							 | 
						|
								          idx = this.files.findIndex((p) => p.uuid === progressEvent.tempFile.uuid);
							 | 
						|
								        }
							 | 
						|
								        if (idx === -1 || !this.files[idx]) return;
							 | 
						|
								        // fix by mehaotian 100 就会消失,-1 是为了让进度条消失
							 | 
						|
								        this.files[idx].progress = percentCompleted - 1;
							 | 
						|
								        // 上传中
							 | 
						|
								        this.$emit('progress', {
							 | 
						|
								          index: idx,
							 | 
						|
								          progress: parseInt(percentCompleted),
							 | 
						|
								          tempFile: this.files[idx],
							 | 
						|
								        });
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 删除文件
							 | 
						|
								       * @param {Object} index
							 | 
						|
								       */
							 | 
						|
								      delFile(index) {
							 | 
						|
								        this.$emit('delete', {
							 | 
						|
								          tempFile: this.files[index],
							 | 
						|
								          tempFilePath: this.files[index].url,
							 | 
						|
								        });
							 | 
						|
								        this.files.splice(index, 1);
							 | 
						|
								        this.$nextTick(() => {
							 | 
						|
								          this.setEmit();
							 | 
						|
								        });
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 获取文件名和后缀
							 | 
						|
								       * @param {Object} name
							 | 
						|
								       */
							 | 
						|
								      getFileExt(name) {
							 | 
						|
								        const last_len = name.lastIndexOf('.');
							 | 
						|
								        const len = name.length;
							 | 
						|
								        return {
							 | 
						|
								          name: name.substring(0, last_len),
							 | 
						|
								          ext: name.substring(last_len + 1, len),
							 | 
						|
								        };
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 处理返回事件
							 | 
						|
								       */
							 | 
						|
								      setEmit() {
							 | 
						|
								        let data = [];
							 | 
						|
								        let updateUrl = [];
							 | 
						|
								        if (this.returnType === 'object') {
							 | 
						|
								          data = this.backObject(this.files)[0];
							 | 
						|
								          this.localValue = data ? data : null;
							 | 
						|
								          updateUrl = data ? data.url : '';
							 | 
						|
								        } else {
							 | 
						|
								          data = this.backObject(this.files);
							 | 
						|
								          if (!this.localValue) {
							 | 
						|
								            this.localValue = [];
							 | 
						|
								          }
							 | 
						|
								          this.localValue = [...data];
							 | 
						|
								          if (this.localValue.length > 0) {
							 | 
						|
								            this.localValue.forEach((item) => {
							 | 
						|
								              updateUrl.push(item.url);
							 | 
						|
								            });
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								        this.$emit('update:modelValue', this.localValue);
							 | 
						|
								        this.$emit('update:url', updateUrl);
							 | 
						|
								      },
							 | 
						|
								
							 | 
						|
								      /**
							 | 
						|
								       * 处理返回参数
							 | 
						|
								       * @param {Object} files
							 | 
						|
								       */
							 | 
						|
								      backObject(files) {
							 | 
						|
								        let newFilesData = [];
							 | 
						|
								        files.forEach((v) => {
							 | 
						|
								          newFilesData.push({
							 | 
						|
								            extname: v.extname,
							 | 
						|
								            fileType: v.fileType,
							 | 
						|
								            image: v.image,
							 | 
						|
								            name: v.name,
							 | 
						|
								            path: v.path,
							 | 
						|
								            size: v.size,
							 | 
						|
								            fileID: v.fileID,
							 | 
						|
								            url: v.url,
							 | 
						|
								          });
							 | 
						|
								        });
							 | 
						|
								        return newFilesData;
							 | 
						|
								      },
							 | 
						|
								      async getTempFileURL(fileList) {
							 | 
						|
								        fileList = {
							 | 
						|
								          fileList: [].concat(fileList),
							 | 
						|
								        };
							 | 
						|
								        const urls = await uniCloud.getTempFileURL(fileList);
							 | 
						|
								        return urls.fileList[0].tempFileURL || '';
							 | 
						|
								      },
							 | 
						|
								      /**
							 | 
						|
								       * 获取父元素实例
							 | 
						|
								       */
							 | 
						|
								      getForm(name = 'uniForms') {
							 | 
						|
								        let parent = this.$parent;
							 | 
						|
								        let parentName = parent.$options.name;
							 | 
						|
								        while (parentName !== name) {
							 | 
						|
								          parent = parent.$parent;
							 | 
						|
								          if (!parent) return false;
							 | 
						|
								          parentName = parent.$options.name;
							 | 
						|
								        }
							 | 
						|
								        return parent;
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								  };
							 | 
						|
								</script>
							 | 
						|
								
							 | 
						|
								<style lang="scss" scoped>
							 | 
						|
								  .uni-file-picker {
							 | 
						|
								    /* #ifndef APP-NVUE */
							 | 
						|
								    box-sizing: border-box;
							 | 
						|
								    overflow: hidden;
							 | 
						|
								    /* width: 100%; */
							 | 
						|
								    /* #endif */
							 | 
						|
								    /* flex: 1; */
							 | 
						|
								    position: relative;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  .uni-file-picker__header {
							 | 
						|
								    padding-top: 5px;
							 | 
						|
								    padding-bottom: 10px;
							 | 
						|
								    /* #ifndef APP-NVUE */
							 | 
						|
								    display: flex;
							 | 
						|
								    /* #endif */
							 | 
						|
								    justify-content: space-between;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  .file-title {
							 | 
						|
								    font-size: 14px;
							 | 
						|
								    color: #333;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  .file-count {
							 | 
						|
								    font-size: 14px;
							 | 
						|
								    color: #999;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  .is-add {
							 | 
						|
								    /* #ifndef APP-NVUE */
							 | 
						|
								    display: flex;
							 | 
						|
								    /* #endif */
							 | 
						|
								    align-items: center;
							 | 
						|
								    justify-content: center;
							 | 
						|
								  }
							 | 
						|
								  .add-icon {
							 | 
						|
								    width: 57rpx;
							 | 
						|
								    height: 49rpx;
							 | 
						|
								  }
							 | 
						|
								  .file-subtitle {
							 | 
						|
								    position: absolute;
							 | 
						|
								    left: 50%;
							 | 
						|
								    transform: translateX(-50%);
							 | 
						|
								    bottom: 0;
							 | 
						|
								    width: 140rpx;
							 | 
						|
								    height: 36rpx;
							 | 
						|
								    z-index: 1;
							 | 
						|
								    display: flex;
							 | 
						|
								    justify-content: center;
							 | 
						|
								    color: #fff;
							 | 
						|
								    font-weight: 500;
							 | 
						|
								    background: rgba(#000, 0.3);
							 | 
						|
								    font-size: 24rpx;
							 | 
						|
								  }
							 | 
						|
								</style>
							 |