logistics-adapters

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Taiwan Logistics Adapters (台灣物流適配器)

台湾物流适配器

Overview

概述

@rytass/logistics
系列套件提供統一的台灣物流服務整合介面,支援包裹追蹤、訂單建立和狀態管理。
@rytass/logistics
系列套件提供统一的台湾物流服务集成接口,支持包裹追踪、订单创建和状态管理。

套件清單

套件清单

套件說明功能
@rytass/logistics
基礎介面定義統一的物流服務介面
@rytass/logistics-adapter-tcat
黑貓宅急便包裹追蹤(HTML 爬蟲)
@rytass/logistics-adapter-ctc
中華宅配包裹追蹤 + 訂單管理(REST API)
套件说明功能
@rytass/logistics
基础接口定义统一的物流服务接口
@rytass/logistics-adapter-tcat
黑猫宅急便包裹追踪(HTML 爬虫)
@rytass/logistics-adapter-ctc
中华宅配包裹追踪+订单管理(REST API)

Quick Start

快速开始

安裝

安装

bash
undefined
bash
undefined

黑貓宅急便

黑猫宅急便

npm install @rytass/logistics-adapter-tcat
npm install @rytass/logistics-adapter-tcat

中華宅配

中华宅配

npm install @rytass/logistics-adapter-ctc
undefined
npm install @rytass/logistics-adapter-ctc
undefined

黑貓宅急便追蹤

黑猫宅急便追踪

typescript
import { TCatLogisticsService, TCatLogistics } from '@rytass/logistics-adapter-tcat';

const logistics = new TCatLogisticsService(TCatLogistics);

// 追蹤單一包裹
const [result] = await logistics.trace('800978442950');
console.log(result.statusHistory);
// [{ date: '2024-01-15 14:30', status: 'DELIVERED', businessPremise: '台北營業所' }]

// 批量追蹤
const results = await logistics.trace(['800978442950', '903404283301']);
typescript
import { TCatLogisticsService, TCatLogistics } from '@rytass/logistics-adapter-tcat';

const logistics = new TCatLogisticsService(TCatLogistics);

// 追踪单个包裹
const [result] = await logistics.trace('800978442950');
console.log(result.statusHistory);
// [{ date: '2024-01-15 14:30', status: 'DELIVERED', businessPremise: '台北營業所' }]

// 批量追踪
const results = await logistics.trace(['800978442950', '903404283301']);

中華宅配追蹤與建單

中华宅配追踪与建单

⚠️ 安全警告:預設的
CtcLogistics
配置包含測試用的 API Token,請勿用於生產環境。務必使用您自己的 API Token。
typescript
import { CtcLogisticsService, CtcLogistics } from '@rytass/logistics-adapter-ctc';

// 使用預設設定(必須替換 apiToken)
const logistics = new CtcLogisticsService({
  ...CtcLogistics,
  apiToken: process.env.CTC_API_TOKEN!, // ⚠️ 必須替換為您的 API Token
});

// 追蹤包裹
const [result] = await logistics.trace('TRACKING-001');

// 建立託運單
const order = await logistics.create({
  senderCompany: '寄件公司',
  senderAddress: '台北市中正區重慶南路一段122號',
  senderMobile: '0912345678',
  receiverCompany: '收件公司',
  receiverContactName: '收件人',
  receiverAddress: '台北市信義區信義路五段7號',
  receiverMobile: '0987654321',
  paidCode: '客戶宅配',
});

console.log(order.shippingNumber); // 託運單號
console.log(order.trackingNumber); // 查件單號

// 更新託運單(需指定 trackingNumber)
const updatedOrder = await logistics.update({
  trackingNumber: 'TRACKING-001', // 必填:查件單號
  senderCompany: '新寄件公司',
  senderAddress: '台北市中正區重慶南路一段122號',
  senderMobile: '0912345678',
  receiverCompany: '新收件公司',
  receiverContactName: '新收件人',
  receiverAddress: '台北市信義區信義路五段7號',
  receiverMobile: '0987654321',
  paidCode: '客戶宅配',
});
⚠️ 安全警告:默认的
CtcLogistics
配置包含测试用的 API Token,请勿用于生产环境。务必使用您自己的 API Token。
typescript
import { CtcLogisticsService, CtcLogistics } from '@rytass/logistics-adapter-ctc';

