import { ERROR_PATH } from '@/config/image-setting.uts';
import { VITE_APP_BASE_API } from '@/config/setting.uts';
import { userState } from '@/store/user-store.uts';
import type { ApiUplaodSinglePictureResponse } from '@/api/youhujun/upload/upload-type.uts';
/**
* @description 处理上传成功后的服务器响应
* @param {UploadFileSuccess} res - uni.uploadFile 的成功响应对象
* @returns {Promise<ApiUplaodSinglePictureResponse>} 返回一个解析后的业务数据 Promise
*/
const handleResponse = (res: UploadFileSuccess): Promise<ApiUplaodSinglePictureResponse> => {
return new Promise((resolve, reject) => {
// 校验响应数据是否存在
if (!res.data) {
const errorMsg = '请求数据异常,响应体为空';
uni.showToast({ image: ERROR_PATH, title: errorMsg, mask: true, duration: 2000 });
return reject(new Error(errorMsg));
}
// 校验 HTTP 状态码
if (res.statusCode !== 200) {
const errorMsg = `请求失败,HTTP 状态码: ${res.statusCode}`;
uni.showToast({ image: ERROR_PATH, title: `请求失败(${res.statusCode})`, mask: true, duration: 2000 });
return reject(new Error(errorMsg));
}
try {
// 解析 JSON 数据
const responseData: ApiUplaodSinglePictureResponse | null = JSON.parse(res.data);
// 校验业务码
if(responseData){
if (responseData.code === 0) {
return resolve(responseData);
} else {
const errorMsg = responseData.msg || '业务处理失败';
uni.showToast({ image: ERROR_PATH, title: errorMsg, mask: true, duration: 2000 });
return reject(new Error(errorMsg));
}
}
} catch (e) {
// 5. 捕获 JSON 解析错误
const errorMsg = '响应数据格式错误,无法解析为 JSON';
uni.showToast({ image: ERROR_PATH, title: errorMsg, mask: true, duration: 2000 });
return reject(new Error(errorMsg));
}
});
};
/**
* @description 封装 uni.uploadFile,增加参数校验和统一的响应处理
* @param {UploadFileOptions} uploadOptions - 上传配置
* @returns {Promise<ApiUplaodSinglePictureResponse>} 返回一个 Promise,resolve 业务成功数据,reject 错误信息
*/
const service = async (uploadOptions: UploadFileOptions = {url:''}): Promise<ApiUplaodSinglePictureResponse> => {
// --- 核心优化:增强参数校验 ---
if (!uploadOptions.url || typeof uploadOptions.url !== 'string') {
const errorMsg = '上传失败:缺少或无效的 url';
console.error(errorMsg);
uni.showToast({ image: ERROR_PATH, title: '参数错误', mask: true, duration: 2000 });
// 在 async 函数中,throw 会被 Promise.catch 捕获
throw new Error(errorMsg);
}
if (!uploadOptions.filePath || typeof uploadOptions.filePath !== 'string') {
const errorMsg = '上传失败:缺少或无效的 filePath';
console.error(errorMsg);
uni.showToast({ image: ERROR_PATH, title: '文件路径错误', mask: true, duration: 2000 });
throw new Error(errorMsg);
}
// name 有默认值 'file',校验一下类型
if (uploadOptions.name && typeof uploadOptions.name !== 'string') {
const errorMsg = '上传失败:name 必须是字符串';
console.error(errorMsg);
uni.showToast({ image: ERROR_PATH, title: '参数错误', mask: true, duration: 2000 });
throw new Error(errorMsg);
}
return new Promise<ApiUplaodSinglePictureResponse>((resolve, reject) => {
uni.uploadFile({
...uploadOptions,
url: VITE_APP_BASE_API + uploadOptions.url,
header: {
...uploadOptions.header,
'X-Token': userState.token,
},
success: async (res: UploadFileSuccess) => {
try {
const data = await handleResponse(res);
resolve(data);
} catch (error) {
reject(error);
}
},
fail: (error: UploadFileFail) => {
const errorMsg = `文件上传失败: ${error.errMsg || '未知错误'}`;
console.error(errorMsg, error);
uni.showToast({ image: ERROR_PATH, title: '上传失败', mask: true, duration: 2000 });
reject(new Error(errorMsg));
}
});
});
};
export default service;