文件
mashangyoujiu/_ai_archive/docs/订单分配方案.md

483 行
14 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

# 骑手端订单智能分配方案
## 一、现状分析
### 1.1 现有系统架构
- **订单表结构**: `ls_retail_bill_order`(主订单)+ `ls_rider_order`(配送订单)
- **骑手管理**: `ls_rider_info`(骑手信息)+ 相关统计和收入表
- **分配方式**: 主要依赖手动分配和骑手抢单,缺乏智能化分配
### 1.2 存在问题
1. **效率低下**: 手动分配耗时,影响配送时效
2. **分配不均**: 缺乏负载均衡,部分骑手过忙,部分闲置
3. **距离优化不足**: 未考虑骑手位置与商家/客户距离
4. **成本控制薄弱**: 没有综合考虑配送成本和收益
## 二、智能分配策略设计
### 2.1 分配模式
采用**混合分配模式**:
- **智能推荐** + **骑手抢单** + **手动干预**
### 2.2 核心分配算法
#### 2.2.1 骑手筛选条件
```sql
-- 可分配骑手筛选条件
SELECT * FROM ls_rider_info
WHERE status = 1 -- 正常状态
AND auth_status = 2 -- 已认证
AND health_status = 1 -- 健康证通过
AND work_status IN (1, 2) -- 在线或忙碌但未达上限
AND (SELECT COUNT(*) FROM ls_rider_order
WHERE rider_id = ls_rider_info.id
AND order_status IN (1,2,3,4,5)) < max_orders_per_time -- 未达最大接单数
```
#### 2.2.2 距离权重计算
```php
/**
* 计算骑手到商家的距离权重
* @param float $rider_lat 骑手纬度
* @param float $rider_lng 骑手经度
* @param float $store_lat 商家纬度
* @param float $store_lng 商家经度
* @return float 距离权重分数 (0-100)
*/
function calculateDistanceScore($rider_lat, $rider_lng, $store_lat, $store_lng) {
$distance = getDistance($rider_lat, $rider_lng, $store_lat, $store_lng);
if ($distance <= 1) return 100; // 1公里内满分
if ($distance <= 3) return 80; // 1-3公里
if ($distance <= 5) return 60; // 3-5公里
if ($distance <= 8) return 40; // 5-8公里
if ($distance <= 12) return 20; // 8-12公里
return 0; // 超过12公里不推荐
}
```
#### 2.2.3 骑手能力评分
```php
/**
* 计算骑手综合能力评分
* @param array $rider 骑手信息
* @return float 能力评分 (0-100)
*/
function calculateRiderScore($rider) {
$score = 0;
// 评分权重 (30%)
$score += ($rider['rating'] / 5) * 30;
// 准时率权重 (25%)
$score += ($rider['on_time_rate'] / 100) * 25;
// 完成订单数权重 (20%) - 经验值
$experience_score = min(($rider['completed_orders'] / 1000) * 20, 20);
$score += $experience_score;
// 当前负载权重 (15%) - 负载越低分数越高
$current_orders = getCurrentOrderCount($rider['id']);
$load_score = (1 - ($current_orders / $rider['max_orders_per_time'])) * 15;
$score += $load_score;
// 在线时长权重 (10%) - 今日在线时长
$online_hours = getTodayOnlineHours($rider['id']);
$time_score = min(($online_hours / 8) * 10, 10);
$score += $time_score;
return $score;
}
```
#### 2.2.4 订单优先级计算
```php
/**
* 计算订单优先级
* @param array $order 订单信息
* @return int 优先级分数 (1-100)
*/
function calculateOrderPriority($order) {
$priority = 50; // 基础优先级
// VIP客户 +20
if ($order['is_vip']) $priority += 20;
// 预约单 +15
if ($order['order_type'] == 2) $priority += 15;
// 高价值订单 +10
if ($order['all_money'] > 100) $priority += 10;
// 距离远的订单 +5 (避免无人接单)
if ($order['distance'] > 5) $priority += 5;
// 等待时间过长 +时间权重
$wait_minutes = (time() - strtotime($order['add_time'])) / 60;
if ($wait_minutes > 10) $priority += min($wait_minutes - 10, 20);
return min($priority, 100);
}
```
### 2.3 智能分配流程
#### 2.3.1 自动分配流程
```
1. 新订单产生 → 触发分配任务
2. 筛选可用骑手 → 应用筛选条件
3. 计算匹配度 → 距离 + 能力 + 偏好匹配
4. 排序推荐 → 按综合评分排序
5. 推送通知 → 向前3名骑手推送
6. 等待响应 → 30秒内等待接单
7. 超时处理 → 扩大范围或转手动分配
```
#### 2.3.2 匹配度计算公式
```php
/**
* 计算骑手与订单的匹配度
*/
function calculateMatchScore($rider, $order) {
// 距离权重 40%
$distance_score = calculateDistanceScore(
$rider['last_location_lat'],
$rider['last_location_lng'],
$order['store_lat'],
$order['store_lng']
) * 0.4;
// 骑手能力 35%
$rider_score = calculateRiderScore($rider) * 0.35;
// 订单偏好匹配 15%
$preference_score = checkOrderPreference($rider, $order) * 0.15;
// 时间匹配 10%
$time_score = checkTimePreference($rider, $order) * 0.1;
return $distance_score + $rider_score + $preference_score + $time_score;
}
```
## 三、分配策略细化
### 3.1 分时段策略
- **早高峰 (7:00-9:00)**: 优先就近分配,减少等待时间
- **午高峰 (11:00-13:00)**: 负载均衡优先,避免骑手过载
- **晚高峰 (17:00-20:00)**: 综合考虑距离和能力
- **其他时段**: 标准分配策略
### 3.2 特殊订单处理
- **VIP订单**: 优先分配给高评分骑手
- **预约订单**: 提前30分钟开始分配
- **紧急订单**: 立即分配给最近的可用骑手
- **大额订单**: 分配给经验丰富的骑手
### 3.3 负载均衡机制
```php
/**
* 负载均衡调整
*/
function adjustForLoadBalance($candidates) {
foreach ($candidates as &$candidate) {
$current_load = getCurrentOrderCount($candidate['rider_id']);
$max_load = $candidate['max_orders_per_time'];
$load_ratio = $current_load / $max_load;
// 负载过高降低匹配度
if ($load_ratio > 0.8) {
$candidate['match_score'] *= 0.7;
} elseif ($load_ratio < 0.3) {
// 负载过低提升匹配度
$candidate['match_score'] *= 1.2;
}
}
return $candidates;
}
```
## 四、技术实现方案
### 4.1 数据库设计优化
#### 4.1.1 新增配置表
```sql
-- 分配规则配置表
CREATE TABLE `ls_allocation_config` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`config_key` varchar(50) NOT NULL COMMENT '配置键',
`config_value` text NOT NULL COMMENT '配置值(JSON)',
`description` varchar(255) DEFAULT '' COMMENT '配置描述',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `config_key` (`config_key`)
) COMMENT='订单分配配置表';
-- 分配记录表
CREATE TABLE `ls_allocation_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL COMMENT '订单ID',
`allocation_type` tinyint(1) NOT NULL COMMENT '分配类型:1自动2手动3抢单',
`candidate_riders` text COMMENT '候选骑手列表(JSON)',
`selected_rider_id` int(11) DEFAULT 0 COMMENT '选中的骑手ID',
`allocation_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '分配时间',
`response_time` int(11) DEFAULT 0 COMMENT '响应时间(秒)',
`allocation_result` tinyint(1) DEFAULT 0 COMMENT '分配结果:0失败1成功',
`failure_reason` varchar(255) DEFAULT '' COMMENT '失败原因',
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`),
KEY `allocation_time` (`allocation_time`)
) COMMENT='订单分配日志表';
```
#### 4.1.2 骑手表字段扩展
```sql
-- 为ls_rider_info表添加分配相关字段
ALTER TABLE `ls_rider_info`
ADD COLUMN `allocation_score` decimal(5,2) DEFAULT 0.00 COMMENT '分配评分',
ADD COLUMN `last_allocation_time` datetime DEFAULT NULL COMMENT '最后分配时间',
ADD COLUMN `allocation_count_today` int(11) DEFAULT 0 COMMENT '今日分配次数',
ADD COLUMN `refuse_count_today` int(11) DEFAULT 0 COMMENT '今日拒单次数',
ADD COLUMN `auto_accept_conditions` text COMMENT '自动接单条件(JSON)';
```
### 4.2 核心服务类设计
#### 4.2.1 订单分配服务
```php
<?php
/**
* 订单分配服务类
*/
class OrderAllocationService {
/**
* 主分配方法
*/
public function allocateOrder($order_id) {
$order = $this->getOrderInfo($order_id);
if (!$order) return false;
// 1. 获取候选骑手
$candidates = $this->getCandidateRiders($order);
// 2. 计算匹配度
$scored_candidates = $this->scoreRiders($candidates, $order);
// 3. 负载均衡调整
$balanced_candidates = $this->adjustForLoadBalance($scored_candidates);
// 4. 排序并选择前N名
$top_candidates = $this->selectTopCandidates($balanced_candidates, 3);
// 5. 推送通知
$result = $this->notifyRiders($top_candidates, $order);
// 6. 记录分配日志
$this->logAllocation($order_id, $top_candidates, $result);
return $result;
}
/**
* 获取候选骑手
*/
private function getCandidateRiders($order) {
// 实现骑手筛选逻辑
}
/**
* 计算骑手评分
*/
private function scoreRiders($candidates, $order) {
// 实现评分算法
}
// ... 其他方法
}
```
#### 4.2.2 分配任务队列
```php
<?php
/**
* 分配任务队列处理
*/
class AllocationQueue {
/**
* 添加分配任务
*/
public function addTask($order_id, $priority = 'normal') {
$task = [
'order_id' => $order_id,
'priority' => $priority,
'created_at' => time(),
'attempts' => 0
];
// 添加到Redis队列
$this->redis->lpush('allocation_queue', json_encode($task));
}
/**
* 处理队列任务
*/
public function processQueue() {
while (true) {
$task_data = $this->redis->brpop('allocation_queue', 1);
if ($task_data) {
$task = json_decode($task_data[1], true);
$this->processTask($task);
}
}
}
private function processTask($task) {
$allocation_service = new OrderAllocationService();
$result = $allocation_service->allocateOrder($task['order_id']);
if (!$result && $task['attempts'] < 3) {
// 重试机制
$task['attempts']++;
$this->addTask($task['order_id'], 'retry');
}
}
}
```
### 4.3 API接口设计
#### 4.3.1 自动分配接口
```php
/**
* 触发自动分配
* POST /api/allocation/auto
*/
public function autoAllocate() {
$order_id = I('order_id', 0, 'intval');
if (!$order_id) {
$this->ajaxReturn(['code' => 400, 'msg' => '订单ID不能为空']);
}
$allocation_service = new OrderAllocationService();
$result = $allocation_service->allocateOrder($order_id);
if ($result) {
$this->ajaxReturn(['code' => 200, 'msg' => '分配成功', 'data' => $result]);
} else {
$this->ajaxReturn(['code' => 500, 'msg' => '分配失败']);
}
}
```
#### 4.3.2 骑手推荐接口
```php
/**
* 获取推荐骑手列表
* GET /api/allocation/recommend
*/
public function getRecommendRiders() {
$order_id = I('order_id', 0, 'intval');
$limit = I('limit', 5, 'intval');
$allocation_service = new OrderAllocationService();
$recommendations = $allocation_service->getRecommendations($order_id, $limit);
$this->ajaxReturn([
'code' => 200,
'msg' => '获取成功',
'data' => $recommendations
]);
}
```
### 4.4 前端界面优化
#### 4.4.1 智能分配面板
```html
<!-- 订单分配面板 -->
<div class="allocation-panel">
<div class="order-info">
<h3>订单 #{{ order.order_no }}</h3>
<p>商家:{{ order.store_name }}</p>
<p>距离:{{ order.distance }}km</p>
<p>配送费:¥{{ order.delivery_fee }}</p>
</div>
<div class="allocation-options">
<el-button type="primary" @click="autoAllocate">智能分配</el-button>
<el-button @click="showRecommendations">查看推荐</el-button>
<el-button @click="manualAssign">手动分配</el-button>
</div>
<div class="recommendations" v-if="showRecommendList">
<h4>推荐骑手</h4>
<div v-for="rider in recommendations" :key="rider.id" class="rider-card">
<div class="rider-info">
<img :src="rider.avatar" class="avatar">
<div class="details">
<h5>{{ rider.name }}</h5>
<p>评分:{{ rider.rating }}⭐</p>
<p>距离:{{ rider.distance }}km</p>
<p>匹配度:{{ rider.match_score }}%</p>
</div>
</div>
<el-button size="mini" @click="assignToRider(rider.id)">分配</el-button>
</div>
</div>
</div>
```
## 五、实施计划
### 5.1 第一阶段:基础功能 (2周)
- [ ] 数据库表结构调整
- [ ] 核心分配算法实现
- [ ] 基础API接口开发
- [ ] 简单的管理后台界面
### 5.2 第二阶段:智能优化 (2周)
- [ ] 机器学习模型训练
- [ ] 实时数据分析
- [ ] 分配效果监控
- [ ] 骑手端推送优化
### 5.3 第三阶段:完善优化 (1周)
- [ ] 性能优化
- [ ] 异常处理完善
- [ ] 用户体验优化
- [ ] 数据统计分析
## 六、预期效果
### 6.1 效率提升
- **分配时间**: 从平均5分钟降低到30秒内
- **接单率**: 提升至85%以上
- **配送时效**: 平均配送时间缩短15%
### 6.2 成本控制
- **人工成本**: 减少50%的手动分配工作量
- **配送成本**: 通过距离优化降低10%的配送成本
- **客户满意度**: 提升20%的客户满意度
### 6.3 数据驱动
- **实时监控**: 分配成功率、响应时间等关键指标
- **智能调优**: 基于历史数据持续优化分配算法
- **预测分析**: 预测高峰期订单量,提前调配资源
## 七、风险控制
### 7.1 技术风险
- **算法准确性**: 建立A/B测试机制,逐步优化
- **系统稳定性**: 设置降级机制,确保服务可用性
- **数据安全**: 加强位置数据和个人信息保护
### 7.2 业务风险
- **骑手适应性**: 提供培训和激励机制
- **客户体验**: 建立反馈机制,及时调整策略
- **成本控制**: 设置分配成本上限,避免过度优化
这个方案结合了现有系统的特点,提供了一个渐进式的智能化升级路径,既保证了系统的稳定性,又能显著提升订单分配的效率和准确性。