复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>销售数据可视化仪表盘</title>
<!-- 引入Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入Font Awesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 引入Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
<!-- 配置Tailwind自定义颜色和字体 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#165DFF',
secondary: '#36CFC9',
accent: '#722ED1',
success: '#52C41A',
warning: '#FAAD14',
danger: '#F5222D',
info: '#1890FF',
dark: '#1D2129',
'gray-light': '#F2F3F5',
'gray-medium': '#C9CDD4'
},
fontFamily: {
inter: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<!-- 自定义工具类 -->
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.card-shadow {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
.animate-fade-in {
animation: fadeIn 0.5s ease-in-out;
}
.animate-slide-up {
animation: slideUp 0.5s ease-out;
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
</style>
</head>
<body class="bg-gray-50 font-inter text-dark">
<!-- 顶部导航栏 -->
<header class="bg-white shadow-sm fixed top-0 left-0 right-0 z-50 transition-all duration-300" id="navbar">
<div class="container mx-auto px-4 py-3 flex items-center justify-between">
<div class="flex items-center space-x-2">
<i class="fa fa-line-chart text-primary text-2xl"></i>
<h1 class="text-xl font-bold text-primary">销售数据分析平台</h1>
</div>
<div class="hidden md:flex items-center space-x-6">
<a href="#" class="text-primary font-medium">仪表盘</a>
<a href="#" class="text-gray-600 hover:text-primary transition-colors">报表</a>
<a href="#" class="text-gray-600 hover:text-primary transition-colors">分析</a>
<a href="#" class="text-gray-600 hover:text-primary transition-colors">设置</a>
</div>
<div class="flex items-center space-x-4">
<button id="refreshBtn" class="p-2 rounded-full hover:bg-gray-light transition-colors text-gray-600">
<i class="fa fa-refresh"></i>
</button>
<div class="relative">
<button class="flex items-center space-x-2 focus:outline-none">
<img src="https://picsum.photos/id/1005/40/40" alt="用户头像" class="w-8 h-8 rounded-full object-cover border-2 border-primary">
<span class="hidden md:inline text-sm font-medium">管理员</span>
<i class="fa fa-angle-down text-gray-500"></i>
</button>
</div>
</div>
</div>
</header>
<!-- 主内容区 -->
<main class="container mx-auto px-4 pt-24 pb-16">
<!-- 页面标题和过滤器 -->
<div class="mb-8 animate-fade-in">
<div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold mb-2">销售数据概览</h2>
<p class="text-gray-500">实时监控销售趋势和关键指标</p>
</div>
<div class="flex flex-wrap gap-3 mt-4 md:mt-0">
<div class="relative">
<select id="timeFilter" class="appearance-none bg-white border border-gray-300 rounded-lg py-2 pl-4 pr-10 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary">
<option value="month">近30天</option>
<option value="quarter">近90天</option>
<option value="year">近一年</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-500">
<i class="fa fa-chevron-down text-xs"></i>
</div>
</div>
<div class="relative">
<select id="regionFilter" class="appearance-none bg-white border border-gray-300 rounded-lg py-2 pl-4 pr-10 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary">
<option value="all">全部区域</option>
<option value="north">北区</option>
<option value="south">南区</option>
<option value="east">东区</option>
<option value="west">西区</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-500">
<i class="fa fa-chevron-down text-xs"></i>
</div>
</div>
<button class="bg-primary hover:bg-primary/90 text-white rounded-lg py-2 px-4 text-sm transition-colors flex items-center">
<i class="fa fa-download mr-2"></i>导出报表
</button>
</div>
</div>
<!-- 日期显示 -->
<div class="bg-white rounded-lg p-3 shadow-sm flex items-center justify-between">
<div class="text-sm text-gray-500">
<i class="fa fa-calendar-o mr-2"></i>
<span id="dateRange">2023年5月15日 - 2023年6月14日</span>
</div>
<div class="text-sm text-gray-500 flex items-center">
<span class="mr-4"><i class="fa fa-refresh mr-1"></i> 上次更新: <span id="lastUpdate">今天 09:45</span></span>
<span class="text-success"><i class="fa fa-check-circle mr-1"></i> 数据已同步</span>
</div>
</div>
</div>
<!-- 关键指标卡片 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<!-- 总销售额 -->
<div class="bg-white rounded-xl p-6 card-shadow card-hover animate-slide-up" style="animation-delay: 0.1s">
<div class="flex justify-between items-start mb-4">
<div>
<p class="text-gray-500 text-sm">总销售额</p>
<h3 class="text-2xl font-bold mt-1" id="totalSales">¥0</h3>
</div>
<div class="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary">
<i class="fa fa-rmb"></i>
</div>
</div>
<div class="flex items-center">
<span class="text-success text-sm flex items-center">
<i class="fa fa-arrow-up mr-1"></i>
<span id="salesGrowth">0%</span>
</span>
<span class="text-gray-400 text-xs ml-2">相比上期</span>
</div>
</div>
<!-- 订单数量 -->
<div class="bg-white rounded-xl p-6 card-shadow card-hover animate-slide-up" style="animation-delay: 0.2s">
<div class="flex justify-between items-start mb-4">
<div>
<p class="text-gray-500 text-sm">订单数量</p>
<h3 class="text-2xl font-bold mt-1" id="orderCount">0</h3>
</div>
<div class="w-10 h-10 rounded-full bg-secondary/10 flex items-center justify-center text-secondary">
<i class="fa fa-shopping-cart"></i>
</div>
</div>
<div class="flex items-center">
<span class="text-success text-sm flex items-center">
<i class="fa fa-arrow-up mr-1"></i>
<span id="orderGrowth">0%</span>
</span>
<span class="text-gray-400 text-xs ml-2">相比上期</span>
</div>
</div>
<!-- 平均客单价 -->
<div class="bg-white rounded-xl p-6 card-shadow card-hover animate-slide-up" style="animation-delay: 0.3s">
<div class="flex justify-between items-start mb-4">
<div>
<p class="text-gray-500 text-sm">平均客单价</p>
<h3 class="text-2xl font-bold mt-1" id="avgOrderValue">¥0</h3>
</div>
<div class="w-10 h-10 rounded-full bg-accent/10 flex items-center justify-center text-accent">
<i class="fa fa-usd"></i>
</div>
</div>
<div class="flex items-center">
<span class="text-danger text-sm flex items-center">
<i class="fa fa-arrow-down mr-1"></i>
<span id="avgValueGrowth">0%</span>
</span>
<span class="text-gray-400 text-xs ml-2">相比上期</span>
</div>
</div>
<!-- 转化率 -->
<div class="bg-white rounded-xl p-6 card-shadow card-hover animate-slide-up" style="animation-delay: 0.4s">
<div class="flex justify-between items-start mb-4">
<div>
<p class="text-gray-500 text-sm">转化率</p>
<h3 class="text-2xl font-bold mt-1" id="conversionRate">0%</h3>
</div>
<div class="w-10 h-10 rounded-full bg-success/10 flex items-center justify-center text-success">
<i class="fa fa-exchange"></i>
</div>
</div>
<div class="flex items-center">
<span class="text-success text-sm flex items-center">
<i class="fa fa-arrow-up mr-1"></i>
<span id="conversionGrowth">0%</span>
</span>
<span class="text-gray-400 text-xs ml-2">相比上期</span>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
<!-- 销售趋势图 -->
<div class="bg-white rounded-xl p-6 card-shadow lg:col-span-2 animate-slide-up" style="animation-delay: 0.5s">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-lg">销售趋势分析</h3>
<div class="flex space-x-2">
<button class="chart-filter-btn active px-3 py-1 text-xs rounded-full bg-primary text-white" data-period="day">按日</button>
<button class="chart-filter-btn px-3 py-1 text-xs rounded-full bg-gray-light text-gray-600 hover:bg-gray-200" data-period="week">按周</button>
<button class="chart-filter-btn px-3 py-1 text-xs rounded-full bg-gray-light text-gray-600 hover:bg-gray-200" data-period="month">按月</button>
</div>
</div>
<div class="h-[300px]">
<canvas id="salesTrendChart"></canvas>
</div>
</div>
<!-- 销售分布 -->
<div class="bg-white rounded-xl p-6 card-shadow animate-slide-up" style="animation-delay: 0.6s">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-lg">销售区域分布</h3>
<button class="text-gray-400 hover:text-gray-600">
<i class="fa fa-ellipsis-v"></i>
</button>
</div>
<div class="h-[300px] flex items-center justify-center">
<canvas id="salesDistributionChart"></canvas>
</div>
</div>
</div>
<!-- 产品销售和区域表现 -->
<div class="grid grid-cols-1 lg:grid-cols-5 gap-6">
<!-- 产品销售排行 -->
<div class="bg-white rounded-xl p-6 card-shadow lg:col-span-3 animate-slide-up" style="animation-delay: 0.7s">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-lg">产品销售排行</h3>
<button class="text-primary text-sm hover:underline flex items-center">
查看全部 <i class="fa fa-angle-right ml-1"></i>
</button>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="border-b border-gray-100">
<th class="py-3 px-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">产品名称</th>
<th class="py-3 px-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">类别</th>
<th class="py-3 px-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">销售额</th>
<th class="py-3 px-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">销量</th>
<th class="py-3 px-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">同比增长</th>
</tr>
</thead>
<tbody id="productTableBody" class="divide-y divide-gray-100">
<!-- 产品数据将通过JavaScript动态生成 -->
</tbody>
</table>
</div>
</div>
<!-- 区域销售表现 -->
<div class="bg-white rounded-xl p-6 card-shadow lg:col-span-2 animate-slide-up" style="animation-delay: 0.8s">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-lg">区域销售表现</h3>
<div class="relative">
<select id="regionMetricFilter" class="appearance-none bg-gray-light border-none rounded-lg py-1.5 pl-3 pr-8 text-xs focus:outline-none focus:ring-1 focus:ring-primary">
<option value="sales">按销售额</option>
<option value="orders">按订单数</option>
<option value="growth">按增长率</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-500">
<i class="fa fa-chevron-down text-xs"></i>
</div>
</div>
</div>
<div class="space-y-5" id="regionPerformance">
<!-- 区域数据将通过JavaScript动态生成 -->
</div>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-white border-t border-gray-200 py-6">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="text-gray-500 text-sm mb-4 md:mb-0">
© 2023 销售数据分析平台. 保留所有权利.
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-400 hover:text-primary transition-colors">
<i class="fa fa-question-circle"></i>
<span class="ml-1 text-sm">帮助中心</span>
</a>
<a href="#" class="text-gray-400 hover:text-primary transition-colors">
<i class="fa fa-file-text-o"></i>
<span class="ml-1 text-sm">使用文档</span>
</a>
<a href="#" class="text-gray-400 hover:text-primary transition-colors">
<i class="fa fa-envelope-o"></i>
<span class="ml-1 text-sm">联系我们</span>
</a>
</div>
</div>
</div>
</footer>
<script>
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// 生成模拟数据(1万至100万区间)
const salesData = generateSalesData();
// 渲染数据到页面
renderDashboard(salesData);
// 初始化图表
initCharts(salesData);
// 添加事件监听器
addEventListeners();
// 导航栏滚动效果
window.addEventListener('scroll', function() {
const navbar = document.getElementById('navbar');
if (window.scrollY > 10) {
navbar.classList.add('py-2', 'shadow');
navbar.classList.remove('py-3', 'shadow-sm');
} else {
navbar.classList.add('py-3', 'shadow-sm');
navbar.classList.remove('py-2', 'shadow');
}
});
});
// 生成模拟数据(1万至100万区间)
function generateSalesData() {
// 生成30天的销售数据
const days = 30;
const dailySales = [];
const dailyOrders = [];
for (let i = 0; i < days; i++) {
// 销售额:1万至100万之间的随机数
const sales = Math.floor(Math.random() * 990000) + 10000;
// 订单数:根据销售额估算,平均客单价约2万
const orders = Math.max(1, Math.floor(sales / 20000));
dailySales.push(sales);
dailyOrders.push(orders);
// 添加一些趋势,使数据更真实
if (i > 0) {
const trend = Math.random() > 0.6 ? 1 : -1;
const variation = Math.floor(dailySales[i] * (0.05 + Math.random() * 0.15) * trend);
dailySales[i] = Math.max(10000, dailySales[i] + variation);
}
}
// 计算总计
const totalSales = dailySales.reduce((sum, val) => sum + val, 0);
const totalOrders = dailyOrders.reduce((sum, val) => sum + val, 0);
const avgOrderValue = Math.round(totalSales / totalOrders);
// 模拟上期数据,用于计算增长率
const lastPeriodSales = totalSales * (0.9 + Math.random() * 0.15);
const lastPeriodOrders = totalOrders * (0.9 + Math.random() * 0.15);
const lastPeriodAvgValue = Math.round(lastPeriodSales / lastPeriodOrders);
// 计算增长率
const salesGrowth = ((totalSales - lastPeriodSales) / lastPeriodSales * 100).toFixed(1);
const orderGrowth = ((totalOrders - lastPeriodOrders) / lastPeriodOrders * 100).toFixed(1);
const avgValueGrowth = ((avgOrderValue - lastPeriodAvgValue) / lastPeriodAvgValue * 100).toFixed(1);
// 转化率(随机5%-15%)
const conversionRate = (5 + Math.random() * 10).toFixed(1);
const lastPeriodConversion = (5 + Math.random() * 10).toFixed(1);
const conversionGrowth = ((conversionRate - lastPeriodConversion) / lastPeriodConversion * 100).toFixed(1);
// 区域销售分布
const regions = [
{ name: '北区', sales: Math.floor(totalSales * (0.2 + Math.random() * 0.15)), color: '#165DFF' },
{ name: '南区', sales: Math.floor(totalSales * (0.2 + Math.random() * 0.15)), color: '#36CFC9' },
{ name: '东区', sales: Math.floor(totalSales * (0.2 + Math.random() * 0.15)), color: '#722ED1' },
{ name: '西区', sales: Math.floor(totalSales * (0.2 + Math.random() * 0.15)), color: '#FAAD14' }
];
// 确保区域销售总和接近总销售额
const regionSalesTotal = regions.reduce((sum, r) => sum + r.sales, 0);
const ratio = totalSales / regionSalesTotal;
regions.forEach(r => r.sales = Math.floor(r.sales * ratio));
// 为每个区域计算增长率
regions.forEach(region => {
region.growth = (5 - Math.random() * 10 + Math.random() * 10).toFixed(1);
region.orders = Math.max(1, Math.floor(region.sales / (15000 + Math.random() * 15000)));
});
// 产品数据
const productCategories = ['电子产品', '服装鞋帽', '家居用品', '食品饮料', '图书音像'];
const products = [];
for (let i = 0; i < 8; i++) {
const category = productCategories[Math.floor(Math.random() * productCategories.length)];
const sales = Math.floor(Math.random() * 990000) + 10000; // 1万至100万
const volume = Math.max(1, Math.floor(sales / (5000 + Math.random() * 15000)));
const growth = (5 - Math.random() * 10 + Math.random() * 10).toFixed(1);
products.push({
id: i + 1,
name: `产品${String.fromCharCode(65 + i)}`,
category,
sales,
volume,
growth
});
}
// 按销售额排序
products.sort((a, b) => b.sales - a.sales);
// 生成日期标签
const labels = [];
const today = new Date();
for (let i = days - 1; i >= 0; i--) {
const date = new Date();
date.setDate(today.getDate() - i);
labels.push(`${date.getMonth() + 1}/${date.getDate()}`);
}
return {
dailySales,
dailyOrders,
labels,
totalSales,
totalOrders,
avgOrderValue,
conversionRate,
salesGrowth,
orderGrowth,
avgValueGrowth,
conversionGrowth,
regions,
products
};
}
// 渲染仪表盘数据
function renderDashboard(data) {
// 格式化数字为带逗号的形式
const formatNumber = (num) => {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
// 渲染关键指标
document.getElementById('totalSales').textContent = `¥${formatNumber(data.totalSales)}`;
document.getElementById('orderCount').textContent = formatNumber(data.totalOrders);
document.getElementById('avgOrderValue').textContent = `¥${formatNumber(data.avgOrderValue)}`;
document.getElementById('conversionRate').textContent = `${data.conversionRate}%`;
// 渲染增长率并设置颜色
renderGrowthRate('salesGrowth', data.salesGrowth);
renderGrowthRate('orderGrowth', data.orderGrowth);
renderGrowthRate('avgValueGrowth', data.avgValueGrowth);
renderGrowthRate('conversionGrowth', data.conversionGrowth);
// 更新最后更新时间
const now = new Date();
document.getElementById('lastUpdate').textContent = `今天 ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
// 渲染产品表格
const productTableBody = document.getElementById('productTableBody');
productTableBody.innerHTML = '';
data.products.forEach(product => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50 transition-colors';
row.innerHTML = `
<td class="py-4 px-4 whitespace-nowrap">
<div class="flex items-center">
<div class="w-8 h-8 rounded-md bg-gray-100 flex items-center justify-center mr-3">
<i class="fa fa-cube text-gray-500"></i>
</div>
<div>
<div class="font-medium">${product.name}</div>
</div>
</div>
</td>
<td class="py-4 px-4 whitespace-nowrap">
<span class="px-2 py-1 text-xs rounded-full bg-gray-100 text-gray-600">${product.category}</span>
</td>
<td class="py-4 px-4 whitespace-nowrap font-medium">¥${formatNumber(product.sales)}</td>
<td class="py-4 px-4 whitespace-nowrap">${formatNumber(product.volume)}</td>
<td class="py-4 px-4 whitespace-nowrap">
<span class="${product.growth >= 0 ? 'text-success' : 'text-danger'} text-sm flex items-center">
<i class="fa fa-arrow-${product.growth >= 0 ? 'up' : 'down'} mr-1"></i>
${Math.abs(product.growth)}%
</span>
</td>
`;
productTableBody.appendChild(row);
});
// 渲染区域表现
renderRegionPerformance(data.regions, 'sales');
}
// 渲染增长率
function renderGrowthRate(elementId, value) {
const element = document.getElementById(elementId);
element.textContent = `${Math.abs(value)}%`;
if (parseFloat(value) >= 0) {
element.parentElement.className = 'text-success text-sm flex items-center';
element.parentElement.innerHTML = `<i class="fa fa-arrow-up mr-1"></i><span id="${elementId}">${Math.abs(value)}%</span>`;
} else {
element.parentElement.className = 'text-danger text-sm flex items-center';
element.parentElement.innerHTML = `<i class="fa fa-arrow-down mr-1"></i><span id="${elementId}">${Math.abs(value)}%</span>`;
}
}
// 渲染区域表现
function renderRegionPerformance(regions, metric) {
const container = document.getElementById('regionPerformance');
container.innerHTML = '';
// 根据所选指标排序
let sortedRegions = [...regions];
if (metric === 'sales') {
sortedRegions.sort((a, b) => b.sales - a.sales);
} else if (metric === 'orders') {
sortedRegions.sort((a, b) => b.orders - a.orders);
} else if (metric === 'growth') {
sortedRegions.sort((a, b) => b.growth - a.growth);
}
sortedRegions.forEach(region => {
let value, label;
if (metric === 'sales') {
value = region.sales;
label = `¥${formatNumber(value)}`;
} else if (metric === 'orders') {
value = region.orders;
label = formatNumber(value);
} else {
value = Math.abs(region.growth);
label = `${region.growth}%`;
}
// 计算最大值用于进度条
const maxValue = metric === 'sales'
? Math.max(...regions.map(r => r.sales))
: metric === 'orders'
? Math.max(...regions.map(r => r.orders))
: 20; // 增长率最大20%
const percentage = Math.min(100, Math.round((value / maxValue) * 100));
const regionElement = document.createElement('div');
regionElement.className = 'region-item';
regionElement.innerHTML = `
<div class="flex justify-between items-center mb-1">
<div class="flex items-center">
<div class="w-3 h-3 rounded-full mr-2" style="background-color: ${region.color}"></div>
<span class="text-sm font-medium">${region.name}</span>
</div>
<span class="text-sm font-semibold ${metric === 'growth' && region.growth < 0 ? 'text-danger' : metric === 'growth' ? 'text-success' : ''}">${label}</span>
</div>
<div class="w-full bg-gray-100 rounded-full h-2">
<div class="h-2 rounded-full" style="width: ${percentage}%; background-color: ${region.color}"></div>
</div>
`;
container.appendChild(regionElement);
});
}
// 初始化图表
function initCharts(data) {
// 销售趋势图
const trendCtx = document.getElementById('salesTrendChart').getContext('2d');
// 图表样式配置
const gridLineColor = 'rgba(0, 0, 0, 0.05)';
const tooltipBackgroundColor = 'rgba(255, 255, 255, 0.95)';
const tooltipBorderColor = 'rgba(0, 0, 0, 0.1)';
window.salesTrendChart = new Chart(trendCtx, {
type: 'line',
data: {
labels: data.labels,
datasets: [
{
label: '销售额',
data: data.dailySales,
borderColor: '#165DFF',
backgroundColor: 'rgba(22, 93, 255, 0.1)',
borderWidth: 2,
pointBackgroundColor: '#FFFFFF',
pointBorderColor: '#165DFF',
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.3,
fill: true
},
{
label: '订单数',
data: data.dailyOrders,
borderColor: '#722ED1',
backgroundColor: 'transparent',
borderWidth: 2,
pointBackgroundColor: '#FFFFFF',
pointBorderColor: '#722ED1',
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6,
tension: 0.3,
fill: false,
yAxisID: 'y1'
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
plugins: {
legend: {
position: 'top',
align: 'end',
labels: {
usePointStyle: true,
boxWidth: 6,
font: {
size: 12
},
padding: 20
}
},
tooltip: {
backgroundColor: tooltipBackgroundColor,
titleColor: '#1D2129',
bodyColor: '#4E5969',
borderColor: tooltipBorderColor,
borderWidth: 1,
padding: 12,
boxPadding: 6,
usePointStyle: true,
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.datasetIndex === 0) {
label += '¥' + formatNumber(context.parsed.y);
} else {
label += formatNumber(context.parsed.y) + ' 单';
}
return label;
}
}
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
maxRotation: 0,
autoSkip: true,
maxTicksLimit: 8
}
},
y: {
beginAtZero: true,
grid: {
color: gridLineColor
},
ticks: {
callback: function(value) {
if (value >= 1000000) {
return '¥' + (value / 1000000).toFixed(1) + 'M';
} else if (value >= 1000) {
return '¥' + (value / 1000).toFixed(0) + 'K';
}
return '¥' + value;
}