综述: 添加数据分析模块
- 新增数据分析目录及相应的数据分析功能页面 - 实现数据统计和分析功能,为商户提供经营数据洞察
This commit is contained in:
		
							parent
							
								
									5aaa837e22
								
							
						
					
					
						commit
						26fafa296a
					
				|  | @ -0,0 +1,778 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="zh-CN"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>数据分析 - 商家端</title> | ||||
|     <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | ||||
|     <style> | ||||
|         * { | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|             box-sizing: border-box; | ||||
|         } | ||||
| 
 | ||||
|         body { | ||||
|             font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif; | ||||
|             background-color: #f5f5f5; | ||||
|             color: #333; | ||||
|             overflow-x: hidden; | ||||
|         } | ||||
| 
 | ||||
|         .container { | ||||
|             max-width: 1400px; | ||||
|             margin: 0 auto; | ||||
|             padding: 30px; | ||||
|         } | ||||
| 
 | ||||
|         /* 筛选区域 */ | ||||
|         .filter-section { | ||||
|             background: #fff; | ||||
|             padding: 20px; | ||||
|             border-radius: 8px; | ||||
|             margin-bottom: 30px; | ||||
|             box-shadow: 0 2px 8px rgba(0,0,0,0.1); | ||||
|         } | ||||
| 
 | ||||
|         .filter-row { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 20px; | ||||
|             flex-wrap: wrap; | ||||
|         } | ||||
| 
 | ||||
|         .filter-item { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 10px; | ||||
|         } | ||||
| 
 | ||||
|         .filter-item label { | ||||
|             font-weight: 500; | ||||
|             color: #333; | ||||
|             min-width: 70px; | ||||
|         } | ||||
| 
 | ||||
|         .filter-item select, | ||||
|         .filter-item input { | ||||
|             padding: 8px 12px; | ||||
|             border: 1px solid #d9d9d9; | ||||
|             border-radius: 4px; | ||||
|             min-width: 120px; | ||||
|             font-size: 14px; | ||||
|             transition: all 0.3s ease; | ||||
|         } | ||||
| 
 | ||||
|         .filter-item select:focus, | ||||
|         .filter-item input:focus { | ||||
|             border-color: #1890ff; | ||||
|             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | ||||
|             outline: none; | ||||
|         } | ||||
| 
 | ||||
|         .btn { | ||||
|             padding: 10px 20px; | ||||
|             border-radius: 5px; | ||||
|             font-size: 14px; | ||||
|             font-weight: 500; | ||||
|             transition: all 0.3s ease; | ||||
|             display: inline-flex; | ||||
|             align-items: center; | ||||
|             gap: 5px; | ||||
|             border: none; | ||||
|             cursor: pointer; | ||||
|         } | ||||
| 
 | ||||
|         .btn-primary { | ||||
|             background-color: #1890ff; | ||||
|             color: #fff; | ||||
|         } | ||||
| 
 | ||||
|         .btn-primary:hover { | ||||
|             background-color: #40a9ff; | ||||
|             transform: translateY(-2px); | ||||
|         } | ||||
| 
 | ||||
|         .btn-success { | ||||
|             background-color: #52c41a; | ||||
|             color: #fff; | ||||
|         } | ||||
| 
 | ||||
|         .btn-success:hover { | ||||
|             background-color: #73d13d; | ||||
|             transform: translateY(-2px); | ||||
|         } | ||||
| 
 | ||||
|         /* 数据卡片区域 */ | ||||
|         .stats-section { | ||||
|             display: grid; | ||||
|             grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | ||||
|             gap: 20px; | ||||
|             margin-bottom: 30px; | ||||
|         } | ||||
| 
 | ||||
|         .stats-card { | ||||
|             background: #fff; | ||||
|             padding: 20px; | ||||
|             border-radius: 8px; | ||||
|             box-shadow: 0 2px 8px rgba(0,0,0,0.1); | ||||
|             position: relative; | ||||
|             overflow: hidden; | ||||
|         } | ||||
| 
 | ||||