// 使用默认配置(必须替换 apiToken)
const logistics = new CtcLogisticsService({
  ...CtcLogistics,
  apiToken: process.env.CTC_API_TOKEN!, // ⚠️ 必须替换为您的 API Token
});

// 追踪包裹
const [result] = await logistics.trace('TRACKING-001');

// 创建托运单
const order = await logistics.create({
  senderCompany: '寄件公司',
  senderAddress: '台北市中正區重慶南路一段122號',
  senderMobile: '0912345678',
  receiverCompany: '收件公司',
  receiverContactName: '收件人',
  receiverAddress: '台北市信義區信義路五段7號',
  receiverMobile: '0987654321',
  paidCode: '客戶宅配',
});

console.log(order.shippingNumber); // 托运单号
console.log(order.trackingNumber); // 查件单号

// 更新托运单(需指定 trackingNumber)
const updatedOrder = await logistics.update({
  trackingNumber: 'TRACKING-001', // 必填:查件单号
  senderCompany: '新寄件公司',
  senderAddress: '台北市中正區重慶南路一段122號',
  senderMobile: '0912345678',
  receiverCompany: '新收件公司',
  receiverContactName: '新收件人',
  receiverAddress: '台北市信義區信義路五段7號',
  receiverMobile: '0987654321',
  paidCode: '客戶宅配',
});

CTC 建單/更新選項

CTC 建单/更新选项

typescript
interface CreateOrUpdateCtcLogisticsOptions {
  // 基本資訊
  trackingNumber?: string;        // 查件單號(create 時可選,update 時必填)
  customerDepartmentId?: number;  // 客戶部門 ID
  customerDepartmentUnitId?: number; // 客戶部門單位 ID

  // 寄件人資訊
  senderCompany: string;          // 寄件人公司名稱(必填)
  senderContactName?: string;     // 寄件人聯絡人(預設同 senderCompany)
  senderAddress: string;          // 寄件人地址(必填)
  senderTel?: string;             // 寄件人市話(與 senderMobile 二擇一)
  senderMobile?: string;          // 寄件人手機(與 senderTel 二擇一)
  senderRemark?: string;          // 寄件人備註

  // 收件人資訊
  receiverCompany: string;        // 收件人公司名稱(必填)
  receiverContactName: string;    // 收件人聯絡人(必填)
  receiverAddress: string;        // 收件人地址(必填)
  receiverTel?: string;           // 收件人市話(與 receiverMobile 二擇一)
  receiverMobile?: string;        // 收件人手機(與 receiverTel 二擇一)
  receiverRemark?: string;        // 收件人備註

  // 運送資訊
  paidCode: string;                // 付款代碼(必填)
  shipmentContent?: string;       // 貨物內容(預設 '貨件')
  transportation?: string;        // 運輸工具(預設 'truck')
  shippingMethod?: string;        // 運送方式(預設 'land')
  payer?: string;                 // 費用支付方(預設 'receiver')
  shippingTime?: string;          // 送件時效(預設 'regular')
  paymentMethod?: string;         // 結算方式(預設 'monthly')
  quantity?: number;              // 件數(預設 1)
  weight?: number;                // 重量(預設 1)
  volume?: number;                // 材積(預設 1)
}

// 回傳結果
interface CtcLogisticsDto {
  trackingNumber?: string;  // 查件單號
  shippingNumber: string;   // 託運單號
}
typescript
interface CreateOrUpdateCtcLogisticsOptions {
  // 基本信息
  trackingNumber?: string;        // 查件单号(create 时可选,update 时必填)
  customerDepartmentId?: number;  // 客户部门 ID
  customerDepartmentUnitId?: number; // 客户部门单位 ID

  // 寄件人信息
  senderCompany: string;          // 寄件人公司名称(必填)
  senderContactName?: string;     // 寄件人联系人(默认同 senderCompany)
  senderAddress: string;          // 寄件人地址(必填)
  senderTel?: string;             // 寄件人电话(与 senderMobile 二选一)
  senderMobile?: string;          // 寄件人手机(与 senderTel 二选一)
  senderRemark?: string;          // 寄件人备注

