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): ?>
转化率: %