Files
xiaokuaisong-shangjia/p-BluPrint_1.0.288888/pages/Statistics/Statistics.vue
2025-08-18 10:01:04 +08:00

217 lines
5.3 KiB
Vue

<template>
<view class="page-container">
<view style="width:750rpx; height:800rpx">
<picker mode="selector" :range="years" @change="onChangeYear">
<view class="year-selector">选择年份: {{ selectedYear }}</view>
</picker>
<l-echart ref="chartRef" @finished="fetchDataAndInit" class="charts"></l-echart>
</view>
</view>
</template>
<script>
import * as echarts from 'echarts';
import { apiImageUrl } from '../../API/api';
export default {
data() {
return {
selectedYear: new Date().getFullYear(),
years: [],
option: {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
confine: true
},
legend: {
data: ['收款', '退款']
},
grid: {
left: 20,
right: 20,
bottom: 15,
top: 40,
containLabel: true
},
xAxis: [
{
type: 'value',
axisLine: {
lineStyle: {
color: '#999999'
}
},
axisLabel: {
color: '#666666'
}
}
],
yAxis: [
{
type: 'category',
axisTick: { show: false },
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
axisLine: {
lineStyle: {
color: '#999999'
}
},
axisLabel: {
color: '#666666'
}
}
],
series: [
{
name: '收款',
type: 'bar',
stack: '总量',
label: {
normal: {
show: true
}
},
data: []
},
{
name: '退款',
type: 'bar',
stack: '总量',
label: {
normal: {
show: true,
position: 'left'
}
},
data: []
}
]
}
};
},
created() {
this.initYears();
},
methods: {
initYears() {
const currentYear = new Date().getFullYear();
for (let year = currentYear - 5; year <= currentYear; year++) {
this.years.push(year);
}
},
onChangeYear(e) {
this.selectedYear = this.years[e.detail.value];
this.fetchDataAndInit();
},
async fetchDataAndInit() {
try {
const [incomeData, refundData] = await Promise.all([
this.getMonthlyRevenue(this.selectedYear, 1),
this.getMonthlyRevenue(this.selectedYear, 2)
]);
console.log('Fetched monthly income:', incomeData);
console.log('Fetched monthly refunds:', refundData);
this.option.series[0].data = incomeData.map(Number);
this.option.series[1].data = refundData.map(revenue => -Math.abs(Number(revenue)));
this.initChart();
} catch (error) {
console.error('Error fetching monthly revenue:', error);
}
},
async getMonthlyRevenue(year, state) {
let revenues = [];
for (let month = 0; month < 12; month++) {
const startDate = new Date(year, month, 1).toISOString().split('T')[0];
const endDate = new Date(year, month + 1, 0).toISOString().split('T')[0];
try {
const response = await uni.request({
url: `${apiImageUrl}/api/orders/count/money`,
method: 'POST',
header: {
'cookie': uni.getStorageSync("cookie")
},
data: {
businessId: uni.getStorageSync("businessId"),
businessName: uni.getStorageSync("businessName"),
businessState: 0,
categoryId: 1,
endTime: endDate,
startTime: startDate,
state: state,
type: "1"
}
});
if (response[1].data && response[1].data.data !== undefined) {
const revenue = parseFloat(response[1].data.data);
revenues.push(isNaN(revenue) ? 0 : revenue);
} else {
revenues.push(0);
}
} catch (error) {
console.error(`Error fetching revenue for ${month + 1}月 with state ${state}:`, error);
revenues.push(0);
}
}
return revenues;
},
async initChart() {
const chart = await this.$refs.chartRef.init(echarts);
chart.setOption(this.option);
}
}
};
</script>
<style scoped>
.page-container {
background-color: #2237bf;
width: 100%;
height: 100vh;
padding: 20rpx;
box-sizing: border-box;
}
.year-selector {
width: 220px;
height: 30px;
margin: 0 auto;
margin-bottom: 15px;
text-align: center;
line-height: 30px;
background-color:rgba(245, 245, 220, 0.6);
border-radius: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
font-size: 14px;
color: #333;
cursor: pointer;
transition: all 0.2s ease-in-out;
&:hover,
&:active {
background-color: rgba(245, 245, 220, 0.8);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1);
}
}
.charts {
background-color: #fff;
width: 90%;
margin: 0 auto;
border: 1px solid #000;
border-radius: 15px;
}
</style>