Browse Source

fleat: sales

igb 2 weeks ago
parent
commit
b5f1ab1078
2 changed files with 545 additions and 15 deletions
  1. 157 2
      sales_stats.php
  2. 388 13
      statistics_sales.php

+ 157 - 2
sales_stats.php

@@ -18,6 +18,12 @@ $end_date = $date_params['end_date_sql'];
 $date_range = $date_params['date_range'];
 $period = $date_params['period'];
 
+// 获取选中的业务员ID
+$selected_employee = isset($_GET['employee_id']) ? intval($_GET['employee_id']) : 0;
+
+// 获取所有业务员列表
+$employees = getAllEmployees($conn);
+
 // 页面头部
 include('statistics_header.php');
 ?>
@@ -159,6 +165,80 @@ include('statistics_header.php');
 .data-table tr:hover {
     background: #f9f9f9;
 }
+
+.employee-stats {
+    background: #fff;
+    border-radius: 8px;
+    padding: 20px;
+    margin-bottom: 30px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+
+.employee-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 20px;
+    padding-bottom: 15px;
+    border-bottom: 1px solid #eee;
+}
+
+.employee-avatar {
+    width: 64px;
+    height: 64px;
+    border-radius: 50%;
+    background: #f0f0f0;
+    margin-right: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 24px;
+    color: #666;
+}
+
+.employee-info {
+    flex: 1;
+}
+
+.employee-name {
+    font-size: 20px;
+    font-weight: bold;
+    margin: 0 0 5px;
+}
+
+.employee-contact {
+    color: #666;
+    font-size: 14px;
+}
+
+.performance-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 15px;
+    margin-bottom: 20px;
+}
+
+.performance-card {
+    background: #f8f9fa;
+    padding: 15px;
+    border-radius: 6px;
+    text-align: center;
+}
+
+.performance-label {
+    font-size: 14px;
+    color: #666;
+    margin-bottom: 5px;
+}
+
+.performance-value {
+    font-size: 20px;
+    font-weight: bold;
+    color: #4a90e2;
+}
+
+.trend-chart {
+    margin-top: 20px;
+}
 </style>
 
 <div class="container">
@@ -166,9 +246,20 @@ include('statistics_header.php');
         <h1 class="page-title">销售统计分析</h1>
     </div>
     
-    <!-- 日期筛选 -->
+    <!-- 日期和业务员筛选 -->
     <div class="filter-form">
         <form method="get" class="filter-form-inline">
+            <div class="form-group">
+                <label for="employee_id">选择业务员</label>
+                <select class="form-control" id="employee_id" name="employee_id">
+                    <option value="0">全部业务员</option>
+                    <?php foreach ($employees as $emp): ?>
+                    <option value="<?php echo $emp['id']; ?>" <?php echo $selected_employee == $emp['id'] ? 'selected' : ''; ?>>
+                        <?php echo htmlspecialchars($emp['em_user']); ?>
+                    </option>
+                    <?php endforeach; ?>
+                </select>
+            </div>
             <div class="form-group">
                 <label for="date_range">选择日期范围</label>
                 <select class="form-control" id="date_range" name="date_range" onchange="toggleCustomDates()">
@@ -201,7 +292,71 @@ include('statistics_header.php');
             </div>
         </form>
     </div>
