135 lines
4.2 KiB
JavaScript
135 lines
4.2 KiB
JavaScript
import { getToken } from './storage'
|
||
|
||
/**
|
||
* 二次封装的uni.uploadFile方法 (Promise化)
|
||
* @param {string} filePath - 要上传的文件路径
|
||
* @param {Object} [config] - 可选配置项
|
||
* @param {string} [config.url] - 上传接口地址,若不传则使用默认或全局配置
|
||
* @param {string} [config.name='file'] - 文件对应的 key
|
||
* @param {Object} [config.formData={}] - 额外的 form data
|
||
* @param {Object} [config.header] - 请求头,可覆盖默认头
|
||
* @param {number} [config.timeout] - 超时时间(ms)
|
||
* @returns {Promise} 返回一个Promise对象,成功时解析上传响应数据
|
||
*/
|
||
export const uploadSingleFile = (filePath, config = {}) => {
|
||
// 默认配置,可从全局导入或在此定义
|
||
const DEFAULT_CONFIG = {
|
||
baseURL: import.meta.env.VITE_SYSTEM_URL,
|
||
// timeout: 30000,
|
||
name: 'file',
|
||
header: {
|
||
deviceId: uni.getDeviceInfo().deviceId,
|
||
Authorization: `Bearer ${getToken()}`
|
||
}
|
||
}
|
||
|
||
// 合并配置
|
||
const mergedConfig = {
|
||
...DEFAULT_CONFIG,
|
||
...config,
|
||
header: {
|
||
...DEFAULT_CONFIG.header
|
||
}
|
||
}
|
||
|
||
const { baseURL, ...uploadOptions } = mergedConfig
|
||
const finalUrl = baseURL
|
||
? `${baseURL}${uploadOptions.url || ''}`
|
||
: uploadOptions.url
|
||
|
||
if (!finalUrl) {
|
||
return Promise.reject(new Error('上传接口地址不能为空'))
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
uni.showLoading({
|
||
title: '上传中...',
|
||
mask: true // 防止触摸穿透
|
||
})
|
||
const uploadTask = uni.uploadFile({
|
||
url: finalUrl,
|
||
filePath: filePath,
|
||
name: uploadOptions.name,
|
||
formData: uploadOptions.formData,
|
||
header: uploadOptions.header,
|
||
timeout: uploadOptions.timeout,
|
||
success: res => {
|
||
uni.hideLoading()
|
||
if (res.statusCode === 200) {
|
||
try {
|
||
// 尝试解析返回数据,假设是
|
||
const data =
|
||
typeof res.data === 'string'
|
||
? JSON.parse(res.data)
|
||
: res.data
|
||
// 验证失效去登录页
|
||
if (data.code === 401) {
|
||
uni.removeStorage({
|
||
key: 'token'
|
||
})
|
||
uni.reLaunch({
|
||
url: '/pages/login/login'
|
||
})
|
||
return
|
||
}
|
||
if (data.code === 200) {
|
||
console.log('上传成功:', data)
|
||
resolve(data.url) // 根据后端实际结构,可能需进一步处理,如 data.data.url
|
||
return
|
||
}
|
||
|
||
uni.showToast({
|
||
title: data.msg || '请求失败',
|
||
icon: 'none'
|
||
})
|
||
} catch (e) {
|
||
// 解析失败可能返回的是字符串,直接返回
|
||
resolve(res.data)
|
||
}
|
||
return
|
||
}
|
||
|
||
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
|
||
},
|
||
fail: err => {
|
||
uni.hideLoading()
|
||
reject(err)
|
||
}
|
||
})
|
||
|
||
// 可选:监听上传进度事件[6](@ref)
|
||
uploadTask.onProgressUpdate(res => {
|
||
console.log('上传进度:', res.progress)
|
||
console.log('已上传:', res.totalBytesSent, '字节')
|
||
console.log('总大小:', res.totalBytesExpectedToSend, '字节')
|
||
if (res.progress !== 100) {
|
||
uni.showLoading({
|
||
title: `上传进度: ${res.progress}`,
|
||
mask: true // 防止触摸穿透
|
||
})
|
||
}
|
||
// 可通过自定义事件或回调函数将进度传递出去
|
||
if (typeof config.onProgress === 'function') {
|
||
config.onProgress(res)
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 多文件上传
|
||
* @param {Array<string>} filePaths - 文件路径数组
|
||
* @param {Object} config - 同uploadSingleFile的config
|
||
* @returns {Promise<Array>} 返回一个Promise,解析为所有上传结果数组
|
||
*/
|
||
export const uploadMultipleFiles = (filePaths, config = {}) => {
|
||
// 使用Promise.all同时发起所有上传请求[3,4](@ref)
|
||
const uploadPromises = filePaths.map(
|
||
filePath =>
|
||
uploadSingleFile(filePath, config)
|
||
.then(res => ({ status: 'fulfilled', value: res })) // 成功,记录结果
|
||
.catch(err => ({ status: 'rejected', reason: err })) // 失败,记录原因
|
||
)
|
||
return Promise.all(uploadPromises)
|
||
}
|