electripper-v2-ui/src/views/bst/index/components/OrderDailyStat.vue

281 lines
7.2 KiB
Vue
Raw Normal View History

2025-04-06 18:20:25 +08:00
<template>
2025-04-10 14:07:21 +08:00
<div v-loading="loading">
2025-04-08 08:48:03 +08:00
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
@change="getDailyAmount"
size="mini"
:clearable="false"
:picker-options="DatePickerOptions.DEFAULT"
/>
<div ref="chart" :style="{width: width, height: height}"></div>
2025-04-10 14:07:21 +08:00
</div>
2025-04-06 18:20:25 +08:00
</template>
<script>
2025-05-06 18:42:44 +08:00
import { getDailyAmount } from '@/api/dashboard/dashboard';
2025-04-08 08:48:03 +08:00
import { getLastDateStr } from '@/utils';
2025-05-06 18:42:44 +08:00
import { DatePickerOptions } from '@/utils/constants';
2025-04-08 08:48:03 +08:00
import $resize from '@/views/dashboard/mixins/resize';
2025-05-06 18:42:44 +08:00
import * as echarts from 'echarts';
2025-04-06 18:20:25 +08:00
export default {
name: "OrderDailyStat",
2025-04-08 08:48:03 +08:00
mixins: [$resize],
props: {
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
2025-04-10 14:07:21 +08:00
},
query: {
type: Object,
default: () => ({})
2025-04-08 08:48:03 +08:00
}
},
2025-04-06 18:20:25 +08:00
data() {
return {
2025-04-08 08:48:03 +08:00
DatePickerOptions,
2025-04-06 18:20:25 +08:00
loading: false,
2025-04-08 08:48:03 +08:00
dailyAmount: [],
queryParams: {
dateRange: [
getLastDateStr(7),
getLastDateStr(0)
]
},
chart: null
2025-04-06 18:20:25 +08:00
}
},
created() {
2025-04-08 08:48:03 +08:00
this.getDailyAmount();
},
mounted() {
this.initChart();
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
this.chart = null;
}
2025-04-06 18:20:25 +08:00
},
methods: {
2025-04-08 08:48:03 +08:00
getDailyAmount() {
2025-04-06 18:20:25 +08:00
this.loading = true;
2025-04-10 14:07:21 +08:00
Object.assign(this.queryParams, this.query);
2025-04-08 08:48:03 +08:00
getDailyAmount(this.queryParams).then(res => {
this.dailyAmount = res.data;
this.updateChart();
}).finally(() => {
this.loading = false;
2025-04-06 18:20:25 +08:00
})
2025-04-08 08:48:03 +08:00
},
initChart() {
this.chart = echarts.init(this.$refs.chart);
this.updateChart();
},
resizeChart() {
if (this.chart) {
this.chart.resize();
}
},
updateChart() {
if (!this.chart || !this.dailyAmount.length) return;
const dates = this.dailyAmount.map(item => item.date);
2025-04-10 14:07:21 +08:00
const orderCounts = this.dailyAmount.map(item => item.order?.count || 0)
2025-04-08 08:48:03 +08:00
const orderAmounts = this.dailyAmount.map(item => item.order?.payAmount || 0);
const bonusAmounts = this.dailyAmount.map(item => item.bonus?.amount || 0);
const orderRefunds = this.dailyAmount.map(item => item.orderRefund?.amount || 0);
const bonusRefunds = this.dailyAmount.map(item => item.bonusRefund?.amount || 0);
const orderNetAmounts = this.dailyAmount.map((item, index) =>
(item.order?.payAmount || 0) - (item.orderRefund?.amount || 0)
);
const bonusNetAmounts = this.dailyAmount.map((item, index) =>
(item.bonus?.amount || 0) - (item.bonusRefund?.amount || 0)
);
const option = {
color: [
2025-04-10 14:07:21 +08:00
'#5B8FF9', // 柔和蓝 - 订单数量
'#61DDAA', // 柔和绿 - 订单金额
'#F6BD16', // 柔和黄 - 订单退款
'#6DC8EC', // 淡青 - 订单实收
'#9270CA', // 淡紫 - 分成金额
'#E8684A', // 柔和橙 - 分成退款
'#FF9D4D' // 柔和橙红 - 分成实收
2025-04-08 08:48:03 +08:00
],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
2025-04-10 14:07:21 +08:00
},
formatter: function(params) {
let result = params[0].axisValueLabel + '<br/>';
params.forEach(param => {
const value = param.value;
const marker = param.marker;
const seriesName = param.seriesName;
if (seriesName === '订单数量') {
result += marker + seriesName + '<span style="float: right; margin-left: 20px;">' + value + ' 单</span><br/>';
} else {
result += marker + seriesName + '<span style="float: right; margin-left: 20px;">' + value.toFixed(2) + ' 元</span><br/>';
}
});
return result;
2025-04-08 08:48:03 +08:00
}
},
legend: {
2025-05-06 18:42:44 +08:00
data: ['订单数量', '支付金额', '支付退款', '支付实收', '分成金额', '分成退款', '分成实收'],
2025-04-10 14:07:21 +08:00
top: 8,
selected: {
'订单数量': true,
2025-05-06 18:42:44 +08:00
'支付金额': false,
'支付退款': false,
'支付实收': true,
2025-04-10 14:07:21 +08:00
'分成金额': false,
'分成退款': false,
'分成实收': true
}
2025-04-08 08:48:03 +08:00
},
grid: {
left: '3%',
2025-04-10 14:07:21 +08:00
right: '3%',
bottom: '2%',
2025-04-08 08:48:03 +08:00
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
data: dates,
axisLabel: {
interval: 'auto',
fontSize: 12,
},
boundaryGap: true
},
yAxis: [
{
type: 'value',
name: '金额',
position: 'left',
axisLabel: {
2025-04-10 14:07:21 +08:00
formatter: value => {
return value.toFixed(2) + ' 元'
}
2025-04-08 08:48:03 +08:00
}
2025-04-10 14:07:21 +08:00
},
2025-04-08 08:48:03 +08:00
{
type: 'value',
name: '订单数量',
position: 'right',
axisLabel: {
formatter: '{value}'
}
}
],
series: [
{
name: '订单数量',
type: 'bar',
yAxisIndex: 1,
data: orderCounts,
itemStyle: {
opacity: 0.6
},
barWidth: '20%'
},
{
2025-05-06 18:42:44 +08:00
name: '支付金额',
2025-04-08 08:48:03 +08:00
type: 'line',
yAxisIndex: 0,
data: orderAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
2025-05-06 18:42:44 +08:00
name: '支付退款',
2025-04-08 08:48:03 +08:00
type: 'line',
yAxisIndex: 0,
data: orderRefunds,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
2025-05-06 18:42:44 +08:00
name: '支付实收',
2025-04-08 08:48:03 +08:00
type: 'line',
yAxisIndex: 0,
data: orderNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2
}
},
{
name: '分成金额',
type: 'line',
yAxisIndex: 0,
data: bonusAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '分成退款',
type: 'line',
yAxisIndex: 0,
data: bonusRefunds,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '分成实收',
type: 'line',
yAxisIndex: 0,
data: bonusNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2
}
}
]
};
this.chart.setOption(option);
2025-04-06 18:20:25 +08:00
}
}
}
</script>
<style lang="scss" scoped>
2025-04-08 08:48:03 +08:00
.el-date-picker {
margin-bottom: 20px;
}
</style>