更新:登录功能
This commit is contained in:
364
uni_modules/wot-design-uni/components/composables/useUpload.ts
Normal file
364
uni_modules/wot-design-uni/components/composables/useUpload.ts
Normal file
@@ -0,0 +1,364 @@
|
||||
import { isArray, isDef, isFunction } from '../common/util'
|
||||
import type { ChooseFile, ChooseFileOption, UploadFileItem, UploadMethod, UploadStatusType } from '../wd-upload/types'
|
||||
|
||||
export const UPLOAD_STATUS: Record<string, UploadStatusType> = {
|
||||
PENDING: 'pending',
|
||||
LOADING: 'loading',
|
||||
SUCCESS: 'success',
|
||||
FAIL: 'fail'
|
||||
}
|
||||
|
||||
export interface UseUploadReturn {
|
||||
// 开始上传文件
|
||||
startUpload: (file: UploadFileItem, options: UseUploadOptions) => UniApp.UploadTask | void | Promise<void>
|
||||
// 中断上传
|
||||
abort: (task?: UniApp.UploadTask) => void
|
||||
// 上传状态常量
|
||||
UPLOAD_STATUS: Record<string, UploadStatusType>
|
||||
// 选择文件
|
||||
chooseFile: (options: ChooseFileOption) => Promise<ChooseFile[]>
|
||||
}
|
||||
|
||||
export interface UseUploadOptions {
|
||||
// 上传地址
|
||||
action: string
|
||||
// 请求头
|
||||
header?: Record<string, any>
|
||||
// 文件对应的 key
|
||||
name?: string
|
||||
// 其它表单数据
|
||||
formData?: Record<string, any>
|
||||
// 文件类型 仅支付宝支持且在支付宝平台必填
|
||||
fileType?: 'image' | 'video' | 'audio'
|
||||
// 成功状态码
|
||||
statusCode?: number
|
||||
// 文件状态的key
|
||||
statusKey?: string
|
||||
// 自定义上传方法
|
||||
uploadMethod?: UploadMethod
|
||||
// 上传成功回调
|
||||
onSuccess?: (res: UniApp.UploadFileSuccessCallbackResult, file: UploadFileItem, formData: Record<string, any>) => void
|
||||
// 上传失败回调
|
||||
onError?: (res: UniApp.GeneralCallbackResult, file: UploadFileItem, formData: Record<string, any>) => void
|
||||
// 上传进度回调
|
||||
onProgress?: (res: UniApp.OnProgressUpdateResult, file: UploadFileItem) => void
|
||||
// 是否自动中断之前的上传任务
|
||||
abortPrevious?: boolean
|
||||
// 根据文件拓展名过滤(H5支持全部类型过滤,微信小程序支持all和file时过滤,其余平台不支持)
|
||||
extension?: string[]
|
||||
}
|
||||
|
||||
export function useUpload(): UseUploadReturn {
|
||||
let currentTask: UniApp.UploadTask | null = null
|
||||
|
||||
// 中断上传
|
||||
const abort = (task?: UniApp.UploadTask) => {
|
||||
if (task) {
|
||||
task.abort()
|
||||
} else if (currentTask) {
|
||||
currentTask.abort()
|
||||
currentTask = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认上传方法
|
||||
*/
|
||||
const defaultUpload: UploadMethod = (file, formData, options) => {
|
||||
// 如果配置了自动中断,则中断之前的上传任务
|
||||
if (options.abortPrevious) {
|
||||
abort()
|
||||
}
|
||||
|
||||
const uploadTask = uni.uploadFile({
|
||||
url: options.action,
|
||||
header: options.header,
|
||||
name: options.name,
|
||||
fileName: options.name,
|
||||
fileType: options.fileType,
|
||||
formData,
|
||||
filePath: file.url,
|
||||
success(res) {
|
||||
if (res.statusCode === options.statusCode) {
|
||||
// 上传成功
|
||||
options.onSuccess(res, file, formData)
|
||||
} else {
|
||||
// 上传失败
|
||||
options.onError({ ...res, errMsg: res.errMsg || '' }, file, formData)
|
||||
}
|
||||
},
|
||||
fail(err) {
|
||||
// 上传失败
|
||||
options.onError(err, file, formData)
|
||||
}
|
||||
})
|
||||
|
||||
currentTask = uploadTask
|
||||
|
||||
// 获取当前文件加载的百分比
|
||||
uploadTask.onProgressUpdate((res) => {
|
||||
options.onProgress(res, file)
|
||||
})
|
||||
|
||||
// 返回上传任务实例,让外部可以控制上传过程
|
||||
return uploadTask
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始上传文件
|
||||
*/
|
||||
const startUpload = (file: UploadFileItem, options: UseUploadOptions) => {
|
||||
const {
|
||||
uploadMethod,
|
||||
formData = {},
|
||||
action,
|
||||
name = 'file',
|
||||
header = {},
|
||||
fileType = 'image',
|
||||
statusCode = 200,
|
||||
statusKey = 'status',
|
||||
abortPrevious = false
|
||||
} = options
|
||||
|
||||
// 设置上传中状态
|
||||
file[statusKey] = UPLOAD_STATUS.LOADING
|
||||
|
||||
const uploadOptions = {
|
||||
action,
|
||||
header,
|
||||
name,
|
||||
fileName: name,
|
||||
fileType,
|
||||
statusCode,
|
||||
abortPrevious,
|
||||
onSuccess: (res: UniApp.UploadFileSuccessCallbackResult, file: UploadFileItem, formData: Record<string, any>) => {
|
||||
// 更新文件状态
|
||||
file[statusKey] = UPLOAD_STATUS.SUCCESS
|
||||
currentTask = null
|
||||
options.onSuccess?.(res, file, formData)
|
||||
},
|
||||
onError: (error: UniApp.GeneralCallbackResult, file: UploadFileItem, formData: Record<string, any>) => {
|
||||
// 更新文件状态和错误信息
|
||||
file[statusKey] = UPLOAD_STATUS.FAIL
|
||||
file.error = error.errMsg
|
||||
currentTask = null
|
||||
options.onError?.(error, file, formData)
|
||||
},
|
||||
onProgress: (res: UniApp.OnProgressUpdateResult, file: UploadFileItem) => {
|
||||
// 更新上传进度
|
||||
file.percent = res.progress
|
||||
options.onProgress?.(res, file)
|
||||
}
|
||||
}
|
||||
|
||||
// 返回上传任务实例,支持外部获取uploadTask进行操作
|
||||
if (isFunction(uploadMethod)) {
|
||||
return uploadMethod(file, formData, uploadOptions)
|
||||
} else {
|
||||
return defaultUpload(file, formData, uploadOptions)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化图片信息
|
||||
*/
|
||||
function formatImage(res: UniApp.ChooseImageSuccessCallbackResult): ChooseFile[] {
|
||||
// #ifdef MP-DINGTALK
|
||||
// 钉钉文件在files中
|
||||
res.tempFiles = isDef((res as any).files) ? (res as any).files : res.tempFiles
|
||||
// #endif
|
||||
if (isArray(res.tempFiles)) {
|
||||
return res.tempFiles.map((item: any) => ({
|
||||
path: item.path || '',
|
||||
name: item.name || '',
|
||||
size: item.size,
|
||||
type: 'image',
|
||||
thumb: item.path || ''
|
||||
}))
|
||||
}
|
||||
return [
|
||||
{
|
||||
path: (res.tempFiles as any).path || '',
|
||||
name: (res.tempFiles as any).name || '',
|
||||
size: (res.tempFiles as any).size,
|
||||
type: 'image',
|
||||
thumb: (res.tempFiles as any).path || ''
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化视频信息
|
||||
*/
|
||||
function formatVideo(res: UniApp.ChooseVideoSuccess): ChooseFile[] {
|
||||
return [
|
||||
{
|
||||
path: res.tempFilePath || (res as any).filePath || '',
|
||||
name: res.name || '',
|
||||
size: res.size,
|
||||
type: 'video',
|
||||
thumb: (res as any).thumbTempFilePath || '',
|
||||
duration: res.duration
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化媒体信息
|
||||
*/
|
||||
function formatMedia(res: UniApp.ChooseMediaSuccessCallbackResult): ChooseFile[] {
|
||||
return res.tempFiles.map((item) => ({
|
||||
type: item.fileType,
|
||||
path: item.tempFilePath,
|
||||
thumb: item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath,
|
||||
size: item.size,
|
||||
duration: item.duration
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择文件
|
||||
*/
|
||||
function chooseFile({
|
||||
multiple,
|
||||
sizeType,
|
||||
sourceType,
|
||||
maxCount,
|
||||
accept,
|
||||
compressed,
|
||||
maxDuration,
|
||||
camera,
|
||||
extension
|
||||
}: ChooseFileOption): Promise<ChooseFile[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
switch (accept) {
|
||||
case 'image':
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.chooseMedia({
|
||||
count: multiple ? maxCount : 1,
|
||||
mediaType: ['image'],
|
||||
sourceType,
|
||||
sizeType,
|
||||
camera,
|
||||
success: (res) => resolve(formatMedia(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.chooseImage({
|
||||
count: multiple ? maxCount : 1,
|
||||
sizeType,
|
||||
sourceType,
|
||||
// #ifdef H5
|
||||
extension,
|
||||
// #endif
|
||||
success: (res) => resolve(formatImage(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
break
|
||||
case 'video':
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.chooseMedia({
|
||||
count: multiple ? maxCount : 1,
|
||||
mediaType: ['video'],
|
||||
sourceType,
|
||||
camera,
|
||||
maxDuration,
|
||||
success: (res) => resolve(formatMedia(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.chooseVideo({
|
||||
sourceType,
|
||||
compressed,
|
||||
maxDuration,
|
||||
camera,
|
||||
// #ifdef H5
|
||||
extension,
|
||||
// #endif
|
||||
success: (res) => resolve(formatVideo(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
break
|
||||
// #ifdef MP-WEIXIN
|
||||
case 'media':
|
||||
uni.chooseMedia({
|
||||
count: multiple ? maxCount : 1,
|
||||
sourceType,
|
||||
sizeType,
|
||||
camera,
|
||||
maxDuration,
|
||||
success: (res) => resolve(formatMedia(res)),
|
||||
fail: reject
|
||||
})
|
||||
break
|
||||
case 'file':
|
||||
uni.chooseMessageFile({
|
||||
count: multiple ? (isDef(maxCount) ? maxCount : 100) : 1,
|
||||
type: accept,
|
||||
extension,
|
||||
success: (res) => resolve(res.tempFiles),
|
||||
fail: reject
|
||||
})
|
||||
break
|
||||
// #endif
|
||||
case 'all':
|
||||
// #ifdef H5
|
||||
uni.chooseFile({
|
||||
count: multiple ? maxCount : 1,
|
||||
type: accept,
|
||||
extension,
|
||||
success: (res) => resolve(res.tempFiles as ChooseFile[]),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.chooseMessageFile({
|
||||
count: multiple ? Number(maxCount) : 1,
|
||||
type: accept,
|
||||
extension,
|
||||
success: (res) => resolve(res.tempFiles),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
|
||||
break
|
||||
default:
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.chooseMedia({
|
||||
count: multiple ? maxCount : 1,
|
||||
mediaType: ['image'],
|
||||
sourceType,
|
||||
sizeType,
|
||||
camera,
|
||||
success: (res) => resolve(formatMedia(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.chooseImage({
|
||||
count: multiple ? maxCount : 1,
|
||||
sizeType,
|
||||
sourceType,
|
||||
// #ifdef H5
|
||||
extension,
|
||||
// #endif
|
||||
success: (res) => resolve(formatImage(res)),
|
||||
fail: reject
|
||||
})
|
||||
// #endif
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
startUpload,
|
||||
abort,
|
||||
UPLOAD_STATUS,
|
||||
chooseFile
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user