|
@@ -1,24 +1,355 @@
|
|
|
-import { defineComponent } from 'vue';
|
|
|
+import {
|
|
|
+ closeToast,
|
|
|
+ Icon,
|
|
|
+ Image,
|
|
|
+ showLoadingToast,
|
|
|
+ showToast,
|
|
|
+ Uploader
|
|
|
+} from 'vant';
|
|
|
+import { defineComponent, PropType } from 'vue';
|
|
|
import styles from './index.module.less';
|
|
|
-import { Uploader } from 'vant';
|
|
|
+import { useCustomFieldValue } from '@vant/use';
|
|
|
+import { postMessage } from '@/helpers/native-message';
|
|
|
+import umiRequest from 'umi-request';
|
|
|
+import iconUploader from '@common/images/icon-upload.png';
|
|
|
+// import iconUploadClose from '@common/images/icon-upload-close.png';
|
|
|
+import request from '@/helpers/request';
|
|
|
+import { getOssUploadUrl } from '@/state';
|
|
|
|
|
|
export default defineComponent({
|
|
|
- name: 'm-uploader',
|
|
|
+ name: 'col-upload',
|
|
|
props: {
|
|
|
+ modelValue: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ },
|
|
|
+ deletable: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true
|
|
|
+ },
|
|
|
maxCount: {
|
|
|
type: Number,
|
|
|
default: 1
|
|
|
},
|
|
|
- maxSize: {
|
|
|
+ native: {
|
|
|
+ // 是否原生上传
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ uploadSize: {
|
|
|
+ // 上传图片大小
|
|
|
type: Number,
|
|
|
- default: 2048
|
|
|
+ default: 5
|
|
|
+ },
|
|
|
+ uploadType: {
|
|
|
+ type: String as PropType<'IMAGE' | 'VIDEO'>,
|
|
|
+ default: 'IMAGE'
|
|
|
+ },
|
|
|
+ accept: {
|
|
|
+ type: String,
|
|
|
+ default: 'image/*'
|
|
|
+ },
|
|
|
+ bucket: {
|
|
|
+ type: String,
|
|
|
+ default: 'gyt'
|
|
|
+ },
|
|
|
+ path: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ uploadIcon: {
|
|
|
+ type: String,
|
|
|
+ default: iconUploader
|
|
|
+ },
|
|
|
+ size: {
|
|
|
+ type: String,
|
|
|
+ default: 'default'
|
|
|
+ },
|
|
|
+ disabled: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
}
|
|
|
},
|
|
|
- setup(props) {
|
|
|
- return () => (
|
|
|
- <>
|
|
|
- <Uploader maxCount={props.maxCount} />
|
|
|
- </>
|
|
|
+ emits: ['uploadChange', 'update:modelValue'],
|
|
|
+ methods: {
|
|
|
+ nativeUpload() {
|
|
|
+ if (this.disabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const type = this.uploadType === 'VIDEO' ? 'video' : 'img';
|
|
|
+ postMessage(
|
|
|
+ {
|
|
|
+ api: 'chooseFile',
|
|
|
+ content: { type: type, max: 1, bucket: this.bucket, path: this.path }
|
|
|
+ },
|
|
|
+ (res: any) => {
|
|
|
+ console.log(res, 'fileUrl');
|
|
|
+ // 判断是否是多选
|
|
|
+ if (this.maxCount > 1) {
|
|
|
+ this.$emit('update:modelValue', [...this.modelValue, res.fileUrl]);
|
|
|
+ this.$emit('uploadChange', [...this.modelValue, res.fileUrl]);
|
|
|
+ } else {
|
|
|
+ this.$emit('update:modelValue', [res.fileUrl]);
|
|
|
+ this.$emit('uploadChange', [res.fileUrl]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ },
|
|
|
+ beforeRead(file: any) {
|
|
|
+ console.log(file, 'beforeRead');
|
|
|
+ const isLt2M = file.size / 1024 / 1024 < this.uploadSize;
|
|
|
+ if (!isLt2M) {
|
|
|
+ showToast(`上传文件大小不能超过 ${this.uploadSize}MB`);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ beforeDelete() {
|
|
|
+ // this.dataModel.splice(detail.index, 1)
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ async afterRead(file: any) {
|
|
|
+ try {
|
|
|
+ file.status = 'uploading';
|
|
|
+ file.message = '上传中...';
|
|
|
+ await this.uploadFile(file.file);
|
|
|
+ } catch (error) {
|
|
|
+ closeToast();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onClose(e: any, item: any) {
|
|
|
+ const models = this.modelValue;
|
|
|
+ const index = models.findIndex(model => model == item);
|
|
|
+ if (index > -1) {
|
|
|
+ models.splice(index, 1);
|
|
|
+ this.$emit('update:modelValue', models);
|
|
|
+ this.$emit('uploadChange');
|
|
|
+ }
|
|
|
+
|
|
|
+ e.stopPropagation();
|
|
|
+ },
|
|
|
+ async getFile(file: any) {
|
|
|
+ try {
|
|
|
+ await this.uploadFile(file);
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async uploadFile(file: any) {
|
|
|
+ // 上传文件
|
|
|
+ try {
|
|
|
+ // 获取签名
|
|
|
+ const signUrl = '/api-school/open/getUploadSign';
|
|
|
+ const tempName = file.name || '';
|
|
|
+ const fileName =
|
|
|
+ this.path + '/' + (tempName && tempName.replace(/ /gi, '_'));
|
|
|
+ const key = new Date().getTime() + fileName;
|
|
|
+ console.log(file);
|
|
|
+
|
|
|
+ const res = await request.post(signUrl, {
|
|
|
+ data: {
|
|
|
+ filename: fileName,
|
|
|
+ bucketName: this.bucket,
|
|
|
+ postData: {
|
|
|
+ filename: fileName,
|
|
|
+ acl: 'public-read',
|
|
|
+ key: key,
|
|
|
+ unknowValueField: []
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ showLoadingToast({
|
|
|
+ message: '加载中...',
|
|
|
+ forbidClick: true,
|
|
|
+ loadingType: 'spinner',
|
|
|
+ duration: 0
|
|
|
+ });
|
|
|
+ const obj = {
|
|
|
+ policy: res.data.policy,
|
|
|
+ signature: res.data.signature,
|
|
|
+ key: key,
|
|
|
+ KSSAccessKeyId: res.data.kssAccessKeyId,
|
|
|
+ acl: 'public-read',
|
|
|
+ name: fileName
|
|
|
+ };
|
|
|
+ const formData = new FormData();
|
|
|
+ for (const key in obj) {
|
|
|
+ formData.append(key, obj[key]);
|
|
|
+ }
|
|
|
+ formData.append('file', file, fileName);
|
|
|
+ await umiRequest(getOssUploadUrl(this.bucket), {
|
|
|
+ method: 'POST',
|
|
|
+ data: formData
|
|
|
+ });
|
|
|
+ console.log(getOssUploadUrl(this.bucket) + key);
|
|
|
+ const uploadUrl = getOssUploadUrl(this.bucket) + key;
|
|
|
+ closeToast();
|
|
|
+ // 判断是否是多选
|
|
|
+ if (this.maxCount > 1) {
|
|
|
+ this.$emit('update:modelValue', [...this.modelValue, uploadUrl]);
|
|
|
+ this.$emit('uploadChange', [...this.modelValue, uploadUrl]);
|
|
|
+ } else {
|
|
|
+ this.$emit('update:modelValue', [uploadUrl]);
|
|
|
+ this.$emit('uploadChange', [uploadUrl]);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error, 'uploadFile');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ render() {
|
|
|
+ useCustomFieldValue(() => this.modelValue);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div class={styles['uploader-section']}>
|
|
|
+ {this.modelValue.length > 0 &&
|
|
|
+ this.maxCount > 1 &&
|
|
|
+ this.modelValue.map((item: any) => (
|
|
|
+ <div class={[styles.uploader, styles[this.size]]}>
|
|
|
+ {/* 删除按钮 */}
|
|
|
+ {this.deletable && !this.disabled && (
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ onClick={(e: any) => this.onClose(e, item)}
|
|
|
+ class={styles['img-close']}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ <div class={['van-uploader__upload']}>
|
|
|
+ {this.uploadType === 'IMAGE' ? (
|
|
|
+ <Image src={item} class={styles.previewImg} fit="cover" />
|
|
|
+ ) : (
|
|
|
+ <video
|
|
|
+ ref="videoUpload"
|
|
|
+ style={{ backgroundColor: '#F8F8F8' }}
|
|
|
+ class={styles.previewImg}
|
|
|
+ src={item + '#t=1,4'}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+
|
|
|
+ {this.native ? (
|
|
|
+ this.maxCount > 1 ? (
|
|
|
+ // 小于长度才显示
|
|
|
+ this.modelValue.length < this.maxCount && (
|
|
|
+ <div
|
|
|
+ class={[styles.uploader, styles[this.size]]}
|
|
|
+ onClick={this.nativeUpload}>
|
|
|
+ <Icon
|
|
|
+ name={this.uploadIcon}
|
|
|
+ class={['van-uploader__upload']}
|
|
|
+ size="32"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ ) : (
|
|
|
+ <div
|
|
|
+ class={[styles.uploader, styles[this.size]]}
|
|
|
+ onClick={this.nativeUpload}>
|
|
|
+ {this.modelValue.length > 0 ? (
|
|
|
+ <div class={['van-uploader__upload']}>
|
|
|
+ {this.modelValue.map((item: any) => (
|
|
|
+ <>
|
|
|
+ {/* 删除按钮 */}
|
|
|
+ {this.deletable && !this.disabled && (
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ onClick={(e: any) => this.onClose(e, item)}
|
|
|
+ class={[styles['img-close'], styles.singleImgClose]}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {this.uploadType === 'IMAGE' ? (
|
|
|
+ <Image
|
|
|
+ fit="cover"
|
|
|
+ position="center"
|
|
|
+ class={styles.uploadImg}
|
|
|
+ src={item}
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <video
|
|
|
+ ref="videoUpload"
|
|
|
+ class={styles.uploadImg}
|
|
|
+ style={{ backgroundColor: '#F8F8F8' }}
|
|
|
+ src={item + '#t=1,4'}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <Icon
|
|
|
+ name={this.uploadIcon}
|
|
|
+ class={['van-uploader__upload']}
|
|
|
+ size="32"
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ ) : this.maxCount > 1 ? (
|
|
|
+ // 小于长度才显示
|
|
|
+ this.modelValue.length < this.maxCount && (
|
|
|
+ <Uploader
|
|
|
+ class={[styles.uploader, styles[this.size]]}
|
|
|
+ afterRead={this.afterRead}
|
|
|
+ beforeRead={this.beforeRead}
|
|
|
+ beforeDelete={this.beforeDelete}
|
|
|
+ uploadIcon={this.uploadIcon}
|
|
|
+ maxCount={this.maxCount}
|
|
|
+ disabled={this.disabled}
|
|
|
+ accept={this.accept}
|
|
|
+ />
|
|
|
+ )
|
|
|
+ ) : (
|
|
|
+ <Uploader
|
|
|
+ class={[styles.uploader, styles[this.size]]}
|
|
|
+ afterRead={this.afterRead}
|
|
|
+ beforeRead={this.beforeRead}
|
|
|
+ beforeDelete={this.beforeDelete}
|
|
|
+ uploadIcon={this.uploadIcon}
|
|
|
+ accept={this.accept}
|
|
|
+ disabled={this.disabled}>
|
|
|
+ {this.modelValue.length > 0 ? (
|
|
|
+ <div class={['van-uploader__upload']}>
|
|
|
+ {this.modelValue.map((item: any) => (
|
|
|
+ <>
|
|
|
+ {/* 删除按钮 */}
|
|
|
+ {this.deletable && !this.disabled && (
|
|
|
+ <Icon
|
|
|
+ name="cross"
|
|
|
+ onClick={(e: any) => this.onClose(e, item)}
|
|
|
+ class={[styles['img-close'], styles.singleImgClose]}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {this.uploadType === 'IMAGE' ? (
|
|
|
+ <Image
|
|
|
+ fit="cover"
|
|
|
+ position="center"
|
|
|
+ class={styles.uploadImg}
|
|
|
+ src={item}
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <video
|
|
|
+ ref="videoUpload"
|
|
|
+ class={styles.uploadImg}
|
|
|
+ style={{ backgroundColor: '#F8F8F8' }}
|
|
|
+ src={item + '#t=1,4'}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <Icon
|
|
|
+ name={this.uploadIcon}
|
|
|
+ class={['van-uploader__upload']}
|
|
|
+ size="32"
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Uploader>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
);
|
|
|
}
|
|
|
});
|