  // 收件人信息
  receiverCompany: string;        // 收件人公司名称(必填)
  receiverContactName: string;    // 收件人联系人(必填)
  receiverAddress: string;        // 收件人地址(必填)
  receiverTel?: string;           // 收件人电话(与 receiverMobile 二选一)
  receiverMobile?: string;        // 收件人手机(与 receiverTel 二选一)
  receiverRemark?: string;        // 收件人备注

  // 运送信息
  paidCode: string;                // 付款代码(必填)
  shipmentContent?: string;       // 货物内容(默认 '貨件')
  transportation?: string;        // 运输工具(默认 'truck')
  shippingMethod?: string;        // 运送方式(默认 'land')
  payer?: string;                 // 费用支付方(默认 'receiver')
  shippingTime?: string;          // 送件时效(默认 'regular')
  paymentMethod?: string;         // 结算方式(默认 'monthly')
  quantity?: number;              // 件数(默认 1)
  weight?: number;                // 重量(默认 1)
  volume?: number;                // 材积(默认 1)
}

// 返回结果
interface CtcLogisticsDto {
  trackingNumber?: string;  // 查件单号
  shippingNumber: string;   // 托运单号
}

Core Concepts

核心概念

統一介面 LogisticsService

统一接口 LogisticsService

所有適配器都實現
LogisticsService
介面:
typescript
// 基礎物流介面
interface LogisticsInterface<T = LogisticsBaseStatus> {
  reference?: T;
  url: string;
}

// LogisticsService 介面(泛型約束較複雜)
interface LogisticsService<LogisticsType extends LogisticsInterface<LogisticsStatus<LogisticsType>>> {
  trace(request: string): Promise<LogisticsTraceResponse<LogisticsType>[]>;
  trace(request: string[]): Promise<LogisticsTraceResponse<LogisticsType>[]>;
}
所有适配器都实现
LogisticsService
接口:
typescript
// 基础物流接口
interface LogisticsInterface<T = LogisticsBaseStatus> {
  reference?: T;
  url: string;
}

// LogisticsService 接口(泛型约束较复杂)
interface LogisticsService<LogisticsType extends LogisticsInterface<LogisticsStatus<LogisticsType>>> {
  trace(request: string): Promise<LogisticsTraceResponse<LogisticsType>[]>;
  trace(request: string[]): Promise<LogisticsTraceResponse<LogisticsType>[]>;
}

追蹤結果結構

追踪结果结构

typescript
// 泛型約束較複雜,簡化理解:K 代表物流介面類型
interface LogisticsTraceResponse<K extends LogisticsInterface<LogisticsStatus<K>>> {
  logisticsId: string;                          // 追蹤號碼
  statusHistory: LogisticsStatusHistory<K['reference']>[];  // 狀態歷史
}

interface LogisticsStatusHistory<T> {
  date: string;    // 時間
  status: T;       // 狀態代碼(字串)
}

// T-CAT 擴展(包含營業所資訊)
interface TCatLogisticsStatusHistory<T> extends LogisticsStatusHistory<T> {
  businessPremise: string;  // 營業所名稱
}

// CTC 擴展(包含狀態碼)
interface CtcLogisticsStatusHistory<T> extends LogisticsStatusHistory<T> {
  statusCode: CtcLogisticsStatusEnum;  // 狀態碼(數字)
}

// CTC 狀態碼枚舉
enum CtcLogisticsStatusEnum {
  CREATED = 10,              // 新單
  PICKUP_EXCEPTION = 29,     // 取件異常
  PICKED_UP = 30,            // 已取件
  PICKUP_ARRIVED_AT_HUB = 40, // 取件到站
  IN_TRANSIT = 50,           // 轉運中
  TRANSIT_ARRIVED_AT_HUB = 60, // 轉運到站
  SHELVED = 65,              // 回站保管
  DELIVERING = 70,           // 配送中
  DELIVERY_EXCEPTION = 75,   // 配送異常
  DELIVERED = 80,            // 配送完成
  EMPTY_TRIP = 87,           // 空趟
  COMPLETED = 88,            // 正常結案
  NOTIFICATION_SENT = 91,    // 通知完成
  CANCELLED = 99,            // 取消
}
typescript
// 泛型约束较复杂,简化理解:K 代表物流接口类型
interface LogisticsTraceResponse<K extends LogisticsInterface<LogisticsStatus<K>>> {
  logisticsId: string;                          // 追踪号码
  statusHistory: LogisticsStatusHistory<K['reference']>[];  // 状态历史
}

