|
@@ -59,6 +59,7 @@
|
|
|
import { ref, onMounted } from 'vue';
|
|
import { ref, onMounted } from 'vue';
|
|
|
import * as echarts from 'echarts';
|
|
import * as echarts from 'echarts';
|
|
|
import { PageTitle, StatCards } from '@/components';
|
|
import { PageTitle, StatCards } from '@/components';
|
|
|
|
|
+import { customerOrderTradeData } from '@/api/pc/enterprise/order';
|
|
|
|
|
|
|
|
const trendType = ref('month');
|
|
const trendType = ref('month');
|
|
|
const categoryType = ref('month');
|
|
const categoryType = ref('month');
|
|
@@ -67,39 +68,58 @@ const trendChartRef = ref<HTMLElement>();
|
|
|
const pieChartRef = ref<HTMLElement>();
|
|
const pieChartRef = ref<HTMLElement>();
|
|
|
const dailyChartRef = ref<HTMLElement>();
|
|
const dailyChartRef = ref<HTMLElement>();
|
|
|
|
|
|
|
|
-const statData = [
|
|
|
|
|
- { value: '10,239.00', label: '购买金额(元)' },
|
|
|
|
|
- { value: '3', label: '购买数量(件)' },
|
|
|
|
|
- { value: '45', label: '订单量(单)' },
|
|
|
|
|
- { value: '78', label: '客单价(元/单)' }
|
|
|
|
|
-];
|
|
|
|
|
|
|
+let trendChart: echarts.ECharts | null = null;
|
|
|
|
|
+let pieChart: echarts.ECharts | null = null;
|
|
|
|
|
+let dailyChart: echarts.ECharts | null = null;
|
|
|
|
|
|
|
|
-const categoryData = [
|
|
|
|
|
- { name: '品类01', value: 600 },
|
|
|
|
|
- { name: '品类02', value: 200 },
|
|
|
|
|
- { name: '品类03', value: 200 }
|
|
|
|
|
-];
|
|
|
|
|
|
|
+const statData = ref([
|
|
|
|
|
+ { value: '0', label: '购买金额(元)' },
|
|
|
|
|
+ { value: '0', label: '购买数量(件)' },
|
|
|
|
|
+ { value: '0', label: '订单量(单)' },
|
|
|
|
|
+ { value: '0', label: '客单价(元/单)' }
|
|
|
|
|
+]);
|
|
|
|
|
+
|
|
|
|
|
+const categoryData = ref<{ name: string; value: number }[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+const pieColors = ['#f4c542', '#3498db', '#1abc9c', '#e74c3c', '#9b59b6', '#e67e22', '#2ecc71', '#e60012'];
|
|
|
|
|
+
|
|
|
|
|
+const fetchData = async () => {
|
|
|
|
|
+ const res = await customerOrderTradeData();
|
|
|
|
|
+ if (res.code !== 200 || !res.data) return;
|
|
|
|
|
+ const data = res.data;
|
|
|
|
|
+
|
|
|
|
|
+ statData.value = [
|
|
|
|
|
+ { value: (data.totalAmount ?? 0).toLocaleString('en-US', { minimumFractionDigits: 2 }), label: '购买金额(元)' },
|
|
|
|
|
+ { value: String(data.totalQuantity ?? 0), label: '购买数量(件)' },
|
|
|
|
|
+ { value: String(data.orderCount ?? 0), label: '订单量(单)' },
|
|
|
|
|
+ { value: (data.avgOrderAmount ?? 0).toLocaleString('en-US', { minimumFractionDigits: 2 }), label: '客单价(元/单)' }
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ categoryData.value = data.categoryProportion || [];
|
|
|
|
|
+
|
|
|
|
|
+ initTrendChart(data.amountTrend || []);
|
|
|
|
|
+ initPieChart(data.categoryProportion || []);
|
|
|
|
|
+ initDailyChart(data.dailyChange || []);
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
- initTrendChart();
|
|
|
|
|
- initPieChart();
|
|
|
|
|
- initDailyChart();
|
|
|
|
|
|
|
+ fetchData();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const initTrendChart = () => {
|
|
|
|
|
|
|
+const initTrendChart = (amountTrend: { month: string; amount: number }[]) => {
|
|
|
if (!trendChartRef.value) return;
|
|
if (!trendChartRef.value) return;
|
|
|
- const chart = echarts.init(trendChartRef.value);
|
|
|
|
|
- chart.setOption({
|
|
|
|
|
|
|
+ if (!trendChart) trendChart = echarts.init(trendChartRef.value);
|
|
|
|
|
+ trendChart.setOption({
|
|
|
grid: { left: 60, right: 20, top: 30, bottom: 30 },
|
|
grid: { left: 60, right: 20, top: 30, bottom: 30 },
|
|
|
xAxis: {
|
|
xAxis: {
|
|
|
type: 'category',
|
|
type: 'category',
|
|
|
- data: ['2025/01', '2025/02', '2025/03', '2025/04', '2025/05', '2025/06', '2025/07', '2025/08', '2025/09', '2025/10', '2025/11', '2025/12'],
|
|
|
|
|
|
|
+ data: amountTrend.map((d) => d.month),
|
|
|
axisLine: { lineStyle: { color: '#eee' } },
|
|
axisLine: { lineStyle: { color: '#eee' } },
|
|
|
axisLabel: { color: '#999' }
|
|
axisLabel: { color: '#999' }
|
|
|
},
|
|
},
|
|
|
yAxis: {
|
|
yAxis: {
|
|
|
type: 'value',
|
|
type: 'value',
|
|
|
- name: '销量(万元)',
|
|
|
|
|
|
|
+ name: '金额(元)',
|
|
|
nameTextStyle: { color: '#999' },
|
|
nameTextStyle: { color: '#999' },
|
|
|
axisLine: { show: false },
|
|
axisLine: { show: false },
|
|
|
splitLine: { lineStyle: { color: '#eee' } },
|
|
splitLine: { lineStyle: { color: '#eee' } },
|
|
@@ -108,31 +128,31 @@ const initTrendChart = () => {
|
|
|
series: [
|
|
series: [
|
|
|
{
|
|
{
|
|
|
type: 'line',
|
|
type: 'line',
|
|
|
- data: [300, 980, 450, 600, 400, 550, 900, 700, 650, 800, 500, 750],
|
|
|
|
|
|
|
+ data: amountTrend.map((d) => d.amount),
|
|
|
lineStyle: { color: '#e60012', width: 2 },
|
|
lineStyle: { color: '#e60012', width: 2 },
|
|
|
itemStyle: { color: '#e60012' },
|
|
itemStyle: { color: '#e60012' },
|
|
|
symbol: 'circle',
|
|
symbol: 'circle',
|
|
|
- symbolSize: 6
|
|
|
|
|
|
|
+ symbolSize: 6,
|
|
|
|
|
+ areaStyle: { color: 'rgba(230, 0, 18, 0.05)' }
|
|
|
}
|
|
}
|
|
|
],
|
|
],
|
|
|
tooltip: { trigger: 'axis', formatter: (params: any) => `${params[0].name}<br/>¥${params[0].value.toFixed(2)}` }
|
|
tooltip: { trigger: 'axis', formatter: (params: any) => `${params[0].name}<br/>¥${params[0].value.toFixed(2)}` }
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const initPieChart = () => {
|
|
|
|
|
|
|
+const initPieChart = (categoryProportion: { name: string; value: number }[]) => {
|
|
|
if (!pieChartRef.value) return;
|
|
if (!pieChartRef.value) return;
|
|
|
- const chart = echarts.init(pieChartRef.value);
|
|
|
|
|
- chart.setOption({
|
|
|
|
|
|
|
+ if (!pieChart) pieChart = echarts.init(pieChartRef.value);
|
|
|
|
|
+ pieChart.setOption({
|
|
|
series: [
|
|
series: [
|
|
|
{
|
|
{
|
|
|
type: 'pie',
|
|
type: 'pie',
|
|
|
radius: ['40%', '70%'],
|
|
radius: ['40%', '70%'],
|
|
|
center: ['50%', '50%'],
|
|
center: ['50%', '50%'],
|
|
|
- data: [
|
|
|
|
|
- { value: 600, name: '品类01', itemStyle: { color: '#f4c542' } },
|
|
|
|
|
- { value: 200, name: '品类02', itemStyle: { color: '#3498db' } },
|
|
|
|
|
- { value: 200, name: '品类03', itemStyle: { color: '#1abc9c' } }
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ data: categoryProportion.map((item, idx) => ({
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ itemStyle: { color: pieColors[idx % pieColors.length] }
|
|
|
|
|
+ })),
|
|
|
label: { formatter: '{b} {d}%', color: '#666' }
|
|
label: { formatter: '{b} {d}%', color: '#666' }
|
|
|
}
|
|
}
|
|
|
],
|
|
],
|
|
@@ -140,20 +160,20 @@ const initPieChart = () => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const initDailyChart = () => {
|
|
|
|
|
|
|
+const initDailyChart = (dailyChange: { day: string; amount: number; quantity: number }[]) => {
|
|
|
if (!dailyChartRef.value) return;
|
|
if (!dailyChartRef.value) return;
|
|
|
- const chart = echarts.init(dailyChartRef.value);
|
|
|
|
|
- chart.setOption({
|
|
|
|
|
|
|
+ if (!dailyChart) dailyChart = echarts.init(dailyChartRef.value);
|
|
|
|
|
+ dailyChart.setOption({
|
|
|
grid: { left: 60, right: 20, top: 40, bottom: 30 },
|
|
grid: { left: 60, right: 20, top: 40, bottom: 30 },
|
|
|
xAxis: {
|
|
xAxis: {
|
|
|
type: 'category',
|
|
type: 'category',
|
|
|
- data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
|
|
|
|
|
|
|
+ data: dailyChange.map((d) => d.day),
|
|
|
axisLine: { lineStyle: { color: '#eee' } },
|
|
axisLine: { lineStyle: { color: '#eee' } },
|
|
|
axisLabel: { color: '#999' }
|
|
axisLabel: { color: '#999' }
|
|
|
},
|
|
},
|
|
|
yAxis: {
|
|
yAxis: {
|
|
|
type: 'value',
|
|
type: 'value',
|
|
|
- name: '销量(万元)',
|
|
|
|
|
|
|
+ name: '金额/数量',
|
|
|
nameTextStyle: { color: '#999' },
|
|
nameTextStyle: { color: '#999' },
|
|
|
axisLine: { show: false },
|
|
axisLine: { show: false },
|
|
|
splitLine: { lineStyle: { color: '#eee' } },
|
|
splitLine: { lineStyle: { color: '#eee' } },
|
|
@@ -163,7 +183,7 @@ const initDailyChart = () => {
|
|
|
{
|
|
{
|
|
|
name: '购买金额',
|
|
name: '购买金额',
|
|
|
type: 'line',
|
|
type: 'line',
|
|
|
- data: [400, 500, 350, 600, 450, 640, 500, 550, 400, 600, 450, 500],
|
|
|
|
|
|
|
+ data: dailyChange.map((d) => d.amount),
|
|
|
lineStyle: { color: '#f4c542', width: 2 },
|
|
lineStyle: { color: '#f4c542', width: 2 },
|
|
|
itemStyle: { color: '#f4c542' },
|
|
itemStyle: { color: '#f4c542' },
|
|
|
symbol: 'circle',
|
|
symbol: 'circle',
|
|
@@ -172,7 +192,7 @@ const initDailyChart = () => {
|
|
|
{
|
|
{
|
|
|
name: '购买数量',
|
|
name: '购买数量',
|
|
|
type: 'line',
|
|
type: 'line',
|
|
|
- data: [300, 400, 250, 500, 350, 332, 400, 450, 300, 500, 350, 400],
|
|
|
|
|
|
|
+ data: dailyChange.map((d) => d.quantity),
|
|
|
lineStyle: { color: '#3498db', width: 2 },
|
|
lineStyle: { color: '#3498db', width: 2 },
|
|
|
itemStyle: { color: '#3498db' },
|
|
itemStyle: { color: '#3498db' },
|
|
|
symbol: 'circle',
|
|
symbol: 'circle',
|