|
|
@@ -25,7 +25,7 @@
|
|
|
class="nut-uploader__preview-img__c"
|
|
|
mode="aspectFit"
|
|
|
@click="fileItemClick(item)"
|
|
|
- v-if="item.type?.includes('image') && item.url"
|
|
|
+ v-if="['image','video'].includes(item.type as string) && item.url"
|
|
|
:src="item.url"
|
|
|
/>
|
|
|
<view v-else class="nut-uploader__preview-img__file">
|
|
|
@@ -74,7 +74,7 @@
|
|
|
import { computed, PropType, reactive } from 'vue';
|
|
|
import { createComponent } from '@/packages/utils/create';
|
|
|
import { UploaderTaro, UploadOptions } from './uploader';
|
|
|
-import { FileItem, SizeType, SourceType } from './type';
|
|
|
+import { FileItem, MediaType, SizeType, SourceType } from './type';
|
|
|
import { funInterceptor, Interceptor } from '@/packages/utils/util';
|
|
|
import Progress from '../progress/index.taro.vue';
|
|
|
import Button from '../button/index.taro.vue';
|
|
|
@@ -102,6 +102,15 @@ export default create({
|
|
|
type: Array as PropType<SourceType[]>,
|
|
|
default: () => ['album', 'camera']
|
|
|
},
|
|
|
+ mediaType: {
|
|
|
+ type: Array as PropType<MediaType[]>,
|
|
|
+ default: () => ['image', 'video', 'mix']
|
|
|
+ },
|
|
|
+ camera: {
|
|
|
+ type: String,
|
|
|
+ default: 'back'
|
|
|
+ },
|
|
|
+
|
|
|
timeout: { type: [Number, String], default: 1000 * 30 },
|
|
|
// defaultFileList: { type: Array, default: () => new Array<FileItem>() },
|
|
|
fileList: { type: Array, default: () => [] },
|
|
|
@@ -121,10 +130,7 @@ export default create({
|
|
|
multiple: { type: Boolean, default: true },
|
|
|
disabled: { type: Boolean, default: false },
|
|
|
autoUpload: { type: Boolean, default: true },
|
|
|
- beforeUpload: {
|
|
|
- type: Function,
|
|
|
- default: null
|
|
|
- },
|
|
|
+ maxDuration: { type: Number, default: 10 },
|
|
|
beforeXhrUpload: {
|
|
|
type: Function,
|
|
|
default: null
|
|
|
@@ -177,17 +183,59 @@ export default create({
|
|
|
document.body.appendChild(obj);
|
|
|
}
|
|
|
}
|
|
|
+ if (Taro.getEnv() == 'WEAPP') {
|
|
|
+ // chooseMedia 目前只支持微信小程序原生,其余端全部使用 chooseImage API
|
|
|
+ Taro.chooseMedia({
|
|
|
+ /** 最多可以选择的文件个数 */
|
|
|
+ count: props.multiple ? (props.maximum as number) * 1 - props.fileList.length : 1,
|
|
|
+ /** 文件类型 */
|
|
|
+ mediaType: props.mediaType,
|
|
|
+ /** 图片和视频选择的来源 */
|
|
|
+ sourceType: props.sourceType,
|
|
|
+ /** 拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间 */
|
|
|
+ maxDuration: props.maxDuration,
|
|
|
+ /** 仅对 mediaType 为 image 时有效,是否压缩所选文件 */
|
|
|
+ sizeType: [],
|
|
|
+ /** 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 */
|
|
|
+ camera: props.camera,
|
|
|
+ /** 接口调用失败的回调函数 */
|
|
|
+ fail: (res: TaroGeneral.CallbackResult) => {
|
|
|
+ emit('failure', res);
|
|
|
+ },
|
|
|
+ /** 接口调用成功的回调函数 */
|
|
|
+ success: onChangeMedia
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ Taro.chooseImage({
|
|
|
+ // 选择数量
|
|
|
+ count: props.multiple ? (props.maximum as number) * 1 - props.fileList.length : 1,
|
|
|
+ // 可以指定是原图还是压缩图,默认二者都有
|
|
|
+ sizeType: props.sizeType,
|
|
|
+ sourceType: props.sourceType,
|
|
|
+ success: onChangeImage,
|
|
|
+ fail: (res: any) => {
|
|
|
+ emit('failure', res);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
- Taro.chooseImage({
|
|
|
- // 选择数量
|
|
|
- count: props.multiple ? (props.maximum as number) * 1 - props.fileList.length : 1,
|
|
|
- // 可以指定是原图还是压缩图,默认二者都有
|
|
|
- sizeType: props.sizeType,
|
|
|
- sourceType: props.sourceType,
|
|
|
- success: onChange,
|
|
|
- fail: (res: any) => {
|
|
|
- emit('failure', res);
|
|
|
- }
|
|
|
+ const onChangeMedia = (res: Taro.chooseMedia.SuccessCallbackResult) => {
|
|
|
+ // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
|
|
|
+ const { type, tempFiles } = res;
|
|
|
+ const _files: Taro.chooseMedia.ChooseMedia[] = filterFiles<Taro.chooseMedia.ChooseMedia>(tempFiles);
|
|
|
+ readFile<Taro.chooseMedia.ChooseMedia>(_files);
|
|
|
+ emit('change', {
|
|
|
+ fileList
|
|
|
+ });
|
|
|
+ };
|
|
|
+ const onChangeImage = (res: Taro.chooseImage.SuccessCallbackResult) => {
|
|
|
+ // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
|
|
|
+ const { tempFilePaths, tempFiles } = res;
|
|
|
+ const _files: Taro.chooseImage.ImageFile[] = filterFiles<Taro.chooseImage.ImageFile>(tempFiles);
|
|
|
+ readFile<Taro.chooseImage.ImageFile>(_files);
|
|
|
+ emit('change', {
|
|
|
+ fileList
|
|
|
});
|
|
|
};
|
|
|
|
|
|
@@ -267,17 +315,31 @@ export default create({
|
|
|
res.forEach((i) => i.uploadTaro(Taro.uploadFile, Taro.getEnv()));
|
|
|
});
|
|
|
};
|
|
|
-
|
|
|
- const readFile = (files: Taro.chooseImage.ImageFile[]) => {
|
|
|
- const imgReg = /\.(png|jpeg|jpg|webp|gif)$/i;
|
|
|
- files.forEach((file: Taro.chooseImage.ImageFile, index: number) => {
|
|
|
+ interface TFileType {
|
|
|
+ size: number;
|
|
|
+ type?: string;
|
|
|
+ fileType?: string;
|
|
|
+ originalFileObj?: any;
|
|
|
+ tempFilePath?: string;
|
|
|
+ thumbTempFilePath?: string;
|
|
|
+ path?: string;
|
|
|
+ }
|
|
|
+ const readFile = <T extends TFileType>(files: T[]) => {
|
|
|
+ files.forEach((file: T, index: number) => {
|
|
|
let fileType = file.type;
|
|
|
+ let filepath = (file.tempFilePath || file.path) as string;
|
|
|
const fileItem = reactive(new FileItem());
|
|
|
- if (!fileType && (imgReg.test(file.path) || file.path.includes('data:image'))) {
|
|
|
- fileType = 'image';
|
|
|
+ if (file.fileType) {
|
|
|
+ fileType = file.fileType;
|
|
|
+ } else {
|
|
|
+ const imgReg = /\.(png|jpeg|jpg|webp|gif)$/i;
|
|
|
+ if (!fileType && (imgReg.test(filepath) || filepath.includes('data:image'))) {
|
|
|
+ fileType = 'image';
|
|
|
+ }
|
|
|
}
|
|
|
- fileItem.path = file.path;
|
|
|
- fileItem.name = file.path;
|
|
|
+
|
|
|
+ fileItem.path = filepath;
|
|
|
+ fileItem.name = filepath;
|
|
|
fileItem.status = 'ready';
|
|
|
fileItem.message = translate('waitingUpload');
|
|
|
fileItem.type = fileType;
|
|
|
@@ -294,18 +356,18 @@ export default create({
|
|
|
fileItem.formData = props.data;
|
|
|
}
|
|
|
if (props.isPreview) {
|
|
|
- fileItem.url = file.path;
|
|
|
+ fileItem.url = fileType == 'video' ? file.thumbTempFilePath : filepath;
|
|
|
}
|
|
|
fileList.push(fileItem);
|
|
|
executeUpload(fileItem, index);
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- const filterFiles = (files: Taro.chooseImage.ImageFile[]) => {
|
|
|
+ const filterFiles = <T extends TFileType>(files: T[]) => {
|
|
|
const maximum = (props.maximum as number) * 1;
|
|
|
const maximize = (props.maximize as number) * 1;
|
|
|
- const oversizes = new Array<Taro.chooseImage.ImageFile>();
|
|
|
- files = files.filter((file: Taro.chooseImage.ImageFile) => {
|
|
|
+ const oversizes = new Array<T>();
|
|
|
+ files = files.filter((file: T) => {
|
|
|
if (file.size > maximize) {
|
|
|
oversizes.push(file);
|
|
|
return false;
|
|
|
@@ -340,26 +402,6 @@ export default create({
|
|
|
});
|
|
|
};
|
|
|
|
|
|
- const onChange = (res: Taro.chooseImage.SuccessCallbackResult) => {
|
|
|
- // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
|
|
|
- const { tempFilePaths, tempFiles } = res;
|
|
|
-
|
|
|
- if (props.beforeUpload) {
|
|
|
- props.beforeUpload(tempFiles).then((f: Array<Taro.chooseImage.ImageFile>) => changeReadFile(f));
|
|
|
- } else {
|
|
|
- changeReadFile(tempFiles);
|
|
|
- }
|
|
|
-
|
|
|
- emit('change', {
|
|
|
- fileList
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const changeReadFile = (f: any) => {
|
|
|
- const _files: Taro.chooseImage.ImageFile[] = filterFiles(f);
|
|
|
- readFile(_files);
|
|
|
- };
|
|
|
-
|
|
|
return {
|
|
|
onDelete,
|
|
|
fileList,
|