7.4 KiB
7.4 KiB
物流追踪系统 - 问题修复
已修复的问题
1. 命令未注册错误 ✅
问题:
[InvalidArgumentException]
There are no commands defined in the "express" namespace.
原因:
命令未在 server/config/console.php 中注册。
解决方案:
已在 server/config/console.php 中添加命令注册:
'commands' => [
// ... 其他命令
'express:auto-update' => 'app\command\ExpressAutoUpdate',
],
验证:
cd server
php think express:auto-update
2. 已签收订单过滤优化 ✅
问题: 定时任务可能会处理已签收的快递,浪费查询次数。
解决方案:
优化了 ExpressTrackingService::autoUpdateBatch() 方法的查询条件:
$list = ExpressTracking::where('auto_update', 1)
->where('next_update_time', '<=', $now)
->where('is_signed', 0) // 【新增】未签收
->whereNotIn('current_state', [ // 【新增】排除终态
ExpressTracking::STATE_SIGNED, // 已签收
ExpressTracking::STATE_RETURN_SIGNED, // 退签
ExpressTracking::STATE_REJECTED, // 拒签
])
->whereNull('delete_time')
->limit($limit)
->select();
过滤规则:
| 条件 | 说明 |
|---|---|
auto_update = 1 |
启用自动更新 |
next_update_time <= now |
到达更新时间 |
is_signed = 0 |
未签收 |
current_state NOT IN (3,4,14) |
排除终态(已签收、退签、拒签) |
delete_time IS NULL |
未删除 |
会被处理的状态:
- 0: 在途
- 1: 揽收
- 2: 疑难
- 5: 派件中
- 6: 退回
- 7: 转投
- 8: 清关
- 10: 待清关
- 11: 清关中
- 12: 已清关
- 13: 清关异常
不会被处理的状态:
- 3: 已签收 ❌
- 4: 退签 ❌
- 14: 拒签 ❌
自动停止更新机制
触发条件
当快递状态变为以下任一状态时,系统会自动停止更新:
// 在 ExpressTrackingService::queryAndUpdate() 中
if (ExpressTracking::isFinalState($tracking->current_state)) {
$tracking->is_signed = 1;
$tracking->sign_time = $now;
$tracking->auto_update = 0; // 自动停止更新
}
终态判断
public static function isFinalState(string $state): bool
{
return in_array($state, [
self::STATE_SIGNED, // 3: 已签收
self::STATE_RETURN_SIGNED, // 4: 退签
self::STATE_REJECTED, // 14: 拒签
], true);
}
双重保护机制
系统采用双重保护,确保已签收的快递不会被重复查询:
第一层:查询时过滤
在 autoUpdateBatch() 方法中,查询时就排除了终态订单:
->where('is_signed', 0)
->whereNotIn('current_state', ['3', '4', '14'])
第二层:更新时自动停止
在 queryAndUpdate() 方法中,当检测到签收时自动停止:
if (ExpressTracking::isFinalState($tracking->current_state)) {
$tracking->auto_update = 0;
$tracking->save();
}
测试验证
1. 测试命令注册
cd server
php think list
# 应该能看到:
# express
# express:auto-update 自动更新物流追踪信息
2. 测试过滤逻辑
cd server
php test_express_auto_update.php
# 查看输出,确认过滤规则正确
3. 测试实际执行
cd server
php think express:auto-update
# 应该看到:
# 开始自动更新物流信息...
# 更新完成!
# 总数: X
# 成功: X
# 失败: 0
# 耗时: X秒
性能优化
查询优化
通过添加过滤条件,减少了不必要的查询:
优化前:
- 查询所有
auto_update = 1的记录 - 包括已签收的快递
- 浪费查询次数
优化后:
- 只查询未签收且未到达终态的记录
- 自动排除已签收的快递
- 节省查询次数和API费用
索引建议
确保以下字段有索引:
-- 复合索引(最重要)
CREATE INDEX idx_auto_update_query
ON zyt_express_tracking(auto_update, next_update_time, is_signed, current_state);
-- 单字段索引
CREATE INDEX idx_is_signed ON zyt_express_tracking(is_signed);
CREATE INDEX idx_current_state ON zyt_express_tracking(current_state);
监控建议
1. 监控自动更新执行情况
# 查看定时任务日志
tail -f server/runtime/log/info.log | grep "Auto update"
# 查看错误日志
tail -f server/runtime/log/error.log | grep "express"
2. 统计查询情况
-- 查看自动更新的记录数
SELECT COUNT(*) as count
FROM zyt_express_tracking
WHERE auto_update = 1
AND is_signed = 0
AND current_state NOT IN ('3', '4', '14')
AND delete_time IS NULL;
-- 查看已签收的记录数
SELECT COUNT(*) as count
FROM zyt_express_tracking
WHERE is_signed = 1;
-- 查看各状态分布
SELECT
current_state,
current_state_text,
COUNT(*) as count,
SUM(auto_update) as auto_update_count
FROM zyt_express_tracking
WHERE delete_time IS NULL
GROUP BY current_state, current_state_text
ORDER BY count DESC;
3. 查询日志分析
-- 查看最近的查询记录
SELECT
tracking_number,
query_type,
is_success,
error_message,
FROM_UNIXTIME(query_time) as query_time
FROM zyt_express_query_log
ORDER BY query_time DESC
LIMIT 20;
-- 统计自动查询成功率
SELECT
DATE(FROM_UNIXTIME(query_time)) as date,
COUNT(*) as total,
SUM(is_success) as success,
ROUND(SUM(is_success) / COUNT(*) * 100, 2) as success_rate
FROM zyt_express_query_log
WHERE query_type = 'auto'
GROUP BY date
ORDER BY date DESC
LIMIT 7;
常见问题
Q1: 命令执行后显示 "总数: 0"?
A: 这是正常的,说明:
- 没有需要更新的快递记录
- 或所有快递都已签收
- 或还没到更新时间
检查:
SELECT
COUNT(*) as total,
SUM(CASE WHEN auto_update = 1 THEN 1 ELSE 0 END) as auto_update_enabled,
SUM(CASE WHEN is_signed = 1 THEN 1 ELSE 0 END) as signed,
SUM(CASE WHEN next_update_time <= UNIX_TIMESTAMP() THEN 1 ELSE 0 END) as need_update
FROM zyt_express_tracking
WHERE delete_time IS NULL;
Q2: 已签收的快递还在被查询?
A: 检查以下几点:
- 确认代码已更新到最新版本
- 检查
is_signed字段是否正确设置 - 检查
auto_update字段是否为 0
修复:
-- 手动修复已签收但未停止更新的记录
UPDATE zyt_express_tracking
SET auto_update = 0
WHERE current_state IN ('3', '4', '14')
AND auto_update = 1;
Q3: 如何手动停止某个快递的自动更新?
A:
UPDATE zyt_express_tracking
SET auto_update = 0
WHERE tracking_number = 'JD0230761381812';
或通过代码:
$tracking = ExpressTracking::where('tracking_number', 'JD0230761381812')->find();
$tracking->auto_update = 0;
$tracking->save();
总结
已修复
- ✅ 命令注册问题
- ✅ 已签收订单过滤
- ✅ 双重保护机制
- ✅ 性能优化
优势
- 节省费用 - 不查询已签收的快递
- 提高效率 - 只处理需要更新的记录
- 自动停止 - 签收后自动停止更新
- 双重保护 - 查询和更新两层过滤
下一步
- ✅ 执行
php think express:auto-update测试 - ✅ 配置crontab定时任务
- ✅ 监控执行情况
- ✅ 查看查询日志
相关文档
EXPRESS_TRACKING_SYSTEM.md- 完整系统文档EXPRESS_TRACKING_QUICKSTART.md- 快速开始指南KUAIDI100_ACCOUNT_ISSUE.md- 快递100账号问题