更新图表

This commit is contained in:
磷叶 2025-05-14 09:32:06 +08:00
parent 28e6883777
commit 809c447b72
4 changed files with 399 additions and 10 deletions

View File

@ -26,6 +26,19 @@ export function getDailyAmount(query) {
}) })
} }
/**
* 获取每日结算金额统计数据
* @param {Object} query 查询参数
* @returns {Promise} 返回每日结算金额统计数据
*/
export function getDailySettleAmount(query) {
return request({
url: '/dashboard/dailySettleAmount',
method: 'get',
params: query
})
}
/** /**
* 获取营收统计数据 * 获取营收统计数据
* @param {Object} query 查询参数 * @param {Object} query 查询参数

View File

@ -1,6 +1,6 @@
<template> <template>
<div style="min-height: 800px" v-loading="loading"> <div style="min-height: 800px" v-loading="loading">
<el-row :gutter="gutter" v-if="stat"> <el-row :gutter="gutter">
<el-col :sm="24" :md="18"> <el-col :sm="24" :md="18">
<el-row type="flex" justify="space-between"> <el-row type="flex" justify="space-between">
@ -35,8 +35,8 @@
</el-col> </el-col>
</el-row> </el-row>
<el-card header="每日流水统计" shadow="never" id="order-daily-stat"> <el-card header="结算统计" shadow="never" id="order-daily-stat">
<order-daily-stat ref="dailyStat" :query="areaQuery"/> <daily-settle-amount-stat ref="dailyStat" :query="areaQuery"/>
</el-card> </el-card>
</el-col> </el-col>
<el-col :sm="24" :md="6"> <el-col :sm="24" :md="6">
@ -63,22 +63,21 @@ import { getInfo } from '@/api/login'
import { StatKeys } from '@/utils/enums' import { StatKeys } from '@/utils/enums'
import { startGuide } from '@/utils/guide' import { startGuide } from '@/utils/guide'
import BalancePanel from '@/views/bst/index/components/BalancePanel' import BalancePanel from '@/views/bst/index/components/BalancePanel'
import DailySettleAmountStat from '@/views/bst/index/components/DailySettleAmountStat'
import DeviceStat from '@/views/bst/index/components/DeviceStat' import DeviceStat from '@/views/bst/index/components/DeviceStat'
import MchStat from '@/views/bst/index/components/MchStat' import MchStat from '@/views/bst/index/components/MchStat'
import OrderDailyStat from '@/views/bst/index/components/OrderDailyStat'
import OrderStat from '@/views/bst/index/components/OrderStat'
import TodoList from '@/views/bst/index/components/TodoList' import TodoList from '@/views/bst/index/components/TodoList'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
export default { export default {
name: 'Index', name: 'Index',
components: { components: {
MchStat, MchStat,
DeviceStat, DeviceStat,
TodoList, TodoList,
OrderDailyStat,
BalancePanel, BalancePanel,
OrderStat, DailySettleAmountStat,
}, },
data() { data() {
return { return {
@ -97,7 +96,7 @@ export default {
areaQuery() { areaQuery() {
return { return {
areaId: this.areaId, areaId: this.areaId,
bonusUserId: this.isSysAdmin() ? null : this.userId, userId: this.isSysAdmin() ? null : this.userId,
} }
}, },
mchStatQuery() { mchStatQuery() {
@ -128,7 +127,7 @@ export default {
this.getStat(); this.getStat();
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.dailyStat) { if (this.$refs.dailyStat) {
this.$refs.dailyStat.getDailyAmount(); this.$refs.dailyStat.getList();
} }
if (this.$refs.mchStat) { if (this.$refs.mchStat) {
this.$refs.mchStat.getStat(); this.$refs.mchStat.getStat();

View File

@ -0,0 +1,375 @@
<template>
<div v-loading="loading">
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
@change="getList"
size="mini"
:clearable="false"
:picker-options="DatePickerOptions.DEFAULT"
/>
<div ref="chart" :style="{width: width, height: height}"></div>
</div>
</template>
<script>
import { getDailySettleAmount } from '@/api/dashboard/dashboard';
import { getLastDateStr } from '@/utils';
import { DatePickerOptions } from '@/utils/constants';
import * as echarts from 'echarts';
export default {
name: 'DailySettleAmountStat',
props: {
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
},
query: {
type: Object,
default: () => ({})
}
},
data() {
return {
DatePickerOptions,
loading: false,
chartData: [],
queryParams: {
dateRange: [
getLastDateStr(7),
getLastDateStr(0)
]
},
chart: null
}
},
created() {
this.getList();
},
mounted() {
this.initChart();
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
this.chart = null;
}
},
methods: {
getList() {
this.loading = true;
Object.assign(this.queryParams, this.query);
getDailySettleAmount(this.queryParams).then(res => {
this.chartData = res.data;
this.updateChart();
}).finally(() => {
this.loading = false;
})
},
initChart() {
this.chart = echarts.init(this.$refs.chart);
this.updateChart();
},
resizeChart() {
if (this.chart) {
this.chart.resize();
}
},
updateChart() {
if (!this.chart || !this.chartData.length) {
return;
}
const dates = this.chartData.map(item => item.date);
const orderSettleAmounts = this.chartData.map(item => item.orderSettleAmount || 0);
const refundAmounts = this.chartData.map(item => item.refundAmount || 0);
const bonusSettleAmounts = this.chartData.map(item => item.bonusSettleAmount || 0);
const bonusRefundAmounts = this.chartData.map(item => item.bonusRefundAmount || 0);
const orderNetAmounts = this.chartData.map((item) =>
(item.orderSettleAmount || 0) - (item.refundAmount || 0)
);
const bonusNetAmounts = this.chartData.map((item) =>
(item.bonusSettleAmount || 0) - (item.bonusRefundAmount || 0)
);
const option = {
color: [
'#67C23A', //
'#F56C6C', // 退
'#E6A23C', //
'#909399', //
'#F56C6C', // 退
'#67C23A' //
],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderColor: '#ccc',
borderWidth: 1,
textStyle: {
color: '#333'
},
formatter: function(params) {
let result = params[0].axisValueLabel + '<br/>';
params.forEach(param => {
const value = param.value;
const marker = param.marker;
const seriesName = param.seriesName;
result += marker + seriesName + '<span style="float: right; margin-left: 20px;">' + value.toFixed(2) + ' 元</span><br/>';
});
return result;
}
},
legend: {
data: ['支付金额', '退款金额', '订单实收', '分成结算金额', '分成退款金额', '分成实收'],
bottom: 0,
left: 'center',
textStyle: {
color: '#666'
},
selected: {
'支付金额': false,
'退款金额': false,
'订单实收': true,
'分成结算金额': false,
'分成退款金额': false,
'分成实收': true
}
},
grid: {
left: '3%',
right: '3%',
bottom: '40px',
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
data: dates,
axisLabel: {
interval: 'auto',
fontSize: 12,
color: '#666'
},
axisLine: {
lineStyle: {
color: '#ddd'
}
},
boundaryGap: true
},
yAxis: {
type: 'value',
name: '金额',
axisLabel: {
formatter: value => {
return value.toFixed(2) + ' 元'
},
color: '#666'
},
axisLine: {
lineStyle: {
color: '#ddd'
}
},
splitLine: {
lineStyle: {
color: '#eee'
}
}
},
series: [
{
name: '支付金额',
type: 'line',
data: orderSettleAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(103, 194, 58, 0.3)'
}, {
offset: 1,
color: 'rgba(103, 194, 58, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
},
{
name: '退款金额',
type: 'line',
data: refundAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(245, 108, 108, 0.3)'
}, {
offset: 1,
color: 'rgba(245, 108, 108, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
},
{
name: '订单实收',
type: 'line',
data: orderNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(230, 162, 60, 0.3)'
}, {
offset: 1,
color: 'rgba(230, 162, 60, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
},
{
name: '分成结算金额',
type: 'line',
data: bonusSettleAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(144, 147, 153, 0.3)'
}, {
offset: 1,
color: 'rgba(144, 147, 153, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
},
{
name: '分成退款金额',
type: 'line',
data: bonusRefundAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(245, 108, 108, 0.3)'
}, {
offset: 1,
color: 'rgba(245, 108, 108, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
},
{
name: '分成实收',
type: 'line',
data: bonusNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 4,
areaStyle: {
opacity: 0.2,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(103, 194, 58, 0.3)'
}, {
offset: 1,
color: 'rgba(103, 194, 58, 0.1)'
}]
}
},
lineStyle: {
width: 2
}
}
]
};
this.chart.setOption(option);
}
}
}
</script>
<style lang="scss" scoped>
.el-date-picker {
margin-bottom: 20px;
}
</style>

View File

@ -85,7 +85,9 @@ export default {
} }
}, },
updateChart() { updateChart() {
if (!this.chart || !this.dailyAmount.length) return; if (!this.chart || !this.dailyAmount.length) {
return;
}
const dates = this.dailyAmount.map(item => item.date); const dates = this.dailyAmount.map(item => item.date);
const orderCounts = this.dailyAmount.map(item => item.order?.count || 0) const orderCounts = this.dailyAmount.map(item => item.order?.count || 0)