34 Commits 4516f40c59 ... 97db01a6f6

Author SHA1 Message Date
  igb 97db01a6f6 fleat: warning 3 weeks ago
  igb dcaadf2ce9 fleat: warning 3 weeks ago
  igb 62535c3f0c fleat: warning 3 weeks ago
  igb de8a918f4f fleat: warning 3 weeks ago
  igb 38f20ff48c fleat: sales 3 weeks ago
  igb cef81b78b8 fleat: sales 3 weeks ago
  igb b5f1ab1078 fleat: sales 3 weeks ago
  igb 670be84bf2 fleat: sales 3 weeks ago
  igb b2875bdfae fleat: region 3 weeks ago
  igb 87ab58a972 fleat: status 3 weeks ago
  igb 7e13db9847 fleat: status 3 weeks ago
  igb b81cba3bc4 fleat: status 3 weeks ago
  igb 0ee1c015a6 fleat: status 3 weeks ago
  igb fbd1da7182 fleat: status 3 weeks ago
  igb 5039aae58b fleat: status 3 weeks ago
  igb b4f7aee5c0 fleat: status 3 weeks ago
  igb 09106c4567 fleat: permission_role_id 3 weeks ago
  igb 29376e75c8 fleat: 删除小组公海 ,公司公海改为60天无更新 3 weeks ago
  igb 5940ccfef1 fleat: system edit products 3 weeks ago
  igb de06912739 fleat: add statistics 3 weeks ago
  igb f458d63ca3 fleat: add statistics 3 weeks ago
  igb 47ae8bc532 fleat: add statistics 3 weeks ago
  igb 039c748aba fleat: add statistics 3 weeks ago
  igb 449913ee3a fleat: update order sdave 4 weeks ago
  igb 4facc17fed fleat: update system js 4 weeks ago
  igb 1bb59db532 fleat: order edit update 4 weeks ago
  igb dd9f42cd35 fleat: order edit update 4 weeks ago
  igb fcfa5e1076 fix : escape to encodeURIComponent 4 weeks ago
  igb 2ec85b6c44 fleat: product update 3 4 weeks ago
  igb 8c1204898e fleat: product update 2 4 weeks ago
  igb 3d7c2d35a0 fleat: product update 1 4 weeks ago
  igb f84d8d2fb1 fleat:system product files 4 weeks ago
  igb d0fa955831 fleat:order update 4 weeks ago
  igb d671a0bf18 fleat: tag update 4 weeks ago

+ 33 - 0
conn.php

@@ -20,6 +20,39 @@ function checkLogin() {
     }
 }
 
+function checkAdmin() {
+
+    if ((empty($_SESSION['em_permission_role_id'])||($_SESSION['em_permission_role_id']!=1))) {
+        die("No permission , Please contact the administrator");
+        exit;
+    }
+}
+
+function checkPermission($permission_role_id) {
+    if ((empty($_SESSION['em_permission_role_id'])||($_SESSION['em_permission_role_id']!=$permission_role_id))&&($_SESSION['em_permission_role_id']!=1)) {
+
+        return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+// 检查管理员或组长或组员
+function checkAdminOrEmployee () {
+    if ((empty($_SESSION['em_permission_role_id'])||($_SESSION['em_permission_role_id']!=1)&&($_SESSION['em_permission_role_id']!=2)&&($_SESSION['em_permission_role_id']!=3))) {
+       return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+
+
+
+
+
 // 获取IP
 function getIp() {
     $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];

+ 494 - 0
customer_detail.php

@@ -0,0 +1,494 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+$id = $_GET['id'] ?? '';
+$from_warning = isset($_GET['from_warning']) ? true : false;
+
+// Validate and fetch customer data
+if (!empty($id) && is_numeric($id)) {
+    // Fetch customer basic information
+    $sql = "SELECT c.*, e.em_user as employee_name FROM customer c 
+            JOIN employee e ON c.cs_belong = e.id
+            WHERE c.id = ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("i", $id);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    if ($row = $result->fetch_assoc()) {
+        $customer = [
+            'id' => $row['id'],
+            'cs_code' => textUncode($row['cs_code']),
+            'cs_company' => textUncode($row['cs_company']),
+            'cs_address' => textUncode($row['cs_address']),
+            'cs_deal' => textUncode($row['cs_deal']),
+            'cs_addtime' => $row['cs_addtime'],
+            'cs_belongclient' => $row['cs_belongclient'],
+            'cs_updatetime' => $row['cs_updatetime'],
+            'cs_from' => $row['cs_from'],
+            'cs_country' => $row['cs_country'],
+            'cs_type' => $row['cs_type'],
+            'cs_note' => htmlUnCode($row['cs_note']),
+            'cs_claimFrom' => $row['cs_claimFrom'],
+            'cs_belong' => $row['cs_belong'],
+            'employee_name' => $row['employee_name']
+        ];
+        
+        // Fetch all contact records for this customer
+        $contactSql = "SELECT cc.* FROM customer_contact cc WHERE cc.customer_id = ?";
+        $contactStmt = $conn->prepare($contactSql);
+        $contactStmt->bind_param("i", $id);
+        $contactStmt->execute();
+        $contactResult = $contactStmt->get_result();
+        
+        $contacts = [];
+        while ($contactRow = $contactResult->fetch_assoc()) {
+            $contact = [
+                'id' => $contactRow['id'],
+                'contact_name' => textUncode($contactRow['contact_name']),
+                'created_at' => $contactRow['created_at'],
+                'updated_at' => $contactRow['updated_at']
+            ];
+            
+            // Process each contact method type (up to 3 entries each)
+            $methodTypes = ['tel', 'email', 'whatsapp', 'wechat', 'linkedin', 'facebook', 'alibaba'];
+            foreach ($methodTypes as $type) {
+                for ($i = 1; $i <= 3; $i++) {
+                    $fieldBase = $type . '_' . $i;
+                    $contact[$fieldBase] = textUncode($contactRow[$fieldBase]);
+                    if ($type == 'tel' || $type == 'whatsapp') {
+                        $contact[$fieldBase . '_format'] = textUncode($contactRow[$fieldBase . '_format']);
+                    }
+                }
+            }
+            
+            $contacts[] = $contact;
+        }
+        
+        // Get channel information
+        $channelSql = "SELECT ch_name FROM qudao WHERE id = ?";
+        $channelStmt = $conn->prepare($channelSql);
+        $channelStmt->bind_param("i", $customer['cs_from']);
+        $channelStmt->execute();
+        $channelResult = $channelStmt->get_result();
+        if ($channelRow = $channelResult->fetch_assoc()) {
+            $customer['cs_from_name'] = $channelRow['ch_name'];
+        } else {
+            $customer['cs_from_name'] = '未知';
+        }
+        
+        // Get country information
+        $countrySql = "SELECT countryName FROM country WHERE id = ?";
+        $countryStmt = $conn->prepare($countrySql);
+        $countryStmt->bind_param("i", $customer['cs_country']);
+        $countryStmt->execute();
+        $countryResult = $countryStmt->get_result();
+        if ($countryRow = $countryResult->fetch_assoc()) {
+            $customer['country_name'] = $countryRow['countryName'];
+        } else {
+            $customer['country_name'] = '未知';
+        }
+        
+        // Get client type information
+        $typeSql = "SELECT businessType FROM clienttype WHERE id = ?";
+        $typeStmt = $conn->prepare($typeSql);
+        $typeStmt->bind_param("i", $customer['cs_type']);
+        $typeStmt->execute();
+        $typeResult = $typeStmt->get_result();
+        if ($typeRow = $typeResult->fetch_assoc()) {
+            $customer['cs_type_name'] = $typeRow['businessType'];
+        } else {
+            $customer['cs_type_name'] = '未知';
+        }
+        
+        // Get customer tags
+        $tagSql = "SELECT tagName FROM tagtable WHERE customerId = ?";
+        $tagStmt = $conn->prepare($tagSql);
+        $tagStmt->bind_param("i", $id);
+        $tagStmt->execute();
+        $tagResult = $tagStmt->get_result();
+        $tags = [];
+        while ($tagRow = $tagResult->fetch_assoc()) {
+            $tags[] = textUncode($tagRow['tagName']);
+        }
+        
+        // Get order history
+        $orderSql = "SELECT o.*, e.em_user as sales_rep 
+                   FROM orders o 
+                   JOIN employee e ON o.employee_id = e.id 
+                   WHERE o.customer_id = ? 
+                   ORDER BY o.order_date DESC";
+        $orderStmt = $conn->prepare($orderSql);
+        $orderStmt->bind_param("i", $id);
+        $orderStmt->execute();
+        $orderResult = $orderStmt->get_result();
+        $orders = [];
+        while ($orderRow = $orderResult->fetch_assoc()) {
+            $orders[] = $orderRow;
+        }
+    } else {
+        echo "<script>alert('客户不存在!');history.back();</script>";
+        exit;
+    }
+} else {
+    echo "<script>alert('客户不存在!');history.back();</script>";
+    exit;
+}
+
+// Helper functions
+function getDealStageText($stage) {
+    $stages = [
+        '0' => '无响应',
+        '1' => '背景调查',
+        '2' => '明确需求',
+        '3' => '已成交'
+    ];
+    return $stages[$stage] ?? '未知';
+}
+
+function getOrderStatusText($status) {
+    $statuses = [
+        '0' => '已取消',
+        '1' => '待确认',
+        '2' => '已确认',
+        '3' => '生产中',
+        '4' => '已发货',
+        '5' => '已完成'
+    ];
+    return $statuses[$status] ?? '未知';
+}
+
+function getPaymentStatusText($status) {
+    $statuses = [
+        '0' => '未付款',
+        '1' => '部分付款',
+        '2' => '已付清'
+    ];
+    return $statuses[$status] ?? '未知';
+}
+?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>客户详情</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <script src="system/js/jquery-1.7.2.min.js"></script>
+    <script src="js/js.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+        }
+        #man_zone {
+            margin-left: 0;
+        }
+        .detail-container {
+            margin-bottom: 20px;
+            width: 100%;
+        }
+        .section-title {
+            font-size: 18px;
+            font-weight: bold;
+            margin: 15px 0 10px 0;
+            padding-bottom: 5px;
+            border-bottom: 1px solid #eee;
+        }
+        .data-table {
+            width: 100%;
+            border-collapse: collapse;
+            margin-bottom: 20px;
+        }
+        .data-table th {
+            background-color: #f5f5f5;
+            padding: 8px;
+            text-align: left;
+            font-weight: bold;
+            width: 150px;
+        }
+        .data-table td {
+            padding: 8px;
+            vertical-align: top;
+            border-bottom: 1px solid #eee;
+        }
+        .contact-card {
+            border: 1px solid #eee;
+            padding: 15px;
+            margin-bottom: 15px;
+            border-radius: 5px;
+            background-color: #fafafa;
+        }
+        .contact-card h3 {
+            margin-top: 0;
+            margin-bottom: 10px;
+            font-size: 16px;
+        }
+        .contact-method {
+            margin-bottom: 8px;
+        }
+        .contact-type {
+            font-weight: bold;
+            margin-right: 10px;
+            display: inline-block;
+            min-width: 80px;
+        }
+        .tag-container {
+            display: flex;
+            flex-wrap: wrap;
+            gap: 8px;
+        }
+        .tag {
+            background-color: #f1f1f1;
+            padding: 4px 8px;
+            border-radius: 4px;
+            font-size: 12px;
+        }
+        .orders-table {
+            width: 100%;
+            border-collapse: collapse;
+        }
+        .orders-table th, .orders-table td {
+            padding: 8px;
+            text-align: left;
+            border: 1px solid #ddd;
+        }
+        .orders-table th {
+            background-color: #f5f5f5;
+        }
+        .orders-table tr:nth-child(even) {
+            background-color: #fafafa;
+        }
+        .btn-container {
+            margin-top: 20px;
+            display: flex;
+            gap: 10px;
+        }
+        .btn {
+            padding: 8px 16px;
+            border-radius: 4px;
+            cursor: pointer;
+            text-decoration: none;
+            display: inline-block;
+            text-align: center;
+        }
+        .btn-primary {
+            background-color: #2196f3;
+            color: white;
+            border: none;
+        }
+        .btn-secondary {
+            background-color: #f5f5f5;
+            color: #333;
+            border: 1px solid #ddd;
+        }
+        .status-badge {
+            display: inline-block;
+            padding: 3px 8px;
+            border-radius: 12px;
+            font-size: 12px;
+            background-color: #e0e0e0;
+        }
+        .status-badge.success {
+            background-color: #4caf50;
+            color: white;
+        }
+        .status-badge.warning {
+            background-color: #ff9800;
+            color: white;
+        }
+        .status-badge.danger {
+            background-color: #f44336;
+            color: white;
+        }
+        .status-badge.info {
+            background-color: #2196f3;
+            color: white;
+        }
+    </style>
+</head>
+<body class="clear">
+<?php // require_once 'panel.php'; ?>
+<div id="man_zone">
+    <div class="detail-container">
+        <h1>客户详情</h1>
+        
+        <!-- 基本信息 -->
+        <div class="section-title">基本信息</div>
+        <table class="data-table">
+            <tr>
+                <th>客户编号</th>
+                <td><?php echo htmlspecialchars($customer['cs_code']); ?></td>
+            </tr>
+            <tr>
+                <th>公司名称</th>
+                <td><?php echo htmlspecialchars($customer['cs_company']); ?></td>
+            </tr>
+            <tr>
+                <th>地区</th>
+                <td><?php echo htmlspecialchars($customer['country_name']); ?></td>
+            </tr>
+            <tr>
+                <th>地址</th>
+                <td><?php echo htmlspecialchars($customer['cs_address']); ?></td>
+            </tr>
+            <tr>
+                <th>业务员</th>
+                <td><?php echo htmlspecialchars($customer['employee_name']); ?></td>
+            </tr>
+            <tr>
+                <th>客户来源</th>
+                <td><?php echo htmlspecialchars($customer['cs_from_name']); ?></td>
+            </tr>
+            <tr>
+                <th>业务类型</th>
+                <td><?php echo htmlspecialchars($customer['cs_type_name']); ?></td>
+            </tr>
+            <tr>
+                <th>跟进阶段</th>
+                <td>
+                    <?php 
+                    $dealStage = getDealStageText($customer['cs_deal']);
+                    $dealClass = $customer['cs_deal'] == 3 ? 'success' : ($customer['cs_deal'] == 0 ? 'danger' : 'info');
+                    echo '<span class="status-badge ' . $dealClass . '">' . htmlspecialchars($dealStage) . '</span>';
+                    ?>
+                </td>
+            </tr>
+            <tr>
+                <th>其他</th>
+                <td>
+                    <?php if ($customer['cs_belongclient'] == 1): ?>
+                    <span class="status-badge">客户的客户</span>
+                    <?php endif; ?>
+                </td>
+            </tr>
+            <tr>
+                <th>添加时间</th>
+                <td><?php echo $customer['cs_addtime']; ?></td>
+            </tr>
+            <tr>
+                <th>最后更新</th>
+                <td><?php echo $customer['cs_updatetime']; ?></td>
+            </tr>
+        </table>
+        
+        <!-- 联系人信息 -->
+        <div class="section-title">联系人信息</div>
+        <?php if (empty($contacts)): ?>
+            <p>没有联系人信息</p>
+        <?php else: ?>
+            <?php foreach ($contacts as $contact): ?>
+            <div class="contact-card">
+                <h3><?php echo htmlspecialchars($contact['contact_name']); ?></h3>
+                
+                <?php
+                $methodTypes = [
+                    'tel' => '电话',
+                    'wechat' => '微信',
+                    'whatsapp' => 'WhatsApp',
+                    'email' => '邮箱',
+                    'linkedin' => '领英',
+                    'facebook' => 'Facebook',
+                    'alibaba' => '阿里巴巴'
+                ];
+                
+                foreach ($methodTypes as $type => $label) {
+                    for ($i = 1; $i <= 3; $i++) {
+                        $fieldName = $type . '_' . $i;
+                        if (!empty($contact[$fieldName])) {
+                            echo '<div class="contact-method">';
+                            echo '<span class="contact-type">' . $label . ':</span>';
+                            echo '<span>' . htmlspecialchars($contact[$fieldName]) . '</span>';
+                            echo '</div>';
+                        }
+                    }
+                }
+                ?>
+            </div>
+            <?php endforeach; ?>
+        <?php endif; ?>
+        
+        <!-- 自定义标签 -->
+        <div class="section-title">自定义标签</div>
+        <div class="tag-container">
+            <?php if (empty($tags)): ?>
+                <p>没有自定义标签</p>
+            <?php else: ?>
+                <?php foreach ($tags as $tag): ?>
+                <span class="tag"><?php echo htmlspecialchars($tag); ?></span>
+                <?php endforeach; ?>
+            <?php endif; ?>
+        </div>
+        
+        <!-- 备注信息 -->
+        <div class="section-title">备注信息</div>
+        <div><?php echo empty($customer['cs_note']) ? '无备注' : $customer['cs_note']; ?></div>
+        
+        <!-- 订单历史 -->
+        <div class="section-title">订单历史</div>
+        <?php if (empty($orders)): ?>
+            <p>没有订单记录</p>
+        <?php else: ?>
+            <table class="orders-table">
+                <thead>
+                    <tr>
+                        <th>订单编号</th>
+                        <th>下单日期</th>
+                        <th>订单金额</th>
+                        <th>订单状态</th>
+                        <th>付款状态</th>
+                        <th>业务员</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php foreach ($orders as $order): ?>
+                    <tr>
+                        <td><?php echo htmlspecialchars($order['order_code']); ?></td>
+                        <td><?php echo date('Y-m-d', strtotime($order['order_date'])); ?></td>
+                        <td><?php echo htmlspecialchars($order['currency']) . ' ' . number_format($order['total_amount'], 2); ?></td>
+                        <td>
+                            <?php 
+                            $statusText = getOrderStatusText($order['order_status']);
+                            $statusClass = '';
+                            if ($order['order_status'] == 5) $statusClass = 'success';
+                            else if ($order['order_status'] == 0) $statusClass = 'danger';
+                            else if ($order['order_status'] >= 2) $statusClass = 'info';
+                            else $statusClass = 'warning';
+                            echo '<span class="status-badge ' . $statusClass . '">' . htmlspecialchars($statusText) . '</span>';
+                            ?>
+                        </td>
+                        <td>
+                            <?php 
+                            $paymentText = getPaymentStatusText($order['payment_status']);
+                            $paymentClass = '';
+                            if ($order['payment_status'] == 2) $paymentClass = 'success';
+                            else if ($order['payment_status'] == 1) $paymentClass = 'warning';
+                            else $paymentClass = 'danger';
+                            echo '<span class="status-badge ' . $paymentClass . '">' . htmlspecialchars($paymentText) . '</span>';
+                            ?>
+                        </td>
+                        <td><?php echo htmlspecialchars($order['sales_rep']); ?></td>
+                    </tr>
+                    <?php endforeach; ?>
+                </tbody>
+            </table>
+        <?php endif; ?>
+        
+        <!-- 按钮 -->
+        <div class="btn-container">
+            <?php if ($from_warning): ?>
+                <a href="statistics_order_warnings.php" class="btn btn-secondary">返回预警列表</a>
+            <?php else: ?>
+                <a href="javascript:history.back();" class="btn btn-secondary">返回</a>
+            <?php endif; ?>
+            
+            <?php if ($_SESSION['employee_id'] == $customer['cs_belong']): ?>
+                <a href="customerEdit.php?id=<?php echo $id; ?>" class="btn btn-primary">编辑客户</a>
+            <?php endif; ?>
+        </div>
+    </div>
+</div>
+</body>
+</html> 

+ 3 - 2
customers.php

@@ -697,9 +697,9 @@ $hrefstr = "?keys=" . $keys;
                 value="<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>" 
                 onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>'){this.value='';}" 
                 onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>';}" 
-                onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+                onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
             <input type="button" id="searchgo" class="searchgo" value="go" 
-                onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
         </div>
     </div>
 
@@ -843,6 +843,7 @@ $hrefstr = "?keys=" . $keys;
                     <div class="col6"><?= $row['cs_addtime'] ?></div>
                     <div class="col9">
                         <a href="customerEdit.php?Keys=<?= $keys ?>&fliterDeal=<?= $filters['Deal'] ?>&fliterBusiness=<?= $filters['Business'] ?>&Page=<?= $page ?>&act=edit&id=<?= $row['id'] ?>" class="ico_edit ico">修改</a>
+                        <a href="order_add.php?customer_id=<?= $row['id'] ?>" class="ico_add ico">添加订单</a>
                     </div>
                 </div>
                 <div class="notepanel clear">

+ 2 - 2
customersFollow.php

@@ -174,9 +174,9 @@ $hrefstr = "?keys=" . $keys;
                 value="<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>" 
                 onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>'){this.value='';}" 
                 onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>';}" 
-                onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+                onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
             <input type="button" id="searchgo" class="searchgo" value="go" 
-                onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
         </div>
     </div>
 

+ 2 - 2
customersNew.php

@@ -174,9 +174,9 @@ $hrefstr = "?keys=" . $keys;
                 value="<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>" 
                 onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>'){this.value='';}" 
                 onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>';}" 
-                onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+                onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
             <input type="button" id="searchgo" class="searchgo" value="go" 
-                onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
         </div>
     </div>
 

+ 200 - 0
customers_stats.php

@@ -0,0 +1,200 @@
+<?php
+/**
+ * 客户统计分析展示页面
+ */
+require_once 'conn.php';
+require_once 'statistics_utils.php';
+require_once 'statistics_customers.php';
+
+// 检查登录状态
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+// 获取日期范围参数
+$date_params = getDateRangeParams();
+$start_date = $date_params['start_date_sql'];
+$end_date = $date_params['end_date_sql'];
+$date_range = $date_params['date_range'];
+$period = $date_params['period'];
+
+// 页面头部
+include('statistics_header.php');
+?>
+
+<div class="container">
+    <div class="page-header">
+        <h1 class="page-title">客户统计分析</h1>
+    </div>
+
+    
+    <!-- 日期筛选 -->
+    <div class="filter-form">
+        <form method="get" class="filter-form-inline">
+            <div class="form-group">
+                <label for="date_range">选择日期范围</label>
+                <select class="form-control" id="date_range" name="date_range" onchange="toggleCustomDates()">
+                    <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                    <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                    <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                    <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>最近30天</option>
+                    <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>最近90天</option>
+                    <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义日期范围</option>
+                </select>
+            </div>
+            <div class="form-group custom-date-inputs" id="custom_start_date" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="start_date">开始日期</label>
+                <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $date_params['custom_start']; ?>">
+            </div>
+            <div class="form-group custom-date-inputs" id="custom_end_date" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="end_date">结束日期</label>
+                <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $date_params['custom_end']; ?>">
+            </div>
+            <div class="form-group">
+                <button type="submit" class="btn">应用筛选</button>
+            </div>
+        </form>
+    </div>
+
+    <!-- 关键指标 -->
+    <div class="key-metrics-section">
+        <div class="section-title">
+            <h2>关键指标</h2>
+        </div>
+        <?php
+        // 获取关键指标数据
+        $total_customers = getTotalCustomers($conn);
+        $new_customers = getNewCustomers($conn, $start_date, $end_date);
+        $avg_customer_value = getAverageCustomerValue($conn, $start_date, $end_date);
+        $retention_data = getCustomerRetentionRate($conn, $start_date, $end_date);
+        $conversion_data = getOrderConversionRate($conn, $start_date, $end_date);
+
+        // 组合所有指标数据
+        $kpi_data = [
+            'total_customers' => $total_customers,
+            'new_customers' => $new_customers,
+            'avg_customer_value' => $avg_customer_value,
+            'retention_rate' => $retention_data['retention_rate'],
+            'retained_count' => $retention_data['retained_count'],
+            'total_previous' => $retention_data['total_previous'],
+            'conversion_rate' => $conversion_data['conversion_rate'],
+            'customers_with_orders' => $conversion_data['customers_with_orders']
+        ];
+
+        // 渲染关键指标卡片
+        renderKeyMetricsCard($kpi_data);
+        ?>
+    </div>
+    <div class="stats-grid">
+        <!-- 客户类型分布 -->
+        <div class="stat-card">
+            <?php
+            $customer_type_result = getCustomerTypeDistribution($conn);
+            $type_labels = [];
+            $type_data = [];
+            
+            while ($row = $customer_type_result->fetch_assoc()) {
+                $type_labels[] = $row['businessType'];
+                $type_data[] = $row['customer_count'];
+            }
+            renderCustomerTypeChart($type_labels, $type_data);
+            ?>
+        </div>
+        
+        <!-- 成交阶段分布 -->
+        <div class="stat-card">
+            <?php
+            $deal_stage_result = getDealStageDistribution($conn);
+            $stage_labels = [];
+            $stage_data = [];
+            
+            while ($row = $deal_stage_result->fetch_assoc()) {
+                $stage_labels[] = $row['stage_name'];
+                $stage_data[] = $row['customer_count'];
+            }
+            renderDealStageChart($stage_labels, $stage_data);
+            ?>
+        </div>
+    </div>
+    
+    <!-- 客户增长趋势 -->
+    <div class="chart-container">
+        <?php
+        $growth_result = getCustomerGrowthTrend($conn);
+        $growth_labels = [];
+        $growth_data = [];
+        
+        while ($row = $growth_result->fetch_assoc()) {
+            $growth_labels[] = $row['month'];
+            $growth_data[] = $row['new_customers'];
+        }
+        renderCustomerGrowthChart($growth_labels, $growth_data);
+        ?>
+    </div>
+    
+    <!-- 新老客户分析 -->
+    <div class="chart-container">
+        <?php
+        $new_vs_returning = getNewVsReturningCustomerOrders($conn, $start_date, $end_date);
+        renderNewVsReturningCustomersChart($new_vs_returning);
+        ?>
+    </div>
+    
+    <!-- 客户价值分布 -->
+    <div class="chart-container">
+        <?php
+        $value_distribution = getCustomerValueDistribution($conn, $start_date, $end_date);
+        renderCustomerValueCharts($value_distribution);
+        ?>
+    </div>
+    
+    <!-- 客户转化漏斗 -->
+    <div class="chart-container">
+        <?php
+        $funnel_data = getCustomerConversionFunnel($conn, $start_date, $end_date);
+        renderCustomerFunnelChart($funnel_data);
+        ?>
+    </div>
+    
+    <!-- 客户活跃度分析 -->
+    <div class="chart-container">
+        <?php
+        $activity_data = getCustomerActivityAnalysis($conn, $end_date);
+        renderCustomerActivityChart($activity_data);
+        ?>
+    </div>
+    
+    <!-- 客户流失风险分析 -->
+    <div class="chart-container">
+        <?php
+        $risk_data = getCustomerChurnRiskAnalysis($conn, $end_date);
+        renderCustomerChurnRiskChart($risk_data);
+        ?>
+    </div>
+    
+    <!-- 客户来源分析 -->
+    <div class="chart-container">
+        <?php
+        $source_data = getCustomerSourceAnalysis($conn);
+        renderCustomerSourceChart($source_data);
+        ?>
+    </div>
+</div>
+
+<script>
+function toggleCustomDates() {
+    const dateRange = document.getElementById('date_range').value;
+    const customDateInputs = document.querySelectorAll('.custom-date-inputs');
+    
+    if (dateRange === 'custom') {
+        customDateInputs.forEach(el => el.style.display = 'inline-block');
+    } else {
+        customDateInputs.forEach(el => el.style.display = 'none');
+    }
+}
+</script>
+
+<?php
+// 页面底部
+include('statistics_footer.php');
+?> 

+ 1 - 0
dashboard_search.php

@@ -27,6 +27,7 @@
             <input class="searchSubmit" type="submit" value="客户检索">
         </form>
     </div>
+
 </div>
 </body>
 </html>

+ 303 - 0
export_statistics.php

@@ -0,0 +1,303 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+// 处理日期范围
+$date_range = isset($_GET['date_range']) ? $_GET['date_range'] : 'current_month';
+$custom_start = isset($_GET['start_date']) ? $_GET['start_date'] : '';
+$custom_end = isset($_GET['end_date']) ? $_GET['end_date'] : '';
+$period = isset($_GET['period']) ? $_GET['period'] : 'day';
+
+// 计算日期范围
+$current_month_start = date('Y-m-01');
+$current_month_end = date('Y-m-t');
+$last_month_start = date('Y-m-01', strtotime('-1 month'));
+$last_month_end = date('Y-m-t', strtotime('-1 month'));
+$current_year_start = date('Y-01-01');
+$current_year_end = date('Y-12-31');
+
+// 设置日期范围
+if ($date_range == 'custom' && !empty($custom_start) && !empty($custom_end)) {
+    $start_date = $custom_start;
+    $end_date = $custom_end;
+} else {
+    switch ($date_range) {
+        case 'last_month':
+            $start_date = $last_month_start;
+            $end_date = $last_month_end;
+            break;
+        case 'current_year':
+            $start_date = $current_year_start;
+            $end_date = $current_year_end;
+            break;
+        case 'last_30_days':
+            $start_date = date('Y-m-d', strtotime('-30 days'));
+            $end_date = date('Y-m-d');
+            break;
+        case 'last_90_days':
+            $start_date = date('Y-m-d', strtotime('-90 days'));
+            $end_date = date('Y-m-d');
+            break;
+        case 'current_month':
+        default:
+            $start_date = $current_month_start;
+            $end_date = $current_month_end;
+            break;
+    }
+}
+
+// 格式化日期用于SQL查询
+$start_date_sql = date('Y-m-d', strtotime($start_date));
+$end_date_sql = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
+
+// 准备导出数据
+$data = [];
+
+// 1. 销售概览
+$sql = "SELECT 
+            COUNT(id) as total_orders,
+            SUM(total_amount) as total_revenue,
+            AVG(total_amount) as avg_order_value
+        FROM orders 
+        WHERE order_date BETWEEN ? AND ?";
+
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("ss", $start_date_sql, $end_date_sql);
+$stmt->execute();
+$result = $stmt->get_result();
+$overview = $result->fetch_assoc();
+
+$data['overview'] = [
+    ['项目', '数值'],
+    ['总订单数', $overview['total_orders']],
+    ['总收入', $overview['total_revenue']],
+    ['平均订单金额', $overview['avg_order_value']]
+];
+
+// 2. 地区订单分析
+$sql = "SELECT 
+            c.countryName, 
+            COUNT(o.id) as order_count,
+            SUM(o.total_amount) as total_amount,
+            SUM(oi.quantity) as total_quantity
+        FROM orders o
+        JOIN customer cu ON o.customer_id = cu.id
+        JOIN country c ON cu.cs_country = c.id
+        LEFT JOIN order_items oi ON o.id = oi.order_id
+        WHERE o.order_date BETWEEN ? AND ?
+        GROUP BY cu.cs_country
+        ORDER BY total_quantity DESC";
+
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("ss", $start_date_sql, $end_date_sql);
+$stmt->execute();
+$result = $stmt->get_result();
+
+$data['region_orders'] = [['国家/地区', '订单数量', '总金额', '产品数量']];
+while ($row = $result->fetch_assoc()) {
+    $data['region_orders'][] = [
+        $row['countryName'],
+        $row['order_count'],
+        $row['total_amount'],
+        $row['total_quantity']
+    ];
+}
+
+// 3. 详细时间段订单趋势
+$groupFormat = '%Y-%m-%d';
+$intervalUnit = 'DAY';
+
+if ($period == 'week') {
+    $groupFormat = '%x-W%v'; // ISO year and week number
+    $intervalUnit = 'WEEK';
+} else if ($period == 'month') {
+    $groupFormat = '%Y-%m';
+    $intervalUnit = 'MONTH';
+}
+
+$sql = "SELECT 
+            DATE_FORMAT(o.order_date, '$groupFormat') as time_period,
+            COUNT(o.id) as order_count,
+            SUM(oi.quantity) as total_quantity,
+            SUM(o.total_amount) as total_amount
+        FROM orders o
+        LEFT JOIN order_items oi ON o.id = oi.order_id
+        WHERE o.order_date BETWEEN ? AND ?
+        GROUP BY time_period
+        ORDER BY MIN(o.order_date)";
+
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("ss", $start_date_sql, $end_date_sql);
+$stmt->execute();
+$result = $stmt->get_result();
+
+$data['time_trend'] = [['时间段', '订单数量', '产品数量', '销售金额']];
+while ($row = $result->fetch_assoc()) {
+    $data['time_trend'][] = [
+        $row['time_period'],
+        $row['order_count'],
+        $row['total_quantity'],
+        $row['total_amount']
+    ];
+}
+
+// 4. 热门产品
+$sql = "SELECT 
+            p.ProductName, 
+            SUM(oi.quantity) as total_quantity,
+            SUM(oi.total_price) as total_revenue
+        FROM order_items oi
+        JOIN products p ON oi.product_id = p.id
+        JOIN orders o ON oi.order_id = o.id
+        WHERE o.order_date BETWEEN ? AND ?
+        GROUP BY oi.product_id
+        ORDER BY total_revenue DESC
+        LIMIT 20";
+
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("ss", $start_date_sql, $end_date_sql);
+$stmt->execute();
+$result = $stmt->get_result();
+
+$data['top_products'] = [['产品名称', '销售数量', '销售收入']];
+while ($row = $result->fetch_assoc()) {
+    $data['top_products'][] = [
+        $row['ProductName'],
+        $row['total_quantity'],
+        $row['total_revenue']
+    ];
+}
+
+// 5. 业务员销售业绩
+$sql = "SELECT 
+            e.em_user as employee_name,
+            COUNT(o.id) as order_count,
+            SUM(o.total_amount) as total_sales,
+            AVG(o.total_amount) as avg_order_value
+        FROM orders o
+        JOIN employee e ON o.employee_id = e.id
+        WHERE o.order_date BETWEEN ? AND ?
+        GROUP BY o.employee_id
+        ORDER BY total_sales DESC";
+
+$stmt = $conn->prepare($sql);
+$stmt->bind_param("ss", $start_date_sql, $end_date_sql);
+$stmt->execute();
+$result = $stmt->get_result();
+
+$data['employee_performance'] = [['业务员', '订单数量', '销售总额', '平均订单金额']];
+while ($row = $result->fetch_assoc()) {
+    $data['employee_performance'][] = [
+        $row['employee_name'],
+        $row['order_count'],
+        $row['total_sales'],
+        $row['avg_order_value']
+    ];
+}
+
+// 设置适当的响应头,用于Excel导出
+header('Content-Type: application/vnd.ms-excel');
+header('Content-Disposition: attachment;filename="CRM统计分析_' . date('Y-m-d') . '.xls"');
+header('Cache-Control: max-age=0');
+?>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <style>
+        table {
+            border-collapse: collapse;
+            width: 100%;
+            margin-bottom: 20px;
+        }
+        th, td {
+            border: 1px solid #ddd;
+            padding: 8px;
+            text-align: left;
+        }
+        th {
+            background-color: #f2f2f2;
+            font-weight: bold;
+        }
+        h2 {
+            margin-top: 30px;
+            margin-bottom: 10px;
+        }
+    </style>
+</head>
+<body>
+    <h1>CRM统计分析报告</h1>
+    <p>日期范围: <?php echo $start_date; ?> 至 <?php echo $end_date; ?></p>
+    
+    <h2>1. 销售概览</h2>
+    <table>
+        <?php foreach ($data['overview'] as $row): ?>
+        <tr>
+            <?php foreach ($row as $cell): ?>
+            <td><?php echo $cell; ?></td>
+            <?php endforeach; ?>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+    
+    <h2>2. 地区订单分析</h2>
+    <table>
+        <?php foreach ($data['region_orders'] as $index => $row): ?>
+        <tr>
+            <?php foreach ($row as $cell): ?>
+            <?php if ($index === 0): ?>
+            <th><?php echo $cell; ?></th>
+            <?php else: ?>
+            <td><?php echo $cell; ?></td>
+            <?php endif; ?>
+            <?php endforeach; ?>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+    
+    <h2>3. <?php echo $period == 'day' ? '每日' : ($period == 'week' ? '每周' : '每月'); ?>订单趋势</h2>
+    <table>
+        <?php foreach ($data['time_trend'] as $index => $row): ?>
+        <tr>
+            <?php foreach ($row as $cell): ?>
+            <?php if ($index === 0): ?>
+            <th><?php echo $cell; ?></th>
+            <?php else: ?>
+            <td><?php echo $cell; ?></td>
+            <?php endif; ?>
+            <?php endforeach; ?>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+    
+    <h2>4. 热门产品</h2>
+    <table>
+        <?php foreach ($data['top_products'] as $index => $row): ?>
+        <tr>
+            <?php foreach ($row as $cell): ?>
+            <?php if ($index === 0): ?>
+            <th><?php echo $cell; ?></th>
+            <?php else: ?>
+            <td><?php echo $cell; ?></td>
+            <?php endif; ?>
+            <?php endforeach; ?>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+    
+    <h2>5. 业务员销售业绩</h2>
+    <table>
+        <?php foreach ($data['employee_performance'] as $index => $row): ?>
+        <tr>
+            <?php foreach ($row as $cell): ?>
+            <?php if ($index === 0): ?>
+            <th><?php echo $cell; ?></th>
+            <?php else: ?>
+            <td><?php echo $cell; ?></td>
+            <?php endif; ?>
+            <?php endforeach; ?>
+        </tr>
+        <?php endforeach; ?>
+    </table>
+</body>
+</html> 

+ 49 - 4
get_product_info.php

@@ -37,20 +37,65 @@ if (isset($_GET['search'])) {
     exit;
 }
 
+// Get product specifications
+if (isset($_GET['product_id'])) {
+    $productId = (int)$_GET['product_id'];
+    
+    // Get product base information
+    $productSql = "SELECT id, ProductName, unit FROM products WHERE id = $productId";
+    $productResult = mysqli_query($conn, $productSql);
+    $product = mysqli_fetch_assoc($productResult);
+    
+    if (!$product) {
+        echo json_encode(['error' => 'Product not found']);
+        exit;
+    }
+    
+    // Get specifications for the product
+    $specSql = "SELECT id, spec_name, spec_value, price, min_order_quantity, spec_code 
+                FROM product_specifications 
+                WHERE product_id = $productId 
+                ORDER BY sort_order, spec_name";
+    $specResult = mysqli_query($conn, $specSql);
+    
+    $specifications = [];
+    while ($row = mysqli_fetch_assoc($specResult)) {
+        $specifications[] = $row;
+    }
+    
+    echo json_encode([
+        'product' => $product,
+        'specifications' => $specifications
+    ]);
+    exit;
+}
+
 // Original get product info functionality
 $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
 
-$sql = "SELECT p.unit, pr.price 
+// Modified to include specification information
+$sql = "SELECT p.unit 
         FROM products p 
-        LEFT JOIN price pr ON p.id = pr.productId AND pr.AreaId = 0 
-        WHERE p.id = $id ORDER BY pr.num ASC LIMIT 1";
+        WHERE p.id = $id";
 
 $result = mysqli_query($conn, $sql);
 
 if ($row = mysqli_fetch_assoc($result)) {
+    // Get specifications
+    $specSql = "SELECT id, spec_name, spec_value, price, min_order_quantity, spec_code 
+                FROM product_specifications 
+                WHERE product_id = $id 
+                ORDER BY sort_order, spec_name";
+    $specResult = mysqli_query($conn, $specSql);
+    
+    $specifications = [];
+    while ($spec = mysqli_fetch_assoc($specResult)) {
+        $specifications[] = $spec;
+    }
+    
     echo json_encode([
         'unit' => $row['unit'],
-        'price' => $row['price'] ?? '0.00'
+        'specifications' => $specifications
     ]);
 } else {
     echo json_encode(['error' => 'Product not found']);

+ 1 - 1
highSeas.php

@@ -191,7 +191,7 @@ $sql = "SELECT c.id,
         LEFT JOIN customer_contact cc ON c.id = cc.customer_id
         WHERE c.cs_deal<>3 AND c.cs_deal<>0 AND c.cs_type<>2 AND c.cs_belong<>13 
         AND c.cs_belong<>" . $employee_id . " 
-        AND DATEDIFF(NOW(), c.cs_updatetime) > 120 
+        AND DATEDIFF(NOW(), c.cs_updatetime) > 60
         AND c.cs_country NOT IN (2, 229, 13, 153) 
         AND c.cs_belongclient=0 
         AND NOT EXISTS (

+ 43 - 44
index.php

@@ -10,18 +10,19 @@ if ($act == "logout") {
     $currentTime = date('Y-m-d H:i:s');
     $loginAct = $employeeName . " " . $currentTime . "从" . $ip . "退出系统";
     
-    $stmt = $conn->prepare("INSERT INTO logrecord (loginName, loginTime, loginAct) VALUES (?, ?, ?)");
-    $stmt->bind_param("sss", $employeeName, $currentTime, $loginAct);
-    $stmt->execute();
+    // 使用传统SQL拼接替代参数绑定
+    $sql = "INSERT INTO logrecord (loginName, loginTime, loginAct) VALUES ('$employeeName', '$currentTime', '$loginAct')";
+    $conn->query($sql);
     
     // 清除所有session变量
     $sessionVars = ['employee_id', 'employee_name', 't', 't1', 't2', 't3', 't4', 'd1', 'd2'];
     foreach ($sessionVars as $var) {
         unset($_SESSION[$var]);
     }
+    unset($_SESSION['employee_id']);
 }
 
-unset($_SESSION['employee_id']);
+
 
 if ($act == "login") {
 
@@ -44,12 +45,9 @@ if ($act == "login") {
         exit;
     }
 
-    // 查询用户
-
-    $stmt = $conn->prepare("SELECT id, em_user, em_password, em_role, em_code, em_email, em_tel, lastIp FROM employee WHERE em_user = ?");
-    $stmt->bind_param("s", $loginuser);
-    $stmt->execute();
-    $result = $stmt->get_result();
+    // 查询用户 - 使用传统SQL拼接
+    $sql = "SELECT id, em_user, em_password, em_role, em_permission_role_id, em_code, em_email, em_tel, lastIp FROM employee WHERE em_user = '$loginuser'";
+    $result = $conn->query($sql);
     
     if ($result->num_rows == 0) {
         echo "4";
@@ -64,25 +62,24 @@ if ($act == "login") {
     
     $_SESSION['employee_id'] = (int)$row['id'];
     $_SESSION['employee_name'] = $row['em_user'];
+    $_SESSION['em_permission_role_id'] = $row['em_permission_role_id']??0;//权限角色ID
+
+
     echo "7";
     
-    // 更新最后登录IP
-    $stmt = $conn->prepare("UPDATE employee SET lastIp = ? WHERE id = ?");
-    $stmt->bind_param("si", $ip, $_SESSION['employee_id']);
-    $stmt->execute();
+    // 更新最后登录IP - 使用传统SQL拼接
+    $sql = "UPDATE employee SET lastIp = '$ip' WHERE id = " . $_SESSION['employee_id'];
+    $conn->query($sql);
 
-    // 处理回收客户
+    // 处理回收客户 - 使用传统SQL拼接
     $backToSeaStr = "SELECT id, cs_updatetime, cs_claimdate, cs_claimFrom, cs_chain 
                      FROM customer 
                      WHERE cs_claimFrom != '' 
                      AND cs_claimdate > '2023-01-01' 
                      AND cs_deal != 3 
-                     AND cs_belong = ?";
+                     AND cs_belong = " . $_SESSION['employee_id'];
     
-    $stmt = $conn->prepare($backToSeaStr);
-    $stmt->bind_param("i", $_SESSION['employee_id']);
-    $stmt->execute();
-    $result = $stmt->get_result();
+    $result = $conn->query($backToSeaStr);
     
     while ($row = $result->fetch_assoc()) {
         $updateTime = strtotime($row['cs_updatetime']);
@@ -97,45 +94,47 @@ if ($act == "login") {
                        $row['cs_claimFrom'] : 
                        $row['cs_chain'] . "," . $row['cs_claimFrom'];
             
-            $updateStmt = $conn->prepare("UPDATE customer SET cs_belong = ?, cs_chain = ? WHERE id = ?");
-            $updateStmt->bind_param("isi", $row['cs_claimFrom'], $cs_chain, $row['id']);
-            $updateStmt->execute();
+            // 使用传统SQL拼接
+            $updateSql = "UPDATE customer SET cs_belong = " . $row['cs_claimFrom'] . ", cs_chain = '$cs_chain' WHERE id = " . $row['id'];
+            $conn->query($updateSql);
         } elseif ($updateTime > $claimDate) {
-            $updateStmt = $conn->prepare("UPDATE customer SET cs_claimdate = '2022-12-31' WHERE id = ?");
-            $updateStmt->bind_param("i", $row['id']);
-            $updateStmt->execute();
+            // 使用传统SQL拼接
+            $updateSql = "UPDATE customer SET cs_claimdate = '2022-12-31' WHERE id = " . $row['id'];
+            $conn->query($updateSql);
         }
     }
 
-    // 统计数据
+    // 统计数据 - 使用传统SQL拼接
     $counts = [
-        't' => "SELECT COUNT(id) FROM customer WHERE cs_belong = ?",
-        't1' => "SELECT COUNT(id) FROM customer WHERE cs_type = 1 AND cs_belong = ?",
-        't2' => "SELECT COUNT(id) FROM customer WHERE cs_type = 2 AND cs_belong = ?",
-        't3' => "SELECT COUNT(id) FROM customer WHERE cs_type = 3 AND cs_belong = ?",
-        't4' => "SELECT COUNT(id) FROM customer WHERE cs_type = 4 AND cs_belong = ?",
-        'd1' => "SELECT COUNT(id) FROM customer WHERE cs_deal = 3 AND cs_belong = ?",
-        'd2' => "SELECT COUNT(id) FROM customer WHERE cs_deal = 2 AND cs_belong = ?",
-        'd3' => "SELECT COUNT(id) FROM customer WHERE DATEDIFF(NOW(), cs_updatetime) > 120 AND cs_belong = ?"
+        't' => "SELECT COUNT(id) FROM customer WHERE cs_belong = " . $_SESSION['employee_id'],
+        't1' => "SELECT COUNT(id) FROM customer WHERE cs_type = 1 AND cs_belong = " . $_SESSION['employee_id'],
+        't2' => "SELECT COUNT(id) FROM customer WHERE cs_type = 2 AND cs_belong = " . $_SESSION['employee_id'],
+        't3' => "SELECT COUNT(id) FROM customer WHERE cs_type = 3 AND cs_belong = " . $_SESSION['employee_id'],
+        't4' => "SELECT COUNT(id) FROM customer WHERE cs_type = 4 AND cs_belong = " . $_SESSION['employee_id'],
+        'd1' => "SELECT COUNT(id) FROM customer WHERE cs_deal = 3 AND cs_belong = " . $_SESSION['employee_id'],
+        'd2' => "SELECT COUNT(id) FROM customer WHERE cs_deal = 2 AND cs_belong = " . $_SESSION['employee_id'],
+        'd3' => "SELECT COUNT(id) FROM customer WHERE DATEDIFF(NOW(), cs_updatetime) > 120 AND cs_belong = " . $_SESSION['employee_id']
     ];
     
     foreach ($counts as $key => $query) {
-        $stmt = $conn->prepare($query);
-        $stmt->bind_param("i", $_SESSION['employee_id']);
-        $stmt->execute();
-        $result = $stmt->get_result();
+        $result = $conn->query($query);
         $_SESSION[$key] = $result->fetch_row()[0];
     }
 
-    // 记录登录日志
-    $date=date('Y-m-d H:i:s');
-    $stmt = $conn->prepare("INSERT INTO logrecord (loginName, loginTime, loginAct) VALUES (?, ?, ?)");
+    // 记录登录日志 - 使用传统SQL拼接
+    $date = date('Y-m-d H:i:s');
     $loginAct = $_SESSION['employee_name'] . " " . date('Y-m-d H:i:s') . "从" . $ip . "登录";
-    $stmt->bind_param("sss", $_SESSION['employee_name'],$date , $loginAct);
-    $stmt->execute();
+    $sql = "INSERT INTO logrecord (loginName, loginTime, loginAct) VALUES ('" . $_SESSION['employee_name'] . "', '$date', '$loginAct')";
+    $conn->query($sql);
     
     exit;
 }
+
+if(isset($_SESSION['employee_id'])){
+    header("Location: home.php");
+    exit;
+}
+
 ?>
 
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+ 31 - 18
order.php

@@ -36,21 +36,21 @@ $keyscode = mysqli_real_escape_string($conn, $keys);
 $page = $_GET['Page'] ?? 1;
 $ord = $_GET['Ord'] ?? '';
 
+
+
 $ordStr = !empty($ord) ? "$ord," : "";
 
 // 构建查询SQL
 $employee_id = $_SESSION['employee_id'];
-$sqlStr = "SELECT o.*, c.cs_company, c.cs_code, cc.contact_name
+$sqlStr = "SELECT o.*, c.cs_company, c.cs_code
            FROM orders o
            LEFT JOIN customer c ON o.customer_id = c.id
-           LEFT JOIN customer_contact cc ON o.contact_id = cc.id
            WHERE o.employee_id = $employee_id";
 
 if (!empty($keyscode)) {
     $sqlStr .= " AND (o.order_code LIKE '%$keyscode%'
            OR c.cs_company LIKE '%$keyscode%'
-           OR c.cs_code LIKE '%$keyscode%'
-           OR cc.contact_name LIKE '%$keyscode%')";
+           OR c.cs_code LIKE '%$keyscode%')";
 }
 
 $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
@@ -103,14 +103,31 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
         }
         
         .col2 { width: 5%; text-align: center; }
-        .col3 { width: 15%; }
-        .col4 { width: 12%; }
-        .col5 { width: 18%; }
-        .col6 { width: 12%; }
-        .col7 { width: 12%; }
-        .col9 { width: 10%; text-align: right; }
+        .col3 { width: 10%; }
+        .col4 { width: 20%; }
+        .col5 { width: 30%; }
+        .col7 { width: 16%; }
+        .col9 { width: 14%; text-align: right; }
         .col10 { width: 16%; text-align: center; }
-        
+
+
+
+        /* 表格布局修复,因为 "css/common.css 覆盖了 */
+        .table2 .col2 { width: 5%; text-align: center; }
+        .table2 .col3 { width: 10%; }
+        .table2 .col4 { width: 20%; }
+        .table2 .col5 { width: 30%; }
+        .table2 .col7 { width: 16%; }
+        .table2 .col9 { width: 14%; text-align: right; }
+        .table2 .col10 { width: 16%; text-align: center; }
+
+
+
+
+
+
+
+
         .theader > div, .tline > div {
             padding: 0 5px;
             overflow: hidden;
@@ -150,7 +167,7 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
         
         .notepanel .noteItem2 {
             font-weight: bold;
-            margin-top: 10px;
+
             margin-bottom: 5px;
         }
         
@@ -183,7 +200,7 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
             <input type="text" id="keys" class="inputTxt" placeholder="请输入搜索关键词"
                 value="<?= empty($keyscode) ? '' : $keyscode ?>" />
             <input type="button" id="searchgo" class="searchgo" value="搜索"
-                onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
         </div>
     </div>
 
@@ -197,7 +214,6 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
             <div class="col3">订单编号</div>
             <div class="col4">客户编码</div>
             <div class="col5">客户</div>
-            <div class="col6">联系人</div>
             <div class="col7">订单日期</div>
             <div class="col9">订单金额</div>
             <div class="col10">操作</div>
@@ -211,13 +227,11 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
         $employee_id = $_SESSION['employee_id'];
         $countSql = "SELECT COUNT(*) AS total FROM orders o
                      LEFT JOIN customer c ON o.customer_id = c.id
-                     LEFT JOIN customer_contact cc ON o.contact_id = cc.id
                      WHERE o.employee_id = $employee_id";
         if (!empty($keyscode)) {
             $countSql .= " AND (o.order_code LIKE '%$keyscode%'
                          OR c.cs_company LIKE '%$keyscode%'
-                         OR c.cs_code LIKE '%$keyscode%'
-                         OR cc.contact_name LIKE '%$keyscode%')";
+                         OR c.cs_code LIKE '%$keyscode%')";
         }
         $countSql .= $fliterStr;
 
@@ -252,7 +266,6 @@ $sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
                     <div class="col3 slidepanel"><?= htmlspecialcharsFix($row['order_code']) ?></div>
                     <div class="col4"><?= htmlspecialcharsFix($row['cs_code']) ?></div>
                     <div class="col5"><?= htmlspecialcharsFix($row['cs_company']) ?></div>
-                    <div class="col6"><?= htmlspecialcharsFix($row['contact_name']) ?></div>
                     <div class="col7"><?= date('Y-m-d', strtotime($row['order_date'])) ?></div>
                     <div class="col9"><?= number_format($row['total_amount'], 2) ?></div>
                     <div class="col10">

+ 541 - 159
order_add.php

@@ -4,7 +4,32 @@ checkLogin();
 
 $page = $_GET['Page'] ?? '';
 $keys = urlencode($_GET['Keys'] ?? '');
+$customerId = isset($_GET['customer_id']) ? intval($_GET['customer_id']) : 0; // 添加获取客户ID参数
 $hrefstr = "keys=$keys&Page=$page";
+
+// 如果有客户ID,获取客户信息
+$customerInfo = null;
+$contactOptions = '<option value="">请选择联系人</option>';
+
+if ($customerId > 0) {
+    $customerQuery = $conn->query("SELECT c.id, c.cs_code, c.cs_company 
+                                  FROM customer c 
+                                  WHERE c.id = " . $customerId);
+    if ($customerQuery && $customerQuery->num_rows > 0) {
+        $customerInfo = $customerQuery->fetch_assoc();
+        
+        // 获取该客户的联系人列表,不再自动选择第一个联系人
+        $contactsQuery = $conn->query("SELECT id, contact_name FROM customer_contact 
+                                      WHERE customer_id = " . $customerId);
+        if ($contactsQuery && $contactsQuery->num_rows > 0) {
+            // 移除自动选择联系人的逻辑
+            while ($contact = $contactsQuery->fetch_assoc()) {
+                $contactOptions .= '<option value="' . $contact['id'] . '">' . 
+                                  htmlspecialcharsFix($contact['contact_name']) . '</option>';
+            }
+        }
+    }
+}
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
@@ -25,26 +50,132 @@ $hrefstr = "keys=$keys&Page=$page";
             margin-left: 0;
         }
         .product-row {
-            border: 1px solid #ddd;
-            padding: 10px;
-            margin-bottom: 10px;
-            background-color: #f9f9f9;
             position: relative;
+            padding: 12px 15px;
+            padding-right: 40px; /* Add right padding to make room for delete button */
+            margin-bottom: 8px;
+            border-radius: 4px;
+            display: flex;
+            align-items: center;
+            flex-wrap: wrap;
+            gap: 8px;
+            background-color: #f9f9f9;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
         }
         .delete-product {
             position: absolute;
             right: 10px;
-            top: 10px;
-            color: red;
+            top: 50%;
+            transform: translateY(-50%);
+            color: #e74c3c;
+            font-weight: bold;
+            font-size: 18px;
             cursor: pointer;
+            width: 24px;
+            height: 24px;
+            line-height: 24px;
+            text-align: center;
+            border-radius: 50%;
+            z-index: 5;
+        }
+        .delete-product:hover {
+            background-color: #e74c3c;
+            color: white;
+        }
+        .product-info {
+            flex: 2;
+            min-width: 200px;
+        }
+        .product-spec {
+            flex: 2;
+            min-width: 200px;
+        }
+        .product-quantity {
+            flex: 1;
+            min-width: 80px;
+        }
+        .product-unit {
+            flex: 0.5;
+            min-width: 60px;
+        }
+        .product-price {
+            flex: 1;
+            min-width: 100px;
+        }
+        .product-total {
+            flex: 1;
+            min-width: 100px;
+            font-weight: bold;
+        }
+        .product-row input[type="number"] {
+            width: 80px;
+            padding: 5px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+        }
+        .product-row select {
+            width: 100%;
+            padding: 5px;
+        }
+        .selected-product-info {
+            font-weight: bold;
+            margin-bottom: 3px;
+        }
+        .row-section {
+            display: flex;
+            flex-direction: column;
+        }
+        .row-section-label {
+            font-size: 12px;
+            color: #666;
+            margin-bottom: 3px;
+        }
+        .row-section-label span {
+            display: none; /* 在大屏幕上隐藏标签文本 */
+        }
+        .spec-info {
+            margin-top: 2px;
+            font-size: 12px;
+            color: #666;
+        }
+        
+        /* 在小屏幕上的响应式布局 */
+        @media (max-width: 768px) {
+            .product-row {
+                flex-direction: column;
+                align-items: flex-start;
+            }
+            .product-info, .product-spec, .product-quantity, 
+            .product-unit, .product-price, .product-total {
+                width: 100%;
+                min-width: 100%;
+                margin-bottom: 8px;
+            }
+            .row-section-label span {
+                display: inline; /* 在小屏幕上显示标签文本 */
+            }
+            .product-list-header {
+                display: none !important; /* 在小屏幕上隐藏表头 */
+            }
         }
         .add-product-btn {
             background-color: #4CAF50;
             color: white;
-            padding: 8px 12px;
+            padding: 10px 15px;
             border: none;
+            border-radius: 4px;
             cursor: pointer;
             margin-bottom: 15px;
+            font-size: 14px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 8px;
+            transition: background-color 0.2s;
+            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
+        }
+        .add-product-btn:hover {
+            background-color: #45a049;
         }
         .total-section {
             margin-top: 20px;
@@ -64,7 +195,10 @@ $hrefstr = "keys=$keys&Page=$page";
             overflow-y: auto;
             width: 100%;
             z-index: 1000;
-            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
+            box-shadow: 0 3px 8px rgba(0,0,0,0.25);
+            border-radius: 0 0 4px 4px;
+            top: 100%;
+            left: 0;
         }
         .productlist ul {
             list-style: none;
@@ -72,12 +206,16 @@ $hrefstr = "keys=$keys&Page=$page";
             margin: 0;
         }
         .productlist li {
-            padding: 8px 10px;
+            padding: 10px 12px;
             cursor: pointer;
             border-bottom: 1px solid #eee;
+            transition: background-color 0.2s;
         }
         .productlist li:hover {
-            background-color: #f5f5f5;
+            background-color: #f0f0f0;
+        }
+        .productlist li:last-child {
+            border-bottom: none;
         }
         .productinput {
             position: relative;
@@ -88,6 +226,22 @@ $hrefstr = "keys=$keys&Page=$page";
             font-style: italic;
             margin-left: 5px;
         }
+        /* Specification select styling */
+        .spec-select {
+            width: 100%;
+            padding: 6px;
+            margin-top: 5px;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+        }
+        .spec-select:disabled {
+            background-color: #f9f9f9;
+        }
+        .spec-price {
+            font-weight: bold;
+            color: #d9534f;
+        }
+        /* 产品行样式优化 - 单行布局 */
     </style>
 </head>
 <body>
@@ -102,22 +256,28 @@ $hrefstr = "keys=$keys&Page=$page";
             <tr>
                 <th width="8%">客户选择</th>
                 <td>
+                    <?php if ($customerInfo): ?>
+                    <!-- 已有客户ID,只显示客户信息 -->
+                    <div style="display: inline-block; width: 60%;">
+                        <input type="hidden" name="customer_id" id="customer_id" value="<?= $customerId ?>">
+                        <!-- 联系人字段设为空 -->
+                        <input type="hidden" name="contact_id" id="contact_id" value="">
+                        <div class="selected-customer-info" style="font-weight: bold; padding: 8px 0; border: 1px solid #ddd; background-color: #f9f9f9; padding-left: 10px;">
+                            <?= htmlspecialcharsFix($customerInfo['cs_code'] . ' - ' . $customerInfo['cs_company']) ?>
+                        </div>
+                    </div>
+                    <?php else: ?>
+                    <!-- 无客户ID,显示搜索框 -->
                     <div style="display: inline-block; width: 60%;" class="customerinput">
                         <input type="text" class="customer-search fastsearch" placeholder="输入客户名称搜索..." style="width: 100%;">
                         <div class="customerlist" style="display: none; position: absolute; background: white; border: 1px solid #ccc; max-height: 200px; overflow-y: auto; width: 100%; z-index: 1000; box-shadow: 0 2px 5px rgba(0,0,0,0.2);">
                             <ul style="list-style: none; padding: 0; margin: 0;"></ul>
                         </div>
                         <input type="hidden" name="customer_id" id="customer_id" value="0">
+                        <input type="hidden" name="contact_id" id="contact_id" value="">
                         <div class="selected-customer-info" style="margin-top: 5px; font-weight: bold;"></div>
                     </div>
-                </td>
-            </tr>
-            <tr>
-                <th width="8%">联系人</th>
-                <td>
-                    <select id="contact_id" name="contact_id">
-                        <option value="">请选择联系人</option>
-                    </select>
+                    <?php endif; ?>
                 </td>
             </tr>
             <tr>
@@ -127,28 +287,31 @@ $hrefstr = "keys=$keys&Page=$page";
             <tr>
                 <th width="8%" valign="top">产品列表</th>
                 <td>
+                    <button type="button" id="add-product-btn" class="add-product-btn">添加产品</button>
+                    
+                    <div class="product-list-header" style="display: flex; background-color: #eee; padding: 8px 15px; margin-bottom: 10px; border-radius: 4px; font-weight: bold; color: #555; font-size: 13px; gap: 8px;">
+                        <div style="flex: 2; min-width: 200px;">产品</div>
+                        <div style="flex: 2; min-width: 200px;">规格</div>
+                        <div style="flex: 1; min-width: 80px;">数量</div>
+                        <div style="flex: 0.5; min-width: 60px;">单位</div>
+                        <div style="flex: 1; min-width: 100px;">单价</div>
+                        <div style="flex: 1; min-width: 100px;">总价</div>
+                    </div>
+                    
                     <div id="product-container">
-                        <!-- 产品行将通过搜索添加 -->
-                        <div id="no-products-message" style="padding: 20px; text-align: center; color: #777; background-color: #f9f9f9; border: 1px dashed #ddd; display: block;">
-                            请使用下方的产品搜索框添加产品
+                        <!-- 产品行将通过添加按钮添加 -->
+                        <div id="no-products-message" style="padding: 15px; text-align: center; color: #777; background-color: #f5f5f5; border: 1px dashed #ddd; border-radius: 4px; margin-bottom: 15px; display: block;">
+                            <i class="fa fa-info-circle"></i> 请点击"添加产品"按钮添加产品
                         </div>
                     </div>
-                    <div class="total-section">
-                        <div>
-                            <label>订单总额:</label>
-                            <span id="total-amount">0.00</span>
+                    <div class="total-section" style="margin-top: 20px; padding: 15px; background-color: #f5f5f5; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
+                        <div style="display: flex; justify-content: flex-end; align-items: center;">
+                            <label style="font-size: 16px; margin-right: 10px;">订单总额:</label>
+                            <span id="total-amount" style="font-size: 18px; font-weight: bold; color: #e74c3c;">0.00</span>
                             <input type="hidden" name="total_amount" id="total-amount-input" value="0.00">
                             <input type="hidden" name="subtotal" id="subtotal-input" value="0.00">
                         </div>
                     </div>
-                    
-                    <div style="margin-top: 15px; border-top: 1px dashed #ccc; padding-top: 15px;">
-                        <div class="productinput" style="position: relative; width: 60%;">
-                            <label>产品搜索:</label>
-                            <input type="text" id="product-search-single" class="fastsearch" placeholder="输入产品名称搜索并添加..." style="width: 100%;">
-                            <div id="product-list-single" class="productlist" style="width: 100%;"><ul></ul></div>
-                        </div>
-                    </div>
                 </td>
             </tr>
             <tr>
@@ -180,6 +343,16 @@ $hrefstr = "keys=$keys&Page=$page";
                 $('.product-row').first().remove();
             }
             
+            // 添加默认的产品行
+            addEmptyProductRow();
+            updateNoProductsMessage();
+            
+            // 添加产品行按钮点击事件
+            $('#add-product-btn').on('click', function() {
+                addEmptyProductRow();
+                updateNoProductsMessage();
+            });
+            
             // 删除产品行
             $(document).on('click', '.delete-product', function() {
                 if ($('.product-row').length > 1) {
@@ -260,15 +433,29 @@ $hrefstr = "keys=$keys&Page=$page";
                 loadCustomerContacts(customerId);
             });
 
-            // 单一产品搜索功能 - 使用防抖动以减少请求数量
-            var productSearchTimeout = null;
-            $(document).on('keyup', '#product-search-single', function() {
+            // 产品搜索框聚焦时显示搜索提示
+            $(document).on('focus', '.product-search', function() {
+                // 隐藏所有已打开的产品搜索列表
+                $('.productlist').hide();
+                
+                // 当前搜索框的值
+                var searchTerm = $(this).val().trim();
+                if (searchTerm.length >= 2) {
+                    // 找到当前行的产品列表并显示
+                    $(this).siblings('.productlist').show();
+                }
+            });
+            
+            // 产品搜索功能 - 行内搜索
+            var productSearchTimeouts = {};
+            $(document).on('keyup', '.product-search', function() {
                 var $this = $(this);
+                var rowIndex = $this.closest('.product-row').data('index');
                 var searchTerm = $this.val().trim();
-                var productList = $('#product-list-single');
+                var productList = $this.siblings('.productlist');
                 
                 // 清除之前的超时
-                clearTimeout(productSearchTimeout);
+                clearTimeout(productSearchTimeouts[rowIndex]);
                 
                 // 隐藏之前的结果
                 productList.hide();
@@ -279,7 +466,7 @@ $hrefstr = "keys=$keys&Page=$page";
                 }
                 
                 // 设置一个300毫秒的超时,以减少请求数量
-                productSearchTimeout = setTimeout(function() {
+                productSearchTimeouts[rowIndex] = setTimeout(function() {
                     $.ajax({
                         url: 'get_product_info.php',
                         type: 'GET',
@@ -306,80 +493,198 @@ $hrefstr = "keys=$keys&Page=$page";
                 }, 300);
             });
             
-            // 点击选择产品 - 从单一搜索框
-            $(document).on('click', '#product-list-single li', function() {
+            // 点击选择产品 - 行内搜索结果
+            $(document).on('click', '.productlist li', function() {
                 var $this = $(this);
                 var productId = $this.data('id');
                 var productName = $this.text(); // 这会包含分类名,需要清理
                 var categoryTag = $this.find('.category-tag').text();
+                var row = $this.closest('.product-row');
                 
                 // 清理产品名称,移除分类信息
                 if (categoryTag) {
                     productName = productName.replace(categoryTag, '').trim();
                 }
                 
-                // 检查产品是否已经添加
-                var isDuplicate = false;
-                $('.product-id-input').each(function() {
-                    if ($(this).val() == productId) {
-                        isDuplicate = true;
-                        return false; // 跳出循环
-                    }
-                });
+                // 设置产品ID和名称
+                row.find('.product-id-input').val(productId);
+                row.find('.product-search').hide();
                 
-                if (isDuplicate) {
-                    alert('该产品已添加,不能重复添加');
-                    $('#product-search-single').val('');
-                    $('#product-list-single').hide();
-                    return;
+                // 显示包含分类的完整产品信息
+                var displayName = productName;
+                if (categoryTag) {
+                    displayName += ' <span class="category-tag">' + categoryTag + '</span>';
                 }
+                row.find('.selected-product-info').html(displayName).show();
                 
-                // 添加产品行
-                addProductRowWithProduct(productId, productName, categoryTag);
+                // 隐藏产品搜索结果
+                row.find('.productlist').hide();
                 
-                // 清空搜索框并隐藏结果
-                $('#product-search-single').val('');
-                $('#product-list-single').hide();
+                // 获取产品规格信息
+                getProductSpecifications(productId, row);
+            });
+            
+            // 规格选择改变事件
+            $(document).on('change', '.spec-select', function() {
+                var $this = $(this);
+                var row = $this.closest('.product-row');
+                var specId = $this.val();
+                var specData = $this.find('option:selected').data();
+                
+                if (specId) {
+                    // 检查是否已存在相同的产品规格组合
+                    var isDuplicate = false;
+                    $('.spec-select').not($this).each(function() {
+                        if ($(this).val() == specId) {
+                            isDuplicate = true;
+                            return false; // 跳出循环
+                        }
+                    });
+                    
+                    if (isDuplicate) {
+                        alert('该产品规格已添加,不能重复添加');
+                        $this.val(''); // 重置选择
+                        return;
+                    }
+                    
+                    // 设置规格ID到隐藏字段
+                    row.find('.spec-id-input').val(specId);
+                    
+                    // 不再自动设置价格信息
+                    // if (specData.price) {
+                    //     row.find('.price-input').val(specData.price);
+                    // } else {
+                    //     row.find('.price-input').val('');
+                    // }
+                    
+                    // 存储规格价格作为最低价格限制
+                    var minPrice = specData.price || 0;
+                    var priceInput = row.find('.price-input');
+                    priceInput.attr('data-min-price', minPrice);
+                    if (minPrice > 0) {
+                        priceInput.attr('placeholder', '输入单价');
+                    } else {
+                        priceInput.attr('placeholder', '输入单价');
+                    }
+                    
+                    // 设置最小订购数量
+                    var minQty = specData.minQty || 1;
+                    var qtyInput = row.find('.quantity-input');
+                    if (parseInt(qtyInput.val()) < minQty) {
+                        qtyInput.val(minQty);
+                    }
+                    qtyInput.attr('min', minQty);
+                    
+                    // 更新规格信息显示
+                    // var specInfoHtml = '';
+                    // if (specData.code) {
+                    //     specInfoHtml += '<span>编码: ' + specData.code + '</span>';
+                    // }
+                    // if (specData.minQty > 1) {
+                    //     specInfoHtml += ' <span>最小订购量: ' + specData.minQty + '</span>';
+                    // }
+                    // if (specData.price) {
+                    //     specInfoHtml += ' <span>参考价格: ¥' + specData.price + '</span>';
+                    // }
+                    // row.find('.spec-info').html(specInfoHtml);
+                    
+                    // 重新计算总价
+                    calculateItemTotal(row.find('.price-input')[0]);
+                } else {
+                    // 清除规格相关信息
+                    row.find('.spec-id-input').val('');
+                    // 不再清除价格
+                    // row.find('.price-input').val('');
+                    row.find('.price-input').attr('data-min-price', '0').attr('placeholder', '输入单价');
+                    row.find('.spec-info').html('');
+                    calculateItemTotal(row.find('.price-input')[0]);
+                }
             });
             
             // 点击其他地方隐藏下拉列表
             $(document).on('click', function(e) {
-                if (!$(e.target).closest('#product-search-single').length) {
-                    $('#product-list-single').hide();
+                if (!$(e.target).closest('.product-search').length && !$(e.target).closest('.productlist').length) {
+                    $('.productlist').hide();
                 }
                 if (!$(e.target).closest('.customerinput').length) {
                     $('.customerlist').hide();
                 }
             });
+            
+            // 点击已选产品名显示的标签时,切换回搜索模式
+            $(document).on('click', '.selected-product-info', function() {
+                var row = $(this).closest('.product-row');
+                var productId = row.find('.product-id-input').val();
+                
+                // 只有当已经选择了产品时才允许重新选择
+                if (productId) {
+                    if (confirm('确定要重新选择产品吗?这将清除当前选择的产品及其规格信息。')) {
+                        // 清空产品ID和选择的规格
+                        row.find('.product-id-input').val('');
+                        row.find('.spec-id-input').val('');
+                        
+                        // 隐藏产品信息,显示搜索框
+                        $(this).hide();
+                        row.find('.product-search').val('').show();
+                        
+                        // 隐藏并清空规格选择
+                        row.find('.spec-select').hide().empty();
+                        row.find('.spec-info').html('');
+                        
+                        // 清除单位信息
+                        row.find('.unit-input').val('');
+                        row.find('.unit-label').text('');
+                        
+                        // 清除价格信息并重新计算总额
+                        row.find('.price-input').val('');
+                        calculateItemTotal(row.find('.price-input')[0]);
+                    }
+                }
+            });
         });
 
         function addEmptyProductRow() {
             var html = `
             <div class="product-row" data-index="${productIndex}">
                 <span class="delete-product">×</span>
-                <div>
-                    <label>产品:</label>
-                    <div style="display: inline-block; width: 60%;">
-                        <input type="hidden" name="items[${productIndex}][product_id]" class="product-id-input" value="">
-                        <div class="selected-product-info" style="margin-top: 5px; font-weight: bold;"></div>
-                    </div>
+                
+                <div class="row-section product-info">
+                    <div class="row-section-label"><span>产品</span></div>
+                    <input type="hidden" name="items[${productIndex}][product_id]" class="product-id-input" value="">
+                    <input type="text" class="product-search" placeholder="输入产品名称搜索..." style="width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 4px;">
+                    <div class="productlist" style="width: 100%; max-height: 200px;"><ul></ul></div>
+                    <div class="selected-product-info" style="cursor: pointer; display: none;" title="点击重新选择产品"></div>
+                </div>
+                
+                <div class="row-section product-spec">
+                    <div class="row-section-label"><span>规格</span></div>
+                    <input type="hidden" name="items[${productIndex}][spec_id]" class="spec-id-input" value="">
+                    <select class="spec-select" name="items[${productIndex}][spec_select]" style="display: none;">
+                        <option value="">请选择规格</option>
+                    </select>
+                    <div class="spec-info"></div>
                 </div>
-                <div style="margin-top: 5px;">
-                    <label>数量:</label>
+                
+                <div class="row-section product-quantity">
+                    <div class="row-section-label"><span>数量</span></div>
                     <input type="number" name="items[${productIndex}][quantity]" value="1" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
-
-                    <label style="margin-left: 10px;">单位:</label>
-                    <input type="text" name="items[${productIndex}][unit]" value="" class="unit-input">
-
-                    <label style="margin-left: 10px;">单价:</label>
-                    <input type="number" step="0.01" name="items[${productIndex}][unit_price]" value="" class="price-input" placeholder="请输入单价" onchange="calculateItemTotal(this)">
-                    
-                    <label style="margin-left: 10px;">总价:</label>
-                    <input type="number" step="0.01" name="items[${productIndex}][total_price]" value="0.00" class="total-price-input" readonly>
                 </div>
-                <div style="margin-top: 5px;">
-                    <label>备注:</label>
-                    <input type="text" name="items[${productIndex}][notes]" value="" style="width: 90%;">
+                
+                <div class="row-section product-unit">
+                    <div class="row-section-label"><span>单位</span></div>
+                    <span class="unit-label" style="display: inline-block; padding: 2px 5px; min-width: 30px;"></span>
+                    <input type="hidden" name="items[${productIndex}][unit]" class="unit-input" value="">
+                </div>
+                
+                <div class="row-section product-price">
+                    <div class="row-section-label"><span>单价</span></div>
+                    <input type="number" step="0.01" name="items[${productIndex}][unit_price]" value="" class="price-input" placeholder="输入单价" onchange="calculateItemTotal(this)">
+                </div>
+                
+                <div class="row-section product-total">
+                    <div class="row-section-label"><span>总价</span></div>
+                    <span class="total-price-display" style="display: inline-block; background-color: #f0f0f0; border: 1px solid #ddd; padding: 2px 8px; min-width: 60px; text-align: right;">0.00</span>
+                    <input type="hidden" name="items[${productIndex}][total_price]" value="0.00" class="total-price-input">
                 </div>
             </div>
             `;
@@ -389,26 +694,72 @@ $hrefstr = "keys=$keys&Page=$page";
             return productIndex - 1; // 返回新添加行的索引
         }
         
-        function addProductRowWithProduct(productId, productName, categoryTag) {
-            // 添加空行
-            var rowIndex = addEmptyProductRow();
-            var row = $('.product-row[data-index="' + rowIndex + '"]');
-            
-            // 设置产品ID和名称
-            row.find('.product-id-input').val(productId);
-            
-            // 显示包含分类的完整产品信息
-            var displayName = productName;
-            if (categoryTag) {
-                displayName += ' <span class="category-tag">' + categoryTag + '</span>';
-            }
-            row.find('.selected-product-info').html(displayName);
-            
-            // 获取产品信息
-            getProductInfo(productId, row);
+        function getProductSpecifications(productId, row) {
+            if (!productId) return;
             
-            // 更新无产品消息显示
-            updateNoProductsMessage();
+            $.ajax({
+                url: 'get_product_info.php',
+                type: 'GET',
+                data: {product_id: productId},
+                dataType: 'json',
+                success: function(data) {
+                    if (data && data.product && data.specifications) {
+                        // 恢复设置单位信息
+                        if (data.product.unit) {
+                            row.find('.unit-input').val(data.product.unit);
+                            row.find('.unit-label').text(data.product.unit);
+                        }
+                        
+                        // 处理规格信息
+                        var specifications = data.specifications;
+                        if (specifications.length === 0) {
+                            alert('此产品没有规格信息,请添加规格后再选择');
+                            // 重置产品选择
+                            row.find('.product-id-input').val('');
+                            row.find('.selected-product-info').hide();
+                            row.find('.product-search').val('').show();
+                            return;
+                        }
+                        
+                        // 填充规格选择下拉框
+                        var specSelect = row.find('.spec-select');
+                        specSelect.empty();
+                        specSelect.append('<option value="">请选择规格</option>');
+                        
+                        $.each(specifications, function(i, spec) {
+                            var displayText = spec.spec_name + ': ' + spec.spec_value;
+                            if (spec.price) {
+                                displayText += ' (¥' + spec.price + ')';
+                            }
+                            
+                            var option = $('<option></option>')
+                                .attr('value', spec.id)
+                                .text(displayText)
+                                .data('price', spec.price)
+                                .data('minQty', spec.min_order_quantity)
+                                .data('code', spec.spec_code);
+                            
+                            specSelect.append(option);
+                        });
+                        
+                        // 显示规格选择下拉框
+                        specSelect.show();
+                    } else {
+                        alert('获取产品规格失败');
+                        // 重置产品选择
+                        row.find('.product-id-input').val('');
+                        row.find('.selected-product-info').hide();
+                        row.find('.product-search').val('').show();
+                    }
+                },
+                error: function() {
+                    alert('获取产品规格失败,请重试');
+                    // 重置产品选择
+                    row.find('.product-id-input').val('');
+                    row.find('.selected-product-info').hide();
+                    row.find('.product-search').val('').show();
+                }
+            });
         }
 
         function reindexProductRows() {
@@ -425,40 +776,26 @@ $hrefstr = "keys=$keys&Page=$page";
             productIndex = $('.product-row').length;
         }
 
-        function getProductInfo(productId, row) {
-            if (!productId) return;
-            
-            $.ajax({
-                url: 'get_product_info.php',
-                type: 'GET',
-                data: {id: productId},
-                dataType: 'json',
-                success: function(data) {
-                    if (data) {
-                        row.find('.unit-input').val(data.unit);
-
-                        // 只有当数据库中有价格信息时才设置价格
-                        if (data.price && data.price !== '0' && data.price !== '0.00') {
-                            //默认不设置单价
-                            //row.find('.price-input').val(data.price);
-
-                        }
-                        calculateItemTotal(row.find('.price-input')[0]);
-                    }
-                }
-            });
-        }
-
         function calculateItemTotal(element) {
             var row = $(element).closest('.product-row');
             var quantity = parseInt(row.find('.quantity-input').val()) || 0;
             var priceInput = row.find('.price-input');
             var priceValue = priceInput.val().trim();
             var price = (priceValue === '') ? 0 : (parseFloat(priceValue) || 0);
+            var minPrice = parseFloat(priceInput.attr('data-min-price')) || 0;
+
+            // 检查价格是否低于规格最低价
+            if (price > 0 && minPrice > 0 && price < minPrice) {
+                priceInput.css('color', 'red');
+            } else {
+                priceInput.css('color', '');
+            }
 
             var total = quantity * price;
             if (total < 0) total = 0;
 
+            // 更新显示元素和隐藏输入框
+            row.find('.total-price-display').text(total.toFixed(2));
             row.find('.total-price-input').val(total.toFixed(2));
 
             calculateOrderTotal();
@@ -484,17 +821,12 @@ $hrefstr = "keys=$keys&Page=$page";
                     data: {customer_id: customerId},
                     dataType: 'json',
                     success: function(data) {
-                        var options = '<option value="">请选择联系人</option>';
-                        if (data && data.length > 0) {
-                            for (var i = 0; i < data.length; i++) {
-                                options += '<option value="' + data[i].id + '">' + data[i].contact_name + '</option>';
-                            }
-                        }
-                        $('#contact_id').html(options);
+                        // 不自动选择第一个联系人,让字段为空
+                        $('#contact_id').val('');
                     }
                 });
             } else {
-                $('#contact_id').html('<option value="">请选择联系人</option>');
+                $('#contact_id').val('');
             }
         }
 
@@ -502,25 +834,60 @@ $hrefstr = "keys=$keys&Page=$page";
             var orderCode = $('#order_code').val();
             var customerId = $('#customer_id').val();
             var customerName = $('.customer-search').val();
-            var contactId = $('#contact_id').val(); 
             var hasProducts = false;
+            var allSpecsSelected = true;
             var allPricesValid = true;
-            var firstEmptyPriceField = null;
+            var allPricesHighEnough = true;
+            var firstInvalidField = null;
 
-            $('.product-id-input').each(function() {
-                if ($(this).val()) {
-                    hasProducts = true;
-                    
-                    // 检查该产品的单价是否已填写
-                    var row = $(this).closest('.product-row');
-                    var priceInput = row.find('.price-input');
-                    var priceValue = priceInput.val().trim();
-                    
-                    if (priceValue === '' || isNaN(parseFloat(priceValue))) {
-                        allPricesValid = false;
-                        if (!firstEmptyPriceField) {
-                            firstEmptyPriceField = priceInput;
-                        }
+            // 检查是否有产品行
+            if ($('.product-row').length === 0) {
+                alert('请至少添加一个产品');
+                $('#add-product-btn').focus();
+                return false;
+            }
+
+            $('.product-row').each(function() {
+                var productId = $(this).find('.product-id-input').val();
+                var specId = $(this).find('.spec-id-input').val();
+                var priceInput = $(this).find('.price-input');
+                var priceValue = priceInput.val().trim();
+                var price = parseFloat(priceValue) || 0;
+                var minPrice = parseFloat(priceInput.attr('data-min-price')) || 0;
+                var specSelect = $(this).find('.spec-select');
+                var productSearch = $(this).find('.product-search');
+                
+                // 检查产品是否已选择
+                if (!productId) {
+                    if (!firstInvalidField) {
+                        firstInvalidField = productSearch;
+                    }
+                    return true; // continue
+                }
+                
+                hasProducts = true;
+                
+                // 检查规格是否已选择
+                if (!specId && specSelect.is(':visible')) {
+                    allSpecsSelected = false;
+                    if (!firstInvalidField) {
+                        firstInvalidField = specSelect;
+                    }
+                }
+                
+                // 检查单价是否有效
+                if (priceValue === '' || isNaN(parseFloat(priceValue))) {
+                    allPricesValid = false;
+                    if (!firstInvalidField) {
+                        firstInvalidField = priceInput;
+                    }
+                }
+                
+                // 检查单价是否大于等于规格价格
+                if (minPrice > 0 && price < minPrice) {
+                    allPricesHighEnough = false;
+                    if (!firstInvalidField) {
+                        firstInvalidField = priceInput;
                     }
                 }
             });
@@ -537,32 +904,47 @@ $hrefstr = "keys=$keys&Page=$page";
                 return false;
             }
             
-            if (!customerName) {
+            // 只有当客户ID为0时才检查客户名称
+            if (customerId == '0' && !customerName) {
                 alert('请输入并选择有效的客户');
                 $('.customer-search').focus();
                 return false;
             }
             
-            if (!contactId) {
-                alert('请选择联系人');
-                $('#contact_id').focus();
+            if (!hasProducts) {
+                alert('请至少添加一个有效的产品');
+                if (firstInvalidField) {
+                    firstInvalidField.focus();
+                } else {
+                    $('#add-product-btn').focus();
+                }
                 return false;
             }
-
-            if (!hasProducts) {
-                alert('请至少添加一个产品');
-                $('#product-search-single').focus();
+            
+            if (!allSpecsSelected) {
+                alert('请为所有产品选择规格');
+                if (firstInvalidField) {
+                    firstInvalidField.focus();
+                }
                 return false;
             }
             
             if (!allPricesValid) {
                 alert('请为所有产品输入有效的单价');
-                if (firstEmptyPriceField) {
-                    firstEmptyPriceField.focus();
+                if (firstInvalidField) {
+                    firstInvalidField.focus();
                 }
                 return false;
             }
-
+            
+            if (!allPricesHighEnough) {
+                alert('单价不能低于规格设定的参考价格');
+                if (firstInvalidField) {
+                    firstInvalidField.focus();
+                }
+                return false;
+            }
+            
             return true;
         }
 

+ 161 - 66
order_details.php

@@ -25,9 +25,10 @@ if (!empty($id) && is_numeric($id)) {
     }
 
     // 获取订单项信息
-    $sql = "SELECT oi.*, p.ProductName 
+    $sql = "SELECT oi.*, p.ProductName,ps.spec_name
             FROM order_items oi 
             LEFT JOIN products p ON oi.product_id = p.id 
+            LEFT JOIN product_specifications ps ON oi.specification_id = ps.id
             WHERE oi.order_id = $id";
 
     $itemsResult = mysqli_query($conn, $sql);
@@ -64,6 +65,8 @@ if (!empty($id) && is_numeric($id)) {
             padding: 15px;
             margin-bottom: 20px;
             background-color: #f9f9f9;
+            border-radius: 4px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
         }
         .order-info h2 {
             margin-top: 0;
@@ -78,31 +81,101 @@ if (!empty($id) && is_numeric($id)) {
             display: inline-block;
             width: 120px;
         }
-        .products-table {
-            width: 100%;
-            border-collapse: collapse;
-            margin-bottom: 20px;
+        
+        /* 产品行样式 - 从order_add.php采用 */
+        .product-row {
+            position: relative;
+            padding: 12px 15px;
+            margin-bottom: 8px;
+            border-radius: 4px;
+            display: flex;
+            align-items: center;
+            flex-wrap: wrap;
+            gap: 8px;
+            background-color: #f9f9f9;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
         }
-        .products-table th, .products-table td {
-            border: 1px solid #ddd;
-            padding: 8px;
-            text-align: left;
+        .product-info {
+            flex: 2;
+            min-width: 200px;
+        }
+        .product-spec {
+            flex: 2;
+            min-width: 200px;
+        }
+        .product-quantity {
+            flex: 1;
+            min-width: 80px;
         }
-        .products-table th {
-            background-color: #f2f2f2;
+        .product-unit {
+            flex: 0.5;
+            min-width: 60px;
         }
-        /* 移除徽章式样,使用普通文本显示 */
-        .order-status {
+        .product-price {
+            flex: 1;
+            min-width: 100px;
+        }
+        .product-total {
+            flex: 1;
+            min-width: 100px;
             font-weight: bold;
         }
-        .payment-status {
+        .product-discount {
+            flex: 1;
+            min-width: 100px;
+        }
+        .product-notes {
+            flex: 2;
+            min-width: 200px;
+        }
+        .row-section {
+            display: flex;
+            flex-direction: column;
+        }
+        .row-section-label {
+            font-size: 12px;
+            color: #666;
+            margin-bottom: 3px;
+        }
+        .product-list-header {
+            display: flex;
+            background-color: #eee;
+            padding: 8px 15px;
+            margin-bottom: 10px;
+            border-radius: 4px;
             font-weight: bold;
+            color: #555;
+            font-size: 13px;
+            gap: 8px;
         }
-
+        
+        /* 响应式设计 */
+        @media (max-width: 768px) {
+            .product-row {
+                flex-direction: column;
+                align-items: flex-start;
+            }
+            .product-info, .product-spec, .product-quantity, 
+            .product-unit, .product-price, .product-total,
+            .product-discount, .product-notes {
+                width: 100%;
+                min-width: 100%;
+                margin-bottom: 8px;
+            }
+            .product-list-header {
+                display: none !important;
+            }
+            .row-section-label span {
+                display: inline;
+            }
+        }
+        
         .notes-section {
             border: 1px solid #ddd;
             padding: 15px;
             margin-bottom: 20px;
+            border-radius: 4px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
         }
         .total-section {
             text-align: right;
@@ -110,6 +183,10 @@ if (!empty($id) && is_numeric($id)) {
             margin-top: 10px;
             border-top: 1px solid #ddd;
             padding-top: 10px;
+            background-color: #f5f5f5;
+            border-radius: 4px;
+            padding: 15px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
         }
     </style>
 </head>
@@ -132,9 +209,9 @@ if (!empty($id) && is_numeric($id)) {
             <?php endif; ?>
             <?= htmlspecialcharsFix($order['cs_company']) ?>
         </div>
-        <div class="info-row">
-            <span class="info-label">联系人:</span> <?= htmlspecialcharsFix($order['contact_name']) ?>
-        </div>
+<!--        <div class="info-row">-->
+<!--            <span class="info-label">联系人:</span> --><?php //= htmlspecialcharsFix($order['contact_name']) ?>
+<!--        </div>-->
         <div class="info-row">
             <span class="info-label">订单日期:</span> <?= date('Y-m-d', strtotime($order['order_date'])) ?>
         </div>
@@ -150,65 +227,83 @@ if (!empty($id) && is_numeric($id)) {
     </div>
 
     <h2>订单产品</h2>
-    <table class="products-table">
-        <thead>
-        <tr>
-            <th>序号</th>
-            <th>产品名称</th>
-            <th>数量</th>
-            <th>单位</th>
-            <th>单价</th>
-            <th>折扣</th>
-            <th>总价</th>
-            <th>备注</th>
-        </tr>
-        </thead>
-        <tbody>
+    
+    <!-- 产品表头 -->
+    <div class="product-list-header">
+        <div style="flex: 2; min-width: 200px;">产品</div>
+        <div style="flex: 2; min-width: 200px;">规格</div>
+        <div style="flex: 1; min-width: 80px;">数量</div>
+        <div style="flex: 0.5; min-width: 60px;">单位</div>
+        <div style="flex: 1; min-width: 100px;">单价</div>
+
+        <div style="flex: 1; min-width: 100px;">总价</div>
+
+    </div>
+    
+    <!-- 产品列表 -->
+    <div id="product-container">
         <?php foreach ($orderItems as $index => $item): ?>
-            <tr>
-                <td><?= $index + 1 ?></td>
-                <td><?= htmlspecialcharsFix($item['ProductName']) ?></td>
-                <td><?= $item['quantity'] ?></td>
-                <td><?= htmlspecialcharsFix($item['unit']) ?></td>
-                <td><?= number_format($item['unit_price'], 2) ?></td>
-                <td>
-                    <?php if ($item['discount_amount'] > 0): ?>
-                        <?= number_format($item['discount_amount'], 2) ?>
-                        (<?= number_format($item['discount_percent'], 2) ?>%)
-                    <?php else: ?>
-                        -
-                    <?php endif; ?>
-                </td>
-                <td><?= number_format($item['total_price'], 2) ?></td>
-                <td><?= htmlspecialcharsFix($item['notes']) ?></td>
-            </tr>
+            <div class="product-row">
+                <!-- 产品名称 -->
+                <div class="row-section product-info">
+
+                    <div class="selected-product-info"><?= htmlspecialcharsFix($item['ProductName']) ?></div>
+                </div>
+                
+                <!-- 规格 -->
+                <div class="row-section product-spec">
+
+                    <div><?= $item['spec_name'] ?></div>
+                </div>
+                
+                <!-- 数量 -->
+                <div class="row-section product-quantity">
+
+                    <div><?= $item['quantity'] ?></div>
+                </div>
+                
+                <!-- 单位 -->
+                <div class="row-section product-unit">
+
+                    <div><?= htmlspecialcharsFix($item['unit']) ?></div>
+                </div>
+                
+                <!-- 单价 -->
+                <div class="row-section product-price">
+
+                    <div><?= number_format($item['unit_price'], 2) ?></div>
+                </div>
+                
+
+                
+                <!-- 总价 -->
+                <div class="row-section product-total">
+
+                    <div><?= number_format($item['total_price'], 2) ?></div>
+                </div>
+                
+
+            </div>
         <?php endforeach; ?>
-        </tbody>
-    </table>
+    </div>
 
     <div class="total-section">
-<!--        <div>-->
-<!--            <strong>订单小计:</strong> --><?php //= number_format($order['subtotal'], 2) ?>
-<!--        </div>-->
-<!--        --><?php //if(isset($order['discount_amount']) && $order['discount_amount'] > 0): ?>
-<!--        <div>-->
-<!--            <strong>订单折扣:</strong> --><?php //= number_format($order['discount_amount'], 2) ?>
-<!--        </div>-->
-<!--        --><?php //endif; ?>
         <div style="font-size: 1.2em; margin-top: 5px;">
             <strong>订单总额:</strong> <?= number_format($order['total_amount'], 2) ?>
         </div>
     </div>
 
-    <?php if (!empty($order['notes'])): ?>
-        <div class="notes-section">
-            <h2>订单备注</h2>
-            <div>
-             
+    <div class="notes-section">
+        <h2>订单备注</h2>
+        <div>
+            <?php if (!empty($order['notes'])): ?>
                 <p><?= nl2br(htmlspecialcharsFix($order['notes'])) ?></p>
-            </div>
+            <?php else: ?>
+                <p><em>无备注</em></p>
+            <?php endif; ?>
         </div>
-    <?php endif; ?>
+    </div>
+
 </div>
 </body>
 </html>

File diff suppressed because it is too large
+ 608 - 186
order_edit.php


+ 76 - 44
order_save.php

@@ -56,6 +56,7 @@ if (empty($items)) {
     exit;
 }
 
+$customer_country=0;
 // 检查客户国家和产品销售限制
 $customer_query = "SELECT cs_country FROM customer WHERE id = $customer_id LIMIT 1";
 $customer_result = mysqli_query($conn, $customer_query);
@@ -112,6 +113,7 @@ if ($isedit) {
         if (empty($item['product_id'])) continue;
         
         $product_id = (int)$item['product_id'];
+        $spec_id = isset($item['spec_id']) ? (int)$item['spec_id'] : 0;
         $quantity = (int)$item['quantity'];
         $unit_price = (float)$item['unit_price'];
         
@@ -128,27 +130,41 @@ if ($isedit) {
         $product_row = mysqli_fetch_assoc($product_result);
         $product_name = $product_row['ProductName'];
         
-        // 查询该产品在价格表中的最低价格要求
-        // 根据产品ID和数量查找最接近但不超过当前订单数量的价格记录
-        $price_query = "SELECT * FROM price 
-                       WHERE productId = $product_id 
-                       AND num <= $quantity 
-                       ORDER BY num DESC 
-                       LIMIT 1";
-        
-        $price_result = mysqli_query($conn, $price_query);
-        
-        if (mysqli_num_rows($price_result) > 0) {
-            $price_row = mysqli_fetch_assoc($price_result);
-            $min_price = (float)$price_row['price'];
+        // 如果有规格ID,检查规格价格
+        if ($spec_id > 0) {
+
+            //先判断是否国家有特殊规格
+
+
+            $spec_result=null;
+            if($customer_country>0) {
+                $spec_query = "SELECT pcp.price,pcp.min_order_quantity, ps.spec_name, ps.spec_value FROM product_country_price pcp
+                                    left join product_specifications ps on pcp.specification_id=ps.id
+                          WHERE pcp.specification_id = $spec_id  AND pcp.country_id = $customer_country
+                          LIMIT 1";
+                $spec_result = mysqli_query($conn, $spec_query);
+            }
+
+            if (mysqli_num_rows($spec_result) < 1) {
+                $spec_query = "SELECT price, spec_name, spec_value FROM product_specifications 
+                          WHERE id = $spec_id AND product_id = $product_id 
+                          LIMIT 1";
+
+                $spec_result = mysqli_query($conn, $spec_query);
+            }
             
-            // 如果单价低于指导价,标记错误
-            if ($unit_price < $min_price) {
-                $price_error = true;
-                $error_product_name = $product_name;
-                $error_min_price = $min_price;
-                $error_current_price = $unit_price;
-                break;
+            if (mysqli_num_rows($spec_result) > 0) {
+                $spec_row = mysqli_fetch_assoc($spec_result);
+                $min_price = (float)$spec_row['price'];
+                
+                // 如果单价低于规格价格,标记错误
+                if ($min_price > 0 && $unit_price < $min_price) {
+                    $price_error = true;
+                    $error_product_name = $product_name . " (" . $spec_row['spec_name'] . ": " . $spec_row['spec_value'] . ")";
+                    $error_min_price = $min_price;
+                    $error_current_price = $unit_price;
+                    break;
+                }
             }
         }
     }
@@ -191,6 +207,7 @@ if ($isedit) {
         if (empty($item['product_id'])) continue; // 跳过没有选择产品的行
 
         $product_id = (int)$item['product_id'];
+        $spec_id = isset($item['spec_id']) ? (int)$item['spec_id'] : 0; // 添加规格ID
         $quantity = (int)$item['quantity'];
         $unit = mysqli_real_escape_string($conn, htmlspecialchars($item['unit'], ENT_QUOTES, 'UTF-8'));
         $unit_price = (float)$item['unit_price'];
@@ -198,11 +215,11 @@ if ($isedit) {
         $item_notes = mysqli_real_escape_string($conn, htmlspecialchars($item['notes'] ?? '', ENT_QUOTES, 'UTF-8'));
 
         $sql = "INSERT INTO order_items (
-                order_id, product_id, quantity, unit, unit_price, 
+                order_id, product_id, specification_id, quantity, unit, unit_price, 
                 total_price, notes, 
                 created_at, updated_at
             ) VALUES (
-                $id, $product_id, $quantity, '$unit', $unit_price, 
+                $id, $product_id, $spec_id, $quantity, '$unit', $unit_price, 
                 $total_price, '$item_notes', 
                 NOW(), NOW()
             )";
@@ -223,6 +240,7 @@ if ($isedit) {
         if (empty($item['product_id'])) continue;
         
         $product_id = (int)$item['product_id'];
+        $spec_id = isset($item['spec_id']) ? (int)$item['spec_id'] : 0;
         $quantity = (int)$item['quantity'];
         $unit_price = (float)$item['unit_price'];
         
@@ -239,27 +257,40 @@ if ($isedit) {
         $product_row = mysqli_fetch_assoc($product_result);
         $product_name = $product_row['ProductName'];
         
-        // 查询该产品在价格表中的最低价格要求
-        // 根据产品ID和数量查找最接近但不超过当前订单数量的价格记录
-        $price_query = "SELECT * FROM price 
-                       WHERE productId = $product_id 
-                       AND num <= $quantity 
-                       ORDER BY num DESC 
-                       LIMIT 1";
-        
-        $price_result = mysqli_query($conn, $price_query);
-        
-        if (mysqli_num_rows($price_result) > 0) {
-            $price_row = mysqli_fetch_assoc($price_result);
-            $min_price = (float)$price_row['price'];
+        // 如果有规格ID,检查规格价格
+        if ($spec_id > 0) {
+
+            //先判断是否国家有特殊规格
+
+            $spec_result=null;
+            if($customer_country>0) {
+                $spec_query = "SELECT pcp.price,pcp.min_order_quantity, ps.spec_name, ps.spec_value FROM product_country_price pcp
+                                    left join product_specifications ps on pcp.specification_id=ps.id
+                          WHERE pcp.specification_id = $spec_id  AND pcp.country_id = $customer_country
+                          LIMIT 1";
+                $spec_result = mysqli_query($conn, $spec_query);
+            }
+
+            if (mysqli_num_rows($spec_result) < 1) {
+                $spec_query = "SELECT price, spec_name, spec_value FROM product_specifications 
+                          WHERE id = $spec_id AND product_id = $product_id 
+                          LIMIT 1";
+
+                $spec_result = mysqli_query($conn, $spec_query);
+            }
             
-            // 如果单价低于指导价,标记错误
-            if ($unit_price < $min_price) {
-                $price_error = true;
-                $error_product_name = $product_name;
-                $error_min_price = $min_price;
-                $error_current_price = $unit_price;
-                break;
+            if (mysqli_num_rows($spec_result) > 0) {
+                $spec_row = mysqli_fetch_assoc($spec_result);
+                $min_price = (float)$spec_row['price'];
+                
+                // 如果单价低于规格价格,标记错误
+                if ($min_price > 0 && $unit_price < $min_price) {
+                    $price_error = true;
+                    $error_product_name = $product_name . " (" . $spec_row['spec_name'] . ": " . $spec_row['spec_value'] . ")";
+                    $error_min_price = $min_price;
+                    $error_current_price = $unit_price;
+                    break;
+                }
             }
         }
     }
@@ -294,6 +325,7 @@ if ($isedit) {
         if (empty($item['product_id'])) continue; // 跳过没有选择产品的行
 
         $product_id = (int)$item['product_id'];
+        $spec_id = isset($item['spec_id']) ? (int)$item['spec_id'] : 0; // 添加规格ID
         $quantity = (int)$item['quantity'];
         $unit = mysqli_real_escape_string($conn, htmlspecialchars($item['unit'], ENT_QUOTES, 'UTF-8'));
         $unit_price = (float)$item['unit_price'];
@@ -301,11 +333,11 @@ if ($isedit) {
         $item_notes = mysqli_real_escape_string($conn, htmlspecialchars($item['notes'] ?? '', ENT_QUOTES, 'UTF-8'));
 
         $sql = "INSERT INTO order_items (
-                order_id, product_id, quantity, unit, unit_price, 
+                order_id, product_id, specification_id, quantity, unit, unit_price, 
                 total_price, notes, 
                 created_at, updated_at
             ) VALUES (
-                $order_id, $product_id, $quantity, '$unit', $unit_price, 
+                $order_id, $product_id, $spec_id, $quantity, '$unit', $unit_price, 
                 $total_price, '$item_notes', 
                 NOW(), NOW()
             )";

+ 39 - 10
panel.php

@@ -11,6 +11,7 @@ if ($row = $result->fetch_assoc()) {
     $em_code = textUncode($row['em_code']);
     $em_email = textUncode($row['em_email']);
     $em_tel = textUncode($row['em_tel']);
+    $em_permission_role_id=$row['em_permission_role_id'];
 } else {
     $stmt->close();
     $conn->close();
@@ -18,12 +19,19 @@ if ($row = $result->fetch_assoc()) {
     exit;
 }
 $stmt->close();
+
 ?>
 
 <div class="panel">
     <section>
         <h3><?= $em_user ?></h3>
-        <div class="role_text"><?= ($em_role == 0) ? "组长" : "组员" ?></div>
+        <div class="role_text">
+            <?php
+            $em_permission_role_array=array(0=>"普通",1=>"管理员",2=>"组长",3=>"组员",4=>"分公司");
+            echo $em_permission_role_array[$em_permission_role_id];
+
+            ?>
+        </div>
         <ul class="lxfs">
             <li class="tel"><?= $em_tel ?></li>
             <li class="mail"><?= $em_email ?></li>
@@ -31,7 +39,7 @@ $stmt->close();
     </section>
     <div>
         <dl>
-            <?php if (strpos($em_code, "BX") === false): ?>
+            <?php if (checkAdminOrEmployee()): ?>
                 <dt><a href="../home.php" target="contentFrame">客户查找</a></dt>
             <?php endif; ?>
             <dt><a href="../customerAdd.php" target="contentFrame">客户录入</a></dt>
@@ -46,28 +54,48 @@ $stmt->close();
                     <a href="../customers.php?fliterDeal=2" target="contentFrame">明确需求  (<?= $_SESSION['d2'] ?>)</a>
                     <a href="../customers.php?fliterDeal=3" target="contentFrame">已经成交  (<?= $_SESSION['d1'] ?>)</a>
                     <a href="../customersNew.php" target="contentFrame">本月新增</a>
-                    <?php if (strpos($em_code, "BX") === false): ?>
+                    <?php if (checkAdminOrEmployee()): ?>
                         <a href="../customersFollow.php" target="contentFrame">即将加入公海 </a>
-                        <a href="../teamSeas.php" target="contentFrame">小组公海(60天无更新)</a>
-                        <a href="../highSeas.php" target="contentFrame">公司公海(120天无更新)</a>
+                        <a href="../highSeas.php" target="contentFrame">公司公海(60天无更新)</a>
                         <a href="../claimRecord.php" target="contentFrame">认领记录</a>
                         <a href="../abnormal.php" target="contentFrame" class="new">异常客户</a>
                     <?php endif; ?>
                 </div>
             </dt>
+            <?php if (checkAdminOrEmployee()): ?>
             <dt class="subnav">数据
                 <div class="list-wraper">
-                    <a href="../dashboard.php" target="contentFrame">数据看板</a>
-                    <?php if (strpos($em_code, "BX") === false): ?>
+
+                        <a href="../dashboard.php" target="contentFrame">数据看板</a>
                         <a href="../team.php" target="contentFrame">本月小组数据</a>
-                    <?php endif; ?>
+
                 </div>
             </dt>
+            <?php endif; ?>
+            <?php
+            //权限角色为的时候显示统计分析
+            if(checkPermission(1))
+            {
+
+             ?>
+            <dt class="subnav">统计分析
+                <div class="list-wraper">
+                    <a href="statistics.php" target="contentFrame">汇总统计</a>
+                    <a href="customers_stats.php" target="contentFrame">客户统计分析</a>
+                    <a href="products_stats.php" target="contentFrame">产品统计分析</a>
+                    <a href="region_stats.php" target="contentFrame">地区统计分析</a>
+                    <a href="sales_stats.php" target="contentFrame">销售统计分析</a>
+                    <a href="statistics_order_warnings.php" target="contentFrame">订单预警系统</a>
+
+                </div>
+
+            </dt>
+            <?php }?>
             <dt><a href="../tagClound.php" target="contentFrame">标签云</a></dt>
-            <?php if (strpos($em_code, "BX") === false): ?>
+            <?php if (checkAdminOrEmployee()): ?>
                 <dt><a href="../silentCustomer.php" target="contentFrame">静默客户</a></dt>
             <?php endif; ?>
-            <?php if ($em_role == 0): ?>
+            <?php if(($em_role == 0)&&($em_permission_role_id==2)): ?>
                 <dt class="subnav">我的团队
                     <div class="list-wraper">
                         <a href="../subcustomers.php" target="contentFrame">组员客户</a>
@@ -77,6 +105,7 @@ $stmt->close();
             <?php endif; ?>
             <dt><a href="../pwdEdit.php" target="contentFrame">修改密码</a></dt>
             <dt><a href="../index.php?act=logout" onclick="return confirm('确认要退出吗?');">退出登录</a></dt>
+
         </dl>
     </div>
     <div class="copyright">

+ 209 - 0
products_stats.php

@@ -0,0 +1,209 @@
+<?php
+/**
+ * 产品统计分析展示页面
+ */
+require_once 'conn.php';
+require_once 'statistics_utils.php';
+require_once 'statistics_products.php';
+
+// 检查登录状态
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+// 获取日期范围参数
+$date_params = getDateRangeParams();
+$start_date = $date_params['start_date_sql'];
+$end_date = $date_params['end_date_sql'];
+$date_range = $date_params['date_range'];
+$period = $date_params['period'];
+
+// 特定产品过滤
+$product_id = isset($_GET['product_id']) ? intval($_GET['product_id']) : 0;
+
+// 页面头部
+include('statistics_header.php');
+?>
+
+<div class="container">
+    <div class="page-header">
+        <h1 class="page-title">产品统计分析</h1>
+    </div>
+    
+    <!-- 日期筛选 -->
+    <div class="filter-form">
+        <form method="get" class="filter-form-inline">
+            <div class="form-group">
+                <label for="date_range">选择日期范围</label>
+                <select class="form-control" id="date_range" name="date_range" onchange="toggleCustomDates()">
+                    <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                    <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                    <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                    <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>最近30天</option>
+                    <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>最近90天</option>
+                    <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义日期范围</option>
+                </select>
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="start_date">开始日期</label>
+                <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $date_params['custom_start']; ?>">
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="end_date">结束日期</label>
+                <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $date_params['custom_end']; ?>">
+            </div>
+            <div class="form-group">
+                <label for="period">时间粒度</label>
+                <select class="form-control" id="period" name="period">
+                    <option value="day" <?php echo $period == 'day' ? 'selected' : ''; ?>>日</option>
+                    <option value="week" <?php echo $period == 'week' ? 'selected' : ''; ?>>周</option>
+                    <option value="month" <?php echo $period == 'month' ? 'selected' : ''; ?>>月</option>
+                </select>
+            </div>
+            <div class="form-group">
+                <label for="category_id">产品分类</label>
+                <select class="form-control" id="category_id" name="category_id">
+                    <option value="0">全部分类</option>
+                    <?php
+                    $category_filter = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
+                    $categories = getProductCategories($conn);
+                    while($category = $categories->fetch_assoc()) {
+                        $selected = ($category_filter == $category['id']) ? 'selected' : '';
+                        echo "<option value='{$category['id']}' {$selected}>{$category['name']}</option>";
+                    }
+                    ?>
+                </select>
+            </div>
+            <div class="form-group">
+                <button type="submit" class="btn">应用筛选</button>
+            </div>
+        </form>
+    </div>
+    
+    <!-- 产品销售概览 -->
+    <div class="key-metrics-section">
+        <div class="section-title">
+            <h2>产品销售概览</h2>
+        </div>
+        <?php
+        $sales_overview = getProductSalesOverview($conn, $start_date, $end_date, $category_filter);
+        renderProductSalesOverview($sales_overview);
+        ?>
+    </div>
+    
+    <!-- 热门产品 -->
+    <div class="chart-container">
+        <?php
+        $top_products = getTopProducts($conn, $start_date, $end_date, 10);
+        renderTopProductsTable($top_products);
+        ?>
+    </div>
+    
+    <!-- 产品销售趋势 -->
+    <div class="chart-container">
+        <?php
+        $product_trends = getProductSalesTrend($conn, $start_date, $end_date, $product_id, $period);
+        
+        $time_labels = [];
+        $quantities = [];
+        $revenues = [];
+        
+        while ($row = $product_trends->fetch_assoc()) {
+            $time_labels[] = $row['time_period'];
+            $quantities[] = $row['total_quantity'];
+            $revenues[] = $row['total_revenue'];
+        }
+        renderProductSalesTrendChart($time_labels, $quantities, $revenues);
+        ?>
+    </div>
+    
+    <!-- 产品类别销售分布 -->
+    <div class="chart-container">
+        <?php
+        $category_sales = getProductCategorySales($conn, $start_date, $end_date);
+        
+        $categories = [];
+        $category_quantities = [];
+        $category_revenues = [];
+        
+        while ($row = $category_sales->fetch_assoc()) {
+            $categories[] = $row['category_name'];
+            $category_quantities[] = $row['total_quantity'];
+            $category_revenues[] = $row['total_revenue'];
+        }
+        renderProductCategorySalesChart($categories, $category_quantities, $category_revenues);
+        ?>
+    </div>
+    
+    <!-- 产品价格趋势分析 -->
+    <div class="chart-container">
+        <?php
+        $price_trend_data = getProductPriceTrendAnalysis($conn, $start_date, $end_date, $product_id, $period);
+        renderProductPriceTrendChart($price_trend_data);
+        ?>
+    </div>
+    
+    <!-- 产品季节性分析 -->
+    <div class="chart-container">
+        <?php
+        $seasonality_data = getProductSeasonalityAnalysis($conn, $start_date, $end_date, $product_id);
+        renderProductSeasonalityChart($seasonality_data);
+        ?>
+    </div>
+    
+    <!-- 产品客户细分分析 -->
+    <div class="chart-container">
+        <?php
+        $customer_segment_data = getProductCustomerSegmentAnalysis($conn, $start_date, $end_date, $product_id);
+        renderProductCustomerSegmentChart($customer_segment_data);
+        ?>
+    </div>
+    
+    <!-- 产品地区关联分析 -->
+    <div class="chart-container">
+        <?php
+        $product_region_data = getProductRegionAnalysis($conn, $start_date, $end_date);
+        renderProductRegionAnalysisTable($product_region_data);
+        ?>
+    </div>
+    
+    <!-- 产品增长率分析 -->
+    <div class="chart-container">
+        <?php
+        $growth_data = getProductGrowthAnalysis($conn, $start_date, $end_date, $period);
+        renderProductGrowthAnalysis($growth_data);
+        ?>
+    </div>
+    
+    <!-- 产品购买频率分析 -->
+    <div class="chart-container">
+        <?php
+        $frequency_data = getProductPurchaseFrequency($conn, $start_date, $end_date);
+        renderProductPurchaseFrequency($frequency_data);
+        ?>
+    </div>
+</div>
+
+<script>
+function toggleCustomDates() {
+    const dateRange = document.getElementById('date_range').value;
+    const customDateInputs = document.querySelectorAll('.custom-date-inputs');
+    
+    if (dateRange === 'custom') {
+        customDateInputs.forEach(el => el.style.display = 'inline-block');
+    } else {
+        customDateInputs.forEach(el => el.style.display = 'none');
+    }
+}
+
+// 初始化所有图表的配置
+Chart.defaults.font.family = "'Arial', sans-serif";
+Chart.defaults.color = '#666';
+Chart.defaults.plugins.tooltip.backgroundColor = 'rgba(0, 0, 0, 0.8)';
+Chart.defaults.plugins.legend.position = 'bottom';
+</script>
+
+<?php
+// 页面底部
+include('statistics_footer.php');
+?> 

+ 385 - 0
region_stats.php

@@ -0,0 +1,385 @@
+<?php
+/**
+ * 地区统计分析展示页面
+ */
+require_once 'conn.php';
+require_once 'statistics_utils.php';
+require_once 'statistics_region.php';
+
+// 检查登录状态
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+// 获取日期范围参数
+$date_params = getDateRangeParams();
+$start_date = $date_params['start_date_sql'];
+$end_date = $date_params['end_date_sql'];
+$date_range = $date_params['date_range'];
+$period = $date_params['period'];
+
+// 特定国家过滤
+$country_id = isset($_GET['country_id']) ? intval($_GET['country_id']) : 0;
+
+// 页面头部
+include('statistics_header.php');
+?>
+
+
+    <div class="page-header">
+        <h1 class="page-title">地区统计分析</h1>
+    </div>
+    
+    <!-- 日期筛选 -->
+    <div class="filter-form">
+        <form method="get" class="filter-form-inline">
+            <div class="form-group">
+                <label for="date_range">选择日期范围</label>
+                <select class="form-control" id="date_range" name="date_range" onchange="toggleCustomDates()">
+                    <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                    <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                    <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                    <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>最近30天</option>
+                    <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>最近90天</option>
+                    <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义日期范围</option>
+                </select>
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="start_date">开始日期</label>
+                <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $date_params['custom_start']; ?>">
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="end_date">结束日期</label>
+                <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $date_params['custom_end']; ?>">
+            </div>
+            <div class="form-group">
+                <label for="period">时间粒度</label>
+                <select class="form-control" id="period" name="period">
+                    <option value="day" <?php echo $period == 'day' ? 'selected' : ''; ?>>日</option>
+                    <option value="week" <?php echo $period == 'week' ? 'selected' : ''; ?>>周</option>
+                    <option value="month" <?php echo $period == 'month' ? 'selected' : ''; ?>>月</option>
+                </select>
+            </div>
+            <div class="form-group">
+                <label for="country_id">国家/地区</label>
+                <select class="form-control" id="country_id" name="country_id">
+                    <option value="0">全部地区</option>
+                    <?php
+                    $country_filter = isset($_GET['country_id']) ? intval($_GET['country_id']) : 0;
+                    $sql = "SELECT id, countryName FROM country ORDER BY countryName";
+                    $countries = $conn->query($sql);
+                    while($country = $countries->fetch_assoc()) {
+                        $selected = ($country_filter == $country['id']) ? 'selected' : '';
+                        echo "<option value='{$country['id']}' {$selected}>{$country['countryName']}</option>";
+                    }
+                    ?>
+                </select>
+            </div>
+            <div class="form-group">
+                <button type="submit" class="btn">应用筛选</button>
+            </div>
+        </form>
+    </div>
+    
+    <!-- 地区销售数据概览 -->
+    <div class="key-metrics-section">
+        <div class="section-title">
+            <h2>地区销售概览</h2>
+        </div>
+        <div class="stats-row">
+            <div class="stat-card">
+                <h3>总销售额</h3>
+                <?php
+                $total_sales = getRegionTotalSales($conn, $start_date, $end_date);
+                echo "<div class='stat-value'>¥" . number_format($total_sales['total_amount'], 2) . "</div>";
+                echo "<div class='stat-trend " . ($total_sales['growth'] >= 0 ? 'positive' : 'negative') . "'>";
+                echo ($total_sales['growth'] >= 0 ? '+' : '') . number_format($total_sales['growth'], 2) . "%</div>";
+                ?>
+            </div>
+            
+            <div class="stat-card">
+                <h3>活跃国家数</h3>
+                <?php
+                $active_countries = getActiveCountries($conn, $start_date, $end_date);
+                echo "<div class='stat-value'>" . $active_countries['count'] . "</div>";
+                ?>
+            </div>
+            
+            <div class="stat-card">
+                <h3>平均订单金额</h3>
+                <?php
+                $avg_order = getAverageOrderByRegion($conn, $start_date, $end_date);
+                echo "<div class='stat-value'>¥" . number_format($avg_order['global_avg'], 2) . "</div>";
+                ?>
+            </div>
+        </div>
+    </div>
+    
+    <!-- 热门地区 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>热门地区</h2>
+        </div>
+        <?php
+        $region_orders = getOrdersByRegion($conn, $start_date, $end_date);
+        $region_labels = [];
+        $region_order_counts = [];
+        $region_quantities = [];
+        $region_amounts = [];
+        
+        while ($row = $region_orders->fetch_assoc()) {
+            $region_labels[] = $row['countryName'];
+            $region_order_counts[] = $row['order_count'];
+            $region_quantities[] = $row['total_quantity'];
+            $region_amounts[] = $row['total_amount'];
+        }
+        renderTopRegionsTable($region_labels, $region_order_counts, $region_quantities, $region_amounts);
+        ?>
+    </div>
+    
+    <!-- 客户国家分布 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>客户国家分布</h2>
+        </div>
+        <?php
+        $country_distribution = getCustomerCountryDistribution($conn);
+        $country_labels = [];
+        $country_data = [];
+        
+        while ($row = $country_distribution->fetch_assoc()) {
+            $country_labels[] = $row['countryName'];
+            $country_data[] = $row['customer_count'];
+        }
+        renderCustomerCountryDistributionChart($country_labels, $country_data);
+        ?>
+    </div>
+    
+    <!-- 地区销售趋势 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区销售趋势</h2>
+        </div>
+        <?php
+        $growth_trends = getRegionGrowthTrends($conn, $start_date, $end_date, $period);
+        renderRegionGrowthTrendsChart($growth_trends);
+        ?>
+    </div>
+    
+    <!-- 地区订单分析 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区订单分析</h2>
+        </div>
+        <?php
+        renderRegionOrdersChart($region_labels, $region_order_counts, $region_quantities);
+        ?>
+    </div>
+    
+    <!-- 地区平均订单金额分析 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区平均订单金额分析</h2>
+        </div>
+        <?php
+        $avg_order_data = getAverageOrderByRegion($conn, $start_date, $end_date);
+        renderAverageOrderByRegionChart($avg_order_data['regions']);
+        ?>
+    </div>
+    
+    <!-- 各地区产品类别偏好 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>各地区产品类别偏好</h2>
+        </div>
+        <?php
+        $category_preferences = getRegionCategoryPreferences($conn, $start_date, $end_date);
+        renderRegionCategoryPreferencesChart($category_preferences);
+        ?>
+    </div>
+    
+    <!-- 地区销售同比分析 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区销售同比分析</h2>
+        </div>
+        <?php
+        $comparison_data = getRegionSalesComparison($conn, $start_date, $end_date);
+        renderRegionSalesComparisonTable($comparison_data);
+        ?>
+    </div>
+    
+    <!-- 地区季节性分析 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区季节性分析</h2>
+        </div>
+        <?php
+        $seasonal_analysis = getRegionSeasonalAnalysis($conn);
+        renderRegionSeasonalAnalysisChart($seasonal_analysis);
+        ?>
+    </div>
+    
+    <!-- 地区销售预测 -->
+    <div class="chart-container">
+        <div class="section-title">
+            <h2>地区销售预测</h2>
+        </div>
+        <?php
+        $forecast_data = getRegionSalesForecast($conn, $start_date, $end_date);
+        renderRegionSalesForecastChart($forecast_data);
+        ?>
+    </div>
+
+
+<style>
+    .positive {
+        color: #28a745;
+        font-weight: bold;
+    }
+    .negative {
+        color: #dc3545;
+        font-weight: bold;
+    }
+    .key-metrics-section {
+        margin-bottom: 30px;
+    }
+    .section-title {
+        margin-bottom: 20px;
+        border-bottom: 1px solid #eee;
+        padding-bottom: 10px;
+    }
+    .section-title h2 {
+        font-size: 20px;
+        margin: 0;
+        color: #333;
+    }
+    .stats-row {
+        display: flex;
+        flex-wrap: nowrap;
+        gap: 20px;
+        justify-content: space-between;
+        width: 100%;
+        margin-bottom: 20px;
+    }
+    .stat-card {
+        background-color: #f8f9fa;
+        border-radius: 8px;
+        padding: 20px;
+        margin-bottom: 0;
+        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+        height: 100%;
+        transition: all 0.3s ease;
+        flex: 1;
+        min-width: 0; /* Prevents flex items from overflowing */
+    }
+    .stat-card:hover {
+        transform: translateY(-5px);
+        box-shadow: 0 5px 15px rgba(0,0,0,0.1);
+    }
+    .stat-value {
+        font-size: 24px;
+        font-weight: bold;
+        margin: 10px 0;
+    }
+    .stat-trend {
+        font-size: 16px;
+    }
+    .chart-container {
+        background-color: #fff;
+        border-radius: 8px;
+        padding: 20px;
+        margin-bottom: 30px;
+        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+    }
+    .chart-title {
+        margin-top: 0;
+        margin-bottom: 20px;
+        font-size: 18px;
+        font-weight: bold;
+    }
+    .filter-form {
+        background-color: #f8f9fa;
+        border-radius: 8px;
+        padding: 15px;
+        margin-bottom: 30px;
+        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+    }
+    .filter-form-inline {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: end;
+        gap: 15px;
+    }
+    .form-group {
+        margin-bottom: 10px;
+    }
+    .data-table {
+        width: 100%;
+        border-collapse: collapse;
+        margin-top: 15px;
+    }
+    .data-table th, .data-table td {
+        padding: 12px 15px;
+        text-align: left;
+        border-bottom: 1px solid #ddd;
+    }
+    .data-table th {
+        background-color: #f8f9fa;
+        font-weight: bold;
+        color: #333;
+    }
+    .data-table tr:hover {
+        background-color: #f5f5f5;
+    }
+    .subchart-container {
+        margin-bottom: 20px;
+    }
+    .subchart-title {
+        font-size: 16px;
+        margin-bottom: 15px;
+        color: #555;
+    }
+    .grid-row {
+        display: flex;
+        flex-wrap: wrap;
+        margin: -10px; /* Negative margin to offset the padding in grid-column */
+    }
+    .grid-column {
+        flex: 0 0 50%; /* Two columns per row */
+        padding: 10px;
+        box-sizing: border-box;
+    }
+    @media (max-width: 768px) {
+        .grid-column {
+            flex: 0 0 100%; /* Full width on small screens */
+        }
+        .stats-row {
+            flex-direction: column;
+        }
+    }
+</style>
+
+<script>
+function toggleCustomDates() {
+    const dateRange = document.getElementById('date_range').value;
+    const customDateInputs = document.querySelectorAll('.custom-date-inputs');
+    
+    if (dateRange === 'custom') {
+        customDateInputs.forEach(el => el.style.display = 'inline-block');
+    } else {
+        customDateInputs.forEach(el => el.style.display = 'none');
+    }
+}
+
+// 初始化所有图表的配置
+Chart.defaults.font.family = "'Arial', sans-serif";
+Chart.defaults.color = '#666';
+Chart.defaults.plugins.tooltip.backgroundColor = 'rgba(0, 0, 0, 0.8)';
+Chart.defaults.plugins.legend.position = 'bottom';
+</script>
+
+<?php
+// 页面底部
+include('statistics_footer.php');
+?> 

+ 475 - 0
sales_stats.php

@@ -0,0 +1,475 @@
+<?php
+/**
+ * 销售统计分析展示页面
+ */
+require_once 'conn.php';
+require_once 'statistics_utils.php';
+require_once 'statistics_sales.php';
+
+// Helper functions for formatting
+
+function formatCurrency($value) {
+    return '¥' . number_format($value ?? 0, 2);
+}
+
+// 检查登录状态
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+// 获取日期范围参数
+$date_params = getDateRangeParams();
+$start_date = $date_params['start_date_sql'];
+$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');
+?>
+
+<style>
+
+.page-header {
+    margin-bottom: 30px;
+}
+
+.page-title {
+    font-size: 24px;
+    color: #333;
+    margin: 0;
+}
+
+.filter-form {
+    background: #f5f5f5;
+    padding: 20px;
+    border-radius: 8px;
+    margin-bottom: 30px;
+}
+
+.filter-form-inline {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+    align-items: flex-end;
+}
+
+.form-group {
+    margin-bottom: 10px;
+}
+
+.form-group label {
+    display: block;
+    margin-bottom: 5px;
+    color: #666;
+}
+
+
+
+.btn {
+    background: #4a90e2;
+    color: white;
+    padding: 8px 16px;
+    border: none;
+    border-radius: 4px;
+    cursor: pointer;
+}
+
+.btn:hover {
+    background: #357abd;
+}
+
+.chart-container {
+    background: white;
+    border-radius: 8px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+    padding: 20px;
+    margin-bottom: 30px;
+}
+
+.chart-header {
+    margin-bottom: 20px;
+}
+
+.chart-title {
+    font-size: 18px;
+    color: #333;
+    margin: 0;
+}
+
+.stats-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+    gap: 20px;
+    margin-bottom: 30px;
+}
+
+.stat-card {
+    background: white;
+    padding: 20px;
+    border-radius: 8px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+    text-align: center;
+}
+
+.stat-card h3 {
+    font-size: 16px;
+    color: #666;
+    margin: 0 0 10px 0;
+}
+
+.stat-value {
+    font-size: 24px;
+    color: #4a90e2;
+    font-weight: bold;
+}
+
+.analysis-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
+    gap: 20px;
+    margin-bottom: 30px;
+}
+
+.table-responsive {
+    overflow-x: auto;
+}
+
+.data-table {
+    width: 100%;
+    border-collapse: collapse;
+}
+
+.data-table th,
+.data-table td {
+    padding: 12px;
+    text-align: left;
+    border-bottom: 1px solid #ddd;
+}
+
+.data-table th {
+    background: #f5f5f5;
+    font-weight: bold;
+}
+
+.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">
+    <div class="page-header">
+        <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()">
+                    <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                    <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                    <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                    <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>最近30天</option>
+                    <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>最近90天</option>
+                    <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义日期范围</option>
+                </select>
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="start_date">开始日期</label>
+                <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $date_params['custom_start']; ?>">
+            </div>
+            <div class="form-group custom-date-inputs" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="end_date">结束日期</label>
+                <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $date_params['custom_end']; ?>">
+            </div>
+            <div class="form-group">
+                <label for="period">时间粒度</label>
+                <select class="form-control" id="period" name="period">
+                    <option value="day" <?php echo $period == 'day' ? 'selected' : ''; ?>>日</option>
+                    <option value="week" <?php echo $period == 'week' ? 'selected' : ''; ?>>周</option>
+                    <option value="month" <?php echo $period == 'month' ? 'selected' : ''; ?>>月</option>
+                </select>
+            </div>
+            <div class="form-group">
+                <button type="submit" class="btn">应用筛选</button>
+            </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 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>
+
+        <!-- 业务员销售趋势 -->
+        <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">
+            <h2 class="chart-title">销售概览</h2>
+        </div>
+        <div class="card-body">
+            <?php
+            $sales_overview = getSalesOverview($conn, $start_date, $end_date);
+            renderSalesOverviewCards($sales_overview);
+            ?>
+        </div>
+    </div>
+    
+    <!-- 销售转化率分析 -->
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">销售转化率分析</h2>
+        </div>
+        <?php
+        $conversion_stats = getOrderConversionStats($conn, $start_date, $end_date);
+        renderConversionAnalysis($conversion_stats);
+        ?>
+    </div>
+
+    <!-- 产品类别销售分析 -->
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品类别销售分析</h2>
+        </div>
+        <?php
+        $category_sales = getProductCategorySales($conn, $start_date, $end_date);
+        renderCategorySalesChart($category_sales);
+        ?>
+    </div>
+
+    <!-- 客户地区分布 -->
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户地区分布</h2>
+        </div>
+        <?php
+        $customer_distribution = getCustomerDistribution($conn, $start_date, $end_date);
+        renderCustomerDistributionChart($customer_distribution);
+        ?>
+    </div>
+
+    <!-- 销售员业绩排行 -->
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">销售员业绩排行</h2>
+        </div>
+        <?php
+        $employee_performance = getEmployeePerformance($conn, $start_date, $end_date);
+        renderEmployeePerformanceTable($employee_performance);
+        ?>
+    </div>
+    
+    <!-- 月度销售趋势 -->
+    <div class="chart-container">
+        <?php
+        $monthly_sales = getMonthlySalesTrend($conn, $start_date, $end_date);
+        
+        $monthly_labels = [];
+        $monthly_orders = [];
+        $monthly_revenue = [];
+        
+        while ($row = $monthly_sales->fetch_assoc()) {
+            $monthly_labels[] = $row['month'];
+            $monthly_orders[] = $row['orders'];
+            $monthly_revenue[] = $row['revenue'];
+        }
+        
+        renderMonthlySalesTrendChart($monthly_labels, $monthly_orders, $monthly_revenue);
+        ?>
+    </div>
+    
+    <!-- 支付状态分析 -->
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">支付状态分析</h2>
+        </div>
+        <?php
+        $payment_stats = getPaymentStatusStats($conn, $start_date, $end_date);
+        renderPaymentStatusChart($payment_stats);
+        ?>
+    </div>
+
+    <!-- 详细订单趋势 -->
+    <div class="chart-container">
+        <?php
+        $detailed_trends = getDetailedOrderTrend($conn, $start_date, $end_date, $period);
+        
+        $time_labels = [];
+        $time_orders = [];
+        $time_quantities = [];
+        
+        while ($row = $detailed_trends->fetch_assoc()) {
+            $time_labels[] = $row['time_period'];
+            $time_orders[] = $row['order_count'];
+            $time_quantities[] = $row['total_quantity'];
+        }
+        renderDetailedOrderTrendChart($time_labels, $time_orders, $time_quantities, $period);
+        ?>
+    </div>
+</div>
+
+<script>
+function toggleCustomDates() {
+    const dateRange = document.getElementById('date_range').value;
+    const customDateInputs = document.querySelectorAll('.custom-date-inputs');
+    
+    customDateInputs.forEach(el => {
+        el.style.display = dateRange === 'custom' ? 'inline-block' : 'none';
+    });
+}
+</script>
+
+<?php
+include('statistics_footer.php');
+?> 

+ 2 - 2
silentCustomer.php

@@ -188,9 +188,9 @@ $hrefstr = "?keys=" . $keys;
                        value="<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>" 
                        onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>'){this.value='';}" 
                        onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>';}" 
-                       onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+                       onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
                 <input type="button" id="searchgo" class="searchgo" value="go" 
-                       onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                       onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
             </div>
         </div>
 

+ 1011 - 0
statistics.php

@@ -0,0 +1,1011 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+//检查是否管理员
+checkAdmin();
+
+// 计算日期范围
+$current_month_start = date('Y-m-01');
+$current_month_end = date('Y-m-t');
+$last_month_start = date('Y-m-01', strtotime('-1 month'));
+$last_month_end = date('Y-m-t', strtotime('-1 month'));
+$current_year_start = date('Y-01-01');
+$current_year_end = date('Y-12-31');
+
+// 可选的日期范围筛选
+$date_range = isset($_GET['date_range']) ? $_GET['date_range'] : 'current_month';
+$custom_start = isset($_GET['start_date']) ? $_GET['start_date'] : '';
+$custom_end = isset($_GET['end_date']) ? $_GET['end_date'] : '';
+
+// 设置日期范围
+if ($date_range == 'custom' && !empty($custom_start) && !empty($custom_end)) {
+    $start_date = $custom_start;
+    $end_date = $custom_end;
+} else {
+    switch ($date_range) {
+        case 'last_month':
+            $start_date = $last_month_start;
+            $end_date = $last_month_end;
+            break;
+        case 'current_year':
+            $start_date = $current_year_start;
+            $end_date = $current_year_end;
+            break;
+        case 'last_30_days':
+            $start_date = date('Y-m-d', strtotime('-30 days'));
+            $end_date = date('Y-m-d');
+            break;
+        case 'last_90_days':
+            $start_date = date('Y-m-d', strtotime('-90 days'));
+            $end_date = date('Y-m-d');
+            break;
+        case 'current_month':
+        default:
+            $start_date = $current_month_start;
+            $end_date = $current_month_end;
+            break;
+    }
+}
+
+// 格式化日期用于SQL查询
+$start_date_sql = date('Y-m-d', strtotime($start_date));
+$end_date_sql = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
+
+// 函数:获取销售概览数据
+function getSalesOverview($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                COUNT(id) as total_orders,
+                SUM(total_amount) as total_revenue,
+                AVG(total_amount) as avg_order_value
+            FROM orders 
+            WHERE order_date BETWEEN ? AND ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    return $result->fetch_assoc();
+}
+
+// 函数:获取每月销售趋势
+function getMonthlySalesTrend($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                DATE_FORMAT(order_date, '%Y-%m') as month,
+                COUNT(id) as orders,
+                SUM(total_amount) as revenue
+            FROM orders 
+            WHERE order_date BETWEEN ? AND ?
+            GROUP BY DATE_FORMAT(order_date, '%Y-%m')
+            ORDER BY month";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 函数:获取客户国家分布
+function getCustomerCountryDistribution($conn) {
+    $sql = "SELECT 
+                c.countryName, 
+                COUNT(cu.id) as customer_count
+            FROM customer cu
+            JOIN country c ON cu.cs_country = c.id
+            GROUP BY cu.cs_country
+            ORDER BY customer_count DESC
+            LIMIT 10";
+    
+    return $conn->query($sql);
+}
+
+// 函数:获取客户类型分布
+function getCustomerTypeDistribution($conn) {
+    $sql = "SELECT 
+                ct.businessType, 
+                COUNT(c.id) as customer_count
+            FROM customer c
+            JOIN clienttype ct ON c.cs_type = ct.id
+            GROUP BY c.cs_type";
+    
+    return $conn->query($sql);
+}
+
+// 函数:获取成交阶段分布
+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);
+}
+
+// 函数:获取热门产品
+function getTopProducts($conn, $start_date, $end_date, $limit = 5) {
+    $sql = "SELECT 
+                p.ProductName, 
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY oi.product_id
+            ORDER BY total_revenue DESC
+            LIMIT ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ssi", $start_date, $end_date, $limit);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 函数:获取业务员销售业绩
+function getEmployeeSalesPerformance($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                e.em_user as employee_name,
+                COUNT(o.id) as order_count,
+                SUM(o.total_amount) as total_sales
+            FROM orders o
+            JOIN employee e ON o.employee_id = e.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY o.employee_id
+            ORDER BY total_sales DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 函数:获取客户增长趋势
+function getCustomerGrowthTrend($conn) {
+    $sql = "SELECT 
+                DATE_FORMAT(cs_addtime, '%Y-%m') as month,
+                COUNT(id) as new_customers
+            FROM customer
+            WHERE cs_addtime >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
+            GROUP BY DATE_FORMAT(cs_addtime, '%Y-%m')
+            ORDER BY month";
+    
+    return $conn->query($sql);
+}
+
+// 函数:获取不同地区的订单数量
+function getOrdersByRegion($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName, 
+                COUNT(o.id) as order_count,
+                SUM(o.total_amount) as total_amount,
+                SUM(oi.quantity) as total_quantity
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            LEFT JOIN order_items oi ON o.id = oi.order_id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country
+            ORDER BY total_quantity DESC
+            LIMIT 10";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 函数:获取详细时间段订单数量
+function getDetailedOrderTrend($conn, $start_date, $end_date, $period = 'day') {
+    $groupFormat = '%Y-%m-%d';
+    $intervalUnit = 'DAY';
+    
+    if ($period == 'week') {
+        $groupFormat = '%x-W%v'; // ISO year and week number
+        $intervalUnit = 'WEEK';
+    } else if ($period == 'month') {
+        $groupFormat = '%Y-%m';
+        $intervalUnit = 'MONTH';
+    }
+    
+    $sql = "SELECT 
+                DATE_FORMAT(o.order_date, '$groupFormat') as time_period,
+                COUNT(o.id) as order_count,
+                SUM(oi.quantity) as total_quantity
+            FROM orders o
+            LEFT JOIN order_items oi ON o.id = oi.order_id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY time_period
+            ORDER BY MIN(o.order_date)";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 获取统计数据
+$sales_overview = getSalesOverview($conn, $start_date_sql, $end_date_sql);
+$monthly_sales = getMonthlySalesTrend($conn, $start_date_sql, $end_date_sql);
+$country_distribution = getCustomerCountryDistribution($conn);
+$customer_types = getCustomerTypeDistribution($conn);
+$deal_stages = getDealStageDistribution($conn);
+$top_products = getTopProducts($conn, $start_date_sql, $end_date_sql);
+$employee_performance = getEmployeeSalesPerformance($conn, $start_date_sql, $end_date_sql);
+$customer_growth = getCustomerGrowthTrend($conn);
+$orders_by_region = getOrdersByRegion($conn, $start_date_sql, $end_date_sql);
+
+// 获取详细时间段订单趋势 - 默认按日期
+$period = isset($_GET['period']) ? $_GET['period'] : 'day';
+$detailed_orders = getDetailedOrderTrend($conn, $start_date_sql, $end_date_sql, $period);
+
+// 将月度销售数据转换为图表所需格式
+$monthly_labels = [];
+$monthly_orders = [];
+$monthly_revenue = [];
+
+while ($row = $monthly_sales->fetch_assoc()) {
+    $monthly_labels[] = $row['month'];
+    $monthly_orders[] = $row['orders'];
+    $monthly_revenue[] = $row['revenue'];
+}
+
+// 将国家分布数据转换为图表所需格式
+$country_labels = [];
+$country_data = [];
+
+while ($row = $country_distribution->fetch_assoc()) {
+    $country_labels[] = $row['countryName'];
+    $country_data[] = $row['customer_count'];
+}
+
+// 将客户类型数据转换为图表所需格式
+$type_labels = [];
+$type_data = [];
+
+while ($row = $customer_types->fetch_assoc()) {
+    $type_labels[] = $row['businessType'];
+    $type_data[] = $row['customer_count'];
+}
+
+// 将成交阶段数据转换为图表所需格式
+$stage_labels = [];
+$stage_data = [];
+
+while ($row = $deal_stages->fetch_assoc()) {
+    $stage_labels[] = $row['stage_name'];
+    $stage_data[] = $row['customer_count'];
+}
+
+// 将客户增长数据转换为图表所需格式
+$growth_labels = [];
+$growth_data = [];
+
+while ($row = $customer_growth->fetch_assoc()) {
+    $growth_labels[] = $row['month'];
+    $growth_data[] = $row['new_customers'];
+}
+
+// 将地区订单数据转换为图表所需格式
+$region_labels = [];
+$region_orders = [];
+$region_quantities = [];
+
+while ($row = $orders_by_region->fetch_assoc()) {
+    $region_labels[] = $row['countryName'];
+    $region_orders[] = $row['order_count'];
+    $region_quantities[] = $row['total_quantity'];
+}
+
+// 将详细时间订单数据转换为图表所需格式
+$time_labels = [];
+$time_orders = [];
+$time_quantities = [];
+
+while ($row = $detailed_orders->fetch_assoc()) {
+    $time_labels[] = $row['time_period'];
+    $time_orders[] = $row['order_count'];
+    $time_quantities[] = $row['total_quantity'];
+}
+?>
+
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>统计分析</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <script src="system/js/jquery-1.7.2.min.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+            font-family: Arial, sans-serif;
+        }
+        
+        .container {
+            width: 100%;
+            max-width: 1200px;
+            margin: 0 auto;
+        }
+        
+        .page-header {
+            margin-bottom: 20px;
+            border-bottom: 1px solid #eee;
+            padding-bottom: 10px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+        }
+        
+        .page-title {
+            font-size: 24px;
+            font-weight: bold;
+            color: #333;
+            margin: 0;
+        }
+        
+        .export-btn {
+            padding: 8px 15px;
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+            text-decoration: none;
+            display: inline-block;
+        }
+        
+        .export-btn:hover {
+            background: #45a049;
+        }
+        
+        .filter-form {
+            background: #f9f9f9;
+            padding: 15px;
+            border-radius: 5px;
+            margin-bottom: 20px;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 15px;
+            align-items: center;
+        }
+        
+        .form-group {
+            margin-right: 15px;
+        }
+        
+        .form-group label {
+            display: block;
+            margin-bottom: 5px;
+            font-weight: bold;
+        }
+        
+        .form-control {
+            padding: 8px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            min-width: 150px;
+        }
+        
+        .btn {
+            padding: 8px 15px;
+            background: #337ab7;
+            color: white;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+        
+        .btn:hover {
+            background: #286090;
+        }
+        
+        .stats-grid {
+            display: grid;
+            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+        
+        .stat-card {
+            background: white;
+            border-radius: 5px;
+            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+            padding: 20px;
+        }
+        
+        .stat-card h3 {
+            margin-top: 0;
+            color: #555;
+            font-size: 16px;
+            border-bottom: 1px solid #eee;
+            padding-bottom: 10px;
+        }
+        
+        .stat-value {
+            font-size: 24px;
+            font-weight: bold;
+            color: #333;
+            margin: 15px 0;
+        }
+        
+        .chart-container {
+            margin-bottom: 30px;
+            background: white;
+            border-radius: 5px;
+            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+            padding: 20px;
+        }
+        
+        .chart-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 15px;
+        }
+        
+        .chart-title {
+            font-size: 18px;
+            font-weight: bold;
+            color: #333;
+            margin: 0;
+        }
+        
+        .data-table {
+            width: 100%;
+            border-collapse: collapse;
+            margin-top: 20px;
+        }
+        
+        .data-table th, .data-table td {
+            padding: 10px;
+            text-align: left;
+            border-bottom: 1px solid #eee;
+        }
+        
+        .data-table th {
+            background: #f5f5f5;
+            font-weight: bold;
+        }
+        
+        .data-table tr:hover {
+            background: #f9f9f9;
+        }
+        
+        .custom-date-inputs {
+            display: none;
+        }
+        
+        #date_range[value="custom"]:checked ~ .custom-date-inputs {
+            display: block;
+        }
+        
+        .download-btn {
+            padding: 5px 10px;
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 3px;
+            font-size: 14px;
+            cursor: pointer;
+        }
+        
+        .download-btn:hover {
+            background: #45a049;
+        }
+        
+        /* 确保筛选表单元素在同一行显示 */
+        .filter-form form {
+            display: flex;
+            flex-direction: row;
+            align-items: flex-end;
+            gap: 15px;
+            flex-wrap: nowrap;
+            width: 100%;
+        }
+        .filter-form .form-group {
+            margin-right: 0;
+            flex: 0 0 auto;
+            white-space: nowrap;
+        }
+        .filter-form label {
+            display: block;
+            margin-bottom: 5px;
+            font-weight: bold;
+        }
+        .filter-form #custom_dates {
+            display: flex;
+            flex-direction: row;
+            gap: 10px;
+            flex: 0 0 auto;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="page-header">
+            <h1 class="page-title">统计分析</h1>
+            <a href="export_statistics.php?date_range=<?php echo $date_range; ?>&start_date=<?php echo $custom_start; ?>&end_date=<?php echo $custom_end; ?>&period=<?php echo $period; ?>" class="export-btn">导出数据</a>
+        </div>
+        
+        <div class="filter-form">
+            <form method="get" action="">
+                <div class="form-group">
+                    <label>日期范围</label>
+                    <select name="date_range" id="date_range" class="form-control" onchange="toggleCustomDates()">
+                        <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                        <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                        <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>过去30天</option>
+                        <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>过去90天</option>
+                        <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                        <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义</option>
+                    </select>
+                </div>
+                
+                <div id="custom_dates" style="display: <?php echo $date_range == 'custom' ? 'flex' : 'none'; ?>;">
+                    <div class="form-group">
+                        <label>开始日期</label>
+                        <input type="date" name="start_date" class="form-control" value="<?php echo $custom_start; ?>">
+                    </div>
+                    <div class="form-group">
+                        <label>结束日期</label>
+                        <input type="date" name="end_date" class="form-control" value="<?php echo $custom_end; ?>">
+                    </div>
+                </div>
+                
+                <div class="form-group">
+                    <label>时间粒度</label>
+                    <select name="period" class="form-control">
+                        <option value="day" <?php echo $period == 'day' ? 'selected' : ''; ?>>按日</option>
+                        <option value="week" <?php echo $period == 'week' ? 'selected' : ''; ?>>按周</option>
+                        <option value="month" <?php echo $period == 'month' ? 'selected' : ''; ?>>按月</option>
+                    </select>
+                </div>
+                
+                <div class="form-group">
+                    <input type="submit" class="btn" value="应用筛选">
+                </div>
+            </form>
+        </div>
+        
+        <!-- 销售概览卡片 -->
+        <div class="stats-grid">
+            <div class="stat-card">
+                <h3>总订单数</h3>
+                <div class="stat-value"><?php echo number_format($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>
+            
+            <div class="stat-card">
+                <h3>平均订单金额</h3>
+                <div class="stat-value">¥<?php echo number_format($sales_overview['avg_order_value'], 2); ?></div>
+            </div>
+        </div>
+        
+        <!-- 月度销售趋势图 -->
+        <div class="chart-container">
+            <div class="chart-header">
+                <h2 class="chart-title">销售趋势</h2>
+            </div>
+            <canvas id="salesTrendChart"></canvas>
+        </div>
+        
+        <!-- 客户分布图 -->
+        <div class="stats-grid">
+            <div class="chart-container">
+                <div class="chart-header">
+                    <h2 class="chart-title">客户国家分布</h2>
+                </div>
+                <canvas id="countryDistributionChart"></canvas>
+            </div>
+            
+            <div class="chart-container">
+                <div class="chart-header">
+                    <h2 class="chart-title">客户类型分布</h2>
+                </div>
+                <canvas id="customerTypeChart"></canvas>
+            </div>
+        </div>
+        
+        <div class="stats-grid">
+            <div class="chart-container">
+                <div class="chart-header">
+                    <h2 class="chart-title">成交阶段分布</h2>
+                </div>
+                <canvas id="dealStageChart"></canvas>
+            </div>
+            
+            <div class="chart-container">
+                <div class="chart-header">
+                    <h2 class="chart-title">客户增长趋势</h2>
+                </div>
+                <canvas id="customerGrowthChart"></canvas>
+            </div>
+        </div>
+        
+        <!-- 地区订单分析 -->
+        <div class="chart-container">
+            <div class="chart-header">
+                <h2 class="chart-title">地区订单分析</h2>
+            </div>
+            <canvas id="regionOrdersChart"></canvas>
+        </div>
+        
+        <!-- 详细时间段订单趋势 -->
+        <div class="chart-container">
+            <div class="chart-header">
+                <h2 class="chart-title">详细订单趋势 (<?php echo $period == 'day' ? '日' : ($period == 'week' ? '周' : '月'); ?>)</h2>
+            </div>
+            <canvas id="detailedOrdersChart"></canvas>
+        </div>
+        
+        <!-- 热门产品表格 -->
+        <div class="chart-container">
+            <div class="chart-header">
+                <h2 class="chart-title">热门产品</h2>
+            </div>
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>产品名称</th>
+                        <th>销售数量</th>
+                        <th>销售收入</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php while ($row = $top_products->fetch_assoc()): ?>
+                    <tr>
+                        <td><?php echo htmlspecialchars($row['ProductName']); ?></td>
+                        <td><?php echo number_format($row['total_quantity']); ?></td>
+                        <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
+                    </tr>
+                    <?php endwhile; ?>
+                </tbody>
+            </table>
+        </div>
+        
+        <!-- 业务员销售业绩表格 -->
+        <div class="chart-container">
+            <div class="chart-header">
+                <h2 class="chart-title">业务员销售业绩</h2>
+            </div>
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>业务员姓名</th>
+                        <th>订单数量</th>
+                        <th>销售总额</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php while ($row = $employee_performance->fetch_assoc()): ?>
+                    <tr>
+                        <td><?php echo htmlspecialchars($row['employee_name']); ?></td>
+                        <td><?php echo number_format($row['order_count']); ?></td>
+                        <td>¥<?php echo number_format($row['total_sales'], 2); ?></td>
+                    </tr>
+                    <?php endwhile; ?>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    
+    <script>
+        // 切换自定义日期区域显示
+        function toggleCustomDates() {
+            var dateRange = document.getElementById('date_range').value;
+            var customDates = document.getElementById('custom_dates');
+            
+            if (dateRange === 'custom') {
+                customDates.style.display = 'flex';
+            } else {
+                customDates.style.display = 'none';
+            }
+        }
+        
+        // 销售趋势图
+        var salesTrendCtx = document.getElementById('salesTrendChart').getContext('2d');
+        var salesTrendChart = new Chart(salesTrendCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($monthly_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($monthly_orders); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.2)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-orders'
+                    },
+                    {
+                        label: '销售收入',
+                        data: <?php echo json_encode($monthly_revenue); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.2)',
+                        borderColor: 'rgba(255, 99, 132, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-revenue'
+                    }
+                ]
+            },
+            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
+                        }
+                    }
+                }
+            }
+        });
+        
+        // 客户国家分布图
+        var countryDistributionCtx = document.getElementById('countryDistributionChart').getContext('2d');
+        var countryDistributionChart = new Chart(countryDistributionCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($country_labels); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($country_data); ?>,
+                    backgroundColor: [
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)',
+                        'rgba(255, 159, 64, 0.7)',
+                        'rgba(199, 199, 199, 0.7)',
+                        'rgba(83, 102, 255, 0.7)',
+                        'rgba(40, 159, 64, 0.7)',
+                        'rgba(210, 199, 199, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+        
+        // 客户类型分布图
+        var customerTypeCtx = document.getElementById('customerTypeChart').getContext('2d');
+        var customerTypeChart = new Chart(customerTypeCtx, {
+            type: 'doughnut',
+            data: {
+                labels: <?php echo json_encode($type_labels); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($type_data); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+        
+        // 成交阶段分布图
+        var dealStageCtx = document.getElementById('dealStageChart').getContext('2d');
+        var dealStageChart = new Chart(dealStageCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($stage_labels); ?>,
+                datasets: [{
+                    label: '客户数量',
+                    data: <?php echo json_encode($stage_data); ?>,
+                    backgroundColor: [
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+        
+        // 客户增长趋势图
+        var customerGrowthCtx = document.getElementById('customerGrowthChart').getContext('2d');
+        var customerGrowthChart = new Chart(customerGrowthCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($growth_labels); ?>,
+                datasets: [{
+                    label: '新增客户',
+                    data: <?php echo json_encode($growth_data); ?>,
+                    backgroundColor: 'rgba(75, 192, 192, 0.2)',
+                    borderColor: 'rgba(75, 192, 192, 1)',
+                    borderWidth: 2,
+                    tension: 0.1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+        
+        // 地区订单分析图
+        var regionOrdersCtx = document.getElementById('regionOrdersChart').getContext('2d');
+        var regionOrdersChart = new Chart(regionOrdersCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($region_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($region_orders); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.6)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-orders'
+                    },
+                    {
+                        label: '产品订购数量',
+                        data: <?php echo json_encode($region_quantities); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.6)',
+                        borderColor: 'rgba(255, 99, 132, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-quantity'
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '地区'
+                        }
+                    },
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        },
+                        beginAtZero: true
+                    },
+                    'y-quantity': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '产品订购数量'
+                        },
+                        beginAtZero: true,
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+        
+        // 详细时间段订单趋势图
+        var detailedOrdersCtx = document.getElementById('detailedOrdersChart').getContext('2d');
+        var detailedOrdersChart = new Chart(detailedOrdersCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($time_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($time_orders); ?>,
+                        backgroundColor: 'rgba(75, 192, 192, 0.2)',
+                        borderColor: 'rgba(75, 192, 192, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-orders',
+                        tension: 0.1
+                    },
+                    {
+                        label: '产品订购数量',
+                        data: <?php echo json_encode($time_quantities); ?>,
+                        backgroundColor: 'rgba(255, 159, 64, 0.2)',
+                        borderColor: 'rgba(255, 159, 64, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-quantity',
+                        tension: 0.1
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '时间'
+                        }
+                    },
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        },
+                        beginAtZero: true
+                    },
+                    'y-quantity': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '产品订购数量'
+                        },
+                        beginAtZero: true,
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+</body>
+</html> 

+ 1315 - 0
statistics_customers.php

@@ -0,0 +1,1315 @@
+<?php
+/**
+ * 客户统计分析模块
+ * 
+ * 包含与客户相关的数据分析功能
+ */
+
+require_once 'statistics_utils.php';
+
+/**
+ * 获取客户类型分布
+ * 
+ * @param mysqli $conn 数据库连接
+ * @return mysqli_result 客户类型分布数据结果集
+ */
+function getCustomerTypeDistribution($conn) {
+    $sql = "SELECT 
+                ct.businessType, 
+                COUNT(c.id) as customer_count
+            FROM customer c
+            JOIN clienttype ct ON c.cs_type = ct.id
+            GROUP BY c.cs_type";
+    
+    return $conn->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) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户类型分布</h2>
+        </div>
+        <canvas id="customerTypeChart"></canvas>
+    </div>
+    
+    <script>
+        // 客户类型分布图
+        var customerTypeCtx = document.getElementById('customerTypeChart').getContext('2d');
+        var customerTypeChart = new Chart(customerTypeCtx, {
+            type: 'doughnut',
+            data: {
+                labels: <?php echo json_encode($type_labels); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($type_data); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染成交阶段分布图
+ * 
+ * @param array $stage_labels 阶段标签
+ * @param array $stage_data 阶段数据
+ * @return void
+ */
+function renderDealStageChart($stage_labels, $stage_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">成交阶段分布</h2>
+        </div>
+        <canvas id="dealStageChart"></canvas>
+    </div>
+    
+    <script>
+        // 成交阶段分布图
+        var dealStageCtx = document.getElementById('dealStageChart').getContext('2d');
+        var dealStageChart = new Chart(dealStageCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($stage_labels); ?>,
+                datasets: [{
+                    label: '客户数量',
+                    data: <?php echo json_encode($stage_data); ?>,
+                    backgroundColor: [
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染客户增长趋势图
+ * 
+ * @param array $growth_labels 增长标签
+ * @param array $growth_data 增长数据
+ * @return void
+ */
+function renderCustomerGrowthChart($growth_labels, $growth_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户增长趋势</h2>
+        </div>
+        <canvas id="customerGrowthChart"></canvas>
+    </div>
+    
+    <script>
+        // 客户增长趋势图
+        var customerGrowthCtx = document.getElementById('customerGrowthChart').getContext('2d');
+        var customerGrowthChart = new Chart(customerGrowthCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($growth_labels); ?>,
+                datasets: [{
+                    label: '新增客户',
+                    data: <?php echo json_encode($growth_data); ?>,
+                    backgroundColor: 'rgba(75, 192, 192, 0.2)',
+                    borderColor: 'rgba(75, 192, 192, 1)',
+                    borderWidth: 2,
+                    tension: 0.1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染新老客户分析图
+ * 
+ * @param array $new_vs_returning 新老客户数据
+ * @return void
+ */
+function renderNewVsReturningCustomersChart($new_vs_returning) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">新老客户分析</h2>
+        </div>
+        <style>
+            .pie-charts-container {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                margin-bottom: 20px;
+            }
+            .pie-chart-wrapper {
+                flex: 0 0 48%;
+                max-width: 48%;
+            }
+            .customer-stats-summary {
+                margin-top: 20px;
+                padding: 15px;
+                background-color: #f9f9f9;
+                border-radius: 5px;
+            }
+            .stats-row {
+                display: flex;
+                margin-bottom: 15px;
+            }
+            .stat-item {
+                flex: 1;
+                padding: 0 10px;
+            }
+            .stat-label {
+                display: block;
+                font-weight: bold;
+                margin-bottom: 5px;
+                color: #555;
+            }
+            .stat-value {
+                font-size: 16px;
+                color: #333;
+            }
+        </style>
+        <div class="pie-charts-container">
+            <div class="pie-chart-wrapper">
+                <h3 style="text-align: center; margin-bottom: 15px;">客户数量分布</h3>
+                <canvas id="newVsReturningCustomersChart"></canvas>
+            </div>
+            <div class="pie-chart-wrapper">
+                <h3 style="text-align: center; margin-bottom: 15px;">销售额分布</h3>
+                <canvas id="newVsReturningAmountChart"></canvas>
+            </div>
+        </div>
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <div class="stat-item">
+                    <span class="stat-label">总客户数:</span>
+                    <span class="stat-value"><?php echo number_format($new_vs_returning['total_customers']); ?></span>
+                </div>
+                <div class="stat-item">
+                    <span class="stat-label">新客户:</span>
+                    <span class="stat-value"><?php echo number_format($new_vs_returning['new_customers']); ?> 
+                    (<?php echo ($new_vs_returning['total_customers'] > 0) ? number_format(($new_vs_returning['new_customers'] / $new_vs_returning['total_customers']) * 100, 1) : '0'; ?>%)</span>
+                </div>
+                <div class="stat-item">
+                    <span class="stat-label">老客户:</span>
+                    <span class="stat-value"><?php echo number_format($new_vs_returning['returning_customers']); ?> 
+                    (<?php echo ($new_vs_returning['total_customers'] > 0) ? number_format(($new_vs_returning['returning_customers'] / $new_vs_returning['total_customers']) * 100, 1) : '0'; ?>%)</span>
+                </div>
+            </div>
+            <div class="stats-row">
+                <div class="stat-item">
+                    <span class="stat-label">总销售额:</span>
+                    <span class="stat-value">¥<?php echo number_format($new_vs_returning['total_amount'], 2); ?></span>
+                </div>
+                <div class="stat-item">
+                    <span class="stat-label">新客户销售额:</span>
+                    <span class="stat-value">¥<?php echo number_format($new_vs_returning['new_customer_amount'], 2); ?> 
+                    (<?php echo ($new_vs_returning['total_amount'] > 0) ? number_format(($new_vs_returning['new_customer_amount'] / $new_vs_returning['total_amount']) * 100, 1) : '0'; ?>%)</span>
+                </div>
+                <div class="stat-item">
+                    <span class="stat-label">老客户销售额:</span>
+                    <span class="stat-value">¥<?php echo number_format($new_vs_returning['returning_customer_amount'], 2); ?> 
+                    (<?php echo ($new_vs_returning['total_amount'] > 0) ? number_format(($new_vs_returning['returning_customer_amount'] / $new_vs_returning['total_amount']) * 100, 1) : '0'; ?>%)</span>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 新老客户数量图
+        var newVsReturningCtx = document.getElementById('newVsReturningCustomersChart').getContext('2d');
+        var newVsReturningChart = new Chart(newVsReturningCtx, {
+            type: 'pie',
+            data: {
+                labels: ['新客户', '老客户'],
+                datasets: [{
+                    data: [
+                        <?php echo $new_vs_returning['new_customers']; ?>, 
+                        <?php echo $new_vs_returning['returning_customers']; ?>
+                    ],
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                maintainAspectRatio: true,
+                plugins: {
+                    legend: {
+                        position: 'bottom',
+                    }
+                }
+            }
+        });
+        
+        // 新老客户销售额图
+        var amountCtx = document.getElementById('newVsReturningAmountChart').getContext('2d');
+        var amountChart = new Chart(amountCtx, {
+            type: 'pie',
+            data: {
+                labels: ['新客户销售额', '老客户销售额'],
+                datasets: [{
+                    data: [
+                        <?php echo $new_vs_returning['new_customer_amount']; ?>, 
+                        <?php echo $new_vs_returning['returning_customer_amount']; ?>
+                    ],
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 99, 132, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                maintainAspectRatio: true,
+                plugins: {
+                    legend: {
+                        position: 'bottom',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 获取客户总数
+ * 
+ * @param mysqli $conn 数据库连接
+ * @return int 客户总数
+ */
+function getTotalCustomers($conn) {
+    $sql = "SELECT COUNT(id) as total FROM customer";
+    $result = $conn->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) {
+    ?>
+    <div class="stats-card-container">
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>客户总数</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($kpi_data['total_customers']); ?></div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>新增客户</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($kpi_data['new_customers']); ?></div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>平均客户价值</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value">¥<?php echo number_format($kpi_data['avg_customer_value'], 2); ?></div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>客户留存率</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($kpi_data['retention_rate'], 1); ?>%</div>
+                <div class="stats-card-subtitle"><?php echo number_format($kpi_data['retained_count']); ?> / <?php echo number_format($kpi_data['total_previous']); ?></div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>下单转换率</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($kpi_data['conversion_rate'], 1); ?>%</div>
+                <div class="stats-card-subtitle"><?php echo number_format($kpi_data['customers_with_orders']); ?> / <?php echo number_format($kpi_data['total_customers']); ?></div>
+            </div>
+        </div>
+    </div>
+    <?php
+}
+
+/**
+ * 获取客户价值分布数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 客户价值分布数据
+ */
+function getCustomerValueDistribution($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                value_segment,
+                COUNT(customer_id) as customer_count,
+                SUM(total_amount) as total_amount
+            FROM (
+                SELECT 
+                    o.customer_id,
+                    SUM(o.total_amount) as total_amount,
+                    CASE 
+                        WHEN SUM(o.total_amount) > 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) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户价值分布</h2>
+        </div>
+        
+        <div class="chart-row" style="display: flex; width: 100%; margin: 0 -10px;">
+            <div class="chart-column" style="flex: 0 0 50%; max-width: 50%; padding: 0 10px; box-sizing: border-box;">
+                <h3 style="text-align: center; margin-bottom: 15px;">客户价值分布(柱状图)</h3>
+                <canvas id="customerValueBarChart"></canvas>
+            </div>
+            <div class="chart-column" style="flex: 0 0 50%; max-width: 50%; padding: 0 10px; box-sizing: border-box;">
+                <h3 style="text-align: center; margin-bottom: 15px;">客户价值分布(饼图)</h3>
+                <canvas id="customerValuePieChart"></canvas>
+            </div>
+        </div>
+        
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <?php foreach ($value_data['segments'] as $index => $segment): ?>
+                <div class="stat-item">
+                    <span class="stat-label"><?php echo $segment; ?>:</span>
+                    <span class="stat-value"><?php echo number_format($value_data['counts'][$index]); ?> 
+                    (<?php echo ($value_data['total_customers'] > 0) ? 
+                        number_format(($value_data['counts'][$index] / $value_data['total_customers']) * 100, 1) : '0'; ?>%)</span>
+                    <span class="stat-sub-value">¥<?php echo number_format($value_data['amounts'][$index], 2); ?></span>
+                </div>
+                <?php endforeach; ?>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户价值分布柱状图
+        var valueBarCtx = document.getElementById('customerValueBarChart').getContext('2d');
+        var valueBarChart = new Chart(valueBarCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($value_data['segments']); ?>,
+                datasets: [{
+                    label: '客户数量',
+                    data: <?php echo json_encode($value_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+        
+        // 客户价值分布饼图
+        var valuePieCtx = document.getElementById('customerValuePieChart').getContext('2d');
+        var valuePieChart = new Chart(valuePieCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($value_data['segments']); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($value_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染客户活跃度分析图表
+ * 
+ * @param array $activity_data 客户活跃度数据
+ * @return void
+ */
+function renderCustomerActivityChart($activity_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户活跃度分析</h2>
+        </div>
+        <canvas id="customerActivityChart"></canvas>
+        
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <?php 
+                $total_customers = array_sum($activity_data['counts']);
+                foreach ($activity_data['levels'] as $index => $level): 
+                ?>
+                <div class="stat-item">
+                    <span class="stat-label"><?php echo $level; ?>:</span>
+                    <span class="stat-value"><?php echo number_format($activity_data['counts'][$index]); ?> 
+                    (<?php echo ($total_customers > 0) ? 
+                        number_format(($activity_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)</span>
+                </div>
+                <?php endforeach; ?>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户活跃度分析图
+        var activityCtx = document.getElementById('customerActivityChart').getContext('2d');
+        var activityChart = new Chart(activityCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($activity_data['levels']); ?>,
+                datasets: [{
+                    label: '客户数量',
+                    data: <?php echo json_encode($activity_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染客户流失风险分析图表
+ * 
+ * @param array $risk_data 客户流失风险数据
+ * @return void
+ */
+function renderCustomerChurnRiskChart($risk_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户流失风险分析</h2>
+        </div>
+        <canvas id="customerRiskChart"></canvas>
+        
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <?php 
+                $total_customers = array_sum($risk_data['counts']);
+                foreach ($risk_data['levels'] as $index => $level): 
+                ?>
+                <div class="stat-item">
+                    <span class="stat-label"><?php echo $level; ?>:</span>
+                    <span class="stat-value"><?php echo number_format($risk_data['counts'][$index]); ?> 
+                    (<?php echo ($total_customers > 0) ? 
+                        number_format(($risk_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)</span>
+                </div>
+                <?php endforeach; ?>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户流失风险分析图
+        var riskCtx = document.getElementById('customerRiskChart').getContext('2d');
+        var riskChart = new Chart(riskCtx, {
+            type: 'doughnut',
+            data: {
+                labels: <?php echo json_encode($risk_data['levels']); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($risk_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染客户来源分析图表
+ * 
+ * @param array $source_data 客户来源数据
+ * @return void
+ */
+function renderCustomerSourceChart($source_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户来源分析</h2>
+        </div>
+        <canvas id="customerSourceChart"></canvas>
+        
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <?php 
+                $total_customers = array_sum($source_data['counts']);
+                foreach ($source_data['sources'] as $index => $source): 
+                ?>
+                <div class="stat-item">
+                    <span class="stat-label"><?php echo $source; ?>:</span>
+                    <span class="stat-value"><?php echo number_format($source_data['counts'][$index]); ?> 
+                    (<?php echo ($total_customers > 0) ? 
+                        number_format(($source_data['counts'][$index] / $total_customers) * 100, 1) : '0'; ?>%)</span>
+                </div>
+                <?php endforeach; ?>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户来源分析图
+        var sourceCtx = document.getElementById('customerSourceChart').getContext('2d');
+        var sourceChart = new Chart(sourceCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($source_data['sources']); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($source_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)',
+                        'rgba(255, 159, 64, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 获取客户转化漏斗数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 客户转化漏斗数据
+ */
+function getCustomerConversionFunnel($conn, $start_date, $end_date) {
+    // 获取总客户数(潜在客户)
+    $total_sql = "SELECT COUNT(id) as total FROM customer";
+    $total_result = $conn->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) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户转化漏斗</h2>
+        </div>
+        <canvas id="customerFunnelChart" style="max-height: 400px;"></canvas>
+        
+        <div class="customer-stats-summary">
+            <div class="stats-row">
+                <?php 
+                foreach ($funnel_data['stages'] as $index => $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;
+                ?>
+                <div class="stat-item">
+                    <span class="stat-label"><?php echo $stage; ?>:</span>
+                    <span class="stat-value"><?php echo number_format($current_count); ?></span>
+                    <?php if ($index > 0): ?>
+                        <span class="stat-conversion">
+                            转化率: <?php echo number_format($conversion_rate, 1); ?>%
+                        </span>
+                    <?php endif; ?>
+                </div>
+                <?php endforeach; ?>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户转化漏斗图
+        var funnelCtx = document.getElementById('customerFunnelChart').getContext('2d');
+        var funnelChart = new Chart(funnelCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($funnel_data['stages']); ?>,
+                datasets: [{
+                    label: '客户数量',
+                    data: <?php echo json_encode($funnel_data['counts']); ?>,
+                    backgroundColor: [
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(153, 102, 255, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                indexAxis: 'y',
+                responsive: true,
+                scales: {
+                    x: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '客户数量'
+                        }
+                    }
+                },
+                plugins: {
+                    tooltip: {
+                        callbacks: {
+                            afterLabel: function(context) {
+                                var index = context.dataIndex;
+                                if (index > 0) {
+                                    var currentValue = context.parsed.x;
+                                    var previousValue = context.dataset.data[index-1];
+                                    var conversionRate = previousValue > 0 ? (currentValue / previousValue * 100).toFixed(1) : 0;
+                                    return '转化率: ' + conversionRate + '%';
+                                }
+                                return '';
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+} 

+ 3 - 0
statistics_footer.php

@@ -0,0 +1,3 @@
+</div>
+</body>
+</html>

+ 297 - 0
statistics_header.php

@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>统计分析</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <script src="system/js/jquery-1.7.2.min.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+            font-family: Arial, sans-serif;
+        }
+
+        .container {
+            width: 100%;
+            max-width: 1200px;
+            margin: 0 auto;
+        }
+
+        .page-header {
+            margin-bottom: 20px;
+            border-bottom: 1px solid #eee;
+            padding-bottom: 10px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+        }
+
+        .page-title {
+            font-size: 24px;
+            font-weight: bold;
+            color: #333;
+            margin: 0;
+        }
+
+        .export-btn {
+            padding: 8px 15px;
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+            text-decoration: none;
+            display: inline-block;
+        }
+
+        .export-btn:hover {
+            background: #45a049;
+        }
+
+        .filter-form {
+            background: #f9f9f9;
+            padding: 15px;
+            border-radius: 5px;
+            margin-bottom: 20px;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 15px;
+            align-items: center;
+        }
+        
+        .filter-form-inline {
+            display: flex;
+            flex-wrap: nowrap;
+            align-items: flex-end;
+            gap: 15px;
+            width: 100%;
+        }
+        
+        .filter-form-inline .form-group {
+            margin-right: 0;
+            flex: 0 0 auto;
+        }
+
+        .form-group {
+            margin-right: 15px;
+        }
+
+        .form-group label {
+            display: block;
+            margin-bottom: 5px;
+            font-weight: bold;
+        }
+
+        .form-control {
+            padding: 8px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            min-width: 150px;
+        }
+
+        .btn {
+            padding: 8px 15px;
+            background: #337ab7;
+            color: white;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+        }
+
+        .btn:hover {
+            background: #286090;
+        }
+
+        .stats-grid {
+            display: grid;
+            grid-template-columns: repeat(auto-fill, minmax(45%, 1fr));
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+
+        .stat-card {
+            background: white;
+            border-radius: 5px;
+            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+            padding: 20px;
+        }
+
+        .stat-card h3 {
+            margin-top: 0;
+            color: #555;
+            font-size: 16px;
+            border-bottom: 1px solid #eee;
+            padding-bottom: 10px;
+        }
+
+        .stat-value {
+            font-size: 24px;
+            font-weight: bold;
+            color: #333;
+            margin: 15px 0;
+        }
+
+        .chart-container {
+            margin-bottom: 30px;
+            background: white;
+            border-radius: 5px;
+            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+            padding: 20px;
+        }
+
+        .chart-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 15px;
+        }
+
+        .chart-title {
+            font-size: 18px;
+            font-weight: bold;
+            color: #333;
+            margin: 0;
+        }
+        
+        .chart-row {
+            display: flex;
+            flex-wrap: wrap;
+        }
+        
+        .chart-column {
+            flex: 0 0 50%;
+            max-width: 50%;
+            padding: 0 10px;
+        }
+
+        .data-table {
+            width: 100%;
+            border-collapse: collapse;
+            margin-top: 20px;
+        }
+
+        .data-table th, .data-table td {
+            padding: 10px;
+            text-align: left;
+            border-bottom: 1px solid #eee;
+        }
+
+        .data-table th {
+            background: #f5f5f5;
+            font-weight: bold;
+        }
+
+        .data-table tr:hover {
+            background: #f9f9f9;
+        }
+
+        .custom-date-inputs {
+            display: none;
+        }
+
+        #date_range[value="custom"]:checked ~ .custom-date-inputs {
+            display: block;
+        }
+
+        .download-btn {
+            padding: 5px 10px;
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 3px;
+            font-size: 14px;
+            cursor: pointer;
+        }
+
+        .download-btn:hover {
+            background: #45a049;
+        }
+        
+        /* 关键指标样式 */
+        .key-metrics-section {
+            margin-bottom: 30px;
+        }
+        
+        .section-title {
+            margin-bottom: 15px;
+        }
+        
+        .section-title h2 {
+            font-size: 20px;
+            font-weight: bold;
+            color: #333;
+            margin: 0;
+        }
+        
+        .stats-card-container {
+            display: flex;
+            flex-wrap: wrap;
+            gap: 20px;
+            justify-content: space-between;
+        }
+        
+        .stats-card {
+            background: white;
+            border-radius: 5px;
+            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
+            padding: 15px;
+            min-width: 180px;
+            flex: 1;
+            transition: all 0.3s ease;
+        }
+        
+        .stats-card:hover {
+            transform: translateY(-3px);
+            box-shadow: 0 4px 8px rgba(0,0,0,0.15);
+        }
+        
+        .stats-card-header {
+            margin-bottom: 10px;
+        }
+        
+        .stats-card-header h3 {
+            font-size: 16px;
+            font-weight: bold;
+            color: #555;
+            margin: 0;
+        }
+        
+        .stats-card-body {
+            text-align: center;
+        }
+        
+        .stats-card-value {
+            font-size: 28px;
+            font-weight: bold;
+            color: #2196F3;
+        }
+        
+        .stats-card-subtitle {
+            font-size: 14px;
+            color: #777;
+            margin-top: 5px;
+        }
+        
+        /* 添加客户价值分布的子值样式 */
+        .stat-sub-value {
+            display: block;
+            font-size: 14px;
+            color: #4CAF50;
+            margin-top: 3px;
+        }
+
+		/* 转化率样式 */
+        .stat-conversion {
+            display: block;
+            font-size: 13px;
+            color: #FF5722;
+            margin-top: 3px;
+            font-style: italic;
+        }
+    </style>
+</head>
+<body>
+<div class="container">

+ 1133 - 0
statistics_order_warnings.php

@@ -0,0 +1,1133 @@
+<?php
+/**
+ * 订单预警系统 - 监控订单异常情况
+ */
+require_once 'conn.php';
+require_once 'statistics_utils.php';
+
+// 检查登录状态
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+// 获取日期范围参数
+$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;
+
+// 获取所有业务员列表
+$sql_employees = "SELECT id, em_user FROM employee ORDER BY em_user";
+$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_max_threshold = 90; // 复购周期超过90天触发预警
+$repurchase_cycle_min_threshold = 0.5; // 复购周期小于正常值的50%触发预警(异常频繁购买)
+$inactive_threshold = 60; // 60天未购买视为不活跃客户
+$normal_repurchase_days = 30; // 正常复购周期参考值(天)
+
+// 页面头部
+include('statistics_header.php');
+?>
+
+
+    <div class="page-header">
+        <h1 class="page-title">订单预警系统</h1>
+        <p class="page-description">监控订单异常情况,提前预警潜在问题</p>
+    </div>
+    
+    <!-- 日期筛选 -->
+    <div class="filter-form">
+        <form method="get" class="filter-form-inline">
+            <div class="form-group">
+                <label for="date_range">分析周期</label>
+                <select class="form-control" id="date_range" name="date_range" onchange="toggleCustomDates()">
+                    <option value="current_month" <?php echo $date_range == 'current_month' ? 'selected' : ''; ?>>本月</option>
+                    <option value="last_month" <?php echo $date_range == 'last_month' ? 'selected' : ''; ?>>上月</option>
+                    <option value="current_year" <?php echo $date_range == 'current_year' ? 'selected' : ''; ?>>今年</option>
+                    <option value="last_30_days" <?php echo $date_range == 'last_30_days' ? 'selected' : ''; ?>>最近30天</option>
+                    <option value="last_90_days" <?php echo $date_range == 'last_90_days' ? 'selected' : ''; ?>>最近90天</option>
+                    <option value="custom" <?php echo $date_range == 'custom' ? 'selected' : ''; ?>>自定义日期范围</option>
+                </select>
+            </div>
+            <div class="form-group custom-date-inputs" id="custom_start_date" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="start_date">开始日期</label>
+                <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $date_params['custom_start']; ?>">
+            </div>
+            <div class="form-group custom-date-inputs" id="custom_end_date" style="display: <?php echo $date_range == 'custom' ? 'inline-block' : 'none'; ?>">
+                <label for="end_date">结束日期</label>
+                <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $date_params['custom_end']; ?>">
+            </div>
+            <div class="form-group">
+                <label for="employee_id">业务员</label>
+                <select class="form-control" id="employee_id" name="employee_id">
+                    <option value="0">全部业务员</option>
+                    <?php while ($emp = $employees_result->fetch_assoc()): ?>
+                    <option value="<?php echo $emp['id']; ?>" <?php echo $selected_employee == $emp['id'] ? 'selected' : ''; ?>><?php echo htmlspecialchars($emp['em_user']); ?></option>
+                    <?php endwhile; ?>
+                </select>
+            </div>
+            <div class="form-group">
+                <button type="submit" class="form-btn form-btn-primary">应用筛选</button>
+            </div>
+        </form>
+    </div>
+    
+    <!-- 预警概览 -->
+    <div class="warnings-overview">
+        <div class="row">
+            <?php
+            // 获取总预警数
+            $sql_total_warnings = "SELECT 
+                (SELECT COUNT(*) FROM customer WHERE cs_deal = 3) as total_customers,
+                (SELECT COUNT(DISTINCT customer_id) FROM orders WHERE order_date BETWEEN ? AND ?) as active_customers";
+            
+            $stmt = $conn->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();
+            
+            // 获取订单金额下降的客户数
+            $decreasing_amount_count = getDecreasingOrderAmountCustomers($conn, $current_start_date, $current_end_date, $previous_start_date, $previous_end_date, $order_amount_decrease_threshold, true, $selected_employee);
+            
+            // 获取复购周期异常的客户数
+            $abnormal_cycle_count = getAbnormalRepurchaseCycleCustomers($conn, $current_start_date, $current_end_date, $repurchase_cycle_max_threshold, $repurchase_cycle_min_threshold, $normal_repurchase_days, true, $selected_employee);
+            
+            // 获取长期不活跃客户数
+            $inactive_customers_count = getInactiveCustomers($conn, $current_end_date, $inactive_threshold, true, 1, 10, $selected_employee);
+            ?>
+            
+            <div class="col-md-3">
+                <div class="stat-card warning">
+                    <h3>订单金额下降客户</h3>
+                    <div class="stat-value"><?php echo $decreasing_amount_count; ?></div>
+                    <div class="stat-desc">金额下降超过<?php echo abs($order_amount_decrease_threshold); ?>%</div>
+                </div>
+            </div>
+            
+            <div class="col-md-3">
+                <div class="stat-card warning">
+                    <h3>复购周期异常客户</h3>
+                    <div class="stat-value"><?php echo $abnormal_cycle_count; ?></div>
+                    <div class="stat-desc">周期异常或不规律</div>
+                </div>
+            </div>
+            
+            <div class="col-md-3">
+                <div class="stat-card danger">
+                    <h3>长期不活跃客户</h3>
+                    <div class="stat-value"><?php echo $inactive_customers_count; ?></div>
+                    <div class="stat-desc"><?php echo $inactive_threshold; ?>天以上未下单</div>
+                </div>
+            </div>
+            
+            <div class="col-md-3">
+                <div class="stat-card info">
+                    <h3>客户活跃率</h3>
+                    <div class="stat-value">
+                        <?php 
+                        $active_rate = ($warning_count['total_customers'] > 0) ? 
+                            round(($warning_count['active_customers'] / $warning_count['total_customers']) * 100, 1) : 0;
+                        echo $active_rate . '%'; 
+                        ?>
+                    </div>
+                    <div class="stat-desc">选定周期内下单客户占比</div>
+                </div>
+            </div>
+        </div>
+    </div>
+    
+    <!-- 订单金额下降客户列表 -->
+    <div class="warning-section">
+        <div class="section-header">
+            <h2>订单金额下降客户</h2>
+            <p>与上一周期相比,订单金额显著下降的客户</p>
+        </div>
+        
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>客户名称</th>
+                    <th>本期订单金额</th>
+                    <th>上期订单金额</th>
+                    <th>变化百分比</th>
+                    <th>最近订单日期</th>
+                    <th>业务员</th>
+                    <th>操作</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php
+                $decreasing_customers = getDecreasingOrderAmountCustomers(
+                    $conn, 
+                    $current_start_date, 
+                    $current_end_date, 
+                    $previous_start_date, 
+                    $previous_end_date, 
+                    $order_amount_decrease_threshold,
+                    false,
+                    $selected_employee
+                );
+                
+                while ($customer = $decreasing_customers->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 "<tr>";
+                    echo "<td>" . htmlspecialchars($customer['cs_company']) . "</td>";
+                    echo "<td>¥" . number_format($customer['current_amount'], 2) . "</td>";
+                    echo "<td>¥" . number_format($customer['previous_amount'], 2) . "</td>";
+                    echo "<td class='{$change_class}'>" . $change_percent . "%</td>";
+                    echo "<td>" . $customer['last_order_date'] . "</td>";
+                    echo "<td>" . htmlspecialchars($customer['em_user']) . "</td>";
+                    echo "<td><a href='customer_detail.php?id=" . $customer['id'] . "&from_warning=1' class='action-btn action-btn-view'>查看</a></td>";
+                    echo "</tr>";
+                }
+                
+                if ($decreasing_customers->num_rows == 0) {
+                    echo "<tr><td colspan='7' class='text-center'>没有发现订单金额下降的客户</td></tr>";
+                }
+                ?>
+            </tbody>
+        </table>
+    </div>
+    
+    <!-- 复购周期异常客户列表 -->
+    <div class="warning-section">
+        <div class="section-header">
+            <h2>复购周期异常客户</h2>
+            <p>复购周期异常延长或缩短的客户</p>
+        </div>
+        
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>客户名称</th>
+                    <th>平均复购周期(天)</th>
+                    <th>最近复购周期(天)</th>
+                    <th>偏离正常值</th>
+                    <th>最近订单日期</th>
+                    <th>订单总数</th>
+                    <th>业务员</th>
+                    <th>操作</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php
+                $abnormal_customers = getAbnormalRepurchaseCycleCustomers(
+                    $conn, 
+                    $current_start_date, 
+                    $current_end_date, 
+                    $repurchase_cycle_max_threshold, 
+                    $repurchase_cycle_min_threshold,
+                    $normal_repurchase_days,
+                    false,
+                    $selected_employee
+                );
+                
+                while ($customer = $abnormal_customers->fetch_assoc()) {
+                    $deviation = round((($customer['recent_cycle'] - $normal_repurchase_days) / $normal_repurchase_days) * 100, 1);
+                    $deviation_text = $deviation > 0 ? "+{$deviation}%" : "{$deviation}%";
+                    $deviation_class = $deviation > 50 ? 'text-danger' : ($deviation < -30 ? 'text-warning' : 'text-info');
+                    
+                    echo "<tr>";
+                    echo "<td>" . htmlspecialchars($customer['cs_company']) . "</td>";
+                    echo "<td>" . round($customer['avg_cycle'], 1) . "</td>";
+                    echo "<td>" . round($customer['recent_cycle'], 1) . "</td>";
+                    echo "<td class='{$deviation_class}'>" . $deviation_text . "</td>";
+                    echo "<td>" . $customer['last_order_date'] . "</td>";
+                    echo "<td>" . $customer['order_count'] . "</td>";
+                    echo "<td>" . htmlspecialchars($customer['em_user']) . "</td>";
+                    echo "<td><a href='customer_detail.php?id=" . $customer['id'] . "&from_warning=1' class='action-btn action-btn-view'>查看</a></td>";
+                    echo "</tr>";
+                }
+                
+                if ($abnormal_customers->num_rows == 0) {
+                    echo "<tr><td colspan='8' class='text-center'>没有发现复购周期异常的客户</td></tr>";
+                }
+                ?>
+            </tbody>
+        </table>
+    </div>
+    
+    <!-- 长期不活跃客户列表 -->
+    <div class="warning-section" id="inactive-customers">
+        <div class="section-header">
+            <h2>长期不活跃客户</h2>
+            <p>超过<?php echo $inactive_threshold; ?>天未下单的客户</p>
+        </div>
+        
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>客户编码</th>
+                    <th>客户名称</th>
+                    <th>最后订单日期</th>
+                    <th>不活跃天数</th>
+                    <th>历史订单数</th>
+                    <th>历史订单总额</th>
+                    <th>业务员</th>
+                    <th>操作</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php
+                // 获取分页参数
+                $page = isset($_GET['inactive_page']) ? intval($_GET['inactive_page']) : 1;
+                $page_size = 10; // 每页显示10条记录
+                
+                // 获取总记录数
+                $total_inactive = getInactiveCustomers($conn, $current_end_date, $inactive_threshold, true, 1, 10, $selected_employee);
+                
+                // 计算总页数
+                $total_pages = ceil($total_inactive / $page_size);
+                
+                // 确保页码合法
+                if ($page < 1) $page = 1;
+                if ($page > $total_pages && $total_pages > 0) $page = $total_pages;
+                
+                // 获取当页数据
+                $inactive_customers = getInactiveCustomers($conn, $current_end_date, $inactive_threshold, false, $page, $page_size, $selected_employee);
+                
+                while ($customer = $inactive_customers->fetch_assoc()) {
+                    $inactive_days = $customer['inactive_days'];
+                    $inactive_class = $inactive_days > 90 ? 'text-danger' : 'text-warning';
+                    
+                    echo "<tr>";
+                    echo "<td title='{$customer['cs_code']}'>" . htmlspecialchars($customer['cs_code']) . "</td>";
+                    echo "<td>" . htmlspecialchars($customer['cs_company'] ?: '未填写') . "</td>";
+                    echo "<td>" . ($customer['last_order_date'] ? $customer['last_order_date'] : '从未下单') . "</td>";
+                    echo "<td class='{$inactive_class}'>" . $inactive_days . "</td>";
+                    echo "<td>" . $customer['order_count'] . "</td>";
+                    echo "<td>¥" . number_format($customer['total_amount'], 2) . "</td>";
+                    echo "<td>" . htmlspecialchars($customer['em_user']) . "</td>";
+                    echo "<td><a href='customer_detail.php?id=" . $customer['id'] . "&from_warning=1' class='action-btn action-btn-view'>查看</a></td>";
+                    echo "</tr>";
+                }
+                
+                if ($inactive_customers->num_rows == 0) {
+                    echo "<tr><td colspan='8' class='text-center'>没有发现长期不活跃的客户</td></tr>";
+                }
+                ?>
+            </tbody>
+        </table>
+        
+        <!-- 分页控件 -->
+        <?php if ($total_pages > 1): ?>
+        <div class="pagination-container">
+            <ul class="pagination">
+                <?php
+                // 生成分页链接的基础URL
+                $base_url = '?';
+                foreach ($_GET as $key => $value) {
+                    if ($key != 'inactive_page') {
+                        $base_url .= $key . '=' . urlencode($value) . '&';
+                    }
+                }
+                
+                // 上一页链接
+                if ($page > 1) {
+                    echo "<li class='pager-item'><a class='pager-link' href='{$base_url}inactive_page=" . ($page - 1) . "#inactive-customers'>上一页</a></li>";
+                } else {
+                    echo "<li class='pager-item disabled'><a class='pager-link' href='#inactive-customers'>上一页</a></li>";
+                }
+                
+                // 页码链接
+                $start_page = max(1, $page - 2);
+                $end_page = min($total_pages, $page + 2);
+                
+                if ($start_page > 1) {
+                    echo "<li class='pager-item'><a class='pager-link' href='{$base_url}inactive_page=1#inactive-customers'>1</a></li>";
+                    if ($start_page > 2) {
+                        echo "<li class='pager-item disabled'><a class='pager-link' href='#inactive-customers'>...</a></li>";
+                    }
+                }
+                
+                for ($i = $start_page; $i <= $end_page; $i++) {
+                    if ($i == $page) {
+                        echo "<li class='pager-item active'><a class='pager-link' href='#inactive-customers'>{$i}</a></li>";
+                    } else {
+                        echo "<li class='pager-item'><a class='pager-link' href='{$base_url}inactive_page={$i}#inactive-customers'>{$i}</a></li>";
+                    }
+                }
+                
+                if ($end_page < $total_pages) {
+                    if ($end_page < $total_pages - 1) {
+                        echo "<li class='pager-item disabled'><a class='pager-link' href='#inactive-customers'>...</a></li>";
+                    }
+                    echo "<li class='pager-item'><a class='pager-link' href='{$base_url}inactive_page={$total_pages}#inactive-customers'>{$total_pages}</a></li>";
+                }
+                
+                // 下一页链接
+                if ($page < $total_pages) {
+                    echo "<li class='pager-item'><a class='pager-link' href='{$base_url}inactive_page=" . ($page + 1) . "#inactive-customers'>下一页</a></li>";
+                } else {
+                    echo "<li class='pager-item disabled'><a class='pager-link' href='#inactive-customers'>下一页</a></li>";
+                }
+                ?>
+            </ul>
+            <div class="pagination-info">
+                共 <?php echo $total_inactive; ?> 条记录,当前显示第 <?php echo $page; ?> 页,共 <?php echo $total_pages; ?> 页
+            </div>
+        </div>
+        <?php endif; ?>
+    </div>
+    
+    <!-- 总体订单趋势图 -->
+    <div class="chart-section">
+        <div class="section-header">
+            <h2>总体订单趋势</h2>
+            <p>最近12个月的订单数量和金额趋势</p>
+        </div>
+        
+        <div class="chart-container">
+            <canvas id="orderTrendChart"></canvas>
+        </div>
+        
+        <?php
+        // 获取最近12个月的订单趋势数据
+        $sql_trend = "SELECT 
+            DATE_FORMAT(order_date, '%Y-%m') as month,
+            COUNT(*) as order_count,
+            SUM(total_amount) as total_amount
+        FROM orders
+        WHERE order_date >= DATE_SUB(?, INTERVAL 11 MONTH)
+        GROUP BY DATE_FORMAT(order_date, '%Y-%m')
+        ORDER BY month";
+        
+        $stmt = $conn->prepare($sql_trend);
+        $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);
+        ?>
+    </div>
+
+
+<style>
+
+.page-header {
+    margin-bottom: 30px;
+}
+
+.page-title {
+    font-size: 24px;
+    margin-top: 0;
+    margin-bottom: 5px;
+}
+
+.page-description {
+    color: #666;
+    margin-bottom: 0;
+}
+
+.filter-form {
+    background-color: #f8f9fa;
+    border-radius: 4px;
+    padding: 20px;
+    margin-bottom: 30px;
+    box-shadow: 0 1px 2px rgba(0,0,0,0.05);
+}
+
+.filter-form-inline {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+    align-items: end;
+}
+
+.warnings-overview {
+    margin-bottom: 30px;
+}
+
+.warnings-overview .row {
+    display: flex;
+    flex-wrap: wrap;
+    margin: 0 -10px;
+}
+
+.warnings-overview .col-md-3 {
+    padding: 0 10px;
+    width: 25%;
+    flex: 0 0 25%;
+    box-sizing: border-box;
+}
+
+@media (max-width: 992px) {
+    .warnings-overview .col-md-3 {
+        width: 50%;
+        flex: 0 0 50%;
+    }
+}
+
+@media (max-width: 576px) {
+    .warnings-overview .col-md-3 {
+        width: 100%;
+        flex: 0 0 100%;
+    }
+}
+
+.stat-card {
+    border-radius: 8px;
+    padding: 20px;
+    color: #fff;
+    height: 100%;
+    margin-bottom: 20px;
+    box-shadow: 0 3px 6px rgba(0,0,0,0.16);
+    text-align: center;
+    transition: transform 0.3s ease;
+}
+
+.stat-card:hover {
+    transform: translateY(-5px);
+}
+
+.stat-card h3 {
+    margin-top: 0;
+    font-size: 16px;
+    font-weight: 500;
+    margin-bottom: 10px;
+}
+
+.stat-value {
+    font-size: 32px;
+    font-weight: 600;
+    margin-bottom: 10px;
+}
+
+.stat-desc {
+    font-size: 15px;
+    opacity: 0.8;
+}
+
+.stat-card.warning {
+    background-color: #ff9800;
+}
+
+.stat-card.danger {
+    background-color: #f44336;
+}
+
+.stat-card.info {
+    background-color: #2196f3;
+}
+
+.stat-card.success {
+    background-color: #4caf50;
+}
+
+.warning-section {
+    background-color: white;
+    border-radius: 8px;
+    padding: 25px;
+    margin-bottom: 35px;
+    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+}
+
+.section-header {
+    margin-bottom: 20px;
+}
+
+.section-header h2 {
+    font-size: 20px;
+    margin-top: 0;
+    margin-bottom: 5px;
+}
+
+.section-header p {
+    color: #666;
+    font-size: 15px;
+    margin-bottom: 15px;
+}
+
+.chart-section {
+    background-color: white;
+    border-radius: 4px;
+    padding: 20px;
+    margin-bottom: 30px;
+    box-shadow: 0 1px 2px rgba(0,0,0,0.05);
+}
+
+.chart-container {
+    height: 350px;
+}
+
+.text-danger {
+    color: #f44336;
+}
+
+.text-warning {
+    color: #ff9800;
+}
+
+.text-info {
+    color: #2196f3;
+}
+
+/* 调整表格和内容样式 */
+.data-table {
+    margin-bottom: 20px;
+    width: 100%;
+    font-size: 14px; /* 增加表格字体大小 */
+    border-collapse: separate;
+    border-spacing: 0;
+    table-layout: fixed; /* 固定表格布局 */
+}
+
+.data-table th {
+    font-size: 15px; /* 表头字体大小 */
+    padding: 12px 15px;
+    background-color: #f5f5f5;
+    font-weight: 600;
+}
+
+.data-table td {
+    padding: 12px 15px;
+    vertical-align: middle;
+    white-space: nowrap; /* 防止文本换行 */
+    overflow: hidden; /* 溢出隐藏 */
+    text-overflow: ellipsis; /* 文本溢出显示省略号 */
+}
+
+/* 为长期不活跃客户表格设置列宽 */
+#inactive-customers .data-table th:nth-child(1), /* 客户编码 */
+#inactive-customers .data-table td:nth-child(1) {
+    width: 12%;
+}
+
+#inactive-customers .data-table th:nth-child(2), /* 客户名称 */
+#inactive-customers .data-table td:nth-child(2) {
+    width: 20%;
+}
+
+#inactive-customers .data-table th:nth-child(3), /* 最后订单日期 */
+#inactive-customers .data-table td:nth-child(3) {
+    width: 12%;
+}
+
+#inactive-customers .data-table th:nth-child(4), /* 不活跃天数 */
+#inactive-customers .data-table td:nth-child(4) {
+    width: 10%;
+}
+
+#inactive-customers .data-table th:nth-child(5), /* 历史订单数 */
+#inactive-customers .data-table td:nth-child(5) {
+    width: 10%;
+}
+
+#inactive-customers .data-table th:nth-child(6), /* 历史订单总额 */
+#inactive-customers .data-table td:nth-child(6) {
+    width: 12%;
+}
+
+#inactive-customers .data-table th:nth-child(7), /* 业务员 */
+#inactive-customers .data-table td:nth-child(7) {
+    width: 12%;
+}
+
+#inactive-customers .data-table th:nth-child(8), /* 操作 */
+#inactive-customers .data-table td:nth-child(8) {
+    width: 12%;
+}
+
+.data-table td:last-child {
+    min-width: 80px; /* 确保操作列有足够宽度 */
+    text-align: center;
+}
+
+.data-table tr:hover {
+    background-color: #f9f9f9;
+}
+
+.action-btn {
+    padding: 5px 10px;
+    margin: 0 3px;
+    min-width: 60px;
+    display: inline-block;
+    text-align: center;
+    border-radius: 4px;
+    font-size: 13px;
+    transition: all 0.3s ease;
+}
+
+.action-btn-view {
+    background-color: #2196f3;
+    color: white;
+    border: none;
+}
+
+.action-btn-view:hover {
+    background-color: #0d8aee;
+    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
+}
+
+/* 为所有客户列表表格添加共同样式 */
+.warning-section .data-table {
+    border: 1px solid #eee;
+    border-radius: 4px;
+    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
+}
+
+.warning-section .data-table th:first-child,
+.warning-section .data-table td:first-child {
+    padding-left: 20px; /* 左侧留出更多间距 */
+}
+
+/* 表格内数字列的对齐方式 */
+.warning-section .data-table td:nth-child(3),
+.warning-section .data-table td:nth-child(4),
+.warning-section .data-table td:nth-child(5) {
+    text-align: left;
+}
+
+/* 调整整体字体大小 */
+body {
+    font-size: 14px;
+}
+
+/* 分页样式 */
+.pagination-container {
+    margin-top: 25px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.pagination {
+    display: flex;
+    list-style: none;
+    padding: 0;
+    margin-bottom: 15px;
+}
+
+.pagination .pager-item {
+    margin: 0 2px;
+}
+
+.pagination .pager-link {
+    padding: 8px 16px;
+    border-radius: 4px;
+    margin: 0 3px;
+    font-weight: 500;
+    border: 1px solid #ddd;
+    background-color: #fff;
+    color: #2196f3;
+    text-decoration: none;
+    display: inline-block;
+}
+
+.pagination .pager-item.active .pager-link {
+    background-color: #2196f3;
+    color: white;
+    border-color: #2196f3;
+}
+
+.pagination .pager-item.disabled .pager-link {
+    color: #999;
+    cursor: not-allowed;
+    background-color: #f5f5f5;
+}
+
+.pagination-info {
+    margin-top: 10px;
+    font-size: 14px;
+    color: #666;
+}
+
+.form-btn {
+    padding: 8px 15px;
+    border-radius: 4px;
+    cursor: pointer;
+    font-size: 14px;
+    border: none;
+    transition: all 0.3s ease;
+}
+
+.form-btn-primary {
+    background-color: #2196f3;
+    color: white;
+}
+
+.form-btn-primary:hover {
+    background-color: #0d8aee;
+    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
+}
+
+/* 添加斑马纹和悬停效果 */
+.data-table tr:nth-child(even) {
+    background-color: #f8f8f8;
+}
+
+.data-table tbody tr:hover {
+    background-color: #f0f7ff;
+}
+</style>
+
+<script>
+function toggleCustomDates() {
+    const dateRange = document.getElementById('date_range').value;
+    const customDateInputs = document.querySelectorAll('.custom-date-inputs');
+    
+    if (dateRange === 'custom') {
+        customDateInputs.forEach(el => el.style.display = 'inline-block');
+    } else {
+        customDateInputs.forEach(el => el.style.display = 'none');
+    }
+}
+
+// 订单趋势图
+document.addEventListener('DOMContentLoaded', function() {
+    const ctx = document.getElementById('orderTrendChart').getContext('2d');
+    
+    const months = <?php echo $months_json; ?>;
+    const orderCounts = <?php echo $order_counts_json; ?>;
+    const orderAmounts = <?php echo $order_amounts_json; ?>;
+    
+    const chart = new Chart(ctx, {
+        type: 'line',
+        data: {
+            labels: months,
+            datasets: [
+                {
+                    label: '订单数量',
+                    data: orderCounts,
+                    backgroundColor: 'rgba(54, 162, 235, 0.2)',
+                    borderColor: 'rgba(54, 162, 235, 1)',
+                    borderWidth: 2,
+                    yAxisID: 'y-axis-1'
+                },
+                {
+                    label: '订单金额',
+                    data: orderAmounts,
+                    backgroundColor: 'rgba(255, 99, 132, 0.2)',
+                    borderColor: 'rgba(255, 99, 132, 1)',
+                    borderWidth: 2,
+                    yAxisID: 'y-axis-2'
+                }
+            ]
+        },
+        options: {
+            responsive: true,
+            maintainAspectRatio: false,
+            scales: {
+                'y-axis-1': {
+                    type: 'linear',
+                    position: 'left',
+                    title: {
+                        display: true,
+                        text: '订单数量'
+                    }
+                },
+                'y-axis-2': {
+                    type: 'linear',
+                    position: 'right',
+                    title: {
+                        display: true,
+                        text: '订单金额'
+                    },
+                    grid: {
+                        drawOnChartArea: false
+                    }
+                }
+            }
+        }
+    });
+});
+</script>
+
+<?php
+/**
+ * 获取订单金额下降的客户
+ */
+function getDecreasingOrderAmountCustomers($conn, $current_start, $current_end, $previous_start, $previous_end, $threshold, $count_only = false, $selected_employee = 0) {
+    // 构建业务员筛选条件
+    $employee_filter = $selected_employee > 0 ? " AND c.cs_belong = ?" : "";
+    
+    // 如果只需要计数
+    if ($count_only) {
+        $sql = "SELECT COUNT(DISTINCT c.id) as count
+        FROM customer c
+        LEFT JOIN (
+            SELECT customer_id, SUM(total_amount) as amount
+            FROM orders
+            WHERE order_date BETWEEN ? AND ?
+            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 ? AND ?
+            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 <= ?)
+        AND c.cs_deal = 3" . $employee_filter;
+        
+        $stmt = $conn->prepare($sql);
+        
+        if ($selected_employee > 0) {
+            $stmt->bind_param("ssssdi", $current_start, $current_end, $previous_start, $previous_end, $threshold, $selected_employee);
+        } else {
+            $stmt->bind_param("ssssd", $current_start, $current_end, $previous_start, $previous_end, $threshold);
+        }
+        
+        $stmt->execute();
+        $result = $stmt->get_result();
+        $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 ? AND ?
+        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 ? AND ?
+        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 <= ?)
+    AND c.cs_deal = 3" . $employee_filter . "
+    ORDER BY (current_period.amount / previous_period.amount) ASC";
+    
+    $stmt = $conn->prepare($sql);
+    
+    if ($selected_employee > 0) {
+        $stmt->bind_param("ssssdi", $current_start, $current_end, $previous_start, $previous_end, $threshold, $selected_employee);
+    } else {
+        $stmt->bind_param("ssssd", $current_start, $current_end, $previous_start, $previous_end, $threshold);
+    }
+    
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取复购周期异常的客户
+ */
+function getAbnormalRepurchaseCycleCustomers($conn, $current_start, $current_end, $max_threshold, $min_threshold, $normal_cycle, $count_only = false, $selected_employee = 0) {
+    // 构建业务员筛选条件
+    $employee_filter = $selected_employee > 0 ? " AND c.cs_belong = ?" : "";
+    
+    if ($count_only) {
+        $sql = "SELECT COUNT(DISTINCT t.customer_id) as count
+        FROM (
+            SELECT 
+                o.customer_id,
+                COUNT(o.id) as order_count,
+                AVG(DATEDIFF(o.order_date, prev_order.order_date)) as avg_cycle,
+                MAX(DATEDIFF(o.order_date, prev_order.order_date)) as recent_cycle
+            FROM orders o
+            JOIN customer c ON o.customer_id = c.id
+            JOIN orders prev_order ON o.customer_id = prev_order.customer_id AND prev_order.order_date < o.order_date
+            WHERE o.order_date BETWEEN ? AND ?" . $employee_filter . "
+            GROUP BY o.customer_id
+            HAVING order_count > 1
+            AND (recent_cycle > ? OR recent_cycle < (? * ?))
+        ) t";
+        
+        $stmt = $conn->prepare($sql);
+        
+        if ($selected_employee > 0) {
+            $stmt->bind_param("ssiddd", $current_start, $current_end, $selected_employee, $max_threshold, $normal_cycle, $min_threshold);
+        } else {
+            $stmt->bind_param("ssddd", $current_start, $current_end, $max_threshold, $normal_cycle, $min_threshold);
+        }
+        
+        $stmt->execute();
+        $result = $stmt->get_result();
+        $row = $result->fetch_assoc();
+        return $row['count'];
+    }
+    
+    // 使用子查询方式,先获取所有符合条件的客户及其复购周期数据
+    $sql = "SELECT 
+        abnormal.customer_id as id,
+        c.cs_company,
+        abnormal.order_count,
+        abnormal.avg_cycle,
+        abnormal.recent_cycle,
+        abnormal.last_order_date,
+        e.em_user,
+        CASE 
+            WHEN abnormal.recent_cycle > ? THEN 1 /* 周期过长 */
+            ELSE 2 /* 周期过短 */
+        END as cycle_type,
+        CASE 
+            WHEN abnormal.recent_cycle > ? THEN abnormal.recent_cycle
+            ELSE (? * ?) - abnormal.recent_cycle
+        END as sort_value
+    FROM (
+        SELECT 
+            o.customer_id,
+            COUNT(o.id) as order_count,
+            AVG(DATEDIFF(o.order_date, prev_order.order_date)) as avg_cycle,
+            MAX(DATEDIFF(o.order_date, prev_order.order_date)) as recent_cycle,
+            (SELECT MAX(order_date) FROM orders WHERE customer_id = o.customer_id) as last_order_date
+        FROM orders o
+        JOIN customer c ON o.customer_id = c.id
+        JOIN orders prev_order ON o.customer_id = prev_order.customer_id AND prev_order.order_date < o.order_date
+        WHERE o.order_date BETWEEN ? AND ?" . $employee_filter . "
+        GROUP BY o.customer_id
+        HAVING order_count > 1
+        AND (recent_cycle > ? OR recent_cycle < (? * ?))
+    ) as abnormal
+    JOIN customer c ON abnormal.customer_id = c.id
+    JOIN employee e ON c.cs_belong = e.id
+    ORDER BY sort_value DESC";
+    
+    $stmt = $conn->prepare($sql);
+    
+    if ($selected_employee > 0) {
+        $stmt->bind_param("ddddssiddd", $max_threshold, $max_threshold, $normal_cycle, $min_threshold, $current_start, $current_end, $selected_employee, $max_threshold, $normal_cycle, $min_threshold);
+    } else {
+        $stmt->bind_param("ddddssddd", $max_threshold, $max_threshold, $normal_cycle, $min_threshold, $current_start, $current_end, $max_threshold, $normal_cycle, $min_threshold);
+    }
+    
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取长期不活跃的客户
+ */
+function getInactiveCustomers($conn, $end_date, $inactive_days, $count_only = false, $page = 1, $page_size = 10, $selected_employee = 0) {
+    // 构建业务员筛选条件
+    $employee_filter = $selected_employee > 0 ? " AND c.cs_belong = ?" : "";
+    
+    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(?, last_orders.last_order_date) > ?
+        )" . $employee_filter;
+        
+        $stmt = $conn->prepare($sql);
+        
+        if ($selected_employee > 0) {
+            $stmt->bind_param("sii", $end_date, $inactive_days, $selected_employee);
+        } else {
+            $stmt->bind_param("si", $end_date, $inactive_days);
+        }
+        
+        $stmt->execute();
+        $result = $stmt->get_result();
+        $row = $result->fetch_assoc();
+        return $row['count'];
+    }
+    
+    $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(?, c.cs_addtime)
+            ELSE DATEDIFF(?, 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(?, last_orders.last_order_date) > ?
+    )" . $employee_filter . "
+    ORDER BY inactive_days DESC
+    LIMIT ?, ?";
+    
+    $offset = ($page - 1) * $page_size;
+    
+    $stmt = $conn->prepare($sql);
+    
+    if ($selected_employee > 0) {
+        $stmt->bind_param("sssiiii", $end_date, $end_date, $end_date, $inactive_days, $selected_employee, $offset, $page_size);
+    } else {
+        $stmt->bind_param("sssiii", $end_date, $end_date, $end_date, $inactive_days, $offset, $page_size);
+    }
+    
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+// 页面底部
+include('statistics_footer.php');
+?>

+ 1149 - 0
statistics_products.php

@@ -0,0 +1,1149 @@
+<?php
+/**
+ * 产品统计分析模块
+ * 
+ * 包含与产品相关的数据分析功能
+ */
+
+require_once 'statistics_utils.php';
+
+/**
+ * 获取热门产品数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @param int $limit 限制返回的产品数量
+ * @return mysqli_result 热门产品数据结果集
+ */
+function getTopProducts($conn, $start_date, $end_date, $limit = 5) {
+    $sql = "SELECT 
+                p.ProductName, 
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY oi.product_id
+            ORDER BY total_revenue DESC
+            LIMIT ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ssi", $start_date, $end_date, $limit);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品销售趋势
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @param int $product_id 产品ID,为0时获取所有产品的总体趋势
+ * @param string $period 时间粒度 (day/week/month)
+ * @return mysqli_result 产品销售趋势数据结果集
+ */
+function getProductSalesTrend($conn, $start_date, $end_date, $product_id = 0, $period = 'month') {
+    $groupFormat = '%Y-%m-%d';
+    if ($period == 'week') {
+        $groupFormat = '%x-W%v'; // ISO year and week number
+    } else if ($period == 'month') {
+        $groupFormat = '%Y-%m';
+    }
+    
+    $sql = "SELECT 
+                DATE_FORMAT(o.order_date, '$groupFormat') as time_period,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue,
+                COUNT(DISTINCT o.id) as order_count
+            FROM order_items oi
+            JOIN orders o ON oi.order_id = o.id";
+    
+    if ($product_id > 0) {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ? AND oi.product_id = ?";
+    } else {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ?";
+    }
+    
+    $sql .= " GROUP BY time_period
+              ORDER BY MIN(o.order_date)";
+    
+    $stmt = $conn->prepare($sql);
+    
+    if ($product_id > 0) {
+        $stmt->bind_param("ssi", $start_date, $end_date, $product_id);
+    } else {
+        $stmt->bind_param("ss", $start_date, $end_date);
+    }
+    
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品类别销售分布
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return mysqli_result 产品类别销售分布数据结果集
+ */
+function getProductCategorySales($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                pc.name as category_name, 
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue,
+                COUNT(DISTINCT o.id) as order_count
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN product_categories pc ON p.category_id = pc.id
+            JOIN orders o ON oi.order_id = o.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY p.category_id
+            ORDER BY total_revenue DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品与地区关联分析
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @param int $limit 限制返回的产品-地区组合数量
+ * @return mysqli_result 产品与地区关联分析数据结果集
+ */
+function getProductRegionAnalysis($conn, $start_date, $end_date, $limit = 10) {
+    $sql = "SELECT 
+                p.ProductName, 
+                c.countryName,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY oi.product_id, cu.cs_country
+            ORDER BY total_revenue DESC
+            LIMIT ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ssi", $start_date, $end_date, $limit);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品销售概览数据
+ */
+function getProductSalesOverview($conn, $start_date, $end_date, $category_filter = 0) {
+    $where_clause = "WHERE o.order_date BETWEEN ? AND ?";
+    $params = [$start_date, $end_date];
+    
+    if ($category_filter > 0) {
+        $where_clause .= " AND p.category_id = ?";
+        $params[] = $category_filter;
+    }
+    
+    $sql = "SELECT 
+                COUNT(DISTINCT oi.product_id) as total_products,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue,
+                AVG(oi.unit_price) as avg_unit_price,
+                COUNT(DISTINCT o.id) as total_orders,
+                SUM(oi.total_price) / COUNT(DISTINCT o.id) as avg_order_value,
+                COUNT(DISTINCT o.customer_id) as total_customers
+            FROM order_items oi
+            JOIN orders o ON oi.order_id = o.id
+            JOIN products p ON oi.product_id = p.id
+            $where_clause";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param(str_repeat('s', count($params)), ...$params);
+    $stmt->execute();
+    return $stmt->get_result()->fetch_assoc();
+}
+
+/**
+ * 获取产品价格趋势分析
+ */
+function getProductPriceTrendAnalysis($conn, $start_date, $end_date, $product_id = 0, $period = 'month') {
+    $groupFormat = getPeriodFormat($period);
+    
+    $sql = "SELECT 
+                DATE_FORMAT(o.order_date, '$groupFormat') as time_period,
+                AVG(oi.unit_price) as avg_price,
+                MIN(oi.unit_price) as min_price,
+                MAX(oi.unit_price) as max_price
+            FROM order_items oi
+            JOIN orders o ON oi.order_id = o.id";
+    
+    if ($product_id > 0) {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ? AND oi.product_id = ?";
+    } else {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ?";
+    }
+    
+    $sql .= " GROUP BY time_period ORDER BY MIN(o.order_date)";
+    
+    $stmt = $conn->prepare($sql);
+    if ($product_id > 0) {
+        $stmt->bind_param("ssi", $start_date, $end_date, $product_id);
+    } else {
+        $stmt->bind_param("ss", $start_date, $end_date);
+    }
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品季节性分析
+ */
+function getProductSeasonalityAnalysis($conn, $start_date, $end_date, $product_id = 0) {
+    $sql = "SELECT 
+                MONTH(o.order_date) as month,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue,
+                COUNT(DISTINCT o.id) as order_count
+            FROM order_items oi
+            JOIN orders o ON oi.order_id = o.id";
+    
+    if ($product_id > 0) {
+        $sql .= " WHERE oi.product_id = ? AND o.order_date BETWEEN ? AND ?";
+    } else {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ?";
+    }
+    
+    $sql .= " GROUP BY MONTH(o.order_date)
+              ORDER BY MONTH(o.order_date)";
+    
+    $stmt = $conn->prepare($sql);
+    if ($product_id > 0) {
+        $stmt->bind_param("iss", $product_id, $start_date, $end_date);
+    } else {
+        $stmt->bind_param("ss", $start_date, $end_date);
+    }
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品客户细分分析
+ */
+function getProductCustomerSegmentAnalysis($conn, $start_date, $end_date, $product_id = 0) {
+    $sql = "SELECT 
+                ct.businessType as segment_name,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                SUM(oi.quantity) as total_quantity,
+                SUM(oi.total_price) as total_revenue,
+                AVG(oi.unit_price) as avg_unit_price
+            FROM order_items oi
+            JOIN orders o ON oi.order_id = o.id
+            JOIN customer c ON o.customer_id = c.id
+            JOIN clienttype ct ON c.cs_type = ct.id";
+    
+    if ($product_id > 0) {
+        $sql .= " WHERE oi.product_id = ? AND o.order_date BETWEEN ? AND ?";
+    } else {
+        $sql .= " WHERE o.order_date BETWEEN ? AND ?";
+    }
+    
+    $sql .= " GROUP BY ct.id";
+    
+    $stmt = $conn->prepare($sql);
+    if ($product_id > 0) {
+        $stmt->bind_param("iss", $product_id, $start_date, $end_date);
+    } else {
+        $stmt->bind_param("ss", $start_date, $end_date);
+    }
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品分类列表
+ * 
+ * @param mysqli $conn 数据库连接
+ * @return mysqli_result 产品分类数据结果集
+ */
+function getProductCategories($conn) {
+    $sql = "SELECT 
+                id,
+                parent_id,
+                name,
+                description,
+                sort_order
+            FROM product_categories 
+            WHERE status = 1
+            ORDER BY sort_order ASC, id ASC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 渲染热门产品表格
+ * 
+ * @param mysqli_result $top_products 热门产品数据
+ * @return void
+ */
+function renderTopProductsTable($top_products) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">热门产品</h2>
+        </div>
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>产品名称</th>
+                    <th>销售数量</th>
+                    <th>销售收入</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php while ($row = $top_products->fetch_assoc()): ?>
+                <tr>
+                    <td><?php echo htmlspecialchars($row['ProductName']); ?></td>
+                    <td><?php echo number_format($row['total_quantity']); ?></td>
+                    <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
+                </tr>
+                <?php endwhile; ?>
+            </tbody>
+        </table>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染产品销售趋势图
+ * 
+ * @param array $time_labels 时间标签
+ * @param array $quantities 产品销售数量
+ * @param array $revenues 产品销售收入
+ * @return void
+ */
+function renderProductSalesTrendChart($time_labels, $quantities, $revenues) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品销售趋势</h2>
+        </div>
+        <canvas id="productSalesTrendChart"></canvas>
+    </div>
+    
+    <script>
+        // 产品销售趋势图
+        var productSalesTrendCtx = document.getElementById('productSalesTrendChart').getContext('2d');
+        var productSalesTrendChart = new Chart(productSalesTrendCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($time_labels); ?>,
+                datasets: [
+                    {
+                        label: '销售数量',
+                        data: <?php echo json_encode($quantities); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.2)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-quantity',
+                        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-quantity': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '销售数量'
+                        },
+                        beginAtZero: true
+                    },
+                    'y-revenue': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '销售收入'
+                        },
+                        beginAtZero: true,
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染产品类别销售分布图
+ * 
+ * @param array $categories 类别名称
+ * @param array $quantities 类别销售数量
+ * @param array $revenues 类别销售收入
+ * @return void
+ */
+function renderProductCategorySalesChart($categories, $quantities, $revenues) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品类别销售分布</h2>
+        </div>
+        <style>
+            .pie-charts-container {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                margin-bottom: 20px;
+            }
+            .pie-chart-wrapper {
+                flex: 0 0 48%;
+                max-width: 48%;
+            }
+        </style>
+        <div class="pie-charts-container">
+            <div class="pie-chart-wrapper">
+                <h3 style="text-align: center; margin-bottom: 15px;">产品类别销售数量分布</h3>
+                <canvas id="categoryQuantityChart"></canvas>
+            </div>
+            <div class="pie-chart-wrapper">
+                <h3 style="text-align: center; margin-bottom: 15px;">产品类别销售收入分布</h3>
+                <canvas id="categoryRevenueChart"></canvas>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 产品类别数量分布图
+        var categoryQuantityCtx = document.getElementById('categoryQuantityChart').getContext('2d');
+        var categoryQuantityChart = new Chart(categoryQuantityCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($categories); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($quantities); ?>,
+                    backgroundColor: [
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)',
+                        'rgba(255, 159, 64, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                maintainAspectRatio: true,
+                plugins: {
+                    legend: {
+                        position: 'bottom',
+                    }
+                }
+            }
+        });
+        
+        // 产品类别收入分布图
+        var categoryRevenueCtx = document.getElementById('categoryRevenueChart').getContext('2d');
+        var categoryRevenueChart = new Chart(categoryRevenueCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($categories); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($revenues); ?>,
+                    backgroundColor: [
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)',
+                        'rgba(255, 159, 64, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                maintainAspectRatio: true,
+                plugins: {
+                    legend: {
+                        position: 'bottom',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染产品与地区关联分析表格
+ * 
+ * @param mysqli_result $product_region_data 产品与地区关联数据
+ * @return void
+ */
+function renderProductRegionAnalysisTable($product_region_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品地区关联分析</h2>
+        </div>
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>产品名称</th>
+                    <th>国家/地区</th>
+                    <th>销售数量</th>
+                    <th>销售收入</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php while ($row = $product_region_data->fetch_assoc()): ?>
+                <tr>
+                    <td><?php echo htmlspecialchars($row['ProductName']); ?></td>
+                    <td><?php echo htmlspecialchars($row['countryName']); ?></td>
+                    <td><?php echo number_format($row['total_quantity']); ?></td>
+                    <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
+                </tr>
+                <?php endwhile; ?>
+            </tbody>
+        </table>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染产品销售概览
+ */
+function renderProductSalesOverview($overview) {
+    // 处理可能为null的值
+    $total_products = isset($overview['total_products']) ? $overview['total_products'] : 0;
+    $total_quantity = isset($overview['total_quantity']) ? $overview['total_quantity'] : 0;
+    $total_revenue = isset($overview['total_revenue']) ? $overview['total_revenue'] : 0;
+    $avg_unit_price = isset($overview['avg_unit_price']) ? $overview['avg_unit_price'] : 0;
+    $total_orders = isset($overview['total_orders']) ? $overview['total_orders'] : 0;
+    $avg_order_value = isset($overview['avg_order_value']) ? $overview['avg_order_value'] : 0;
+    ?>
+    <div class="stats-card-container">
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>总销售产品数</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($total_products); ?></div>
+                <div class="stats-card-subtitle">种类</div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>总销售数量</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($total_quantity); ?></div>
+                <div class="stats-card-subtitle">件</div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>总销售收入</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value">¥<?php echo number_format($total_revenue, 2); ?></div>
+                <div class="stats-card-subtitle">元</div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>平均单价</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value">¥<?php echo number_format($avg_unit_price, 2); ?></div>
+                <div class="stats-card-subtitle">元/件</div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>订单数量</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value"><?php echo number_format($total_orders); ?></div>
+                <div class="stats-card-subtitle">笔</div>
+            </div>
+        </div>
+        
+        <div class="stats-card">
+            <div class="stats-card-header">
+                <h3>平均订单金额</h3>
+            </div>
+            <div class="stats-card-body">
+                <div class="stats-card-value">¥<?php echo number_format($avg_order_value, 2); ?></div>
+                <div class="stats-card-subtitle">元/订单</div>
+            </div>
+        </div>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染产品价格趋势图表
+ */
+function renderProductPriceTrendChart($price_trend_data) {
+    $time_periods = [];
+    $avg_prices = [];
+    $min_prices = [];
+    $max_prices = [];
+    
+    while ($row = $price_trend_data->fetch_assoc()) {
+        $time_periods[] = $row['time_period'];
+        $avg_prices[] = round($row['avg_price'], 2);
+        $min_prices[] = round($row['min_price'], 2);
+        $max_prices[] = round($row['max_price'], 2);
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品价格趋势分析</h2>
+        </div>
+        <canvas id="priceTrendChart"></canvas>
+    </div>
+    
+    <script>
+        var priceTrendCtx = document.getElementById('priceTrendChart').getContext('2d');
+        new Chart(priceTrendCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($time_periods); ?>,
+                datasets: [
+                    {
+                        label: '平均价格',
+                        data: <?php echo json_encode($avg_prices); ?>,
+                        borderColor: 'rgb(54, 162, 235)',
+                        backgroundColor: 'rgba(54, 162, 235, 0.1)',
+                        borderWidth: 2,
+                        fill: false
+                    },
+                    {
+                        label: '最低价格',
+                        data: <?php echo json_encode($min_prices); ?>,
+                        borderColor: 'rgb(75, 192, 192)',
+                        backgroundColor: 'rgba(75, 192, 192, 0.1)',
+                        borderWidth: 2,
+                        fill: false
+                    },
+                    {
+                        label: '最高价格',
+                        data: <?php echo json_encode($max_prices); ?>,
+                        borderColor: 'rgb(255, 99, 132)',
+                        backgroundColor: 'rgba(255, 99, 132, 0.1)',
+                        borderWidth: 2,
+                        fill: false
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    y: {
+                        beginAtZero: true,
+                        title: {
+                            display: true,
+                            text: '价格 (元)'
+                        }
+                    }
+                },
+                plugins: {
+                    title: {
+                        display: true,
+                        text: '产品价格变化趋势'
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染产品季节性分析图表
+ */
+function renderProductSeasonalityChart($seasonality_data) {
+    $months = [];
+    $quantities = [];
+    $revenues = [];
+    $order_counts = [];
+    
+    while ($row = $seasonality_data->fetch_assoc()) {
+        $months[] = date('n月', mktime(0, 0, 0, $row['month'], 1));
+        $quantities[] = (int)$row['total_quantity'];
+        $revenues[] = round($row['total_revenue'], 2);
+        $order_counts[] = (int)$row['order_count'];
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品季节性分析</h2>
+        </div>
+        <canvas id="seasonalityChart"></canvas>
+    </div>
+    
+    <script>
+        var seasonalityCtx = document.getElementById('seasonalityChart').getContext('2d');
+        new Chart(seasonalityCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($months); ?>,
+                datasets: [
+                    {
+                        label: '销售数量',
+                        data: <?php echo json_encode($quantities); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.5)',
+                        borderColor: 'rgb(54, 162, 235)',
+                        borderWidth: 1,
+                        yAxisID: 'y-quantity'
+                    },
+                    {
+                        label: '销售收入',
+                        data: <?php echo json_encode($revenues); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.5)',
+                        borderColor: 'rgb(255, 99, 132)',
+                        borderWidth: 1,
+                        yAxisID: 'y-revenue'
+                    },
+                    {
+                        label: '订单数',
+                        data: <?php echo json_encode($order_counts); ?>,
+                        type: 'line',
+                        fill: false,
+                        borderColor: 'rgb(75, 192, 192)',
+                        tension: 0.1,
+                        yAxisID: 'y-orders'
+                    }
+                ]
+            },
+            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
+                        }
+                    },
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '订单数'
+                        },
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                },
+                plugins: {
+                    title: {
+                        display: true,
+                        text: '产品销售季节性分布'
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染产品客户细分分析图表
+ */
+function renderProductCustomerSegmentChart($segment_data) {
+    $segments = [];
+    $customer_counts = [];
+    $revenues = [];
+    $avg_prices = [];
+    
+    while ($row = $segment_data->fetch_assoc()) {
+        $segments[] = $row['segment_name'];
+        $customer_counts[] = (int)$row['customer_count'];
+        $revenues[] = round($row['total_revenue'], 2);
+        $avg_prices[] = round($row['avg_unit_price'], 2);
+    }
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品客户细分分析</h2>
+        </div>
+        <div class="chart-row">
+            <div class="chart-column">
+                <canvas id="customerSegmentChart1"></canvas>
+            </div>
+            <div class="chart-column">
+                <canvas id="customerSegmentChart2"></canvas>
+            </div>
+        </div>
+    </div>
+    
+    <script>
+        // 客户数量和收入分布
+        var segmentCtx1 = document.getElementById('customerSegmentChart1').getContext('2d');
+        new Chart(segmentCtx1, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($segments); ?>,
+                datasets: [
+                    {
+                        label: '客户数量',
+                        data: <?php echo json_encode($customer_counts); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.5)',
+                        borderColor: 'rgb(54, 162, 235)',
+                        borderWidth: 1,
+                        yAxisID: 'y-customers'
+                    },
+                    {
+                        label: '销售收入',
+                        data: <?php echo json_encode($revenues); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.5)',
+                        borderColor: 'rgb(255, 99, 132)',
+                        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
+                        }
+                    }
+                },
+                plugins: {
+                    title: {
+                        display: true,
+                        text: '客户细分分布'
+                    }
+                }
+            }
+        });
+
+        // 平均单价分布
+        var segmentCtx2 = document.getElementById('customerSegmentChart2').getContext('2d');
+        new Chart(segmentCtx2, {
+            type: 'radar',
+            data: {
+                labels: <?php echo json_encode($segments); ?>,
+                datasets: [{
+                    label: '平均单价',
+                    data: <?php echo json_encode($avg_prices); ?>,
+                    backgroundColor: 'rgba(75, 192, 192, 0.2)',
+                    borderColor: 'rgb(75, 192, 192)',
+                    pointBackgroundColor: 'rgb(75, 192, 192)',
+                    pointBorderColor: '#fff',
+                    pointHoverBackgroundColor: '#fff',
+                    pointHoverBorderColor: 'rgb(75, 192, 192)'
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    title: {
+                        display: true,
+                        text: '客户细分平均单价分布'
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 获取产品增长率分析
+ */
+function getProductGrowthAnalysis($conn, $start_date, $end_date, $period = 'month') {
+    $groupFormat = getPeriodFormat($period);
+    
+    // 获取当前期间的数据
+    $sql = "SELECT 
+                p.ProductName,
+                SUM(oi.total_price) as current_revenue,
+                SUM(oi.quantity) as current_quantity,
+                COUNT(DISTINCT o.id) as current_orders
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY oi.product_id
+            HAVING current_revenue > 0
+            ORDER BY current_revenue DESC
+            LIMIT 10";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    $current_data = $stmt->get_result();
+    
+    // 计算上一个时间段
+    $date1 = new DateTime($start_date);
+    $date2 = new DateTime($end_date);
+    $interval = $date1->diff($date2);
+    $days_diff = $interval->days;
+    
+    $prev_end = $date1->format('Y-m-d');
+    $prev_start = $date1->modify("-{$days_diff} days")->format('Y-m-d');
+    
+    // 获取上一期间的数据
+    $sql = "SELECT 
+                p.ProductName,
+                SUM(oi.total_price) as prev_revenue,
+                SUM(oi.quantity) as prev_quantity,
+                COUNT(DISTINCT o.id) as prev_orders
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY oi.product_id";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $prev_start, $prev_end);
+    $stmt->execute();
+    $prev_result = $stmt->get_result();
+    
+    $prev_data = [];
+    while ($row = $prev_result->fetch_assoc()) {
+        $prev_data[$row['ProductName']] = $row;
+    }
+    
+    $growth_data = [];
+    while ($current = $current_data->fetch_assoc()) {
+        $product_name = $current['ProductName'];
+        $prev = isset($prev_data[$product_name]) ? $prev_data[$product_name] : [
+            'prev_revenue' => 0,
+            'prev_quantity' => 0,
+            'prev_orders' => 0
+        ];
+        
+        $growth_data[] = [
+            'product_name' => $product_name,
+            'current_revenue' => $current['current_revenue'],
+            'current_quantity' => $current['current_quantity'],
+            'current_orders' => $current['current_orders'],
+            'prev_revenue' => $prev['prev_revenue'],
+            'prev_quantity' => $prev['prev_quantity'],
+            'prev_orders' => $prev['prev_orders'],
+            'revenue_growth' => calculateGrowthRate($current['current_revenue'], $prev['prev_revenue']),
+            'quantity_growth' => calculateGrowthRate($current['current_quantity'], $prev['prev_quantity']),
+            'orders_growth' => calculateGrowthRate($current['current_orders'], $prev['prev_orders'])
+        ];
+    }
+    
+    return $growth_data;
+}
+
+/**
+ * 计算增长率
+ */
+function calculateGrowthRate($current, $previous) {
+    if ($previous == 0) {
+        return $current > 0 ? 100 : 0;
+    }
+    return round((($current - $previous) / $previous) * 100, 2);
+}
+
+/**
+ * 渲染产品增长率分析
+ */
+function renderProductGrowthAnalysis($growth_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品增长率分析</h2>
+            <div class="chart-subtitle">与上一时期相比</div>
+        </div>
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>产品名称</th>
+                    <th>当期收入</th>
+                    <th>收入增长率</th>
+                    <th>当期销量</th>
+                    <th>销量增长率</th>
+                    <th>当期订单数</th>
+                    <th>订单增长率</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php foreach ($growth_data as $row): ?>
+                <tr>
+                    <td><?php echo htmlspecialchars($row['product_name']); ?></td>
+                    <td>¥<?php echo number_format($row['current_revenue'], 2); ?></td>
+                    <td class="<?php echo $row['revenue_growth'] >= 0 ? 'positive' : 'negative'; ?>">
+                        <?php echo ($row['revenue_growth'] >= 0 ? '+' : '') . $row['revenue_growth']; ?>%
+                    </td>
+                    <td><?php echo number_format($row['current_quantity']); ?></td>
+                    <td class="<?php echo $row['quantity_growth'] >= 0 ? 'positive' : 'negative'; ?>">
+                        <?php echo ($row['quantity_growth'] >= 0 ? '+' : '') . $row['quantity_growth']; ?>%
+                    </td>
+                    <td><?php echo number_format($row['current_orders']); ?></td>
+                    <td class="<?php echo $row['orders_growth'] >= 0 ? 'positive' : 'negative'; ?>">
+                        <?php echo ($row['orders_growth'] >= 0 ? '+' : '') . $row['orders_growth']; ?>%
+                    </td>
+                </tr>
+                <?php endforeach; ?>
+            </tbody>
+        </table>
+    </div>
+    
+    <style>
+    .positive {
+        color: #4CAF50;
+        font-weight: bold;
+    }
+    .negative {
+        color: #f44336;
+        font-weight: bold;
+    }
+    .chart-subtitle {
+        font-size: 14px;
+        color: #666;
+        margin-top: 5px;
+    }
+    </style>
+    <?php
+}
+
+/**
+ * 获取产品购买频率分析
+ */
+function getProductPurchaseFrequency($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                p.ProductName,
+                COUNT(DISTINCT o.id) as order_count,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                COUNT(DISTINCT o.id) / COUNT(DISTINCT o.customer_id) as purchase_frequency,
+                AVG(
+                    CASE 
+                        WHEN next_order.next_date IS NOT NULL 
+                        THEN DATEDIFF(next_order.next_date, o.order_date)
+                        ELSE NULL 
+                    END
+                ) as avg_days_between_orders
+            FROM order_items oi
+            JOIN products p ON oi.product_id = p.id
+            JOIN orders o ON oi.order_id = o.id
+            LEFT JOIN (
+                SELECT 
+                    o1.customer_id,
+                    o1.order_date,
+                    MIN(o2.order_date) as next_date
+                FROM orders o1
+                LEFT JOIN orders o2 ON o1.customer_id = o2.customer_id 
+                    AND o2.order_date > o1.order_date
+                WHERE o1.order_date BETWEEN ? AND ?
+                GROUP BY o1.customer_id, o1.order_date
+            ) next_order ON o.customer_id = next_order.customer_id 
+                AND o.order_date = next_order.order_date
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY p.id
+            HAVING order_count > 1
+            ORDER BY purchase_frequency DESC
+            LIMIT 10";
+            
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ssss", $start_date, $end_date, $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 渲染产品购买频率分析
+ */
+function renderProductPurchaseFrequency($frequency_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">产品购买频率分析</h2>
+        </div>
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>产品名称</th>
+                    <th>订单总数</th>
+                    <th>购买客户数</th>
+                    <th>平均购买频率</th>
+                    <th>平均购买间隔(天)</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php while ($row = $frequency_data->fetch_assoc()): ?>
+                <tr>
+                    <td><?php echo htmlspecialchars($row['ProductName']); ?></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['purchase_frequency'], 2); ?>次/客户</td>
+                    <td><?php echo $row['avg_days_between_orders'] ? number_format($row['avg_days_between_orders'], 1) : '-'; ?></td>
+                </tr>
+                <?php endwhile; ?>
+            </tbody>
+        </table>
+    </div>
+    <?php
+}

+ 1177 - 0
statistics_region.php

@@ -0,0 +1,1177 @@
+<?php
+/**
+ * 地区统计分析模块
+ * 
+ * 包含与地区相关的数据分析功能
+ */
+
+require_once 'statistics_utils.php';
+
+/**
+ * 获取客户国家分布
+ * 
+ * @param mysqli $conn 数据库连接
+ * @return mysqli_result 客户国家分布数据结果集
+ */
+function getCustomerCountryDistribution($conn) {
+    $sql = "SELECT 
+                c.countryName, 
+                COUNT(cu.id) as customer_count
+            FROM customer cu
+            JOIN country c ON cu.cs_country = c.id
+            GROUP BY cu.cs_country
+            ORDER BY customer_count DESC
+            LIMIT 10";
+    
+    return $conn->query($sql);
+}
+
+/**
+ * 获取不同地区的订单数量
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return mysqli_result 地区订单数据结果集
+ */
+function getOrdersByRegion($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName, 
+                COUNT(o.id) as order_count,
+                SUM(o.total_amount) as total_amount,
+                SUM(oi.quantity) as total_quantity
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            LEFT JOIN order_items oi ON o.id = oi.order_id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country
+            ORDER BY total_quantity DESC
+            LIMIT 10";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取地区销售同比环比数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $current_start 当前周期开始日期
+ * @param string $current_end 当前周期结束日期
+ * @return array 地区销售同比环比数据
+ */
+function getRegionSalesComparison($conn, $current_start, $current_end) {
+    // 计算上一个相同时长的周期
+    $current_start_date = new DateTime($current_start);
+    $current_end_date = new DateTime($current_end);
+    $interval = $current_start_date->diff($current_end_date);
+    
+    $prev_end_date = clone $current_start_date;
+    $prev_end_date->modify('-1 day');
+    $prev_start_date = clone $prev_end_date;
+    $prev_start_date->sub($interval);
+    
+    $prev_start = $prev_start_date->format('Y-m-d');
+    $prev_end = $prev_end_date->format('Y-m-d') . ' 23:59:59';
+    
+    // 获取当前周期数据
+    $sql = "SELECT 
+                c.countryName, 
+                COUNT(o.id) as order_count,
+                SUM(o.total_amount) as total_amount
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country
+            ORDER BY total_amount DESC
+            LIMIT 5";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $current_start, $current_end);
+    $stmt->execute();
+    $current_result = $stmt->get_result();
+    
+    $current_data = [];
+    while ($row = $current_result->fetch_assoc()) {
+        $current_data[$row['countryName']] = [
+            'order_count' => $row['order_count'],
+            'total_amount' => $row['total_amount']
+        ];
+    }
+    
+    // 获取上一个周期数据
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $prev_start, $prev_end);
+    $stmt->execute();
+    $prev_result = $stmt->get_result();
+    
+    $prev_data = [];
+    while ($row = $prev_result->fetch_assoc()) {
+        $prev_data[$row['countryName']] = [
+            'order_count' => $row['order_count'],
+            'total_amount' => $row['total_amount']
+        ];
+    }
+    
+    // 计算同比变化
+    $comparison_data = [];
+    foreach ($current_data as $country => $current) {
+        $prev = $prev_data[$country] ?? ['order_count' => 0, 'total_amount' => 0];
+        
+        $order_growth = $prev['order_count'] > 0 
+            ? (($current['order_count'] - $prev['order_count']) / $prev['order_count']) * 100 
+            : 100;
+            
+        $amount_growth = $prev['total_amount'] > 0 
+            ? (($current['total_amount'] - $prev['total_amount']) / $prev['total_amount']) * 100 
+            : 100;
+            
+        $comparison_data[] = [
+            'countryName' => $country,
+            'current_orders' => $current['order_count'],
+            'prev_orders' => $prev['order_count'],
+            'order_growth' => $order_growth,
+            'current_amount' => $current['total_amount'],
+            'prev_amount' => $prev['total_amount'],
+            'amount_growth' => $amount_growth
+        ];
+    }
+    
+    return $comparison_data;
+}
+
+/**
+ * 渲染客户国家分布图
+ * 
+ * @param array $country_labels 国家标签
+ * @param array $country_data 国家数据
+ * @return void
+ */
+function renderCustomerCountryDistributionChart($country_labels, $country_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">客户国家分布</h2>
+        </div>
+        <canvas id="countryDistributionChart"></canvas>
+    </div>
+    
+    <script>
+        // 客户国家分布图
+        var countryDistributionCtx = document.getElementById('countryDistributionChart').getContext('2d');
+        var countryDistributionChart = new Chart(countryDistributionCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php echo json_encode($country_labels); ?>,
+                datasets: [{
+                    data: <?php echo json_encode($country_data); ?>,
+                    backgroundColor: [
+                        'rgba(255, 99, 132, 0.7)',
+                        'rgba(54, 162, 235, 0.7)',
+                        'rgba(255, 206, 86, 0.7)',
+                        'rgba(75, 192, 192, 0.7)',
+                        'rgba(153, 102, 255, 0.7)',
+                        'rgba(255, 159, 64, 0.7)',
+                        'rgba(199, 199, 199, 0.7)',
+                        'rgba(83, 102, 255, 0.7)',
+                        'rgba(40, 159, 64, 0.7)',
+                        'rgba(210, 199, 199, 0.7)'
+                    ],
+                    borderWidth: 1
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right',
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染地区订单分析图
+ * 
+ * @param array $region_labels 地区标签
+ * @param array $region_orders 地区订单数量
+ * @param array $region_quantities 地区产品数量
+ * @return void
+ */
+function renderRegionOrdersChart($region_labels, $region_orders, $region_quantities) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">地区订单分析</h2>
+        </div>
+        <canvas id="regionOrdersChart"></canvas>
+    </div>
+    
+    <script>
+        // 地区订单分析图
+        var regionOrdersCtx = document.getElementById('regionOrdersChart').getContext('2d');
+        var regionOrdersChart = new Chart(regionOrdersCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($region_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($region_orders); ?>,
+                        backgroundColor: 'rgba(54, 162, 235, 0.6)',
+                        borderColor: 'rgba(54, 162, 235, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-orders'
+                    },
+                    {
+                        label: '产品订购数量',
+                        data: <?php echo json_encode($region_quantities); ?>,
+                        backgroundColor: 'rgba(255, 99, 132, 0.6)',
+                        borderColor: 'rgba(255, 99, 132, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-quantity'
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '地区'
+                        }
+                    },
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        },
+                        beginAtZero: true
+                    },
+                    'y-quantity': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '产品订购数量'
+                        },
+                        beginAtZero: true,
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染地区销售同比环比表格
+ * 
+ * @param array $comparison_data 比较数据
+ * @return void
+ */
+function renderRegionSalesComparisonTable($comparison_data) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">地区销售同比分析</h2>
+        </div>
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>国家/地区</th>
+                    <th>当前订单数</th>
+                    <th>上期订单数</th>
+                    <th>订单增长率</th>
+                    <th>当前销售额</th>
+                    <th>上期销售额</th>
+                    <th>销售额增长率</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php foreach ($comparison_data as $row): ?>
+                <tr>
+                    <td><?php echo htmlspecialchars($row['countryName']); ?></td>
+                    <td><?php echo number_format($row['current_orders']); ?></td>
+                    <td><?php echo number_format($row['prev_orders']); ?></td>
+                    <td class="<?php echo $row['order_growth'] >= 0 ? 'positive' : 'negative'; ?>">
+                        <?php echo number_format($row['order_growth'], 2); ?>%
+                    </td>
+                    <td>¥<?php echo number_format($row['current_amount'], 2); ?></td>
+                    <td>¥<?php echo number_format($row['prev_amount'], 2); ?></td>
+                    <td class="<?php echo $row['amount_growth'] >= 0 ? 'positive' : 'negative'; ?>">
+                        <?php echo number_format($row['amount_growth'], 2); ?>%
+                    </td>
+                </tr>
+                <?php endforeach; ?>
+            </tbody>
+        </table>
+    </div>
+    <?php
+}
+
+/**
+ * 获取地区总销售额及增长率
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 总销售额和增长率
+ */
+function getRegionTotalSales($conn, $start_date, $end_date) {
+    // 计算当前周期销售额
+    $sql = "SELECT SUM(o.total_amount) as total_amount
+            FROM orders o
+            WHERE o.order_date BETWEEN ? AND ?";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    $row = $result->fetch_assoc();
+    $current_amount = $row['total_amount'] ?? 0;
+    
+    // 计算上一个相同时长的周期
+    $current_start_date = new DateTime($start_date);
+    $current_end_date = new DateTime($end_date);
+    $interval = $current_start_date->diff($current_end_date);
+    
+    $prev_end_date = clone $current_start_date;
+    $prev_end_date->modify('-1 day');
+    $prev_start_date = clone $prev_end_date;
+    $prev_start_date->sub($interval);
+    
+    $prev_start = $prev_start_date->format('Y-m-d');
+    $prev_end = $prev_end_date->format('Y-m-d') . ' 23:59:59';
+    
+    // 获取上一周期销售额
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $prev_start, $prev_end);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    $row = $result->fetch_assoc();
+    $prev_amount = $row['total_amount'] ?? 0;
+    
+    // 计算增长率
+    $growth = 0;
+    if ($prev_amount > 0) {
+        $growth = (($current_amount - $prev_amount) / $prev_amount) * 100;
+    }
+    
+    return [
+        'total_amount' => $current_amount,
+        'growth' => $growth
+    ];
+}
+
+/**
+ * 获取活跃国家数
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 活跃国家信息
+ */
+function getActiveCountries($conn, $start_date, $end_date) {
+    $sql = "SELECT COUNT(DISTINCT cu.cs_country) as country_count
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            WHERE o.order_date 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 [
+        'count' => $row['country_count'] ?? 0
+    ];
+}
+
+/**
+ * 获取各地区平均订单金额
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 各地区平均订单金额数据
+ */
+function getAverageOrderByRegion($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName, 
+                AVG(o.total_amount) as avg_amount,
+                COUNT(o.id) as order_count
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country
+            HAVING order_count >= 5
+            ORDER BY avg_amount DESC
+            LIMIT 10";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $regions = [];
+    $total_avg = 0;
+    $total_orders = 0;
+    
+    while ($row = $result->fetch_assoc()) {
+        $regions[] = [
+            'countryName' => $row['countryName'],
+            'avg_amount' => $row['avg_amount'],
+            'order_count' => $row['order_count']
+        ];
+        
+        $total_avg += $row['avg_amount'] * $row['order_count'];
+        $total_orders += $row['order_count'];
+    }
+    
+    // 计算全球平均订单金额
+    $global_avg = $total_orders > 0 ? $total_avg / $total_orders : 0;
+    
+    return [
+        'regions' => $regions,
+        'global_avg' => $global_avg
+    ];
+}
+
+/**
+ * 获取各地区产品类别偏好
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 各地区产品类别偏好数据
+ */
+function getRegionCategoryPreferences($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName, 
+                pc.name as category_name,
+                SUM(oi.quantity) as total_quantity
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            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.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country, p.category_id
+            ORDER BY c.countryName, total_quantity DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $preferences = [];
+    $current_country = '';
+    $country_data = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        if ($current_country != $row['countryName']) {
+            if (!empty($current_country)) {
+                $preferences[$current_country] = $country_data;
+            }
+            $current_country = $row['countryName'];
+            $country_data = [];
+        }
+        
+        $country_data[] = [
+            'category' => $row['category_name'],
+            'quantity' => $row['total_quantity']
+        ];
+    }
+    
+    // 添加最后一个国家的数据
+    if (!empty($current_country)) {
+        $preferences[$current_country] = $country_data;
+    }
+    
+    // 只保留前5个主要市场
+    $top_markets = array_slice(array_keys($preferences), 0, 5);
+    $filtered_preferences = [];
+    
+    foreach ($top_markets as $market) {
+        $filtered_preferences[$market] = array_slice($preferences[$market], 0, 5);
+    }
+    
+    return $filtered_preferences;
+}
+
+/**
+ * 获取地区销售增长趋势
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @param string $period 时间粒度 (day/week/month)
+ * @return array 地区销售增长趋势数据
+ */
+function getRegionGrowthTrends($conn, $start_date, $end_date, $period = 'month') {
+    $period_format = getPeriodFormat($period);
+    
+    $sql = "SELECT 
+                c.countryName,
+                DATE_FORMAT(o.order_date, ?) as time_period,
+                SUM(o.total_amount) as total_amount
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date BETWEEN ? AND ?
+            GROUP BY cu.cs_country, time_period
+            ORDER BY c.countryName, time_period";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("sss", $period_format, $start_date, $end_date);
+    $stmt->execute();
+    $result = $stmt->get_result();
+    
+    $trends = [];
+    $time_periods = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        if (!in_array($row['time_period'], $time_periods)) {
+            $time_periods[] = $row['time_period'];
+        }
+        
+        if (!isset($trends[$row['countryName']])) {
+            $trends[$row['countryName']] = [];
+        }
+        
+        $trends[$row['countryName']][$row['time_period']] = $row['total_amount'];
+    }
+    
+    // 只保留前5个主要市场
+    $top_markets = array_slice(array_keys($trends), 0, 5);
+    $filtered_trends = [];
+    
+    foreach ($top_markets as $market) {
+        $filtered_trends[$market] = $trends[$market];
+    }
+    
+    return [
+        'time_periods' => $time_periods,
+        'trends' => $filtered_trends
+    ];
+}
+
+/**
+ * 获取地区季节性销售分析
+ * 
+ * @param mysqli $conn 数据库连接
+ * @return array 地区季节性销售分析数据
+ */
+function getRegionSeasonalAnalysis($conn) {
+    $sql = "SELECT 
+                c.countryName,
+                MONTH(o.order_date) as month,
+                SUM(o.total_amount) as total_amount
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date >= DATE_SUB(CURDATE(), INTERVAL 2 YEAR)
+            GROUP BY cu.cs_country, month
+            ORDER BY c.countryName, month";
+    
+    $result = $conn->query($sql);
+    
+    $seasonal = [];
+    $months = range(1, 12);
+    
+    while ($row = $result->fetch_assoc()) {
+        if (!isset($seasonal[$row['countryName']])) {
+            $seasonal[$row['countryName']] = array_fill(1, 12, 0);
+        }
+        
+        $seasonal[$row['countryName']][$row['month']] += $row['total_amount'];
+    }
+    
+    // 只保留前5个主要市场
+    $top_markets = array_slice(array_keys($seasonal), 0, 5);
+    $filtered_seasonal = [];
+    
+    foreach ($top_markets as $market) {
+        $filtered_seasonal[$market] = array_values($seasonal[$market]);
+    }
+    
+    return [
+        'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+        'data' => $filtered_seasonal
+    ];
+}
+
+/**
+ * 获取地区销售预测数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 地区销售预测数据
+ */
+function getRegionSalesForecast($conn, $start_date, $end_date) {
+    // 获取过去12个月的销售数据作为基础
+    $sql = "SELECT 
+                c.countryName,
+                MONTH(o.order_date) as month,
+                YEAR(o.order_date) as year,
+                SUM(o.total_amount) as total_amount
+            FROM orders o
+            JOIN customer cu ON o.customer_id = cu.id
+            JOIN country c ON cu.cs_country = c.id
+            WHERE o.order_date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
+            GROUP BY cu.cs_country, year, month
+            ORDER BY c.countryName, year, month";
+    
+    $result = $conn->query($sql);
+    
+    $historical = [];
+    
+    while ($row = $result->fetch_assoc()) {
+        $period = $row['year'] . '-' . str_pad($row['month'], 2, '0', STR_PAD_LEFT);
+        
+        if (!isset($historical[$row['countryName']])) {
+            $historical[$row['countryName']] = [];
+        }
+        
+        $historical[$row['countryName']][$period] = $row['total_amount'];
+    }
+    
+    // 生成未来6个月的预测
+    $forecast = [];
+    $periods = [];
+    $current_month = (int)date('m');
+    $current_year = (int)date('Y');
+    
+    // 收集所有历史数据点时间
+    $all_periods = [];
+    foreach ($historical as $country => $data) {
+        foreach (array_keys($data) as $period) {
+            $all_periods[$period] = true;
+        }
+    }
+    $all_periods = array_keys($all_periods);
+    sort($all_periods);
+    
+    // 生成未来6个月的预测点
+    $future_periods = [];
+    for ($i = 1; $i <= 6; $i++) {
+        $forecast_month = ($current_month + $i) % 12;
+        $forecast_month = $forecast_month == 0 ? 12 : $forecast_month;
+        $forecast_year = $current_year + floor(($current_month + $i - 1) / 12);
+        $period = $forecast_year . '-' . str_pad($forecast_month, 2, '0', STR_PAD_LEFT);
+        $future_periods[] = $period;
+    }
+    
+    // 合并历史和预测时间点
+    $all_chart_periods = array_merge($all_periods, $future_periods);
+    
+    // 只选取主要的5个市场做预测
+    $top_markets = array_slice(array_keys($historical), 0, 5);
+    $forecast_data = [];
+    
+    foreach ($top_markets as $market) {
+        $forecast_data[$market] = [];
+        
+        // 为每个市场生成简单的预测
+        // 这里使用简单的线性增长预测
+        // 实际应用中可以采用更复杂的时间序列预测算法
+        
+        // 计算过去几个月的平均增长率
+        $growth_rate = 0.05; // 默认月度增长率为5%
+        
+        if (count($historical[$market]) >= 2) {
+            $values = array_values($historical[$market]);
+            $start_val = array_shift($values);
+            $end_val = array_pop($values);
+            
+            if ($start_val > 0) {
+                $periods_count = count($historical[$market]) - 1;
+                $total_growth = ($end_val / $start_val) - 1;
+                $growth_rate = pow(1 + $total_growth, 1 / $periods_count) - 1;
+                
+                // 限制增长率在合理范围内
+                $growth_rate = max(-0.2, min(0.2, $growth_rate));
+            }
+        }
+        
+        // 对于历史数据,直接使用实际值
+        foreach ($all_periods as $period) {
+            $forecast_data[$market][$period] = [
+                'value' => $historical[$market][$period] ?? null,
+                'is_forecast' => false
+            ];
+        }
+        
+        // 对于预测数据,基于最后一个历史数据点和增长率计算
+        $last_period = end($all_periods);
+        $last_value = $historical[$market][$last_period] ?? array_values($historical[$market])[count($historical[$market])-1];
+        
+        foreach ($future_periods as $i => $period) {
+            $forecast_value = $last_value * pow(1 + $growth_rate, $i + 1);
+            $forecast_data[$market][$period] = [
+                'value' => $forecast_value,
+                'is_forecast' => true
+            ];
+        }
+    }
+    
+    return [
+        'periods' => $all_chart_periods,
+        'forecast' => $forecast_data
+    ];
+}
+
+/**
+ * 渲染平均订单金额分析图表
+ * 
+ * @param array $region_data 地区平均订单金额数据
+ * @return void
+ */
+function renderAverageOrderByRegionChart($region_data) {
+    $region_labels = [];
+    $avg_amounts = [];
+    $order_counts = [];
+    
+    foreach ($region_data as $region) {
+        $region_labels[] = $region['countryName'];
+        $avg_amounts[] = $region['avg_amount'];
+        $order_counts[] = $region['order_count'];
+    }
+    ?>
+    <div class="chart-header">
+        <h2 class="chart-title">地区平均订单金额分析</h2>
+    </div>
+    <canvas id="avgOrderChart"></canvas>
+    
+    <script>
+        // 地区平均订单金额分析图
+        var avgOrderCtx = document.getElementById('avgOrderChart').getContext('2d');
+        var avgOrderChart = new Chart(avgOrderCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($region_labels); ?>,
+                datasets: [
+                    {
+                        label: '平均订单金额',
+                        data: <?php echo json_encode($avg_amounts); ?>,
+                        backgroundColor: 'rgba(75, 192, 192, 0.6)',
+                        borderColor: 'rgba(75, 192, 192, 1)',
+                        borderWidth: 1,
+                        yAxisID: 'y-amount'
+                    },
+                    {
+                        type: 'line',
+                        label: '订单数量',
+                        data: <?php echo json_encode($order_counts); ?>,
+                        backgroundColor: 'rgba(255, 159, 64, 0.6)',
+                        borderColor: 'rgba(255, 159, 64, 1)',
+                        borderWidth: 2,
+                        fill: false,
+                        yAxisID: 'y-count'
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '地区'
+                        }
+                    },
+                    'y-amount': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '平均订单金额'
+                        }
+                    },
+                    'y-count': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        },
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染地区产品类别偏好图表
+ * 
+ * @param array $preferences 地区产品类别偏好数据
+ * @return void
+ */
+function renderRegionCategoryPreferencesChart($preferences) {
+    ?>
+    <div class="chart-header">
+        <h2 class="chart-title">各地区产品类别偏好</h2>
+    </div>
+    
+    <div class="grid-row">
+        <?php foreach ($preferences as $country => $categories): ?>
+            <?php
+            $category_labels = [];
+            $category_data = [];
+            
+            foreach ($categories as $cat) {
+                $category_labels[] = $cat['category'];
+                $category_data[] = $cat['quantity'];
+            }
+            ?>
+            <div class="grid-column">
+                <div class="subchart-container">
+                    <h3 class="subchart-title"><?php echo $country; ?></h3>
+                    <canvas id="categoryChart<?php echo md5($country); ?>"></canvas>
+                </div>
+            </div>
+            
+            <script>
+                // <?php echo $country; ?> 产品类别偏好
+                var categoryCtx<?php echo md5($country); ?> = document.getElementById('categoryChart<?php echo md5($country); ?>').getContext('2d');
+                var categoryChart<?php echo md5($country); ?> = new Chart(categoryCtx<?php echo md5($country); ?>, {
+                    type: 'doughnut',
+                    data: {
+                        labels: <?php echo json_encode($category_labels); ?>,
+                        datasets: [{
+                            data: <?php echo json_encode($category_data); ?>,
+                            backgroundColor: [
+                                'rgba(255, 99, 132, 0.7)',
+                                'rgba(54, 162, 235, 0.7)',
+                                'rgba(255, 206, 86, 0.7)',
+                                'rgba(75, 192, 192, 0.7)',
+                                'rgba(153, 102, 255, 0.7)'
+                            ],
+                            borderWidth: 1
+                        }]
+                    },
+                    options: {
+                        responsive: true,
+                        plugins: {
+                            legend: {
+                                position: 'right',
+                            }
+                        }
+                    }
+                });
+            </script>
+        <?php endforeach; ?>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染地区销售增长趋势图表
+ * 
+ * @param array $growth_data 地区销售增长趋势数据
+ * @return void
+ */
+function renderRegionGrowthTrendsChart($growth_data) {
+    $time_periods = $growth_data['time_periods'];
+    $trends = $growth_data['trends'];
+    
+    $datasets = [];
+    $colors = [
+        ['rgba(255, 99, 132, 0.6)', 'rgba(255, 99, 132, 1)'],
+        ['rgba(54, 162, 235, 0.6)', 'rgba(54, 162, 235, 1)'],
+        ['rgba(255, 206, 86, 0.6)', 'rgba(255, 206, 86, 1)'],
+        ['rgba(75, 192, 192, 0.6)', 'rgba(75, 192, 192, 1)'],
+        ['rgba(153, 102, 255, 0.6)', 'rgba(153, 102, 255, 1)']
+    ];
+    
+    $i = 0;
+    foreach ($trends as $country => $data) {
+        $dataset = [
+            'label' => $country,
+            'data' => [],
+            'backgroundColor' => $colors[$i % count($colors)][0],
+            'borderColor' => $colors[$i % count($colors)][1],
+            'borderWidth' => 2,
+            'fill' => false,
+            'tension' => 0.1
+        ];
+        
+        foreach ($time_periods as $period) {
+            $dataset['data'][] = $data[$period] ?? null;
+        }
+        
+        $datasets[] = $dataset;
+        $i++;
+    }
+    ?>
+    <div class="chart-header">
+        <h2 class="chart-title">地区销售增长趋势</h2>
+    </div>
+    <canvas id="growthTrendsChart"></canvas>
+    
+    <script>
+        // 地区销售增长趋势图
+        var growthTrendsCtx = document.getElementById('growthTrendsChart').getContext('2d');
+        var growthTrendsChart = new Chart(growthTrendsCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($time_periods); ?>,
+                datasets: <?php echo json_encode($datasets); ?>
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '时间段'
+                        }
+                    },
+                    y: {
+                        title: {
+                            display: true,
+                            text: '销售额'
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染地区季节性分析图表
+ * 
+ * @param array $seasonal_data 地区季节性分析数据
+ * @return void
+ */
+function renderRegionSeasonalAnalysisChart($seasonal_data) {
+    $months = $seasonal_data['months'];
+    $data = $seasonal_data['data'];
+    
+    $datasets = [];
+    $colors = [
+        ['rgba(255, 99, 132, 0.6)', 'rgba(255, 99, 132, 1)'],
+        ['rgba(54, 162, 235, 0.6)', 'rgba(54, 162, 235, 1)'],
+        ['rgba(255, 206, 86, 0.6)', 'rgba(255, 206, 86, 1)'],
+        ['rgba(75, 192, 192, 0.6)', 'rgba(75, 192, 192, 1)'],
+        ['rgba(153, 102, 255, 0.6)', 'rgba(153, 102, 255, 1)']
+    ];
+    
+    $i = 0;
+    foreach ($data as $country => $values) {
+        $datasets[] = [
+            'label' => $country,
+            'data' => $values,
+            'backgroundColor' => $colors[$i % count($colors)][0],
+            'borderColor' => $colors[$i % count($colors)][1],
+            'borderWidth' => 2,
+            'fill' => false,
+            'tension' => 0.1
+        ];
+        $i++;
+    }
+    ?>
+    <div class="chart-header">
+        <h2 class="chart-title">地区季节性销售分析</h2>
+    </div>
+    <canvas id="seasonalAnalysisChart"></canvas>
+    
+    <script>
+        // 地区季节性销售分析图
+        var seasonalCtx = document.getElementById('seasonalAnalysisChart').getContext('2d');
+        var seasonalChart = new Chart(seasonalCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($months); ?>,
+                datasets: <?php echo json_encode($datasets); ?>
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '月份'
+                        }
+                    },
+                    y: {
+                        title: {
+                            display: true,
+                            text: '销售额'
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染地区销售预测图表
+ * 
+ * @param array $forecast_data 地区销售预测数据
+ * @return void
+ */
+function renderRegionSalesForecastChart($forecast_data) {
+    $periods = $forecast_data['periods'];
+    $forecast = $forecast_data['forecast'];
+    
+    $datasets = [];
+    $colors = [
+        ['rgba(255, 99, 132, 0.6)', 'rgba(255, 99, 132, 1)'],
+        ['rgba(54, 162, 235, 0.6)', 'rgba(54, 162, 235, 1)'],
+        ['rgba(255, 206, 86, 0.6)', 'rgba(255, 206, 86, 1)'],
+        ['rgba(75, 192, 192, 0.6)', 'rgba(75, 192, 192, 1)'],
+        ['rgba(153, 102, 255, 0.6)', 'rgba(153, 102, 255, 1)']
+    ];
+    
+    $i = 0;
+    foreach ($forecast as $country => $data) {
+        $historical_data = [];
+        $forecast_data = [];
+        
+        foreach ($periods as $period) {
+            if (isset($data[$period])) {
+                if ($data[$period]['is_forecast']) {
+                    $historical_data[] = null;
+                    $forecast_data[] = $data[$period]['value'];
+                } else {
+                    $historical_data[] = $data[$period]['value'];
+                    $forecast_data[] = null;
+                }
+            } else {
+                $historical_data[] = null;
+                $forecast_data[] = null;
+            }
+        }
+        
+        $datasets[] = [
+            'label' => $country . ' (历史)',
+            'data' => $historical_data,
+            'backgroundColor' => $colors[$i % count($colors)][0],
+            'borderColor' => $colors[$i % count($colors)][1],
+            'borderWidth' => 2,
+            'fill' => false
+        ];
+        
+        $datasets[] = [
+            'label' => $country . ' (预测)',
+            'data' => $forecast_data,
+            'backgroundColor' => $colors[$i % count($colors)][0],
+            'borderColor' => $colors[$i % count($colors)][1],
+            'borderWidth' => 2,
+            'borderDash' => [5, 5],
+            'fill' => false
+        ];
+        
+        $i++;
+    }
+    ?>
+    <div class="chart-header">
+        <h2 class="chart-title">地区销售预测 (未来6个月)</h2>
+    </div>
+    <canvas id="forecastChart"></canvas>
+    
+    <script>
+        // 地区销售预测图
+        var forecastCtx = document.getElementById('forecastChart').getContext('2d');
+        var forecastChart = new Chart(forecastCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($periods); ?>,
+                datasets: <?php echo json_encode($datasets); ?>
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '时间段'
+                        }
+                    },
+                    y: {
+                        title: {
+                            display: true,
+                            text: '销售额'
+                        }
+                    }
+                },
+                plugins: {
+                    tooltip: {
+                        callbacks: {
+                            title: function(tooltipItems) {
+                                return tooltipItems[0].label;
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染热门地区表格
+ * 
+ * @param array $region_labels 地区标签
+ * @param array $region_order_counts 地区订单数量
+ * @param array $region_quantities 地区产品数量
+ * @param array $region_amounts 地区销售金额
+ * @return void
+ */
+function renderTopRegionsTable($region_labels, $region_order_counts, $region_quantities, $region_amounts) {
+    ?>
+    <table class="data-table">
+        <thead>
+            <tr>
+                <th>排名</th>
+                <th>国家/地区</th>
+                <th>订单数</th>
+                <th>产品数量</th>
+                <th>销售金额</th>
+                <th>平均订单金额</th>
+            </tr>
+        </thead>
+        <tbody>
+            <?php for ($i = 0; $i < count($region_labels); $i++): ?>
+                <tr>
+                    <td><?php echo $i + 1; ?></td>
+                    <td><?php echo htmlspecialchars($region_labels[$i]); ?></td>
+                    <td><?php echo number_format($region_order_counts[$i]); ?></td>
+                    <td><?php echo number_format($region_quantities[$i]); ?></td>
+                    <td>¥<?php echo number_format($region_amounts[$i], 2); ?></td>
+                    <td>¥<?php echo number_format($region_order_counts[$i] > 0 ? $region_amounts[$i] / $region_order_counts[$i] : 0, 2); ?></td>
+                </tr>
+            <?php endfor; ?>
+        </tbody>
+    </table>
+    <?php
+} 

+ 1176 - 0
statistics_sales.php

@@ -0,0 +1,1176 @@
+<?php
+/**
+ * 销售统计分析模块
+ * 
+ * 包含与销售相关的数据分析功能
+ */
+
+require_once 'statistics_utils.php';
+
+/**
+ * 获取销售概览数据
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return array 销售概览数据
+ */
+function getSalesOverview($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                COUNT(DISTINCT o.id) as total_orders,
+                SUM(o.total_amount) as total_revenue,
+                AVG(o.total_amount) as avg_order_value,
+                COUNT(DISTINCT o.customer_id) as unique_customers,
+                SUM(oi.quantity) as total_items_sold
+            FROM orders o
+            LEFT JOIN order_items oi ON o.id = oi.order_id 
+            WHERE o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0"; // 排除已取消订单
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result()->fetch_assoc();
+}
+
+/**
+ * 获取订单转化率统计
+ */
+function getOrderConversionStats($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                order_status,
+                COUNT(*) as count,
+                SUM(total_amount) as amount
+            FROM orders 
+            WHERE order_date BETWEEN ? AND ?
+            GROUP BY order_status";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取产品类别销售统计
+ */
+function getProductCategorySales($conn, $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.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("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取客户地区分布
+ */
+function getCustomerDistribution($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                c.countryName as region,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                COUNT(o.id) as order_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.order_date BETWEEN ? AND ?
+            AND o.order_status != 0
+            GROUP BY c.id
+            ORDER BY total_revenue DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取销售员业绩统计
+ */
+function getEmployeePerformance($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                e.em_user as employee_name,
+                COUNT(DISTINCT o.id) as order_count,
+                COUNT(DISTINCT o.customer_id) as customer_count,
+                SUM(o.total_amount) as total_revenue,
+                AVG(o.total_amount) as avg_order_value
+            FROM orders o
+            JOIN employee e ON o.employee_id = e.id
+            WHERE o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0
+            GROUP BY e.id
+            ORDER BY total_revenue DESC";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取支付状态统计
+ */
+function getPaymentStatusStats($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                payment_status,
+                COUNT(*) as count,
+                SUM(total_amount) as amount
+            FROM orders 
+            WHERE order_date BETWEEN ? AND ?
+            AND order_status != 0
+            GROUP BY payment_status";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取每月销售趋势
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @return mysqli_result 月度销售数据结果集
+ */
+function getMonthlySalesTrend($conn, $start_date, $end_date) {
+    $sql = "SELECT 
+                DATE_FORMAT(order_date, '%Y-%m') as month,
+                COUNT(DISTINCT id) as orders,
+                SUM(total_amount) as revenue,
+                COUNT(DISTINCT customer_id) as unique_customers
+            FROM orders 
+            WHERE order_date BETWEEN ? AND ?
+            AND order_status != 0
+            GROUP BY DATE_FORMAT(order_date, '%Y-%m')
+            ORDER BY month";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 获取详细时间段订单趋势
+ * 
+ * @param mysqli $conn 数据库连接
+ * @param string $start_date 开始日期
+ * @param string $end_date 结束日期
+ * @param string $period 时间粒度 (day/week/month)
+ * @return mysqli_result 订单趋势数据结果集
+ */
+function getDetailedOrderTrend($conn, $start_date, $end_date, $period = 'day') {
+    $groupFormat = '%Y-%m-%d';
+    
+    if ($period == 'week') {
+        $groupFormat = '%x-W%v';
+    } else if ($period == 'month') {
+        $groupFormat = '%Y-%m';
+    }
+    
+    $sql = "SELECT 
+                DATE_FORMAT(o.order_date, '$groupFormat') as time_period,
+                COUNT(DISTINCT o.id) as order_count,
+                SUM(oi.quantity) as total_quantity,
+                SUM(o.total_amount) as total_amount,
+                COUNT(DISTINCT o.customer_id) as unique_customers
+            FROM orders o
+            LEFT JOIN order_items oi ON o.id = oi.order_id
+            WHERE o.order_date BETWEEN ? AND ?
+            AND o.order_status != 0
+            GROUP BY time_period
+            ORDER BY MIN(o.order_date)";
+    
+    $stmt = $conn->prepare($sql);
+    $stmt->bind_param("ss", $start_date, $end_date);
+    $stmt->execute();
+    return $stmt->get_result();
+}
+
+/**
+ * 渲染销售概览卡片
+ * 
+ * @param array $sales_overview 销售概览数据
+ * @return void
+ */
+function renderSalesOverviewCards($sales_overview) {
+    // 添加空值检查函数
+
+    
+
+    ?>
+    <div class="stats-grid">
+        <div class="stat-card">
+            <h3>总订单数</h3>
+            <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 formatCurrency($sales_overview['total_revenue']); ?></div>
+        </div>
+        
+        <div class="stat-card">
+            <h3>平均订单金额</h3>
+            <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 formatNumber($sales_overview['unique_customers']); ?></div>
+        </div>
+
+        <div class="stat-card">
+            <h3>总销售数量</h3>
+            <div class="stat-value"><?php echo formatNumber($sales_overview['total_items_sold']); ?></div>
+        </div>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染订单转化率分析
+ */
+function renderConversionAnalysis($conversion_stats) {
+    // 添加空值检查函数
+
+    
+
+
+    $status_names = [
+        1 => '待确认',
+        2 => '已确认',
+        3 => '生产中',
+        4 => '已发货',
+        5 => '已完成',
+        0 => '已取消'
+    ];
+    
+    $total_orders = 0;
+    $data = [];
+    while ($row = $conversion_stats->fetch_assoc()) {
+        $total_orders += $row['count'];
+        $data[$row['order_status']] = $row;
+    }
+    ?>
+    <div class="analysis-grid">
+        <div>
+            <canvas id="orderStatusChart"></canvas>
+        </div>
+        <div class="table-responsive">
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>订单状态</th>
+                        <th>订单数</th>
+                        <th>转化率</th>
+                        <th>金额</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php foreach ($status_names as $status_id => $status_name): ?>
+                        <?php if (isset($data[$status_id])): ?>
+                        <tr>
+                            <td><?php echo $status_name; ?></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; ?>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    <script>
+        var orderStatusCtx = document.getElementById('orderStatusChart').getContext('2d');
+        new Chart(orderStatusCtx, {
+            type: 'doughnut',
+            data: {
+                labels: <?php 
+                    $labels = [];
+                    $values = [];
+                    foreach ($status_names as $status_id => $status_name) {
+                        if (isset($data[$status_id])) {
+                            $labels[] = $status_name;
+                            $values[] = $data[$status_id]['count'];
+                        }
+                    }
+                    echo json_encode($labels);
+                ?>,
+                datasets: [{
+                    data: <?php echo json_encode($values); ?>,
+                    backgroundColor: [
+                        '#FF6384',
+                        '#36A2EB',
+                        '#FFCE56',
+                        '#4BC0C0',
+                        '#9966FF',
+                        '#FF9F40'
+                    ]
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right'
+                    },
+                    title: {
+                        display: true,
+                        text: '订单状态分布'
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染产品类别销售分析图表
+ */
+function renderCategorySalesChart($category_sales) {
+    $labels = [];
+    $quantities = [];
+    $revenues = [];
+    
+    while ($row = $category_sales->fetch_assoc()) {
+        $labels[] = $row['category_name'];
+        $quantities[] = $row['total_quantity'];
+        $revenues[] = $row['total_revenue'];
+    }
+    ?>
+    <div class="analysis-grid">
+        <div>
+            <canvas id="categorySalesChart"></canvas>
+        </div>
+        <div class="table-responsive">
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>产品类别</th>
+                        <th>订单数</th>
+                        <th>销售数量</th>
+                        <th>销售金额</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php
+                    $category_sales->data_seek(0);
+                    while ($row = $category_sales->fetch_assoc()):
+                    ?>
+                    <tr>
+                        <td><?php echo $row['category_name']; ?></td>
+                        <td><?php echo number_format($row['order_count']); ?></td>
+                        <td><?php echo number_format($row['total_quantity']); ?></td>
+                        <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
+                    </tr>
+                    <?php endwhile; ?>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    <script>
+        var categorySalesCtx = document.getElementById('categorySalesChart').getContext('2d');
+        new Chart(categorySalesCtx, {
+            type: 'bar',
+            data: {
+                labels: <?php echo json_encode($labels); ?>,
+                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 renderCustomerDistributionChart($customer_distribution) {
+    $regions = [];
+    $customers = [];
+    $revenues = [];
+    
+    while ($row = $customer_distribution->fetch_assoc()) {
+        $regions[] = $row['region'];
+        $customers[] = $row['customer_count'];
+        $revenues[] = $row['total_revenue'];
+    }
+    ?>
+    <div class="analysis-grid">
+        <div>
+            <canvas id="regionDistributionChart"></canvas>
+        </div>
+        <div class="table-responsive">
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>地区</th>
+                        <th>客户数</th>
+                        <th>订单数</th>
+                        <th>销售金额</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php
+                    $customer_distribution->data_seek(0);
+                    while ($row = $customer_distribution->fetch_assoc()):
+                    ?>
+                    <tr>
+                        <td><?php echo $row['region']; ?></td>
+                        <td><?php echo number_format($row['customer_count']); ?></td>
+                        <td><?php echo number_format($row['order_count']); ?></td>
+                        <td>¥<?php echo number_format($row['total_revenue'], 2); ?></td>
+                    </tr>
+                    <?php endwhile; ?>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    <script>
+        var regionDistributionCtx = document.getElementById('regionDistributionChart').getContext('2d');
+        new Chart(regionDistributionCtx, {
+            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 renderEmployeePerformanceTable($employee_performance) {
+    // 添加空值检查函数
+
+
+    ?>
+    <div class="table-responsive">
+        <table class="data-table">
+            <thead>
+                <tr>
+                    <th>销售员</th>
+                    <th>订单数</th>
+                    <th>客户数</th>
+                    <th>总销售额</th>
+                    <th>平均订单金额</th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php while ($row = $employee_performance->fetch_assoc()): ?>
+                <tr>
+                    <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>
+        </table>
+    </div>
+    <?php
+}
+
+/**
+ * 渲染支付状态分析图表
+ */
+function renderPaymentStatusChart($payment_stats) {
+    $status_names = [
+        0 => '未付款',
+        1 => '部分付款',
+        2 => '已付清'
+    ];
+    
+    $data = [];
+    while ($row = $payment_stats->fetch_assoc()) {
+        $data[$row['payment_status']] = $row;
+    }
+    ?>
+    <div class="analysis-grid">
+        <div>
+            <canvas id="paymentStatusChart"></canvas>
+        </div>
+        <div class="table-responsive">
+            <table class="data-table">
+                <thead>
+                    <tr>
+                        <th>支付状态</th>
+                        <th>订单数</th>
+                        <th>订单金额</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <?php foreach ($status_names as $status_id => $status_name): ?>
+                        <?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]['amount'], 2); ?></td>
+                        </tr>
+                        <?php endif; ?>
+                    <?php endforeach; ?>
+                </tbody>
+            </table>
+        </div>
+    </div>
+    <script>
+        var paymentStatusCtx = document.getElementById('paymentStatusChart').getContext('2d');
+        new Chart(paymentStatusCtx, {
+            type: 'pie',
+            data: {
+                labels: <?php 
+                    $labels = [];
+                    $values = [];
+                    foreach ($status_names as $status_id => $status_name) {
+                        if (isset($data[$status_id])) {
+                            $labels[] = $status_name;
+                            $values[] = $data[$status_id]['amount'];
+                        }
+                    }
+                    echo json_encode($labels);
+                ?>,
+                datasets: [{
+                    data: <?php echo json_encode($values); ?>,
+                    backgroundColor: [
+                        '#FF6384',
+                        '#36A2EB',
+                        '#4BC0C0'
+                    ]
+                }]
+            },
+            options: {
+                responsive: true,
+                plugins: {
+                    legend: {
+                        position: 'right'
+                    },
+                    title: {
+                        display: true,
+                        text: '支付状态分布'
+                    }
+                }
+            }
+        });
+    </script>
+    <?php
+}
+
+/**
+ * 渲染月度销售趋势图
+ * 
+ * @param array $monthly_labels 月份标签
+ * @param array $monthly_orders 月度订单数量
+ * @param array $monthly_revenue 月度收入
+ * @return void
+ */
+function renderMonthlySalesTrendChart($monthly_labels, $monthly_orders, $monthly_revenue) {
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">销售趋势</h2>
+        </div>
+        <canvas id="salesTrendChart"></canvas>
+    </div>
+    
+    <script>
+        var salesTrendCtx = document.getElementById('salesTrendChart').getContext('2d');
+        new Chart(salesTrendCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($monthly_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($monthly_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($monthly_revenue); ?>,
+                        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
+}
+
+/**
+ * 渲染详细订单趋势图
+ * 
+ * @param array $time_labels 时间标签
+ * @param array $time_orders 时间段订单数量
+ * @param array $time_quantities 时间段产品数量
+ * @param string $period 时间粒度
+ * @return void
+ */
+function renderDetailedOrderTrendChart($time_labels, $time_orders, $time_quantities, $period = 'day') {
+    $period_text = $period == 'day' ? '日' : ($period == 'week' ? '周' : '月');
+    ?>
+    <div class="chart-container">
+        <div class="chart-header">
+            <h2 class="chart-title">详细订单趋势 (<?php echo $period_text; ?>)</h2>
+        </div>
+        <canvas id="detailedOrdersChart"></canvas>
+    </div>
+    
+    <script>
+        var detailedOrdersCtx = document.getElementById('detailedOrdersChart').getContext('2d');
+        new Chart(detailedOrdersCtx, {
+            type: 'line',
+            data: {
+                labels: <?php echo json_encode($time_labels); ?>,
+                datasets: [
+                    {
+                        label: '订单数量',
+                        data: <?php echo json_encode($time_orders); ?>,
+                        backgroundColor: 'rgba(75, 192, 192, 0.2)',
+                        borderColor: 'rgba(75, 192, 192, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-orders',
+                        tension: 0.1
+                    },
+                    {
+                        label: '产品订购数量',
+                        data: <?php echo json_encode($time_quantities); ?>,
+                        backgroundColor: 'rgba(255, 159, 64, 0.2)',
+                        borderColor: 'rgba(255, 159, 64, 1)',
+                        borderWidth: 2,
+                        yAxisID: 'y-quantity',
+                        tension: 0.1
+                    }
+                ]
+            },
+            options: {
+                responsive: true,
+                scales: {
+                    x: {
+                        title: {
+                            display: true,
+                            text: '时间'
+                        }
+                    },
+                    'y-orders': {
+                        type: 'linear',
+                        position: 'left',
+                        title: {
+                            display: true,
+                            text: '订单数量'
+                        },
+                        beginAtZero: true
+                    },
+                    'y-quantity': {
+                        type: 'linear',
+                        position: 'right',
+                        title: {
+                            display: true,
+                            text: '产品订购数量'
+                        },
+                        beginAtZero: true,
+                        grid: {
+                            drawOnChartArea: false
+                        }
+                    }
+                }
+            }
+        });
+    </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
+} 

+ 150 - 0
statistics_utils.php

@@ -0,0 +1,150 @@
+<?php
+/**
+ * 统计分析工具函数
+ * 
+ * 包含所有统计模块共用的工具函数和日期处理逻辑
+ */
+
+// 确保直接访问时需要先登录
+require_once 'conn.php';
+
+if (!isset($_SESSION['employee_id'])) {
+    checkLogin();
+}
+
+//检查是否管理员
+checkAdmin();
+
+/**
+ * 获取和处理日期范围参数
+ * 
+ * @return array 包含开始日期、结束日期和其他日期相关参数
+ */
+function getDateRangeParams() {
+    // 计算日期范围
+    $current_month_start = date('Y-m-01');
+    $current_month_end = date('Y-m-t');
+    $last_month_start = date('Y-m-01', strtotime('-1 month'));
+    $last_month_end = date('Y-m-t', strtotime('-1 month'));
+    $current_year_start = date('Y-01-01');
+    $current_year_end = date('Y-12-31');
+
+    // 可选的日期范围筛选
+    $date_range = isset($_GET['date_range']) ? $_GET['date_range'] : 'current_month';
+    $custom_start = isset($_GET['start_date']) ? $_GET['start_date'] : '';
+    $custom_end = isset($_GET['end_date']) ? $_GET['end_date'] : '';
+    $period = isset($_GET['period']) ? $_GET['period'] : 'day';
+
+    // 设置日期范围
+    if ($date_range == 'custom' && !empty($custom_start) && !empty($custom_end)) {
+        $start_date = $custom_start;
+        $end_date = $custom_end;
+    } else {
+        switch ($date_range) {
+            case 'last_month':
+                $start_date = $last_month_start;
+                $end_date = $last_month_end;
+                break;
+            case 'current_year':
+                $start_date = $current_year_start;
+                $end_date = $current_year_end;
+                break;
+            case 'last_30_days':
+                $start_date = date('Y-m-d', strtotime('-30 days'));
+                $end_date = date('Y-m-d');
+                break;
+            case 'last_90_days':
+                $start_date = date('Y-m-d', strtotime('-90 days'));
+                $end_date = date('Y-m-d');
+                break;
+            case 'current_month':
+            default:
+                $start_date = $current_month_start;
+                $end_date = $current_month_end;
+                break;
+        }
+    }
+
+    // 格式化日期用于SQL查询
+    $start_date_sql = date('Y-m-d', strtotime($start_date));
+    $end_date_sql = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
+
+    return [
+        'date_range' => $date_range,
+        'custom_start' => $custom_start,
+        'custom_end' => $custom_end,
+        'period' => $period,
+        'start_date' => $start_date,
+        'end_date' => $end_date,
+        'start_date_sql' => $start_date_sql,
+        'end_date_sql' => $end_date_sql
+    ];
+}
+
+/**
+ * 生成图表颜色数组
+ * 
+ * @param int $count 需要的颜色数量
+ * @param bool $transparent 是否透明
+ * @return array 背景色和边框色数组
+ */
+function generateChartColors($count = 10, $transparent = true) {
+    $colors = [
+        ['rgba(255, 99, 132, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(255, 99, 132, 1)'],
+        ['rgba(54, 162, 235, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(54, 162, 235, 1)'],
+        ['rgba(255, 206, 86, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(255, 206, 86, 1)'],
+        ['rgba(75, 192, 192, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(75, 192, 192, 1)'],
+        ['rgba(153, 102, 255, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(153, 102, 255, 1)'],
+        ['rgba(255, 159, 64, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(255, 159, 64, 1)'],
+        ['rgba(199, 199, 199, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(199, 199, 199, 1)'],
+        ['rgba(83, 102, 255, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(83, 102, 255, 1)'],
+        ['rgba(40, 159, 64, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(40, 159, 64, 1)'],
+        ['rgba(210, 199, 199, ' . ($transparent ? '0.7' : '1') . ')', 'rgba(210, 199, 199, 1)']
+    ];
+    
+    $result = [];
+    
+    // 确保有足够的颜色
+    while (count($result) < $count) {
+        foreach ($colors as $color) {
+            $result[] = $color;
+            if (count($result) >= $count) {
+                break;
+            }
+        }
+    }
+    
+    return array_slice($result, 0, $count);
+}
+
+/**
+ * 格式化数值,处理空值和小数位数
+ * 
+ * @param mixed $value 要格式化的值
+ * @param int $decimals 小数位数
+ * @return string 格式化后的数值
+ */
+function formatNumber($value, $decimals = 2) {
+    if ($value === null || $value === '') {
+        return '0';
+    }
+    return number_format((float)$value, $decimals);
+}
+
+/**
+ * 获取时间粒度对应的MySQL DATE_FORMAT格式
+ * 
+ * @param string $period 时间粒度 (day/week/month)
+ * @return string MySQL DATE_FORMAT格式字符串
+ */
+function getPeriodFormat($period) {
+    switch ($period) {
+        case 'week':
+            return '%x-W%v'; // ISO year and week number
+        case 'month':
+            return '%Y-%m';
+        case 'day':
+        default:
+            return '%Y-%m-%d';
+    }
+} 

+ 142 - 35
subCustomers.php

@@ -46,34 +46,34 @@ $filterStr = "";
 $urlStr = "";
 
 if (!empty($filterCountry)) {
-    $filterStr .= " AND cs_country=" . (int)$filterCountry;
+    $filterStr .= " AND c.cs_country=" . (int)$filterCountry;
     $urlStr .= "&fliterCountry=" . $filterCountry;
 }
 
 if (!empty($filterQudao)) {
-    $filterStr .= " AND cs_from=" . (int)$filterQudao;
+    $filterStr .= " AND c.cs_from=" . (int)$filterQudao;
     $urlStr .= "&fliterQudao=" . $filterQudao;
 }
 
 if (!empty($filterDeal)) {
-    $filterStr .= " AND cs_deal=" . (int)$filterDeal;
+    $filterStr .= " AND c.cs_deal=" . (int)$filterDeal;
     $urlStr .= "&fliterDeal=" . $filterDeal;
 }
 
 if (!empty($filterBusiness)) {
-    $filterStr .= " AND cs_type=" . (int)$filterBusiness;
+    $filterStr .= " AND c.cs_type=" . (int)$filterBusiness;
     $urlStr .= "&fliterBusiness=" . $filterBusiness;
 }
 
 if (!empty($filterContact)) {
     switch ($filterContact) {
-        case "1": $filterStr .= " AND cs_tel<>''"; break;
-        case "2": $filterStr .= " AND cs_wechat<>''"; break;
-        case "3": $filterStr .= " AND cs_whatsapp<>''"; break;
-        case "4": $filterStr .= " AND cs_email<>''"; break;
-        case "5": $filterStr .= " AND cs_linkedin<>''"; break;
-        case "6": $filterStr .= " AND cs_facebook<>''"; break;
-        default: $filterStr .= " AND cs_alibaba<>''";
+        case "1": $filterStr .= " AND (cc.tel_1 != '' OR cc.tel_2 != '' OR cc.tel_3 != '')"; break;
+        case "2": $filterStr .= " AND (cc.wechat_1 != '' OR cc.wechat_2 != '' OR cc.wechat_3 != '')"; break;
+        case "3": $filterStr .= " AND (cc.whatsapp_1 != '' OR cc.whatsapp_2 != '' OR cc.whatsapp_3 != '')"; break;
+        case "4": $filterStr .= " AND (cc.email_1 != '' OR cc.email_2 != '' OR cc.email_3 != '')"; break;
+        case "5": $filterStr .= " AND (cc.linkedin_1 != '' OR cc.linkedin_2 != '' OR cc.linkedin_3 != '')"; break;
+        case "6": $filterStr .= " AND (cc.facebook_1 != '' OR cc.facebook_2 != '' OR cc.facebook_3 != '')"; break;
+        case "7": $filterStr .= " AND (cc.alibaba_1 != '' OR cc.alibaba_2 != '' OR cc.alibaba_3 != '')"; break;
     }
     $urlStr .= "&fliterContact=" . $filterContact;
 }
@@ -170,13 +170,10 @@ $hrefstr = "?keys=" . $keys;
                 </select>
             </div>
             <div class="inputSearch">
-                <input type="text" id="keys" class="inputTxt" 
-                       value="<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>" 
-                       onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>'){this.value='';}" 
-                       onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode) ?>';}" 
-                       onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+                <input type="text" id="keys" class="inputTxt" placeholder="请输入搜索关键词"
+                       value="<?= empty($keyscode) ? '' : htmlspecialcharsFix($keyscode) ?>"/>
                 <input type="button" id="searchgo" class="searchgo" value="go" 
-                       onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                       onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
             </div>
         </div>
 
@@ -194,17 +191,57 @@ $hrefstr = "?keys=" . $keys;
             </div>
 
 <?php
-$sqlStr = "SELECT id, cs_code, cs_from, cs_country, cs_type, cs_deal, cs_addtime, cs_tel, cs_email, 
-           cs_whatsapp, cs_wechat, cs_linkedin, cs_facebook, cs_alibaba, cs_belong, cs_note, cs_claimFrom 
-           FROM customer 
-           WHERE (cs_code LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
-           OR cs_name LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
-           OR cs_email LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
-           OR cs_wechat LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
-           OR cs_tel LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
-           OR cs_whatsapp LIKE '%" . $conn->real_escape_string($keyscode) . "%') 
-           AND cs_belong IN (SELECT id FROM employee WHERE em_role=" . $_SESSION['employee_id'] . ")" . 
-           $filterStr . " ORDER BY cs_state DESC, id DESC";
+$sqlStr = "SELECT c.id, c.cs_code, c.cs_from, c.cs_country, c.cs_type, c.cs_deal, c.cs_addtime, c.cs_belong, 
+           c.cs_note, c.cs_claimFrom, 
+           cc.id as contact_id, cc.contact_name,
+           cc.tel_1, cc.tel_1_format, cc.tel_1_bu,
+           cc.tel_2, cc.tel_2_format, cc.tel_2_bu,
+           cc.tel_3, cc.tel_3_format, cc.tel_3_bu,
+           cc.email_1, cc.email_1_bu,
+           cc.email_2, cc.email_2_bu,
+           cc.email_3, cc.email_3_bu,
+           cc.whatsapp_1, cc.whatsapp_1_format, cc.whatsapp_1_bu,
+           cc.whatsapp_2, cc.whatsapp_2_format, cc.whatsapp_2_bu,
+           cc.whatsapp_3, cc.whatsapp_3_format, cc.whatsapp_3_bu,
+           cc.wechat_1, cc.wechat_1_bu,
+           cc.wechat_2, cc.wechat_2_bu,
+           cc.wechat_3, cc.wechat_3_bu,
+           cc.linkedin_1, cc.linkedin_1_bu,
+           cc.linkedin_2, cc.linkedin_2_bu,
+           cc.linkedin_3, cc.linkedin_3_bu,
+           cc.facebook_1, cc.facebook_1_bu,
+           cc.facebook_2, cc.facebook_2_bu,
+           cc.facebook_3, cc.facebook_3_bu,
+           cc.alibaba_1, cc.alibaba_1_bu,
+           cc.alibaba_2, cc.alibaba_2_bu,
+           cc.alibaba_3, cc.alibaba_3_bu
+           FROM customer c 
+           LEFT JOIN customer_contact cc ON c.id = cc.customer_id
+           WHERE (c.cs_code LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
+           OR cc.contact_name LIKE '%" . $conn->real_escape_string($keyscode) . "%' 
+           OR cc.tel_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.tel_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.tel_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.email_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.email_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.email_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.wechat_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.wechat_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.wechat_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.whatsapp_1_format LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.whatsapp_2_format LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.whatsapp_3_format LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.linkedin_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.linkedin_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.linkedin_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.facebook_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.facebook_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.facebook_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.alibaba_1 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.alibaba_2 LIKE '%" . $conn->real_escape_string($keyscode) . "%'
+           OR cc.alibaba_3 LIKE '%" . $conn->real_escape_string($keyscode) . "%') 
+           AND c.cs_belong IN (SELECT id FROM employee WHERE em_role=" . $_SESSION['employee_id'] . ")" . 
+           $filterStr . " ORDER BY c.cs_state DESC, c.id DESC";
 
 $result = $conn->query($sqlStr);
 
@@ -279,13 +316,83 @@ if ($result && $result->num_rows > 0) {
         <div class="notepanel clear">
             <div class="noteItem">联系方式</div>
             <div class="lx">
-                <div class="tel"><?= htmlspecialcharsFix($row['cs_tel']) ?></div>
-                <div class="mail"><a href="mailto:<?= htmlspecialcharsFix($row['cs_email']) ?>"><?= htmlspecialcharsFix($row['cs_email']) ?></a></div>
-                <div class="whatsapp"><?= htmlspecialcharsFix($row['cs_whatsapp']) ?></div>
-                <div class="wechat"><?= htmlspecialcharsFix($row['cs_wechat']) ?></div>
-                <div class="linkedin"><?= htmlspecialcharsFix($row['cs_linkedin']) ?></div>
-                <div class="facebook"><?= htmlspecialcharsFix($row['cs_facebook']) ?></div>
-                <div class="alibaba"><?= htmlspecialcharsFix($row['cs_alibaba']) ?></div>
+                <div class="tel">
+                    <?php if(!empty($row['tel_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['tel_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['tel_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['tel_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['tel_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['tel_3']) ?></div>
+                    <?php endif; ?>
+                </div>
+                <div class="mail">
+                    <?php if(!empty($row['email_1'])): ?>
+                        <div><a href="mailto:<?= htmlspecialcharsFix($row['email_1']) ?>"><?= htmlspecialcharsFix($row['email_1']) ?></a></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['email_2'])): ?>
+                        <div><a href="mailto:<?= htmlspecialcharsFix($row['email_2']) ?>"><?= htmlspecialcharsFix($row['email_2']) ?></a></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['email_3'])): ?>
+                        <div><a href="mailto:<?= htmlspecialcharsFix($row['email_3']) ?>"><?= htmlspecialcharsFix($row['email_3']) ?></a></div>
+                    <?php endif; ?>
+                </div>
+                <div class="whatsapp">
+                    <?php if(!empty($row['whatsapp_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['whatsapp_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['whatsapp_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['whatsapp_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['whatsapp_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['whatsapp_3']) ?></div>
+                    <?php endif; ?>
+                </div>
+                <div class="wechat">
+                    <?php if(!empty($row['wechat_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['wechat_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['wechat_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['wechat_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['wechat_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['wechat_3']) ?></div>
+                    <?php endif; ?>
+                </div>
+                <div class="linkedin">
+                    <?php if(!empty($row['linkedin_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['linkedin_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['linkedin_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['linkedin_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['linkedin_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['linkedin_3']) ?></div>
+                    <?php endif; ?>
+                </div>
+                <div class="facebook">
+                    <?php if(!empty($row['facebook_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['facebook_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['facebook_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['facebook_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['facebook_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['facebook_3']) ?></div>
+                    <?php endif; ?>
+                </div>
+                <div class="alibaba">
+                    <?php if(!empty($row['alibaba_1'])): ?>
+                        <div><?= htmlspecialcharsFix($row['alibaba_1']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['alibaba_2'])): ?>
+                        <div><?= htmlspecialcharsFix($row['alibaba_2']) ?></div>
+                    <?php endif; ?>
+                    <?php if(!empty($row['alibaba_3'])): ?>
+                        <div><?= htmlspecialcharsFix($row['alibaba_3']) ?></div>
+                    <?php endif; ?>
+                </div>
             </div>
             <div class="noteItem2">备注</div>
             <div class="notecontent"><?= htmlUnCode($row['cs_note']) ?></div>

+ 186 - 14
subTag.php

@@ -1,6 +1,19 @@
 <?php
 require_once 'conn.php';
 checkLogin();
+
+// 获取URL参数
+$tagName = $_GET['tagName'] ?? '';
+$employeeId = $_GET['employeeId'] ?? 0;
+
+if (empty($employeeId) || !is_numeric($employeeId)) {
+    $employeeId = 0;
+}
+
+if (empty($tagName)) {
+    header('Location: customers.php');
+    exit;
+}
 ?>
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
@@ -25,26 +38,185 @@ checkLogin();
 <body class="clear">
 <?php // require_once 'panel.php'; ?>
 <div id="man_zone">
-    <?php
-    $result = $conn->query("SELECT id, em_user FROM employee WHERE em_role=" . $_SESSION['employee_id']);
-    while ($row = $result->fetch_assoc()) {
-    ?>
-    <div class="tagclound">
-        <h1 class="tagCloundHead2"><?= htmlspecialcharsFix($row['em_user']) ?>的客户画像:</h1>
-        <div class="tagArea">
+    <div class="fastSelect clear">
+        <h1>标签:<?= htmlspecialcharsFix($tagName) ?></h1>
+    </div>
+
+    <div width="100%" border="0" cellpadding="3" cellspacing="1" class="table2">
+        <div class="theader">
+            <div class="col2">序号</div>
+            <div class="col3">客户编号</div>
+            <div class="col4">渠道来源</div>
+            <div class="col5">区域</div>
+            <div class="col6">客户类型</div>
+            <div class="col7">跟进阶段</div>
+            <div class="col8">录入时间</div>
+            <div class="col10">操作</div>
+        </div>
+
         <?php
-        $tagResult = $conn->query("SELECT tagName, COUNT(id) as count FROM tagtable WHERE employeeId=" . (int)$row['id'] . " GROUP BY tagName");
-        while ($tagRow = $tagResult->fetch_assoc()) {
+        // 组合查询SQL,使用LEFT JOIN获取联系人信息
+        $sqlStr = "SELECT c.id, c.cs_code, c.cs_from, c.cs_country, c.cs_type, c.cs_deal, c.cs_addtime, c.cs_note,
+                  cc.id as contact_id, cc.contact_name,
+                  cc.tel_1, cc.tel_1_format, cc.tel_1_bu,
+                  cc.tel_2, cc.tel_2_format, cc.tel_2_bu,
+                  cc.tel_3, cc.tel_3_format, cc.tel_3_bu,
+                  cc.email_1, cc.email_1_bu,
+                  cc.email_2, cc.email_2_bu,
+                  cc.email_3, cc.email_3_bu,
+                  cc.whatsapp_1, cc.whatsapp_1_format, cc.whatsapp_1_bu,
+                  cc.whatsapp_2, cc.whatsapp_2_format, cc.whatsapp_2_bu,
+                  cc.whatsapp_3, cc.whatsapp_3_format, cc.whatsapp_3_bu,
+                  cc.wechat_1, cc.wechat_1_bu,
+                  cc.wechat_2, cc.wechat_2_bu,
+                  cc.wechat_3, cc.wechat_3_bu,
+                  cc.linkedin_1, cc.linkedin_1_bu,
+                  cc.linkedin_2, cc.linkedin_2_bu,
+                  cc.linkedin_3, cc.linkedin_3_bu,
+                  cc.facebook_1, cc.facebook_1_bu,
+                  cc.facebook_2, cc.facebook_2_bu,
+                  cc.facebook_3, cc.facebook_3_bu,
+                  cc.alibaba_1, cc.alibaba_1_bu,
+                  cc.alibaba_2, cc.alibaba_2_bu,
+                  cc.alibaba_3, cc.alibaba_3_bu
+                  FROM customer c
+                  LEFT JOIN customer_contact cc ON c.id = cc.customer_id
+                  WHERE c.cs_belong=" . (int)$employeeId . " 
+                  AND c.id IN (SELECT customerId FROM tagtable WHERE tagName='" . $conn->real_escape_string($tagName) . "')";
+
+        $result = $conn->query($sqlStr);
+        $tempNum = 0;
+
+        if ($result && $result->num_rows > 0) {
+            while ($row = $result->fetch_assoc()) {
+                $tempNum++;
         ?>
-            <a href="subTag.php?employeeId=<?= $row['id'] ?>&tagName=<?= urlencode($tagRow['tagName']) ?>"><?= htmlspecialcharsFix($tagRow['tagName']) ?>(<?= $tagRow['count'] ?>)</a>
+                <div class="tline">
+                    <div class="col2"><?= $tempNum ?></div>
+                    <div class="col3 slidepanel"><?= htmlspecialcharsFix($row['cs_code']) ?></div>
+                    <div class="col4">
+                        <?php
+                        $qudaoResult = $conn->query("SELECT ch_name FROM qudao WHERE id=" . (int)$row['cs_from']);
+                        echo ($qudaoRow = $qudaoResult->fetch_assoc()) ? htmlspecialcharsFix($qudaoRow['ch_name']) : '未填写';
+                        ?>
+                    </div>
+                    <div class="col5">
+                        <?php
+                        $countryResult = $conn->query("SELECT countryName FROM country WHERE id=" . (int)$row['cs_country']);
+                        echo ($countryRow = $countryResult->fetch_assoc()) ? htmlspecialcharsFix($countryRow['countryName']) : '未填写';
+                        ?>
+                    </div>
+                    <div class="col6">
+                        <?php
+                        $typeResult = $conn->query("SELECT businessType FROM clienttype WHERE id=" . (int)$row['cs_type']);
+                        echo ($typeRow = $typeResult->fetch_assoc()) ? htmlspecialcharsFix($typeRow['businessType']) : '未填写';
+                        ?>
+                    </div>
+                    <div class="col7">
+                        <?php
+                        if ($row['cs_deal'] == 3) {
+                            echo "<span style='color:red;'>成交</span>";
+                        } elseif ($row['cs_deal'] == 2) {
+                            echo "明确需求";
+                        } elseif ($row['cs_deal'] == 1) {
+                            echo "背景调查";
+                        } else {
+                            echo "无响应";
+                        }
+                        ?>
+                    </div>
+                    <div class="col8"><?= $row['cs_addtime'] ?></div>
+                    <div class="col10"><a href="customerEdit.php?id=<?= $row['id'] ?>" class="ico_edit ico">修改</a></div>
+                </div>
+                <div class="notepanel clear">
+                    <div class="noteItem">联系方式</div>
+                    <div class="lx">
+                        <div class="tel">
+                            <?php if(!empty($row['tel_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['tel_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['tel_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="mail">
+                            <?php if(!empty($row['email_1'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_1']) ?>"><?= htmlspecialcharsFix($row['email_1']) ?></a></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['email_2'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_2']) ?>"><?= htmlspecialcharsFix($row['email_2']) ?></a></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['email_3'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_3']) ?>"><?= htmlspecialcharsFix($row['email_3']) ?></a></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="whatsapp">
+                            <?php if(!empty($row['whatsapp_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['whatsapp_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['whatsapp_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="wechat">
+                            <?php if(!empty($row['wechat_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['wechat_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['wechat_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="linkedin">
+                            <?php if(!empty($row['linkedin_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['linkedin_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['linkedin_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="facebook">
+                            <?php if(!empty($row['facebook_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['facebook_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['facebook_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="alibaba">
+                            <?php if(!empty($row['alibaba_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['alibaba_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['alibaba_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                    </div>
+                    <div class="noteItem2">备注</div>
+                    <div class="notecontent"><?= htmlUnCode($row['cs_note']) ?></div>
+                </div>
         <?php
+            }
         }
         ?>
-        </div>
     </div>
-    <?php
-    }
-    ?>
 </div>
 </body>
 </html>

+ 19 - 13
subTagClound.php

@@ -25,27 +25,33 @@ checkLogin();
 <body class="clear">
 <?php // require_once 'panel.php'; ?>
 <div id="man_zone">
+<?php
+// 获取所有em_role等于当前用户employee_id的员工
+$employeeResult = $conn->query("SELECT id, em_user FROM employee WHERE em_role=" . $_SESSION['employee_id']);
+
+if ($employeeResult) {
+    while ($employeeRow = $employeeResult->fetch_assoc()) {
+?>
     <div class="tagclound">
-        <h1 class="tagCloundHead">自定义标签云</h1>
+        <h1 class="tagCloundHead2"><?= htmlspecialcharsFix($employeeRow['em_user']) ?>的客户画像:</h1>
         <div class="tagArea">
         <?php
-        $result = $conn->query("SELECT tagName, COUNT(DISTINCT c.cs_code) as count 
-                               FROM tagtable 
-                               LEFT JOIN customer c ON tagtable.customerId=c.id 
-                               WHERE employeeId=" . $_SESSION['employee_id'] . " 
-                               GROUP BY tagName");
+        // 对每个员工,查询其添加的所有标签
+        $tagResult = $conn->query("SELECT tagName, COUNT(id) as count FROM tagtable WHERE employeeId=" . $employeeRow['id'] . " GROUP BY tagName");
         
-        while ($row = $result->fetch_assoc()) {
-        ?>
-            <a href="tag.php?tagName=<?= urlencode($row['tagName']) ?>" style="font-size:16px;">
-                <?= htmlspecialcharsFix($row['tagName']) ?>(<?= $row['count'] ?>)
-            </a>
-        <?php
+        if ($tagResult) {
+            while ($tagRow = $tagResult->fetch_assoc()) {
+                echo '<a href="subTag.php?employeeId=' . $employeeRow['id'] . '&tagName=' . urlencode($tagRow['tagName']) . '">' . 
+                     htmlspecialcharsFix($tagRow['tagName']) . '(' . $tagRow['count'] . ')</a>';
+            }
         }
         ?>
-            <a href="nullTag.php">无标签客户</a>
         </div>
     </div>
+<?php
+    }
+}
+?>
 </div>
 </body>
 </html>

+ 2 - 2
system/IP.php

@@ -262,8 +262,8 @@ $hrefstr = "?keys=$keys";
                     <input type="text" id="keys" value="<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>" 
                            onFocus="if(this.value == '<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>'){this.value='';}" 
                            onBlur="if(this.value == ''){this.value='<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>';}" 
-                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
-                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
+                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
                 </div>
                 <div class="postchkbox">
                     <select id="chkact" name="chkact">

+ 221 - 0
system/add_product.php

@@ -0,0 +1,221 @@
+<?php
+require_once('conn.php');
+require_once('functions.php');
+
+// Check login status
+checkLogin("信息管理");
+
+// Initialize variables
+$product_name = '';
+$product_img = '';
+$unit = '';
+$moq = '';
+$category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
+$note = '';
+$tips = '';
+$keys = isset($_GET['Keys']) ? urlencode($_GET['Keys']) : '';
+$page = isset($_GET['Page']) ? $_GET['Page'] : 1;
+
+// Get the return URL
+$href_str = "products.php?keys=" . $keys . "&Page=" . $page;
+if ($category_id) {
+    $href_str .= "&category_id=" . $category_id;
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>添加产品</title>
+<link rel="stylesheet" href="css/common.css" type="text/css" />
+<script language="javascript" src="js/jquery-1.7.2.min.js"></script>
+<script type="text/javascript" src="js/js.js"></script>
+<script type="text/javascript" src="js/SearchArea.js"></script>
+<script type="text/javascript" src="xheditor-1.1.9/xheditor-1.1.9-zh-cn.min.js"></script>
+<style>
+    /* Styles for specification section */
+    .specifications {
+        margin-bottom: 10px;
+        width: 100%;
+    }
+    .specitem {
+        margin-bottom: 8px;
+        padding: 8px 10px;
+        /*background-color: #f9f9f9;*/
+        border: 1px solid #e0e0e0;
+        border-radius: 4px;
+        clear: both;
+        overflow: hidden;
+    }
+    .addspecitem, .delspecitem {
+        display: inline-block;
+        width: 20px;
+        height: 20px;
+        text-align: center;
+        line-height: 18px;
+        border-radius: 50%;
+        font-weight: bold;
+        cursor: pointer;
+        margin-left: 10px;
+    }
+    .addspecitem {
+        background-color: #5cb85c;
+        color: white;
+    }
+    .delspecitem {
+        background-color: #d9534f;
+        color: white;
+    }
+    .spec-input {
+        width: 160px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .spec-small-input {
+        width: 80px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .spec-label {
+        display: inline-block;
+        margin-right: 5px;
+        font-weight: normal;
+    }
+    .required {
+        color: red;
+        margin-left: 2px;
+    }
+</style>
+</head>
+
+<body>
+<div id="man_zone">
+    <form name="form1" method="post" action="save_product.php">
+        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
+            <tbody>
+                <tr>
+                    <th width="8%">产品名称</th>
+                    <td><input type="text" id="ProductName" name="ProductName" value="<?php echo $product_name; ?>" class="txt1" />
+                    <input type="hidden" name="id" value="" />
+                    <input type="hidden" name="keys" value="<?php echo $keys; ?>" />
+                    <input type="hidden" name="page" value="<?php echo $page; ?>" />
+                    <input type="hidden" name="category_id" value="<?php echo $category_id; ?>" />
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">产品分类</th>
+                    <td>
+                        <select name="category_id" id="category_id" class="select1">
+                            <option value="0">-- 请选择分类 --</option>
+                            <?php
+                            // Build category tree
+                            $category_data = buildCategoryTree($conn);
+                            $cat_tree = $category_data['tree'];
+                            
+                            // Output options
+                            outputCategoryOptions($cat_tree, $category_id);
+                            ?>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">产品图片</th>
+                    <td><input type="text" id="ProductImg" name="ProductImg" placeholder="186x*186px" value="<?php echo $product_img; ?>" class="txt1" style="width:390px;float:left;" />
+                    <iframe src="uploadfile.php" frameborder="0" scrolling="no" style="width:400px;height:22px;float:left;margin-left:10px;"></iframe></td>
+                </tr>
+                <tr>
+                    <th width="8%">计价单位</th>
+                    <td><input type="text" id="unit" name="unit" value="<?php echo $unit; ?>" class="txt1"/></td>
+                </tr>
+<!--                <tr>-->
+<!--                    <th width="8%">起订数量</th>-->
+<!--                    <td><input type="text" id="moq" name="moq" value="--><?php //echo $moq; ?><!--" class="txt1"/></td>-->
+<!--                </tr>-->
+                <tr>
+                    <th width="8%">产品规格</th>
+                    <td>
+                        <div class="specifications">
+                            <div class="specitem">
+                                <span class="spec-label">规格名称<span class="required">*</span>:</span>
+                                <input type="text" class="spec-input" name="spec_name[]" placeholder="如: 红色、XL" required>
+                                
+                                <span class="spec-label">起订数量<span class="required">*</span>:</span>
+                                <input type="number" class="spec-small-input" name="spec_moq[]" value="1" required>
+                                
+                                <span class="spec-label">规格价格<span class="required">*</span>:</span>
+                                <input type="text" class="spec-small-input" name="spec_price[]" placeholder="价格" required>
+                                
+                                <span class="addspecitem">+</span>
+                                <span class="delspecitem">-</span>
+                                
+                                <!-- 隐藏字段,仍然提交但不显示 -->
+                                <input type="hidden" name="spec_value[]" value="">
+                                <input type="hidden" name="spec_code[]" value="">
+                                <input type="hidden" name="spec_sort[]" value="0">
+                            </div>
+                        </div>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">不报价地区</th>
+                    <td>
+                        <ul class="areadd"></ul>
+                        <input type="text" id="AreaSearch" class="fastsearch">
+                        <div id="arealist" class="productlist"><ul></ul></div>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">不报价处理方式</th>
+                    <td><input type="text" id="note" name="note" value="<?php echo $note; ?>" class="txt1"/></td>
+                </tr>
+                <tr>
+                    <th width="8%">备注</th>
+                    <td><input type="text" id="tips" name="tips" value="<?php echo $tips; ?>" class="txt1"/></td>
+                </tr>
+                <tr>
+                    <th></th>
+                    <td colspan="2">
+                        <input type="submit" name="save" value="确定" class="btn1" />
+                        <input type="reset" name="reset" value="重置" class="btn1" />
+                        <input type="button" value="返回" class="btn1" onClick="location.href='<?php echo $href_str; ?>'" />
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </form>
+</div>
+
+<script>
+    $(document).ready(function(){
+        // Add specification item
+        $(document).on('click', '.addspecitem', function(){
+            var newSpecItem = $(this).closest('.specitem').clone(true);
+            newSpecItem.find('input[type="text"], input[type="hidden"]').val(''); // Clear values
+            newSpecItem.find('input[name="spec_moq[]"]').val('1'); // Reset MOQ to 1
+            newSpecItem.find('input[name="spec_sort[]"]').val('0'); // Reset sort to 0
+            $(this).closest('.specifications').append(newSpecItem);
+        });
+        
+        // Remove specification item
+        $(document).on('click', '.delspecitem', function(){
+            if($('.specitem').length > 1){
+                $(this).closest('.specitem').remove();
+            } else {
+                alert('至少需要保留一个规格项');
+            }
+        });
+        
+        // Update unit display when unit field changes
+        $('#unit').on('change keyup', function(){
+            $('.unit').text($(this).val());
+        });
+    });
+</script>
+
+</body>
+</html>
+<?php mysqli_close($conn); ?> 

+ 2 - 2
system/additional.php

@@ -167,8 +167,8 @@ if ($totalPages > 1) {
                     <input type="text" id="keys" value="<?php echo empty($Keyscode) ? '请输入搜索关键词' : $Keyscode; ?>" 
                            onFocus="if(this.value == '<?php echo empty($Keyscode) ? '请输入搜索关键词' : $Keyscode; ?>'){this.value='';}" 
                            onBlur="if(this.value == ''){this.value='<?php echo empty($Keyscode) ? '请输入搜索关键词' : $Keyscode; ?>';}" 
-                           onKeyDown="if(event.keyCode==13){location.href='?qid=<?php echo $qid; ?>&Keys='+escape(document.getElementById('keys').value)}" />
-                    <input type="button" id="searchgo" value="go" onClick="location.href='?qid=<?php echo $qid; ?>&Keys='+escape(document.getElementById('keys').value)" />
+                           onKeyDown="if(event.keyCode==13){location.href='?qid=<?php echo $qid; ?>&Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
+                    <input type="button" id="searchgo" value="go" onClick="location.href='?qid=<?php echo $qid; ?>&Keys='+encodeURIComponent(document.getElementById('keys').value)" />
                 </div>
                 <div class="postchkbox">
                     <select id="chkact" name="chkact">

+ 67 - 0
system/ajax_get_product_specifications.php

@@ -0,0 +1,67 @@
+<?php
+require_once 'conn.php';
+require_once 'functions.php';
+
+checklogin("信息管理");
+// Get product ID
+$product_id = isset($_POST['product_id']) ? (int)$_POST['product_id'] : 0;
+
+if (empty($product_id)) {
+    echo '<p class="error-message" style="color:red;text-align:center;padding:10px;">无效的产品ID</p>';
+    exit;
+}
+
+// Get all specifications for this product
+$sql = "SELECT ps.id as spec_id, ps.spec_name, ps.sort_order, ps.spec_value, ps.spec_code, 
+        ps.min_order_quantity, p.id as product_id, p.unit  
+        FROM product_specifications ps
+        JOIN products p ON ps.product_id = p.id
+        WHERE ps.product_id = $product_id
+        ORDER BY ps.sort_order, ps.id";
+
+$result = $conn->query($sql);
+$html = '';
+
+if ($result && $result->num_rows > 0) {
+    while ($row = $result->fetch_assoc()) {
+        $product_id = $row['product_id'];
+        $spec_id = $row['spec_id'];
+        $spec_name = htmlspecialcharsFix($row['spec_name']);
+        $spec_value = htmlspecialcharsFix($row['spec_value'] ?? '');
+        $spec_code = htmlspecialcharsFix($row['spec_code'] ?? '');
+        $unit = htmlspecialcharsFix($row['unit']);
+        $min_qty = !empty($row['min_order_quantity']) ? intval($row['min_order_quantity']) : 1;
+        
+        // 构建完整的规格显示文本
+        $spec_display = $spec_name;
+        if (!empty($spec_value)) {
+            $spec_display .= ': ' . $spec_value;
+        }
+        if (!empty($spec_code)) {
+            $spec_display .= ' <span style="font-size:12px;color:#666;">(编码: ' . $spec_code . ')</span>';
+        }
+        
+        $html .= '<div class="specitem">
+            <div class="specdelete" title="删除此规格">✕</div>
+            <input type="hidden" name="spec_product_id[]" value="' . $product_id . '">
+            <input type="hidden" name="spec_id[]" value="' . $spec_id . '">
+            
+            <span class="spec-label">规格:</span>
+            <span class="spec-name">' . $spec_display . '</span>
+            
+            <span class="spec-label" style="margin-left:15px;">起订数量:</span>
+            <input type="number" class="spec-small-input" name="spec_moq[]" value="' . $min_qty . '" min="1">
+            <span class="unit">' . $unit . '</span>
+            
+            <span class="spec-label" style="margin-left:15px;">售价:</span>
+            <input type="text" class="spec-small-input" name="spec_price[]" value="" required min="0.01">
+            <span>RMB</span>
+        </div>';
+    }
+    echo $html;
+} else {
+    echo '<p style="padding:10px; background:#fff3f3; color:#d9534f; text-align:center; margin:10px 0; border-radius:4px;">该产品没有规格信息,请先在产品管理中添加规格</p>';
+}
+
+$conn->close();
+?> 

+ 53 - 0
system/ajax_search_products_for_spec.php

@@ -0,0 +1,53 @@
+<?php
+require_once 'conn.php';
+require_once 'functions.php';
+
+checklogin("信息管理");
+
+// Get search keyword
+$keyword = isset($_POST['keyword']) ? trim($_POST['keyword']) : '';
+
+if (empty($keyword) || strlen($keyword) < 2) {
+    echo '<li class="error-message" style="text-align:center; color:#666; padding:8px;">请输入至少2个字符</li>';
+    exit;
+}
+
+// Search for products matching the keyword
+$sql = "SELECT p.id, p.ProductName, p.unit, pc.name as category_name,
+        (SELECT COUNT(*) FROM product_specifications WHERE product_id = p.id) as spec_count
+        FROM products p
+        LEFT JOIN product_categories pc ON p.category_id = pc.id
+        WHERE p.ProductName LIKE '%".$conn->real_escape_string($keyword)."%'
+        HAVING spec_count > 0
+        ORDER BY p.ProductName
+        LIMIT 20";
+
+$result = $conn->query($sql);
+
+if ($result && $result->num_rows > 0) {
+    while ($row = $result->fetch_assoc()) {
+        $product_id = $row['id'];
+        $product_name = htmlspecialcharsFix($row['ProductName']);
+        $unit = htmlspecialcharsFix($row['unit'] ?? '');
+        $category_name = htmlspecialcharsFix($row['category_name'] ?? '');
+        $spec_count = (int)$row['spec_count'];
+        
+        $unit_display = !empty($unit) ? " <span style=\"color:#666;font-size:12px;\">($unit)</span>" : "";
+        $spec_display = " <span style=\"color:#0066cc;font-size:12px;\">($spec_count 个规格)</span>";
+        
+        echo '<li data-product-id="'.$product_id.'" data-product-name="'.$product_name.'" 
+                data-unit="'.$unit.'" data-category-name="'.$category_name.'">
+                <span class="product-name" style="font-weight:bold;">'.$product_name.'</span>'.$unit_display.$spec_display;
+        
+        if (!empty($category_name)) {
+            echo ' <br><span class="category-tag" style="color:#777;font-size:12px;font-style:italic;">分类: '.$category_name.'</span>';
+        }
+        
+        echo '</li>';
+    }
+} else {
+    echo '<li style="text-align:center; color:#666; padding:10px;">未找到相关产品或产品没有规格</li>';
+}
+
+$conn->close();
+?> 

+ 235 - 69
system/country.php

@@ -13,7 +13,107 @@ checklogin("信息管理");
 <script language="javascript" src="js/jquery-1.7.2.min.js"></script>
 <script type="text/javascript" src="js/js.js"></script>
 <script type="text/javascript" src="xheditor-1.1.9/xheditor-1.1.9-zh-cn.min.js"></script>
-<script type="text/javascript" src="js/Searchproduct.js"></script>
+<script type="text/javascript" src="js/NewSearchproduct.js"></script>
+<style>
+    /* Styles for specification section */
+    .specifications {
+        margin-bottom: 10px;
+        width: 100%;
+    }
+    .specitem {
+        margin-bottom: 8px;
+        padding: 8px 10px;
+        border: 1px solid #e0e0e0;
+        border-radius: 4px;
+        clear: both;
+        overflow: hidden;
+    }
+    .spec-label {
+        display: inline-block;
+        margin-right: 5px;
+        font-weight: normal;
+    }
+    .spec-input {
+        width: 120px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .spec-small-input {
+        width: 80px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .required {
+        color: red;
+        margin-left: 2px;
+    }
+    .specdelete {
+        float: right;
+        cursor: pointer;
+        color: red;
+        font-weight: bold;
+        margin-right: 5px;
+    }
+    #specificationlist {
+        max-height: 300px;
+        overflow-y: auto;
+        border: 1px solid #ddd;
+        margin-top: 5px;
+        display: none;
+        background-color: white;
+        z-index: 999;
+        position: absolute;
+        width: 100%;
+        left: 0;
+        right: 0;
+        box-shadow: 0 3px 8px rgba(0,0,0,0.25);
+        box-sizing: border-box;
+    }
+    #specificationlist ul {
+        list-style: none;
+        padding: 0;
+        margin: 0;
+    }
+    #specificationlist li {
+        padding: 8px 10px;
+        cursor: pointer;
+        border-bottom: 1px solid #eee;
+    }
+    #specificationlist li:hover {
+        background-color: #f0f0f0;
+    }
+    .product-header {
+        margin-top: 10px;
+        padding: 8px;
+        background: #f5f5f5;
+        font-weight: bold;
+        border-radius: 4px;
+        border: 1px solid #ddd;
+    }
+    /* 增加搜索相关样式 */
+    .productinput {
+        position: relative;
+        width: 100%;
+        max-width: 90%;
+    }
+    .fastsearch {
+        width: 100%;
+        padding: 8px;
+        border: 1px solid #ddd;
+        border-radius: 4px;
+        box-sizing: border-box;
+    }
+    .category-tag {
+        color: #777;
+        font-size: 12px;
+        font-style: italic;
+        margin-left: 5px;
+    }
+</style>
 </head>
 <body>
 <div id="man_zone">
@@ -27,11 +127,59 @@ if ($act == "save") {
         $isedit = true;
     }
 
-    $productIds = $_POST['productId'] ?? [];
-    $nums = $_POST['num'] ?? [];
-    $prices = $_POST['price'] ?? [];
     $countryName = $_POST['countryName'] ?? '';
     $countryCode = $_POST['countryCode'] ?? '';
+    
+    // 验证国家和区号不能为空
+    if (trim($countryName) === '') {
+        echo "<script>alert('错误:国家名称不能为空!');history.back();</script>";
+        exit;
+    }
+    
+    if (trim($countryCode) === '') {
+        echo "<script>alert('错误:区号不能为空!');history.back();</script>";
+        exit;
+    }
+    
+    // 规格相关数据
+    $specProductIds = $_POST['spec_product_id'] ?? [];
+    $specIds = $_POST['spec_id'] ?? [];
+    $specPrices = $_POST['spec_price'] ?? [];
+    $specMoqs = $_POST['spec_moq'] ?? [];
+
+    // 验证售价不能为0
+    $hasZeroPrice = false;
+    $zeroProductName = '';
+    $zeroSpecName = '';
+
+    if (!empty($specProductIds) && !empty($specIds) && is_array($specProductIds) && is_array($specIds)) {
+        for ($i = 0; $i < count($specProductIds); $i++) {
+            if (isset($specPrices[$i])) {
+                $price = trim($specPrices[$i]);
+                if ($price === '' || $price === '0' || floatval($price) <= 0) {
+                    // 查询产品和规格名称
+                    $productId = intval($specProductIds[$i]);
+                    $specId = intval($specIds[$i]);
+                    $nameQuery = "SELECT p.ProductName, ps.spec_name 
+                                 FROM products p 
+                                 JOIN product_specifications ps ON p.id = ps.product_id 
+                                 WHERE p.id = $productId AND ps.id = $specId";
+                    $nameResult = $conn->query($nameQuery);
+                    if ($nameResult && $nameRow = $nameResult->fetch_assoc()) {
+                        $zeroProductName = $nameRow['ProductName'];
+                        $zeroSpecName = $nameRow['spec_name'];
+                    }
+                    $hasZeroPrice = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    if ($hasZeroPrice) {
+        echo "<script>alert('错误:产品 [".$zeroProductName."] 的规格 [".$zeroSpecName."] 售价不能为0或空白!');history.back();</script>";
+        exit;
+    }
 
     if ($isedit) {
         $sql = "UPDATE country SET 
@@ -41,19 +189,21 @@ if ($act == "save") {
             WHERE id = $id";
         $conn->query($sql);
         
-        // Delete all existing prices for this area
-        $conn->query("DELETE FROM price WHERE AreaId=$id");
+        // 删除该国家的所有产品规格价格
+        $conn->query("DELETE FROM product_country_price WHERE country_id=$id");
         
-        // Only process if we have product IDs
-        if (!empty($productIds) && is_array($productIds)) {
-            for ($i = 0; $i < count($productIds); $i++) {
-                if (isset($nums[$i]) && isset($prices[$i])) {
-                    $numVal = empty($nums[$i]) ? 0 : floatval($nums[$i]);
-                    $priceVal = empty($prices[$i]) ? 0 : $conn->real_escape_string($prices[$i]);
-                    $productId = intval($productIds[$i]);
+        // 处理规格价格数据
+        if (!empty($specProductIds) && !empty($specIds) && is_array($specProductIds) && is_array($specIds)) {
+            for ($i = 0; $i < count($specProductIds); $i++) {
+                if (isset($specPrices[$i]) && isset($specMoqs[$i]) && isset($specIds[$i])) {
+                    $productId = intval($specProductIds[$i]);
+                    $specId = intval($specIds[$i]);
+                    $specPrice = $conn->real_escape_string($specPrices[$i]);
+                    $specMoq = empty($specMoqs[$i]) ? 1 : intval($specMoqs[$i]);
                     
-                    if ($productId > 0) {
-                        $sql = "INSERT INTO price (productId, AreaId, num, price) VALUES ($productId, $id, $numVal, '$priceVal')";
+                    if ($productId > 0 && $specId > 0) {
+                        $sql = "INSERT INTO product_country_price (country_id, product_id, specification_id, price, min_order_quantity, addtime) 
+                                VALUES ($id, $productId, $specId, '$specPrice', $specMoq, NOW())";
                         $conn->query($sql);
                     }
                 }
@@ -75,16 +225,18 @@ if ($act == "save") {
         $conn->query($sql);
         $id = $conn->insert_id;
         
-        // Only process if we have product IDs
-        if (!empty($productIds) && is_array($productIds)) {
-            for ($i = 0; $i < count($productIds); $i++) {
-                if (isset($nums[$i]) && isset($prices[$i])) {
-                    $numVal = empty($nums[$i]) ? 0 : floatval($nums[$i]);
-                    $priceVal = empty($prices[$i]) ? 0 : $conn->real_escape_string($prices[$i]);
-                    $productId = intval($productIds[$i]);
+        // 处理规格价格数据
+        if (!empty($specProductIds) && !empty($specIds) && is_array($specProductIds) && is_array($specIds)) {
+            for ($i = 0; $i < count($specProductIds); $i++) {
+                if (isset($specPrices[$i]) && isset($specMoqs[$i]) && isset($specIds[$i])) {
+                    $productId = intval($specProductIds[$i]);
+                    $specId = intval($specIds[$i]);
+                    $specPrice = $conn->real_escape_string($specPrices[$i]);
+                    $specMoq = empty($specMoqs[$i]) ? 1 : intval($specMoqs[$i]);
                     
-                    if ($productId > 0) {
-                        $sql = "INSERT INTO price (productId, AreaId, num, price) VALUES ($productId, $id, $numVal, '$priceVal')";
+                    if ($productId > 0 && $specId > 0) {
+                        $sql = "INSERT INTO product_country_price (country_id, product_id, specification_id, price, min_order_quantity, addtime) 
+                                VALUES ($id, $productId, $specId, '$specPrice', $specMoq, NOW())";
                         $conn->query($sql);
                     }
                 }
@@ -128,78 +280,86 @@ if ($act == "add" || $act == "edit") {
         <tbody>
             <tr>
                 <th width="8%">国家</th>
-                <td><input type="text" id="countryName" name="countryName" value="<?= htmlspecialcharsFix($countryName) ?>" class="txt1" /><input type="hidden" name="id" value="<?= $id ?>" /></td>
+                <td><input type="text" id="countryName" name="countryName" value="<?= htmlspecialcharsFix($countryName) ?>" class="txt1" required /><input type="hidden" name="id" value="<?= $id ?>" /></td>
             </tr>
             <tr>
                 <th width="8%">区号</th>
-                <td><input type="text" id="countryCode" name="countryCode" value="<?= htmlspecialcharsFix($countryCode) ?>" class="txt1" /></td>
+                <td><input type="text" id="countryCode" name="countryCode" value="<?= htmlspecialcharsFix($countryCode) ?>" class="txt1" required /></td>
             </tr>
             <tr>
                 <th width="8%">更新日期</th>
                 <td><?= $addtime ?></td>
             </tr>           
+            <!-- 新增: 产品规格价格管理 -->
             <tr>
-                <th width="8%">售价管理</th>
+                <th width="8%">规格价格管理</th>
                 <td>
-                <div class="prowapper">             
+                <div class="specifications">
                     <?php
                     if (!empty($id) && $id > 0) {
-                        $sql = "SELECT p.id, p.ProductName, p.ProductImg, p.unit, p.category_id, pc.name as categoryName 
-                                FROM products p 
-                                LEFT JOIN product_categories pc ON p.category_id = pc.id 
-                                WHERE p.id IN (SELECT productId FROM price WHERE AreaId = $id)";
+                        // 只获取已经添加过的规格价格,而不是所有规格
+                        $sql = "SELECT p.id, p.ProductName, p.unit, ps.id as specification_id, 
+                                ps.spec_name, pcp.price, pcp.min_order_quantity, pc.name as categoryName
+                                FROM product_country_price pcp
+                                JOIN products p ON pcp.product_id = p.id
+                                JOIN product_specifications ps ON pcp.specification_id = ps.id
+                                LEFT JOIN product_categories pc ON p.category_id = pc.id
+                                WHERE pcp.country_id = $id
+                                ORDER BY p.ProductName, ps.sort_order";
                         $result = $conn->query($sql);
                         if ($result && $result->num_rows > 0) {
+                            $current_product = 0;
                             while ($row = $result->fetch_assoc()) {
-                                // 准备分类显示
-                                $categoryDisplay = !empty($row['categoryName']) ? ' <span style="color:#888;font-size:12px;">['.$row['categoryName'].']</span>' : '';
+                                // 显示产品名称,每个产品只显示一次
+                                if ($current_product != $row['id']) {
+                                    $current_product = $row['id'];
+                                    $categoryDisplay = !empty($row['categoryName']) ? ' <span style="color:#888;font-size:12px;">['.$row['categoryName'].']</span>' : '';
+                                    echo '<div class="product-header" style="margin-top:10px;padding:5px;background:#f5f5f5;font-weight:bold;">
+                                        '.htmlspecialcharsFix($row['ProductName']).$categoryDisplay.'
+                                    </div>';
+                                }
+                                
+                                // 设置默认值
+                                $price = isset($row['price']) ? $row['price'] : '';
+                                $moq = isset($row['min_order_quantity']) ? $row['min_order_quantity'] : '1';
                             ?>
-                                <div class="proitem">
-                                    <div class="prodelet"></div>
-                                    <div class="proname"><?= htmlspecialcharsFix($row['ProductName']) ?><?= $categoryDisplay ?></div>
-                                    <div class="propic"><img src="<?= htmlspecialcharsFix($row['ProductImg']) ?>"></div>      
-                                    <div class="proprice">
-                                        <?php
-                                        $sql2 = "SELECT num, price FROM price WHERE productId = {$row['id']} AND AreaId = $id ORDER BY num ASC";
-                                        $result2 = $conn->query($sql2);
-                                        while ($row2 = $result2->fetch_assoc()) {
-                                        ?>
-                                            <div class="priceitem">
-                                                <input type="hidden" name="productId[]" value="<?= $row['id'] ?>">
-                                                <label>≥</label>
-                                                <input type="number" autocomplete="off" class="txt3 num" name="num[]" value="<?= $row2['num'] ?>">
-                                                <label class='unit'><?= htmlspecialcharsFix($row['unit']) ?></label>
-                                                <label>售价</label>
-                                                <input type="text" class="txt3 price" autocomplete="off" name="price[]" value="<?= $row2['price'] ?>">
-                                                <label>RMB</label>
-                                                <span class="additem"></span>
-                                                <span class="delitem"></span>
-                                                <span class="note"></span>
-                                            </div>
-                                        <?php
-                                        }
-                                        ?>
-                                    </div>      
+                                <div class="specitem">
+                                    <div class="specdelete" style="float:right;cursor:pointer;color:red;">✕</div>
+                                    <input type="hidden" name="spec_product_id[]" value="<?= $row['id'] ?>">
+                                    <input type="hidden" name="spec_id[]" value="<?= $row['specification_id'] ?>">
+                                    
+                                    <span class="spec-label">规格:</span>
+                                    <span class="spec-name"><?= htmlspecialcharsFix($row['spec_name']) ?></span>
+                                    
+                                    <span class="spec-label" style="margin-left:15px;">起订数量:</span>
+                                    <input type="number" class="spec-small-input" name="spec_moq[]" value="<?= $moq ?>">
+                                    <span class="unit"><?= htmlspecialcharsFix($row['unit']) ?></span>
+                                    
+                                    <span class="spec-label" style="margin-left:15px;">售价:</span>
+                                    <input type="text" class="spec-small-input" name="spec_price[]" value="<?= $price ?>" required min="0.01">
+                                    <span>RMB</span>
                                 </div>
                             <?php
                             }
                         } else {
-                            echo "<p>该地区暂无产品价格设置</p>";
+                            echo "<p>该地区暂无产品规格价格设置,请使用下方的搜索功能添加</p>";
                         }
                     } else {
-                        echo "<p>添加产品后可管理产品价格</p>";
+                        echo "<p>添加产品后可管理产品规格价格</p>";
                     }
                     ?>
-                </div>                  
+                </div>
                 </td>
             </tr>
             <tr>
-                <th width="8%">产品添加</th>
-                <td class="productinput">
-                    <input type="text" id="productSearch" class="fastsearch">
-                    <div id="productlist" class="productlist"><ul></ul></div>
+                <th width="8%">添加规格价格</th>
+                <td>
+                    <div class="productinput">
+                        <input type="text" id="specificationSearch" class="fastsearch" placeholder="搜索产品">
+                        <div id="specificationlist" class="productlist"><ul></ul></div>
+                    </div>
                 </td>
-            </tr>          
+            </tr>
             <tr>
                 <th></th>
                 <td>
@@ -228,6 +388,10 @@ if ($act == "postchk") {
         $ids = implode(',', array_map('intval', $_POST['chkbox']));
         $sql = "DELETE FROM country WHERE id IN ($ids)";
         $conn->query($sql);
+        
+        // 删除相关的产品规格价格
+        $sql = "DELETE FROM product_country_price WHERE country_id IN ($ids)";
+        $conn->query($sql);
     }
     
     header("Location: ?Keys=$keys&Ord=$ord&Page=$page");
@@ -376,7 +540,7 @@ $hrefstr = "?keys=$keys";
                             <option value="1">请选择</option>
                             <option value="-1">删除</option>
                         </select>
-                        <input type="button" value="执行" onClick="postchk(1)" class="btn1" />
+                        <input type="button" value="执行" onClick="postchk_new(1)" class="btn1" />
                         <input type="button" value="新增" onClick="location.href='?act=add'" class="btn1" />
                     </div>
                 </td>
@@ -389,6 +553,8 @@ $hrefstr = "?keys=$keys";
 $('.click-open-iframe').galpop({
     contentType: 'iframe',
 });
+
+// 规格搜索和添加功能已移至 js/NewSearchproduct.js
 </script>
 </body>
 </html> 

+ 1 - 1
system/customers.php

@@ -955,7 +955,7 @@ $tempNum = $pageSize * ($page - 1);
             <input type="text" id="keys" class="inputTxt" placeholder="请输入搜索关键词" value="<?php echo empty($keyscode) ? '' : $keyscode; ?>"
                     />
             <input type="button" id="searchgo" class="searchgo" value="go" 
-                   onClick="location.href='?Keys='+escape(document.getElementById('keys').value)+'<?php echo $urlStr; ?>'" />
+                   onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)+'<?php echo $urlStr; ?>'" />
         </div>
     </div>
     

+ 290 - 0
system/edit_product.php

@@ -0,0 +1,290 @@
+<?php
+require_once('conn.php');
+require_once('functions.php');
+
+// Check login status
+checkLogin("信息管理");
+
+// Initialize variables
+$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
+$keys = isset($_GET['Keys']) ? urlencode($_GET['Keys']) : '';
+$page = isset($_GET['Page']) ? $_GET['Page'] : 1;
+$category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
+
+// Get the return URL
+$href_str = "products.php?keys=" . $keys . "&Page=" . $page;
+if ($category_id) {
+    $href_str .= "&category_id=" . $category_id;
+}
+
+// Check if the product exists
+if ($id <= 0) {
+    header("Location: " . $href_str);
+    exit();
+}
+
+// Fetch product data
+$sql = "SELECT * FROM products WHERE id = " . (int)$id;
+$result = mysqli_query($conn, $sql);
+
+if (mysqli_num_rows($result) <= 0) {
+    // Product not found, redirect
+    header("Location: " . $href_str);
+    exit();
+}
+
+$row = mysqli_fetch_assoc($result);
+$product_name = htmlspecialcharsFix($row['ProductName']);
+$product_img = htmlspecialcharsFix($row['ProductImg']);
+$unit = htmlspecialcharsFix($row['unit']);
+$moq = htmlspecialcharsFix($row['moq']);
+$nosale = $row['nosale'];
+$note = htmlspecialcharsFix($row['note']);
+$tips = htmlspecialcharsFix($row['tips']);
+$category_id = $row['category_id'] ? intval($row['category_id']) : 0;
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>编辑产品</title>
+<link rel="stylesheet" href="css/common.css" type="text/css" />
+<script language="javascript" src="js/jquery-1.7.2.min.js"></script>
+<script type="text/javascript" src="js/js.js"></script>
+<script type="text/javascript" src="js/SearchArea.js"></script>
+<script type="text/javascript" src="xheditor-1.1.9/xheditor-1.1.9-zh-cn.min.js"></script>
+<style>
+    /* Styles for specification section */
+    .specifications {
+        margin-bottom: 10px;
+        width: 100%;
+    }
+    .specitem {
+        margin-bottom: 8px;
+        padding: 8px 10px;
+        /*background-color: #f9f9f9;*/
+        border: 1px solid #e0e0e0;
+        border-radius: 4px;
+        clear: both;
+        overflow: hidden;
+    }
+    .addspecitem, .delspecitem {
+        display: inline-block;
+        width: 20px;
+        height: 20px;
+        text-align: center;
+        line-height: 18px;
+        border-radius: 50%;
+        font-weight: bold;
+        cursor: pointer;
+        margin-left: 10px;
+    }
+    .addspecitem {
+        background-color: #5cb85c;
+        color: white;
+    }
+    .delspecitem {
+        background-color: #d9534f;
+        color: white;
+    }
+    .spec-input {
+        width: 160px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .spec-small-input {
+        width: 80px;
+        padding: 4px;
+        margin-right: 10px;
+        border: 1px solid #ccc;
+        border-radius: 3px;
+    }
+    .spec-label {
+        display: inline-block;
+        margin-right: 5px;
+        font-weight: normal;
+    }
+    .required {
+        color: red;
+        margin-left: 2px;
+    }
+</style>
+</head>
+
+<body>
+<div id="man_zone">
+    <form name="form1" method="post" action="save_product.php">
+        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
+            <tbody>
+                <tr>
+                    <th width="8%">产品名称</th>
+                    <td><input type="text" id="ProductName" name="ProductName" value="<?php echo $product_name; ?>" class="txt1" />
+                    <input type="hidden" name="id" value="<?php echo $id; ?>" />
+                    <input type="hidden" name="keys" value="<?php echo $keys; ?>" />
+                    <input type="hidden" name="page" value="<?php echo $page; ?>" />
+                    <input type="hidden" name="category_id" value="<?php echo $category_id; ?>" />
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">产品分类</th>
+                    <td>
+                        <select name="category_id" id="category_id" class="select1">
+                            <option value="0">-- 请选择分类 --</option>
+                            <?php
+                            // Build category tree
+                            $category_data = buildCategoryTree($conn);
+                            $cat_tree = $category_data['tree'];
+                            
+                            // Output options
+                            outputCategoryOptions($cat_tree, $category_id);
+                            ?>
+                        </select>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">产品图片</th>
+                    <td><input type="text" id="ProductImg" name="ProductImg" placeholder="186x*186px" value="<?php echo $product_img; ?>" class="txt1" style="width:390px;float:left;" />
+                    <iframe src="uploadfile.php" frameborder="0" scrolling="no" style="width:400px;height:22px;float:left;margin-left:10px;"></iframe></td>
+                </tr>
+                <tr>
+                    <th width="8%">计价单位</th>
+                    <td><input type="text" id="unit" name="unit" value="<?php echo $unit; ?>" class="txt1"/></td>
+                </tr>
+<!--                <tr>-->
+<!--                    <th width="8%">起订数量</th>-->
+<!--                    <td><input type="text" id="moq" name="moq" value="--><?php //echo $moq; ?><!--" class="txt1"/></td>-->
+<!--                </tr>-->
+                <tr>
+                    <th width="8%">产品规格</th>
+                    <td>
+                        <div class="specifications">
+                        <?php
+                        // Fetch specifications for this product
+                        $spec_sql = "SELECT * FROM product_specifications WHERE product_id = " . (int)$id . " ORDER BY sort_order ASC";
+                        $spec_result = mysqli_query($conn, $spec_sql);
+                        
+                        if (mysqli_num_rows($spec_result) > 0) {
+                            while ($spec_row = mysqli_fetch_assoc($spec_result)) {
+                                ?>
+                                <div class="specitem">
+                                    <span class="spec-label">规格名称<span class="required">*</span>:</span>
+                                    <input type="text" class="spec-input" name="spec_name[]" placeholder="如: 红色、XL" value="<?php echo htmlspecialcharsFix($spec_row['spec_name']); ?>" required>
+                                    
+                                    <span class="spec-label">起订数量<span class="required">*</span>:</span>
+                                    <input type="number" class="spec-small-input" name="spec_moq[]" value="<?php echo $spec_row['min_order_quantity']; ?>" required>
+                                    
+                                    <span class="spec-label">规格价格<span class="required">*</span>:</span>
+                                    <input type="text" class="spec-small-input" name="spec_price[]" placeholder="价格" value="<?php echo $spec_row['price']; ?>" required>
+                                    
+                                    <span class="addspecitem">+</span>
+                                    <span class="delspecitem">-</span>
+                                    
+                                    <!-- 隐藏字段,保留原始数据 -->
+                                    <input type="hidden" name="spec_value[]" value="<?php echo htmlspecialcharsFix($spec_row['spec_value']); ?>">
+                                    <input type="hidden" name="spec_code[]" value="<?php echo htmlspecialcharsFix($spec_row['spec_code']); ?>">
+                                    <input type="hidden" name="spec_sort[]" value="<?php echo $spec_row['sort_order']; ?>">
+                                </div>
+                                <?php
+                            }
+                        } else {
+                            // No specifications found, show one empty form
+                            ?>
+                            <div class="specitem">
+                                <span class="spec-label">规格名称<span class="required">*</span>:</span>
+                                <input type="text" class="spec-input" name="spec_name[]" placeholder="如: 红色、XL" required>
+                                
+                                <span class="spec-label">起订数量<span class="required">*</span>:</span>
+                                <input type="number" class="spec-small-input" name="spec_moq[]" value="1" required>
+                                
+                                <span class="spec-label">规格价格<span class="required">*</span>:</span>
+                                <input type="text" class="spec-small-input" name="spec_price[]" placeholder="价格" required>
+                                
+                                <span class="addspecitem">+</span>
+                                <span class="delspecitem">-</span>
+                                
+                                <!-- 隐藏字段,仍然提交但不显示 -->
+                                <input type="hidden" name="spec_value[]" value="">
+                                <input type="hidden" name="spec_code[]" value="">
+                                <input type="hidden" name="spec_sort[]" value="0">
+                            </div>
+                            <?php
+                        }
+                        ?>
+                        </div>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">不报价地区</th>
+                    <td>
+                        <ul class="areadd">
+                        <?php
+                        if (!empty($nosale)) {
+                            // 确保nosale是逗号分隔的字符串格式
+                            $nosale_str = is_array($nosale) ? implode(',', $nosale) : $nosale;
+                            $area_sql = "SELECT id, countryName FROM country WHERE id IN(" . $nosale_str . ")";
+                            $area_result = mysqli_query($conn, $area_sql);
+                            while ($area_row = mysqli_fetch_assoc($area_result)) {
+                                ?>
+                                <li><input type="hidden" name="nosale[]" value="<?php echo $area_row['id']; ?>"><span class="cname"><?php echo htmlspecialcharsFix($area_row['countryName']); ?></span><span class="close"></span></li>
+                                <?php
+                            }
+                        }
+                        ?>
+                        </ul>
+                        <input type="text" id="AreaSearch" class="fastsearch">
+                        <div id="arealist" class="productlist"><ul></ul></div>
+                    </td>
+                </tr>
+                <tr>
+                    <th width="8%">不报价处理方式</th>
+                    <td><input type="text" id="note" name="note" value="<?php echo $note; ?>" class="txt1"/></td>
+                </tr>
+                <tr>
+                    <th width="8%">备注</th>
+                    <td><input type="text" id="tips" name="tips" value="<?php echo $tips; ?>" class="txt1"/></td>
+                </tr>
+                <tr>
+                    <th></th>
+                    <td colspan="2">
+                        <input type="submit" name="save" value="确定" class="btn1" />
+                        <input type="reset" name="reset" value="重置" class="btn1" />
+                        <input type="button" value="返回" class="btn1" onClick="location.href='<?php echo $href_str; ?>'" />
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </form>
+</div>
+
+<script>
+    $(document).ready(function(){
+        // Add specification item
+        $(document).on('click', '.addspecitem', function(){
+            var newSpecItem = $(this).closest('.specitem').clone(true);
+            newSpecItem.find('input[type="text"], input[type="hidden"]').val(''); // Clear values
+            newSpecItem.find('input[name="spec_moq[]"]').val('1'); // Reset MOQ to 1
+            newSpecItem.find('input[name="spec_sort[]"]').val('0'); // Reset sort to 0
+            $(this).closest('.specifications').append(newSpecItem);
+        });
+        
+        // Remove specification item
+        $(document).on('click', '.delspecitem', function(){
+            if($('.specitem').length > 1){
+                $(this).closest('.specitem').remove();
+            } else {
+                alert('至少需要保留一个规格项');
+            }
+        });
+        
+        // Update unit display when unit field changes
+        $('#unit').on('change keyup', function(){
+            $('.unit').text($(this).val());
+        });
+    });
+</script>
+
+</body>
+</html>
+<?php mysqli_close($conn); ?> 

+ 22 - 8
system/employee.php

@@ -19,6 +19,7 @@ if($act == "save") {
     $em_code = textEncode($_POST['em_code']);
     $em_email = textEncode($_POST['em_email']);
     $em_tel = textEncode($_POST['em_tel']);
+    $em_permission_role_id = $_POST['em_permission_role_id'];
     $nullPwd = false;
 
     if(empty($em_password)) {
@@ -36,7 +37,7 @@ if($act == "save") {
         if($result->num_rows > 0) {
             $password_sql = $nullPwd ? "" : ",em_password='".md5($em_password)."'";
             $sql = "UPDATE employee SET em_user='$em_user'$password_sql,em_role=$em_role,
-                    em_code='$em_code',em_email='$em_email',em_tel='$em_tel' WHERE id=$id";
+                    em_code='$em_code',em_email='$em_email',em_tel='$em_tel',em_permission_role_id=$em_permission_role_id WHERE id=$id";
             $conn->query($sql);
         }
         
@@ -50,8 +51,8 @@ if($act == "save") {
             $em_password = "MTB".$em_code;
         }
         
-        $sql = "INSERT INTO employee(em_user,em_password,em_role,em_code,em_email,em_tel) 
-                VALUES('$em_user','".md5($em_password)."',$em_role,'$em_code','$em_email','$em_tel')";
+        $sql = "INSERT INTO employee(em_user,em_password,em_role,em_code,em_email,em_tel,em_permission_role_id) 
+                VALUES('$em_user','".md5($em_password)."',$em_role,'$em_code','$em_email','$em_tel',$em_permission_role_id)";
         $conn->query($sql);
         header("Location: ?");
         exit;
@@ -106,6 +107,7 @@ if($act == "add" || $act == "edit") {
             $em_code = textUncode($row['em_code']);
             $em_email = textUncode($row['em_email']);
             $em_tel = textUncode($row['em_tel']);
+            $em_permission_role_id = $row['em_permission_role_id'];
         } else {
             $isEdit = false;
         }
@@ -138,20 +140,32 @@ if($act == "add" || $act == "edit") {
                 <td><input type="text" id="em_code" name="em_code" value="<?php echo $em_code ?? ''; ?>" class="txt1" /></td>
             </tr>
             <tr>
-                <th width="8%">角色</th>
+                <th width="8%">该用户上级</th>
                 <td><select name="em_role">
-                    <option value="0">组长</option>
+                    <option value="0"></option>
                     <?php
                     $query = "SELECT id,em_user FROM employee WHERE em_role=0";
                     $result = $conn->query($query);
                     while($row = $result->fetch_assoc()) {
                         $selected = ($row['id'] == ($em_role ?? '')) ? ' selected="selected"' : '';
-                        echo "<option value=\"{$row['id']}\"$selected>组长:{$row['em_user']}</option>";
+                        echo "<option value=\"{$row['id']}\"$selected>{$row['em_user']}</option>";
                     }
                     ?>
                     </select>
                 </td>
             </tr>
+            <tr>
+                <th width="8%">权限角色</th>
+                <td>
+                    <select name="em_permission_role_id">
+                        <option value="0" <?php echo (isset($em_permission_role_id) && $em_permission_role_id == 0) ? 'selected' : ''; ?>>0 * 普通</option>
+                        <option value="2" <?php echo (isset($em_permission_role_id) && $em_permission_role_id == 2) ? 'selected' : ''; ?>>2 * 组长</option>
+                        <option value="3" <?php echo (isset($em_permission_role_id) && $em_permission_role_id == 3) ? 'selected' : ''; ?>>3 * 组员</option>
+                        <option value="4" <?php echo (isset($em_permission_role_id) && $em_permission_role_id == 4) ? 'selected' : ''; ?>>4 * 分公司</option>
+                        <option value="1" <?php echo (isset($em_permission_role_id) && $em_permission_role_id == 1) ? 'selected' : ''; ?>>1 * 管理员</option>
+                    </select>
+                </td>
+            </tr>
             <tr>
                 <th width="8%">邮箱</th>
                 <td><input type="text" id="em_email" name="em_email" value="<?php echo $em_email ?? ''; ?>" class="txt1" /></td>
@@ -300,8 +314,8 @@ $hrefstr = "?keys=$keys";
                     <input type="text" id="keys" value="<?php echo $keyscode == '' ? '请输入搜索关键词' : $keyscode; ?>" 
                            onFocus="if(this.value == '<?php echo $keyscode == '' ? '请输入搜索关键词' : $keyscode; ?>'){this.value='';}" 
                            onBlur="if(this.value == ''){this.value='<?php echo $keyscode == '' ? '请输入搜索关键词' : $keyscode; ?>';}" 
-                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
-                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
+                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
                 </div>
                 <div class="postchkbox">
                     <select id="chkact" name="chkact">

+ 1 - 1
system/index.php

@@ -217,7 +217,7 @@ switch($iframe) {
 
         t = outlookbar.addtitle('权限管理','其它管理',1);
         <?php if(chkLogin("权限管理")): ?>
-        outlookbar.additem('员工管理',t,'employee.php');
+        outlookbar.additem('用户管理',t,'employee.php');
         <?php endif; ?>
         </script>
         <body onload="initinav('信息管理')">

+ 55 - 0
system/js/js.js

@@ -90,6 +90,61 @@ return false;
 }
 
 
+function postchk_new(t){
+
+	var $form = document.getElementById('form1'),
+		chkact = parseInt(document.getElementById("chkact").value),
+		ischk = false;
+	for (var i=0;i<$form.elements.length;i++){
+		if($form.elements[i].name=="chkbox[]" && $form.elements[i].checked == true){ischk = true;}
+	}
+	if(!ischk){alert('请至少选择一条数据');return false;}
+	switch(t){
+		case 1:
+			switch(chkact){
+				case 1:
+					if(confirm('确认要设置所选状态为【显示】吗?'))$form.submit();
+					break;
+				case 0:
+					if(confirm('确认要设置所选状态为【隐藏】吗?'))$form.submit();
+					break;
+				default:
+					if(confirm('确认要删除吗?\n删除后不可恢复'))$form.submit();
+			}
+			break;
+		case 2:
+			switch(chkact){
+				case 1:
+					if(confirm('确认要设置所选状态为【正常】吗?'))$form.submit();
+					break;
+				case 0:
+					if(confirm('确认要设置所选状态为【隐藏】吗?'))$form.submit();
+					break;
+				default:
+					if(confirm('确认要删除吗?\n删除后不可恢复'))$form.submit();
+			}
+			break;
+		case 3:
+			switch(chkact){
+				case 1:
+					if(confirm('确认要设置所选状态为【已读】吗?'))$form.submit();
+					break;
+				case 0:
+					if(confirm('确认要设置所选状态为【未读】吗?'))$form.submit();
+					break;
+				default:
+					if(confirm('确认要删除吗?\n删除后不可恢复'))$form.submit();
+			}
+			break;
+		default:
+			return false;
+	}
+
+
+	return false;
+}
+
+
 function subform(){
 	$("#form1").submit();
 }

+ 2 - 2
system/log.php

@@ -138,9 +138,9 @@ $result = mysqli_query($conn, $sql);
                             value="<?php echo empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode); ?>" 
                             onFocus="if(this.value == '<?php echo empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode); ?>'){this.value='';}" 
                             onBlur="if(this.value == ''){this.value='<?php echo empty($keyscode) ? '请输入搜索关键词' : htmlspecialcharsFix($keyscode); ?>';}" 
-                            onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)+'&Page=<?php echo $page; ?>'}" />
+                            onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)+'&Page=<?php echo $page; ?>'}" />
                         <input type="button" id="searchgo" class="searchgo" value="go" 
-                            onClick="location.href='?Keys='+escape(document.getElementById('keys').value)+'&Page=<?php echo $page; ?>'" />
+                            onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)+'&Page=<?php echo $page; ?>'" />
                     </div>
                 </td>
             </tr>

+ 2 - 2
system/power.php

@@ -272,8 +272,8 @@ $hrefstr = "?keys=$keys";
                     <input type="text" id="keys" value="<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>" 
                            onFocus="if(this.value == '<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>'){this.value='';}" 
                            onBlur="if(this.value == ''){this.value='<?php echo ($keyscode == "") ? "请输入搜索关键词" : $keyscode; ?>';}" 
-                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
-                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                           onKeyDown="if(event.keyCode==13){location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)}" />
+                    <input type="button" id="searchgo" value="go" onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
                 </div>
                 <div class="postchkbox">
                     <select id="chkact" name="chkact">

+ 2 - 2
system/product_category.php

@@ -459,7 +459,7 @@ if ($act == 'edit' || $act == 'add') {
 
                     <div style="padding-left: 50px;">
                         <input type="text" id="keys" class="inputTxt" value="<?php echo $keyscode; ?>" placeholder="请输入搜索关键词" />
-                        <input type="button" id="searchgo" class="searchgo" value="搜索" onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+                        <input type="button" id="searchgo" class="searchgo" value="搜索" onClick="location.href='?Keys='+encodeURIComponent(document.getElementById('keys').value)" />
                     </div>
                 </div>
             </div>
@@ -644,7 +644,7 @@ if ($act == 'edit' || $act == 'add') {
                                 <select id="chkact" name="chkact">
                                     <option value="-1">删除</option>
                                 </select>
-                                <input type="button" value="执行" onClick="postchk(1)" class="btn1" />
+                                <input type="button" value="执行" onClick="postchk_new(1)" class="btn1" />
                             </div>
                         </td>
                     </tr>

+ 242 - 440
system/products.php

@@ -1,101 +1,28 @@
 <?php
 require_once('conn.php');
 
-
 // Check login status (assuming you have a similar function in PHP)
 checkLogin("信息管理");
 
 // Initialize all variables to avoid undefined warnings
 $act = isset($_GET['act']) ? $_GET['act'] : '';
-$product_name = isset($_POST['ProductName']) ? htmlspecialcharsFix($_POST['ProductName']) : '';
-$product_img = isset($_POST['ProductImg']) ? htmlspecialcharsFix($_POST['ProductImg']) : '';
-$unit = isset($_POST['unit']) ? htmlspecialcharsFix($_POST['unit']) : '';
-$moq = isset($_POST['moq']) ? htmlspecialcharsFix($_POST['moq']) : '';
-$category_id = isset($_POST['category_id']) ? intval($_POST['category_id']) : (isset($_GET['category_id']) ? intval($_GET['category_id']) : 0);
-$nosale = isset($_POST['nosale']) ? $_POST['nosale'] : array();
-$num = isset($_POST['num']) ? $_POST['num'] : array();
-$price = isset($_POST['price']) ? $_POST['price'] : array();
-$note = isset($_POST['note']) ? htmlspecialcharsFix($_POST['note']) : '';
-$tips = isset($_POST['tips']) ? htmlspecialcharsFix($_POST['tips']) : '';
 $page = isset($_GET['Page']) ? $_GET['Page'] : 1;
 $keys = isset($_GET['Keys']) ? urlencode($_GET['Keys']) : '';
 $keyscode = isset($_GET['Keys']) ? htmlspecialcharsFix($_GET['Keys']) : '';
+$category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
 
 // Handle form submissions and redirects before any output
-if ($act == 'save') {
-    $id = isset($_POST['id']) ? $_POST['id'] : '';
-    $is_edit = (!empty($id) && is_numeric($id));
-    
-    // Process nosale array into comma-separated string
-    $nosale_str = '';
-    if (is_array($nosale) && !empty($nosale)) {
-        $nosale_clean = array_map('intval', $nosale); // Ensure all values are integers
-        $nosale_str = implode(',', $nosale_clean);
-    }
-    
-    if ($is_edit) {
-        // Update existing product
-        $sql = "UPDATE products SET 
-                ProductName = '" . mysqli_real_escape_string($conn, $product_name) . "',
-                ProductImg = '" . mysqli_real_escape_string($conn, $product_img) . "',
-                Addtime = NOW(),
-                moq = '" . mysqli_real_escape_string($conn, $moq) . "',
-                unit = '" . mysqli_real_escape_string($conn, $unit) . "',
-                nosale = '" . $nosale_str . "',
-                note = '" . mysqli_real_escape_string($conn, $note) . "',
-                tips = '" . mysqli_real_escape_string($conn, $tips) . "',
-                category_id = " . $category_id . "
-                WHERE id = " . (int)$id;
-        mysqli_query($conn, $sql);
-        
-        // Handle price updates
-        mysqli_query($conn, "DELETE FROM price WHERE productId = " . (int)$id . " AND AreaId = 0");
-        
-        if (is_array($num) && is_array($price)) {
-            foreach ($num as $key => $num_value) {
-                if (isset($price[$key])) { // Only process if we have both num and price
-                    $num_value = empty($num_value) ? 0 : (float)$num_value;
-                    $price_value = empty($price[$key]) ? 0 : (float)$price[$key];
-                    $sql = "INSERT INTO price (productId, AreaId, num, price) VALUES 
-                            (" . (int)$id . ", 0, " . $num_value . ", '" . $price_value . "')";
-                    mysqli_query($conn, $sql);
-                }
-            }
-        }
-    } else {
-        // Insert new product
-        $sql = "INSERT INTO products (ProductName, ProductImg, Addtime, moq, unit, nosale, note, tips, category_id) 
-                VALUES (
-                    '" . mysqli_real_escape_string($conn, $product_name) . "',
-                    '" . mysqli_real_escape_string($conn, $product_img) . "',
-                    NOW(),
-                    '" . mysqli_real_escape_string($conn, $moq) . "',
-                    '" . mysqli_real_escape_string($conn, $unit) . "',
-                    '" . $nosale_str . "',
-                    '" . mysqli_real_escape_string($conn, $note) . "',
-                    '" . mysqli_real_escape_string($conn, $tips) . "',
-                    " . $category_id . "
-                )";
-        mysqli_query($conn, $sql);
-        $id = mysqli_insert_id($conn);
-        
-        // Handle price insertions
-        if (is_array($num) && is_array($price)) {
-            foreach ($num as $key => $num_value) {
-                if (isset($price[$key])) { // Only process if we have both num and price
-                    $num_value = empty($num_value) ? 0 : (float)$num_value;
-                    $price_value = empty($price[$key]) ? 0 : (float)$price[$key];
-                    $sql = "INSERT INTO price (productId, AreaId, num, price) VALUES 
-                            (" . (int)$id . ", 0, " . $num_value . ", '" . $price_value . "')";
-                    mysqli_query($conn, $sql);
-                }
-            }
-        }
-    }
-    
-    // Redirect after save
-    header("Location: ?keys=" . $keys . "&Page=" . $page);
+if ($act == 'add') {
+    // Redirect to the add product page
+    header("Location: add_product.php?Keys=" . $keys . "&Page=" . $page . ($category_id ? "&category_id=" . $category_id : ""));
     exit();
+} else if ($act == 'edit') {
+    $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
+    if ($id > 0) {
+        // Redirect to the edit product page
+        header("Location: edit_product.php?id=" . $id . "&Keys=" . $keys . "&Page=" . $page . ($category_id ? "&category_id=" . $category_id : ""));
+        exit();
+    }
 }
 
 // Handle bulk actions
@@ -122,7 +49,7 @@ if ($act == 'postchk') {
             }
         }
         
-        header("Location: ?Keys=" . $keys . "&Page=" . $page);
+        header("Location: ?Keys=" . $keys . "&Page=" . $page . ($category_id ? "&category_id=" . $category_id : ""));
         exit();
     }
 }
@@ -189,378 +116,253 @@ if ($act == 'postchk') {
 <body>
 <div id="man_zone">
 <?php
-// Handle add/edit form display
-if ($act == 'add' || $act == 'edit') {
-    $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
-    $is_edit = ($id > 0);
-    
-    if ($is_edit) {
-        $sql = "SELECT * FROM products WHERE id = " . (int)$id;
-        $result = mysqli_query($conn, $sql);
-        
-        if (mysqli_num_rows($result) > 0) {
-            $row = mysqli_fetch_assoc($result);
-            $product_name = htmlspecialcharsFix($row['ProductName']);
-            $product_img = htmlspecialcharsFix($row['ProductImg']);
-            $unit = htmlspecialcharsFix($row['unit']);
-            $moq = htmlspecialcharsFix($row['moq']);
-            $nosale = $row['nosale'];
-            $note = htmlspecialcharsFix($row['note']);
-            $tips = htmlspecialcharsFix($row['tips']);
-            $category_id = $row['category_id'] ? intval($row['category_id']) : 0;
-        } else {
-            // Product not found, redirect
-            header("Location: ?Keys=" . $keys . "&Page=" . $page);
-            exit();
-        }
-    }
-    
-    $href_str = "?keys=" . $keys . "&Page=" . $page;
-    ?>
-    <form name="form1" method="post" action="<?php echo $href_str; ?>&act=save">
-        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
-            <tbody>
-                <tr>
-                    <th width="8%">产品名称</th>
-                    <td><input type="text" id="ProductName" name="ProductName" value="<?php echo $product_name; ?>" class="txt1" />
-                    <input type="hidden" name="id" value="<?php echo $id; ?>" /></td>
-                </tr>
-                <tr>
-                    <th width="8%">产品分类</th>
-                    <td>
-                        <select name="category_id" id="category_id" class="select1">
-                            <option value="0">-- 请选择分类 --</option>
-                            <?php
-                            // Include the category display functions
-                            require_once 'functions.php';
-                            
-                            // Build category tree
-                            $category_data = buildCategoryTree($conn);
-                            $cat_tree = $category_data['tree'];
-                            
-                            // Output options
-                            outputCategoryOptions($cat_tree, $category_id);
-                            ?>
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <th width="8%">产品图片</th>
-                    <td><input type="text" id="ProductImg" name="ProductImg" placeholder="186x*186px" value="<?php echo $product_img; ?>" class="txt1" style="width:390px;float:left;" />
-                    <iframe src="uploadfile.php" frameborder="0" scrolling="no" style="width:400px;height:22px;float:left;margin-left:10px;"></iframe></td>
-                </tr>
-                <tr>
-                    <th width="8%">计价单位</th>
-                    <td><input type="text" id="unit" name="unit" value="<?php echo $unit; ?>" class="txt1"/></td>
-                </tr>
-                <tr>
-                    <th width="8%">起订数量</th>
-                    <td><input type="text" id="moq" name="moq" value="<?php echo $moq; ?>" class="txt1"/></td>
-                </tr>
-                <tr>
-                    <th width="8%">默认售价</th>
-                    <td>
-                        <div class="Price">
-                        <?php
-                        if ($is_edit) {
-                            $price_sql = "SELECT num, price FROM price WHERE AreaId = 0 AND productId = " . $id . " ORDER BY num ASC";
-                            $price_result = mysqli_query($conn, $price_sql);
-                            if (mysqli_num_rows($price_result) > 0) {
-                                while ($price_row = mysqli_fetch_assoc($price_result)) {
-                                    ?>
-                                    <div class="priceitem">
-                                        <label>≥</label>
-                                        <input type="number" class="txt3 num" name="num[]" value="<?php echo $price_row['num']; ?>">
-                                        <label class="unit"><?php echo $unit; ?></label>
-                                        <label>售价</label>
-                                        <input type="text" class="txt3 price" name="price[]" value="<?php echo $price_row['price']; ?>">
-                                        <label>RMB</label>
-                                        <span class="additem"></span>
-                                        <span class="delitem"></span>
-                                        <span class="note"></span>
-                                    </div>
-                                    <?php
-                                }
-                            }
-                        }
-                        if (!$is_edit || mysqli_num_rows($price_result) == 0) {
-                            ?>
-                            <div class="priceitem">
-                                <label>≥</label>
-                                <input type="number" class="txt3 num" name="num[]">
-                                <label class="unit"><?php echo $unit; ?></label>
-                                <label>售价</label>
-                                <input type="text" class="txt3 price" name="price[]">
-                                <label>RMB</label>
-                                <span class="additem"></span>
-                                <span class="delitem"></span>
-                                <span class="note"></span>
-                            </div>
-                            <?php
-                        }
-                        ?>
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <th width="8%">不报价地区</th>
-                    <td>
-                        <ul class="areadd">
-                        <?php
-                        if (!empty($nosale)) {
-                            // 确保nosale是逗号分隔的字符串格式
-                            $nosale_str = is_array($nosale) ? implode(',', $nosale) : $nosale;
-                            $area_sql = "SELECT id, countryName FROM country WHERE id IN(" . $nosale_str . ")";
-                            $area_result = mysqli_query($conn, $area_sql);
-                            while ($area_row = mysqli_fetch_assoc($area_result)) {
-                                ?>
-                                <li><input type="hidden" name="nosale[]" value="<?php echo $area_row['id']; ?>"><span class="cname"><?php echo htmlspecialcharsFix($area_row['countryName']); ?></span><span class="close"></span></li>
-                                <?php
-                            }
-                        }
-                        ?>
-                        </ul>
-                        <input type="text" id="AreaSearch" class="fastsearch">
-                        <div id="arealist" class="productlist"><ul></ul></div>
-                    </td>
-                </tr>
-                <tr>
-                    <th width="8%">不报价处理方式</th>
-                    <td><input type="text" id="note" name="note" value="<?php echo $note; ?>" class="txt1"/></td>
-                </tr>
-                <tr>
-                    <th width="8%">备注</th>
-                    <td><input type="text" id="tips" name="tips" value="<?php echo $tips; ?>" class="txt1"/></td>
-                </tr>
-                <tr>
-                    <th></th>
-                    <td colspan="2">
-                        <input type="submit" name="save" value="确定" class="btn1" />
-                        <input type="reset" name="reset" value="重置" class="btn1" />
-                        <input type="button" value="返回" class="btn1" onClick="location.href='<?php echo $href_str; ?>'" />
-                    </td>
-                </tr>
-            </tbody>
-        </table>
-    </form>
-    <?php
-} else {
-    // Display product list
-    require_once 'functions.php';
-    
-    // Get filter category id
-    $filter_category_id = isset($_GET['category_id']) ? intval($_GET['category_id']) : 0;
-    
-    // Prepare SQL condition for category filtering
-    $category_condition = '';
-    if ($filter_category_id > 0) {
-        // Get all subcategories of the selected category
-        $category_data = buildCategoryTree($conn);
-        $all_categories = $category_data['all_categories'];
-        
-        $category_ids = array($filter_category_id);
-        getSubcategoryIds($all_categories, $filter_category_id, $category_ids);
-        
-        $category_condition = " WHERE category_id IN (" . implode(',', $category_ids) . ")";
-    }
-    
-    // Search condition
-    $search_condition = '';
-    if (!empty($keyscode)) {
-        $search_condition = ($category_condition ? " AND " : " WHERE ") . 
-                           "ProductName LIKE '%" . mysqli_real_escape_string($conn, $keyscode) . "%'";
-    }
-    
-    // Get total records count using a COUNT query instead of fetching all records
-    $count_sql = "SELECT COUNT(*) as total FROM products" . $category_condition . $search_condition;
-    $count_result = mysqli_query($conn, $count_sql);
-    $count_row = mysqli_fetch_assoc($count_result);
-    $total_records = $count_row['total'];
-    
-    // 固定每页显示18条记录(与 customers.php 保持一致)
-    $pageSize = 18;
-    $total_pages = ceil($total_records / $pageSize);
-    if ($total_pages < 1) $total_pages = 1; // 确保至少有一页,即使没有结果
-    
-    // Validate page number
-    if (empty($page)) $page = 1;
-    if ($page == 'end') $page = $total_pages;
-    if (!is_numeric($page) || $page < 1) $page = 1;
-    $page = (int)$page;
-    if ($page > $total_pages) $page = $total_pages;
-    
-    // Apply pagination
-    $offset = ($page - 1) * $pageSize;
-    if ($offset < 0) $offset = 0; // 确保偏移量不为负数
+// Display product list
+require_once 'functions.php';
+
+// Get filter category id
+$filter_category_id = $category_id;
+
+// Prepare SQL condition for category filtering
+$category_condition = '';
+if ($filter_category_id > 0) {
+    // Get all subcategories of the selected category
+    $category_data = buildCategoryTree($conn);
+    $all_categories = $category_data['all_categories'];
     
-    // Fetch only the records for the current page
-    $sql = "SELECT id, ProductName, ProductImg, category_id FROM products" . 
-           $category_condition . $search_condition . " ORDER BY id DESC LIMIT $offset, $pageSize";
-    $result = mysqli_query($conn, $sql);
+    $category_ids = array($filter_category_id);
+    getSubcategoryIds($all_categories, $filter_category_id, $category_ids);
     
-    $temp_num = $pageSize * ($page - 1);
-    ?>
-    <div class="search_panel">
-        <form method="get" action="">
-            <input type="hidden" name="Page" value="1">
-            <div style="display: flex; margin-bottom: 10px;style="margin-left: 20px;"">
+    $category_condition = " WHERE category_id IN (" . implode(',', $category_ids) . ")";
+}
+
+// Search condition
+$search_condition = '';
+if (!empty($keyscode)) {
+    $search_condition = ($category_condition ? " AND " : " WHERE ") . 
+                       "ProductName LIKE '%" . mysqli_real_escape_string($conn, $keyscode) . "%'";
+}
+
+// Get total records count using a COUNT query instead of fetching all records
+$count_sql = "SELECT COUNT(*) as total FROM products" . $category_condition . $search_condition;
+$count_result = mysqli_query($conn, $count_sql);
+$count_row = mysqli_fetch_assoc($count_result);
+$total_records = $count_row['total'];
+
+// 固定每页显示18条记录(与 customers.php 保持一致)
+$pageSize = 18;
+$total_pages = ceil($total_records / $pageSize);
+if ($total_pages < 1) $total_pages = 1; // 确保至少有一页,即使没有结果
+
+// Validate page number
+if (empty($page)) $page = 1;
+if ($page == 'end') $page = $total_pages;
+if (!is_numeric($page) || $page < 1) $page = 1;
+$page = (int)$page;
+if ($page > $total_pages) $page = $total_pages;
+
+// Apply pagination
+$offset = ($page - 1) * $pageSize;
+if ($offset < 0) $offset = 0; // 确保偏移量不为负数
+
+// Fetch only the records for the current page
+$sql = "SELECT id, ProductName, ProductImg, category_id FROM products" . 
+       $category_condition . $search_condition . " ORDER BY id DESC LIMIT $offset, $pageSize";
+$result = mysqli_query($conn, $sql);
+
+$temp_num = $pageSize * ($page - 1);
+?>
+<div class="search_panel">
+    <form method="get" action="">
+        <input type="hidden" name="Page" value="1">
+        <div style="display: flex; margin-bottom: 10px;style="margin-left: 20px;"">
+        <div style="margin-right: 20px;">
+            <input type="button" value="+ 新增产品" onClick="location.href='?act=add<?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>'" class="add_btn" />
+        </div>
             <div style="margin-right: 20px;">
-                <input type="button" value="+ 新增产品" onClick="location.href='?act=add<?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>'" class="add_btn" />
+                <label>按分类筛选:</label>
+                <select name="category_id" class="select1" onchange="this.form.submit()">
+                    <option value="0">-- 所有分类 --</option>
+                    <?php
+                    // Build category tree for filter dropdown
+                    $category_data = buildCategoryTree($conn);
+                    $cat_tree = $category_data['tree'];
+                    
+                    // Output options
+                    outputCategoryOptions($cat_tree, $filter_category_id);
+                    ?>
+                </select>
             </div>
-                <div style="margin-right: 20px;">
-                    <label>按分类筛选:</label>
-                    <select name="category_id" class="select1" onchange="this.form.submit()">
-                        <option value="0">-- 所有分类 --</option>
-                        <?php
-                        // Build category tree for filter dropdown
-                        $category_data = buildCategoryTree($conn);
-                        $cat_tree = $category_data['tree'];
-                        
-                        // Output options
-                        outputCategoryOptions($cat_tree, $filter_category_id);
-                        ?>
-                    </select>
-                </div>
-                <div>
-                    <label>关键词搜索:</label>
-                    <input type="text" name="Keys" value="<?php echo $keyscode; ?>" class="inputTxt" placeholder="请输入产品名称">
-                    <input type="submit" value="搜索" class="searchgo">
-                </div>
-
+            <div>
+                <label>关键词搜索:</label>
+                <input type="text" name="Keys" value="<?php echo $keyscode; ?>" class="inputTxt" placeholder="请输入产品名称">
+                <input type="submit" value="搜索" class="searchgo">
             </div>
-        </form>
-    </div>
-    <form id="form1" method="post" action="?act=postchk&Keys=<?php echo $keys; ?>&Page=<?php echo $page; ?><?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>" onSubmit="return false">
-        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
-            <thead>
-                <tr>
-                    <th width="4%"><input type="checkbox" name="chkall" id="chkall" onClick="chkboxall(this,'chkbox')" /></th>
-                    <th width="6%">序号</th>
-                    <th width="25%">产品名称</th>
-                    <th width="15%">产品分类</th>
-                    <th width="30%">图片</th>
-                    <th width="20%">操作</th>
-                </tr>
-            </thead>
-            <tbody>
-            <?php
-            if (mysqli_num_rows($result) > 0) {
-                $temp_num = $pageSize * ($page - 1);
-                while ($row = mysqli_fetch_assoc($result)) {
-                    $temp_num++;
-                    ?>
-                    <tr onMouseOver="this.style.background='#F7FCFF'" onMouseOut="this.style.background='#FFFFFF'">
-                        <td align="center"><input type="checkbox" name="chkbox[]" value="<?php echo $row['id']; ?>" /></td>
-                        <td align="center"><?php echo $temp_num; ?></td>
-                        <td align="center"><?php echo htmlspecialcharsFix($row['ProductName']); ?></td>
-                        <td align="center">
-                            <?php 
-                            require_once 'functions.php';
-                            echo getCategoryPath($conn, $row['category_id']); 
-                            ?>
-                        </td>
-                        <td align="center"><img src="<?php echo htmlspecialcharsFix($row['ProductImg']); ?>" width="30px"></td>
-                        <td align="center">
-                            <a href="?Keys=<?php echo $keys; ?>&Page=<?php echo $page; ?>&act=edit&id=<?php echo $row['id']; ?>" class="ico_edit ico">修改</a>
-                        </td>
-                    </tr>
-                    <?php
-                }
-            } else {
+
+        </div>
+    </form>
+</div>
+
+<form id="form1" method="post" action="?act=postchk&Keys=<?php echo $keys; ?>&Page=<?php echo $page; ?><?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>">
+    <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
+        <thead>
+            <tr>
+                <th width="4%"><input type="checkbox" name="chkall" id="chkall" onClick="chkboxall(this,'chkbox')" /></th>
+                <th width="6%">序号</th>
+                <th width="25%">产品名称</th>
+                <th width="15%">产品分类</th>
+                <th width="30%">图片</th>
+                <th width="10%">规格数量</th>
+                <th width="20%">操作</th>
+            </tr>
+        </thead>
+        <tbody>
+        <?php
+        if (mysqli_num_rows($result) > 0) {
+            $temp_num = $pageSize * ($page - 1);
+            while ($row = mysqli_fetch_assoc($result)) {
+                $temp_num++;
                 ?>
-                <tr>
-                    <td colspan="9" align="center">
-                        <?php echo empty($keys) ? 'Sorry,当前暂无信息' : '<a href="?">Sorry,没有找到"' . htmlspecialcharsFix($keyscode) . '"相关的信息,点击返回</a>'; ?>
+                <tr onMouseOver="this.style.background='#F7FCFF'" onMouseOut="this.style.background='#FFFFFF'">
+                    <td align="center"><input type="checkbox" name="chkbox[]" value="<?php echo $row['id']; ?>" /></td>
+                    <td align="center"><?php echo $temp_num; ?></td>
+                    <td align="center"><?php echo htmlspecialcharsFix($row['ProductName']); ?></td>
+                    <td align="center">
+                        <?php 
+                        require_once 'functions.php';
+                        echo getCategoryPath($conn, $row['category_id']); 
+                        ?>
+                    </td>
+                    <td align="center"><img src="<?php echo htmlspecialcharsFix($row['ProductImg']); ?>" width="30px"></td>
+                    <td align="center">
+                        <?php 
+                        // Count specifications for this product
+                        $spec_sql = "SELECT COUNT(*) as spec_count FROM product_specifications WHERE product_id = " . $row['id'];
+                        $spec_result = mysqli_query($conn, $spec_sql);
+                        $spec_row = mysqli_fetch_assoc($spec_result);
+                        echo $spec_row['spec_count']; 
+                        ?>
+                    </td>
+                    <td align="center">
+                        <a href="?Keys=<?php echo $keys; ?>&Page=<?php echo $page; ?>&act=edit&id=<?php echo $row['id']; ?><?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>" class="ico_edit ico">修改</a>
                     </td>
                 </tr>
                 <?php
             }
+        } else {
             ?>
-            </tbody>
-            <tfoot>
-                <tr>
-                    <td colspan="9">
-                        <div class="showpagebox">
-                        <?php
-                        if ($total_pages > 1) {
-                            // Build page URL with all parameters
-                            $page_params = array();
-                            if (!empty($keys)) $page_params[] = "Keys=" . urlencode($keys);
-                            if ($filter_category_id > 0) $page_params[] = "category_id=" . $filter_category_id;
-                            
-                            $page_name = "?" . implode("&", $page_params) . ($page_params ? "&" : "");
-                            $page_len = 3;
-                            
-                            // Previous page links
-                            if ($page > 1) {
-                                echo "<a href=\"{$page_name}Page=1\">首页</a>";
-                                echo "<a href=\"{$page_name}Page=" . ($page-1) . "\">上一页</a>";
-                            }
-                            
-                            // Calculate page range
-                            if ($page_len * 2 + 1 >= $total_pages) {
+            <tr>
+                <td colspan="9" align="center">
+                    <?php echo empty($keys) ? 'Sorry,当前暂无信息' : '<a href="?">Sorry,没有找到"' . htmlspecialcharsFix($keyscode) . '"相关的信息,点击返回</a>'; ?>
+                </td>
+            </tr>
+            <?php
+        }
+        ?>
+        </tbody>
+        <tfoot>
+            <tr>
+                <td colspan="9">
+                    <div class="showpagebox">
+                    <?php
+                    if ($total_pages > 1) {
+                        // Build page URL with all parameters
+                        $page_params = array();
+                        if (!empty($keys)) $page_params[] = "Keys=" . urlencode($keys);
+                        if ($filter_category_id > 0) $page_params[] = "category_id=" . $filter_category_id;
+                        
+                        $page_name = "?" . implode("&", $page_params) . ($page_params ? "&" : "");
+                        $page_len = 3;
+                        
+                        // Previous page links
+                        if ($page > 1) {
+                            echo "<a href=\"{$page_name}Page=1\">首页</a>";
+                            echo "<a href=\"{$page_name}Page=" . ($page-1) . "\">上一页</a>";
+                        }
+                        
+                        // Calculate page range
+                        if ($page_len * 2 + 1 >= $total_pages) {
+                            $start_page = 1;
+                            $end_page = $total_pages;
+                        } else {
+                            if ($page <= $page_len + 1) {
                                 $start_page = 1;
-                                $end_page = $total_pages;
+                                $end_page = $page_len * 2 + 1;
                             } else {
-                                if ($page <= $page_len + 1) {
-                                    $start_page = 1;
-                                    $end_page = $page_len * 2 + 1;
-                                } else {
-                                    $start_page = $page - $page_len;
-                                    $end_page = $page + $page_len;
-                                }
-                                if ($page + $page_len > $total_pages) {
-                                    $start_page = $total_pages - $page_len * 2;
-                                    $end_page = $total_pages;
-                                }
+                                $start_page = $page - $page_len;
+                                $end_page = $page + $page_len;
                             }
-                            
-                            // Page numbers
-                            for ($i = $start_page; $i <= $end_page; $i++) {
-                                if ($i == $page) {
-                                    echo "<a class=\"current\">$i</a>";
-                                } else {
-                                    echo "<a href=\"{$page_name}Page=$i\">$i</a>";
-                                }
+                            if ($page + $page_len > $total_pages) {
+                                $start_page = $total_pages - $page_len * 2;
+                                $end_page = $total_pages;
                             }
-                            
-                            // Next page links
-                            if ($page < $total_pages) {
-                                if ($total_pages - $page > $page_len) {
-                                    echo "<a href=\"{$page_name}Page=$total_pages\">...$total_pages</a>";
-                                }
-                                echo "<a href=\"{$page_name}Page=" . ($page+1) . "\">下一页</a>";
-                                echo "<a href=\"{$page_name}Page=$total_pages\">尾页</a>";
+                        }
+                        
+                        // Page numbers
+                        for ($i = $start_page; $i <= $end_page; $i++) {
+                            if ($i == $page) {
+                                echo "<a class=\"current\">$i</a>";
+                            } else {
+                                echo "<a href=\"{$page_name}Page=$i\">$i</a>";
                             }
-                            
-                            // Jump to page input
-                            echo "<input type=\"text\" id=\"Pagego\" value=\"$page\" 
-                                  onFocus=\"if(this.value == '$page'){this.value='';}\" 
-                                  onBlur=\"if(this.value == ''){this.value='$page';}\" 
-                                  onKeyUp=\"this.value=this.value.replace(/\D/g,'')\" 
-                                  onKeyDown=\"if(event.keyCode==13){location.href='{$page_name}Page='+document.getElementById('Pagego').value}\" />";
                         }
-                        ?>
-                        </div>
                         
-                        <div class="postchkbox">
-                            <select id="chkact" name="chkact">
-                                <option value="1">显示</option>
-                                <option value="0">隐藏</option>
-                                <option value="-1">删除</option>
-                            </select>
-                            <input type="button" value="执行" onClick="postchk(1)" class="btn1" />
-                            <input type="button" value="新增" onClick="location.href='?act=add'" class="btn1" />
-                        </div>
-                    </td>
-                </tr>
-            </tfoot>
-        </table>
-    </form>
-    <?php
-}
-mysqli_close($conn);
-?>
+                        // Next page links
+                        if ($page < $total_pages) {
+                            if ($total_pages - $page > $page_len) {
+                                echo "<a href=\"{$page_name}Page=$total_pages\">...$total_pages</a>";
+                            }
+                            echo "<a href=\"{$page_name}Page=" . ($page+1) . "\">下一页</a>";
+                            echo "<a href=\"{$page_name}Page=$total_pages\">尾页</a>";
+                        }
+                        
+                        // Jump to page input
+                        echo "<input type=\"text\" id=\"Pagego\" value=\"$page\" 
+                              onFocus=\"if(this.value == '$page'){this.value='';}\" 
+                              onBlur=\"if(this.value == ''){this.value='$page';}\" 
+                              onKeyUp=\"this.value=this.value.replace(/\D/g,'')\" 
+                              onKeyDown=\"if(event.keyCode==13){location.href='{$page_name}Page='+document.getElementById('Pagego').value}\" />";
+                    }
+                    ?>
+                    </div>
+                    
+                    <div class="postchkbox">
+                        <select id="chkact" name="chkact">
+
+                            <option value="-1">删除</option>
+                        </select>
+                        <input type="button" value="执行" onClick="postchk_products(1)" class="btn1" />
+                        <input type="button" value="新增" onClick="location.href='?act=add<?php echo $filter_category_id ? '&category_id='.$filter_category_id : ''; ?>'" class="btn1" />
+                    </div>
+                </td>
+            </tr>
+        </tfoot>
+    </table>
+</form>
 </div>
+<script type="application/javascript">
+
+    function postchk_products(formBtn) {
+        // Check if at least one checkbox is selected
+        var checkboxes = document.getElementsByName('chkbox[]');
+        var isChecked = false;
+
+        for (var i = 0; i < checkboxes.length; i++) {
+            if (checkboxes[i].checked) {
+                isChecked = true;
+                break;
+            }
+        }
+
+        if (!isChecked) {
+            alert('请至少选择一条数据');
+            return false;
+        }
+
+        // If at least one checkbox is selected, submit the form
+        document.getElementById('form1').submit();
+        return true;
+    }
+</script>
 </body>
-</html> 
+</html>
+<?php mysqli_close($conn); ?> 

+ 161 - 0
system/save_product.php

@@ -0,0 +1,161 @@
+<?php
+require_once('conn.php');
+
+// Check login status
+checkLogin("信息管理");
+
+// Initialize all variables to avoid undefined warnings
+$id = isset($_POST['id']) ? $_POST['id'] : '';
+$product_name = isset($_POST['ProductName']) ? htmlspecialcharsFix($_POST['ProductName']) : '';
+$product_img = isset($_POST['ProductImg']) ? htmlspecialcharsFix($_POST['ProductImg']) : '';
+$unit = isset($_POST['unit']) ? htmlspecialcharsFix($_POST['unit']) : '';
+$moq = isset($_POST['moq']) ? htmlspecialcharsFix($_POST['moq']) : '';
+$category_id = isset($_POST['category_id']) ? intval($_POST['category_id']) : 0;
+$nosale = isset($_POST['nosale']) ? $_POST['nosale'] : array();
+$note = isset($_POST['note']) ? htmlspecialcharsFix($_POST['note']) : '';
+$tips = isset($_POST['tips']) ? htmlspecialcharsFix($_POST['tips']) : '';
+$keys = isset($_POST['keys']) ? $_POST['keys'] : '';
+$page = isset($_POST['page']) ? $_POST['page'] : 1;
+
+// Initialize specification variables
+$spec_name = isset($_POST['spec_name']) ? $_POST['spec_name'] : array();
+$spec_value = isset($_POST['spec_value']) ? $_POST['spec_value'] : array();
+$spec_price = isset($_POST['spec_price']) ? $_POST['spec_price'] : array();
+$spec_moq = isset($_POST['spec_moq']) ? $_POST['spec_moq'] : array();
+$spec_code = isset($_POST['spec_code']) ? $_POST['spec_code'] : array();
+$spec_sort = isset($_POST['spec_sort']) ? $_POST['spec_sort'] : array();
+
+// Redirect URL
+$redirect_url = "products.php?Keys=" . $keys . "&Page=" . $page;
+if ($category_id) {
+    $redirect_url .= "&category_id=" . $category_id;
+}
+
+// Determine if this is an edit or a new record
+$is_edit = (!empty($id) && is_numeric($id));
+
+// Process nosale array into comma-separated string
+$nosale_str = '';
+if (is_array($nosale) && !empty($nosale)) {
+    $nosale_clean = array_map('intval', $nosale); // Ensure all values are integers
+    $nosale_str = implode(',', $nosale_clean);
+}
+
+// Validate form data
+if (empty($product_name)) {
+    // You could add error handling here
+    header("Location: " . $redirect_url);
+    exit();
+}
+
+// Validate specifications - at least one specification is required with all fields filled
+$has_valid_specs = false;
+if (is_array($spec_name) && !empty($spec_name)) {
+    foreach ($spec_name as $key => $name) {
+        if (!empty($name) && isset($spec_price[$key]) && !empty($spec_price[$key]) && 
+            isset($spec_moq[$key]) && !empty($spec_moq[$key])) {
+            $has_valid_specs = true;
+            break;
+        }
+    }
+}
+
+if (!$has_valid_specs) {
+    // Redirect back with error message
+    header("Location: " . $redirect_url . "&error=missing_specs");
+    exit();
+}
+
+if ($is_edit) {
+    // Update existing product
+    $sql = "UPDATE products SET 
+            ProductName = '" . mysqli_real_escape_string($conn, $product_name) . "',
+            ProductImg = '" . mysqli_real_escape_string($conn, $product_img) . "',
+            Addtime = NOW(),
+            moq = '" . mysqli_real_escape_string($conn, $moq) . "',
+            unit = '" . mysqli_real_escape_string($conn, $unit) . "',
+            nosale = '" . $nosale_str . "',
+            note = '" . mysqli_real_escape_string($conn, $note) . "',
+            tips = '" . mysqli_real_escape_string($conn, $tips) . "',
+            category_id = " . $category_id . "
+            WHERE id = " . (int)$id;
+    mysqli_query($conn, $sql);
+    
+    // Clear existing specifications for this product
+    mysqli_query($conn, "DELETE FROM product_specifications WHERE product_id = " . (int)$id);
+    
+    // Add new specifications
+    if (is_array($spec_name) && !empty($spec_name)) {
+        foreach ($spec_name as $key => $name) {
+            if (!empty($name) && isset($spec_price[$key]) && !empty($spec_price[$key])) {
+                $spec_price_value = isset($spec_price[$key]) && is_numeric($spec_price[$key]) ? (float)$spec_price[$key] : 0;
+                $spec_moq_value = isset($spec_moq[$key]) && is_numeric($spec_moq[$key]) ? (int)$spec_moq[$key] : 1;
+                $spec_code_value = isset($spec_code[$key]) ? mysqli_real_escape_string($conn, $spec_code[$key]) : '';
+                $spec_sort_value = isset($spec_sort[$key]) && is_numeric($spec_sort[$key]) ? (int)$spec_sort[$key] : 0;
+                $spec_value_value = isset($spec_value[$key]) ? mysqli_real_escape_string($conn, $spec_value[$key]) : '';
+                
+                $sql = "INSERT INTO product_specifications 
+                        (product_id, spec_name, spec_value, price, min_order_quantity, spec_code, addtime, sort_order) 
+                        VALUES (
+                            " . (int)$id . ", 
+                            '" . mysqli_real_escape_string($conn, $name) . "', 
+                            '" . $spec_value_value . "', 
+                            " . $spec_price_value . ", 
+                            " . $spec_moq_value . ", 
+                            '" . $spec_code_value . "', 
+                            NOW(), 
+                            " . $spec_sort_value . "
+                        )";
+                mysqli_query($conn, $sql);
+            }
+        }
+    }
+} else {
+    // Insert new product
+    $sql = "INSERT INTO products (ProductName, ProductImg, Addtime, moq, unit, nosale, note, tips, category_id) 
+            VALUES (
+                '" . mysqli_real_escape_string($conn, $product_name) . "',
+                '" . mysqli_real_escape_string($conn, $product_img) . "',
+                NOW(),
+                '" . mysqli_real_escape_string($conn, $moq) . "',
+                '" . mysqli_real_escape_string($conn, $unit) . "',
+                '" . $nosale_str . "',
+                '" . mysqli_real_escape_string($conn, $note) . "',
+                '" . mysqli_real_escape_string($conn, $tips) . "',
+                " . $category_id . "
+            )";
+    mysqli_query($conn, $sql);
+    $id = mysqli_insert_id($conn);
+    
+    // Add specifications for new product
+    if (is_array($spec_name) && !empty($spec_name)) {
+        foreach ($spec_name as $key => $name) {
+            if (!empty($name) && isset($spec_price[$key]) && !empty($spec_price[$key])) {
+                $spec_price_value = isset($spec_price[$key]) && is_numeric($spec_price[$key]) ? (float)$spec_price[$key] : 0;
+                $spec_moq_value = isset($spec_moq[$key]) && is_numeric($spec_moq[$key]) ? (int)$spec_moq[$key] : 1;
+                $spec_code_value = isset($spec_code[$key]) ? mysqli_real_escape_string($conn, $spec_code[$key]) : '';
+                $spec_sort_value = isset($spec_sort[$key]) && is_numeric($spec_sort[$key]) ? (int)$spec_sort[$key] : 0;
+                $spec_value_value = isset($spec_value[$key]) ? mysqli_real_escape_string($conn, $spec_value[$key]) : '';
+                
+                $sql = "INSERT INTO product_specifications 
+                        (product_id, spec_name, spec_value, price, min_order_quantity, spec_code, addtime, sort_order) 
+                        VALUES (
+                            " . (int)$id . ", 
+                            '" . mysqli_real_escape_string($conn, $name) . "', 
+                            '" . $spec_value_value . "', 
+                            " . $spec_price_value . ", 
+                            " . $spec_moq_value . ", 
+                            '" . $spec_code_value . "', 
+                            NOW(), 
+                            " . $spec_sort_value . "
+                        )";
+                mysqli_query($conn, $sql);
+            }
+        }
+    }
+}
+
+// Redirect after save
+mysqli_close($conn);
+header("Location: " . $redirect_url);
+exit(); 

+ 104 - 12
tag.php

@@ -79,11 +79,33 @@ while ($row = $result->fetch_assoc()) {
             </div>
 
             <?php
-            $sqlStr = "SELECT id, cs_code, cs_from, cs_country, cs_type, cs_deal, cs_addtime, cs_tel, cs_email, 
-                      cs_whatsapp, cs_wechat, cs_linkedin, cs_facebook, cs_alibaba, cs_note 
-                      FROM customer 
-                      WHERE cs_belong=" . $_SESSION['employee_id'] . " 
-                      AND id IN (SELECT customerId FROM tagtable WHERE tagName='" . $conn->real_escape_string($tagName) . "')";
+            $sqlStr = "SELECT c.id, c.cs_code, c.cs_from, c.cs_country, c.cs_type, c.cs_deal, c.cs_addtime, c.cs_note,
+                      cc.id as contact_id, cc.contact_name,
+                      cc.tel_1, cc.tel_1_format, cc.tel_1_bu,
+                      cc.tel_2, cc.tel_2_format, cc.tel_2_bu,
+                      cc.tel_3, cc.tel_3_format, cc.tel_3_bu,
+                      cc.email_1, cc.email_1_bu,
+                      cc.email_2, cc.email_2_bu,
+                      cc.email_3, cc.email_3_bu,
+                      cc.whatsapp_1, cc.whatsapp_1_format, cc.whatsapp_1_bu,
+                      cc.whatsapp_2, cc.whatsapp_2_format, cc.whatsapp_2_bu,
+                      cc.whatsapp_3, cc.whatsapp_3_format, cc.whatsapp_3_bu,
+                      cc.wechat_1, cc.wechat_1_bu,
+                      cc.wechat_2, cc.wechat_2_bu,
+                      cc.wechat_3, cc.wechat_3_bu,
+                      cc.linkedin_1, cc.linkedin_1_bu,
+                      cc.linkedin_2, cc.linkedin_2_bu,
+                      cc.linkedin_3, cc.linkedin_3_bu,
+                      cc.facebook_1, cc.facebook_1_bu,
+                      cc.facebook_2, cc.facebook_2_bu,
+                      cc.facebook_3, cc.facebook_3_bu,
+                      cc.alibaba_1, cc.alibaba_1_bu,
+                      cc.alibaba_2, cc.alibaba_2_bu,
+                      cc.alibaba_3, cc.alibaba_3_bu
+                      FROM customer c
+                      LEFT JOIN customer_contact cc ON c.id = cc.customer_id
+                      WHERE c.cs_belong=" . $_SESSION['employee_id'] . " 
+                      AND c.id IN (SELECT customerId FROM tagtable WHERE tagName='" . $conn->real_escape_string($tagName) . "')";
 
             $result = $conn->query($sqlStr);
             $tempNum = 0;
@@ -126,13 +148,83 @@ while ($row = $result->fetch_assoc()) {
                 <div class="notepanel clear">
                     <div class="noteItem">联系方式</div>
                     <div class="lx">
-                        <div class="tel"><?= htmlspecialcharsFix($row['cs_tel']) ?></div>
-                        <div class="mail"><a href="mailto:<?= htmlspecialcharsFix($row['cs_email']) ?>"><?= htmlspecialcharsFix($row['cs_email']) ?></a></div>
-                        <div class="whatsapp"><?= htmlspecialcharsFix($row['cs_whatsapp']) ?></div>
-                        <div class="wechat"><?= htmlspecialcharsFix($row['cs_wechat']) ?></div>
-                        <div class="linkedin"><?= htmlspecialcharsFix($row['cs_linkedin']) ?></div>
-                        <div class="facebook"><?= htmlspecialcharsFix($row['cs_facebook']) ?></div>
-                        <div class="alibaba"><?= htmlspecialcharsFix($row['cs_alibaba']) ?></div>
+                        <div class="tel">
+                            <?php if(!empty($row['tel_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['tel_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['tel_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['tel_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="mail">
+                            <?php if(!empty($row['email_1'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_1']) ?>"><?= htmlspecialcharsFix($row['email_1']) ?></a></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['email_2'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_2']) ?>"><?= htmlspecialcharsFix($row['email_2']) ?></a></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['email_3'])): ?>
+                                <div><a href="mailto:<?= htmlspecialcharsFix($row['email_3']) ?>"><?= htmlspecialcharsFix($row['email_3']) ?></a></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="whatsapp">
+                            <?php if(!empty($row['whatsapp_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['whatsapp_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['whatsapp_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['whatsapp_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="wechat">
+                            <?php if(!empty($row['wechat_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['wechat_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['wechat_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['wechat_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="linkedin">
+                            <?php if(!empty($row['linkedin_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['linkedin_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['linkedin_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['linkedin_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="facebook">
+                            <?php if(!empty($row['facebook_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['facebook_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['facebook_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['facebook_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
+                        <div class="alibaba">
+                            <?php if(!empty($row['alibaba_1'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_1']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['alibaba_2'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_2']) ?></div>
+                            <?php endif; ?>
+                            <?php if(!empty($row['alibaba_3'])): ?>
+                                <div><?= htmlspecialcharsFix($row['alibaba_3']) ?></div>
+                            <?php endif; ?>
+                        </div>
                     </div>
                     <div class="noteItem2">备注</div>
                     <div class="notecontent"><?= htmlUnCode($row['cs_note']) ?></div>

+ 9 - 10
tagClound.php

@@ -29,18 +29,17 @@ checkLogin();
         <h1 class="tagCloundHead">自定义标签云</h1>
         <div class="tagArea">
         <?php
-        $result = $conn->query("SELECT tagName, COUNT(DISTINCT cs_code) as count 
-                               FROM tagtable 
-                               LEFT JOIN customer ON tagtable.customerId=customer.id 
-                               WHERE employeeId=" . $_SESSION['employee_id'] . " 
+        $result = $conn->query("SELECT tagName, COUNT(DISTINCT c.cs_code) as count 
+                               FROM tagtable t
+                               LEFT JOIN customer c ON t.customerId = c.id 
+                               WHERE t.employeeId = " . $_SESSION['employee_id'] . " 
                                GROUP BY tagName");
         
-        while ($row = $result->fetch_assoc()) {
-        ?>
-            <a href="tag.php?tagName=<?= urlencode($row['tagName']) ?>" style="font-size:16px;">
-                <?= htmlspecialcharsFix($row['tagName']) ?>(<?= $row['count'] ?>)
-            </a>
-        <?php
+        if ($result) {
+            while ($row = $result->fetch_assoc()) {
+                echo '<a href="tag.php?tagName=' . urlencode($row['tagName']) . '" style="font-size:16px;">' . 
+                     htmlspecialcharsFix($row['tagName']) . '(' . $row['count'] . ')</a>';
+            }
         }
         ?>
             <a href="nullTag.php">无标签客户</a>

Some files were not shown because too many files changed in this diff