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] : '未知'; } } ?>