初步构建起页面布局

This commit is contained in:
2026-01-23 17:55:26 +08:00
parent 2b0ee0c8b6
commit b6ad549737
37 changed files with 13405 additions and 5385 deletions

View 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
}