-    
+
+    <?php if ($selected_employee > 0): ?>
+    <!-- 单个业务员详细分析 -->
+    <?php
+    $employee_detail = getEmployeeDetail($conn, $selected_employee);
+    $employee_stats = getEmployeeStats($conn, $selected_employee, $start_date, $end_date);
+    ?>
+    <div class="employee-stats">
+        <div class="employee-header">
+            <div class="employee-avatar">
+                <?php echo strtoupper(substr($employee_detail['em_user'], 0, 1)); ?>
+            </div>
+            <div class="employee-info">
+                <h2 class="employee-name"><?php echo htmlspecialchars($employee_detail['em_user']); ?></h2>
+                <div class="employee-contact">
+                    <?php if ($employee_detail['em_email']): ?>
+                    <span>邮箱: <?php echo htmlspecialchars($employee_detail['em_email']); ?></span>
+                    <?php endif; ?>
+                    <?php if ($employee_detail['em_tel']): ?>
+                    <span>电话: <?php echo htmlspecialchars($employee_detail['em_tel']); ?></span>
+                    <?php endif; ?>
+                </div>
+            </div>
+        </div>
+
+        <div class="performance-grid">
+            <div class="performance-card">
+                <div class="performance-label">总订单数</div>
+                <div class="performance-value"><?php echo number_format($employee_stats['total_orders']); ?></div>
+            </div>
+            <div class="performance-card">
+                <div class="performance-label">总销售额</div>
+                <div class="performance-value">¥<?php echo number_format($employee_stats['total_revenue'], 2); ?></div>
+            </div>
+            <div class="performance-card">
+                <div class="performance-label">客户数量</div>
+                <div class="performance-value"><?php echo number_format($employee_stats['customer_count']); ?></div>
+            </div>
+            <div class="performance-card">
+                <div class="performance-label">平均订单金额</div>
+                <div class="performance-value">¥<?php echo number_format($employee_stats['avg_order_value'], 2); ?></div>
+            </div>
+            <div class="performance-card">
+                <div class="performance-label">订单完成率</div>
+                <div class="performance-value"><?php echo formatNumber(($employee_stats['completion_rate'] / 100) * 100, 1); ?>%</div>
+            </div>
+        </div>
+
+        <!-- 业务员销售趋势 -->
+        <div class="trend-chart">
+            <?php renderEmployeeSalesTrend($conn, $selected_employee, $start_date, $end_date); ?>
+        </div>
+
+        <!-- 业务员客户分布 -->
+        <div class="trend-chart">
+            <?php renderEmployeeCustomerDistribution($conn, $selected_employee, $start_date, $end_date); ?>
+        </div>
+
+        <!-- 业务员产品销售分析 -->
+        <div class="trend-chart">
+            <?php renderEmployeeProductAnalysis($conn, $selected_employee, $start_date, $end_date); ?>
+        </div>
+    </div>
+    <?php endif; ?>
+
     <!-- 销售概览 -->
     <div class="chart-container">
         <div class="chart-header">

+ 388 - 13
statistics_sales.php

