9433cfb9创建于 2025年12月31日历史提交
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;