# SF快递物流状态判断指南 > **作者**: 阿瑞 > **版本**: 1.0.0 > **更新时间**: 2025-01-28 ## 📖 概述 本文档详细介绍了如何在SF快递物流查询系统中准确判断和显示物流状态。基于SF快递官方API文档和实际开发经验总结。 ## 🔍 状态判断数据源 ### 官方标准数据结构 根据SF快递官方API文档,完整的路由节点应包含以下状态信息: ```typescript interface RouteInfo { acceptTime: string; // 路由节点发生时间 acceptAddress: string; // 路由节点发生地点 remark: string; // 路由节点具体描述 opCode: string; // 路由节点操作码 firstStatusCode?: string; // 一级状态编码 firstStatusName?: string; // 一级状态名称 secondaryStatusCode?: string; // 二级状态编码 secondaryStatusName?: string; // 二级状态名称 } ``` ### 数据完整性检查 实际API返回的数据可能缺少状态编码字段,需要多种备用方案: | 字段 | 重要程度 | 描述 | |------|----------|------| | `firstStatusName` | ⭐⭐⭐ | 官方一级状态,最准确 | | `secondaryStatusName` | ⭐⭐⭐ | 官方二级状态,最详细 | | `opCode` | ⭐⭐ | 操作码,可映射到状态 | | `remark` | ⭐ | 文本描述,可通过关键词分析 | ## 🎯 状态判断方法 ### 方法一:官方状态字段(推荐) **优先级:最高** ```javascript if (route.firstStatusName) { return route.firstStatusName; // 直接使用官方状态 } ``` **常见状态值:** - `待揽收` - 快件等待收取 - `已揽收` - 快件已被收取 - `运输中` - 快件正在运输 - `派送中` - 快件正在派送 - `已签收` - 快件成功签收 - `已拒收` - 快件被拒收 - `退回中` - 快件正在退回 - `已退回` - 快件已退回发件人 ### 方法二:opCode映射表(备用) **优先级:中等** > ✅ **数据来源**: 基于真实SF快递物流数据分析,包含完整快递生命周期的opCode对应关系。 > > 📋 **数据样本**: 分析了从揽收到退回成功的47个物流节点,包含以下新发现的opCode: > - `43`: 已收取(重复确认) > - `302`: 长途运输(显示距离信息) > - `310`: 途经中转(城市中转点) > - `44`: 准备派送(分配快递员) > - `204`: 派送中(具体快递员信息) > - `70`: 派送失败(多种失败原因) > - `33`: 待派送(约定时间) > - `517`: 退回申请中(客户申请) > - `99`: 退回中(实际退回过程) > - `80`: 退回成功(最终完成) ```javascript const statusMap = { // ========== 揽收相关 ========== '54': { status: '已揽收', color: 'blue', description: '快件已被顺丰收取' }, '43': { status: '已收取', color: 'blue', description: '顺丰速运已收取快件' }, // ========== 分拣运输相关 ========== '30': { status: '分拣中', color: 'processing', description: '快件正在分拣处理' }, '36': { status: '运输中', color: 'processing', description: '快件正在运输途中' }, '31': { status: '到达网点', color: 'processing', description: '快件已到达转运中心' }, '302': { status: '长途运输', color: 'processing', description: '快件正在安全运输中(长距离)' }, '310': { status: '途经中转', color: 'processing', description: '快件途经中转城市' }, // ========== 派送相关 ========== '44': { status: '准备派送', color: 'processing', description: '正在为快件分配合适的快递员' }, '204': { status: '派送中', color: 'processing', description: '快件已交给快递员,正在派送途中' }, '70': { status: '派送失败', color: 'warning', description: '快件派送不成功,待再次派送' }, '33': { status: '待派送', color: 'warning', description: '已与客户约定新派送时间,待派送' }, // ========== 退回相关 ========== '517': { status: '退回申请中', color: 'warning', description: '快件退回申请已提交,正在处理中' }, '99': { status: '退回中', color: 'warning', description: '应客户要求,快件正在退回中' }, '80': { status: '退回成功', color: 'success', description: '退回快件已派送成功' }, // ========== 签收相关 ========== '81': { status: '已签收', color: 'success', description: '快件已成功签收' }, '82': { status: '已拒收', color: 'error', description: '快件被拒收' }, // ========== 其他状态 ========== '655': { status: '待揽收', color: 'default', description: '快件等待揽收' }, '701': { status: '待揽收', color: 'default', description: '快件等待揽收' }, '101': { status: '已揽收', color: 'blue', description: '快件已揽收' }, }; ``` ### 方法三:文本关键词分析(最后备用) **优先级:最低** ```javascript const analyzeStatusByRemark = (remark) => { const text = remark.toLowerCase(); // 揽收相关 if (text.includes('已收取快件') || text.includes('已揽收')) { return { status: '已揽收', color: 'blue' }; } // 分拣相关 if (text.includes('完成分拣')) { return { status: '分拣中', color: 'processing' }; } // 运输相关 if (text.includes('离开') || text.includes('发往') || text.includes('路上') || text.includes('安全运输中')) { return { status: '运输中', color: 'processing' }; } if (text.includes('途经')) { return { status: '途经中转', color: 'processing' }; } if (text.includes('到达')) { return { status: '到达网点', color: 'processing' }; } // 派送相关 if (text.includes('分配最合适的快递员')) { return { status: '准备派送', color: 'processing' }; } if (text.includes('交给') && text.includes('正在派送途中')) { return { status: '派送中', color: 'processing' }; } if (text.includes('派送不成功') || text.includes('约定新派送时间')) { return { status: '派送失败', color: 'warning' }; } if (text.includes('待派送')) { return { status: '待派送', color: 'warning' }; } // 签收相关 if (text.includes('派送成功') || text.includes('签收')) { return { status: '已签收', color: 'success' }; } if (text.includes('拒收') || text.includes('拒付费用')) { return { status: '已拒收', color: 'error' }; } // 退回相关 if (text.includes('退回申请已提交')) { return { status: '退回申请中', color: 'warning' }; } if (text.includes('快件正在退回中') || text.includes('应客户要求')) { return { status: '退回中', color: 'warning' }; } if (text.includes('退回快件已派送成功')) { return { status: '退回成功', color: 'success' }; } return { status: '处理中', color: 'default' }; }; ``` ## 🔄 状态判断流程图 ```mermaid graph TD A[接收路由数据] --> B{是否有firstStatusName?} B -->|有| C[使用官方一级状态] B -->|无| D{是否有opCode?} D -->|有| E[查询opCode映射表] D -->|无| F[分析remark文本] E --> G{映射表中存在?} G -->|是| H[返回映射状态] G -->|否| F F --> I[返回文本分析结果] C --> J[状态判断完成] H --> J I --> J ``` ## 🎨 UI状态显示规范 ### 状态颜色映射 | 状态类型 | 颜色 | CSS类 | 含义 | |----------|------|-------|------| | 已签收 | 🟢 绿色 | `bg-green-100 text-green-700` | 成功完成 | | 已拒收/已退回 | 🔴 红色 | `bg-red-100 text-red-700` | 失败/异常 | | 退回中 | 🟡 黄色 | `bg-yellow-100 text-yellow-700` | 警告状态 | | 运输中/派送中 | 🔵 蓝色 | `bg-blue-100 text-blue-700` | 进行中 | | 待揽收/处理中 | ⚪ 灰色 | `bg-gray-100 text-gray-700` | 等待/默认 | ### 时间轴节点显示 ```jsx // 状态标签 {status} // 详细信息