|         .stats-card::before { | ||||
|             content: ''; | ||||
|             position: absolute; | ||||
|             top: 0; | ||||
|             left: 0; | ||||
|             width: 4px; | ||||
|             height: 100%; | ||||
|             background: linear-gradient(45deg, #1890ff, #40a9ff); | ||||
|         } | ||||
| 
 | ||||
|         .stats-item { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: space-between; | ||||
|             margin-bottom: 15px; | ||||
|         } | ||||
| 
 | ||||
|         .stats-item:last-child { | ||||
|             margin-bottom: 0; | ||||
|         } | ||||
| 
 | ||||
|         .stats-label { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 8px; | ||||
|             font-size: 14px; | ||||
|             color: #666; | ||||
|         } | ||||
| 
 | ||||
|         .stats-icon { | ||||
|             width: 20px; | ||||
|             height: 20px; | ||||
|             border-radius: 50%; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             font-size: 12px; | ||||
|             color: #fff; | ||||
|         } | ||||
| 
 | ||||
|         .icon-view { background-color: #1890ff; } | ||||
|         .icon-visitor { background-color: #52c41a; } | ||||
|         .icon-new { background-color: #faad14; } | ||||
|         .icon-order { background-color: #f5222d; } | ||||
|         .icon-rate { background-color: #722ed1; } | ||||
|         .icon-purchase { background-color: #13c2c2; } | ||||
| 
 | ||||
|         .stats-value { | ||||
|             display: flex; | ||||
|             flex-direction: column; | ||||
|             align-items: flex-end; | ||||
|         } | ||||
| 
 | ||||
|         .stats-number { | ||||
|             font-size: 24px; | ||||
|             font-weight: bold; | ||||
|             color: #333; | ||||
|             margin-bottom: 2px; | ||||
|         } | ||||
| 
 | ||||
|         .stats-change { | ||||
|             font-size: 12px; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 2px; | ||||
|         } | ||||
| 
 | ||||
|         .stats-change.positive { | ||||
|             color: #52c41a; | ||||
|         } | ||||
| 
 | ||||
|         .stats-change.negative { | ||||
|             color: #f5222d; | ||||
|         } | ||||
| 
 | ||||
|         .stats-change.neutral { | ||||
|             color: #666; | ||||
|         } | ||||
| 
 | ||||
|         /* 图表区域 */ | ||||
|         .charts-section { | ||||
|             display: grid; | ||||
|             grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); | ||||
|             gap: 20px; | ||||
|         } | ||||
| 
 | ||||
|         .chart-section { | ||||
|             background: #fff; | ||||
|             padding: 20px; | ||||
|             border-radius: 8px; | ||||
|             box-shadow: 0 2px 8px rgba(0,0,0,0.1); | ||||
|         } | ||||
| 
 | ||||
|         .chart-header { | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|             margin-bottom: 20px; | ||||
|             padding-bottom: 15px; | ||||
|             border-bottom: 1px solid #e8e8e8; | ||||
|         } | ||||
| 
 | ||||
|         .chart-title { | ||||
|             font-size: 16px; | ||||
|             font-weight: 600; | ||||
|             color: #333; | ||||
|         } | ||||
| 
 | ||||
|         .chart-legend { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 20px; | ||||
|         } | ||||
| 
 | ||||
|         .legend-item { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             gap: 8px; | ||||
|             font-size: 14px; | ||||
|             color: #666; | ||||
|         } | ||||
| 
 | ||||
|         .legend-color { | ||||
|             width: 12px; | ||||
|             height: 12px; | ||||
|             border-radius: 50%; | ||||
|         } | ||||
| 
 | ||||
|         .chart-container { | ||||
|             position: relative; | ||||
|             height: 300px; | ||||
|             width: 100%; | ||||
|         } | ||||
| 
 | ||||
|         /* 响应式设计 */ | ||||
|         @media (max-width: 768px) { | ||||
|             .container { | ||||
|                 padding: 15px; | ||||
|             } | ||||
| 
 | ||||
|             .filter-row { | ||||
|                 flex-direction: column; | ||||
|                 align-items: stretch; | ||||
|             } | ||||
| 
 | ||||
|             .filter-item { | ||||
|                 flex-direction: column; | ||||
|                 align-items: stretch; | ||||
|                 gap: 5px; | ||||
|             } | ||||
| 
 | ||||
|             .filter-item label { | ||||
|                 min-width: auto; | ||||
|             } | ||||
| 
 | ||||
|             .stats-section { | ||||
|                 grid-template-columns: 1fr; | ||||
|             } | ||||
| 
 | ||||
|             .charts-section { | ||||
|                 grid-template-columns: 1fr; | ||||
|             } | ||||
| 
 | ||||
|             .chart-header { | ||||
|                 flex-direction: column; | ||||
|                 align-items: stretch; | ||||
|                 gap: 15px; | ||||
|             } | ||||
| 
 | ||||
|             .chart-legend { | ||||
|                 justify-content: center; | ||||
|                 flex-wrap: wrap; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /* 动画效果 */ | ||||
|         @keyframes fadeIn { | ||||
|             from { | ||||
|                 opacity: 0; | ||||
|                 transform: translateY(20px); | ||||
|             } | ||||
|             to { | ||||
|                 opacity: 1; | ||||
|                 transform: translateY(0); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         .stats-card, | ||||
|         .filter-section, | ||||
|         .chart-section { | ||||
|             animation: fadeIn 0.6s ease-out; | ||||
|         } | ||||
| 
 | ||||
|         .stats-card:nth-child(2) { animation-delay: 0.1s; } | ||||
|         .stats-card:nth-child(3) { animation-delay: 0.2s; } | ||||
|     </style> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="container"> | ||||
|         <!-- 筛选区域 --> | ||||
|         <div class="filter-section"> | ||||
|             <div class="filter-row"> | ||||
|                 <div class="filter-item"> | ||||
|                     <label>时间范围</label> | ||||
|                     <input type="date" id="startDate"> | ||||
|                     <span style="margin: 0 5px;">至</span> | ||||
|                     <input type="date" id="endDate"> | ||||
|                 </div> | ||||
|                 <button class="btn btn-primary" onclick="queryData()">查询</button> | ||||
|                 <button class="btn btn-success" onclick="exportData()">导出</button> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- 数据卡片区域 --> | ||||
|         <div class="stats-section"> | ||||
|             <div class="stats-card"> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-view">👁</div> | ||||
|                         展现量(次) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0</div> | ||||
|                         <div class="stats-change neutral">↑ 0.00%</div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-order">👤</div> | ||||
|                         支付订单人数(人) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0</div> | ||||
|                         <div class="stats-change neutral"></div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="stats-card"> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-visitor">👥</div> | ||||
|                         浏览人数(人) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0</div> | ||||
|                         <div class="stats-change neutral">↑ 0.00%</div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-rate">📊</div> | ||||
|                         支付订单转化率(%) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0.00%</div> | ||||
|                         <div class="stats-change neutral"></div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="stats-card"> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-new">⭐</div> | ||||
|                         新客数量(人) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0</div> | ||||
|                         <div class="stats-change neutral">↑ 0.00%</div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="stats-item"> | ||||
|                     <div class="stats-label"> | ||||
|                         <div class="stats-icon icon-purchase">💰</div> | ||||
|                         客户复购率(%) | ||||
|                     </div> | ||||
|                     <div class="stats-value"> | ||||
|                         <div class="stats-number">0.00%</div> | ||||
|                         <div class="stats-change neutral"></div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- 图表区域 --> | ||||
|         <div class="charts-section"> | ||||
|             <div class="chart-section"> | ||||
|                 <div class="chart-header"> | ||||
|                     <div class="chart-title">浏览数量趋势</div> | ||||
|                     <div class="chart-legend"> | ||||
|                         <div class="legend-item"> | ||||
|                             <div class="legend-color" style="background-color: #1890ff;"></div> | ||||
|                             浏览数量 | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="chart-container"> | ||||
|                     <canvas id="viewChart"></canvas> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="chart-section"> | ||||
|                 <div class="chart-header"> | ||||
|                     <div class="chart-title">浏览人数趋势</div> | ||||
|                     <div class="chart-legend"> | ||||
|                         <div class="legend-item"> | ||||
|                             <div class="legend-color" style="background-color: #52c41a;"></div> | ||||
|                             浏览人数 | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="chart-container"> | ||||
|                     <canvas id="visitorChart"></canvas> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="chart-section"> | ||||
|                 <div class="chart-header"> | ||||
|                     <div class="chart-title">新客数量趋势</div> | ||||
|                     <div class="chart-legend"> | ||||
|                         <div class="legend-item"> | ||||
|                             <div class="legend-color" style="background-color: #faad14;"></div> | ||||
|                             新客数量 | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="chart-container"> | ||||
|                     <canvas id="newCustomerChart"></canvas> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="chart-section"> | ||||
|                 <div class="chart-header"> | ||||
|                     <div class="chart-title">支付订单人数趋势</div> | ||||
|                     <div class="chart-legend"> | ||||
|                         <div class="legend-item"> | ||||
|                             <div class="legend-color" style="background-color: #f5222d;"></div> | ||||
|                             支付订单人数 | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="chart-container"> | ||||
|                     <canvas id="orderChart"></canvas> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <script> | ||||
|         // 初始化图表数据 | ||||
|         const chartLabels = []; | ||||
|         const chartData = []; | ||||
| 
 | ||||
|         // 生成最近30天的日期标签 | ||||
|         for (let i = 29; i >= 0; i--) { | ||||
|             const date = new Date(); | ||||
|             date.setDate(date.getDate() - i); | ||||
|             chartLabels.push(String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0')); | ||||
|             chartData.push(0); | ||||
|         } | ||||
| 
 | ||||
|         // 设置默认日期范围(最近30天) | ||||
|         const today = new Date(); | ||||
|         const thirtyDaysAgo = new Date(); | ||||
|         thirtyDaysAgo.setDate(today.getDate() - 30); | ||||
| 
 | ||||
|         document.getElementById('startDate').valueAsDate = thirtyDaysAgo; | ||||
|         document.getElementById('endDate').valueAsDate = today; | ||||
| 
 | ||||
|         // 图表配置 | ||||
|         const chartConfig = { | ||||
|             responsive: true, | ||||
|             maintainAspectRatio: false, | ||||
|             plugins: { | ||||
|                 legend: { | ||||
|                     display: false | ||||
|                 } | ||||
|             }, | ||||
|             scales: { | ||||
|                 y: { | ||||
|                     beginAtZero: true, | ||||
|                     grid: { | ||||
|                         color: '#f0f0f0' | ||||
|                     }, | ||||
|                     ticks: { | ||||
|                         color: '#666', | ||||
|                         font: { | ||||
|                             size: 12 | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 x: { | ||||
|                     grid: { | ||||
|                         color: '#f0f0f0' | ||||
|                     }, | ||||
|                     ticks: { | ||||
|                         color: '#666', | ||||
|                         font: { | ||||
|                             size: 12 | ||||
|                         }, | ||||
|                         maxRotation: 45 | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             interaction: { | ||||
|                 intersect: false, | ||||
|                 mode: 'index' | ||||
|             }, | ||||
|             elements: { | ||||
|                 point: { | ||||
|                     hoverRadius: 6 | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         // 初始化浏览数量图表 | ||||
|         const viewChart = new Chart(document.getElementById('viewChart').getContext('2d'), { | ||||
|             type: 'line', | ||||
|             data: { | ||||
|                 labels: chartLabels, | ||||
|                 datasets: [{ | ||||
|                     label: '浏览数量', | ||||
|                     data: chartData, | ||||
|                     borderColor: '#1890ff', | ||||
|                     backgroundColor: 'rgba(24, 144, 255, 0.1)', | ||||
|                     borderWidth: 2, | ||||
|                     fill: true, | ||||
|                     tension: 0.4, | ||||
|                     pointRadius: 4, | ||||
|                     pointBackgroundColor: '#1890ff', | ||||
|                     pointBorderColor: '#fff', | ||||
|                     pointBorderWidth: 2 | ||||
|                 }] | ||||
|             }, | ||||
|             options: chartConfig | ||||
|         }); | ||||
| 
 | ||||
|         // 初始化浏览人数图表 | ||||
|         const visitorChart = new Chart(document.getElementById('visitorChart').getContext('2d'), { | ||||
|             type: 'line', | ||||
|             data: { | ||||
|                 labels: chartLabels, | ||||
|                 datasets: [{ | ||||
|                     label: '浏览人数', | ||||
|                     data: chartData, | ||||
|                     borderColor: '#52c41a', | ||||
|                     backgroundColor: 'rgba(82, 196, 26, 0.1)', | ||||
|                     borderWidth: 2, | ||||
|                     fill: true, | ||||
|                     tension: 0.4, | ||||
|                     pointRadius: 4, | ||||
|                     pointBackgroundColor: '#52c41a', | ||||
|                     pointBorderColor: '#fff', | ||||
|                     pointBorderWidth: 2 | ||||
|                 }] | ||||
|             }, | ||||
|             options: chartConfig | ||||
|         }); | ||||
| 
 | ||||
|         // 初始化新客数量图表 | ||||
|         const newCustomerChart = new Chart(document.getElementById('newCustomerChart').getContext('2d'), { | ||||
|             type: 'line', | ||||
|             data: { | ||||
|                 labels: chartLabels, | ||||
|                 datasets: [{ | ||||
|                     label: '新客数量', | ||||
|                     data: chartData, | ||||
|                     borderColor: '#faad14', | ||||
|                     backgroundColor: 'rgba(250, 173, 20, 0.1)', | ||||
|                     borderWidth: 2, | ||||
|                     fill: true, | ||||
|                     tension: 0.4, | ||||
|                     pointRadius: 4, | ||||
|                     pointBackgroundColor: '#faad14', | ||||
|                     pointBorderColor: '#fff', | ||||
|                     pointBorderWidth: 2 | ||||
|                 }] | ||||
|             }, | ||||
|             options: chartConfig | ||||
|         }); | ||||
| 
 | ||||
|         // 初始化支付订单人数图表 | ||||
|         const orderChart = new Chart(document.getElementById('orderChart').getContext('2d'), { | ||||
|             type: 'line', | ||||
|             data: { | ||||
|                 labels: chartLabels, | ||||
|                 datasets: [{ | ||||
|                     label: '支付订单人数', | ||||
|                     data: chartData, | ||||
|                     borderColor: '#f5222d', | ||||
|                     backgroundColor: 'rgba(245, 34, 45, 0.1)', | ||||
|                     borderWidth: 2, | ||||
|                     fill: true, | ||||
|                     tension: 0.4, | ||||
|                     pointRadius: 4, | ||||
|                     pointBackgroundColor: '#f5222d', | ||||
|                     pointBorderColor: '#fff', | ||||
|                     pointBorderWidth: 2 | ||||
|                 }] | ||||
|             }, | ||||
|             options: chartConfig | ||||
|         }); | ||||
| 
 | ||||
|         // 查询数据函数 | ||||
|         function queryData() { | ||||
|             const startDate = document.getElementById('startDate').value; | ||||
|             const endDate = document.getElementById('endDate').value; | ||||
| 
 | ||||
|             if (!startDate || !endDate) { | ||||
|                 showNotification('请选择时间范围', 'error'); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (new Date(startDate) > new Date(endDate)) { | ||||
|                 showNotification('开始时间不能大于结束时间', 'error'); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             console.log('查询参数:', { startDate, endDate }); | ||||
| 
 | ||||
|             updateStatsCards(); | ||||
|             updateCharts(); | ||||
| 
 | ||||
|             showNotification('数据查询成功', 'success'); | ||||
|         } | ||||
| 
 | ||||
|         // 导出数据函数 | ||||
|         function exportData() { | ||||
|             const startDate = document.getElementById('startDate').value; | ||||
|             const endDate = document.getElementById('endDate').value; | ||||
| 
 | ||||
|             if (!startDate || !endDate) { | ||||
|                 showNotification('请选择时间范围', 'error'); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             console.log('导出数据'); | ||||
|             showNotification('数据导出中...', 'info'); | ||||
| 
 | ||||
|             setTimeout(() => { | ||||
|                 showNotification('数据导出完成', 'success'); | ||||
|             }, 2000); | ||||
|         } | ||||
| 
 | ||||
|         // 更新统计卡片数据 | ||||
|         function updateStatsCards() { | ||||
|             const statsNumbers = document.querySelectorAll('.stats-number'); | ||||
|             statsNumbers.forEach((element, index) => { | ||||
|                 if (element.textContent.includes('%')) { | ||||
|                     element.textContent = (Math.random() * 10).toFixed(2) + '%'; | ||||
|                 } else { | ||||
|                     element.textContent = Math.floor(Math.random() * 1000); | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|             const statsChanges = document.querySelectorAll('.stats-change'); | ||||
|             statsChanges.forEach(element => { | ||||
|                 const change = (Math.random() * 20 - 10).toFixed(2); | ||||
|                 if (change > 0) { | ||||
|                     element.className = 'stats-change positive'; | ||||
|                     element.textContent = `↑ ${change}%`; | ||||
|                 } else if (change < 0) { | ||||
|                     element.className = 'stats-change negative'; | ||||
|                     element.textContent = `↓ ${Math.abs(change)}%`; | ||||
|                 } else { | ||||
|                     element.className = 'stats-change neutral'; | ||||
|                     element.textContent = '0.00%'; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // 更新所有图表数据 | ||||
|         function updateCharts() { | ||||
|             const newData1 = chartData.map(() => Math.floor(Math.random() * 100)); | ||||
|             const newData2 = chartData.map(() => Math.floor(Math.random() * 80)); | ||||
|             const newData3 = chartData.map(() => Math.floor(Math.random() * 50)); | ||||
|             const newData4 = chartData.map(() => Math.floor(Math.random() * 60)); | ||||
| 
 | ||||
|             viewChart.data.datasets[0].data = newData1; | ||||
|             visitorChart.data.datasets[0].data = newData2; | ||||
|             newCustomerChart.data.datasets[0].data = newData3; | ||||
|             orderChart.data.datasets[0].data = newData4; | ||||
| 
 | ||||
|             viewChart.update('active'); | ||||
|             visitorChart.update('active'); | ||||
|             newCustomerChart.update('active'); | ||||
|             orderChart.update('active'); | ||||
|         } | ||||
| 
 | ||||
|         // 显示通知函数 | ||||
|         function showNotification(message, type) { | ||||
|             const notification = document.createElement('div'); | ||||
|             notification.textContent = message; | ||||
|             notification.style.cssText = ` | ||||
|                 position: fixed; | ||||
|                 top: 20px; | ||||
|                 right: 20px; | ||||
|                 padding: 12px 20px; | ||||
|                 border-radius: 4px; | ||||
|                 color: white; | ||||
|                 font-weight: 500; | ||||
|                 z-index: 9999; | ||||
|                 animation: slideIn 0.3s ease-out; | ||||
|                 background-color: ${type === 'success' ? '#52c41a' : type === 'error' ? '#f5222d' : '#1890ff'}; | ||||
|             `; | ||||
| 
 | ||||
|             document.body.appendChild(notification); | ||||
| 
 | ||||
|             setTimeout(() => { | ||||
|                 notification.style.animation = 'slideOut 0.3s ease-in'; | ||||
|                 setTimeout(() => { | ||||
|                     document.body.removeChild(notification); | ||||
|                 }, 300); | ||||
|             }, 3000); | ||||
|         } | ||||
| 
 | ||||
|         // 添加动画样式 | ||||
|         const style = document.createElement('style'); | ||||
|         style.textContent = ` | ||||
|             @keyframes slideIn { | ||||
|                 from { | ||||
|                     transform: translateX(100%); | ||||
|                     opacity: 0; | ||||
|                 } | ||||
|                 to { | ||||
|                     transform: translateX(0); | ||||
|                     opacity: 1; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @keyframes slideOut { | ||||
|                 from { | ||||
|                     transform: translateX(0); | ||||
|                     opacity: 1; | ||||
|                 } | ||||
|                 to { | ||||
|                     transform: translateX(100%); | ||||
|                     opacity: 0; | ||||
|                 } | ||||
|             } | ||||
|         `; | ||||
|         document.head.appendChild(style); | ||||
| 
 | ||||
|         // 页面加载完成后的初始化 | ||||
|         document.addEventListener('DOMContentLoaded', function() { | ||||
|             console.log('数据分析页面加载完成'); | ||||
| 
 | ||||
|             setTimeout(() => { | ||||
|                 updateStatsCards(); | ||||
|                 updateCharts(); | ||||
|             }, 1000); | ||||
|         }); | ||||
|     </script> | ||||
| </body> | ||||
| </html> | ||||
		Loading…
	
		Reference in New Issue