UNPKG

nutui-uniapp

Version:

京东风格的轻量级移动端 Uniapp、Vue3 组件库(支持小程序开发)

241 lines (221 loc) 6.51 kB
import { omit } from '../_utils' import type { AcceptType, FileType, SizeType } from './types' import type { UploaderProps } from './uploader' interface UniChooseFileSuccessCallbackResult { /** * 本地文件路径列表 */ tempFilePaths?: string[] /** * 本地文件列表,每一项是一个 File 对象 */ tempFiles: ({ path: string size: number name: string type: string } & File)[] } interface UniChooseImageSuccessCallbackResult extends UniChooseFileSuccessCallbackResult { } interface UniChooseVideoSuccessCallbackResult { /** * 本地文件路径 */ tempFilePath?: string /** * 本地文件,一个 File 对象 */ tempFile: ({ path: string size: number name: string type: string } & File) /** * 选定视频的时间长度,单位为s */ duration: number /** * 选定视频的数据量大小 */ size: number /** * 返回选定视频的高 */ height: number /** * 返回选定视频的宽 */ width: number /** * 包含扩展名的文件名称 */ name: string } export interface ChooseFile { size: number type?: FileType fileType?: FileType originalFileObj?: any tempFilePath?: string thumbTempFilePath?: string path?: string name: string thumb?: string url?: string [k: string]: unknown } function omitProps<T>(obj: T, keys: string[]) { if (!['[object Object]', '[object File]'].includes(Object.prototype.toString.call(obj))) return {} return omit(obj as unknown as Record<string, unknown>, keys) } function formatImage(res: UniChooseImageSuccessCallbackResult): ChooseFile[] { return res.tempFiles.map(item => ({ ...omitProps(item, ['path']), type: 'image', url: item.path, thumb: item.path, size: item.size, name: item.name || 'image', })) } function formatVideo(res: UniChooseVideoSuccessCallbackResult): ChooseFile[] { return [{ ...omitProps(res.tempFile, ['path']), type: 'video', url: res.tempFilePath, thumb: res.tempFilePath, size: res.tempFile.size, name: res.tempFile.name || 'video', }] } function formatMedia(res: UniApp.ChooseMediaSuccessCallbackResult & { name?: string }): ChooseFile[] { return res.tempFiles.map(item => ({ ...omitProps(item, ['fileType', 'thumbTempFilePath', 'tempFilePath']), type: res.type as FileType, url: item.tempFilePath, thumb: res.type === 'video' ? item.thumbTempFilePath : item.tempFilePath, size: item.size, name: res?.name || 'media', })) } export interface ChooseFileOptions { accept: AcceptType multiple: boolean capture: boolean maxDuration: number sizeType: SizeType[] camera?: 'back' | 'front' maxCount: number } export function chooseFile({ accept, multiple, maxDuration, sizeType, camera, }: ChooseFileOptions, props: UploaderProps, fileList: any[]): Promise<ChooseFile[] | ChooseFile> { return new Promise((resolve, reject) => { // chooseMedia 目前只支持微信小程序原生,其余端全部使用 chooseImage API // #ifdef MP-WEIXIN uni.chooseMedia({ /** 最多可以选择的文件个数 */ count: multiple ? Number(props.maximum) - fileList.length : 1, /** 文件类型 */ mediaType: props.mediaType, /** 图片和视频选择的来源 */ sourceType: props.sourceType, /** 拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间 */ maxDuration, /** 仅对 mediaType 为 image 时有效,是否压缩所选文件 */ sizeType, /** 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 */ camera, /** 接口调用失败的回调函数 */ fail: reject, /** 接口调用成功的回调函数 */ success: res => resolve(formatMedia(res)), }) // #endif // #ifndef MP-WEIXIN if (accept === 'image') { uni.chooseImage({ // 选择数量 count: props.multiple ? Number(props.maximum) - props.fileList.length : 1, // 可以指定是原图还是压缩图,默认二者都有 sizeType, sourceType: props.sourceType, success: (res) => { resolve(formatImage(res as UniChooseFileSuccessCallbackResult)) }, fail: reject, }) } else if (accept === 'video') { uni.chooseVideo({ sourceType: props.sourceType, success: (res) => { resolve(formatVideo(res as UniChooseVideoSuccessCallbackResult)) }, fail: reject, }) } else if (accept === 'all') { uni.chooseFile({ type: 'all', // 选择数量 count: props.multiple ? Number(props.maximum) - props.fileList.length : 1, // 可以指定是原图还是压缩图,默认二者都有 sizeType, sourceType: props.sourceType, success: (res) => { resolve(formatImage(res as UniChooseFileSuccessCallbackResult)) }, fail: reject, }) } // #endif }) } export type OnProgressUpdateResult = UniApp.OnProgressUpdateResult export type UploadFileSuccessCallbackResult = UniApp.UploadFileSuccessCallbackResult export type GeneralCallbackResult = UniApp.GeneralCallbackResult export type UploadOptions = UniNamespace.UploadFileOption & { xhrState?: number onStart?: (option: UploadOptions) => void onProgress?: (result: UniApp.OnProgressUpdateResult, option: UploadOptions) => void onSuccess?: (result: UniApp.UploadFileSuccessCallbackResult, option: UploadOptions) => void onFailure?: (result: UniApp.GeneralCallbackResult | UniApp.UploadFileSuccessCallbackResult, option: UploadOptions) => void } export function createUploader(options: UploadOptions) { const upload = () => { const uploadTask = uni.uploadFile({ url: options.url, fileType: options.fileType, file: options.file, filePath: options.filePath, name: options.name, header: options.header, timeout: options.timeout, formData: options.formData, success: (result) => { if (options.xhrState === result.statusCode) options.onSuccess?.(result, options) else options.onFailure?.(result, options) }, fail: (result) => { options.onFailure?.(result, options) }, }) options.onStart?.(options) uploadTask.onProgressUpdate((event) => { options.onProgress?.(event, options) }) } return { upload, } }