571 行
19 KiB
PHP
571 行
19 KiB
PHP
<?php
|
||
namespace Retail\Controller;
|
||
use Think\Controller;
|
||
use Exception;
|
||
|
||
/**
|
||
* 骑手订单管理控制器
|
||
*/
|
||
class RiderOrderController extends Controller {
|
||
|
||
/**
|
||
* 订单管理首页
|
||
*/
|
||
public function index() {
|
||
$this->display();
|
||
}
|
||
|
||
/**
|
||
* 获取订单列表
|
||
*/
|
||
public function getOrderList() {
|
||
$page = I('page', 1, 'intval');
|
||
$pageSize = I('pageSize', 20, 'intval');
|
||
$keyword = I('keyword', '', 'trim');
|
||
$status = I('status', '', 'trim');
|
||
$riderId = I('riderId', 0, 'intval');
|
||
$startDate = I('startDate', '', 'trim');
|
||
$endDate = I('endDate', '', 'trim');
|
||
|
||
try {
|
||
$where = array();
|
||
|
||
// 关键词搜索(订单号/客户名)
|
||
if (!empty($keyword)) {
|
||
$where['_string'] = "(order_no LIKE '%{$keyword}%' OR customer_name LIKE '%{$keyword}%')";
|
||
}
|
||
|
||
// 状态筛选(将前端传入的文案映射到数值状态)
|
||
if (!empty($status)) {
|
||
$statusMap = array(
|
||
'pending' => 0,
|
||
'accepted' => 1,
|
||
'picking_up' => array('in', array(2,3,4)),
|
||
'delivering' => 5,
|
||
'completed' => 6,
|
||
'cancelled' => 8
|
||
);
|
||
if (isset($statusMap[$status])) {
|
||
$where['order_status'] = $statusMap[$status];
|
||
}
|
||
}
|
||
|
||
// 骑手筛选
|
||
if (!empty($riderId)) {
|
||
$where['rider_id'] = $riderId;
|
||
}
|
||
|
||
// 日期筛选
|
||
if (!empty($startDate) && !empty($endDate)) {
|
||
$where['add_time'] = array('between', array($startDate, $endDate));
|
||
}
|
||
|
||
// 使用骑手订单表
|
||
$orderModel = M('rider_order');
|
||
|
||
// 获取总数
|
||
$totalCount = $orderModel->where($where)->count();
|
||
|
||
// 获取列表数据
|
||
$offset = ($page - 1) * $pageSize;
|
||
$orders = $orderModel
|
||
->where($where)
|
||
->order('add_time DESC')
|
||
->limit($offset, $pageSize)
|
||
->select();
|
||
|
||
// 处理订单数据
|
||
foreach ($orders as &$order) {
|
||
// 获取骑手信息
|
||
if ($order['rider_id']) {
|
||
$rider = M('RiderInfo')->where(array('id' => $order['rider_id']))->find();
|
||
$order['rider'] = array(
|
||
'id' => $rider['id'],
|
||
'name' => $rider['rider_name'],
|
||
'phone' => $rider['rider_phone'],
|
||
'avatar' => $rider['rider_avatar'] ?: '',
|
||
'rating' => floatval($rider['rating'])
|
||
);
|
||
} else {
|
||
$order['rider'] = null;
|
||
}
|
||
|
||
// 商户/门店信息(优先使用订单自带字段以避免额外查询)
|
||
$order['merchant'] = array(
|
||
'name' => isset($order['store_name']) ? $order['store_name'] : '',
|
||
'address' => isset($order['store_address']) ? $order['store_address'] : '',
|
||
'phone' => isset($order['store_phone']) ? $order['store_phone'] : ''
|
||
);
|
||
|
||
// 获取客户信息
|
||
$order['customer'] = array(
|
||
'name' => $order['customer_name'],
|
||
'address' => $order['customer_address'],
|
||
'phone' => $order['customer_phone']
|
||
);
|
||
|
||
// 订单商品(当前库未定义该表,保持空数组)
|
||
$order['items'] = array();
|
||
|
||
// 格式化数据
|
||
$order['deliveryFee'] = floatval($order['delivery_fee']);
|
||
$order['distance'] = floatval($order['distance']);
|
||
$order['estimatedTime'] = intval($order['estimated_time']);
|
||
// 映射状态文案,兼容前端
|
||
$order['status'] = $this->mapOrderStatus(intval($order['order_status']));
|
||
// 兼容 created_at 字段
|
||
$order['created_at'] = isset($order['add_time']) ? $order['add_time'] : '';
|
||
}
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => array(
|
||
'list' => $orders,
|
||
'totalCount' => $totalCount,
|
||
'currentPage' => $page,
|
||
'pageSize' => $pageSize
|
||
)
|
||
));
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '获取失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取订单统计数据
|
||
*/
|
||
public function getStatistics() {
|
||
try {
|
||
$orderModel = M('rider_order');
|
||
|
||
// 总订单数
|
||
$totalOrders = $orderModel->count();
|
||
|
||
// 待分配订单数
|
||
$pendingOrders = $orderModel->where(array('order_status' => 0))->count();
|
||
|
||
// 配送中订单数(在途:取货中+配送中)
|
||
import('Common.Business.OrderStatusUtil');
|
||
$deliveringOrders = $orderModel->where(array('order_status' => array('in', \Common\Business\OrderStatusUtil::getInTransitStatuses())))->count();
|
||
|
||
// 已完成订单数
|
||
$completedOrders = $orderModel->where(array('order_status' => 6))->count();
|
||
|
||
// 今日订单数
|
||
$today = date('Y-m-d');
|
||
$todayOrders = $orderModel->where(array('add_time' => array('like', $today . '%')))->count();
|
||
|
||
// 今日收入
|
||
$todayRevenue = $orderModel
|
||
->where(array(
|
||
'order_status' => 6,
|
||
'delivery_time' => array('like', $today . '%')
|
||
))
|
||
->sum('delivery_fee');
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => array(
|
||
'totalOrders' => intval($totalOrders),
|
||
'pendingOrders' => intval($pendingOrders),
|
||
'deliveringOrders' => intval($deliveringOrders),
|
||
'completedOrders' => intval($completedOrders),
|
||
'todayOrders' => intval($todayOrders),
|
||
'todayRevenue' => floatval($todayRevenue)
|
||
)
|
||
));
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '获取失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 分配骑手
|
||
*/
|
||
public function assignRider() {
|
||
$orderId = I('orderId', 0, 'intval');
|
||
$riderId = I('riderId', 0, 'intval');
|
||
$remark = I('remark', '', 'trim');
|
||
|
||
if (empty($orderId) || empty($riderId)) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '参数错误'
|
||
));
|
||
return;
|
||
}
|
||
|
||
try {
|
||
$orderModel = M('rider_order');
|
||
|
||
// 检查订单状态
|
||
$order = $orderModel->where(array('id' => $orderId))->find();
|
||
if (!$order) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '订单不存在'
|
||
));
|
||
return;
|
||
}
|
||
|
||
if (intval($order['order_status']) !== 0) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '订单状态不允许分配'
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 检查骑手状态
|
||
$rider = M('RiderInfo')->where(array('id' => $riderId))->find();
|
||
if (!$rider) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '骑手不存在'
|
||
));
|
||
return;
|
||
}
|
||
|
||
if (intval($rider['work_status']) !== 1 || intval($rider['auth_status']) !== 2) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '骑手不在线或未认证,无法分配'
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 更新订单
|
||
$updateData = array(
|
||
'rider_id' => $riderId,
|
||
'order_status' => 1,
|
||
'accept_time' => date('Y-m-d H:i:s')
|
||
);
|
||
|
||
$result = $orderModel->where(array('id' => $orderId))->save($updateData);
|
||
|
||
if ($result !== false) {
|
||
// 记录操作日志
|
||
$this->addOrderLog($orderId, 'assigned', "分配给骑手:{$rider['rider_name']}");
|
||
|
||
// 发送通知给骑手(这里可以集成推送服务)
|
||
$this->notifyRider($riderId, $orderId, 'new_order');
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '分配成功'
|
||
));
|
||
} else {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '分配失败'
|
||
));
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '分配失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 取消订单
|
||
*/
|
||
public function cancelOrder() {
|
||
$orderId = I('orderId', 0, 'intval');
|
||
$reason = I('reason', '', 'trim');
|
||
|
||
if (empty($orderId)) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '参数错误'
|
||
));
|
||
return;
|
||
}
|
||
|
||
try {
|
||
$orderModel = M('rider_order');
|
||
|
||
// 检查订单状态
|
||
$order = $orderModel->where(array('id' => $orderId))->find();
|
||
if (!$order) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '订单不存在'
|
||
));
|
||
return;
|
||
}
|
||
|
||
if (!in_array(intval($order['order_status']), array(0, 1))) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '订单状态不允许取消'
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 更新订单状态
|
||
$updateData = array(
|
||
'order_status' => 8,
|
||
'cancel_time' => date('Y-m-d H:i:s'),
|
||
'cancel_reason' => $reason
|
||
);
|
||
|
||
$result = $orderModel->where(array('id' => $orderId))->save($updateData);
|
||
|
||
if ($result !== false) {
|
||
// 记录操作日志
|
||
$this->addOrderLog($orderId, 'cancelled', "订单已取消,原因:{$reason}");
|
||
|
||
// 如果已分配骑手,通知骑手
|
||
if ($order['rider_id']) {
|
||
$this->notifyRider($order['rider_id'], $orderId, 'order_cancelled');
|
||
}
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '取消成功'
|
||
));
|
||
} else {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '取消失败'
|
||
));
|
||
}
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '取消失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取订单详情
|
||
*/
|
||
public function getOrderDetail() {
|
||
// 兼容前端可能传递的不同参数键:优先使用 orderId,其次尝试 id
|
||
$orderId = I('orderId', 0, 'intval');
|
||
if (empty($orderId)) {
|
||
$orderId = I('id', 0, 'intval');
|
||
}
|
||
|
||
if (empty($orderId)) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '参数错误'
|
||
));
|
||
return;
|
||
}
|
||
|
||
try {
|
||
$orderModel = M('rider_order');
|
||
$order = $orderModel->where(array('id' => $orderId))->find();
|
||
|
||
if (!$order) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '订单不存在'
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 获取骑手信息
|
||
if ($order['rider_id']) {
|
||
$rider = M('RiderInfo')->where(array('id' => $order['rider_id']))->find();
|
||
$order['rider'] = array(
|
||
'id' => $rider['id'],
|
||
'name' => $rider['rider_name'],
|
||
'phone' => $rider['rider_phone'],
|
||
'avatar' => $rider['rider_avatar'] ?: '',
|
||
'rating' => floatval($rider['rating'])
|
||
);
|
||
} else {
|
||
$order['rider'] = null;
|
||
}
|
||
|
||
// 获取商户信息(修正为零售商户表)
|
||
$merchant = M('retail_merchant')->where(array('id' => $order['merchant_id']))->find();
|
||
$order['merchant'] = array(
|
||
'name' => isset($merchant['name']) ? $merchant['name'] : '',
|
||
'address' => isset($merchant['address']) ? $merchant['address'] : '',
|
||
// ls_retail_merchant 表使用 mobile 字段作为联系方式
|
||
'phone' => isset($merchant['mobile']) ? $merchant['mobile'] : ''
|
||
);
|
||
|
||
// 获取客户信息
|
||
$order['customer'] = array(
|
||
'name' => $order['customer_name'],
|
||
'address' => $order['customer_address'],
|
||
'phone' => $order['customer_phone']
|
||
);
|
||
|
||
// 订单商品/日志(当前库未定义对应表,保持空数组)
|
||
$order['items'] = array();
|
||
$order['logs'] = array();
|
||
|
||
// 格式化数据
|
||
$order['deliveryFee'] = floatval($order['delivery_fee']);
|
||
$order['distance'] = floatval($order['distance']);
|
||
$order['estimatedTime'] = intval($order['estimated_time']);
|
||
$order['status'] = $this->mapOrderStatus(intval($order['order_status']));
|
||
$order['created_at'] = isset($order['add_time']) ? $order['add_time'] : '';
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => $order
|
||
));
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '获取失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取可用骑手列表
|
||
*/
|
||
public function getAvailableRiders() {
|
||
try {
|
||
$riders = M('RiderInfo')
|
||
->where(array('work_status' => 1, 'auth_status' => 2))
|
||
->field('id, rider_name, rider_phone, rider_avatar, rating, work_status')
|
||
->order('rating DESC')
|
||
->select();
|
||
|
||
$this->ajaxReturn(array(
|
||
'code' => 1,
|
||
'msg' => '获取成功',
|
||
'data' => $riders ?: array()
|
||
));
|
||
|
||
} catch (Exception $e) {
|
||
$this->ajaxReturn(array(
|
||
'code' => 0,
|
||
'msg' => '获取失败:' . $e->getMessage()
|
||
));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 导出订单数据
|
||
*/
|
||
public function exportOrders() {
|
||
$this->ajaxReturn(array(
|
||
'code' => 410,
|
||
'msg' => '导出功能已下线'
|
||
));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 手动同步订单
|
||
*/
|
||
public function syncOrder() {
|
||
$this->ajaxReturn(array(
|
||
'code' => 410,
|
||
'msg' => '订单同步功能已下线'
|
||
));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 批量同步订单
|
||
*/
|
||
public function batchSyncOrders() {
|
||
$this->ajaxReturn(array(
|
||
'code' => 410,
|
||
'msg' => '批量同步功能已下线'
|
||
));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 获取可同步的订单列表
|
||
*/
|
||
public function getSyncableOrders() {
|
||
$this->ajaxReturn(array(
|
||
'code' => 410,
|
||
'msg' => '同步候选订单接口已下线'
|
||
));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 获取同步统计信息
|
||
*/
|
||
public function getSyncStatistics() {
|
||
$this->ajaxReturn(array(
|
||
'code' => 410,
|
||
'msg' => '同步统计接口已下线'
|
||
));
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 记录操作日志
|
||
*/
|
||
private function addOrderLog($orderId, $action, $remark = '') {
|
||
// 当前系统未定义统一的订单操作日志表,暂不写库,避免因缺表报错
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 发送通知给骑手
|
||
*/
|
||
private function notifyRider($riderId, $orderId, $type) {
|
||
// 这里可以集成推送服务,如极光推送、个推等
|
||
// 暂时只记录日志
|
||
$this->addOrderLog($orderId, 'notify_rider', "通知骑手ID:{$riderId},类型:{$type}");
|
||
}
|
||
|
||
/**
|
||
* 获取状态文本
|
||
*/
|
||
private function getStatusText($status) {
|
||
$statusTexts = array(
|
||
'pending' => '待分配',
|
||
'accepted' => '已接单',
|
||
'picking_up' => '取货中',
|
||
'delivering' => '配送中',
|
||
'completed' => '已完成',
|
||
'cancelled' => '已取消'
|
||
);
|
||
|
||
return isset($statusTexts[$status]) ? $statusTexts[$status] : '未知';
|
||
}
|
||
|
||
/**
|
||
* 数值状态到文案映射
|
||
*/
|
||
private function mapOrderStatus($code) {
|
||
switch (intval($code)) {
|
||
case 0: return 'pending';
|
||
case 1: return 'accepted';
|
||
case 2:
|
||
case 3:
|
||
case 4: return 'picking_up';
|
||
case 5: return 'delivering';
|
||
case 6: return 'completed';
|
||
case 8: return 'cancelled';
|
||
case 7: return 'exception';
|
||
default: return 'pending';
|
||
}
|
||
}
|
||
}
|
||
?>
|