初步构建起页面布局
This commit is contained in:
691
layouts/admin/utils/echarts-config.uts
Normal file
691
layouts/admin/utils/echarts-config.uts
Normal file
@@ -0,0 +1,691 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user