interface LogisticsStatusHistory<T> {
  date: string;    // 时间
  status: T;       // 状态代码(字符串)
}

// T-CAT 扩展(包含营业所信息)
interface TCatLogisticsStatusHistory<T> extends LogisticsStatusHistory<T> {
  businessPremise: string;  // 营业所名称
}

// CTC 扩展(包含状态码)
interface CtcLogisticsStatusHistory<T> extends LogisticsStatusHistory<T> {
  statusCode: CtcLogisticsStatusEnum;  // 状态码(数字)
}

// CTC 状态码枚举
enum CtcLogisticsStatusEnum {
  CREATED = 10,              // 新单
  PICKUP_EXCEPTION = 29,     // 取件异常
  PICKED_UP = 30,            // 已取件
  PICKUP_ARRIVED_AT_HUB = 40, // 取件到站
  IN_TRANSIT = 50,           // 转运中
  TRANSIT_ARRIVED_AT_HUB = 60, // 转运到站
  SHELVED = 65,              // 回站保管
  DELIVERING = 70,           // 配送中
  DELIVERY_EXCEPTION = 75,   // 配送异常
  DELIVERED = 80,            // 配送完成
  EMPTY_TRIP = 87,           // 空趟
  COMPLETED = 88,            // 正常结案
  NOTIFICATION_SENT = 91,    // 通知完成
  CANCELLED = 99,            // 取消
}

基本狀態類型

基本状态类型

typescript
type LogisticsBaseStatus = 'DELIVERED' | 'DELIVERING' | 'SHELVED';

// 完整的 T-CAT 狀態類型(Union Type)
type TCatLogisticsStatus =
  | 'DELIVERED'
  | 'TRANSPORTING'
  | 'DELIVERING'
  | 'COLLECTING'
  | 'CONSOLIDATED'
  | 'PICKUP_CANCELED'
  | 'SHELVED'
  | 'INVESTIGATING'
  | 'DELIVERING_TODAY'
  | 'FAIL_PICKUP'
  | 'AWAY_HOME'
  | LogisticsBaseStatus;

// 完整的 CTC 狀態類型(Union Type)
type CtcLogisticsStatus =
  | 'CREATED'
  | 'PICKUP_EXCEPTION'
  | 'PICKED_UP'
  | 'PICKUP_ARRIVED_AT_HUB'
  | 'IN_TRANSIT'
  | 'TRANSIT_ARRIVED_AT_HUB'
  | 'SHELVED'
  | 'DELIVERING'
  | 'DELIVERY_EXCEPTION'
  | 'DELIVERED'
  | 'EMPTY_TRIP'
  | 'COMPLETED'
  | 'NOTIFICATION_SENT'
  | 'CANCELLED';
typescript
type LogisticsBaseStatus = 'DELIVERED' | 'DELIVERING' | 'SHELVED';

// 完整的 T-CAT 状态类型(联合类型)
type TCatLogisticsStatus =
  | 'DELIVERED'
  | 'TRANSPORTING'
  | 'DELIVERING'
  | 'COLLECTING'
  | 'CONSOLIDATED'
  | 'PICKUP_CANCELED'
  | 'SHELVED'
  | 'INVESTIGATING'
  | 'DELIVERING_TODAY'
  | 'FAIL_PICKUP'
  | 'AWAY_HOME'
  | LogisticsBaseStatus;

// 完整的 CTC 状态类型(联合类型)
type CtcLogisticsStatus =
  | 'CREATED'
  | 'PICKUP_EXCEPTION'
  | 'PICKED_UP'
  | 'PICKUP_ARRIVED_AT_HUB'
  | 'IN_TRANSIT'
  | 'TRANSIT_ARRIVED_AT_HUB'
  | 'SHELVED'
  | 'DELIVERING'
  | 'DELIVERY_EXCEPTION'
  | 'DELIVERED'
  | 'EMPTY_TRIP'
  | 'COMPLETED'
  | 'NOTIFICATION_SENT'
  | 'CANCELLED';

額外導出類型

额外导出类型

typescript
// 錯誤介面
interface LogisticsErrorInterface {
  readonly code: string;
  readonly message?: string;
}

