user
Yann authored at 2025-07-01 13:49:14
8.90 KiB
cube-front
/**
 * 统一响应处理工具类
 * 处理API返回的标准格式数据
 */
import notification from '../components/Notification';

/**
 * 标准API响应接口
 */
export interface ApiResponse<T = unknown> {
  /** 响应状态码,0或200表示成功 */
  code: number;
  /** 响应消息 */
  message?: string | null;
  /** 响应数据 */
  data?: T;
  /** 链路追踪ID */
  traceId?: string | null;
  /** 分页信息 */
  page?: {
    pageIndex: number;
    pageSize: number;
    totalCount: number;
    longTotalCount: string;
  } | null;
  /** 统计信息 */
  stat?: Record<string, unknown> | null;
}

/**
 * 分页请求参数接口
 */
export interface PageParams {
  pageIndex?: number;
  pageSize?: number;
}

/**
 * 标准化分页请求参数
 * @param params 原始参数
 * @returns 标准化后的参数
 */
export function normalizePageParams<T extends Record<string, unknown>>(params: T & PageParams): T & Required<PageParams> {
  return {
    ...params,
    pageIndex: params.pageIndex || 1,
    pageSize: params.pageSize || 10,
  };
}

/**
 * 处理API响应
 * @param response API响应数据
 * @param options 处理选项
 * @returns 处理结果
 */
export function handleApiResponse<T = unknown>(
  response: unknown,
  options: {
    /** 是否显示成功提示,默认为false(查询操作通常不显示成功提示) */
    showSuccessMessage?: boolean;
    /** 是否显示错误提示,默认为true */
    showErrorMessage?: boolean;
    /** 自定义成功消息 */
    successMessage?: string;
    /** 自定义错误消息 */
    errorMessage?: string;
  } = {}
): {
  success: boolean;
  data: T | null;
  message: string | null;
  page: ApiResponse['page'];
  stat: ApiResponse['stat'];
} {
  const {
    showSuccessMessage = false, // 默认不显示成功提示
    showErrorMessage = true,
    successMessage,
    errorMessage
  } = options;

  console.log('=== handleApiResponse 开始处理 ===');
  console.log('响应数据:', response);
  console.log('响应数据类型:', typeof response);
  console.log('响应数据是否有 code 字段:', response && typeof response === 'object' && 'code' in response);

  // 检查响应是否为有效对象
  if (!response || typeof response !== 'object') {
    console.log('❌ 无效响应数据');
    const errorMsg = errorMessage || '无效的响应数据';
    if (showErrorMessage) {
      notification.error({ message: errorMsg });
    }
    return {
      success: false,
      data: null,
      message: errorMsg,
      page: null,
      stat: null,
    };
  }

  const responseObj = response as Record<string, unknown>;
  console.log('转换后的响应对象 keys:', Object.keys(responseObj));
  console.log('responseObj.code 原始值:', responseObj.code);
  console.log('responseObj.code 类型:', typeof responseObj.code);

  // 1. 检查 code 字段并判断成功状态
  const code = responseObj.code as number;
  const isSuccess = code === 0 || code === 200;

  console.log('响应状态判断:', {
    code: code,
    codeType: typeof code,
    codeValue: responseObj.code,
    isCodeZero: code === 0,
    isCode200: code === 200,
    isSuccess: isSuccess
  });

  // 2. 处理 message 字段(可能为 null 或空字符串)
  const message = (responseObj.message as string) || null;

  // 3. 处理 traceId 字段(可能为 null、空字符串或不存在)
  const traceId = responseObj.traceId as string;
  if (traceId && traceId.trim() !== '') {
    console.log('TraceId:', traceId);
  }

  // 4. 处理 page 字段(可能为 null、空对象或不存在)
  let pageInfo: ApiResponse['page'] = null;
  if (responseObj.page && typeof responseObj.page === 'object') {
    const page = responseObj.page as Record<string, unknown>;
    // 检查是否为有效的分页对象(包含必要字段)
    if (typeof page.pageIndex === 'number' && typeof page.pageSize === 'number') {
      pageInfo = {
        pageIndex: page.pageIndex,
        pageSize: page.pageSize,
        totalCount: (page.totalCount as number) || 0,
        longTotalCount: (page.longTotalCount as string) || '0',
      };
    }
  }

  // 5. 处理 stat 字段(可能为 null、空对象或不存在)
  let statInfo: ApiResponse['stat'] = null;
  if (responseObj.stat && typeof responseObj.stat === 'object') {
    const stat = responseObj.stat as Record<string, unknown>;
    // 只有当 stat 对象有内容时才保留
    if (Object.keys(stat).length > 0) {
      statInfo = stat;
    }
  }

  // 6. 处理 data 字段(可能是对象、数组、基本类型或 null)
  const data = responseObj.data as T;

  console.log('处理后的数据:', {
    success: isSuccess,
    data: data,
    message: message,
    page: pageInfo,
    stat: statInfo
  });

  if (isSuccess) {
    // 成功处理
    console.log('✅ 处理成功分支');

    // 显示成功提示(如果 message 不为空且配置了显示成功提示)
    const displayMessage = successMessage || message;
    if (showSuccessMessage && displayMessage) {
      console.log('显示成功提示:', displayMessage);
      notification.success({ message: displayMessage });
    }

    const result = {
      success: true,
      data: data || null,
      message: message,
      page: pageInfo,
      stat: statInfo,
    };
    console.log('✅ 返回成功结果:', result);
    return result;
  } else {
    // 错误处理
    console.log('❌ 处理错误分支');

    // 显示错误提示
    const displayMessage = errorMessage || message || '操作失败';
    if (showErrorMessage) {
      console.log('显示错误提示:', displayMessage);
      notification.error({ message: displayMessage });
    }

    const result = {
      success: false,
      data: null,
      message: message,
      page: pageInfo,
      stat: statInfo,
    };
    console.log('❌ 返回错误结果:', result);
    return result;
  }
}

