483 行
14 KiB
Markdown
483 行
14 KiB
Markdown
# 骑手端订单智能分配方案
|
||
|
||
## 一、现状分析
|
||
|
||
### 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 业务风险
|
||
- **骑手适应性**: 提供培训和激励机制
|
||
- **客户体验**: 建立反馈机制,及时调整策略
|
||
- **成本控制**: 设置分配成本上限,避免过度优化
|
||
|
||
这个方案结合了现有系统的特点,提供了一个渐进式的智能化升级路径,既保证了系统的稳定性,又能显著提升订单分配的效率和准确性。 |