// T-CAT 物流介面(可自訂 statusMap)
interface TCatLogisticsInterface<T> extends LogisticsInterface<T> {
  ignoreNotFound: boolean;
  statusMap: (html: string, id: string) => LogisticsStatusHistory<T>[];
}

// CTC 物流介面
interface CtcLogisticsInterface<T> extends LogisticsInterface<T> {
  apiToken: string;
  ignoreNotFound?: boolean;
}

// CTC 狀態對照表常數(可用於自訂映射)
const CtcLogisticsStatusMap: { [key: string]: CtcLogisticsStatus };

// CTC API 回應(內部使用,但有導出)
interface CreateOrUpdateCtcLogisticsResponse {
  success: boolean;
  error: string;
  shipping_number: string;
  tracking_number?: string;
}
typescript
// 错误接口
interface LogisticsErrorInterface {
  readonly code: string;
  readonly message?: string;
}

// T-CAT 物流接口(可自定义 statusMap)
interface TCatLogisticsInterface<T> extends LogisticsInterface<T> {
  ignoreNotFound: boolean;
  statusMap: (html: string, id: string) => LogisticsStatusHistory<T>[];
}

// CTC 物流接口
interface CtcLogisticsInterface<T> extends LogisticsInterface<T> {
  apiToken: string;
  ignoreNotFound?: boolean;
}

// CTC 状态对照表常量(可用于自定义映射)
const CtcLogisticsStatusMap: { [key: string]: CtcLogisticsStatus };

// CTC API 响应(内部使用,但已导出)
interface CreateOrUpdateCtcLogisticsResponse {
  success: boolean;
  error: string;
  shipping_number: string;
  tracking_number?: string;
}

Common Patterns

通用模式

T-CAT 狀態對照表

T-CAT 状态对照表

狀態中文原文說明
DELIVERED
順利送達包裹已成功送達
TRANSPORTING
轉運中包裹在轉運途中
DELIVERING
配送中配送員正在派送
COLLECTING
取件中正在取件
CONSOLIDATED
已集貨已完成集貨
PICKUP_CANCELED
取消取件取件已取消
SHELVED
暫置營業所暫存於營業所
INVESTIGATING
調查處理中正在調查處理
DELIVERING_TODAY
配送中(當配下車) (當配上車)當日配送中
FAIL_PICKUP
未順利取件,請洽客服中心取件失敗
AWAY_HOME
不在家.公司行號休息收件人不在
状态中文说明说明
DELIVERED
顺利送达包裹已成功送达
TRANSPORTING
转运中包裹在转运途中
DELIVERING
配送中配送员正在派送
COLLECTING
取件中正在取件
CONSOLIDATED
已集货已完成集货
PICKUP_CANCELED
取消取件取件已取消
SHELVED
暂置营业所暂存于营业所
INVESTIGATING
调查处理中正在调查处理
DELIVERING_TODAY
配送中(当配下车) (当配上车)当日配送中
FAIL_PICKUP
未顺利取件,请洽客服中心取件失败
AWAY_HOME
不在家.公司行号休息收件人不在

CTC 狀態對照表

CTC 状态对照表

狀態狀態碼說明
CREATED
10新單
PICKUP_EXCEPTION
29取件異常
PICKED_UP
30已取件
PICKUP_ARRIVED_AT_HUB
40取件到站
IN_TRANSIT
50轉運中
TRANSIT_ARRIVED_AT_HUB
60轉運到站
SHELVED
65回站保管
DELIVERING
70配送中
DELIVERY_EXCEPTION
75配送異常
DELIVERED
80配送完成
EMPTY_TRIP
87空趟
COMPLETED
88正常結案
NOTIFICATION_SENT
91通知完成
CANCELLED
99取消
状态状态码说明
CREATED
10新单
PICKUP_EXCEPTION
29取件异常
PICKED_UP
30已取件
PICKUP_ARRIVED_AT_HUB
40取件到站
IN_TRANSIT
50转运中
TRANSIT_ARRIVED_AT_HUB
60转运到站
SHELVED
65回站保管
DELIVERING
70配送中
DELIVERY_EXCEPTION
75配送异常
DELIVERED
80配送完成
EMPTY_TRIP
87空趟
COMPLETED
88正常结案
NOTIFICATION_SENT
91通知完成
CANCELLED
99取消

錯誤處理

错误处理

typescript
import { LogisticsError, ErrorCode } from '@rytass/logistics';

