query($query); if ($result && $row = $result->fetch_assoc()) { $current_permission_role = $row['em_permission_role_id']; } // 获取日期范围参数 $date_params = getDateRangeParams(); $current_start_date = $date_params['start_date_sql']; $current_end_date = $date_params['end_date_sql']; $date_range = $date_params['date_range']; // 获取选中的业务员ID $selected_employee = isset($_GET['employee_id']) ? intval($_GET['employee_id']) : 0; // 确定要显示哪些业务员的数据 $employee_filter = null; if ($selected_employee > 0) { // 如果选择了特定业务员,检查当前用户是否有权限查看该业务员的数据 $has_permission = false; if ($current_permission_role == 1) { // 管理员可以查看所有业务员 $has_permission = true; } else if ($current_permission_role == 2) { // 组长可以查看自己和组员 $query = "SELECT id FROM employee WHERE id = $selected_employee AND (id = $current_user_id OR em_role = $current_user_id)"; $result = $conn->query($query); $has_permission = ($result && $result->num_rows > 0); } else { // 普通业务员只能查看自己 $has_permission = ($selected_employee == $current_user_id); } if ($has_permission) { $employee_filter = $selected_employee; } else { // 如果没有权限,重置为查看自己的数据 $selected_employee = $current_user_id; $employee_filter = $current_user_id; } } else { // 如果没有选择特定业务员,则按权限显示相应的业务员数据 if ($current_permission_role == 1) { // 管理员可以看到所有业务员 $employee_filter = null; } else if ($current_permission_role == 2) { // 组长可以看到自己和组员 $visible_employees = []; $query = "SELECT id FROM employee WHERE id = $current_user_id OR em_role = $current_user_id"; $result = $conn->query($query); if ($result) { while ($row = $result->fetch_assoc()) { $visible_employees[] = intval($row['id']); } } if (!empty($visible_employees)) { $employee_filter = $visible_employees; } else { $employee_filter = $current_user_id; } } else { // 普通业务员只能看到自己 $employee_filter = $current_user_id; } } // 获取业务员列表(基于权限) $sql_employees = ""; if ($current_permission_role == 1) { // 管理员可以看到所有业务员 $sql_employees = "SELECT id, em_user FROM employee WHERE em_role IS NOT NULL ORDER BY em_user"; } else if ($current_permission_role == 2) { // 组长可以看到自己和组员 $sql_employees = "SELECT id, em_user FROM employee WHERE id = $current_user_id OR em_role = $current_user_id ORDER BY em_user"; } else { // 普通业务员只能看到自己 $sql_employees = "SELECT id, em_user FROM employee WHERE id = $current_user_id"; } $employees_result = $conn->query($sql_employees); // 计算上一个时间段范围(用于比较) $previous_start_date = ''; $previous_end_date = ''; // 根据当前选择的日期范围,计算上一个对比时段 if ($date_range == 'current_month') { // 上个月 $previous_start_date = date('Y-m-01', strtotime('-1 month', strtotime($current_start_date))); $previous_end_date = date('Y-m-t', strtotime('-1 month', strtotime($current_end_date))); } elseif ($date_range == 'last_month') { // 上上个月 $previous_start_date = date('Y-m-01', strtotime('-2 month', strtotime($current_start_date))); $previous_end_date = date('Y-m-t', strtotime('-2 month', strtotime($current_end_date))); } elseif ($date_range == 'current_year') { // 去年同期 $previous_start_date = date('Y-01-01', strtotime('-1 year', strtotime($current_start_date))); $previous_end_date = date('Y-12-31', strtotime('-1 year', strtotime($current_end_date))); } elseif ($date_range == 'last_30_days' || $date_range == 'last_90_days' || $date_range == 'custom') { // 上一个同长度周期 $date_diff = (strtotime($current_end_date) - strtotime($current_start_date)) / (60 * 60 * 24); $previous_end_date = date('Y-m-d', strtotime('-1 day', strtotime($current_start_date))); $previous_start_date = date('Y-m-d', strtotime("-{$date_diff} day", strtotime($previous_end_date))); } // 阈值设置(可以移到数据库或配置文件中) $order_amount_decrease_threshold = -15; // 订单金额下降超过15%触发预警 $repurchase_cycle_threshold = 90; // 复购周期超过90天触发预警(3个月内未录入订单) $inactive_threshold = 90; // 90天未有客户信息修改视为不活跃客户(3个月) $churn_threshold = 365; // 365天未下单视为流失客户(1年) $normal_repurchase_days = 30; // 正常复购周期参考值(天) // 页面头部 include('statistics_header.php'); ?>
prepare($sql_total_warnings); $stmt->bind_param("ss", $current_start_date, $current_end_date); $stmt->execute(); $result = $stmt->get_result(); $warning_count = $result->fetch_assoc(); // 获取订单金额下降的客户数 - 使用当前用户的筛选条件 $query_employee_filter = null; if (is_array($employee_filter) && !empty($employee_filter)) { // 如果是组长查看团队,转换为SQL中的IN条件 $query_employee_filter = implode(',', $employee_filter); } else if (!is_array($employee_filter) && $employee_filter > 0) { // 如果是查看单个业务员 $query_employee_filter = $employee_filter; } $decreasing_amount_count = getDecreasingOrderAmountCustomers( $conn, $current_start_date, $current_end_date, $previous_start_date, $previous_end_date, $order_amount_decrease_threshold, true, $query_employee_filter ); // 获取复购周期异常(3个月内未录入订单)的客户数 $abnormal_cycle_count = getAbnormalRepurchaseCycleCustomers( $conn, $current_start_date, $current_end_date, $repurchase_cycle_threshold, true, $query_employee_filter ); // 获取长期不活跃(3个月内没有客户信息修改)客户数 $inactive_customers_count = getInactiveCustomers( $conn, $current_end_date, $inactive_threshold, true, 1, 10, $query_employee_filter ); // 获取流失客户(1年内未录入订单)数 $churn_customers_count = getChurnCustomers( $conn, $current_end_date, $churn_threshold, true, 1, 10, $query_employee_filter ); ?>

