# 派单失败问题修复指南 ## 问题概述 用户下单支付后,派单返回 `ALL_ELIGIBLE_STAFF_BUSY`(当前可服务人员均在忙),导致无法成功派单。 ## 根本原因 ### 原因 1:订单缺少服务经纬度(已修复) **问题**:`createServiceOrder` 函数在创建订单时,没有将地址的经纬度写入 `service_lat` 和 `service_lng` 字段。 **影响**: - 派单 RPC 无法计算人员距离 - 距离筛选条件失效 - 可能匹配到远距离人员 **修复**:`serviceOrderService.uts` 第 1181-1182 行新增: ```typescript service_lat: params.address.latitude != null ? params.address.latitude : null, service_lng: params.address.longitude != null ? params.address.longitude : null, ``` ### 原因 2:时间冲突检查过于严格(待数据库执行) **问题**:原 RPC 函数中,当订单 `scheduled_start_at` 或 `scheduled_end_at` 为 `NULL` 时,时间冲突检查条件会**跳过比较**,但 `NOT EXISTS` 子查询仍然会排除**任何有活跃任务**的人员。 **原逻辑**(第 633-655 行): ```sql AND NOT EXISTS ( SELECT 1 FROM hss_service_assignments existing_assignment JOIN hss_service_orders existing_order ON existing_order.id = existing_assignment.order_id WHERE existing_assignment.staff_id::TEXT = s.id::TEXT AND existing_assignment.deleted_at IS NULL AND existing_assignment.status IN ('assigned', 'accepted', ...) AND ( v_order.scheduled_start_at IS NULL -- 如果订单没有时间 OR v_order.scheduled_end_at IS NULL -- 则跳过比较 OR ...时间重叠判断... ) ) ``` **问题**:当 `v_order.scheduled_start_at IS NULL` 时,整个 `AND` 条件变为 `TRUE`,导致**所有有活跃任务的人员都被排除**。 **修复**:新增优化版 RPC `rpc_homecare_auto_dispatch_optimized`,只有当订单有**明确时间范围**时才检查时间冲突。 ## 修复步骤 ### 第一步:执行诊断脚本(可选,用于确认问题) 在 Supabase SQL Editor 中执行: ``` mall_sql/diagnostics/dispatch_failure_diagnosis.sql ``` 重点关注: 1. 问题订单的 `service_lat`/`service_lng` 是否为 `NULL` 2. 有哪些服务人员在忙(有活跃派单记录) ### 第二步:修复历史订单的经纬度 在 Supabase SQL Editor 中执行: ``` mall_sql/migrations/20260610_fix_service_order_coordinates.sql ``` 此脚本会: 1. 统计有多少订单缺少经纬度 2. 从 `address_snapshot_json` 中提取经纬度并更新到主表字段 ### 第三步:部署优化版派单 RPC 在 Supabase SQL Editor 中执行: ``` mall_sql/migrations/20260610_optimize_dispatch_conflict_check.sql ``` 此脚本会创建新的 RPC 函数 `rpc_homecare_auto_dispatch_optimized`。 ### 第四步:切换使用优化版 RPC ✅ 已完成 修改前端调用优化版 RPC 函数。 **文件**:`serviceOrderService.uts` 第 1015 行 **修改前**: ```typescript const { data, error } = await supa.rpc('rpc_homecare_auto_dispatch', { p_order_id: orderId } as any) ``` **修改后**: ```typescript const { data, error } = await supa.rpc('rpc_homecare_auto_dispatch_optimized', { p_order_id: orderId } as any) ``` > ✅ 此步骤已完成,前端已切换使用优化版 RPC。 ## 验证方法 ### 1. 检查订单经纬度是否已填充 ```sql SELECT id, service_lat, service_lng, address_snapshot_json->>'latitude' as address_lat, address_snapshot_json->>'longitude' as address_lng FROM public.hss_service_orders WHERE id = 'so-1781054320183-35441'; ``` ### 2. 查看在线服务人员状态 ```sql SELECT id, online_status, station_id, current_lat, current_lng, (SELECT COUNT(*) FROM hss_service_assignments sa JOIN hss_service_orders so ON so.id = sa.order_id WHERE sa.staff_id::TEXT = s.id::TEXT AND sa.deleted_at IS NULL AND sa.status IN ('assigned', 'accepted', 'departed', 'arrived', 'serving', 'in_service') ) as active_tasks FROM ml_delivery_staff s WHERE deleted_at IS NULL AND status = 1 AND COALESCE(is_active, TRUE) = TRUE ORDER BY online_status DESC, active_tasks ASC; ``` ### 3. 前端测试流程 1. 重新下单支付 2. 查看控制台日志,应看到: - `[homecare-dispatch] RPC response:` - RPC 原始返回 - `[homecare-dispatch] Parsed result:` - 解析后的结果 - `[confirmPayment] 派单结果:` - 支付页派单结果 ### 4. 预期结果 **修复前**: ``` code: "ALL_ELIGIBLE_STAFF_BUSY" message: "当前可服务人员均在忙,请稍后重新派单" ``` **修复后**(如果有在线空闲人员): ``` code: "DISPATCH_ASSIGNED" message: "系统已为您匹配服务人员" dispatch_status: "assigned" ``` ## 文件清单 | 文件 | 说明 | |------|------| | `services/serviceOrderService.uts` | ✅ 已修改:订单创建时填充经纬度 | | `pages/mall/consumer/payment.uvue` | ✅ 已修改:增加派单日志 | | `pages/mall/consumer/home-service/order-detail.uvue` | ✅ 已修改:增加派单日志 | | `pages/mall/consumer/orders.uvue` | ✅ 已修改:增加派单日志 | | `services/serviceOrderService.uts` | ✅ 已修改:区分显示5种失败原因 | | `mall_sql/diagnostics/dispatch_failure_diagnosis.sql` | 📋 诊断脚本(可选执行) | | `mall_sql/migrations/20260610_fix_service_order_coordinates.sql` | 🔧 修复历史订单经纬度 | | `mall_sql/migrations/20260610_optimize_dispatch_conflict_check.sql` | 🔧 优化版派单 RPC | ## 后续优化建议 1. **订单创建时设置预约时间范围**:将 `appointment_time` 转换为 `scheduled_start_at` 和 `scheduled_end_at` 2. **服务人员位置实时更新**:确保 delivery 端定期上报当前位置 3. **派单失败重试策略**:增加指数退避重试,避免频繁调用 4. **监控告警**:当派单失败率超过阈值时发送告警