// ErrorCode 枚舉
enum ErrorCode {
  NOT_IMPLEMENTED = '999',   // 未實作
  NOT_FOUND_ERROR = '101',   // 找不到包裹
  PERMISSION_DENIED = '102', // 無權查詢
  INVALID_PARAMETER = '103', // 無效參數
}

try {
  const result = await logistics.trace('INVALID');
} catch (error) {
  if (error instanceof LogisticsError) {
    switch (error.code) {
      case ErrorCode.NOT_FOUND_ERROR:
        console.error('找不到此包裹');
        break;
      case ErrorCode.PERMISSION_DENIED:
        console.error('無權查詢');
        break;
      case ErrorCode.INVALID_PARAMETER:
        console.error('無效的追蹤號碼');
        break;
      case ErrorCode.NOT_IMPLEMENTED:
        console.error('功能未實作');
        break;
    }
  }
}
typescript
import { LogisticsError, ErrorCode } from '@rytass/logistics';

// ErrorCode 枚举
enum ErrorCode {
  NOT_IMPLEMENTED = '999',   // 未实现
  NOT_FOUND_ERROR = '101',   // 找不到包裹
  PERMISSION_DENIED = '102', // 无权查询
  INVALID_PARAMETER = '103', // 无效参数
}

try {
  const result = await logistics.trace('INVALID');
} catch (error) {
  if (error instanceof LogisticsError) {
    switch (error.code) {
      case ErrorCode.NOT_FOUND_ERROR:
        console.error('找不到此包裹');
        break;
      case ErrorCode.PERMISSION_DENIED:
        console.error('无权查询');
        break;
      case ErrorCode.INVALID_PARAMETER:
        console.error('无效的追踪号码');
        break;
      case ErrorCode.NOT_IMPLEMENTED:
        console.error('功能未实现');
        break;
    }
  }
}

忽略找不到錯誤

忽略未找到错误

typescript
// T-CAT 預設 ignoreNotFound: false
const tcatLogistics = new TCatLogisticsService({
  ...TCatLogistics,  // 預設 ignoreNotFound: false
  ignoreNotFound: true,  // 找不到時返回空歷史而非拋出錯誤
});

// CTC 預設 ignoreNotFound: true
const ctcLogistics = new CtcLogisticsService({
  ...CtcLogistics,  // 預設 ignoreNotFound: true
  apiToken: 'your-token',
  ignoreNotFound: false,  // 改為找不到時拋出錯誤
});
typescript
// T-CAT 默认 ignoreNotFound: false
const tcatLogistics = new TCatLogisticsService({
  ...TCatLogistics,  // 默认 ignoreNotFound: false
  ignoreNotFound: true,  // 找不到时返回空历史而非抛出错误
});

// CTC 默认 ignoreNotFound: true
const ctcLogistics = new CtcLogisticsService({
  ...CtcLogistics,  // 默认 ignoreNotFound: true
  apiToken: 'your-token',
  ignoreNotFound: false,  // 改为找不到时抛出错误
});

API Reference

API 参考

詳細 API 文件請參閱 reference.md
详细 API 文档请参考 reference.md

Troubleshooting

问题排查

T-CAT 追蹤失敗

T-CAT 追踪失败

T-CAT 使用 HTML 爬蟲,可能因網站改版而失效。檢查:
  1. 網站是否可正常訪問
  2. HTML 結構是否變更
  3. 考慮使用自訂
    statusMap
    函數
T-CAT 使用 HTML 爬虫,可能因网站改版而失效。检查:
  1. 网站是否可正常访问
  2. HTML 结构是否变更
  3. 考虑使用自定义
    statusMap
    函数

CTC API 認證失敗

CTC API 认证失败

  1. 確認
    apiToken
    正確
  2. 檢查 API 端點 URL
  3. 確認帳戶有對應權限
  1. 确认
    apiToken
    正确
  2. 检查 API 端点 URL
  3. 确认账户有对应权限

批量追蹤效能

批量追踪性能

批量追蹤使用
Promise.all
,注意:
  • 避免一次追蹤過多包裹
  • 考慮分批處理大量請求
  • 設置適當的超時時間
批量追踪使用
Promise.all
,注意:
  • 避免一次追踪过多包裹
  • 考虑分批处理大量请求
  • 设置适当的超时时间