订单金额下降客户

金额下降超过%

复购周期异常客户

3个月内未录入订单

流失客户

1年内未录入订单

长期不活跃客户

3个月内无客户信息更新

订单金额下降客户

与上一周期相比,订单金额显著下降的客户

fetch_assoc()) { $change_percent = round((($customer['current_amount'] - $customer['previous_amount']) / $customer['previous_amount']) * 100, 1); $change_class = $change_percent < -20 ? 'text-danger' : 'text-warning'; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } if ($decreasing_customers->num_rows == 0) { echo ""; } ?>
客户名称 本期订单金额 上期订单金额 变化百分比 最近出货日期 业务员 操作
" . htmlspecialcharsFix($customer['cs_company']) . "¥" . number_format($customer['current_amount'], 2) . "¥" . number_format($customer['previous_amount'], 2) . "" . $change_percent . "%" . $customer['last_order_date'] . "" . htmlspecialcharsFix($customer['em_user']) . "查看
没有发现订单金额下降的客户

复购周期异常客户

3个月内未录入订单的客户

$abnormal_total_pages && $abnormal_total_pages > 0) $abnormal_page = $abnormal_total_pages; // 获取当页数据 $abnormal_customers = getAbnormalRepurchaseCycleCustomers( $conn, $current_start_date, $current_end_date, $repurchase_cycle_threshold, false, $query_employee_filter, $abnormal_page, $abnormal_page_size ); while ($customer = $abnormal_customers->fetch_assoc()) { $inactive_days = $customer['inactive_days']; $inactive_class = $inactive_days > 60 ? 'text-danger' : 'text-warning'; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } if ($abnormal_customers->num_rows == 0) { echo ""; } ?>
客户编码 客户名称 上次订单日期 未订单天数 历史订单总数 历史订单总额 业务员 操作
" . htmlspecialcharsFix($customer['cs_code']) . "" . htmlspecialcharsFix($customer['cs_company'] ?: '未填写') . "" . ($customer['last_order_date'] ? $customer['last_order_date'] : '从未下单') . "" . $inactive_days . "" . $customer['order_count'] . "¥" . number_format($customer['total_amount'], 2) . "" . htmlspecialcharsFix($customer['em_user']) . "查看
没有发现复购周期异常的客户
1): ?>
条记录,当前显示第 页,共

流失客户

1年内未录入订单的客户

$total_pages && $total_pages > 0) $page = $total_pages; // 获取当页数据 $churn_customers = getChurnCustomers($conn, $current_end_date, $churn_threshold, false, $page, $page_size, $query_employee_filter); while ($customer = $churn_customers->fetch_assoc()) { $inactive_days = $customer['inactive_days']; $inactive_class = $inactive_days > 365 ? 'text-danger' : 'text-warning'; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } if ($churn_customers->num_rows == 0) { echo ""; } ?>
客户编码 客户名称 最后出货日期 未订单天数 历史订单数 历史订单总额 业务员 操作
" . htmlspecialcharsFix($customer['cs_code']) . "" . htmlspecialcharsFix($customer['cs_company'] ?: '未填写') . "" . ($customer['last_order_date'] ? $customer['last_order_date'] : '从未下单') . "" . $inactive_days . "" . $customer['order_count'] . "¥" . number_format($customer['total_amount'], 2) . "" . htmlspecialcharsFix($customer['em_user']) . "查看
没有发现流失客户
1): ?>
条记录,当前显示第 页,共

总体订单趋势

最近12个月的订单数量和金额趋势

= DATE_SUB(?, INTERVAL 11 MONTH)"; // 添加业务员筛选条件 if (is_array($query_employee_filter) && !empty($query_employee_filter)) { // 如果是组长查看团队数据 $sql_trend .= " AND c.cs_belong IN (" . $query_employee_filter . ")"; } else if (!is_array($query_employee_filter) && $query_employee_filter > 0) { // 如果是查看单个业务员数据 $sql_trend .= " AND c.cs_belong = ?"; } $sql_trend .= " GROUP BY DATE_FORMAT(order_date, '%Y-%m') ORDER BY month"; $stmt = $conn->prepare($sql_trend); if (!is_array($query_employee_filter) && $query_employee_filter > 0) { $stmt->bind_param("si", $current_end_date, $query_employee_filter); } else { $stmt->bind_param("s", $current_end_date); } $stmt->execute(); $trend_result = $stmt->get_result(); $months = []; $order_counts = []; $order_amounts = []; while ($row = $trend_result->fetch_assoc()) { $months[] = $row['month']; $order_counts[] = $row['order_count']; $order_amounts[] = $row['total_amount']; } // 转为JSON格式,用于JavaScript图表 $months_json = json_encode($months); $order_counts_json = json_encode($order_counts); $order_amounts_json = json_encode($order_amounts); ?>
0 AND (current_period.amount IS NULL OR (current_period.amount / previous_period.amount - 1) * 100 <= {$threshold}) AND c.cs_deal = 3{$employee_filter}"; $result = $conn->query($sql); $row = $result->fetch_assoc(); return $row['count']; } // 如果需要详细数据 $sql = "SELECT c.id, c.cs_company, IFNULL(current_period.amount, 0) as current_amount, previous_period.amount as previous_amount, e.em_user, IFNULL((SELECT MAX(order_date) FROM orders WHERE customer_id = c.id), '') as last_order_date FROM customer c LEFT JOIN ( SELECT customer_id, SUM(total_amount) as amount FROM orders WHERE order_date BETWEEN '{$current_start}' AND '{$current_end}' GROUP BY customer_id ) current_period ON c.id = current_period.customer_id LEFT JOIN ( SELECT customer_id, SUM(total_amount) as amount FROM orders WHERE order_date BETWEEN '{$previous_start}' AND '{$previous_end}' GROUP BY customer_id ) previous_period ON c.id = previous_period.customer_id JOIN employee e ON c.cs_belong = e.id WHERE previous_period.amount > 0 AND (current_period.amount IS NULL OR (current_period.amount / previous_period.amount - 1) * 100 <= {$threshold}) AND c.cs_deal = 3{$employee_filter} ORDER BY (current_period.amount / previous_period.amount) ASC"; return $conn->query($sql); } /** * 获取复购周期异常的客户(3个月内未录入订单) */ function getAbnormalRepurchaseCycleCustomers($conn, $current_start, $current_end, $threshold, $count_only = false, $selected_employee = 0, $page = 1, $page_size = 10) { // 构建业务员筛选条件 $employee_filter = ""; if (!empty($selected_employee)) { if (is_numeric($selected_employee)) { // 单个业务员 $employee_filter = " AND c.cs_belong = " . intval($selected_employee); } else if (strpos($selected_employee, ',') !== false) { // 多个业务员(逗号分隔的字符串) $employee_filter = " AND c.cs_belong IN (" . $selected_employee . ")"; } } if ($count_only) { $sql = "SELECT COUNT(DISTINCT c.id) as count FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) last_orders ON c.id = last_orders.customer_id JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND ( last_orders.last_order_date IS NULL OR DATEDIFF('{$current_end}', last_orders.last_order_date) > {$threshold} ){$employee_filter}"; $result = $conn->query($sql); $row = $result->fetch_assoc(); return $row['count']; } $offset = ($page - 1) * $page_size; $sql = "SELECT c.id, c.cs_company, c.cs_code, last_orders.last_order_date, CASE WHEN last_orders.last_order_date IS NULL THEN DATEDIFF('{$current_end}', c.cs_addtime) ELSE DATEDIFF('{$current_end}', last_orders.last_order_date) END as inactive_days, IFNULL(order_stats.order_count, 0) as order_count, IFNULL(order_stats.total_amount, 0) as total_amount, e.em_user FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) last_orders ON c.id = last_orders.customer_id LEFT JOIN ( SELECT customer_id, COUNT(*) as order_count, SUM(total_amount) as total_amount FROM orders GROUP BY customer_id ) order_stats ON c.id = order_stats.customer_id JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND ( last_orders.last_order_date IS NULL OR DATEDIFF('{$current_end}', last_orders.last_order_date) > {$threshold} ){$employee_filter} ORDER BY inactive_days DESC LIMIT {$offset}, {$page_size}"; return $conn->query($sql); } /** * 获取长期不活跃的客户(3个月内没有客户信息修改) */ function getInactiveCustomers($conn, $end_date, $inactive_days, $count_only = false, $page = 1, $page_size = 10, $selected_employee = 0) { // 构建业务员筛选条件 $employee_filter = ""; if (!empty($selected_employee)) { if (is_numeric($selected_employee)) { // 单个业务员 $employee_filter = " AND c.cs_belong = " . intval($selected_employee); } else if (strpos($selected_employee, ',') !== false) { // 多个业务员(逗号分隔的字符串) $employee_filter = " AND c.cs_belong IN (" . $selected_employee . ")"; } } if ($count_only) { $sql = "SELECT COUNT(*) as count FROM customer c JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND DATEDIFF('{$end_date}', c.cs_updatetime) > {$inactive_days}{$employee_filter}"; $result = $conn->query($sql); $row = $result->fetch_assoc(); return $row['count']; } $offset = ($page - 1) * $page_size; $sql = "SELECT c.id, c.cs_company, c.cs_code, last_orders.last_order_date, DATEDIFF('{$end_date}', c.cs_updatetime) as inactive_days, c.cs_updatetime as last_update_time, IFNULL(order_stats.order_count, 0) as order_count, IFNULL(order_stats.total_amount, 0) as total_amount, e.em_user FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) last_orders ON c.id = last_orders.customer_id LEFT JOIN ( SELECT customer_id, COUNT(*) as order_count, SUM(total_amount) as total_amount FROM orders GROUP BY customer_id ) order_stats ON c.id = order_stats.customer_id JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND DATEDIFF('{$end_date}', c.cs_updatetime) > {$inactive_days}{$employee_filter} ORDER BY inactive_days DESC LIMIT {$offset}, {$page_size}"; return $conn->query($sql); } /** * 获取流失客户(1年内未录入订单) */ function getChurnCustomers($conn, $end_date, $churn_days, $count_only = false, $page = 1, $page_size = 10, $selected_employee = 0) { // 构建业务员筛选条件 $employee_filter = ""; if (!empty($selected_employee)) { if (is_numeric($selected_employee)) { // 单个业务员 $employee_filter = " AND c.cs_belong = " . intval($selected_employee); } else if (strpos($selected_employee, ',') !== false) { // 多个业务员(逗号分隔的字符串) $employee_filter = " AND c.cs_belong IN (" . $selected_employee . ")"; } } if ($count_only) { $sql = "SELECT COUNT(*) as count FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) last_orders ON c.id = last_orders.customer_id JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND ( last_orders.last_order_date IS NULL OR DATEDIFF('{$end_date}', last_orders.last_order_date) > {$churn_days} ){$employee_filter}"; $result = $conn->query($sql); $row = $result->fetch_assoc(); return $row['count']; } $offset = ($page - 1) * $page_size; $sql = "SELECT c.id, c.cs_company, c.cs_code, last_orders.last_order_date, CASE WHEN last_orders.last_order_date IS NULL THEN DATEDIFF('{$end_date}', c.cs_addtime) ELSE DATEDIFF('{$end_date}', last_orders.last_order_date) END as inactive_days, IFNULL(order_stats.order_count, 0) as order_count, IFNULL(order_stats.total_amount, 0) as total_amount, e.em_user FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) last_orders ON c.id = last_orders.customer_id LEFT JOIN ( SELECT customer_id, COUNT(*) as order_count, SUM(total_amount) as total_amount FROM orders GROUP BY customer_id ) order_stats ON c.id = order_stats.customer_id JOIN employee e ON c.cs_belong = e.id WHERE c.cs_deal = 3 AND ( last_orders.last_order_date IS NULL OR DATEDIFF('{$end_date}', last_orders.last_order_date) > {$churn_days} ){$employee_filter} ORDER BY inactive_days DESC LIMIT {$offset}, {$page_size}"; return $conn->query($sql); } // 页面底部 include('statistics_footer.php'); ?>