update
This commit is contained in:
parent
e049aaaf45
commit
528929f870
@ -9,32 +9,37 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
/* 允许换行 */
|
||||||
|
}
|
||||||
|
|
||||||
.AreaLegendBoxItem {
|
.AreaLegendBoxItem {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
/* 每个项目占据20%的宽度,最多显示5个 */
|
||||||
|
min-width: 120px;
|
||||||
|
/* 确保每个项目有足够的空间 */
|
||||||
|
|
||||||
.AreaLegendBoxItemIcon {
|
.AreaLegendBoxItemIcon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
border-radius: 50%;
|
margin-bottom: 8px;
|
||||||
}
|
border-radius: 50%;
|
||||||
|
|
||||||
.AreaLegendBoxItemLabel {
|
|
||||||
font-family: OPPOSans, OPPOSans;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #E4F3FF;
|
|
||||||
line-height: 18px;
|
|
||||||
text-align: left;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.AreaLegendBoxItemLabel {
|
||||||
|
font-family: OPPOSans, OPPOSans;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #E4F3FF;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,15 +2,13 @@
|
|||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import './AreaLegend.less'
|
import './AreaLegend.less'
|
||||||
|
|
||||||
|
// 配色方案,扩展为30个颜色
|
||||||
// 配色方案一
|
|
||||||
let colorList1 = [
|
let colorList1 = [
|
||||||
"#4F83FA",
|
"#4F83FA", "#A39BFF", "#63B6FC", "#88DFB2", "#88C3BF", "#d9dcf3",
|
||||||
"#A39BFF",
|
"#FF7F50", "#87CEFA", "#8A2BE2", "#A52A2A", "#DEB887", "#5F9EA0",
|
||||||
"#63B6FC",
|
"#7FFF00", "#D2691E", "#FF69B4", "#CD5C5C", "#8B0000", "#006400",
|
||||||
"#88DFB2",
|
"#FFD700", "#DAA520", "#808080", "#F0E68C", "#ADFF2F", "#00008B",
|
||||||
"#88C3BF",
|
"#008080", "#FF00FF", "#800080", "#FF6347", "#2E8B57", "#F4A460"
|
||||||
"#d9dcf3",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -24,17 +22,17 @@ watch(
|
|||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="AreaLegendBox">
|
<div class="AreaLegendBox">
|
||||||
<div class="AreaLegendBoxList" v-if="props.mapLegend && props.mapLegend.length > 0">
|
<div class="AreaLegendBoxList" v-if="props.mapLegend && props.mapLegend.length > 0">
|
||||||
<div class="AreaLegendBoxItem" :style="{ width: `calc(100% / ${props.mapLegend.length})` }"
|
<div class="AreaLegendBoxItem" :style="{ width: `calc(100% / ${Math.min(props.mapLegend.length, 5)})` }"
|
||||||
v-for="(item, index) in props.mapLegend" :key="index">
|
v-for="(item, index) in props.mapLegend" :key="index">
|
||||||
<div class="AreaLegendBoxItemIcon" :style="{ background: item.value }"></div>
|
<div class="AreaLegendBoxItemIcon" :style="{ background: colorList1[index % colorList1.length] }"></div>
|
||||||
<div class="AreaLegendBoxItemLabel">{{ item.label }}</div>
|
<div class="AreaLegendBoxItemLabel">{{ item.label }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,553 +1,376 @@
|
|||||||
<script setup lang="ts">
|
<template>
|
||||||
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
<view class="business-case">
|
||||||
import SmallTitle from '../smallTitle/smallTitle.vue'
|
<!-- 营收特征标题和Tab切换 -->
|
||||||
import RevenueYOYIcon from '../../../../assets/image/RevenueYOYIcon.png'
|
<view class="section-header">
|
||||||
import './BusinessCase.less'
|
<text class="section-title">营收特征</text>
|
||||||
import moment from 'moment';
|
<view class="tab-container">
|
||||||
import { handleCodeGetRevenueCompare, handleGetRevenueTrend } from '../../service';
|
<view v-for="(item, index) in tabList" :key="index"
|
||||||
import * as echarts from 'echarts/core';
|
:class="selectTab === item.value ? 'tab-item active-tab' : 'tab-item'"
|
||||||
import { BarChart, LineChart } from 'echarts/charts';
|
@click="handleChangeTab(item.value)">
|
||||||
import {
|
{{ item.label }}
|
||||||
GridComponent,
|
</view>
|
||||||
TitleComponent,
|
</view>
|
||||||
TooltipComponent,
|
</view>
|
||||||
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'
|
|
||||||
|
|
||||||
|
<!-- 营收特征分析图表 -->
|
||||||
|
<view class="chart-container">
|
||||||
|
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true"
|
||||||
|
canvasId="businessCaseChart" :animation="false" :ontap="true" :ontouch="true" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||||||
|
import request from "@/util/index.js";
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
// 注册组件
|
export default {
|
||||||
echarts.use([
|
components: {
|
||||||
LineChart,
|
QiunDataCharts
|
||||||
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 }
|
|
||||||
);
|
|
||||||
|
|
||||||
// 监听传入的选中服务区
|
data() {
|
||||||
watch(
|
return {
|
||||||
() => props.selectTab,
|
// Tab列表
|
||||||
(newVal, oldVal) => {
|
tabList: [
|
||||||
handleShowData(newVal)
|
{ label: "营收金额", value: 1 },
|
||||||
|
{ label: "客单量", value: 2 },
|
||||||
|
{ label: "客单均价", value: 3 }
|
||||||
|
],
|
||||||
|
selectTab: 1, // 当前选中的Tab
|
||||||
|
|
||||||
|
// 当前请求来的实际数据
|
||||||
|
realData: {},
|
||||||
|
|
||||||
|
// 图表原始数据
|
||||||
|
rawData: {
|
||||||
|
category: [],
|
||||||
|
seriesData: []
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(async () => {
|
computed: {
|
||||||
// 用tab可以修改的方法
|
// 图表数据
|
||||||
await handleGetData()
|
chartData() {
|
||||||
// await handleGetBottomData()
|
return {
|
||||||
})
|
categories: this.rawData.category,
|
||||||
|
series: this.rawData.seriesData
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 图表配置
|
||||||
|
chartOpts() {
|
||||||
|
return {
|
||||||
|
padding: [15, 15, 40, 15],
|
||||||
|
dataLabel: false,
|
||||||
|
enableScroll: true,
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
itemCount: 4,
|
||||||
|
scrollShow: true,
|
||||||
|
scrollAlign: 'left',
|
||||||
|
scrollColor: '#46B8F3',
|
||||||
|
scrollWidth: 4,
|
||||||
|
scrollHeight: 8,
|
||||||
|
margin: 15
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
data: [{
|
||||||
|
min: 0,
|
||||||
|
title: this.getYAxisTitle()
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// 切换tab的内容
|
onReady() {
|
||||||
const handleChangeTab = async (value: number) => {
|
this.handleGetBusinessCaseData()
|
||||||
selectTab.value = value
|
},
|
||||||
handleShowData(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拿到数据的方法
|
methods: {
|
||||||
const handleGetData = async () => {
|
// 获取营收特征数据
|
||||||
const req: any = {
|
async handleGetBusinessCaseData() {
|
||||||
ProvinceCode: "530000",
|
const req = {
|
||||||
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
ProvinceCode: "530000",
|
||||||
ServerpartId: props.currentService?.SERVERPART_ID || "",
|
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||||
}
|
ServerpartId: "", // 暂时为空,如果需要传入服务区ID可以在这里添加
|
||||||
|
}
|
||||||
|
|
||||||
let BusinessCase = sessionStorage.getItem('BusinessCase')
|
const data = await this.getRevenueCompare(req);
|
||||||
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)
|
// 处理数据
|
||||||
|
this.processChartData(data)
|
||||||
|
},
|
||||||
|
|
||||||
getAllData.value = data
|
// 发起API请求获取营收特征数据
|
||||||
|
async getRevenueCompare(params) {
|
||||||
|
const data = await request.$webGet(
|
||||||
|
"CommercialApi/Revenue/GetCodeRevenueCompare",
|
||||||
|
params
|
||||||
|
);
|
||||||
|
console.log('营收特征数据', data);
|
||||||
|
return data || {}
|
||||||
|
},
|
||||||
|
|
||||||
// 营收金额
|
// 处理图表数据
|
||||||
let category: any = ['product']
|
processChartData(data) {
|
||||||
let monthList: number[] = []
|
let monthList = []
|
||||||
let list = data.RevenueAmountList
|
|
||||||
if (list && list.length > 0) {
|
// 获取月份列表
|
||||||
list.forEach((item: any, index: number) => {
|
let list = data.RevenueAmountList
|
||||||
category.push(item.name)
|
if (list && list.length > 0) {
|
||||||
if (index === 0 && item.data && item.data.length > 0) {
|
list.forEach((item, index) => {
|
||||||
item.data.forEach((subItem: any) => {
|
if (index === 0 && item.data && item.data.length > 0) {
|
||||||
monthList.push(subItem[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)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取Y轴标题
|
||||||
|
getYAxisTitle() {
|
||||||
|
if (this.selectTab === 1) {
|
||||||
|
return '营收金额(万元)'
|
||||||
|
} else if (this.selectTab === 2) {
|
||||||
|
return '客单量(万笔)'
|
||||||
|
} else if (this.selectTab === 3) {
|
||||||
|
return '客单均价(元)'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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: 0,
|
|
||||||
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, 35, 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: '120', // 顶部间距
|
|
||||||
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: 10, // 距离容器底部距离
|
|
||||||
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: '80',
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
handleGetData
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</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;
|
||||||
|
|
||||||
<template>
|
.section-header {
|
||||||
<div class="BusinessCaseBox">
|
display: flex;
|
||||||
<div class="BusinessCaseBoxContent">
|
align-items: center;
|
||||||
<SmallTitle title="营收特征">
|
justify-content: space-between;
|
||||||
<!-- <template #extra>
|
margin-bottom: 20rpx;
|
||||||
<div class="BusinessCaseTabBox">
|
padding: 0 8rpx;
|
||||||
<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>
|
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: @text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
<!-- 营收同比 -->
|
.tab-container {
|
||||||
<div class="BusinessCaseRevenueYOY" v-if="false">
|
display: inline-flex;
|
||||||
<div class="BusinessCaseLeftItem">
|
align-items: center;
|
||||||
<img class="BusinessIcon" :src="RevenueYOYIcon" />
|
background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
</div>
|
padding: 6rpx 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
|
||||||
<div class="BusinessCaseRightItem">
|
.tab-item {
|
||||||
<div class="BusinessCaseRightItemTop">
|
font-size: 30rpx;
|
||||||
<div class="rightItemTitle">营收同比</div>
|
color: @text-secondary;
|
||||||
<div class="rightItemUpdate">{{ moment().subtract(1, 'd').format('YYYY-MM-DD') }}</div>
|
margin: 0 20rpx;
|
||||||
</div>
|
cursor: pointer;
|
||||||
<div class="BusinessCaseRightItemBottom">
|
transition: all 0.3s ease;
|
||||||
<div class="BusinessCaseItemBottomLeft">
|
position: relative;
|
||||||
<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">
|
&.active-tab {
|
||||||
<div class="BusinessCaseRevenueValue">{{ selectTab === 1 ?
|
color: @text-primary;
|
||||||
getAllData?.RevenueAmount.toLocaleString() :
|
font-weight: 600;
|
||||||
selectTab
|
|
||||||
=== 2 ?
|
|
||||||
getAllData?.TicketCount.toLocaleString() : selectTab === 3 ?
|
|
||||||
getAllData?.AvgTicketAmount.toLocaleString() : ''
|
|
||||||
}}</div>
|
|
||||||
<div class="BusinessCaseRevenueUnit">{{ selectTab === 2 ? '笔' : '元' }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div class="rightItemLeft">
|
&::after {
|
||||||
<div class="rightItemTitleBox">
|
content: "";
|
||||||
<div class="rightItemTitle">营收同比</div>
|
width: 100%;
|
||||||
<div class="rightItemUpdate">{{ moment().subtract(1, 'd').format('YYYY-MM-DD') }}</div>
|
height: 2rpx;
|
||||||
</div>
|
background: linear-gradient(180deg, #00F6FF 0%, #008CFF 100%);
|
||||||
<div class="rightItemBottom">
|
position: absolute;
|
||||||
<div class="compareTitle">相比去年同日</div>
|
left: 0;
|
||||||
<div class="changeBox">
|
bottom: -8rpx;
|
||||||
<img class="changeIcon" />
|
}
|
||||||
<div class="changeText"></div>
|
}
|
||||||
</div>
|
}
|
||||||
</div>
|
}
|
||||||
</div> -->
|
}
|
||||||
|
|
||||||
<!-- <div class="rightItemRight">
|
.chart-container {
|
||||||
<div class="BusinessCaseRevenueValue"></div>
|
background: @bg-white;
|
||||||
<div class="BusinessCaseRevenueUnit">元</div>
|
border-radius: @border-radius;
|
||||||
</div> -->
|
padding: 24rpx;
|
||||||
</div>
|
box-shadow: @shadow;
|
||||||
</div>
|
margin-bottom: 24rpx;
|
||||||
|
width: 100%;
|
||||||
<!-- 营收特征分析 -->
|
box-sizing: border-box;
|
||||||
<div class="featureAnalysis">
|
height: 400rpx;
|
||||||
<!-- <SmallTitle title="营收特征分析" /> -->
|
}
|
||||||
|
}
|
||||||
<div class="featureAnalysisBox" id="featureAnalysis"></div>
|
</style>
|
||||||
|
|
||||||
<!-- <SmallTitle title="营收同比分析" style="margin-top: 31px;" />
|
|
||||||
|
|
||||||
<div class="featureAnalysisBottom" id="featureAnalysisBottom"></div> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -12,12 +12,11 @@ import YNHighWayLine from '../../../../options/YNHighWayLine.js'
|
|||||||
const scene = ref<any>();
|
const scene = ref<any>();
|
||||||
// 配色方案一
|
// 配色方案一
|
||||||
let colorList1 = [
|
let colorList1 = [
|
||||||
"#4F83FA",
|
"#4F83FA", "#A39BFF", "#63B6FC", "#88DFB2", "#88C3BF", "#d9dcf3",
|
||||||
"#A39BFF",
|
"#FF7F50", "#87CEFA", "#8A2BE2", "#A52A2A", "#DEB887", "#5F9EA0",
|
||||||
"#63B6FC",
|
"#7FFF00", "#D2691E", "#FF69B4", "#CD5C5C", "#8B0000", "#006400",
|
||||||
"#88DFB2",
|
"#FFD700", "#DAA520", "#808080", "#F0E68C", "#ADFF2F", "#00008B",
|
||||||
"#88C3BF",
|
"#008080", "#FF00FF", "#800080", "#FF6347", "#2E8B57", "#F4A460"
|
||||||
"#d9dcf3",
|
|
||||||
];
|
];
|
||||||
// 所有服务区的数据
|
// 所有服务区的数据
|
||||||
let defaultServerPartList = reactive<any>([]);
|
let defaultServerPartList = reactive<any>([]);
|
||||||
|
|||||||
@ -26,7 +26,13 @@ echarts.use([
|
|||||||
|
|
||||||
let myChart: echarts.ECharts;
|
let myChart: echarts.ECharts;
|
||||||
// 自定义颜色列表
|
// 自定义颜色列表
|
||||||
const colorList = ['#FF307C', '#FF9500', '#FFD900', '#00FFB7', '#0094FF', '#7D4CD2'];
|
const colorList = [
|
||||||
|
"#4F83FA", "#A39BFF", "#63B6FC", "#88DFB2", "#88C3BF", "#d9dcf3",
|
||||||
|
"#FF7F50", "#87CEFA", "#8A2BE2", "#A52A2A", "#DEB887", "#5F9EA0",
|
||||||
|
"#7FFF00", "#D2691E", "#FF69B4", "#CD5C5C", "#8B0000", "#006400",
|
||||||
|
"#FFD700", "#DAA520", "#808080", "#F0E68C", "#ADFF2F", "#00008B",
|
||||||
|
"#008080", "#FF00FF", "#800080", "#FF6347", "#2E8B57", "#F4A460"
|
||||||
|
];
|
||||||
let allServiceId: string = '1143,1144,1186,1188,1189,1190,1191,1192,1193,979,999,1023,1029,1030,1031,1033,1037,1041,1078,1087,1095,1137,1141,1147,1157,1159,1164,1165,1170,1174,981,985,987,994,1007,1009,1010,1012,1016,971,996,1002,1017,1018,1022,1027,1032,1073,1076,1099,1118,1122,1140,1142,1150,1171,970,969,978,1001,1005,1015,1050,1051,1052,1053,1064,1066,1096,1097,1101,1103,1104,1105,1106,1109,1112,1114,1115,1116,1117,991,995,1039,1080,1094,1100,1107,1123,1127,1133,1154,1155,1161,1163,1179,1180,1019,1021,1048,1049,1056,1059,1062,1063,1069,1093,1067,1228,1008,1070,1072,1166,1113,1148,1153,986,1086,1075,1182,1068,1226,1218,1088,1090,1058,1044,1084,1077,1089,1081,1091,1083,1162,1036,1092,988,993,1111,1158,1194,1202,1198,1207,1216,1221,1203,1206,1209,1215,1227,1201,1205,1208,1214,1217,1229,1212,1065,1085,1055,1071,982,1168,1185,1110,977,1169,973,974,1011,1151,1121,1046,1045,1172,1146,976,1187,1156,1181,1136,1138,1211,983,1195,1131,1176,1167,1223,997,1252,1225,1043,1129,992,1149,975,1382,989,1047,1197,1025,1199,1183,1222,1178,1003,1013,1224,1139,1125,1173,1135,1038,1177,1060,1175,1184,1035,1026,1028,1079,1119,1120,1489'
|
let allServiceId: string = '1143,1144,1186,1188,1189,1190,1191,1192,1193,979,999,1023,1029,1030,1031,1033,1037,1041,1078,1087,1095,1137,1141,1147,1157,1159,1164,1165,1170,1174,981,985,987,994,1007,1009,1010,1012,1016,971,996,1002,1017,1018,1022,1027,1032,1073,1076,1099,1118,1122,1140,1142,1150,1171,970,969,978,1001,1005,1015,1050,1051,1052,1053,1064,1066,1096,1097,1101,1103,1104,1105,1106,1109,1112,1114,1115,1116,1117,991,995,1039,1080,1094,1100,1107,1123,1127,1133,1154,1155,1161,1163,1179,1180,1019,1021,1048,1049,1056,1059,1062,1063,1069,1093,1067,1228,1008,1070,1072,1166,1113,1148,1153,986,1086,1075,1182,1068,1226,1218,1088,1090,1058,1044,1084,1077,1089,1081,1091,1083,1162,1036,1092,988,993,1111,1158,1194,1202,1198,1207,1216,1221,1203,1206,1209,1215,1227,1201,1205,1208,1214,1217,1229,1212,1065,1085,1055,1071,982,1168,1185,1110,977,1169,973,974,1011,1151,1121,1046,1045,1172,1146,976,1187,1156,1181,1136,1138,1211,983,1195,1131,1176,1167,1223,997,1252,1225,1043,1129,992,1149,975,1382,989,1047,1197,1025,1199,1183,1222,1178,1003,1013,1224,1139,1125,1173,1135,1038,1177,1060,1175,1184,1035,1026,1028,1079,1119,1120,1489'
|
||||||
|
|
||||||
// 图例数据
|
// 图例数据
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user