691 lines
16 KiB
Plaintext
691 lines
16 KiB
Plaintext
// ECharts 配置工具 - CRMEB 风格图表配置
|
||
// 订单统计图表配置(柱状图 + 折线图)
|
||
export const getOrderChartOption = (period: string = '30days') => {
|
||
const periods = {
|
||
'30days': { label: '30天', days: 30 },
|
||
'week': { label: '本周', days: 7 },
|
||
'month': { label: '本月', days: 30 },
|
||
'year': { label: '本年', days: 365 }
|
||
}
|
||
|
||
const periodConfig = periods[period as keyof typeof periods] || periods['30days']
|
||
|
||
return {
|
||
title: {
|
||
text: `订单统计 (${periodConfig.label})`,
|
||
left: 'center',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
fontWeight: 600,
|
||
color: '#262626'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||
borderColor: 'transparent',
|
||
textStyle: {
|
||
color: '#ffffff',
|
||
fontSize: 12
|
||
},
|
||
axisPointer: {
|
||
type: 'cross',
|
||
crossStyle: {
|
||
color: '#999'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['订单金额', '订单数量'],
|
||
top: 30,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
color: '#666666'
|
||
}
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
bottom: '10%',
|
||
top: '15%',
|
||
containLabel: true
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
boundaryGap: false,
|
||
data: generateDateLabels(periodConfig.days),
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#e8e8e8'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
}
|
||
},
|
||
yAxis: [
|
||
{
|
||
type: 'value',
|
||
name: '订单金额',
|
||
position: 'left',
|
||
axisLabel: {
|
||
formatter: '¥{value}',
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: '#f0f0f0',
|
||
type: 'dashed'
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: 'value',
|
||
name: '订单数量',
|
||
position: 'right',
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
show: false
|
||
}
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
name: '订单金额',
|
||
type: 'bar',
|
||
data: generateAmountData(periodConfig.days),
|
||
barWidth: '40%',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#1890ff' },
|
||
{ offset: 1, color: '#36cfc9' }
|
||
]),
|
||
borderRadius: [4, 4, 0, 0]
|
||
},
|
||
emphasis: {
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{ offset: 0, color: '#40a9ff' },
|
||
{ offset: 1, color: '#5cdbd3' }
|
||
])
|
||
}
|
||
}
|
||
},
|
||
{
|
||
name: '订单数量',
|
||
type: 'line',
|
||
yAxisIndex: 1,
|
||
data: generateCountData(periodConfig.days),
|
||
symbol: 'circle',
|
||
symbolSize: 8,
|
||
lineStyle: {
|
||
color: '#52c41a',
|
||
width: 3
|
||
},
|
||
itemStyle: {
|
||
color: '#52c41a',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true,
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: 'rgba(82, 196, 26, 0.1)' },
|
||
{ offset: 1, color: 'rgba(82, 196, 26, 0.3)' }
|
||
])
|
||
}
|
||
}
|
||
],
|
||
animationDuration: 1000,
|
||
animationEasing: 'cubicOut'
|
||
}
|
||
}
|
||
|
||
// 用户趋势图表配置
|
||
export const getUserTrendOption = () => {
|
||
return {
|
||
title: {
|
||
text: '用户增长趋势',
|
||
left: 'center',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
fontWeight: 600,
|
||
color: '#262626'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||
borderColor: 'transparent',
|
||
textStyle: {
|
||
color: '#ffffff',
|
||
fontSize: 12
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['新增用户'],
|
||
top: 30,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
color: '#666666'
|
||
}
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
bottom: '10%',
|
||
top: '15%',
|
||
containLabel: true
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
boundaryGap: false,
|
||
data: generateDateLabels(30),
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#e8e8e8'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
name: '用户数量',
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: '#f0f0f0',
|
||
type: 'dashed'
|
||
}
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
name: '新增用户',
|
||
type: 'line',
|
||
data: generateUserTrendData(30),
|
||
symbol: 'circle',
|
||
symbolSize: 8,
|
||
lineStyle: {
|
||
color: '#1890ff',
|
||
width: 3
|
||
},
|
||
itemStyle: {
|
||
color: '#1890ff',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true,
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: 'rgba(24, 144, 255, 0.1)' },
|
||
{ offset: 1, color: 'rgba(24, 144, 255, 0.3)' }
|
||
])
|
||
}
|
||
}
|
||
],
|
||
animationDuration: 1000,
|
||
animationEasing: 'cubicOut'
|
||
}
|
||
}
|
||
|
||
// 用户构成饼图配置
|
||
export const getUserCompositionOption = () => {
|
||
return {
|
||
title: {
|
||
text: '用户来源构成',
|
||
left: 'center',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
fontWeight: 600,
|
||
color: '#262626'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: '{a} <br/>{b}: {c}% ({d}%)',
|
||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||
borderColor: 'transparent',
|
||
textStyle: {
|
||
color: '#ffffff',
|
||
fontSize: 12
|
||
}
|
||
},
|
||
legend: {
|
||
orient: 'vertical',
|
||
left: 'left',
|
||
top: 'center',
|
||
itemGap: 16,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
color: '#666666'
|
||
},
|
||
data: ['自然流量', '搜索引擎', '社交媒体', '广告投放', '其他']
|
||
},
|
||
series: [
|
||
{
|
||
name: '用户来源',
|
||
type: 'pie',
|
||
radius: ['40%', '70%'],
|
||
center: ['60%', '50%'],
|
||
avoidLabelOverlap: false,
|
||
label: {
|
||
show: false
|
||
},
|
||
emphasis: {
|
||
label: {
|
||
show: true,
|
||
fontSize: 16,
|
||
fontWeight: 'bold',
|
||
formatter: '{b}\n{c}%'
|
||
}
|
||
},
|
||
labelLine: {
|
||
show: false
|
||
},
|
||
data: [
|
||
{
|
||
value: 35,
|
||
name: '自然流量',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: '#1890ff' },
|
||
{ offset: 1, color: '#36cfc9' }
|
||
])
|
||
}
|
||
},
|
||
{
|
||
value: 28,
|
||
name: '搜索引擎',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: '#52c41a' },
|
||
{ offset: 1, color: '#73d13d' }
|
||
])
|
||
}
|
||
},
|
||
{
|
||
value: 20,
|
||
name: '社交媒体',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: '#faad14' },
|
||
{ offset: 1, color: '#ffc53d' }
|
||
])
|
||
}
|
||
},
|
||
{
|
||
value: 12,
|
||
name: '广告投放',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: '#f5222d' },
|
||
{ offset: 1, color: '#ff7875' }
|
||
])
|
||
}
|
||
},
|
||
{
|
||
value: 5,
|
||
name: '其他',
|
||
itemStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: '#722ed1' },
|
||
{ offset: 1, color: '#b37feb' }
|
||
])
|
||
}
|
||
}
|
||
]
|
||
}
|
||
],
|
||
animationDuration: 1000,
|
||
animationEasing: 'cubicOut'
|
||
}
|
||
}
|
||
|
||
// 用户统计多折线图配置
|
||
export const getUserStatisticsOption = () => {
|
||
return {
|
||
title: {
|
||
text: '用户数据趋势分析',
|
||
left: 'center',
|
||
textStyle: {
|
||
fontSize: 16,
|
||
fontWeight: 600,
|
||
color: '#262626'
|
||
}
|
||
},
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||
borderColor: 'transparent',
|
||
textStyle: {
|
||
color: '#ffffff',
|
||
fontSize: 12
|
||
},
|
||
axisPointer: {
|
||
type: 'cross',
|
||
crossStyle: {
|
||
color: '#999'
|
||
}
|
||
}
|
||
},
|
||
legend: {
|
||
data: ['新增用户', '访客数', '浏览量', '成交用户', '付费会员'],
|
||
top: 30,
|
||
textStyle: {
|
||
fontSize: 12,
|
||
color: '#666666'
|
||
}
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
bottom: '10%',
|
||
top: '15%',
|
||
containLabel: true
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
boundaryGap: false,
|
||
data: generateDateLabels(30, 7), // 30天的数据,每7天一个标签
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#e8e8e8'
|
||
}
|
||
},
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
name: '数量',
|
||
axisLabel: {
|
||
color: '#999999',
|
||
fontSize: 12
|
||
},
|
||
axisLine: {
|
||
show: false
|
||
},
|
||
axisTick: {
|
||
show: false
|
||
},
|
||
splitLine: {
|
||
lineStyle: {
|
||
color: '#f0f0f0',
|
||
type: 'dashed'
|
||
}
|
||
}
|
||
},
|
||
series: [
|
||
{
|
||
name: '新增用户',
|
||
type: 'line',
|
||
data: generateUserStatisticsData('newUsers', 7),
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: {
|
||
color: '#1890ff',
|
||
width: 2
|
||
},
|
||
itemStyle: {
|
||
color: '#1890ff',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true
|
||
},
|
||
{
|
||
name: '访客数',
|
||
type: 'line',
|
||
data: generateUserStatisticsData('visitors', 7),
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: {
|
||
color: '#52c41a',
|
||
width: 2
|
||
},
|
||
itemStyle: {
|
||
color: '#52c41a',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true
|
||
},
|
||
{
|
||
name: '浏览量',
|
||
type: 'line',
|
||
data: generateUserStatisticsData('pageViews', 7),
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: {
|
||
color: '#faad14',
|
||
width: 2
|
||
},
|
||
itemStyle: {
|
||
color: '#faad14',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true
|
||
},
|
||
{
|
||
name: '成交用户',
|
||
type: 'line',
|
||
data: generateUserStatisticsData('conversions', 7),
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: {
|
||
color: '#f5222d',
|
||
width: 2
|
||
},
|
||
itemStyle: {
|
||
color: '#f5222d',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true
|
||
},
|
||
{
|
||
name: '付费会员',
|
||
type: 'line',
|
||
data: generateUserStatisticsData('vipUsers', 7),
|
||
symbol: 'circle',
|
||
symbolSize: 6,
|
||
lineStyle: {
|
||
color: '#722ed1',
|
||
width: 2
|
||
},
|
||
itemStyle: {
|
||
color: '#722ed1',
|
||
borderColor: '#ffffff',
|
||
borderWidth: 2
|
||
},
|
||
smooth: true
|
||
}
|
||
],
|
||
animationDuration: 1000,
|
||
animationEasing: 'cubicOut'
|
||
}
|
||
}
|
||
|
||
// 辅助函数:生成日期标签
|
||
function generateDateLabels(days: number, step: number = 1): string[] {
|
||
const labels = []
|
||
const today = new Date()
|
||
|
||
for (let i = days - 1; i >= 0; i -= step) {
|
||
const date = new Date(today)
|
||
date.setDate(date.getDate() - i)
|
||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||
const day = date.getDate().toString().padStart(2, '0')
|
||
labels.push(`${month}-${day}`)
|
||
}
|
||
|
||
return labels
|
||
}
|
||
|
||
// 辅助函数:生成订单金额数据
|
||
function generateAmountData(days: number): number[] {
|
||
const data = []
|
||
for (let i = 0; i < days; i++) {
|
||
// 生成12000-25000之间的随机金额
|
||
data.push(Math.floor(Math.random() * 13000) + 12000)
|
||
}
|
||
return data
|
||
}
|
||
|
||
// 辅助函数:生成订单数量数据
|
||
function generateCountData(days: number): number[] {
|
||
const data = []
|
||
for (let i = 0; i < days; i++) {
|
||
// 生成50-150之间的随机数量
|
||
data.push(Math.floor(Math.random() * 100) + 50)
|
||
}
|
||
return data
|
||
}
|
||
|
||
// 辅助函数:生成用户趋势数据
|
||
function generateUserTrendData(days: number): number[] {
|
||
const data = []
|
||
let base = 100
|
||
|
||
for (let i = 0; i < days; i++) {
|
||
base += Math.floor(Math.random() * 20) - 5 // -5到+15的随机变化
|
||
base = Math.max(50, base) // 最低50
|
||
data.push(base)
|
||
}
|
||
|
||
return data
|
||
}
|
||
|
||
// 辅助函数:生成用户统计数据
|
||
function generateUserStatisticsData(type: string, points: number): number[] {
|
||
const data = []
|
||
const baseValues = {
|
||
newUsers: 120,
|
||
visitors: 450,
|
||
pageViews: 680,
|
||
conversions: 45,
|
||
vipUsers: 12
|
||
}
|
||
|
||
let base = baseValues[type as keyof typeof baseValues] || 100
|
||
|
||
for (let i = 0; i < points; i++) {
|
||
const variation = type === 'vipUsers' ? 0.3 : 0.2 // 付费会员变化小一些
|
||
base += Math.floor(Math.random() * (base * variation * 2)) - (base * variation)
|
||
base = Math.max(0, base)
|
||
data.push(Math.floor(base))
|
||
}
|
||
|
||
return data
|
||
}
|
||
|
||
// Mock API 数据接口
|
||
export const mockApi = {
|
||
// 获取订单统计数据
|
||
getOrderStats: (period: string = '30days') => {
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve({
|
||
period,
|
||
amountData: generateAmountData(30),
|
||
countData: generateCountData(30),
|
||
dateLabels: generateDateLabels(30)
|
||
})
|
||
}, 500)
|
||
})
|
||
},
|
||
|
||
// 获取用户趋势数据
|
||
getUserTrend: () => {
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve({
|
||
data: generateUserTrendData(30),
|
||
dateLabels: generateDateLabels(30)
|
||
})
|
||
}, 500)
|
||
})
|
||
},
|
||
|
||
// 获取用户构成数据
|
||
getUserComposition: () => {
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve([
|
||
{ name: '自然流量', value: 35, color: '#1890ff' },
|
||
{ name: '搜索引擎', value: 28, color: '#52c41a' },
|
||
{ name: '社交媒体', value: 20, color: '#faad14' },
|
||
{ name: '广告投放', value: 12, color: '#f5222d' },
|
||
{ name: '其他', value: 5, color: '#722ed1' }
|
||
])
|
||
}, 500)
|
||
})
|
||
},
|
||
|
||
// 获取用户统计数据
|
||
getUserStatistics: () => {
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => {
|
||
resolve({
|
||
newUsers: generateUserStatisticsData('newUsers', 7),
|
||
visitors: generateUserStatisticsData('visitors', 7),
|
||
pageViews: generateUserStatisticsData('pageViews', 7),
|
||
conversions: generateUserStatisticsData('conversions', 7),
|
||
vipUsers: generateUserStatisticsData('vipUsers', 7),
|
||
dateLabels: generateDateLabels(30, 7)
|
||
})
|
||
}, 500)
|
||
})
|
||
}
|
||
}
|
||
|
||
// 导出所有配置
|
||
export const chartConfigs = {
|
||
orderChart: getOrderChartOption,
|
||
userTrendChart: getUserTrendOption,
|
||
userCompositionChart: getUserCompositionOption,
|
||
userStatisticsChart: getUserStatisticsOption,
|
||
mockApi
|
||
} |