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} filePaths - 文件路径数组 * @param {Object} config - 同uploadSingleFile的config * @returns {Promise} 返回一个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) }