common.js 4.37 KB
/*
 * @Date: 2022-06-17 14:54:29
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2022-06-18 22:18:46
 * @FilePath: /tswj/src/api/common.js
 * @Description: 通用接口
 */
import { fn, fetch, uploadFn } from '@/api/fn';

const Api = {
  SMS: '/srv/?a=sms',
  TOKEN: '/srv/?a=upload',
  SAVE_FILE: '/srv/?a=upload&t=save_file',
  UPLOAD_IMAGE: '/admin/?m=srv&a=upload', // 上传图片(不带审核)
}

/**
 * @description: 发送验证码
 * @param {Object} params 请求参数
 * @param {string} params.phone 手机号
 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
 */
export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));

/**
 * @description: 获取七牛token
 * @param {Object} params 请求参数
 * @param {string} params.filename 文件名
 * @param {string} params.file 图片 base64
 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为上传 token 等信息)
 */
export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));

/**
 * @description: 上传七牛
 * @param {string} url 七牛上传地址
 * @param {any} data 上传数据
 * @param {Object} config axios 配置
 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false
 */
export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config));

/**
 * @description: 保存图片
 * @param {Object} params 请求参数
 * @param {string} params.format 文件格式
 * @param {string} params.hash 文件 hash
 * @param {string|number} params.height 图片高
 * @param {string|number} params.width 图片宽
 * @param {string} params.filekey 文件 key
 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
 */
export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params));

/**
 * @description: 上传图片到七牛云(完整流程)
 * @param {Object} params 请求参数
 * @param {string} params.filePath 本地文件路径
 * @returns {Promise<{code:number,data:{src:string},msg:string}>} 返回上传结果,data.src 为图片URL
 *
 * @example
 * // 在页面中使用
 * import { uploadImageToQiniuAPI } from '@/api/common'
 *
 * Taro.chooseImage({
 *   count: 1,
 *   success: async (res) => {
 *     const result = await uploadImageToQiniuAPI({
 *       filePath: res.tempFilePaths[0]
 *     })
 *     if (result.code === 1) {
 *       console.log('图片URL:', result.data.src)
 *     }
 *   }
 * })
 */
export const uploadImageToQiniuAPI = async (params) => {
  try {
    // 1. 读取文件为 base64
    const base64Data = await new Promise((resolve, reject) => {
      Taro.getFileSystemManager().readFile({
        filePath: params.filePath,
        encoding: 'base64',
        success: (res) => resolve(res.data),
        fail: (err) => reject(err)
      });
    });

    // 2. 获取七牛上传token
    const tokenRes = await qiniuTokenAPI({
      filename: params.filePath.split('/').pop(),
      file: base64Data
    });

    if (tokenRes.code !== 1 || !tokenRes.data) {
      throw new Error(tokenRes.msg || '获取上传凭证失败');
    }

    const { token, upload_url, filekey } = tokenRes.data;

    // 3. 上传到七牛云
    const formData = new FormData();
    formData.append('file', base64Data);
    formData.append('token', token);
    formData.append('key', filekey);

    const uploadRes = await qiniuUploadAPI(upload_url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    });

    if (!uploadRes) {
      throw new Error('七牛上传失败');
    }

    // 4. 保存文件信息到服务器
    const saveRes = await saveFileAPI({
      format: uploadRes.format,
      hash: uploadRes.hash,
      height: uploadRes.height || 0,
      width: uploadRes.width || 0,
      filekey: uploadRes.key
    });

    if (saveRes.code !== 1) {
      throw new Error(saveRes.msg || '保存文件信息失败');
    }

    return {
      code: 1,
      data: {
        src: uploadRes.src || saveRes.data.src, // 优先使用七牛返回的src,否则使用服务器返回的
        hash: uploadRes.hash,
        format: uploadRes.format,
        width: uploadRes.width,
        height: uploadRes.height
      },
      msg: '上传成功'
    };

  } catch (err) {
    console.error('上传图片失败:', err);
    return {
      code: 0,
      data: null,
      msg: err.message || err.msg || '上传失败'
    };
  }
};