feat: 运单号识别后自动推断快递公司并显示中文名称

- 新增运单号前缀映射表覆盖安能/圆通/顺丰/申通/中通/韵达等
- 前端运单卡片显示快递公司中文名而非编码

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
taiyi 2026-06-08 18:40:46 +08:00
parent 4078be3bfc
commit e7473fc757
2 changed files with 45 additions and 3 deletions

View File

@ -741,7 +741,11 @@ class LogisticsService:
if barcodes and not tracking_number:
tracking_number = str(barcodes[0]).strip()
logger.info("[recognize_waybill] 快递100识别成功: %s, code=%s", tracking_number, result.get("code"))
# 6. 根据运单号前缀推断快递公司
if tracking_number:
express_company, express_name = self._guess_express_by_tracking(tracking_number)
logger.info("[recognize_waybill] 快递100识别成功: %s, company=%s", tracking_number, express_name)
except Exception as exc:
logger.warning("[recognize_waybill] 快递100 OCR 失败,将返回空结果: %s", exc)
raw_result = {"error": str(exc)}
@ -754,6 +758,44 @@ class LogisticsService:
"raw_result": raw_result,
}
# 常见快递公司运单号前缀映射
_EXPRESS_PREFIX_MAP = [
("610", "ane", "安能物流"),
("773", "ane", "安能物流"),
("YT", "yuantong", "圆通速递"),
("SF", "shunfeng", "顺丰速运"),
("77", "shunfeng", "顺丰速运"),
("75", "shentong", "申通快递"),
("76", "shentong", "申通快递"),
("78", "zhongtong", "中通快递"),
("268", "zhongtong", "中通快递"),
("310", "yunda", "韵达快递"),
("468", "yunda", "韵达快递"),
("55", "yunda", "韵达快递"),
("228", "yunda", "韵达快递"),
("57", "jd", "京东物流"),
("JD", "jd", "京东物流"),
("D", "debang", "德邦快递"),
("dpk", "debang", "德邦快递"),
("33", "zhaijisong", "宅急送"),
("EM", "ems", "EMS"),
("E", "ems", "EMS"),
("CN", "guoji", "国际包裹"),
]
@staticmethod
def _guess_express_by_tracking(tracking_number: str) -> tuple[str, str]:
"""根据运单号前缀推断快递公司编码和名称。
Returns:
(express_company, express_name) 元组未匹配时返回空字符串
"""
tn = tracking_number.upper().strip()
for prefix, code, name in LogisticsService._EXPRESS_PREFIX_MAP:
if tn.startswith(prefix):
return code, name
return "", ""
def submit_waybills(self, task_id: int, payload: dict, session: Session | None = None, current_user: dict | None = None) -> dict:
"""批量提交运单号,校验任务状态。"""
if session is None:

View File

@ -65,7 +65,7 @@
<view wx:for="{{waybillList}}" wx:key="index" class="waybill-item">
<view class="waybill-info">
<view class="waybill-number">{{item.tracking_number || '未识别'}}</view>
<view class="waybill-company" wx:if="{{item.express_company}}">{{item.express_company}}</view>
<view class="waybill-company" wx:if="{{item.express_name}}">{{item.express_name}}</view>
<view class="waybill-confidence" wx:if="{{item.confidence > 0 && item.confidence < 0.8}}">识别置信度较低,请核对</view>
</view>
<view class="waybill-actions">
@ -113,7 +113,7 @@
<view wx:for="{{waybillList}}" wx:key="index" class="waybill-item waybill-item-readonly">
<view class="waybill-info">
<view class="waybill-number">{{item.tracking_number}}</view>
<view class="waybill-company" wx:if="{{item.express_company}}">{{item.express_company}}</view>
<view class="waybill-company" wx:if="{{item.express_name}}">{{item.express_name}}</view>
</view>
<view class="waybill-status-badge" wx:if="{{item.status}}">{{item.status}}</view>
</view>