366 lines
7.4 KiB
Markdown
366 lines
7.4 KiB
Markdown
# 物流追踪系统 - 问题修复
|
||
|
||
## 已修复的问题
|
||
|
||
### 1. 命令未注册错误 ✅
|
||
|
||
**问题:**
|
||
```
|
||
[InvalidArgumentException]
|
||
There are no commands defined in the "express" namespace.
|
||
```
|
||
|
||
**原因:**
|
||
命令未在 `server/config/console.php` 中注册。
|
||
|
||
**解决方案:**
|
||
已在 `server/config/console.php` 中添加命令注册:
|
||
|
||
```php
|
||
'commands' => [
|
||
// ... 其他命令
|
||
'express:auto-update' => 'app\command\ExpressAutoUpdate',
|
||
],
|
||
```
|
||
|
||
**验证:**
|
||
```bash
|
||
cd server
|
||
php think express:auto-update
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 已签收订单过滤优化 ✅
|
||
|
||
**问题:**
|
||
定时任务可能会处理已签收的快递,浪费查询次数。
|
||
|
||
**解决方案:**
|
||
优化了 `ExpressTrackingService::autoUpdateBatch()` 方法的查询条件:
|
||
|
||
```php
|
||
$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: 拒签 ❌
|
||
|
||
---
|
||
|
||
## 自动停止更新机制
|
||
|
||
### 触发条件
|
||
|
||
当快递状态变为以下任一状态时,系统会自动停止更新:
|
||
|
||
```php
|
||
// 在 ExpressTrackingService::queryAndUpdate() 中
|
||
if (ExpressTracking::isFinalState($tracking->current_state)) {
|
||
$tracking->is_signed = 1;
|
||
$tracking->sign_time = $now;
|
||
$tracking->auto_update = 0; // 自动停止更新
|
||
}
|
||
```
|
||
|
||
### 终态判断
|
||
|
||
```php
|
||
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()` 方法中,查询时就排除了终态订单:
|
||
|
||
```php
|
||
->where('is_signed', 0)
|
||
->whereNotIn('current_state', ['3', '4', '14'])
|
||
```
|
||
|
||
### 第二层:更新时自动停止
|
||
|
||
在 `queryAndUpdate()` 方法中,当检测到签收时自动停止:
|
||
|
||
```php
|
||
if (ExpressTracking::isFinalState($tracking->current_state)) {
|
||
$tracking->auto_update = 0;
|
||
$tracking->save();
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试验证
|
||
|
||
### 1. 测试命令注册
|
||
|
||
```bash
|
||
cd server
|
||
php think list
|
||
|
||
# 应该能看到:
|
||
# express
|
||
# express:auto-update 自动更新物流追踪信息
|
||
```
|
||
|
||
### 2. 测试过滤逻辑
|
||
|
||
```bash
|
||
cd server
|
||
php test_express_auto_update.php
|
||
|
||
# 查看输出,确认过滤规则正确
|
||
```
|
||
|
||
### 3. 测试实际执行
|
||
|
||
```bash
|
||
cd server
|
||
php think express:auto-update
|
||
|
||
# 应该看到:
|
||
# 开始自动更新物流信息...
|
||
# 更新完成!
|
||
# 总数: X
|
||
# 成功: X
|
||
# 失败: 0
|
||
# 耗时: X秒
|
||
```
|
||
|
||
---
|
||
|
||
## 性能优化
|
||
|
||
### 查询优化
|
||
|
||
通过添加过滤条件,减少了不必要的查询:
|
||
|
||
**优化前:**
|
||
- 查询所有 `auto_update = 1` 的记录
|
||
- 包括已签收的快递
|
||
- 浪费查询次数
|
||
|
||
**优化后:**
|
||
- 只查询未签收且未到达终态的记录
|
||
- 自动排除已签收的快递
|
||
- 节省查询次数和API费用
|
||
|
||
### 索引建议
|
||
|
||
确保以下字段有索引:
|
||
|
||
```sql
|
||
-- 复合索引(最重要)
|
||
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. 监控自动更新执行情况
|
||
|
||
```bash
|
||
# 查看定时任务日志
|
||
tail -f server/runtime/log/info.log | grep "Auto update"
|
||
|
||
# 查看错误日志
|
||
tail -f server/runtime/log/error.log | grep "express"
|
||
```
|
||
|
||
### 2. 统计查询情况
|
||
|
||
```sql
|
||
-- 查看自动更新的记录数
|
||
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. 查询日志分析
|
||
|
||
```sql
|
||
-- 查看最近的查询记录
|
||
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:** 这是正常的,说明:
|
||
1. 没有需要更新的快递记录
|
||
2. 或所有快递都已签收
|
||
3. 或还没到更新时间
|
||
|
||
**检查:**
|
||
```sql
|
||
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:** 检查以下几点:
|
||
1. 确认代码已更新到最新版本
|
||
2. 检查 `is_signed` 字段是否正确设置
|
||
3. 检查 `auto_update` 字段是否为 0
|
||
|
||
**修复:**
|
||
```sql
|
||
-- 手动修复已签收但未停止更新的记录
|
||
UPDATE zyt_express_tracking
|
||
SET auto_update = 0
|
||
WHERE current_state IN ('3', '4', '14')
|
||
AND auto_update = 1;
|
||
```
|
||
|
||
### Q3: 如何手动停止某个快递的自动更新?
|
||
|
||
**A:**
|
||
```sql
|
||
UPDATE zyt_express_tracking
|
||
SET auto_update = 0
|
||
WHERE tracking_number = 'JD0230761381812';
|
||
```
|
||
|
||
或通过代码:
|
||
```php
|
||
$tracking = ExpressTracking::where('tracking_number', 'JD0230761381812')->find();
|
||
$tracking->auto_update = 0;
|
||
$tracking->save();
|
||
```
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
### 已修复
|
||
|
||
1. ✅ 命令注册问题
|
||
2. ✅ 已签收订单过滤
|
||
3. ✅ 双重保护机制
|
||
4. ✅ 性能优化
|
||
|
||
### 优势
|
||
|
||
1. **节省费用** - 不查询已签收的快递
|
||
2. **提高效率** - 只处理需要更新的记录
|
||
3. **自动停止** - 签收后自动停止更新
|
||
4. **双重保护** - 查询和更新两层过滤
|
||
|
||
### 下一步
|
||
|
||
1. ✅ 执行 `php think express:auto-update` 测试
|
||
2. ✅ 配置crontab定时任务
|
||
3. ✅ 监控执行情况
|
||
4. ✅ 查看查询日志
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
- `EXPRESS_TRACKING_SYSTEM.md` - 完整系统文档
|
||
- `EXPRESS_TRACKING_QUICKSTART.md` - 快速开始指南
|
||
- `KUAIDI100_ACCOUNT_ISSUE.md` - 快递100账号问题
|