409 lines
12 KiB
Vue
409 lines
12 KiB
Vue
<template>
|
||
<view class="business-case">
|
||
<!-- 营收特征标题 -->
|
||
<view class="section-header">
|
||
<text class="section-title">营收特征</text>
|
||
</view>
|
||
|
||
<!-- 营收特征分析图表 -->
|
||
<view class="chart-container">
|
||
<view style="width:100%;height: 80rpx;">
|
||
<!-- 选择器 -->
|
||
<picker mode="selector" :range="tabList" range-key="label" :value="getCurrentPickerIndex()"
|
||
@change="handlePickerChange" class="picker-container">
|
||
<view class="picker-display">
|
||
<text class="picker-text">{{ getCurrentTabLabel() }}</text>
|
||
<text class="picker-arrow">▼</text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
|
||
|
||
<view style="width:100%;height: 400rpx;">
|
||
<!-- 图表加载效果 -->
|
||
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
|
||
<!-- 实际图表 -->
|
||
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
|
||
:inScrollView="true" canvasId="businessCaseChart" :animation="false" :ontap="true" :ontouch="true"
|
||
tooltipFormat="businessCaseChart" />
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||
import ChartLoading from './ChartLoading.vue'
|
||
import request from "@/util/index.js";
|
||
import moment from 'moment'
|
||
|
||
export default {
|
||
components: {
|
||
QiunDataCharts,
|
||
ChartLoading
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
// Tab列表
|
||
tabList: [
|
||
{ label: "营收金额", value: 1 },
|
||
{ label: "客单量", value: 2 },
|
||
{ label: "客单均价", value: 3 }
|
||
],
|
||
selectTab: 1, // 当前选中的Tab
|
||
|
||
// 当前请求来的实际数据
|
||
realData: {},
|
||
|
||
// 图表原始数据
|
||
rawData: {
|
||
category: [],
|
||
seriesData: []
|
||
}
|
||
}
|
||
},
|
||
props: {
|
||
selectTime: {
|
||
type: String,
|
||
default: ""
|
||
},
|
||
},
|
||
computed: {
|
||
// 检查是否有图表数据
|
||
hasChartData() {
|
||
return this.rawData.category.length > 0 &&
|
||
this.rawData.seriesData.length > 0
|
||
},
|
||
|
||
// 图表数据
|
||
chartData() {
|
||
return {
|
||
categories: this.rawData.category,
|
||
series: this.rawData.seriesData
|
||
}
|
||
},
|
||
|
||
// 图表配置
|
||
chartOpts() {
|
||
return {
|
||
padding: [15, 15, 0, 15], // 增加顶部padding为picker留出空间
|
||
dataLabel: false,
|
||
enableScroll: true,
|
||
xAxis: {
|
||
disableGrid: true,
|
||
itemCount: 4,
|
||
},
|
||
yAxis: {
|
||
showTitle: true,
|
||
data: [{
|
||
min: 0,
|
||
title: this.getYAxisTitle(),
|
||
titleFontSize: 12,
|
||
titleOffsetY: -5,
|
||
titleOffsetX: 10,
|
||
}]
|
||
},
|
||
legend: {
|
||
show: true,
|
||
position: 'bottom',
|
||
float: 'center',
|
||
backgroundColor: 'rgba(0,0,0,0)',
|
||
borderColor: 'rgba(0,0,0,0)',
|
||
fontSize: 12,
|
||
fontColor: '#333333',
|
||
margin: 0,
|
||
padding: 0,
|
||
itemGap: 10,
|
||
textAlign: 'left'
|
||
},
|
||
extra: {
|
||
column: {
|
||
type: 'group',
|
||
width: 12,
|
||
activeBgColor: '#000000',
|
||
activeBgOpacity: 0.08,
|
||
seriesGap: 0,
|
||
barBorderRadius: [3, 3, 0, 0]
|
||
}
|
||
},
|
||
unitType: this.selectTab
|
||
}
|
||
}
|
||
},
|
||
|
||
onReady() {
|
||
this.handleGetBusinessCaseData()
|
||
},
|
||
|
||
methods: {
|
||
// 获取营收特征数据
|
||
async handleGetBusinessCaseData() {
|
||
const req = {
|
||
ProvinceCode: "530000",
|
||
StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||
ServerpartId: "", // 暂时为空,如果需要传入服务区ID可以在这里添加
|
||
}
|
||
|
||
const data = await this.getRevenueCompare(req);
|
||
|
||
// 处理数据
|
||
this.processChartData(data.Result_Data)
|
||
},
|
||
|
||
// 发起API请求获取营收特征数据
|
||
async getRevenueCompare(params) {
|
||
const data = await request.$webGet(
|
||
"CommercialApi/Revenue/GetRevenueCompare",
|
||
params
|
||
);
|
||
return data || {}
|
||
},
|
||
|
||
// 处理图表数据
|
||
processChartData(data) {
|
||
let monthList = []
|
||
|
||
// 获取月份列表
|
||
let list = data.RevenueAmountList
|
||
if (list && list.length > 0) {
|
||
list.forEach((item, index) => {
|
||
if (index === 0 && item.data && item.data.length > 0) {
|
||
item.data.forEach((subItem) => {
|
||
monthList.push(subItem[0])
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
// 营收金额数据
|
||
let revenueData = this.processRevenueAmount(data, monthList)
|
||
|
||
// 客单量数据
|
||
let ticketData = this.processTicketCount(data, monthList)
|
||
|
||
// 客单均价数据
|
||
let avgData = this.processAvgTicketAmount(data, monthList)
|
||
|
||
// 保存所有数据
|
||
this.realData = {
|
||
1: revenueData,
|
||
2: ticketData,
|
||
3: avgData
|
||
}
|
||
|
||
// 显示当前选中的数据
|
||
this.handleShowData(this.selectTab)
|
||
},
|
||
|
||
// 处理营收金额数据
|
||
processRevenueAmount(data, monthList) {
|
||
let category = []
|
||
let seriesData = []
|
||
|
||
let list = data.RevenueAmountList
|
||
if (list && list.length > 0) {
|
||
list.forEach((item) => {
|
||
let dataValues = []
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
let newData = item.data
|
||
dataValues.push(Number(((newData[month - 1][1]) / 10000).toFixed(2)))
|
||
})
|
||
}
|
||
seriesData.push({
|
||
name: item.name,
|
||
data: dataValues
|
||
})
|
||
})
|
||
}
|
||
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
category.push(`${month}月`)
|
||
})
|
||
}
|
||
|
||
return { category, seriesData }
|
||
},
|
||
|
||
// 处理客单量数据
|
||
processTicketCount(data, monthList) {
|
||
let category = []
|
||
let seriesData = []
|
||
|
||
let list = data.TicketCountList
|
||
if (list && list.length > 0) {
|
||
list.forEach((item) => {
|
||
let dataValues = []
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
let newData = item.data
|
||
dataValues.push(Number(((newData[month - 1][1]) / 10000).toFixed(2)))
|
||
})
|
||
}
|
||
seriesData.push({
|
||
name: item.name,
|
||
data: dataValues
|
||
})
|
||
})
|
||
}
|
||
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
category.push(`${month}月`)
|
||
})
|
||
}
|
||
|
||
return { category, seriesData }
|
||
},
|
||
|
||
// 处理客单均价数据
|
||
processAvgTicketAmount(data, monthList) {
|
||
let category = []
|
||
let seriesData = []
|
||
|
||
let list = data.AvgTicketAmountList
|
||
if (list && list.length > 0) {
|
||
list.forEach((item) => {
|
||
let dataValues = []
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
let newData = item.data
|
||
dataValues.push(Number(newData[month - 1][1]))
|
||
})
|
||
}
|
||
seriesData.push({
|
||
name: item.name,
|
||
data: dataValues
|
||
})
|
||
})
|
||
}
|
||
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((month) => {
|
||
category.push(`${month}月`)
|
||
})
|
||
}
|
||
|
||
return { category, seriesData }
|
||
},
|
||
|
||
// 切换显示的数据
|
||
handleShowData(tabValue) {
|
||
const data = this.realData[tabValue]
|
||
if (data) {
|
||
this.rawData = {
|
||
category: data.category,
|
||
seriesData: data.seriesData
|
||
}
|
||
}
|
||
},
|
||
|
||
// 切换Tab
|
||
handleChangeTab(value) {
|
||
this.selectTab = value
|
||
this.handleShowData(value)
|
||
},
|
||
|
||
// picker选择改变
|
||
handlePickerChange(e) {
|
||
const selectedIndex = e.detail.value
|
||
const selectedTab = this.tabList[selectedIndex]
|
||
this.handleChangeTab(selectedTab.value)
|
||
},
|
||
|
||
// 获取当前picker的索引
|
||
getCurrentPickerIndex() {
|
||
return this.tabList.findIndex(item => item.value === this.selectTab)
|
||
},
|
||
|
||
// 获取当前选中的Tab标签
|
||
getCurrentTabLabel() {
|
||
const currentTab = this.tabList.find(item => item.value === this.selectTab)
|
||
return currentTab ? currentTab.label : '营收金额'
|
||
},
|
||
|
||
// 获取Y轴标题
|
||
getYAxisTitle() {
|
||
if (this.selectTab === 1) {
|
||
return '营收金额(万元)'
|
||
} else if (this.selectTab === 2) {
|
||
return '客单量(万笔)'
|
||
} else if (this.selectTab === 3) {
|
||
return '客单均价(元)'
|
||
}
|
||
return ''
|
||
},
|
||
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
@primary-color: #46B8F3;
|
||
@secondary-color: #3CD495;
|
||
@danger-color: #FF5E5E;
|
||
@success-color: #52C41A;
|
||
@text-primary: #333;
|
||
@text-secondary: #666;
|
||
@text-light: #999;
|
||
@bg-white: #ffffff;
|
||
@border-radius: 16rpx;
|
||
@shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
|
||
.business-case {
|
||
margin-top: 24rpx;
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
padding: 0 8rpx;
|
||
box-sizing: border-box;
|
||
height: 40rpx;
|
||
|
||
.section-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
}
|
||
|
||
.chart-container {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 24rpx;
|
||
box-shadow: @shadow;
|
||
margin-bottom: 24rpx;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
|
||
.picker-container {
|
||
position: absolute;
|
||
top: 16rpx;
|
||
right: 16rpx;
|
||
z-index: 10;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 8rpx;
|
||
padding: 8rpx 16rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
|
||
.picker-display {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 28rpx;
|
||
color: @text-primary;
|
||
|
||
.picker-arrow {
|
||
font-size: 24rpx;
|
||
color: @text-secondary;
|
||
margin-left: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |