query($sql); } /** * 获取成交阶段分布 * * @param mysqli $conn 数据库连接 * @return mysqli_result 成交阶段分布数据结果集 */ function getDealStageDistribution($conn) { $sql = "SELECT cs_deal, CASE WHEN cs_deal = 1 THEN '背景调查' WHEN cs_deal = 2 THEN '明确需求' WHEN cs_deal = 3 THEN '已成交' ELSE '其他' END as stage_name, COUNT(id) as customer_count FROM customer GROUP BY cs_deal"; return $conn->query($sql); } /** * 获取客户增长趋势 * * @param mysqli $conn 数据库连接 * @param int $months 获取多少个月的数据,默认12个月 * @return mysqli_result 客户增长趋势数据结果集 */ function getCustomerGrowthTrend($conn, $months = 12) { $sql = "SELECT DATE_FORMAT(cs_addtime, '%Y-%m') as month, COUNT(id) as new_customers FROM customer WHERE cs_addtime >= DATE_SUB(CURDATE(), INTERVAL ? MONTH) GROUP BY DATE_FORMAT(cs_addtime, '%Y-%m') ORDER BY month"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $months); $stmt->execute(); return $stmt->get_result(); } /** * 获取新老客户订单分析 * * @param mysqli $conn 数据库连接 * @param string $start_date 开始日期 * @param string $end_date 结束日期 * @return array 新老客户订单分析数据 */ function getNewVsReturningCustomerOrders($conn, $start_date, $end_date) { // 获取选定日期范围内的订单 $sql = "SELECT o.customer_id, COUNT(o.id) as order_count, SUM(o.total_amount) as total_amount, MIN(o.order_date) as first_order_date, MAX(c.cs_addtime) as customer_addtime FROM orders o JOIN customer c ON o.customer_id = c.id WHERE o.order_date BETWEEN ? AND ? GROUP BY o.customer_id"; $stmt = $conn->prepare($sql); $stmt->bind_param("ss", $start_date, $end_date); $stmt->execute(); $result = $stmt->get_result(); $new_customers = 0; $returning_customers = 0; $new_customer_amount = 0; $returning_customer_amount = 0; while ($row = $result->fetch_assoc()) { // 查找之前是否有订单 $prev_sql = "SELECT id FROM orders WHERE customer_id = ? AND order_date < ? LIMIT 1"; $prev_stmt = $conn->prepare($prev_sql); $prev_stmt->bind_param("is", $row['customer_id'], $start_date); $prev_stmt->execute(); $prev_result = $prev_stmt->get_result(); if ($prev_result->num_rows > 0) { // 老客户 $returning_customers++; $returning_customer_amount += $row['total_amount']; } else { // 新客户 $new_customers++; $new_customer_amount += $row['total_amount']; } } return [ 'new_customers' => $new_customers, 'returning_customers' => $returning_customers, 'new_customer_amount' => $new_customer_amount, 'returning_customer_amount' => $returning_customer_amount, 'total_customers' => $new_customers + $returning_customers, 'total_amount' => $new_customer_amount + $returning_customer_amount ]; } /** * 渲染客户类型分布图 * * @param array $type_labels 类型标签 * @param array $type_data 类型数据 * @return void */ function renderCustomerTypeChart($type_labels, $type_data) { ?>

客户类型分布

成交阶段分布

客户增长趋势

新老客户分析

客户数量分布

销售额分布

总客户数:
新客户: ( 0) ? number_format(($new_vs_returning['new_customers'] / $new_vs_returning['total_customers']) * 100, 1) : '0'; ?>%)
老客户: ( 0) ? number_format(($new_vs_returning['returning_customers'] / $new_vs_returning['total_customers']) * 100, 1) : '0'; ?>%)
总销售额: ¥
新客户销售额: ¥ ( 0) ? number_format(($new_vs_returning['new_customer_amount'] / $new_vs_returning['total_amount']) * 100, 1) : '0'; ?>%)
老客户销售额: ¥ ( 0) ? number_format(($new_vs_returning['returning_customer_amount'] / $new_vs_returning['total_amount']) * 100, 1) : '0'; ?>%)
query($sql); $row = $result->fetch_assoc(); return $row['total']; } /** * 获取指定时间段内新增客户数 * * @param mysqli $conn 数据库连接 * @param string $start_date 开始日期 * @param string $end_date 结束日期 * @return int 新增客户数 */ function getNewCustomers($conn, $start_date, $end_date) { $sql = "SELECT COUNT(id) as new_count FROM customer WHERE cs_addtime BETWEEN ? AND ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("ss", $start_date, $end_date); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); return $row['new_count']; } /** * 计算平均客户价值(客户平均订单金额) * * @param mysqli $conn 数据库连接 * @param string $start_date 开始日期 * @param string $end_date 结束日期 * @return float 平均客户价值 */ function getAverageCustomerValue($conn, $start_date, $end_date) { $sql = "SELECT AVG(customer_value) as avg_value FROM ( SELECT o.customer_id, SUM(o.total_amount) as customer_value FROM orders o WHERE o.order_date BETWEEN ? AND ? GROUP BY o.customer_id ) as customer_values"; $stmt = $conn->prepare($sql); $stmt->bind_param("ss", $start_date, $end_date); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); return $row['avg_value'] ? $row['avg_value'] : 0; } /** * 计算客户留存率 * * @param mysqli $conn 数据库连接 * @param string $start_date 开始日期 * @param string $end_date 结束日期 * @return array 客户留存率数据 */ function getCustomerRetentionRate($conn, $start_date, $end_date) { // 获取之前时间段的客户 $previous_start = date('Y-m-d', strtotime('-1 year', strtotime($start_date))); $previous_end = date('Y-m-d', strtotime('-1 day', strtotime($start_date))); // 之前时间段的客户ID $prev_sql = "SELECT DISTINCT customer_id FROM orders WHERE order_date BETWEEN ? AND ?"; $prev_stmt = $conn->prepare($prev_sql); $prev_stmt->bind_param("ss", $previous_start, $previous_end); $prev_stmt->execute(); $prev_result = $prev_stmt->get_result(); $previous_customers = []; while ($row = $prev_result->fetch_assoc()) { $previous_customers[] = $row['customer_id']; } $previous_count = count($previous_customers); // 如果没有之前的客户,返回0 if ($previous_count == 0) { return [ 'retained_count' => 0, 'total_previous' => 0, 'retention_rate' => 0 ]; } // 查询当前时间段内,之前客户中再次购买的客户数 $current_sql = "SELECT COUNT(DISTINCT customer_id) as retained_count FROM orders WHERE order_date BETWEEN ? AND ? AND customer_id IN (" . implode(',', $previous_customers) . ")"; $current_stmt = $conn->prepare($current_sql); $current_stmt->bind_param("ss", $start_date, $end_date); $current_stmt->execute(); $current_result = $current_stmt->get_result(); $row = $current_result->fetch_assoc(); $retained_count = $row['retained_count']; $retention_rate = ($retained_count / $previous_count) * 100; return [ 'retained_count' => $retained_count, 'total_previous' => $previous_count, 'retention_rate' => $retention_rate ]; } /** * 计算下单转换率 * * @param mysqli $conn 数据库连接 * @param string $start_date 开始日期 * @param string $end_date 结束日期 * @return array 下单转换率数据 */ function getOrderConversionRate($conn, $start_date, $end_date) { // 获取指定时间段内总客户数 $total_sql = "SELECT COUNT(DISTINCT id) as total_count FROM customer WHERE cs_addtime <= ?"; $total_stmt = $conn->prepare($total_sql); $total_stmt->bind_param("s", $end_date); $total_stmt->execute(); $total_result = $total_stmt->get_result(); $total_row = $total_result->fetch_assoc(); $total_customers = $total_row['total_count']; // 获取有订单的客户数 $order_sql = "SELECT COUNT(DISTINCT customer_id) as order_count FROM orders WHERE order_date BETWEEN ? AND ?"; $order_stmt = $conn->prepare($order_sql); $order_stmt->bind_param("ss", $start_date, $end_date); $order_stmt->execute(); $order_result = $order_stmt->get_result(); $order_row = $order_result->fetch_assoc(); $customers_with_orders = $order_row['order_count']; // 计算转换率 $conversion_rate = ($total_customers > 0) ? ($customers_with_orders / $total_customers) * 100 : 0; return [ 'total_customers' => $total_customers, 'customers_with_orders' => $customers_with_orders, 'conversion_rate' => $conversion_rate ]; } /** * 渲染关键指标仪表板 * * @param array $kpi_data 关键指标数据 * @return void */ function renderKeyMetricsCard($kpi_data) { ?>

客户总数

新增客户

平均客户价值

¥

客户留存率

%
/

下单转换率

%
/
100000 THEN '高价值客户(>10万)' WHEN SUM(o.total_amount) > 50000 THEN '中高价值客户(5-10万)' WHEN SUM(o.total_amount) > 10000 THEN '中价值客户(1-5万)' WHEN SUM(o.total_amount) > 5000 THEN '低价值客户(5千-1万)' ELSE '微价值客户(<5千)' END as value_segment FROM orders o WHERE o.order_date BETWEEN ? AND ? GROUP BY o.customer_id ) as customer_value GROUP BY value_segment ORDER BY CASE value_segment WHEN '高价值客户(>10万)' THEN 1 WHEN '中高价值客户(5-10万)' THEN 2 WHEN '中价值客户(1-5万)' THEN 3 WHEN '低价值客户(5千-1万)' THEN 4 ELSE 5 END"; $stmt = $conn->prepare($sql); $stmt->bind_param("ss", $start_date, $end_date); $stmt->execute(); $result = $stmt->get_result(); $value_segments = []; $customer_counts = []; $total_amounts = []; $total_customers = 0; while ($row = $result->fetch_assoc()) { $value_segments[] = $row['value_segment']; $customer_counts[] = $row['customer_count']; $total_amounts[] = $row['total_amount']; $total_customers += $row['customer_count']; } return [ 'segments' => $value_segments, 'counts' => $customer_counts, 'amounts' => $total_amounts, 'total_customers' => $total_customers ]; } /** * 获取客户活跃度分析数据 * * @param mysqli $conn 数据库连接 * @param string $end_date 截止日期 * @return array 客户活跃度分析数据 */ function getCustomerActivityAnalysis($conn, $end_date) { $sql = "SELECT activity_level, COUNT(*) as customer_count FROM ( SELECT o.customer_id, CASE WHEN DATEDIFF(?, MAX(o.order_date)) <= 30 THEN '活跃客户(30天内)' WHEN DATEDIFF(?, MAX(o.order_date)) <= 90 THEN '一般活跃(90天内)' WHEN DATEDIFF(?, MAX(o.order_date)) <= 180 THEN '低活跃(180天内)' WHEN DATEDIFF(?, MAX(o.order_date)) <= 365 THEN '沉睡客户(1年内)' ELSE '流失客户(超过1年)' END as activity_level FROM orders o GROUP BY o.customer_id ) as customer_activity GROUP BY activity_level ORDER BY CASE activity_level WHEN '活跃客户(30天内)' THEN 1 WHEN '一般活跃(90天内)' THEN 2 WHEN '低活跃(180天内)' THEN 3 WHEN '沉睡客户(1年内)' THEN 4 ELSE 5 END"; $stmt = $conn->prepare($sql); $end_date_formatted = date('Y-m-d', strtotime($end_date)); $stmt->bind_param("ssss", $end_date_formatted, $end_date_formatted, $end_date_formatted, $end_date_formatted); $stmt->execute(); $result = $stmt->get_result(); $activity_levels = []; $customer_counts = []; while ($row = $result->fetch_assoc()) { $activity_levels[] = $row['activity_level']; $customer_counts[] = $row['customer_count']; } return [ 'levels' => $activity_levels, 'counts' => $customer_counts ]; } /** * 获取客户流失风险分析数据 * * @param mysqli $conn 数据库连接 * @param string $end_date 截止日期 * @return array 客户流失风险分析数据 */ function getCustomerChurnRiskAnalysis($conn, $end_date) { $sql = "SELECT risk_level, COUNT(*) as customer_count FROM ( SELECT c.id, CASE WHEN last_order_date IS NULL THEN '从未购买' WHEN DATEDIFF(?, last_order_date) <= 90 THEN '低风险(90天内)' WHEN DATEDIFF(?, last_order_date) <= 180 THEN '中风险(90-180天)' WHEN DATEDIFF(?, last_order_date) <= 365 THEN '高风险(180-365天)' ELSE '极高风险(超过1年)' END as risk_level FROM customer c LEFT JOIN ( SELECT customer_id, MAX(order_date) as last_order_date FROM orders GROUP BY customer_id ) o ON c.id = o.customer_id ) as customer_risk GROUP BY risk_level ORDER BY CASE risk_level WHEN '低风险(90天内)' THEN 1 WHEN '中风险(90-180天)' THEN 2 WHEN '高风险(180-365天)' THEN 3 WHEN '极高风险(超过1年)' THEN 4 WHEN '从未购买' THEN 5 END"; $stmt = $conn->prepare($sql); $end_date_formatted = date('Y-m-d', strtotime($end_date)); $stmt->bind_param("sss", $end_date_formatted, $end_date_formatted, $end_date_formatted); $stmt->execute(); $result = $stmt->get_result(); $risk_levels = []; $customer_counts = []; while ($row = $result->fetch_assoc()) { $risk_levels[] = $row['risk_level']; $customer_counts[] = $row['customer_count']; } return [ 'levels' => $risk_levels, 'counts' => $customer_counts ]; } /** * 获取客户来源分析数据 * * @param mysqli $conn 数据库连接 * @return array 客户来源分析数据 */ function getCustomerSourceAnalysis($conn) { // 假设cs_from字段代表客户来源,需要根据实际情况调整SQL $sql = "SELECT source, COUNT(*) as customer_count FROM ( SELECT id, CASE WHEN cs_from = 1 THEN '网站注册' WHEN cs_from = 2 THEN '销售开发' WHEN cs_from = 3 THEN '广告引流' WHEN cs_from = 4 THEN '展会获取' WHEN cs_from = 5 THEN '客户推荐' ELSE '其他来源' END as source FROM customer ) as customer_source GROUP BY source ORDER BY customer_count DESC"; $result = $conn->query($sql); $sources = []; $counts = []; while ($row = $result->fetch_assoc()) { $sources[] = $row['source']; $counts[] = $row['customer_count']; } return [ 'sources' => $sources, 'counts' => $counts ]; } /** * 渲染客户价值分布图表 * * @param array $value_data 客户价值分布数据 * @return void */ function renderCustomerValueCharts($value_data) { ?>

客户价值分布

客户价值分布(柱状图)

客户价值分布(饼图)

$segment): ?>
: ( 0) ? number_format(($value_data['counts'][$index] / $value_data['total_customers']) * 100, 1) : '0'; ?>%) ¥

客户活跃度分析

$level): ?>
: ( 0) ? number_format(($activity_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)

客户流失风险分析

$level): ?>
: ( 0) ? number_format(($risk_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)

客户来源分析

$source): ?>
: ( 0) ? number_format(($source_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)
query($total_sql); $total_row = $total_result->fetch_assoc(); $total_customers = $total_row['total']; // 获取明确需求的客户数 $needs_sql = "SELECT COUNT(id) as needs_count FROM customer WHERE cs_deal = 2"; $needs_result = $conn->query($needs_sql); $needs_row = $needs_result->fetch_assoc(); $needs_customers = $needs_row['needs_count']; // 获取已成交客户数 $deal_sql = "SELECT COUNT(id) as deal_count FROM customer WHERE cs_deal = 3"; $deal_result = $conn->query($deal_sql); $deal_row = $deal_result->fetch_assoc(); $deal_customers = $deal_row['deal_count']; // 获取有订单的客户数 $order_sql = "SELECT COUNT(DISTINCT customer_id) as order_count FROM orders WHERE order_date BETWEEN ? AND ?"; $order_stmt = $conn->prepare($order_sql); $order_stmt->bind_param("ss", $start_date, $end_date); $order_stmt->execute(); $order_result = $order_stmt->get_result(); $order_row = $order_result->fetch_assoc(); $order_customers = $order_row['order_count']; // 获取复购客户数(多次下单) $repeat_sql = "SELECT COUNT(customer_id) as repeat_count FROM ( SELECT customer_id, COUNT(id) as order_count FROM orders WHERE order_date BETWEEN ? AND ? GROUP BY customer_id HAVING order_count > 1 ) as repeat_customers"; $repeat_stmt = $conn->prepare($repeat_sql); $repeat_stmt->bind_param("ss", $start_date, $end_date); $repeat_stmt->execute(); $repeat_result = $repeat_stmt->get_result(); $repeat_row = $repeat_result->fetch_assoc(); $repeat_customers = $repeat_row['repeat_count']; return [ 'stages' => ['潜在客户', '明确需求', '已成交', '有效订单', '复购客户'], 'counts' => [$total_customers, $needs_customers, $deal_customers, $order_customers, $repeat_customers] ]; } /** * 渲染客户转化漏斗图表 * * @param array $funnel_data 客户转化漏斗数据 * @return void */ function renderCustomerFunnelChart($funnel_data) { ?>

客户转化漏斗

$stage): $current_count = $funnel_data['counts'][$index]; $prev_count = $index > 0 ? $funnel_data['counts'][$index-1] : $current_count; $conversion_rate = $prev_count > 0 ? ($current_count / $prev_count) * 100 : 0; ?>
: 0): ?> 转化率: %