文件
mashangyoujiu/Application/Retail/Controller/RiderAreaController.class.php

547 行
18 KiB
PHP

<?php
namespace Retail\Controller;
use Think\Controller;
/**
* 骑手区域管理控制器
*/
class RiderAreaController extends Controller {
/**
* 区域管理首页
*/
public function index() {
$this->display();
}
/**
* 获取配送区域列表
*/
public function getAreaList() {
$page = I('page', 1, 'intval');
$pageSize = I('pageSize', 20, 'intval');
$keyword = I('keyword', '', 'trim');
$status = I('status', '', 'trim');
$city_id = I('city_id', 0, 'intval');
$where = array();
// 关键词搜索
if (!empty($keyword)) {
$where['area_name'] = array('like', '%' . $keyword . '%');
}
// 状态筛选
if ($status !== '') {
$where['status'] = $status;
}
// 城市筛选
if ($city_id > 0) {
$where['city_id'] = $city_id;
}
$model = M('delivery_area');
$total = $model->where($where)->count();
$list = $model->where($where)
->order('create_time desc')
->page($page, $pageSize)
->select();
// 格式化数据
foreach ($list as &$item) {
$item['status_text'] = $this->getStatusText($item['status']);
$item['create_time_format'] = date('Y-m-d H:i:s', $item['create_time']);
// 获取城市名称
$city = M('city')->where(array('id' => $item['city_id']))->find();
$item['city_name'] = $city ? $city['name'] : '';
// 统计该区域的骑手数量
$item['rider_count'] = M('rider_area')->where(array('area_id' => $item['id']))->count();
// 统计该区域的订单数量(今日)
$today_start = strtotime(date('Y-m-d 00:00:00'));
$today_end = strtotime(date('Y-m-d 23:59:59'));
$item['today_orders'] = M('order')->where(array(
'delivery_area_id' => $item['id'],
'create_time' => array('between', array($today_start, $today_end))
))->count();
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => array(
'list' => $list,
'total' => $total
)
));
}
/**
* 获取区域详情
*/
public function getAreaDetail() {
$id = I('id', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$detail = M('delivery_area')->where(array('id' => $id))->find();
if (empty($detail)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '区域不存在'));
}
// 格式化数据
$detail['status_text'] = $this->getStatusText($detail['status']);
$detail['create_time_format'] = date('Y-m-d H:i:s', $detail['create_time']);
// 获取城市信息
$city = M('city')->where(array('id' => $detail['city_id']))->find();
$detail['city_info'] = $city;
// 解析区域坐标
if (!empty($detail['coordinates'])) {
$detail['coordinate_list'] = json_decode($detail['coordinates'], true);
} else {
$detail['coordinate_list'] = array();
}
// 获取区域统计
$stats = $this->getSingleAreaStats($id);
$detail['stats'] = $stats;
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => $detail
));
}
/**
* 添加/编辑配送区域
*/
public function saveArea() {
$id = I('id', 0, 'intval');
$data = array(
'area_name' => I('area_name', '', 'trim'),
'city_id' => I('city_id', 0, 'intval'),
'coordinates' => I('coordinates', '', 'trim'),
'center_lat' => I('center_lat', 0, 'floatval'),
'center_lng' => I('center_lng', 0, 'floatval'),
'radius' => I('radius', 0, 'floatval'),
'delivery_fee' => I('delivery_fee', 0, 'floatval'),
'min_order_amount' => I('min_order_amount', 0, 'floatval'),
'description' => I('description', '', 'trim'),
'status' => I('status', 1, 'intval')
);
// 数据验证
if (empty($data['area_name'])) {
$this->ajaxReturn(array('code' => 1, 'msg' => '区域名称不能为空'));
}
if ($data['city_id'] <= 0) {
$this->ajaxReturn(array('code' => 1, 'msg' => '请选择城市'));
}
if (empty($data['coordinates'])) {
$this->ajaxReturn(array('code' => 1, 'msg' => '区域坐标不能为空'));
}
$model = M('delivery_area');
if ($id > 0) {
// 编辑
$data['update_time'] = time();
$result = $model->where(array('id' => $id))->save($data);
} else {
// 添加
$data['create_time'] = time();
$data['update_time'] = time();
$result = $model->add($data);
}
if ($result !== false) {
$this->ajaxReturn(array('code' => 0, 'msg' => '操作成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '操作失败'));
}
}
/**
* 删除配送区域
*/
public function deleteArea() {
$id = I('id', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
// 检查是否有骑手绑定
$riderCount = M('rider_area')->where(array('area_id' => $id))->count();
if ($riderCount > 0) {
$this->ajaxReturn(array('code' => 1, 'msg' => '该区域已有骑手绑定,无法删除'));
}
$result = M('delivery_area')->where(array('id' => $id))->delete();
if ($result) {
$this->ajaxReturn(array('code' => 0, 'msg' => '删除成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '删除失败'));
}
}
/**
* 启用/禁用区域
*/
public function toggleStatus() {
$id = I('id', 0, 'intval');
$status = I('status', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$result = M('delivery_area')->where(array('id' => $id))->save(array(
'status' => $status,
'update_time' => time()
));
if ($result !== false) {
$this->ajaxReturn(array('code' => 0, 'msg' => '操作成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '操作失败'));
}
}
/**
* 获取骑手区域分配列表
*/
public function getRiderAreaList() {
$page = I('page', 1, 'intval');
$pageSize = I('pageSize', 20, 'intval');
$keyword = I('keyword', '', 'trim');
$area_id = I('area_id', 0, 'intval');
$where = array();
// 关键词搜索
if (!empty($keyword)) {
$where['_string'] = "(u.nickname LIKE '%{$keyword}%' OR u.phone LIKE '%{$keyword}%')";
}
// 区域筛选
if ($area_id > 0) {
$where['ra.area_id'] = $area_id;
}
$model = M('rider_area');
$total = $model->alias('ra')
->join('ls_users u ON ra.rider_id = u.id')
->join('ls_delivery_area da ON ra.area_id = da.id')
->where($where)
->count();
$list = $model->alias('ra')
->field('ra.*, u.nickname, u.phone, u.avatar, da.area_name')
->join('ls_users u ON ra.rider_id = u.id')
->join('ls_delivery_area da ON ra.area_id = da.id')
->where($where)
->order('ra.create_time desc')
->page($page, $pageSize)
->select();
// 格式化数据
foreach ($list as &$item) {
$item['create_time_format'] = date('Y-m-d H:i:s', $item['create_time']);
// 统计该骑手在该区域的订单数量
$item['order_count'] = M('order')->where(array(
'rider_id' => $item['rider_id'],
'delivery_area_id' => $item['area_id']
))->count();
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => array(
'list' => $list,
'total' => $total
)
));
}
/**
* 分配骑手到区域
*/
public function assignRiderToArea() {
$rider_id = I('rider_id', 0, 'intval');
$area_ids = I('area_ids', '', 'trim');
if ($rider_id <= 0) {
$this->ajaxReturn(array('code' => 1, 'msg' => '请选择骑手'));
}
if (empty($area_ids)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '请选择配送区域'));
}
$area_id_array = explode(',', $area_ids);
// 先删除该骑手的所有区域分配
M('rider_area')->where(array('rider_id' => $rider_id))->delete();
// 重新分配区域
$success_count = 0;
foreach ($area_id_array as $area_id) {
$area_id = intval($area_id);
if ($area_id <= 0) continue;
$data = array(
'rider_id' => $rider_id,
'area_id' => $area_id,
'create_time' => time()
);
$result = M('rider_area')->add($data);
if ($result) {
$success_count++;
}
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => "分配成功,共分配{$success_count}个区域"
));
}
/**
* 移除骑手区域分配
*/
public function removeRiderArea() {
$id = I('id', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$result = M('rider_area')->where(array('id' => $id))->delete();
if ($result) {
$this->ajaxReturn(array('code' => 0, 'msg' => '移除成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '移除失败'));
}
}
/**
* 获取区域热力图数据
*/
public function getHeatmapData() {
$area_id = I('area_id', 0, 'intval');
$date = I('date', date('Y-m-d'), 'trim');
$start_time = strtotime($date . ' 00:00:00');
$end_time = strtotime($date . ' 23:59:59');
$where = array(
'create_time' => array('between', array($start_time, $end_time))
);
if ($area_id > 0) {
$where['delivery_area_id'] = $area_id;
}
// 获取订单分布数据
$orders = M('order')->field('pickup_lat, pickup_lng, delivery_lat, delivery_lng')
->where($where)
->select();
$heatmap_data = array();
foreach ($orders as $order) {
// 取餐点
if (!empty($order['pickup_lat']) && !empty($order['pickup_lng'])) {
$heatmap_data[] = array(
'lat' => floatval($order['pickup_lat']),
'lng' => floatval($order['pickup_lng']),
'type' => 'pickup',
'weight' => 1
);
}
// 配送点
if (!empty($order['delivery_lat']) && !empty($order['delivery_lng'])) {
$heatmap_data[] = array(
'lat' => floatval($order['delivery_lat']),
'lng' => floatval($order['delivery_lng']),
'type' => 'delivery',
'weight' => 1
);
}
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => $heatmap_data
));
}
/**
* 导出区域数据
*/
public function exportArea() {
$keyword = I('keyword', '', 'trim');
$status = I('status', '', 'trim');
$city_id = I('city_id', 0, 'intval');
$where = array();
if (!empty($keyword)) {
$where['area_name'] = array('like', '%' . $keyword . '%');
}
if ($status !== '') {
$where['status'] = $status;
}
if ($city_id > 0) {
$where['city_id'] = $city_id;
}
$list = M('delivery_area')->where($where)->order('create_time desc')->select();
// 导出Excel
vendor('PHPExcel.PHPExcel');
$objPHPExcel = new \PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$objActSheet = $objPHPExcel->getActiveSheet();
// 设置表头
$objActSheet->setCellValue('A1', '区域ID');
$objActSheet->setCellValue('B1', '区域名称');
$objActSheet->setCellValue('C1', '城市');
$objActSheet->setCellValue('D1', '中心坐标');
$objActSheet->setCellValue('E1', '配送半径');
$objActSheet->setCellValue('F1', '配送费');
$objActSheet->setCellValue('G1', '最低起送金额');
$objActSheet->setCellValue('H1', '状态');
$objActSheet->setCellValue('I1', '骑手数量');
$objActSheet->setCellValue('J1', '创建时间');
// 填充数据
$row = 2;
foreach ($list as $item) {
$city = M('city')->where(array('id' => $item['city_id']))->find();
$rider_count = M('rider_area')->where(array('area_id' => $item['id']))->count();
$objActSheet->setCellValue('A' . $row, $item['id']);
$objActSheet->setCellValue('B' . $row, $item['area_name']);
$objActSheet->setCellValue('C' . $row, $city ? $city['name'] : '');
$objActSheet->setCellValue('D' . $row, $item['center_lat'] . ',' . $item['center_lng']);
$objActSheet->setCellValue('E' . $row, $item['radius'] . 'km');
$objActSheet->setCellValue('F' . $row, $item['delivery_fee']);
$objActSheet->setCellValue('G' . $row, $item['min_order_amount']);
$objActSheet->setCellValue('H' . $row, $this->getStatusText($item['status']));
$objActSheet->setCellValue('I' . $row, $rider_count);
$objActSheet->setCellValue('J' . $row, date('Y-m-d H:i:s', $item['create_time']));
$row++;
}
$filename = '配送区域_' . date('YmdHis') . '.xlsx';
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
}
/**
* 获取区域统计数据
*/
public function getAreaStats() {
$city_id = I('city_id', 0, 'intval');
$where = array();
if ($city_id > 0) {
$where['city_id'] = $city_id;
}
$model = M('delivery_area');
$stats = array(
'total_count' => $model->where($where)->count(),
'active_count' => $model->where(array_merge($where, array('status' => 1)))->count(),
'inactive_count' => $model->where(array_merge($where, array('status' => 0)))->count()
);
// 统计骑手分配情况
$stats['total_riders'] = M('rider_area')->alias('ra')
->join('ls_delivery_area da ON ra.area_id = da.id')
->where($where)
->count('DISTINCT ra.rider_id');
// 统计今日订单
$today_start = strtotime(date('Y-m-d 00:00:00'));
$today_end = strtotime(date('Y-m-d 23:59:59'));
$stats['today_orders'] = M('order')->alias('o')
->join('ls_delivery_area da ON o.delivery_area_id = da.id')
->where(array_merge($where, array(
'o.create_time' => array('between', array($today_start, $today_end))
)))
->count();
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => $stats
));
}
/**
* 获取单个区域统计数据
*/
private function getSingleAreaStats($area_id) {
$stats = array();
// 骑手数量
$stats['rider_count'] = M('rider_area')->where(array('area_id' => $area_id))->count();
// 今日订单
$today_start = strtotime(date('Y-m-d 00:00:00'));
$today_end = strtotime(date('Y-m-d 23:59:59'));
$stats['today_orders'] = M('order')->where(array(
'delivery_area_id' => $area_id,
'create_time' => array('between', array($today_start, $today_end))
))->count();
// 本月订单
$month_start = strtotime(date('Y-m-01 00:00:00'));
$month_end = strtotime(date('Y-m-t 23:59:59'));
$stats['month_orders'] = M('order')->where(array(
'delivery_area_id' => $area_id,
'create_time' => array('between', array($month_start, $month_end))
))->count();
// 平均配送时间
$stats['avg_delivery_time'] = M('order')->where(array(
'delivery_area_id' => $area_id,
'status' => 'completed'
))->avg('delivery_duration') / 60; // 转换为分钟
return $stats;
}
/**
* 获取状态文本
*/
private function getStatusText($status) {
$statusMap = array(
0 => '已禁用',
1 => '已启用'
);
return isset($statusMap[$status]) ? $statusMap[$status] : '未知';
}
}
?>