545 lines
17 KiB
Vue
545 lines
17 KiB
Vue
<script setup lang="ts">
|
||
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||
import SmallTitle from '../smallTitle/smallTitle.vue'
|
||
import RevenueYOYIcon from '../../../../assets/image/RevenueYOYIcon.png'
|
||
import './BusinessCase.less'
|
||
import moment from 'moment';
|
||
import { handleCodeGetRevenueCompare, handleGetRevenueTrend } from '../../service';
|
||
import * as echarts from 'echarts/core';
|
||
import { BarChart, LineChart } from 'echarts/charts';
|
||
import {
|
||
GridComponent,
|
||
TitleComponent,
|
||
TooltipComponent,
|
||
LegendComponent,
|
||
DatasetComponent, // 必须添加!否则 dataset 功能无效
|
||
TransformComponent // 如果使用 dataset.source 需要此组件
|
||
} from 'echarts/components';
|
||
import { CanvasRenderer } from 'echarts/renderers';
|
||
import addIcon from '../../../../assets/image/addIcon.png'
|
||
import reduce from '../../../../assets/image/reduce.png'
|
||
|
||
|
||
|
||
// 注册组件
|
||
echarts.use([
|
||
LineChart,
|
||
BarChart,
|
||
GridComponent,
|
||
TitleComponent,
|
||
TooltipComponent,
|
||
LegendComponent,
|
||
DatasetComponent, // 必须注册
|
||
TransformComponent, // 必须注册
|
||
CanvasRenderer
|
||
]);
|
||
|
||
|
||
let myChart: echarts.ECharts;
|
||
let myChartBottom: echarts.ECharts;
|
||
|
||
const tabList: any = [
|
||
{ label: "营收金额", value: 1 },
|
||
{ label: "客单量", value: 2 },
|
||
{ label: "客单均价", value: 3 },
|
||
]
|
||
let selectTab = ref<number>(1)
|
||
|
||
|
||
|
||
// 当前请求来的实际数据
|
||
let realData = ref<any>()
|
||
// 请求到的整个数据
|
||
let getAllData = ref<any>()
|
||
|
||
// 传入的数据
|
||
const props = defineProps<{
|
||
currentService?: any;
|
||
selectTab?: any
|
||
}>();
|
||
|
||
// 监听传入的选中服务区
|
||
watch(
|
||
() => props.currentService,
|
||
(newVal, oldVal) => {
|
||
handleGetData()
|
||
handleGetBottomData()
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
// 监听传入的选中服务区
|
||
watch(
|
||
() => props.selectTab,
|
||
(newVal, oldVal) => {
|
||
handleShowData(newVal)
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
onMounted(async () => {
|
||
// 用tab可以修改的方法
|
||
await handleGetData()
|
||
// await handleGetBottomData()
|
||
})
|
||
|
||
|
||
// 切换tab的内容
|
||
const handleChangeTab = async (value: number) => {
|
||
selectTab.value = value
|
||
handleShowData(value)
|
||
}
|
||
|
||
// 拿到数据的方法
|
||
const handleGetData = async () => {
|
||
const req: any = {
|
||
ProvinceCode: "530000",
|
||
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||
ServerpartId: props.currentService?.SERVERPART_ID || "",
|
||
}
|
||
|
||
let BusinessCase = sessionStorage.getItem('BusinessCase')
|
||
let data: any = []
|
||
if (BusinessCase) {
|
||
data = JSON.parse(BusinessCase)
|
||
} else {
|
||
data = await handleCodeGetRevenueCompare(req)
|
||
sessionStorage.setItem("BusinessCase", JSON.stringify(data))
|
||
}
|
||
|
||
// const data = await handleCodeGetRevenueCompare(req)
|
||
|
||
getAllData.value = data
|
||
|
||
// 营收金额
|
||
let category: any = ['product']
|
||
let monthList: number[] = []
|
||
let list = data.RevenueAmountList
|
||
if (list && list.length > 0) {
|
||
list.forEach((item: any, index: number) => {
|
||
category.push(item.name)
|
||
if (index === 0 && item.data && item.data.length > 0) {
|
||
item.data.forEach((subItem: any) => {
|
||
monthList.push(subItem[0])
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
let aiObj1: any = {}
|
||
// 营收
|
||
let res: any = []
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((item: number) => {
|
||
let list: any = [`${item}月`]
|
||
data.RevenueAmountList.forEach((subItem: any) => {
|
||
let newData: any = subItem.data
|
||
list.push(Number(((newData[item - 1][1]) / 10000).toFixed(2)))
|
||
})
|
||
aiObj1[`${item}月`] = `工作日平均${list[1]}元,周末平均${list[2]}元,节假日平均${list[3]}元`
|
||
res.push(list)
|
||
})
|
||
}
|
||
|
||
// 客单量
|
||
let res2: any = []
|
||
let aiObj2: any = {}
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((item: number) => {
|
||
let list: any = [`${item}月`]
|
||
data.TicketCountList.forEach((subItem: any) => {
|
||
let newData: any = subItem.data
|
||
list.push(Number(((newData[item - 1][1]) / 10000).toFixed(2)))
|
||
})
|
||
aiObj2[`${item}月`] = `工作日平均${list[1]}元,周末平均${list[2]}元,节假日平均${list[3]}元`
|
||
res2.push(list)
|
||
})
|
||
}
|
||
|
||
// 均价
|
||
let res3: any = []
|
||
let aiObj3: any = {}
|
||
if (monthList && monthList.length > 0) {
|
||
monthList.forEach((item: number) => {
|
||
let list: any = [`${item}月`]
|
||
data.AvgTicketAmountList.forEach((subItem: any) => {
|
||
let newData: any = subItem.data
|
||
list.push(newData[item - 1][1])
|
||
})
|
||
aiObj3[`${item}月`] = `工作日平均${list[1]}元,周末平均${list[2]}元,节假日平均${list[3]}元`
|
||
res3.push(list)
|
||
})
|
||
}
|
||
|
||
|
||
let obj: any = {
|
||
1: [category, ...res],
|
||
2: [category, ...res2],
|
||
3: [category, ...res3],
|
||
}
|
||
realData.value = obj
|
||
|
||
let BusinessCaseAI = sessionStorage.getItem('BusinessCaseAI')
|
||
if (BusinessCaseAI) { } else {
|
||
let aiObj: any = {
|
||
"营收金额": aiObj1,
|
||
"客单量": aiObj2,
|
||
"客单均价": aiObj3,
|
||
}
|
||
sessionStorage.setItem("BusinessCaseAI", JSON.stringify(aiObj))
|
||
}
|
||
|
||
handleShowData(selectTab.value)
|
||
}
|
||
|
||
// 拿到底部的方法
|
||
const handleGetBottomData = async () => {
|
||
const req: any = {
|
||
ProvinceCode: "530000",
|
||
StatisticsDate: moment().format('YYYY'),
|
||
StatisticsType: 1,
|
||
ServerpartId: props.currentService?.SERVERPART_ID || "",
|
||
}
|
||
const yesReq: any = {
|
||
ProvinceCode: "530000",
|
||
StatisticsDate: moment().subtract(1, 'y').format('YYYY'),
|
||
StatisticsType: 1,
|
||
ServerpartId: props.currentService?.SERVERPART_ID || "",
|
||
}
|
||
const data = await handleGetRevenueTrend(req)
|
||
const yesData = await handleGetRevenueTrend(yesReq)
|
||
|
||
|
||
let category: string[] = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
||
let currentYear: number[] = []
|
||
let lastYear: number[] = []
|
||
|
||
if (data && data.length > 0) {
|
||
data.forEach((item: any) => {
|
||
currentYear.push(Number((Number(item.value) / 10000).toFixed(2)))
|
||
})
|
||
}
|
||
|
||
if (yesData && yesData.length > 0) {
|
||
yesData.forEach((item: any) => {
|
||
lastYear.push(Number((Number(item.value) / 10000).toFixed(2)))
|
||
})
|
||
}
|
||
|
||
await handleShowBottomData({
|
||
category: category,
|
||
currentYear: currentYear,
|
||
lastYear: lastYear,
|
||
})
|
||
|
||
}
|
||
|
||
// 切换显示的数据源 营收特征分析的
|
||
const handleShowData = async (value: number) => {
|
||
let data = realData.value[value]
|
||
|
||
|
||
|
||
const chartDom = document.getElementById('featureAnalysis');
|
||
if (!chartDom) return;
|
||
|
||
myChart = echarts.init(chartDom);
|
||
|
||
const option = {
|
||
legend: {
|
||
top: 15,
|
||
right: 10,
|
||
textStyle: {
|
||
color: '#ffffff' // 设置图例文字为白色
|
||
}
|
||
},
|
||
tooltip: { trigger: 'axis' },
|
||
dataset: { source: data },
|
||
xAxis: {
|
||
type: 'category',
|
||
axisLabel: {
|
||
width: '80',
|
||
interval: 0,
|
||
color: '#fff',
|
||
formatter: '{value}' // 刻度值保持纯数字
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#fff' // 设置 y 轴线颜色为白色(可选)
|
||
}
|
||
},
|
||
axisTick: {
|
||
show: false // 隐藏刻度小线条
|
||
}
|
||
},
|
||
yAxis: {
|
||
name: `${selectTab.value === 1 ? '营收金额(万元)' : selectTab.value === 2 ? '客单量(万笔)' : selectTab.value === 3 ? '客单均价(元)' : ''}`,
|
||
splitLine: { show: false }, // 隐藏网格线
|
||
axisLine: {
|
||
show: true, // 显示Y轴线
|
||
lineStyle: {
|
||
color: '#fff' // 轴线颜色
|
||
}
|
||
},
|
||
axisTick: {
|
||
show: false // 隐藏刻度线(短横线)
|
||
},
|
||
axisLabel: {
|
||
width: '80',
|
||
color: '#fff'
|
||
},
|
||
nameTextStyle: {
|
||
color: '#fff', // 名称颜色
|
||
padding: [0, 0, 0, 30] // 名称位置调整
|
||
}
|
||
},
|
||
series: [{
|
||
type: 'bar',
|
||
itemStyle: {
|
||
color: '#0094FF' // 第一根柱子的颜色
|
||
}
|
||
},
|
||
{
|
||
type: 'bar',
|
||
itemStyle: {
|
||
color: '#69BCFF' // 第一根柱子的颜色
|
||
}
|
||
},
|
||
{
|
||
type: 'bar',
|
||
itemStyle: {
|
||
color: '#6B7C8B' // 第一根柱子的颜色
|
||
}
|
||
}],
|
||
grid: {
|
||
left: '0', // 左侧间距
|
||
right: '0', // 右侧间距
|
||
bottom: '0', // 底部间距
|
||
top: '50', // 顶部间距
|
||
containLabel: true // 确保坐标轴标签在grid内
|
||
},
|
||
};
|
||
|
||
myChart.setOption(option);
|
||
window.addEventListener('resize', resizeChart);
|
||
}
|
||
|
||
// 切换显示数据源 营收同比分析的
|
||
const handleShowBottomData = async (res: any) => {
|
||
|
||
const chartDom = document.getElementById('featureAnalysisBottom');
|
||
if (!chartDom) return;
|
||
myChartBottom = echarts.init(chartDom);
|
||
|
||
|
||
const option = {
|
||
legend: {
|
||
top: 0, // 距离容器底部距离
|
||
right: 0,
|
||
itemWidth: 20, // 图例标记的图形宽度
|
||
itemHeight: 10, // 图例标记的图形高度
|
||
textStyle: {
|
||
color: '#fff' // 图例文字颜色
|
||
}
|
||
},
|
||
xAxis: {
|
||
type: 'category',
|
||
data: res.category,
|
||
boundaryGap: true,
|
||
axisLabel: {
|
||
interval: 0,
|
||
lineStyle: {
|
||
color: '#fff' // 设置 y 轴线颜色为白色(可选)
|
||
}
|
||
},
|
||
axisLine: {
|
||
lineStyle: {
|
||
color: '#fff' // 设置 y 轴线颜色为白色(可选)
|
||
}
|
||
},
|
||
axisTick: {
|
||
show: false // 隐藏刻度小线条
|
||
}
|
||
},
|
||
yAxis: {
|
||
name: `${selectTab.value === 1 ? '营收金额(万元)' : selectTab.value === 2 ? '客单量(万笔)' : selectTab.value === 3 ? '客单均价(元)' : ''}`,
|
||
type: 'value',
|
||
splitLine: { show: false },
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#fff' // 设置 y 轴线颜色为白色(可选)
|
||
}
|
||
},
|
||
axisLabel: {
|
||
color: '#fff',
|
||
},
|
||
nameTextStyle: {
|
||
color: '#fff', // 名称颜色
|
||
padding: [0, 0, 0, 20] // 名称位置调整
|
||
}
|
||
},
|
||
grid: {
|
||
left: '10', // 增加左侧空间
|
||
right: '10', // 增加右侧空间
|
||
bottom: '0',
|
||
top: '30',
|
||
containLabel: true
|
||
},
|
||
series: [
|
||
{
|
||
name: '今年',
|
||
data: res.currentYear,
|
||
type: 'line',
|
||
lineStyle: {
|
||
width: 2,
|
||
color: '#0094FF'
|
||
},
|
||
itemStyle: {
|
||
color: '#0094FF'
|
||
},
|
||
},
|
||
{
|
||
name: '去年',
|
||
data: res.lastYear,
|
||
type: 'line',
|
||
lineStyle: {
|
||
width: 2,
|
||
color: '#00FFB7' // 改为橙色
|
||
},
|
||
itemStyle: {
|
||
color: '#00FFB7' // 改为橙色
|
||
},
|
||
}
|
||
],
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'line' // 改为线条指示器
|
||
},
|
||
formatter: function (params: any) {
|
||
return `${params.map((item: any) => {
|
||
return `<div>
|
||
${item.seriesName}:${item.value}万元
|
||
</div>`
|
||
}).join("")}`
|
||
}
|
||
}
|
||
};
|
||
|
||
myChartBottom.setOption(option);
|
||
window.addEventListener('resize', resizeChartBottom);
|
||
}
|
||
|
||
const resizeChart = () => {
|
||
myChart?.resize();
|
||
};
|
||
const resizeChartBottom = () => {
|
||
myChart?.resize();
|
||
};
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('resize', resizeChart);
|
||
myChart?.dispose();
|
||
|
||
|
||
window.removeEventListener('resize', resizeChartBottom);
|
||
myChartBottom?.dispose();
|
||
});
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
<template>
|
||
<div class="BusinessCaseBox">
|
||
<SmallTitle title="营收特征">
|
||
<!-- <template #extra>
|
||
<div class="BusinessCaseTabBox">
|
||
<div :class="selectTab === item.value ? 'BusinessCaseItem selectBusinessCaseItem' : 'BusinessCaseItem'"
|
||
v-for="(item, index) in tabList" :key="index" @click="handleChangeTab(item.value)">
|
||
{{ item.label }}
|
||
</div>
|
||
</div>
|
||
</template> -->
|
||
</SmallTitle>
|
||
|
||
<!-- 营收同比 -->
|
||
<div class="BusinessCaseRevenueYOY" v-if="false">
|
||
<div class="BusinessCaseLeftItem">
|
||
<img class="BusinessIcon" :src="RevenueYOYIcon" />
|
||
</div>
|
||
|
||
<div class="BusinessCaseRightItem">
|
||
<div class="BusinessCaseRightItemTop">
|
||
<div class="rightItemTitle">营收同比</div>
|
||
<div class="rightItemUpdate">{{ moment().subtract(1, 'd').format('YYYY-MM-DD') }}</div>
|
||
</div>
|
||
<div class="BusinessCaseRightItemBottom">
|
||
<div class="BusinessCaseItemBottomLeft">
|
||
<div class="changeBox">
|
||
<img v-if="getAllData?.RevenueAmountYOYRate || getAllData?.TicketCountYOYRate || getAllData?.AvgTicketAmountRate"
|
||
class="changeIcon" :src="selectTab === 1 ? getAllData?.RevenueAmountYOYRate > 0 ? addIcon : reduce :
|
||
selectTab === 2 ? getAllData?.TicketCountYOYRate > 0 ? addIcon : reduce :
|
||
selectTab === 3 ? getAllData?.AvgTicketAmountRate > 0 ? addIcon : reduce : ''
|
||
" />
|
||
<div class="changeText" :style="{
|
||
color: selectTab === 1 ? getAllData?.RevenueAmountYOYRate > 0 ? '#00FF00' : '#D24343' :
|
||
selectTab === 2 ? getAllData?.TicketCountYOYRate > 0 ? '#00FF00' : '#D24343' :
|
||
selectTab === 3 ? getAllData?.AvgTicketAmountRate > 0 ? '#00FF00' : '#D24343' : ''
|
||
}">{{
|
||
selectTab === 1 ? getAllData?.RevenueAmountYOYRate || '-' :
|
||
selectTab === 2 ? getAllData?.TicketCountYOYRate || '-' :
|
||
selectTab === 3 ? getAllData?.AvgTicketAmountRate || '-' : ''
|
||
}}%</div>
|
||
<div class="compareTitle">(相比去年同日)</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="BusinessCaseItemBottomRight">
|
||
<div class="BusinessCaseRevenueValue">{{ selectTab === 1 ?
|
||
getAllData?.RevenueAmount.toLocaleString() :
|
||
selectTab
|
||
=== 2 ?
|
||
getAllData?.TicketCount.toLocaleString() : selectTab === 3 ?
|
||
getAllData?.AvgTicketAmount.toLocaleString() : ''
|
||
}}</div>
|
||
<div class="BusinessCaseRevenueUnit">{{ selectTab === 2 ? '笔' : '元' }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <div class="rightItemLeft">
|
||
<div class="rightItemTitleBox">
|
||
<div class="rightItemTitle">营收同比</div>
|
||
<div class="rightItemUpdate">{{ moment().subtract(1, 'd').format('YYYY-MM-DD') }}</div>
|
||
</div>
|
||
<div class="rightItemBottom">
|
||
<div class="compareTitle">相比去年同日</div>
|
||
<div class="changeBox">
|
||
<img class="changeIcon" />
|
||
<div class="changeText"></div>
|
||
</div>
|
||
</div>
|
||
</div> -->
|
||
|
||
<!-- <div class="rightItemRight">
|
||
<div class="BusinessCaseRevenueValue"></div>
|
||
<div class="BusinessCaseRevenueUnit">元</div>
|
||
</div> -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 营收特征分析 -->
|
||
<div class="featureAnalysis">
|
||
<!-- <SmallTitle title="营收特征分析" /> -->
|
||
|
||
<div class="featureAnalysisBox" id="featureAnalysis"></div>
|
||
|
||
<!-- <SmallTitle title="营收同比分析" style="margin-top: 31px;" />
|
||
|
||
<div class="featureAnalysisBottom" id="featureAnalysisBottom"></div> -->
|
||
</div>
|
||
|
||
</div>
|
||
</template> |