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

536 行
19 KiB
PHP

<?php
namespace Retail\Controller;
use Think\Controller;
/**
* 骑手考核管理控制器
*/
class RiderAssessmentController extends Controller {
/**
* 考核管理首页
*/
public function index() {
$this->display();
}
/**
* 获取考核列表
*/
public function getAssessmentList() {
$page = I('page', 1, 'intval');
$pageSize = I('pageSize', 20, 'intval');
$keyword = I('keyword', '', 'trim');
$level = I('level', '', 'trim');
$month = I('month', '', 'trim');
$where = array();
// 关键词搜索(骑手姓名、手机号)
if (!empty($keyword)) {
$where['_string'] = "(u.nickname LIKE '%{$keyword}%' OR u.phone LIKE '%{$keyword}%')";
}
// 考核等级筛选
if ($level !== '') {
$where['a.assessment_level'] = $level;
}
// 月份筛选
if (!empty($month)) {
$where['a.assessment_month'] = $month;
}
$model = M('rider_assessment');
$total = $model->alias('a')
->join('ls_users u ON a.rider_id = u.id')
->where($where)
->count();
$list = $model->alias('a')
->field('a.*, u.nickname, u.phone, u.avatar')
->join('ls_users u ON a.rider_id = u.id')
->where($where)
->order('a.assessment_month desc, a.total_score desc')
->page($page, $pageSize)
->select();
// 格式化数据
foreach ($list as &$item) {
$item['assessment_level_text'] = $this->getAssessmentLevelText($item['assessment_level']);
$item['create_time_format'] = date('Y-m-d H:i:s', $item['create_time']);
$item['punctuality_rate_format'] = number_format($item['punctuality_rate'], 2) . '%';
$item['rating_score_format'] = number_format($item['rating_score'], 1);
$item['complaint_rate_format'] = number_format($item['complaint_rate'], 2) . '%';
$item['total_score_format'] = number_format($item['total_score'], 1);
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => array(
'list' => $list,
'total' => $total
)
));
}
/**
* 获取考核详情
*/
public function getAssessmentDetail() {
$id = I('id', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$detail = M('rider_assessment')->alias('a')
->field('a.*, u.nickname, u.phone, u.avatar')
->join('ls_users u ON a.rider_id = u.id')
->where(array('a.id' => $id))
->find();
if (empty($detail)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '考核记录不存在'));
}
// 格式化数据
$detail['assessment_level_text'] = $this->getAssessmentLevelText($detail['assessment_level']);
$detail['create_time_format'] = date('Y-m-d H:i:s', $detail['create_time']);
$detail['punctuality_rate_format'] = number_format($detail['punctuality_rate'], 2) . '%';
$detail['rating_score_format'] = number_format($detail['rating_score'], 1);
$detail['complaint_rate_format'] = number_format($detail['complaint_rate'], 2) . '%';
$detail['total_score_format'] = number_format($detail['total_score'], 1);
// 获取详细指标数据
$detail['metrics'] = array(
'order_count' => $detail['order_count'],
'completed_count' => $detail['completed_count'],
'cancelled_count' => $detail['cancelled_count'],
'timeout_count' => $detail['timeout_count'],
'complaint_count' => $detail['complaint_count'],
'praise_count' => $detail['praise_count'],
'online_hours' => number_format($detail['online_hours'], 1),
'avg_delivery_time' => number_format($detail['avg_delivery_time'], 1)
);
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => $detail
));
}
/**
* 生成月度考核
*/
public function generateAssessment() {
$month = I('month', '', 'trim');
$rider_id = I('rider_id', 0, 'intval');
if (empty($month)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '请选择考核月份'));
}
// 验证月份格式
if (!preg_match('/^\d{4}-\d{2}$/', $month)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '月份格式错误'));
}
// 获取骑手列表
$where = array('user_type' => 'rider', 'status' => 1);
if ($rider_id > 0) {
$where['id'] = $rider_id;
}
$riders = M('users')->where($where)->select();
if (empty($riders)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '没有找到符合条件的骑手'));
}
$success_count = 0;
$start_time = strtotime($month . '-01 00:00:00');
$end_time = strtotime(date('Y-m-t 23:59:59', $start_time));
foreach ($riders as $rider) {
// 检查是否已生成过该月考核
$exists = M('rider_assessment')->where(array(
'rider_id' => $rider['id'],
'assessment_month' => $month
))->find();
if ($exists) {
continue; // 跳过已存在的考核记录
}
// 计算考核指标
$metrics = $this->calculateMetrics($rider['id'], $start_time, $end_time);
// 计算总分和等级
$total_score = $this->calculateTotalScore($metrics);
$assessment_level = $this->getAssessmentLevel($total_score);
// 保存考核记录
$assessment_data = array_merge($metrics, array(
'rider_id' => $rider['id'],
'assessment_month' => $month,
'total_score' => $total_score,
'assessment_level' => $assessment_level,
'create_time' => time(),
'update_time' => time()
));
$result = M('rider_assessment')->add($assessment_data);
if ($result) {
$success_count++;
}
}
$this->ajaxReturn(array(
'code' => 0,
'msg' => "考核生成完成,成功生成{$success_count}条考核记录"
));
}
/**
* 更新考核记录
*/
public function updateAssessment() {
$id = I('id', 0, 'intval');
$manual_score = I('manual_score', 0, 'floatval');
$remark = I('remark', '', 'trim');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$assessment = M('rider_assessment')->where(array('id' => $id))->find();
if (empty($assessment)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '考核记录不存在'));
}
// 重新计算总分
$new_total_score = $assessment['total_score'] + $manual_score;
$new_level = $this->getAssessmentLevel($new_total_score);
$update_data = array(
'manual_score' => $manual_score,
'total_score' => $new_total_score,
'assessment_level' => $new_level,
'remark' => $remark,
'update_time' => time()
);
$result = M('rider_assessment')->where(array('id' => $id))->save($update_data);
if ($result !== false) {
$this->ajaxReturn(array('code' => 0, 'msg' => '更新成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '更新失败'));
}
}
/**
* 删除考核记录
*/
public function deleteAssessment() {
$id = I('id', 0, 'intval');
if (empty($id)) {
$this->ajaxReturn(array('code' => 1, 'msg' => '参数错误'));
}
$result = M('rider_assessment')->where(array('id' => $id))->delete();
if ($result) {
$this->ajaxReturn(array('code' => 0, 'msg' => '删除成功'));
} else {
$this->ajaxReturn(array('code' => 1, 'msg' => '删除失败'));
}
}
/**
* 导出考核数据
*/
public function exportAssessment() {
$keyword = I('keyword', '', 'trim');
$level = I('level', '', 'trim');
$month = I('month', '', 'trim');
$where = array();
if (!empty($keyword)) {
$where['_string'] = "(u.nickname LIKE '%{$keyword}%' OR u.phone LIKE '%{$keyword}%')";
}
if ($level !== '') {
$where['a.assessment_level'] = $level;
}
if (!empty($month)) {
$where['a.assessment_month'] = $month;
}
$list = M('rider_assessment')->alias('a')
->field('a.*, u.nickname, u.phone')
->join('ls_users u ON a.rider_id = u.id')
->where($where)
->order('a.assessment_month desc, a.total_score 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', '总分');
$objActSheet->setCellValue('K1', '考核等级');
$objActSheet->setCellValue('L1', '在线时长');
$objActSheet->setCellValue('M1', '平均配送时间');
// 填充数据
$row = 2;
foreach ($list as $item) {
$objActSheet->setCellValue('A' . $row, $item['id']);
$objActSheet->setCellValue('B' . $row, $item['nickname']);
$objActSheet->setCellValue('C' . $row, $item['phone']);
$objActSheet->setCellValue('D' . $row, $item['assessment_month']);
$objActSheet->setCellValue('E' . $row, $item['order_count']);
$objActSheet->setCellValue('F' . $row, $item['completed_count']);
$objActSheet->setCellValue('G' . $row, number_format($item['punctuality_rate'], 2) . '%');
$objActSheet->setCellValue('H' . $row, number_format($item['rating_score'], 1));
$objActSheet->setCellValue('I' . $row, number_format($item['complaint_rate'], 2) . '%');
$objActSheet->setCellValue('J' . $row, number_format($item['total_score'], 1));
$objActSheet->setCellValue('K' . $row, $this->getAssessmentLevelText($item['assessment_level']));
$objActSheet->setCellValue('L' . $row, number_format($item['online_hours'], 1) . '小时');
$objActSheet->setCellValue('M' . $row, number_format($item['avg_delivery_time'], 1) . '分钟');
$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 getAssessmentStats() {
$month = I('month', '', 'trim');
$where = array();
if (!empty($month)) {
$where['assessment_month'] = $month;
}
$model = M('rider_assessment');
$stats = array(
'total_count' => $model->where($where)->count(),
'excellent_count' => $model->where(array_merge($where, array('assessment_level' => 'excellent')))->count(),
'good_count' => $model->where(array_merge($where, array('assessment_level' => 'good')))->count(),
'average_count' => $model->where(array_merge($where, array('assessment_level' => 'average')))->count(),
'poor_count' => $model->where(array_merge($where, array('assessment_level' => 'poor')))->count()
);
// 计算平均分
$avg_score = $model->where($where)->avg('total_score');
$stats['avg_score'] = number_format($avg_score ?: 0, 1);
// 计算平均准时率
$avg_punctuality = $model->where($where)->avg('punctuality_rate');
$stats['avg_punctuality'] = number_format($avg_punctuality ?: 0, 2);
// 计算平均评分
$avg_rating = $model->where($where)->avg('rating_score');
$stats['avg_rating'] = number_format($avg_rating ?: 0, 1);
$this->ajaxReturn(array(
'code' => 0,
'msg' => 'success',
'data' => $stats
));
}
/**
* 计算骑手考核指标
*/
private function calculateMetrics($rider_id, $start_time, $end_time) {
$order_model = M('order');
// 基础订单统计
$order_where = array(
'rider_id' => $rider_id,
'create_time' => array('between', array($start_time, $end_time))
);
$order_count = $order_model->where($order_where)->count();
$completed_count = $order_model->where(array_merge($order_where, array('status' => 'completed')))->count();
$cancelled_count = $order_model->where(array_merge($order_where, array('status' => 'cancelled')))->count();
// 超时订单统计
$timeout_count = $order_model->where(array_merge($order_where, array(
'status' => 'completed',
'is_timeout' => 1
)))->count();
// 计算准时率
$punctuality_rate = $completed_count > 0 ? (($completed_count - $timeout_count) / $completed_count) * 100 : 0;
// 评分统计
$rating_score = $order_model->where(array_merge($order_where, array('status' => 'completed')))
->avg('rider_rating') ?: 0;
// 投诉统计
$complaint_count = M('rider_complaint')->where(array(
'rider_id' => $rider_id,
'create_time' => array('between', array($start_time, $end_time))
))->count();
$complaint_rate = $completed_count > 0 ? ($complaint_count / $completed_count) * 100 : 0;
// 好评统计
$praise_count = $order_model->where(array_merge($order_where, array(
'status' => 'completed',
'rider_rating' => array('egt', 4.5)
)))->count();
// 在线时长统计(假设有在线记录表)
$online_hours = M('rider_online_log')->where(array(
'rider_id' => $rider_id,
'date' => array('between', array(date('Y-m-d', $start_time), date('Y-m-d', $end_time)))
))->sum('online_duration') / 3600; // 转换为小时
// 平均配送时间
$avg_delivery_time = $order_model->where(array_merge($order_where, array('status' => 'completed')))
->avg('delivery_duration') / 60; // 转换为分钟
return array(
'order_count' => $order_count,
'completed_count' => $completed_count,
'cancelled_count' => $cancelled_count,
'timeout_count' => $timeout_count,
'punctuality_rate' => $punctuality_rate,
'rating_score' => $rating_score,
'complaint_count' => $complaint_count,
'complaint_rate' => $complaint_rate,
'praise_count' => $praise_count,
'online_hours' => $online_hours ?: 0,
'avg_delivery_time' => $avg_delivery_time ?: 0
);
}
/**
* 计算总分
*/
private function calculateTotalScore($metrics) {
$score = 0;
// 准时率权重 30%
if ($metrics['punctuality_rate'] >= 95) {
$score += 30;
} elseif ($metrics['punctuality_rate'] >= 90) {
$score += 25;
} elseif ($metrics['punctuality_rate'] >= 85) {
$score += 20;
} elseif ($metrics['punctuality_rate'] >= 80) {
$score += 15;
} else {
$score += 10;
}
// 评分权重 25%
if ($metrics['rating_score'] >= 4.8) {
$score += 25;
} elseif ($metrics['rating_score'] >= 4.5) {
$score += 20;
} elseif ($metrics['rating_score'] >= 4.0) {
$score += 15;
} elseif ($metrics['rating_score'] >= 3.5) {
$score += 10;
} else {
$score += 5;
}
// 投诉率权重 20%(投诉率越低分数越高)
if ($metrics['complaint_rate'] <= 1) {
$score += 20;
} elseif ($metrics['complaint_rate'] <= 2) {
$score += 15;
} elseif ($metrics['complaint_rate'] <= 3) {
$score += 10;
} elseif ($metrics['complaint_rate'] <= 5) {
$score += 5;
} else {
$score += 0;
}
// 完成订单数权重 15%
if ($metrics['completed_count'] >= 200) {
$score += 15;
} elseif ($metrics['completed_count'] >= 150) {
$score += 12;
} elseif ($metrics['completed_count'] >= 100) {
$score += 10;
} elseif ($metrics['completed_count'] >= 50) {
$score += 8;
} else {
$score += 5;
}
// 在线时长权重 10%
if ($metrics['online_hours'] >= 200) {
$score += 10;
} elseif ($metrics['online_hours'] >= 150) {
$score += 8;
} elseif ($metrics['online_hours'] >= 100) {
$score += 6;
} elseif ($metrics['online_hours'] >= 50) {
$score += 4;
} else {
$score += 2;
}
return $score;
}
/**
* 根据总分获取考核等级
*/
private function getAssessmentLevel($total_score) {
if ($total_score >= 90) {
return 'excellent';
} elseif ($total_score >= 80) {
return 'good';
} elseif ($total_score >= 70) {
return 'average';
} else {
return 'poor';
}
}
/**
* 获取考核等级文本
*/
private function getAssessmentLevelText($level) {
$levelMap = array(
'excellent' => '优秀',
'good' => '良好',
'average' => '一般',
'poor' => '较差'
);
return isset($levelMap[$level]) ? $levelMap[$level] : '未知';
}
}
?>