@@ -210,31 +210,37 @@ function getDetailedOrderTrend($conn, $start_date, $end_date, $period = 'day') {
  * @return void
  */
 function renderSalesOverviewCards($sales_overview) {
+    // 添加空值检查函数
+
+    
+    function formatCurrency($value) {
+        return '¥' . number_format($value ?? 0, 2);
+    }
     ?>
     <div class="stats-grid">
         <div class="stat-card">
             <h3>总订单数</h3>
-            <div class="stat-value"><?php echo number_format($sales_overview['total_orders']); ?></div>
+            <div class="stat-value"><?php echo formatNumber($sales_overview['total_orders']); ?></div>
         </div>
         
         <div class="stat-card">
             <h3>总收入</h3>
-            <div class="stat-value">¥<?php echo number_format($sales_overview['total_revenue'], 2); ?></div>
+            <div class="stat-value"><?php echo formatCurrency($sales_overview['total_revenue']); ?></div>
         </div>
         
         <div class="stat-card">
             <h3>平均订单金额</h3>
-            <div class="stat-value">¥<?php echo number_format($sales_overview['avg_order_value'], 2); ?></div>
+            <div class="stat-value"><?php echo formatCurrency($sales_overview['avg_order_value']); ?></div>
         </div>
 
         <div class="stat-card">
             <h3>独立客户数</h3>
-            <div class="stat-value"><?php echo number_format($sales_overview['unique_customers']); ?></div>
+            <div class="stat-value"><?php echo formatNumber($sales_overview['unique_customers']); ?></div>
         </div>
 
         <div class="stat-card">
             <h3>总销售数量</h3>
-            <div class="stat-value"><?php echo number_format($sales_overview['total_items_sold']); ?></div>
+            <div class="stat-value"><?php echo formatNumber($sales_overview['total_items_sold']); ?></div>
         </div>
     </div>
     <?php
@@ -244,6 +250,11 @@ function renderSalesOverviewCards($sales_overview) {
  * 渲染订单转化率分析
  */
 function renderConversionAnalysis($conversion_stats) {
+    // 添加空值检查函数
+
+    
+
+
     $status_names = [
         1 => '待确认',
         2 => '已确认',
@@ -279,9 +290,9 @@ function renderConversionAnalysis($conversion_stats) {
                         <?php if (isset($data[$status_id])): ?>
                         <tr>
                             <td><?php echo $status_name; ?></td>
-                            <td><?php echo number_format($data[$status_id]['count']); ?></td>
-                            <td><?php echo number_format(($data[$status_id]['count'] / $total_orders) * 100, 1); ?>%</td>
-                            <td>¥<?php echo number_format($data[$status_id]['amount'], 2); ?></td>
+                            <td><?php echo formatNumber($data[$status_id]['count']); ?></td>
+                            <td><?php echo formatNumber(($data[$status_id]['count'] / ($total_orders ?: 1)) * 100, 1); ?>%</td>
+                            <td><?php echo formatCurrency($data[$status_id]['amount']); ?></td>
                         </tr>
                         <?php endif; ?>
                     <?php endforeach; ?>
@@ -534,6 +545,9 @@ function renderCustomerDistributionChart($customer_distribution) {
  * 渲染销售员业绩表格
  */
 function renderEmployeePerformanceTable($employee_performance) {
+    // 添加空值检查函数
+
+
     ?>
     <div class="table-responsive">
         <table class="data-table">
@@ -549,11 +563,11 @@ function renderEmployeePerformanceTable($employee_performance) {
             <tbody>
                 <?php while ($row = $employee_performance->fetch_assoc()): ?>
                 <tr>
-                    <td><?php echo $row['employee_name']; ?></td>
-                    <td><?php echo number_format($row['order_count']); ?></td>
-                    <td><?php echo number_format($row['customer_count']); ?></td>
-                    <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
-                    <td>¥<?php echo number_format($row['avg_order_value'], 2); ?></td>
+                    <td><?php echo htmlspecialchars($row['employee_name']); ?></td>
+                    <td><?php echo formatNumber($row['order_count']); ?></td>
+                    <td><?php echo formatNumber($row['customer_count']); ?></td>
+                    <td><?php echo formatCurrency($row['total_revenue']); ?></td>
+                    <td><?php echo formatCurrency($row['avg_order_value']); ?></td>
                 </tr>
                 <?php endwhile; ?>
             </tbody>
@@ -800,4 +814,365 @@ function renderDetailedOrderTrendChart($time_labels, $time_orders, $time_quantit
         });
     </script>
     <?php
+}
+
+/**
+ * 获取所有业务员列表
+ */
+function getAllEmployees($conn) {
+    $sql = "SELECT id, em_user, em_email, em_tel FROM employee ORDER BY em_user";
+    $result = $conn->query($sql);
+    return $result->fetch_all(MYSQLI_ASSOC);
+}
+
+/**
+ * 获取业务员详细信息
+ */
+function getEmployeeDetail($conn, $employee_id) {
+    $sql = "SELECT id, em_user, em_email, em_tel FROM employee WHERE id = ?";
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("i", $employee_id);
+    $stmt->execute();
+    return $stmt->get_result()->fetch_assoc();
+}
+
+/**
+ * 获取业务员统计数据
+ */
+function getEmployeeStats($conn, $employee_id, $start_date, $end_date) {
+    $sql = "SELECT 
+                COUNT(DISTINCT o.id) as total_orders,
+                SUM(o.total_amount) as total_revenue,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                AVG(o.total_amount) as avg_order_value,
+                SUM(CASE WHEN o.order_status = 5 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) as completion_rate
+            FROM orders o
+            WHERE o.employee_id = ?
+            AND o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("iss", $employee_id, $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result()->fetch_assoc();
+}
+
+/**
+ * 渲染业务员销售趋势
+ */
+function renderEmployeeSalesTrend($conn, $employee_id, $start_date, $end_date) {
+    $sql = "SELECT 
+                DATE_FORMAT(order_date, '%Y-%m-%d') as date,
+                COUNT(DISTINCT id) as orders,
+                SUM(total_amount) as revenue
+            FROM orders 
+            WHERE employee_id = ?
+            AND order_date BETWEEN ? AND ?
+            AND order_status != 0
+            GROUP BY DATE_FORMAT(order_date, '%Y-%m-%d')
+            ORDER BY date";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("iss", $employee_id, $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $dates = [];
+    $orders = [];
+    $revenues = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        $dates[] = $row['date'];
+        $orders[] = $row['orders'];
+        $revenues[] = $row['revenue'];
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">销售趋势</h2>
+        </div>
+        <canvas id="employeeSalesTrendChart"></canvas>
+    </div>
+    
+    <script>
+        var employeeSalesTrendCtx = document.getElementById('employeeSalesTrendChart').getContext('2d');
+        new Chart(employeeSalesTrendCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($dates); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($orders); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.2)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-orders',
+                        tension: 0.1
+                    },
+                    {
+                        label: '销售收入',
+                        data: <?php echo json_encode($revenues); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.2)',
+                        borderColor: 'rgba(255, 99, 132, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-revenue',
+                        tension: 0.1
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        }
+                    },
+                    'y-revenue': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '销售收入'
+                        },
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染业务员客户分布
+ */
+function renderEmployeeCustomerDistribution($conn, $employee_id, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName as region,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                SUM(o.total_amount) as total_revenue
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.employee_id = ?
+            AND o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0
+            GROUP BY c.id
+            ORDER BY total_revenue DESC
+            LIMIT 10";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("iss", $employee_id, $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $regions = [];
+    $customers = [];
+    $revenues = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        $regions[] = $row['region'];
+        $customers[] = $row['customer_count'];
+        $revenues[] = $row['total_revenue'];
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户地区分布 (Top 10)</h2>
+        </div>
+        <canvas id="employeeCustomerChart"></canvas>
+    </div>
+    
+    <script>
+        var employeeCustomerCtx = document.getElementById('employeeCustomerChart').getContext('2d');
+        new Chart(employeeCustomerCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($regions); ?>,
+                datasets: [
+                    {
+                        label: '客户数',
+                        data: <?php echo json_encode($customers); ?>,
+                        backgroundColor: 'rgba(75, 192, 192, 0.5)',
+                        borderColor: 'rgba(75, 192, 192, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-customers'
+                    },
+                    {
+                        label: '销售金额',
+                        data: <?php echo json_encode($revenues); ?>,
+                        backgroundColor: 'rgba(255, 159, 64, 0.5)',
+                        borderColor: 'rgba(255, 159, 64, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-revenue'
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    'y-customers': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '客户数'
+                        }
+                    },
+                    'y-revenue': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '销售金额'
+                        },
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染业务员产品销售分析
+ */
+function renderEmployeeProductAnalysis($conn, $employee_id, $start_date, $end_date) {
+    $sql = "SELECT 
+                pc.name as category_name,
+                COUNT(DISTINCT o.id) as order_count,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue
+            FROM orders o
+            JOIN order_items oi ON o.id = oi.order_id
+            JOIN products p ON oi.product_id = p.id
+            JOIN product_categories pc ON p.category_id = pc.id
+            WHERE o.employee_id = ?
+            AND o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0
+            GROUP BY pc.id
+            ORDER BY total_revenue DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("iss", $employee_id, $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $categories = [];
+    $quantities = [];
+    $revenues = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        $categories[] = $row['category_name'];
+        $quantities[] = $row['total_quantity'];
+        $revenues[] = $row['total_revenue'];
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品类别销售分析</h2>
+        </div>
+        <canvas id="employeeProductChart"></canvas>
+    </div>
+    
+    <script>
+        var employeeProductCtx = document.getElementById('employeeProductChart').getContext('2d');
+        new Chart(employeeProductCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($categories); ?>,
+                datasets: [
+                    {
+                        label: '销售数量',
+                        data: <?php echo json_encode($quantities); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.5)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-quantity'
+                    },
+                    {
+                        label: '销售金额',
+                        data: <?php echo json_encode($revenues); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.5)',
+                        borderColor: 'rgba(255, 99, 132, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-revenue'
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    'y-quantity': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '销售数量'
+                        }
+                    },
+                    'y-revenue': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '销售金额'
+                        },
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染业务员统计卡片
+ */
+function renderEmployeeStats($employee_stats) {
+    // 添加空值检查函数
+    function formatNumber($value, $decimals = 0) {
+        return number_format($value ?? 0, $decimals);
+    }
+    
+    function formatCurrency($value) {
+        return '¥' . number_format($value ?? 0, 2);
+    }
+    ?>
+    <div class="performance-grid">
+        <div class="performance-card">
+            <div class="performance-label">总订单数</div>
+            <div class="performance-value"><?php echo formatNumber($employee_stats['total_orders']); ?></div>
+        </div>
+        <div class="performance-card">
+            <div class="performance-label">总销售额</div>
+            <div class="performance-value"><?php echo formatCurrency($employee_stats['total_revenue']); ?></div>
+        </div>
+        <div class="performance-card">
+            <div class="performance-label">客户数量</div>
+            <div class="performance-value"><?php echo formatNumber($employee_stats['customer_count']); ?></div>
+        </div>
+        <div class="performance-card">
+            <div class="performance-label">平均订单金额</div>
+            <div class="performance-value"><?php echo formatCurrency($employee_stats['avg_order_value']); ?></div>
+        </div>
+        <div class="performance-card">
+            <div class="performance-label">订单完成率</div>
+            <div class="performance-value"><?php echo formatNumber($employee_stats['completion_rate'], 1); ?>%</div>
+        </div>
+    </div>
+    <?php
 }