/**
 * 创建API请求包装器
 * 自动处理响应并返回标准化结果
 */
export function createApiWrapper<T = unknown, P = unknown>(
  apiCall: (params: P) => Promise<ApiResponse<T>>,
  options?: {
    showSuccessMessage?: boolean;
    showErrorMessage?: boolean;
    successMessage?: string;
    errorMessage?: string;
  }
) {
  return async (params: P) => {
    try {
      console.log('=== createApiWrapper 开始调用 ===');
      console.log('调用参数:', params);

      const response = await apiCall(params);

      console.log('=== createApiWrapper 收到响应 ===');
      console.log('apiCall 返回的 response:', response);
      console.log('response 类型:', typeof response);
      console.log('response 是否为数组:', Array.isArray(response));
      console.log('response 是否有 code 字段:', response && typeof response === 'object' && 'code' in response);

      return handleApiResponse(response, {
        showSuccessMessage: false, // 默认不显示成功提示
        showErrorMessage: true,    // 默认显示错误提示
        ...options,               // 用户配置覆盖默认值
      });
    } catch (error) {
      // 网络错误或其他异常
      console.error('API调用失败:', error);

      if (options?.showErrorMessage !== false) {
        const message = options?.errorMessage || '网络请求失败,请稍后重试';
        notification.error({ message });
      }

      return {
        success: false,
        data: null,
        message: '网络请求失败',
        page: null,
        stat: null,
      };
    }
  };
}

/**
 * 分页API请求包装器
 * 专门处理分页请求,自动标准化分页参数
 */
export function createPageApiWrapper<T = unknown, P = Record<string, unknown>>(
  apiCall: (params: P & Required<PageParams>) => Promise<ApiResponse<T>>,
  options?: {
    showSuccessMessage?: boolean;
    showErrorMessage?: boolean;
    successMessage?: string;
    errorMessage?: string;
  }
) {
  return async (params: P & PageParams) => {
    const normalizedParams = {
      ...params,
      pageIndex: params.pageIndex || 1,
      pageSize: params.pageSize || 10,
    } as P & Required<PageParams>;
    return createApiWrapper(apiCall, options)(normalizedParams);
  };
}

/**
 * 提取响应数据
 * 从API响应中提取数据部分,如果失败则返回null
 * @param response API响应
 * @returns 数据或null
 */
export function extractResponseData<T>(response: ApiResponse<T>): T | null {
  const result = handleApiResponse(response, { showSuccessMessage: false, showErrorMessage: false });
  return result.success ? (result.data as T) : null;
}

/**
 * 提取分页数据
 * 从API响应中提取分页信息
 * @param response API响应
 * @returns 分页信息或null
 */
export function extractPageInfo(response: ApiResponse): ApiResponse['page'] {
  return response.page || null;
}

/**
 * 检查响应是否成功
 * @param response API响应
 * @returns 是否成功
 */
export function isApiSuccess(response: ApiResponse): boolean {
  return response.code === 0 || response.code === 200;
}

// 导出所有工具函数和类型,方便其他模块使用
export * from './response';