update
@ -7,6 +7,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import './assets/css/fonts.less'
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|||||||
18
src/assets/css/fonts.less
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* 常规字体 */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'YouSheBiaoTiHei';
|
||||||
|
src: url('../font/YouSheBiaoTiHei-2.ttf') format('truetype');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
/* 避免文字渲染阻塞 */
|
||||||
|
}
|
||||||
|
|
||||||
|
// /* 粗体字体 */
|
||||||
|
// @font-face {
|
||||||
|
// font-family: 'YouSheBiaoTiHei';
|
||||||
|
// src: url('../font/YouSheBiaoTiHei-2.ttf') format('truetype');
|
||||||
|
// font-weight: 700;
|
||||||
|
// font-style: normal;
|
||||||
|
// font-display: swap;
|
||||||
|
// }
|
||||||
BIN
src/assets/font/YouSheBiaoTiHei-2.ttf
Normal file
BIN
src/assets/image/RevenueYOYIcon.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/image/allPageTopBg.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
src/assets/image/busyIcon.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/image/newBigTitleBg.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
src/assets/image/newPageTitle.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
src/assets/image/newSelectPageTop.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
src/assets/image/normalIcon.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/assets/image/serviceAreaBg.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,103 @@
|
|||||||
|
.AssessmentScoringBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.AssessmentScoringListBox {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
.AssessmentScoringItem {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px;
|
||||||
|
background: linear-gradient(30deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0.05) 100%);
|
||||||
|
|
||||||
|
.AssessmentScoringItemTop {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.AssessmentScoringItemTopIndex {
|
||||||
|
font-family: Impact, Impact;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #171B2D;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
padding: 2px 8px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AssessmentScoringItemTopName {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.AssessmentScoringItemBottom {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.AssessmentScoringPositionItem {
|
||||||
|
width: calc((100% - 10px) / 2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.AssessmentScoringPosition {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #018AEE;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
padding: 5px 6px;
|
||||||
|
background-color: rgba(0, 148, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AssessmentScoringProgress {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.AssessmentScoringMark {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AssessmentScoringALLProgress {
|
||||||
|
margin-top: 4px;
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
background-color: rgba(125, 76, 210, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.AssessmentScoringHave {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(125, 76, 210, 1);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SmallTitle from '../smallTitle/smallTitle.vue';
|
||||||
|
import './AssessmentScoring.less'
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="AssessmentScoringBox">
|
||||||
|
<SmallTitle title="考核打分排行榜" />
|
||||||
|
|
||||||
|
<div class="AssessmentScoringListBox">
|
||||||
|
<div class="AssessmentScoringItem">
|
||||||
|
<div class="AssessmentScoringItemTop">
|
||||||
|
<div class="AssessmentScoringItemTopIndex"></div>
|
||||||
|
<div class="AssessmentScoringItemTopName"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="AssessmentScoringItemBottom">
|
||||||
|
<div class="AssessmentScoringPositionItem">
|
||||||
|
<div class="AssessmentScoringPosition"></div>
|
||||||
|
|
||||||
|
<div class="AssessmentScoringProgress">
|
||||||
|
<div class="AssessmentScoringMark"></div>
|
||||||
|
<div class="AssessmentScoringALLProgress">
|
||||||
|
<div class="AssessmentScoringHave"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -1,5 +1,6 @@
|
|||||||
.BasicMessageBox {
|
.BasicMessageBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 25px;
|
||||||
|
|
||||||
.rightBox {
|
.rightBox {
|
||||||
// position: absolute;
|
// position: absolute;
|
||||||
@ -26,14 +27,15 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
.weatherIcon {
|
.weatherIcon {
|
||||||
width: 20px;
|
width: 18px;
|
||||||
height: 20px;
|
height: 18px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weatherText {
|
.weatherText {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 20px;
|
font-size: 19px;
|
||||||
|
line-height: 19px;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
156
src/page/index/components/BrandDetail/BrandDetail.less
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
.BrandDetailBox {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.brandTypeBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.brandChartBox {
|
||||||
|
width: 100%;
|
||||||
|
height: 132px;
|
||||||
|
margin-top: 35px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandList {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 42px;
|
||||||
|
|
||||||
|
.tabBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.tabItem {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #89929E;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
margin: 0 20px;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectTab {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectTab::after {
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(180deg, #00F6FF 0%, #008CFF 100%);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandListBox {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px 11px;
|
||||||
|
|
||||||
|
.brandItem {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background-color: #0F1625;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.brandLeft {
|
||||||
|
width: 66px;
|
||||||
|
height: 66px;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
.brandIcon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandRight {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
.brandRightTop {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.brandRightTopLeft {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandRightTopRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.brandRightTopRightIcon {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandRightTopRightValue {
|
||||||
|
font-family: Impact, Impact;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandRightTopRightUnit {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #626670;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brandRightBottom {
|
||||||
|
margin-top: 13px;
|
||||||
|
|
||||||
|
.brandRightBottomItem {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #0094FF;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 10px;
|
||||||
|
background-color: rgba(0, 148, 255, 0.3);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
240
src/page/index/components/BrandDetail/BrandDetail.vue
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SmallTitle from '../smallTitle/smallTitle.vue';
|
||||||
|
import './BrandDetail.less'
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { PieChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||||
|
import { handleGetBusinessTradeTree, handleGetCombineBrandList, handleGetFieldEnumTree } from '../../service';
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
echarts.use([
|
||||||
|
PieChart,
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
|
||||||
|
let myChart: echarts.ECharts;
|
||||||
|
// 自定义颜色列表
|
||||||
|
const colorList = ['#FF9500', '#0094FF', '#7D4CD2'];
|
||||||
|
// tab的数组
|
||||||
|
let tabList = ref<any>([
|
||||||
|
])
|
||||||
|
// 选择的tab
|
||||||
|
let selectTab = ref<number>(1)
|
||||||
|
// 品牌列表数据
|
||||||
|
let brandListData = ref<any>([])
|
||||||
|
|
||||||
|
// 传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
currentService?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 监听传入的选中服务区
|
||||||
|
watch(
|
||||||
|
() => props.currentService,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
handleGoMounted()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await handleGoMounted()
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleGoMounted = async () => {
|
||||||
|
const res: any = await handleGetData()
|
||||||
|
|
||||||
|
const chartDom = document.getElementById('brandChartBox');
|
||||||
|
if (!chartDom) return;
|
||||||
|
|
||||||
|
|
||||||
|
myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical', // 图例纵向排列
|
||||||
|
left: '50%', // 距离右侧5%
|
||||||
|
top: 'center', // 垂直居中
|
||||||
|
itemWidth: 12, // 图例标记宽度
|
||||||
|
itemHeight: 12, // 图例标记高度
|
||||||
|
textStyle: {
|
||||||
|
color: '#666', // 文字颜色
|
||||||
|
rich: {
|
||||||
|
// 可以在这里添加富文本样式
|
||||||
|
value: {
|
||||||
|
color: '#333',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
padding: [0, 0, 0, 5] // 文字间距
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 自定义图例内容
|
||||||
|
formatter: function (name: string) {
|
||||||
|
|
||||||
|
return `1111`
|
||||||
|
// // 找到对应的数据项
|
||||||
|
// const dataItem = res.pieData.find((item: any) => item.name === name);
|
||||||
|
// // 返回自定义格式
|
||||||
|
// return `{name|${name}} {value|${dataItem?.value}元}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// tooltip: { // 新增 tooltip 配置
|
||||||
|
// trigger: 'item', // 触发类型:坐标轴触发
|
||||||
|
// axisPointer: { // 坐标轴指示器配置
|
||||||
|
// type: 'shadow' // 阴影指示器(适合柱状图)
|
||||||
|
// },
|
||||||
|
// formatter: function (params: any) { // 自定义提示框内容
|
||||||
|
// return `
|
||||||
|
// <div style="font-weight:bold">${params.data.name} ${params?.percent}% ${res.realData[params.dataIndex].toLocaleString()}元</div>
|
||||||
|
// `;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['0%', '100%'],
|
||||||
|
center: ['25%', '50%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: function (params: any) {
|
||||||
|
return colorList[params.dataIndex];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
emphasis: false,
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: res.pieData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
myChart.resize();
|
||||||
|
window.addEventListener('resize', resizeChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拿到数据
|
||||||
|
const handleGetData = async () => {
|
||||||
|
// 拿到枚举数据
|
||||||
|
const enumData: any = await handleGetFieldEnumTree({
|
||||||
|
FieldExplainField: "BRAND_TYPE",
|
||||||
|
sessionName: "BRAND_TYPE"
|
||||||
|
})
|
||||||
|
console.log('enumDataenumDataenumDataenumData', enumData);
|
||||||
|
|
||||||
|
|
||||||
|
let category: any = ["全国品牌", "地方连锁", "本地个体"]
|
||||||
|
let pieData: any = [
|
||||||
|
{ name: "全国品牌", value: 33.3 },
|
||||||
|
{ name: "地方连锁", value: 33.3 },
|
||||||
|
{ name: "本地个体", value: 33.3 }
|
||||||
|
]
|
||||||
|
let realData: any = []
|
||||||
|
|
||||||
|
|
||||||
|
const req: any = {
|
||||||
|
ProvinceCode: "530000"
|
||||||
|
}
|
||||||
|
const data = await handleGetBusinessTradeTree(req)
|
||||||
|
|
||||||
|
const listData = await handleGetCombineBrandList({
|
||||||
|
PROVINCE_CODE: "530000",
|
||||||
|
BRAND_STATE: 1,
|
||||||
|
SERVERPART_IDS: props.currentService?.SERVERPART_ID || ""
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('dksjaihudvbujscjsalda', data);
|
||||||
|
console.log('listDatalistDatalistData', listData);
|
||||||
|
|
||||||
|
|
||||||
|
let res: any = {
|
||||||
|
category: category,// x轴的内容
|
||||||
|
pieData: pieData,// y轴的数据
|
||||||
|
realData: realData// 真实数据
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换tab
|
||||||
|
const handleChangeTab = (value: number) => {
|
||||||
|
selectTab.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const resizeChart = () => {
|
||||||
|
myChart?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', resizeChart);
|
||||||
|
myChart?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="BrandDetailBox">
|
||||||
|
<div class="brandTypeBox">
|
||||||
|
<SmallTitle title="商户类别比例图" />
|
||||||
|
|
||||||
|
<div class="brandChartBox" id="brandChartBox">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="brandList">
|
||||||
|
<SmallTitle>
|
||||||
|
<template #extra>
|
||||||
|
<div class="tabBox">
|
||||||
|
<div :class="selectTab === item.value ? 'tabItem selectTab' : 'tabItem'"
|
||||||
|
v-for="(item, index) in tabList" :key="index" @click="handleChangeTab(item.value)">
|
||||||
|
{{ item.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="brandListBox">
|
||||||
|
<div class="brandItem" v-for="(item, index) in brandListData" :key="index">
|
||||||
|
<div class="brandLeft">
|
||||||
|
<img class="brandIcon" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="brandRight">
|
||||||
|
<div class="brandRightTop">
|
||||||
|
<div class="brandRightTopLeft"></div>
|
||||||
|
<div class="brandRightTopRight">
|
||||||
|
<img class="brandRightTopRightIcon" />
|
||||||
|
<div class="brandRightTopRightValue"></div>
|
||||||
|
<div class="brandRightTopRightUnit"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="brandRightBottom">
|
||||||
|
<div class="brandRightBottomItem"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</SmallTitle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
159
src/page/index/components/BusinessCase/BusinessCase.less
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
.BusinessCaseBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.BusinessCaseTabBox {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.BusinessCaseItem {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #87919C;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
margin: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectBusinessCaseItem {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.selectBusinessCaseItem::after {
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(180deg, #00F6FF 0%, #008CFF 100%);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.BusinessCaseRevenueYOY {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 26px;
|
||||||
|
background: linear-gradient(30deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
|
||||||
|
.BusinessCaseLeftItem {
|
||||||
|
width: 53px;
|
||||||
|
height: 53px;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
.BusinessIcon {
|
||||||
|
width: 53px;
|
||||||
|
height: 53px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.BusinessCaseRightItem {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.rightItemLeft {
|
||||||
|
.rightItemTitle {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightItemBottom {
|
||||||
|
margin-top: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.compareTitle {
|
||||||
|
font-family: Inter, Inter;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #78828E;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changeBox {
|
||||||
|
margin-left: 5px;
|
||||||
|
|
||||||
|
.changeIcon {
|
||||||
|
width: 6px;
|
||||||
|
height: 8px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changeText {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #00FF00;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.rightItemRight {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.BusinessCaseRevenueValue {
|
||||||
|
font-family: Impact, Impact;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BusinessCaseRevenueUnit {
|
||||||
|
font-family: Inter, Inter;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #788390;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.featureAnalysis {
|
||||||
|
width: 100%;
|
||||||
|
height: 283px;
|
||||||
|
|
||||||
|
.featureAnalysisBox {
|
||||||
|
width: 100%;
|
||||||
|
height: 283px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.featureAnalysisBottom {
|
||||||
|
width: 100%;
|
||||||
|
height: 283px;
|
||||||
|
margin-top: 23px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
432
src/page/index/components/BusinessCase/BusinessCase.vue
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
<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';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
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>()
|
||||||
|
|
||||||
|
// 传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
currentService?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 监听传入的选中服务区
|
||||||
|
watch(
|
||||||
|
() => props.currentService,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
handleGetData()
|
||||||
|
handleGetBottomData()
|
||||||
|
},
|
||||||
|
{ 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: "340000",
|
||||||
|
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||||
|
ServerpartId: props.currentService?.SERVERPART_ID || "",
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await handleCodeGetRevenueCompare(req)
|
||||||
|
console.log('djsakjdaskldjasoifioad', 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 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(newData[item - 1][1])
|
||||||
|
})
|
||||||
|
res.push(list)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客单量
|
||||||
|
let res2: 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(newData[item - 1][1])
|
||||||
|
})
|
||||||
|
res2.push(list)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 均价
|
||||||
|
let res3: 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])
|
||||||
|
})
|
||||||
|
res3.push(list)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let obj: any = {
|
||||||
|
1: [category, ...res],
|
||||||
|
2: [category, ...res2],
|
||||||
|
3: [category, ...res3],
|
||||||
|
}
|
||||||
|
console.log('dhsauhdasjhdak', obj);
|
||||||
|
realData.value = obj
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
console.log('datadatadatadata', data);
|
||||||
|
console.log('yesDatayesDatayesDatayesData', yesData);
|
||||||
|
|
||||||
|
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(item.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yesData && yesData.length > 0) {
|
||||||
|
yesData.forEach((item: any) => {
|
||||||
|
lastYear.push(item.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 10,
|
||||||
|
right: 10,
|
||||||
|
textStyle: {
|
||||||
|
color: '#ffffff' // 设置图例文字为白色
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: { trigger: 'axis' },
|
||||||
|
dataset: { source: data },
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false // 隐藏刻度小线条
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLabel: {
|
||||||
|
width: 40,
|
||||||
|
overflow: 'truncate',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false // 隐藏刻度小线条
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '万元',
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '10', // 增加左侧空间
|
||||||
|
right: '10', // 增加右侧空间
|
||||||
|
bottom: '10',
|
||||||
|
top: '10',
|
||||||
|
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) {
|
||||||
|
console.log('paramsparamsparams', params);
|
||||||
|
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>
|
||||||
|
<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">
|
||||||
|
<div class="BusinessCaseLeftItem">
|
||||||
|
<img class="BusinessIcon" :src="RevenueYOYIcon" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="BusinessCaseRightItem">
|
||||||
|
<div class="rightItemLeft">
|
||||||
|
<div class="rightItemTitle">营收同比</div>
|
||||||
|
<div class="rightItemBottom">
|
||||||
|
<div class="compareTitle">相比去年同日</div>
|
||||||
|
<div class="changeBox">
|
||||||
|
<img class="changeIcon" />
|
||||||
|
<!-- >0 #00FF00 <0 #FF0000 -->
|
||||||
|
<div class="changeText"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rightItemRight">
|
||||||
|
<div class="BusinessCaseRevenueValue">3,329,828.91</div>
|
||||||
|
<div class="BusinessCaseRevenueUnit">元</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 营收特征分析 -->
|
||||||
|
<div class="featureAnalysis">
|
||||||
|
<SmallTitle title="营收特征分析" style="margin-top: 20px;" />
|
||||||
|
|
||||||
|
<div class="featureAnalysisBox" id="featureAnalysis"></div>
|
||||||
|
|
||||||
|
<SmallTitle title="营收同比分析" style="margin-top: 20px;" />
|
||||||
|
|
||||||
|
<div class="featureAnalysisBottom" id="featureAnalysisBottom"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -4,7 +4,7 @@
|
|||||||
.busninessBox {
|
.busninessBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 106px;
|
height: 106px;
|
||||||
background-image: url('../../../../assets/image/businessCenterBg.png');
|
// background-image: url('../../../../assets/image/businessCenterBg.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -93,7 +93,7 @@
|
|||||||
.busninessItemValue {
|
.busninessItemValue {
|
||||||
font-family: Impact, Impact;
|
font-family: Impact, Impact;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -115,4 +115,63 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.newCoreBusinessBox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.newCoreBusinessItem {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 3px 55px;
|
||||||
|
|
||||||
|
.newCoreBusinessItemLabel {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #C1ECF7;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newCoreBusinessItemValue {
|
||||||
|
font-family: Bahnschrift, Bahnschrift;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #48A9F6;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newCoreBusinessItemCompare {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.newCoreBusinessItemText {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 9px;
|
||||||
|
color: #C1ECF7;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newCoreBusinessItemAddIcon {
|
||||||
|
width: 6px;
|
||||||
|
height: 8px;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newCoreBusinessItemAddValue {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #00FF00;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -141,8 +141,72 @@ const handleGetPonitFixed = (str: string) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="CoreBusinessDataBox">
|
<div class="CoreBusinessDataBox">
|
||||||
<CenterTitle :pageTitle="'核心经营数据'" v-if="!props.noTitle" />
|
|
||||||
<div class="busninessBox">
|
<div class="newCoreBusinessBox">
|
||||||
|
<div class="newCoreBusinessItem">
|
||||||
|
<div class="newCoreBusinessItemLabel">营收/{{ revenueAmonut.unit }}</div>
|
||||||
|
<div class="newCoreBusinessItemValue">{{ revenueAmonut.value }}</div>
|
||||||
|
<!-- <div class="newCoreBusinessItemCompare">
|
||||||
|
<div class="newCoreBusinessItemText"></div>
|
||||||
|
<img class="newCoreBusinessItemAddIcon" />
|
||||||
|
<div class="newCoreBusinessItemAddValue"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="newCoreBusinessItem">
|
||||||
|
<div class="newCoreBusinessItemLabel">油品消耗/{{ oilConsumption.unit }}</div>
|
||||||
|
<div class="newCoreBusinessItemValue">{{ oilConsumption.value }}</div>
|
||||||
|
<!-- <div class="newCoreBusinessItemCompare">
|
||||||
|
<div class="newCoreBusinessItemText"></div>
|
||||||
|
<img class="newCoreBusinessItemAddIcon" />
|
||||||
|
<div class="newCoreBusinessItemAddValue"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="newCoreBusinessItem">
|
||||||
|
<div class="newCoreBusinessItemLabel">加水量/{{ waterAddition.unit }}</div>
|
||||||
|
<div class="newCoreBusinessItemValue">{{ waterAddition.value }}</div>
|
||||||
|
<!-- <div class="newCoreBusinessItemCompare">
|
||||||
|
<div class="newCoreBusinessItemText"></div>
|
||||||
|
<img class="newCoreBusinessItemAddIcon" />
|
||||||
|
<div class="newCoreBusinessItemAddValue"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="newCoreBusinessItem">
|
||||||
|
<div class="newCoreBusinessItemLabel">尿素/{{ urea.unit }}</div>
|
||||||
|
<div class="newCoreBusinessItemValue">{{ urea.value }}</div>
|
||||||
|
<!-- <div class="newCoreBusinessItemCompare">
|
||||||
|
<div class="newCoreBusinessItemText"></div>
|
||||||
|
<img class="newCoreBusinessItemAddIcon" />
|
||||||
|
<div class="newCoreBusinessItemAddValue"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="newCoreBusinessItem">
|
||||||
|
<div class="newCoreBusinessItemLabel">充电次数/{{ chargingCycles.unit }}</div>
|
||||||
|
<div class="newCoreBusinessItemValue">{{ chargingCycles.value }}</div>
|
||||||
|
<!-- <div class="newCoreBusinessItemCompare">
|
||||||
|
<div class="newCoreBusinessItemText"></div>
|
||||||
|
<img class="newCoreBusinessItemAddIcon" />
|
||||||
|
<div class="newCoreBusinessItemAddValue"></div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <CenterTitle :pageTitle="'核心经营数据'" v-if="!props.noTitle" /> -->
|
||||||
|
<div class="busninessBox" v-if="false">
|
||||||
<!-- 营收 -->
|
<!-- 营收 -->
|
||||||
<div class="busninessItem">
|
<div class="busninessItem">
|
||||||
<div class="busninessItemLeft">
|
<div class="busninessItemLeft">
|
||||||
@ -168,9 +232,6 @@ const handleGetPonitFixed = (str: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 油品消耗 -->
|
<!-- 油品消耗 -->
|
||||||
<div class="busninessItem">
|
<div class="busninessItem">
|
||||||
<div class="busninessItemLeft">
|
<div class="busninessItemLeft">
|
||||||
@ -222,9 +283,6 @@ const handleGetPonitFixed = (str: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 尿素 -->
|
<!-- 尿素 -->
|
||||||
<div class="busninessItem">
|
<div class="busninessItem">
|
||||||
<div class="busninessItemLeft">
|
<div class="busninessItemLeft">
|
||||||
@ -250,7 +308,6 @@ const handleGetPonitFixed = (str: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- 充电次数 -->
|
<!-- 充电次数 -->
|
||||||
<div class="busninessItem">
|
<div class="busninessItem">
|
||||||
<div class="busninessItemLeft">
|
<div class="busninessItemLeft">
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
.CustomerConsumptionPreferencesBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.CustomerConsumptionPreferencesContent {
|
||||||
|
margin-top: 25px;
|
||||||
|
width: 100%;
|
||||||
|
height: 212px;
|
||||||
|
|
||||||
|
.CustomerConsumptionPreferencesCharts {
|
||||||
|
width: 100%;
|
||||||
|
height: 212px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,200 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SmallTitle from '../smallTitle/smallTitle.vue';
|
||||||
|
import './CustomerConsumptionPreferences.less'
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { BarChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import { onBeforeUnmount, onMounted, watch } from 'vue';
|
||||||
|
import { handleGetCustomerSaleRatio } from '../../service';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
echarts.use([
|
||||||
|
BarChart,
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
|
||||||
|
let myChart: echarts.ECharts;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
|
||||||
|
await handleGoMounted()
|
||||||
|
});
|
||||||
|
|
||||||
|
// 传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
currentService?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 监听传入的选中服务区
|
||||||
|
watch(
|
||||||
|
() => props.currentService,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
handleGoMounted()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 初始运行的方法
|
||||||
|
const handleGoMounted = async () => {
|
||||||
|
const res = await handleGetData()
|
||||||
|
|
||||||
|
const chartDom = document.getElementById('CustomerConsumptionPreferencesCharts');
|
||||||
|
if (!chartDom) return;
|
||||||
|
|
||||||
|
myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: res.category,
|
||||||
|
axisLabel: {
|
||||||
|
width: 40, // 限制标签宽度为60px
|
||||||
|
overflow: 'truncate', // 超出部分显示为省略号
|
||||||
|
ellipsis: '...', // 自定义省略符号(可选)
|
||||||
|
interval: 0 // 强制显示所有标签
|
||||||
|
// rotate: 30, // 标签旋转30度(防止重叠)
|
||||||
|
},
|
||||||
|
// data: res.category
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: "万辆",
|
||||||
|
splitLine: { show: false } // 隐藏刻度线
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
// data: [120, 200, 150, 80, 70, 110, 130],
|
||||||
|
data: res.seriesData,
|
||||||
|
realData: res.realData,
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '6',
|
||||||
|
showBackground: true,
|
||||||
|
smooth: true,
|
||||||
|
backgroundStyle: {
|
||||||
|
borderRadius: [4, 4, 0, 0],
|
||||||
|
color: 'rgba(23, 42, 70, 1)'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: [4, 4, 0, 0],
|
||||||
|
// 动态返回渐变颜色
|
||||||
|
color: function (params: any) {
|
||||||
|
const index = params.dataIndex; // 当前数据的索引
|
||||||
|
// 前3条(Mon, Tue, Wed)使用渐变1
|
||||||
|
if (index < 3) {
|
||||||
|
return new echarts.graphic.LinearGradient(
|
||||||
|
0, 0, 0, 1, // 渐变方向(垂直)
|
||||||
|
[
|
||||||
|
{ offset: 0, color: '#FF4F00' }, // 渐变起始色
|
||||||
|
{ offset: 1, color: '#D3B70E' } // 渐变结束色
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 后3条(Thu, Fri, Sat)使用渐变2
|
||||||
|
else {
|
||||||
|
return new echarts.graphic.LinearGradient(
|
||||||
|
0, 0, 0, 1,
|
||||||
|
[
|
||||||
|
{ offset: 0, color: '#018FFF' }, // 渐变起始色
|
||||||
|
{ offset: 1, color: '#00F4FF' } // 渐变结束色
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
grid: {
|
||||||
|
left: '0', // 左侧间距
|
||||||
|
right: '0', // 右侧间距
|
||||||
|
bottom: '0', // 底部间距
|
||||||
|
top: '10', // 顶部间距
|
||||||
|
containLabel: true // 确保坐标轴标签在grid内
|
||||||
|
},
|
||||||
|
tooltip: { // 新增 tooltip 配置
|
||||||
|
trigger: 'axis', // 触发类型:坐标轴触发
|
||||||
|
axisPointer: { // 坐标轴指示器配置
|
||||||
|
type: 'shadow' // 阴影指示器(适合柱状图)
|
||||||
|
},
|
||||||
|
formatter: function (params: any) { // 自定义提示框内容
|
||||||
|
// params 是数组,包含当前 hover 的所有系列数据
|
||||||
|
const data = params[0];
|
||||||
|
let realData = res.realData[params[0].dataIndex]
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div style="font-weight:bold">${data.name}</div>
|
||||||
|
<div>车流量:${realData ? realData + '%' : data.value + '%'} </div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
window.addEventListener('resize', resizeChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGetData = async () => {
|
||||||
|
const req: any = {
|
||||||
|
statisticsType: 1,
|
||||||
|
startMonth: moment().subtract(1, 'd').startOf('y').format('YYYYMM'),
|
||||||
|
endMonth: moment().subtract(1, 'm').format('YYYYMM'),
|
||||||
|
provinceCode: '530000',
|
||||||
|
serverpartId: props.currentService?.SERVERPART_ID || "",
|
||||||
|
sortStr: 'TOTAL_COUNT desc'
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await handleGetCustomerSaleRatio(req)
|
||||||
|
|
||||||
|
|
||||||
|
let category: string[] = []
|
||||||
|
let seriesData: number[] = []
|
||||||
|
let realData: string[] = []
|
||||||
|
|
||||||
|
|
||||||
|
if (data.CustomerSaleList && data.CustomerSaleList.length > 0) {
|
||||||
|
let list = data.CustomerSaleList.slice(0, 10)
|
||||||
|
list.forEach((item: any) => {
|
||||||
|
category.push(item.BusinessTradeName)
|
||||||
|
seriesData.push(item.TotalRatio)
|
||||||
|
realData.push(item.TotalRatio)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
category: category,
|
||||||
|
seriesData: seriesData,
|
||||||
|
realData: realData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeChart = () => {
|
||||||
|
myChart?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', resizeChart);
|
||||||
|
myChart?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="CustomerConsumptionPreferencesBox">
|
||||||
|
<SmallTitle title="客群消费偏好" />
|
||||||
|
|
||||||
|
<div class="CustomerConsumptionPreferencesContent">
|
||||||
|
<div class="CustomerConsumptionPreferencesCharts" id="CustomerConsumptionPreferencesCharts"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
.CustomerGroupBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.CustomerGroupBoxContent{
|
||||||
|
width: 100%;
|
||||||
|
height: 173px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
200
src/page/index/components/CustomerGroup/CustomerGroup.vue
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SmallTitle from '../smallTitle/smallTitle.vue'
|
||||||
|
import './CustomerGroup.less'
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { ScatterChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DatasetComponent, // 必须添加!否则 dataset 功能无效
|
||||||
|
TransformComponent // 如果使用 dataset.source 需要此组件
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import { onBeforeUnmount, onMounted, watch } from 'vue';
|
||||||
|
import { handleGetCustomerGroupRatio } from '../../service';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
echarts.use([
|
||||||
|
ScatterChart,
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DatasetComponent, // 必须注册
|
||||||
|
TransformComponent, // 必须注册
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
let myChart: echarts.ECharts;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await handleShowCharts()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
currentService?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 监听传入的选中服务区
|
||||||
|
watch(
|
||||||
|
() => props.currentService,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
handleShowCharts()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleShowCharts = async () => {
|
||||||
|
const res = await handleGetData()
|
||||||
|
console.log('handleShowChartshandleShowChartshandleShowChartshandleShowCharts', res);
|
||||||
|
const chartDom = document.getElementById('CustomerGroupBoxContent');
|
||||||
|
if (!chartDom) return;
|
||||||
|
|
||||||
|
myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
grid: {
|
||||||
|
left: '0',
|
||||||
|
right: '10',
|
||||||
|
bottom: '0',
|
||||||
|
top: '10',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '年龄',
|
||||||
|
nameLocation: 'middle',
|
||||||
|
nameGap: 25,
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}岁'
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false // 隐藏刻度线
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false // 隐藏轴线
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false // 确保网格线隐藏
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
name: '交易金额',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false // 隐藏刻度线
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false // 隐藏轴线
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false // 确保网格线隐藏
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: '用户交易',
|
||||||
|
type: 'scatter',
|
||||||
|
symbolSize: function (data) {
|
||||||
|
return Math.sqrt(data[2]) * 5; // 气泡大小与占比相关
|
||||||
|
},
|
||||||
|
data: res,
|
||||||
|
itemStyle: {
|
||||||
|
color: function (params) {
|
||||||
|
// 按性别区分颜色
|
||||||
|
const gender = params.data[3]; // 第四项是性别
|
||||||
|
return gender === '男性' ? '#0094FF' : '#FF307C'; // 男性蓝色,女性红色
|
||||||
|
},
|
||||||
|
opacity: 0.8,
|
||||||
|
// borderColor: '#fff',
|
||||||
|
// borderWidth: 1
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
// 添加图例说明颜色对应的性别
|
||||||
|
legend: {
|
||||||
|
data: ['男性', '女性'],
|
||||||
|
itemGap: 20,
|
||||||
|
textStyle: {
|
||||||
|
color: '#333'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 提示框格式化
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: function (params) {
|
||||||
|
const data = params.data;
|
||||||
|
return `
|
||||||
|
年龄: ${data[0]}岁<br>
|
||||||
|
性别: ${data[3]}<br>
|
||||||
|
交易金额: ${data[1]}元<br>
|
||||||
|
占比: ${data[2]}%
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
window.addEventListener('resize', resizeChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGetData = async () => {
|
||||||
|
const req: any = {
|
||||||
|
provinceCode: "530000",
|
||||||
|
statisticsMonth: moment().subtract(1, 'M').format('YYYYMM'),
|
||||||
|
serverpartId: props.currentService?.SERVERPART_ID || "",
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await handleGetCustomerGroupRatio(req)
|
||||||
|
console.log('jfdjsfklasjflsd', data);
|
||||||
|
|
||||||
|
let res: any = []
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
data.forEach((item: any) => {
|
||||||
|
// let list: any = []
|
||||||
|
if (item.data && item.data.length > 0) {
|
||||||
|
item.data.forEach((subItem: any) => {
|
||||||
|
subItem.push(item.name)
|
||||||
|
res.push(subItem)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// res.push(list)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeChart = () => {
|
||||||
|
myChart?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', resizeChart);
|
||||||
|
myChart?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="CustomerGroupBox">
|
||||||
|
<SmallTitle title="客群特征分析" />
|
||||||
|
|
||||||
|
<div class="CustomerGroupBoxContent" id="CustomerGroupBoxContent">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -5,9 +5,9 @@
|
|||||||
// padding: 35px 20px 40px; // 老的
|
// padding: 35px 20px 40px; // 老的
|
||||||
padding: 20px 10px 30px;
|
padding: 20px 10px 30px;
|
||||||
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
backdrop-filter: blur(10px);
|
// backdrop-filter: blur(10px);
|
||||||
/* 高斯模糊效果 */
|
/* 高斯模糊效果 */
|
||||||
-webkit-backdrop-filter: blur(10px);
|
// -webkit-backdrop-filter: blur(10px);
|
||||||
/* Safari 兼容 */
|
/* Safari 兼容 */
|
||||||
|
|
||||||
.FestivalRevenue {
|
.FestivalRevenue {
|
||||||
|
|||||||
@ -111,10 +111,11 @@ onMounted(async () => {
|
|||||||
|
|
||||||
const data = params[0];
|
const data = params[0];
|
||||||
return `
|
return `
|
||||||
<div style="font-weight:bold">${data.name}服务区</div>
|
<div style="font-weight:bold">${data.name}</div>
|
||||||
<div>销售量:${data.value + '笔'} </div>
|
<div>销售量:${data.value} </div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
// + '笔'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,89 @@
|
|||||||
.MerchantRatingRankingBox {
|
.MerchantRatingRankingBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.MerchantRatingRankingCharts {
|
// .MerchantRatingRankingCharts {
|
||||||
|
// width: 100%;
|
||||||
|
// height: 196px;
|
||||||
|
// margin-top: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
.MerchantRatingRankingList {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 196px;
|
|
||||||
margin-top: 10px;
|
.MerchantRatingRankingItem {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px;
|
||||||
|
background: linear-gradient(30deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0.05) 100%);
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemTop {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemTopLeft {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemTopLeftIndex {
|
||||||
|
font-family: Impact, Impact;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #171B2D;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 1px 8px 2px 4px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemTopLeftName {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemTopRight {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemBottom {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 12px;
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemBottomAllProgress {
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
background-color: rgba(125, 76, 210, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.MerchantRatingRankingItemBottomHaveProgress {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 3px;
|
||||||
|
background-color: rgba(125, 76, 210, 1);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SmallTitle from '../smallTitle/smallTitle.vue'
|
import SmallTitle from '../smallTitle/smallTitle.vue'
|
||||||
import { onMounted, onBeforeUnmount } from 'vue';
|
import { onMounted, onBeforeUnmount, ref } from 'vue';
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import { BarChart } from 'echarts/charts';
|
import { BarChart } from 'echarts/charts';
|
||||||
import {
|
import {
|
||||||
@ -26,7 +26,8 @@ echarts.use([
|
|||||||
|
|
||||||
let myChart: echarts.ECharts;
|
let myChart: echarts.ECharts;
|
||||||
|
|
||||||
|
// 排行列表
|
||||||
|
let rankList = ref<any>()
|
||||||
|
|
||||||
// 拿到传入的数据
|
// 拿到传入的数据
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -38,89 +39,89 @@ onMounted(async () => {
|
|||||||
const res = await handleGetData()
|
const res = await handleGetData()
|
||||||
|
|
||||||
|
|
||||||
const chartDom = document.getElementById('MerchantRatingRanking');
|
// const chartDom = document.getElementById('MerchantRatingRanking');
|
||||||
if (!chartDom) return;
|
// if (!chartDom) return;
|
||||||
|
|
||||||
myChart = echarts.init(chartDom);
|
// myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
const option = {
|
// const option = {
|
||||||
yAxis: { // 改为 yAxis 显示分类数据
|
// yAxis: { // 改为 yAxis 显示分类数据
|
||||||
type: 'category',
|
// type: 'category',
|
||||||
data: res.category,
|
// data: res.category,
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
width: 80,
|
// width: 80,
|
||||||
overflow: 'truncate',
|
// overflow: 'truncate',
|
||||||
ellipsis: '...',
|
// ellipsis: '...',
|
||||||
interval: 0
|
// interval: 0
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
xAxis: { // 改为 xAxis 显示数值
|
// xAxis: { // 改为 xAxis 显示数值
|
||||||
type: 'value',
|
// type: 'value',
|
||||||
name: "笔",
|
// name: "笔",
|
||||||
splitLine: { show: false }
|
// splitLine: { show: false }
|
||||||
},
|
// },
|
||||||
series: [
|
// series: [
|
||||||
{
|
// {
|
||||||
data: res.seriesData,
|
// data: res.seriesData,
|
||||||
realData: res.seriesData,
|
// realData: res.seriesData,
|
||||||
type: 'bar',
|
// type: 'bar',
|
||||||
barWidth: '6', // 现在是柱子的高度
|
// barWidth: '6', // 现在是柱子的高度
|
||||||
showBackground: true,
|
// showBackground: true,
|
||||||
backgroundStyle: {
|
// backgroundStyle: {
|
||||||
borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
// borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||||
color: 'rgba(23, 42, 70, 1)'
|
// color: 'rgba(23, 42, 70, 1)'
|
||||||
},
|
// },
|
||||||
itemStyle: {
|
// itemStyle: {
|
||||||
borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
// borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||||
color: function (params: any) {
|
// color: function (params: any) {
|
||||||
const index = params.dataIndex;
|
// const index = params.dataIndex;
|
||||||
if (index > 6) {
|
// if (index > 6) {
|
||||||
return new echarts.graphic.LinearGradient(
|
// return new echarts.graphic.LinearGradient(
|
||||||
0, 0, 1, 0, // 渐变方向改为水平
|
// 0, 0, 1, 0, // 渐变方向改为水平
|
||||||
[
|
// [
|
||||||
{ offset: 0, color: '#FF4F00' },
|
// { offset: 0, color: '#FF4F00' },
|
||||||
{ offset: 1, color: '#D3B70E' }
|
// { offset: 1, color: '#D3B70E' }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
|
|
||||||
return new echarts.graphic.LinearGradient(
|
// return new echarts.graphic.LinearGradient(
|
||||||
0, 0, 1, 0, // 渐变方向改为水平
|
// 0, 0, 1, 0, // 渐变方向改为水平
|
||||||
[
|
// [
|
||||||
{ offset: 0, color: '#018FFF' },
|
// { offset: 0, color: '#018FFF' },
|
||||||
{ offset: 1, color: '#00F4FF' }
|
// { offset: 1, color: '#00F4FF' }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
grid: {
|
// grid: {
|
||||||
left: '0', // 左侧留更多空间给y轴标签
|
// left: '0', // 左侧留更多空间给y轴标签
|
||||||
right: '10%',
|
// right: '10%',
|
||||||
bottom: '5%',
|
// bottom: '5%',
|
||||||
top: '0',
|
// top: '0',
|
||||||
containLabel: true
|
// containLabel: true
|
||||||
},
|
// },
|
||||||
tooltip: {
|
// tooltip: {
|
||||||
trigger: 'axis',
|
// trigger: 'axis',
|
||||||
axisPointer: { type: 'shadow' },
|
// axisPointer: { type: 'shadow' },
|
||||||
formatter: function (params: any) {
|
// formatter: function (params: any) {
|
||||||
|
|
||||||
const data = params[0];
|
// const data = params[0];
|
||||||
return `
|
// return `
|
||||||
<div style="font-weight:bold">${data.name}服务区</div>
|
// <div style="font-weight:bold">${data.name}服务区</div>
|
||||||
<div>销售量:${data.value + '笔'} </div>
|
// <div>销售量:${data.value + '笔'} </div>
|
||||||
`;
|
// `;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
myChart.setOption(option);
|
// myChart.setOption(option);
|
||||||
window.addEventListener('resize', resizeChart);
|
// window.addEventListener('resize', resizeChart);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 拿到热门商品榜单
|
// 拿到热门商品榜单
|
||||||
@ -143,21 +144,42 @@ const handleGetData = async () => {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizeChart = () => {
|
// const resizeChart = () => {
|
||||||
myChart?.resize();
|
// myChart?.resize();
|
||||||
};
|
// };
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
// onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', resizeChart);
|
// window.removeEventListener('resize', resizeChart);
|
||||||
myChart?.dispose();
|
// myChart?.dispose();
|
||||||
});
|
// });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="MerchantRatingRankingBox">
|
<div class="MerchantRatingRankingBox">
|
||||||
<SmallTitle :title="'商户评分排行榜'" />
|
<SmallTitle :title="'商户评分排行榜'" />
|
||||||
|
|
||||||
<div class="MerchantRatingRankingCharts" id="MerchantRatingRanking">
|
<!-- <div class="MerchantRatingRankingCharts" id="MerchantRatingRanking">
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="MerchantRatingRankingList">
|
||||||
|
<div class="MerchantRatingRankingItem" v-for="(item, index) in rankList" :key="index">
|
||||||
|
<div class="MerchantRatingRankingItemTop">
|
||||||
|
<div class="MerchantRatingRankingItemTopLeft">
|
||||||
|
<div class="MerchantRatingRankingItemTopLeftIndex"></div>
|
||||||
|
<div class="MerchantRatingRankingItemTopLeftName"></div>
|
||||||
|
</div>
|
||||||
|
<div class="MerchantRatingRankingItemTopRight">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="MerchantRatingRankingItemBottom">
|
||||||
|
<div class="MerchantRatingRankingItemBottomAllProgress">
|
||||||
|
<div class="MerchantRatingRankingItemBottomHaveProgress"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -0,0 +1,160 @@
|
|||||||
|
.OverviewOfServiceAreaBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContent {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 11px 0;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentTop {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentTopItem {
|
||||||
|
width: calc((100% - 20px) / 2);
|
||||||
|
min-height: 56px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
background-image: url(../../../../assets/image/serviceAreaBg.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentTopItemLabel {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentTopItemvalue {
|
||||||
|
font-family: Bahnschrift, Bahnschrift;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #56BCE6;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentBottom {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentBottomItem {
|
||||||
|
width: calc((100% - 20px) / 3);
|
||||||
|
min-height: 50px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-image: url(../../../../assets/image/serviceAreaBg.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
border: 1px solid rgba(78, 173, 245, 0.3);
|
||||||
|
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentBottomItemLabel {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaContentBottomItemValue {
|
||||||
|
font-family: Bahnschrift, Bahnschrift;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContent {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 11px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItem {
|
||||||
|
width: calc((100% - 10px) / 2);
|
||||||
|
background: linear-gradient(0, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemLeft {
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemLeftImg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemRight {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemRightTitle {
|
||||||
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #FF5E5E;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemRightValueBox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemRightNumber {
|
||||||
|
font-family: Impact, Impact;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #D24343;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.OverviewOfServiceAreaBusyContentItemRightUnit {
|
||||||
|
font-family: Inter, Inter;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #808A96;
|
||||||
|
text-align: right;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import NewBigTitleBox from '../newBigTitleBox/newBigTitleBox.vue';
|
||||||
|
import './OverviewOfServiceArea.less'
|
||||||
|
import { handleGetCurBusyRank, handleGetServerpartList } from '../../service';
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await handleGetData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 服务区的详情数据
|
||||||
|
const serviceInfo = ref<any>()
|
||||||
|
// 繁忙度的信息
|
||||||
|
const businessInfo = ref<any>()
|
||||||
|
|
||||||
|
// 获取服务区数据
|
||||||
|
const handleGetData = async () => {
|
||||||
|
const req: any = {
|
||||||
|
Province_Code: "530000",
|
||||||
|
ShowService: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await handleGetServerpartList(req)
|
||||||
|
|
||||||
|
console.log('fhdushgsu9dgvuisdvgsudvhnjldsfas', data);
|
||||||
|
|
||||||
|
// 服务区总对数
|
||||||
|
let serviceAllTotal: number = 0
|
||||||
|
// 司机之家对数
|
||||||
|
let HASPILOTLOUNGETotal: number = 0
|
||||||
|
// 加油站对数
|
||||||
|
let REFUELINGGUNTotal: number = 0
|
||||||
|
// 充电桩个数
|
||||||
|
let ChargingStationTotal: number = 0
|
||||||
|
// 停车位个数
|
||||||
|
let ParkingSpaceTotal: number = 0
|
||||||
|
// 卫生间个数
|
||||||
|
let toiletTotal: number = 0
|
||||||
|
// 母婴室个数
|
||||||
|
let NursingRoomTotal: number = 0
|
||||||
|
// 尿素
|
||||||
|
let URECOUNTTotal: number = 0
|
||||||
|
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
data.forEach((item: any) => {
|
||||||
|
serviceAllTotal += 1
|
||||||
|
|
||||||
|
if (item.RegionInfo && item.RegionInfo.length > 0) {
|
||||||
|
item.RegionInfo.forEach((subItem: any) => {
|
||||||
|
if (subItem.HASPILOTLOUNGE > 0) {
|
||||||
|
HASPILOTLOUNGETotal += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subItem.STATEGRIDCHARGE > 0 || subItem.LIAUTOCHARGE > 0 || subItem.GACENERGYCHARGE > 0 || subItem.OTHERCHARGE > 0) {
|
||||||
|
ChargingStationTotal += (subItem.STATEGRIDCHARGE || 0)
|
||||||
|
ChargingStationTotal += (subItem.LIAUTOCHARGE || 0)
|
||||||
|
ChargingStationTotal += (subItem.GACENERGYCHARGE || 0)
|
||||||
|
ChargingStationTotal += (subItem.OTHERCHARGE || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (subItem.REFUELINGGUN98 > 0 || subItem.REFUELINGGUN92 > 0 || subItem.REFUELINGGUN95 > 0 || subItem.REFUELINGGUN0 > 0) {
|
||||||
|
REFUELINGGUNTotal += (subItem.REFUELINGGUN98 || 0)
|
||||||
|
REFUELINGGUNTotal += (subItem.REFUELINGGUN92 || 0)
|
||||||
|
REFUELINGGUNTotal += (subItem.REFUELINGGUN95 || 0)
|
||||||
|
REFUELINGGUNTotal += (subItem.REFUELINGGUN0 || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subItem.SMALLPARKING > 0 || subItem.PACKING > 0 || subItem.TRUCKPACKING > 0 || subItem.LONGPACKING > 0 || subItem.DANPACKING > 0 || subItem.LIVESTOCKPACKING > 0) {
|
||||||
|
ParkingSpaceTotal += (subItem.SMALLPARKING || 0)
|
||||||
|
ParkingSpaceTotal += (subItem.PACKING || 0)
|
||||||
|
ParkingSpaceTotal += (subItem.TRUCKPACKING || 0)
|
||||||
|
ParkingSpaceTotal += (subItem.LONGPACKING || 0)
|
||||||
|
ParkingSpaceTotal += (subItem.DANPACKING || 0)
|
||||||
|
ParkingSpaceTotal += (subItem.LIVESTOCKPACKING || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subItem.TOILETCOUNT > 0 || subItem.HASWIFI > 0 || subItem.HASPANTRY > 0) {
|
||||||
|
toiletTotal += (subItem.TOILETCOUNT || 0)
|
||||||
|
toiletTotal += (subItem.HASWIFI || 0)
|
||||||
|
toiletTotal += (subItem.HASPANTRY || 0)
|
||||||
|
}
|
||||||
|
if (subItem.HASMOTHER) {
|
||||||
|
NursingRoomTotal += 1
|
||||||
|
}
|
||||||
|
if (subItem.UREA_COUNT > 0) {
|
||||||
|
URECOUNTTotal += (subItem.UREA_COUNT || 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let res: any = {
|
||||||
|
serviceAllTotal: serviceAllTotal,
|
||||||
|
HASPILOTLOUNGETotal: HASPILOTLOUNGETotal,
|
||||||
|
REFUELINGGUNTotal: REFUELINGGUNTotal,
|
||||||
|
ChargingStationTotal: ChargingStationTotal,
|
||||||
|
ParkingSpaceTotal: ParkingSpaceTotal,
|
||||||
|
toiletTotal: toiletTotal,
|
||||||
|
NursingRoomTotal: NursingRoomTotal,
|
||||||
|
URECOUNTTotal: URECOUNTTotal,
|
||||||
|
}
|
||||||
|
console.log('fdjsifjasjfs', res);
|
||||||
|
|
||||||
|
serviceInfo.value = res
|
||||||
|
|
||||||
|
|
||||||
|
// 繁忙度
|
||||||
|
const businessReq: any = {
|
||||||
|
// action_type: "getCurHalfCollect",
|
||||||
|
// province_code: 5564
|
||||||
|
ProvinceCode: '530000',
|
||||||
|
ServerpartId: "",
|
||||||
|
DataType: '1'
|
||||||
|
}
|
||||||
|
// const data = await handleGetCurHalfCollect(req)
|
||||||
|
const businessData = await handleGetCurBusyRank(businessReq)
|
||||||
|
console.log('服务区繁忙度数据:', businessData);
|
||||||
|
|
||||||
|
// 繁忙个数
|
||||||
|
let businessTotal: number = 0
|
||||||
|
// 正常个数
|
||||||
|
let noramlTotal: number = 0
|
||||||
|
if (businessData && businessData.length > 0) {
|
||||||
|
businessData.forEach((item: any) => {
|
||||||
|
if (item.TicketCount > 30) {
|
||||||
|
businessTotal += 1
|
||||||
|
} else {
|
||||||
|
noramlTotal += 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
businessInfo.value = {
|
||||||
|
businessTotal: businessTotal,
|
||||||
|
noramlTotal: noramlTotal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="OverviewOfServiceAreaBox">
|
||||||
|
<NewBigTitleBox title="服务区概况" />
|
||||||
|
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaContent">
|
||||||
|
<div class="OverviewOfServiceAreaContentTop">
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItemLabel">服务区总数/对</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItemvalue" style="color: #56BCE6;">{{
|
||||||
|
serviceInfo?.serviceAllTotal || "0" }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItemLabel">司机之家/对</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentTopItemvalue" style="color: #5ABE89;">{{
|
||||||
|
serviceInfo?.HASPILOTLOUNGETotal || "0" }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaContentBottom">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">加油站/对</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.REFUELINGGUNTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">充电桩/个</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.ChargingStationTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">停车位/个</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.ParkingSpaceTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">卫生间/个</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.toiletTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">母婴室/个</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.NursingRoomTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItem">
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemLabel">尿素/台</div>
|
||||||
|
<div class="OverviewOfServiceAreaContentBottomItemValue">{{ serviceInfo?.URECOUNTTotal || "0"
|
||||||
|
}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<NewBigTitleBox title="服务承载" style="margin-top: 23px;" />
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaBusyContent">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItem">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemLeft">
|
||||||
|
<img class="OverviewOfServiceAreaBusyContentItemLeftImg"
|
||||||
|
src="../../../../assets/image/busyIcon.png" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRight">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightTitle">繁忙</div>
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightValueBox">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightNumber">{{ businessInfo?.businessTotal }}
|
||||||
|
</div>
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightUnit">对</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItem">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemLeft">
|
||||||
|
<img class="OverviewOfServiceAreaBusyContentItemLeftImg"
|
||||||
|
src="../../../../assets/image/normalIcon.png" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRight">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightTitle" style="color: #fff;">空闲</div>
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightValueBox">
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightNumber" style="color: #fff;">
|
||||||
|
{{ businessInfo?.noramlTotal }}</div>
|
||||||
|
<div class="OverviewOfServiceAreaBusyContentItemRightUnit">对</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -15,5 +15,16 @@
|
|||||||
.amap-container {
|
.amap-container {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.l7-control-container {
|
||||||
|
.l7-bottom {
|
||||||
|
.l7-control-logo {
|
||||||
|
.l7-control-logo-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,6 +184,7 @@ const handleGetData = async () => {
|
|||||||
|
|
||||||
const data = await handleGetTransactionConvert(req)
|
const data = await handleGetTransactionConvert(req)
|
||||||
|
|
||||||
|
|
||||||
// 客单数据
|
// 客单数据
|
||||||
let customerOrder = data.TransactionList
|
let customerOrder = data.TransactionList
|
||||||
|
|
||||||
|
|||||||
@ -47,159 +47,159 @@ onMounted(async () => {
|
|||||||
|
|
||||||
handleGetOnlineData()
|
handleGetOnlineData()
|
||||||
|
|
||||||
const res: any = await handleGetData()
|
// const res: any = await handleGetData()
|
||||||
|
|
||||||
const chartDom = document.getElementById('TodayTrend');
|
// const chartDom = document.getElementById('TodayTrend');
|
||||||
if (!chartDom) return;
|
// if (!chartDom) return;
|
||||||
|
|
||||||
myChart = echarts.init(chartDom);
|
// myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
const option = {
|
// const option = {
|
||||||
xAxis: {
|
// xAxis: {
|
||||||
type: 'category',
|
// type: 'category',
|
||||||
data: res.category,
|
// data: res.category,
|
||||||
// boundaryGap: true,
|
// // boundaryGap: true,
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
interval: 3,
|
// interval: 3,
|
||||||
showMinLabel: true,
|
// showMinLabel: true,
|
||||||
showMaxLabel: true
|
// showMaxLabel: true
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
yAxis: [
|
// yAxis: [
|
||||||
{
|
// {
|
||||||
type: 'value',
|
// type: 'value',
|
||||||
name: '营收',
|
// name: '营收',
|
||||||
nameTextStyle: {
|
// nameTextStyle: {
|
||||||
color: '#00FFFF'
|
// color: '#00FFFF'
|
||||||
},
|
// },
|
||||||
splitLine: { show: false },
|
// splitLine: { show: false },
|
||||||
axisLine: {
|
// axisLine: {
|
||||||
show: true,
|
// show: true,
|
||||||
lineStyle: {
|
// lineStyle: {
|
||||||
color: '#00FFFF'
|
// color: '#00FFFF'
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
color: '#00FFFF',
|
// color: '#00FFFF',
|
||||||
formatter: '{value}'
|
// formatter: '{value}'
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: 'value',
|
// type: 'value',
|
||||||
name: '客单',
|
// name: '客单',
|
||||||
nameTextStyle: {
|
// nameTextStyle: {
|
||||||
color: '#FFA500'
|
// color: '#FFA500'
|
||||||
},
|
// },
|
||||||
splitLine: { show: false },
|
// splitLine: { show: false },
|
||||||
position: 'right',
|
// position: 'right',
|
||||||
axisLine: {
|
// axisLine: {
|
||||||
show: true,
|
// show: true,
|
||||||
lineStyle: {
|
// lineStyle: {
|
||||||
color: '#FFA500'
|
// color: '#FFA500'
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
color: '#FFA500',
|
// color: '#FFA500',
|
||||||
formatter: '{value}'
|
// formatter: '{value}'
|
||||||
},
|
// },
|
||||||
offset: 0
|
// offset: 0
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
grid: {
|
// grid: {
|
||||||
left: '10',
|
// left: '10',
|
||||||
right: '10',
|
// right: '10',
|
||||||
bottom: '10',
|
// bottom: '10',
|
||||||
top: '10',
|
// top: '10',
|
||||||
containLabel: true
|
// containLabel: true
|
||||||
},
|
// },
|
||||||
series: [
|
// series: [
|
||||||
{
|
// {
|
||||||
name: '营收',
|
// name: '营收',
|
||||||
data: res.seriesData.map((value: any, index: any) => ({
|
// data: res.seriesData.map((value: any, index: any) => ({
|
||||||
value: value,
|
// value: value,
|
||||||
symbol: index % 3 === 0 ? 'circle' : 'none',
|
// symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||||
symbolSize: 6
|
// symbolSize: 6
|
||||||
})),
|
// })),
|
||||||
type: 'line',
|
// type: 'line',
|
||||||
smooth: true,
|
// smooth: true,
|
||||||
lineStyle: {
|
// lineStyle: {
|
||||||
width: 2,
|
// width: 2,
|
||||||
color: '#00FFFF'
|
// color: '#00FFFF'
|
||||||
},
|
// },
|
||||||
itemStyle: {
|
// itemStyle: {
|
||||||
color: '#00FFFF'
|
// color: '#00FFFF'
|
||||||
},
|
// },
|
||||||
areaStyle: {
|
// areaStyle: {
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
{
|
// {
|
||||||
offset: 0,
|
// offset: 0,
|
||||||
color: 'rgba(0, 255, 255, 0.3)'
|
// color: 'rgba(0, 255, 255, 0.3)'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
offset: 1,
|
// offset: 1,
|
||||||
color: 'rgba(0, 255, 255, 0.1)'
|
// color: 'rgba(0, 255, 255, 0.1)'
|
||||||
}
|
// }
|
||||||
])
|
// ])
|
||||||
},
|
// },
|
||||||
yAxisIndex: 0
|
// yAxisIndex: 0
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: '客单',
|
// name: '客单',
|
||||||
data: res.seriesDataSecond.map((value: any, index: any) => ({
|
// data: res.seriesDataSecond.map((value: any, index: any) => ({
|
||||||
value: value,
|
// value: value,
|
||||||
symbol: index % 3 === 0 ? 'circle' : 'none',
|
// symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||||
symbolSize: 6
|
// symbolSize: 6
|
||||||
})),
|
// })),
|
||||||
type: 'line',
|
// type: 'line',
|
||||||
smooth: true,
|
// smooth: true,
|
||||||
lineStyle: {
|
// lineStyle: {
|
||||||
width: 2,
|
// width: 2,
|
||||||
color: '#FFA500'
|
// color: '#FFA500'
|
||||||
},
|
// },
|
||||||
itemStyle: {
|
// itemStyle: {
|
||||||
color: '#FFA500'
|
// color: '#FFA500'
|
||||||
},
|
// },
|
||||||
areaStyle: {
|
// areaStyle: {
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
{
|
// {
|
||||||
offset: 0,
|
// offset: 0,
|
||||||
color: 'rgba(255, 165, 0, 0.3)'
|
// color: 'rgba(255, 165, 0, 0.3)'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
offset: 1,
|
// offset: 1,
|
||||||
color: 'rgba(255, 165, 0, 0.1)'
|
// color: 'rgba(255, 165, 0, 0.1)'
|
||||||
}
|
// }
|
||||||
])
|
// ])
|
||||||
},
|
// },
|
||||||
yAxisIndex: 1
|
// yAxisIndex: 1
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
tooltip: {
|
// tooltip: {
|
||||||
trigger: 'axis',
|
// trigger: 'axis',
|
||||||
axisPointer: {
|
// axisPointer: {
|
||||||
type: 'line',
|
// type: 'line',
|
||||||
snap: true, // 关键点:启用吸附
|
// snap: true, // 关键点:启用吸附
|
||||||
lineStyle: {
|
// lineStyle: {
|
||||||
color: '#FFF', // 可选:调整竖线颜色
|
// color: '#FFF', // 可选:调整竖线颜色
|
||||||
width: 1
|
// width: 1
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
formatter: function (params: any) {
|
// formatter: function (params: any) {
|
||||||
let tip = `<div style="font-weight:bold">${params[0].name}</div>`;
|
// let tip = `<div style="font-weight:bold">${params[0].name}</div>`;
|
||||||
params.forEach((param: any) => {
|
// params.forEach((param: any) => {
|
||||||
const unit = param.seriesName === '营收' ? '元' : '单';
|
// const unit = param.seriesName === '营收' ? '元' : '单';
|
||||||
let value = param.seriesName === '营收' ? res.seriesData[param.dataIndex] : res.seriesDataSecond[param.dataIndex]
|
// let value = param.seriesName === '营收' ? res.seriesData[param.dataIndex] : res.seriesDataSecond[param.dataIndex]
|
||||||
tip += `<div>${param.seriesName}: ${value ? value.toLocaleString() : ''}${unit}</div>`;
|
// tip += `<div>${param.seriesName}: ${value ? value.toLocaleString() : ''}${unit}</div>`;
|
||||||
});
|
// });
|
||||||
|
|
||||||
return tip
|
// return tip
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
myChart.setOption(option);
|
// myChart.setOption(option);
|
||||||
myChart.resize();
|
// myChart.resize();
|
||||||
window.addEventListener('resize', resizeChart);
|
// window.addEventListener('resize', resizeChart);
|
||||||
})
|
})
|
||||||
|
|
||||||
// 修改选择的季月年
|
// 修改选择的季月年
|
||||||
@ -276,29 +276,29 @@ const handleGetOnlineData = async () => {
|
|||||||
onlineCashRegisterValue.value = handleGetFiveNumber(res.MACHINECOUNT)
|
onlineCashRegisterValue.value = handleGetFiveNumber(res.MACHINECOUNT)
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizeChart = () => {
|
// const resizeChart = () => {
|
||||||
myChart?.resize();
|
// myChart?.resize();
|
||||||
};
|
// };
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
// onBeforeUnmount(() => {
|
||||||
window.removeEventListener('resize', resizeChart);
|
// window.removeEventListener('resize', resizeChart);
|
||||||
myChart?.dispose();
|
// myChart?.dispose();
|
||||||
});
|
// });
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="TodayTrendBox">
|
<div class="TodayTrendBox">
|
||||||
<SmallTitle :title="'今日走势图'"></SmallTitle>
|
<!-- <SmallTitle :title="'今日走势图'"></SmallTitle> -->
|
||||||
|
|
||||||
<div class="TodayTrendUnit">
|
<!-- <div class="TodayTrendUnit">
|
||||||
<span>元</span>
|
<span>元</span>
|
||||||
<span>单</span>
|
<span>单</span>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="TodayTrendContent">
|
<!-- <div class="TodayTrendContent">
|
||||||
<div class="TodayTrend" id="TodayTrend"></div>
|
<div class="TodayTrend" id="TodayTrend"></div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<div class="onlineServiceBox">
|
<div class="onlineServiceBox">
|
||||||
<div class="onlineServiceItem">
|
<div class="onlineServiceItem">
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
.TrendOfTrafficFlowCharts {
|
.TrendOfTrafficFlowCharts {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 10px;
|
margin-top: 15px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.trafficFlowCarUnit {
|
.trafficFlowCarUnit {
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
.TrendOfTrafficFlow {
|
.TrendOfTrafficFlow {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 134px;
|
height: 133px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +84,8 @@ const handleGoMounted = async () => {
|
|||||||
smooth: true,
|
smooth: true,
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
borderRadius: [4, 4, 0, 0],
|
borderRadius: [4, 4, 0, 0],
|
||||||
color: 'rgba(23, 42, 70, 1)'
|
// color: 'rgba(23, 42, 70, 1)'
|
||||||
|
color: 'rgba(0, 148, 255, 0.1)'
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: [4, 4, 0, 0],
|
borderRadius: [4, 4, 0, 0],
|
||||||
@ -133,7 +134,7 @@ const handleGoMounted = async () => {
|
|||||||
let realData = res.realData[params[0].dataIndex]
|
let realData = res.realData[params[0].dataIndex]
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div style="font-weight:bold">${data.name}服务区</div>
|
<div style="font-weight:bold">${data.name}</div>
|
||||||
<div>车流量:${realData ? realData + '辆' : data.value + '万辆'} </div>
|
<div>车流量:${realData ? realData + '辆' : data.value + '万辆'} </div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -148,7 +149,8 @@ const handleGoMounted = async () => {
|
|||||||
// 拿到断面流量数据
|
// 拿到断面流量数据
|
||||||
const handleGetSectionFlowCount = async () => {
|
const handleGetSectionFlowCount = async () => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
StatisticsMonth: moment().subtract(1, 'M').format('YYYYMM'),
|
// StatisticsMonth: moment().subtract(1, 'M').format('YYYYMM'),
|
||||||
|
StatisticsMonth: "202504",
|
||||||
Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
||||||
SortStr: "SectionFlow_Count desc",
|
SortStr: "SectionFlow_Count desc",
|
||||||
ProvinceCode: "530000"
|
ProvinceCode: "530000"
|
||||||
@ -188,7 +190,7 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="TrendOfTrafficFlowBox">
|
<div class="TrendOfTrafficFlowBox">
|
||||||
<SmallTitle :title="'车流断面趋势'" />
|
<SmallTitle :title="`车流断面趋势(04月)`" />
|
||||||
|
|
||||||
<div class="TrendOfTrafficFlowCharts">
|
<div class="TrendOfTrafficFlowCharts">
|
||||||
<div class="trafficFlowCarUnit">辆</div>
|
<div class="trafficFlowCarUnit">辆</div>
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
.VehicleStayAnalysisBox {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.VehicleStayAnalysisContent {
|
||||||
|
margin-top: 18px;
|
||||||
|
width: 100%;
|
||||||
|
height: 174px;
|
||||||
|
|
||||||
|
.VehicleStayAnalysisCharts {
|
||||||
|
width: 100%;
|
||||||
|
height: 174px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,197 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SmallTitle from '../smallTitle/smallTitle.vue';
|
||||||
|
import './VehicleStayAnalysis.less'
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import { BarChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
import { onBeforeUnmount, onMounted, watch } from 'vue';
|
||||||
|
import { handleGetBayonetSTAList } from '../../service';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
echarts.use([
|
||||||
|
BarChart,
|
||||||
|
GridComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
|
||||||
|
let myChart: echarts.ECharts;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
|
||||||
|
await handleGoMounted()
|
||||||
|
});
|
||||||
|
|
||||||
|
// 传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
currentService?: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 监听传入的选中服务区
|
||||||
|
watch(
|
||||||
|
() => props.currentService,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
handleGoMounted()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
// 初始运行的方法
|
||||||
|
const handleGoMounted = async () => {
|
||||||
|
const res = await handleGetData()
|
||||||
|
console.log('handleGetDatahandleGetDatahandleGetDatahandleGetData', res);
|
||||||
|
|
||||||
|
const chartDom = document.getElementById('VehicleStayAnalysisCharts');
|
||||||
|
if (!chartDom) return;
|
||||||
|
|
||||||
|
myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: { type: 'shadow' },
|
||||||
|
formatter: function (params: any) {
|
||||||
|
return `
|
||||||
|
<div style="font-weight:bold">${params[0].name}</div>
|
||||||
|
<div>车辆占比: ${params[0].value}%</div>
|
||||||
|
<div>停留时间: ${params[1].value}分钟</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['车辆占比', '停留时间']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '5%',
|
||||||
|
right: '5%',
|
||||||
|
bottom: '5%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: res.category,
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0,
|
||||||
|
width: 60,
|
||||||
|
overflow: 'truncate'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{ // 左侧Y轴(车辆占比)
|
||||||
|
type: 'value',
|
||||||
|
name: '车辆占比(%)',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
axisLine: { show: true },
|
||||||
|
splitLine: { show: false }
|
||||||
|
},
|
||||||
|
{ // 右侧Y轴(停留时间)
|
||||||
|
type: 'value',
|
||||||
|
name: '停留时间(分钟)',
|
||||||
|
axisLine: { show: true },
|
||||||
|
splitLine: { show: false },
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{ // 柱状图(车辆占比)
|
||||||
|
name: '车辆占比',
|
||||||
|
type: 'bar',
|
||||||
|
data: res.realData,
|
||||||
|
yAxisIndex: 0, // 使用右侧Y轴
|
||||||
|
barWidth: 5,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: [4, 4, 0, 0],
|
||||||
|
color: '#0094FF'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ // 折线图(停留时间)
|
||||||
|
name: '停留时间',
|
||||||
|
type: 'bar',
|
||||||
|
yAxisIndex: 1, // 使用右侧Y轴
|
||||||
|
data: res.seriesData,
|
||||||
|
barWidth: 5,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: [4, 4, 0, 0],
|
||||||
|
color: '#00FFB7',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
window.addEventListener('resize', resizeChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleGetData = async () => {
|
||||||
|
const req: any = {
|
||||||
|
ContainWhole: true,
|
||||||
|
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||||
|
Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await handleGetBayonetSTAList(req)
|
||||||
|
console.log('daskdhjfhsidugfajskdfhsjalkfhsduifhsdi', data);
|
||||||
|
|
||||||
|
|
||||||
|
let category: string[] = []
|
||||||
|
let seriesData: number[] = []
|
||||||
|
let realData: number[] = []
|
||||||
|
|
||||||
|
let obj: any = data[0]
|
||||||
|
category = obj.Vehicle_Type
|
||||||
|
if (obj.StayTimesList && obj.StayTimesList.length > 0) {
|
||||||
|
obj.StayTimesList.forEach((item: any) => {
|
||||||
|
seriesData.push(Number(item.value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (obj.VehicleCountList && obj.VehicleCountList.length > 0) {
|
||||||
|
let sum: number = 0
|
||||||
|
obj.VehicleCountList.forEach((item: any) => {
|
||||||
|
sum += Number(item.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
obj.VehicleCountList.forEach((item: any) => {
|
||||||
|
realData.push(Number((Number(item.value) / sum * 100).toFixed(2)))
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
category: category,
|
||||||
|
seriesData: seriesData,
|
||||||
|
realData: realData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeChart = () => {
|
||||||
|
myChart?.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', resizeChart);
|
||||||
|
myChart?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="VehicleStayAnalysisBox">
|
||||||
|
<SmallTitle title="车型停留分析/日均" />
|
||||||
|
|
||||||
|
<div class="VehicleStayAnalysisContent">
|
||||||
|
<div class="VehicleStayAnalysisCharts" id="VehicleStayAnalysisCharts"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
.VehiclesEntering {
|
.VehiclesEntering {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 134px;
|
// height: 134px;
|
||||||
|
height: 167px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,7 +3,7 @@ import SmallTitle from '../smallTitle/smallTitle.vue'
|
|||||||
import './VehiclesEntering.less'
|
import './VehiclesEntering.less'
|
||||||
import { onMounted, onBeforeUnmount, watch } from 'vue';
|
import { onMounted, onBeforeUnmount, watch } from 'vue';
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import { BarChart } from 'echarts/charts';
|
import { BarChart, LineChart } from 'echarts/charts';
|
||||||
import {
|
import {
|
||||||
GridComponent,
|
GridComponent,
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
@ -12,11 +12,12 @@ import {
|
|||||||
} from 'echarts/components';
|
} from 'echarts/components';
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { handleGetSPBayonetList } from '../../service';
|
import { handleGetMonthAnalysis, handleGetSPBayonetList } from '../../service';
|
||||||
|
|
||||||
// 注册组件
|
// 注册组件
|
||||||
echarts.use([
|
echarts.use([
|
||||||
BarChart,
|
BarChart,
|
||||||
|
LineChart,
|
||||||
GridComponent,
|
GridComponent,
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
@ -50,47 +51,102 @@ const handleGoMounted = async () => {
|
|||||||
const chartDom = document.getElementById('VehiclesEntering');
|
const chartDom = document.getElementById('VehiclesEntering');
|
||||||
if (!chartDom) return;
|
if (!chartDom) return;
|
||||||
myChart = echarts.init(chartDom);
|
myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
crossStyle: {
|
||||||
|
color: '#999'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
legend: {
|
||||||
|
data: [`${res.currentYear}年车流量`, `${res.yesYear}年车流量`, `${res.currentYear}年交易额`, `${res.yesYear}年交易额`],
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12 // 设置图例文字大小为12px
|
||||||
|
},
|
||||||
|
right: '4%',
|
||||||
|
top: '0%',
|
||||||
|
orient: 'horizontal',
|
||||||
|
type: 'scroll' // 如果图例过长,启用滚动
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
top: '30%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: true,
|
boundaryGap: true,
|
||||||
data: res.category
|
data: res.category,
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: [
|
||||||
type: 'value',
|
|
||||||
splitLine: { show: false } // 隐藏刻度线
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '0', // 左侧间距
|
|
||||||
right: '0', // 右侧间距
|
|
||||||
bottom: '0', // 底部间距
|
|
||||||
top: '10', // 顶部间距
|
|
||||||
containLabel: true // 确保坐标轴标签在grid内
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
{
|
||||||
data: res.seriesData,
|
type: 'value',
|
||||||
realData: res.realData,
|
name: '车流量(万辆)',
|
||||||
type: 'bar',
|
splitLine: { show: false },
|
||||||
smooth: true,
|
axisLabel: {
|
||||||
barWidth: '18',
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
splitNumber: 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '交易金额(万元)',
|
||||||
|
splitLine: { show: false },
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
},
|
||||||
|
splitNumber: 4
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
tooltip: { // 新增 tooltip 配置
|
series: [
|
||||||
trigger: 'axis', // 触发类型:坐标轴触发
|
{
|
||||||
axisPointer: { // 坐标轴指示器配置
|
name: `${res.currentYear}年车流量`,
|
||||||
type: 'shadow' // 阴影指示器(适合柱状图)
|
type: 'bar',
|
||||||
|
barWidth: '6',
|
||||||
|
data: res.seriesDataCar,
|
||||||
|
yAxisIndex: 0
|
||||||
},
|
},
|
||||||
formatter: function (params: any) { // 自定义提示框内容
|
{
|
||||||
// params 是数组,包含当前 hover 的所有系列数据
|
name: `${res.yesYear}年车流量`,
|
||||||
const data = params[0];
|
type: 'bar',
|
||||||
let realData = res.realData[params[0].dataIndex]
|
smooth: true,
|
||||||
return `
|
data: res.yesSeriesDataCar,
|
||||||
<div style="font-weight:bold">${data.name}</div>
|
yAxisIndex: 0,
|
||||||
<div>车流量:${realData ? realData + '辆' : data.value + '万辆'} </div>
|
barWidth: '6',
|
||||||
`;
|
lineStyle: {
|
||||||
|
width: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${res.currentYear}年交易额`,
|
||||||
|
type: 'line',
|
||||||
|
data: res.seriesDataRevenue,
|
||||||
|
yAxisIndex: 1,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${res.yesYear}年交易额`,
|
||||||
|
type: 'line',
|
||||||
|
data: res.yesSeriesDataRevenue,
|
||||||
|
yAxisIndex: 1,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8
|
||||||
}
|
}
|
||||||
},
|
],
|
||||||
|
color: ['#008CFF', '#69BCFF', '#FF5E5E', '#FF9500'] // Custom colors for each series
|
||||||
};
|
};
|
||||||
myChart.setOption(option);
|
myChart.setOption(option);
|
||||||
myChart.resize();
|
myChart.resize();
|
||||||
@ -99,49 +155,74 @@ const handleGoMounted = async () => {
|
|||||||
|
|
||||||
// 拿到入区车辆的趋势
|
// 拿到入区车辆的趋势
|
||||||
const handleGetSectionFlowCount = async () => {
|
const handleGetSectionFlowCount = async () => {
|
||||||
const req: any = {
|
// const req: any = {
|
||||||
Province_Code: '340000',
|
// Province_Code: '340000',
|
||||||
Statistics_Date: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
// Statistics_Date: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||||
GroupType: 2,
|
// GroupType: 2,
|
||||||
Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
// Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
||||||
}
|
// }
|
||||||
const data = await handleGetSPBayonetList(req)
|
// const data = await handleGetSPBayonetList(req)
|
||||||
// 小型车总数
|
|
||||||
let smallCar: number = 0
|
|
||||||
// 中型车总数
|
|
||||||
let middleCar: number = 0
|
|
||||||
// 大型车总数
|
|
||||||
let bigCar: number = 0
|
|
||||||
|
|
||||||
|
const req: any = {
|
||||||
|
StartDate: moment().startOf('y').format('YYYY-MM-DD'),
|
||||||
|
EndDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||||
|
Serverpart_ID: props.currentService?.SERVERPART_ID || "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,1230,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"
|
||||||
|
}
|
||||||
|
const data = await handleGetMonthAnalysis(req)
|
||||||
|
|
||||||
|
const yesReq: any = {
|
||||||
|
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
|
||||||
|
EndDate: moment().subtract(1, 'y').endOf('y').format('YYYY-MM-DD'),
|
||||||
|
Serverpart_ID: props.currentService?.SERVERPART_ID || "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,1230,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"
|
||||||
|
}
|
||||||
|
|
||||||
|
const yesData = await handleGetMonthAnalysis(yesReq)
|
||||||
|
|
||||||
|
let category: string[] = []
|
||||||
|
let seriesDataCar: number[] = []
|
||||||
|
let seriesDataRevenue: number[] = []
|
||||||
|
let realDataCar: number[] = []
|
||||||
|
let realDataRevenue: number[] = []
|
||||||
|
|
||||||
|
console.log('dnasfhuaidhsdaghsakjlhsldk', data);
|
||||||
if (data && data.length > 0) {
|
if (data && data.length > 0) {
|
||||||
data.forEach((item: any) => {
|
data.forEach((item: any) => {
|
||||||
smallCar += item.MinVehicle_Count
|
category.push(`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}`)
|
||||||
middleCar += item.MediumVehicle_Count
|
seriesDataCar.push(item.Vehicle_Count / 10000)
|
||||||
bigCar += item.LargeVehicle_Count
|
realDataCar.push(item.Vehicle_Count)
|
||||||
|
seriesDataRevenue.push(item.RevenueAmount / 10000)
|
||||||
|
realDataRevenue.push(item.RevenueAmount)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let yesSeriesDataCar: number[] = []
|
||||||
|
let yesSeriesDataRevenue: number[] = []
|
||||||
|
let yesRealDataCar: number[] = []
|
||||||
|
let yesRealDataRevenue: number[] = []
|
||||||
|
|
||||||
|
if (yesData && yesData.length > 0) {
|
||||||
|
yesData.forEach((item: any) => {
|
||||||
|
yesSeriesDataCar.push(item.Vehicle_Count / 10000)
|
||||||
|
yesSeriesDataRevenue.push(item.RevenueAmount / 10000)
|
||||||
|
yesRealDataCar.push(item.Vehicle_Count)
|
||||||
|
yesRealDataRevenue.push(item.RevenueAmount)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let res: any = {
|
let res: any = {
|
||||||
category: ["小型车", "中型车", "大型车"],// x轴的内容
|
category: category,// x轴的内容
|
||||||
seriesData: [{
|
seriesDataCar: seriesDataCar, // 入区车流量 万
|
||||||
value: Number((smallCar / 10000).toFixed(2)),
|
seriesDataRevenue: seriesDataRevenue,// 营收 万
|
||||||
itemStyle: {
|
realDataCar: realDataCar,// 入区车流量 实际
|
||||||
color: '#7D4CD2'
|
realDataRevenue: realDataRevenue,// 营收 实际
|
||||||
}
|
yesSeriesDataCar: yesSeriesDataCar,// 入区车流量 万 去年
|
||||||
},
|
yesSeriesDataRevenue: yesSeriesDataRevenue,// 营收 万 去年
|
||||||
{
|
yesRealDataCar: yesRealDataCar,// 入区车流量 实际 去年
|
||||||
value: Number((middleCar / 10000).toFixed(2)),
|
yesRealDataRevenue: yesRealDataRevenue,// 营收 实际 去年
|
||||||
itemStyle: {
|
currentYear: moment().format('YYYY'), // 当前年份
|
||||||
color: '#0094FF'
|
yesYear: moment().subtract(1, 'y').format('YYYY')// 去年年份
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: Number((bigCar / 10000).toFixed(2)),
|
|
||||||
itemStyle: {
|
|
||||||
color: '#FF9500'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],// y轴的数据
|
|
||||||
realData: [smallCar.toLocaleString(), middleCar.toLocaleString(), bigCar.toLocaleString()]// 真实数据
|
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -163,7 +244,7 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="VehiclesEnteringBox">
|
<div class="VehiclesEnteringBox">
|
||||||
<SmallTitle :title="'入区车辆趋势'">
|
<SmallTitle :title="'月度车流累计'">
|
||||||
<!-- <template #extra>
|
<!-- <template #extra>
|
||||||
<div class="legendBox" style="display: flex;align-items: center;">
|
<div class="legendBox" style="display: flex;align-items: center;">
|
||||||
<div class="legendItem" style="display: flex;align-items: center;margin-right: 20px;">
|
<div class="legendItem" style="display: flex;align-items: center;margin-right: 20px;">
|
||||||
@ -189,7 +270,7 @@ onBeforeUnmount(() => {
|
|||||||
</SmallTitle>
|
</SmallTitle>
|
||||||
|
|
||||||
<div class="VehiclesEnteringCharts">
|
<div class="VehiclesEnteringCharts">
|
||||||
<div class="VehiclesEnteringUnit">辆</div>
|
<!-- <div class="VehiclesEnteringUnit">辆</div> -->
|
||||||
<div class="VehiclesEntering" id="VehiclesEntering"></div>
|
<div class="VehiclesEntering" id="VehiclesEntering"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
16
src/page/index/components/newBigTitleBox/newBigTitleBox.less
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.newBigTitleBox {
|
||||||
|
width: 100%;
|
||||||
|
height: 31px;
|
||||||
|
background-image: url(../../../../assets/image/newBigTitleBg.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
font-family: YouSheBiaoTiHei;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #4CA9EF;
|
||||||
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 38px;
|
||||||
|
}
|
||||||
19
src/page/index/components/newBigTitleBox/newBigTitleBox.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import './newBigTitleBox.less'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 拿到传入的数据
|
||||||
|
const props = defineProps<{
|
||||||
|
title?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="newBigTitleBox">
|
||||||
|
{{ props?.title || "" }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -1,55 +1,128 @@
|
|||||||
|
// 横向滚动
|
||||||
.noticeListBigBox {
|
.noticeListBigBox {
|
||||||
|
width: 100%;
|
||||||
|
height: 25px;
|
||||||
|
// background: rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 18px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
.noticeIcon {
|
.noticeIcon {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
margin-right: 10px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noticeListBox {
|
.noticeListBox {
|
||||||
height: 26px; // 2条高度,按你需求调整
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
.noticeList {
|
.noticeList {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
white-space: nowrap;
|
||||||
|
transition: none;
|
||||||
&.scrolling {
|
position: relative;
|
||||||
animation: scrollAnimation 20s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noticeItem {
|
.noticeItem {
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 6px 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-right: 15px; // 调整item之间的间距
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 8px;
|
width: 3px;
|
||||||
height: 8px;
|
height: 3px;
|
||||||
background: #fff;
|
background: #1989FA;
|
||||||
transform: rotate(45deg);
|
border-radius: 50%;
|
||||||
margin-right: 8px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contentMessage {
|
.contentMessage {
|
||||||
white-space: nowrap;
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
overflow: hidden;
|
font-weight: 400;
|
||||||
text-overflow: ellipsis;
|
font-size: 19px;
|
||||||
font-size: 16px;
|
line-height: 19px;
|
||||||
color: #fff;
|
color: #FFFFFF;
|
||||||
line-height: 26px;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
font-style: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 实现无缝滚动
|
||||||
|
&.scrolling {
|
||||||
|
animation: scrollNotice var(--scroll-duration, 10s) linear infinite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关键帧动画
|
||||||
|
@keyframes scrollNotice {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(-VAR_PX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
// 纵向滚动
|
||||||
|
// .noticeListBigBox {
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
|
||||||
|
|
||||||
|
// .noticeIcon {
|
||||||
|
// width: 18px;
|
||||||
|
// height: 18px;
|
||||||
|
// margin-right: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .noticeListBox {
|
||||||
|
// height: 26px; // 2条高度,按你需求调整
|
||||||
|
// overflow: hidden;
|
||||||
|
// position: relative;
|
||||||
|
// border-radius: 8px;
|
||||||
|
|
||||||
|
// .noticeList {
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
|
||||||
|
// &.scrolling {
|
||||||
|
// animation: scrollAnimation 20s linear infinite;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .noticeItem {
|
||||||
|
// width: 100%;
|
||||||
|
// box-sizing: border-box;
|
||||||
|
// padding: 6px 0;
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
|
||||||
|
// .icon {
|
||||||
|
// width: 8px;
|
||||||
|
// height: 8px;
|
||||||
|
// background: #fff;
|
||||||
|
// transform: rotate(45deg);
|
||||||
|
// margin-right: 8px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .contentMessage {
|
||||||
|
// white-space: nowrap;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
// font-size: 16px;
|
||||||
|
// color: #fff;
|
||||||
|
// line-height: 26px;
|
||||||
|
// text-align: left;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import './noticeListBox.less'
|
import './noticeListBox.less'
|
||||||
import noticeIcon from '../../../../assets/image/noticeIcon.png'
|
import noticeIcon from '../../../../assets/image/noticeIcon.png'
|
||||||
import { onMounted, reactive, ref, watch } from 'vue'
|
import { nextTick, onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { handleGetGDNearServiceList } from '../../service'
|
import { handleGetGDNearServiceList } from '../../service'
|
||||||
|
|
||||||
|
|
||||||
@ -11,6 +11,8 @@ let noticeList = reactive<any>([]);
|
|||||||
let currentIndex = ref<number>(0)
|
let currentIndex = ref<number>(0)
|
||||||
// 滚动的计时器
|
// 滚动的计时器
|
||||||
let scrollInterval = ref<any>(null)
|
let scrollInterval = ref<any>(null)
|
||||||
|
let isScrolling = ref<boolean>(false);
|
||||||
|
let scrollDuration = ref('10s'); // 动态动画时长
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 获取播报数据
|
// 获取播报数据
|
||||||
@ -52,44 +54,94 @@ const handleGetNoticeList = async () => {
|
|||||||
|
|
||||||
noticeList.length = 0;
|
noticeList.length = 0;
|
||||||
list && list.forEach((item: any) => noticeList.push(item));
|
list && list.forEach((item: any) => noticeList.push(item));
|
||||||
if (list && list.length > 0) {
|
console.log('noticeList:', noticeList); // 添加这行
|
||||||
startScrolling()
|
nextTick(() => {
|
||||||
}
|
// 数据加载完成后启动滚动
|
||||||
|
startScrolling();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始滚动的方法
|
// 开始滚动的方法
|
||||||
const startScrolling = () => {
|
const startScrolling = () => {
|
||||||
stopScrolling();
|
isScrolling.value = false;
|
||||||
if (noticeList.length <= 1) return;
|
nextTick(() => {
|
||||||
const duration = 3000;
|
const listEl = document.querySelector('.noticeList') as HTMLElement;
|
||||||
scrollInterval.value = setInterval(() => {
|
if (listEl) {
|
||||||
currentIndex.value++;
|
const originWidth = listEl.scrollWidth / 2;
|
||||||
if (currentIndex.value >= noticeList.length) {
|
const speed = 100; // px/s
|
||||||
setTimeout(() => {
|
const duration = originWidth / speed;
|
||||||
const container = document.querySelector('.noticeContainer') as HTMLElement;
|
scrollDuration.value = duration + 's';
|
||||||
if (container) container.style.transition = 'none';
|
|
||||||
currentIndex.value = 0;
|
// 动态插入 keyframes
|
||||||
setTimeout(() => {
|
const styleId = 'dynamic-scroll-keyframes';
|
||||||
if (container) container.style.transition = '';
|
let styleEl = document.getElementById(styleId) as HTMLStyleElement;
|
||||||
}, 50);
|
if (!styleEl) {
|
||||||
}, 500);
|
styleEl = document.createElement('style');
|
||||||
|
styleEl.id = styleId;
|
||||||
|
document.head.appendChild(styleEl);
|
||||||
|
}
|
||||||
|
styleEl.innerHTML = `
|
||||||
|
@keyframes scrollNotice {
|
||||||
|
0% { transform: translateX(0); }
|
||||||
|
100% { transform: translateX(-${originWidth}px); }
|
||||||
|
}`;
|
||||||
|
isScrolling.value = true;
|
||||||
}
|
}
|
||||||
}, duration);
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// stopScrolling();
|
||||||
|
// if (noticeList.length <= 1) return;
|
||||||
|
// const duration = 3000;
|
||||||
|
// scrollInterval.value = setInterval(() => {
|
||||||
|
// currentIndex.value++;
|
||||||
|
// if (currentIndex.value >= noticeList.length) {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// const container = document.querySelector('.noticeContainer') as HTMLElement;
|
||||||
|
// if (container) container.style.transition = 'none';
|
||||||
|
// currentIndex.value = 0;
|
||||||
|
// setTimeout(() => {
|
||||||
|
// if (container) container.style.transition = '';
|
||||||
|
// }, 50);
|
||||||
|
// }, 500);
|
||||||
|
// }
|
||||||
|
// }, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止滚动的方法
|
// 停止滚动的方法
|
||||||
const stopScrolling = () => {
|
const stopScrolling = () => {
|
||||||
|
isScrolling.value = false;
|
||||||
if (scrollInterval.value) {
|
if (scrollInterval.value) {
|
||||||
clearInterval(scrollInterval.value)
|
clearInterval(scrollInterval.value)
|
||||||
scrollInterval.value = null
|
scrollInterval.value = null
|
||||||
}
|
}
|
||||||
|
// if (scrollInterval.value) {
|
||||||
|
// clearInterval(scrollInterval.value)
|
||||||
|
// scrollInterval.value = null
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- 横向滚动 -->
|
||||||
<div class="noticeListBigBox">
|
<div class="noticeListBigBox">
|
||||||
|
<img class="noticeIcon" :src="noticeIcon" />
|
||||||
|
<div class="noticeListBox">
|
||||||
|
<div :class="['noticeList', { 'scrolling': isScrolling }]" :style="{ '--scroll-duration': scrollDuration }">
|
||||||
|
<div class="noticeItem" v-for="(item, index) in noticeList.concat(noticeList)" :key="index">
|
||||||
|
<div class="icon"></div>
|
||||||
|
<div class="contentMessage">
|
||||||
|
{{ item.NOTICEINFO_TITLE || '-' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 纵向滚动 -->
|
||||||
|
<!-- <div class="noticeListBigBox">
|
||||||
<img class="noticeIcon" :src="noticeIcon" />
|
<img class="noticeIcon" :src="noticeIcon" />
|
||||||
<div class="noticeListBox">
|
<div class="noticeListBox">
|
||||||
<div :class="noticeList.length > 1 ? 'noticeList scrolling' : 'noticeList'">
|
<div :class="noticeList.length > 1 ? 'noticeList scrolling' : 'noticeList'">
|
||||||
@ -101,7 +153,7 @@ const stopScrolling = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="noticeItem" v-for="(item, index) in noticeList" :key="index">
|
<div class="noticeItem" v-for="(item, index) in noticeList" :key="index">
|
||||||
<div class="icon"></div>
|
<div class="icon"></div>
|
||||||
<div class="contentMessage">
|
<div class="contentMessage">
|
||||||
@ -109,7 +161,7 @@ const stopScrolling = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</template>
|
</template>
|
||||||
@ -165,22 +165,27 @@
|
|||||||
|
|
||||||
.pageTop169 {
|
.pageTop169 {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 48px;
|
// height: 48px;
|
||||||
background: linear-gradient(180deg, #182950 0%, #18223F 100%);
|
height: 86px;
|
||||||
border-bottom: 1px solid #0E789A;
|
// background: linear-gradient(180deg, #182950 0%, #18223F 100%);
|
||||||
|
// border-bottom: 1px solid #0E789A;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
background-image: url('../../../../assets/image/allPageTopBg.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
// padding: 0 30px;
|
// padding: 0 30px;
|
||||||
|
|
||||||
.centerBox {
|
.centerBox {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
background-image: url('../../../../assets//image/pageTitle.png');
|
// background-image: url('../../../../assets//image/pageTitle.png');
|
||||||
background-repeat: no-repeat;
|
// background-image: url('../../../../assets/image/newPageTitle.png');
|
||||||
background-size: 100% 100%;
|
// background-repeat: no-repeat;
|
||||||
|
// background-size: 100% 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
// left: 50%;
|
// left: 50%;
|
||||||
@ -210,19 +215,20 @@
|
|||||||
|
|
||||||
.leftTabBox {
|
.leftTabBox {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
height: 100%;
|
// height: 100%;
|
||||||
|
height: 48px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
|
|
||||||
.pageTopTabItem {
|
.pageTopTabItem {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: Inter, Inter;
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
font-weight: 400;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #5D6780;
|
color: #ffffff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -232,8 +238,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.selectPageTopTabItem {
|
.selectPageTopTabItem {
|
||||||
color: #FFFFFF;
|
color: #4CA9EF;
|
||||||
background-image: url('../../../../assets//image/pageTabBg.png');
|
background-image: url('../../../../assets//image/newSelectPageTop.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,7 +123,6 @@ const handleGetNowWeather = async () => {
|
|||||||
weatherInfo.value = weatherObj
|
weatherInfo.value = weatherObj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 改变页面显示状态
|
// 改变页面显示状态
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "handleChangePageType"): void; // 切换页面样式
|
(e: "handleChangePageType"): void; // 切换页面样式
|
||||||
@ -187,8 +186,8 @@ onBeforeUnmount(() => {
|
|||||||
<div :class="props.pageType === 'left' ? 'centerBox leftBgBox' : 'centerBox'"
|
<div :class="props.pageType === 'left' ? 'centerBox leftBgBox' : 'centerBox'"
|
||||||
:style="{ left: props.pageType === 'left' ? '0' : '50%', transform: props.pageType === 'left' ? 'translateX(-50px)' : 'translateX(-50%)' }">
|
:style="{ left: props.pageType === 'left' ? '0' : '50%', transform: props.pageType === 'left' ? 'translateX(-50px)' : 'translateX(-50%)' }">
|
||||||
<!-- @click="handleChangePageType" -->
|
<!-- @click="handleChangePageType" -->
|
||||||
<img class="pageLogo" :src="cyyLogo" />
|
<!-- <img class="pageLogo" :src="cyyLogo" /> -->
|
||||||
<span class="pageTitle">云南高速服务区智慧数智大屏</span>
|
<!-- <span class="pageTitle">云南高速服务区智慧数智大屏</span> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 最初版的内容 -->
|
<!-- 最初版的内容 -->
|
||||||
|
|||||||
@ -1,17 +1,19 @@
|
|||||||
.smallTitleBox {
|
.smallTitleBox {
|
||||||
height: 28px;
|
// height: 28px;
|
||||||
|
height: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 4px 10px;
|
// padding: 4px 10px;
|
||||||
background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
// background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
border-left: 1px solid #01F0FE;
|
// border-left: 1px solid #01F0FE;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
padding-left: 10px;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-family: "Microsoft YaHei";
|
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||||
font-weight: 400;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
font-size: 15px;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import './smallTitle.less'
|
|||||||
// 拿到传入的数据
|
// 拿到传入的数据
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
pageType?: any;
|
pageType?: any;
|
||||||
title: string
|
title?: string
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -42,6 +42,14 @@ import MerchantRatingRanking from './components/MerchantRatingRanking/MerchantRa
|
|||||||
import HighQualityMerchants from './components/HighQualityMerchants/HighQualityMerchants.vue'
|
import HighQualityMerchants from './components/HighQualityMerchants/HighQualityMerchants.vue'
|
||||||
import ThisMonthBenefits from './components/ThisMonthBenefits/ThisMonthBenefits.vue';
|
import ThisMonthBenefits from './components/ThisMonthBenefits/ThisMonthBenefits.vue';
|
||||||
import CoreCategory from './components/CoreCategory/CoreCategory.vue'
|
import CoreCategory from './components/CoreCategory/CoreCategory.vue'
|
||||||
|
import BusinessCase from './components/BusinessCase/BusinessCase.vue'
|
||||||
|
import CustomerGroup from './components/CustomerGroup/CustomerGroup.vue'
|
||||||
|
import CustomerConsumptionPreferences from './components/CustomerConsumptionPreferences/CustomerConsumptionPreferences.vue'
|
||||||
|
import VehicleStayAnalysis from './components/VehicleStayAnalysis/VehicleStayAnalysis.vue'
|
||||||
|
import BrandDetail from './components/BrandDetail/BrandDetail.vue'
|
||||||
|
import AssessmentScoring from './components/AssessmentScoring/AssessmentScoring.vue';
|
||||||
|
import OverviewOfServiceArea from './components/OverviewOfServiceArea/OverviewOfServiceArea.vue'
|
||||||
|
import NewBigTitleBox from './components/newBigTitleBox/newBigTitleBox.vue'
|
||||||
|
|
||||||
// 页面样式
|
// 页面样式
|
||||||
let pageType = ref<string>("center")
|
let pageType = ref<string>("center")
|
||||||
@ -92,15 +100,16 @@ const handleChangePageTab = (value: number) => {
|
|||||||
<!-- 消息轮播框 -->
|
<!-- 消息轮播框 -->
|
||||||
<NoticeListBox :currentService="currentService" />
|
<NoticeListBox :currentService="currentService" />
|
||||||
|
|
||||||
<modalTitle :title="'流量趋势'" style="margin-top: 20px;" />
|
<!-- <modalTitle :title="'流量趋势'" style="margin-top: 20px;" /> -->
|
||||||
<div class="leftContentBox">
|
<NewBigTitleBox title="流量趋势" style="margin-top: 37px;" />
|
||||||
|
|
||||||
|
<div class="content169LeftContent">
|
||||||
<div class="leftContentBoxItem">
|
<div class="leftContentBoxItem">
|
||||||
<!-- 车流断面趋势 -->
|
<!-- 车流断面趋势 -->
|
||||||
<TrendOfTrafficFlow :currentService="currentService" />
|
<TrendOfTrafficFlow :currentService="currentService" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="leftContentBoxItem" style="margin-top: 20px;">
|
<div class="leftContentBoxItem" style="margin-top: 30px;">
|
||||||
<!-- 入区车辆趋势 -->
|
<!-- 入区车辆趋势 -->
|
||||||
<VehiclesEntering :currentService="currentService" />
|
<VehiclesEntering :currentService="currentService" />
|
||||||
</div>
|
</div>
|
||||||
@ -112,6 +121,7 @@ const handleChangePageTab = (value: number) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<modalTitle :title="'节假日营收分析'" style="margin-top: 20px;">
|
<modalTitle :title="'节假日营收分析'" style="margin-top: 20px;">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<div class="FestivalBox">
|
<div class="FestivalBox">
|
||||||
@ -148,7 +158,7 @@ const handleChangePageTab = (value: number) => {
|
|||||||
<MultiIndustryIncome style="margin-top: 20px;" :currentService="currentService" />
|
<MultiIndustryIncome style="margin-top: 20px;" :currentService="currentService" />
|
||||||
|
|
||||||
<!-- 区域营收占比 -->
|
<!-- 区域营收占比 -->
|
||||||
<RegionalRevenue :currentService="currentService" style="margin-top: 56px;" />
|
<RegionalRevenue :currentService="currentService" style="margin-top: 90px;" />
|
||||||
|
|
||||||
<!-- 业态结构占比 -->
|
<!-- 业态结构占比 -->
|
||||||
<BusinessStructure :currentService="currentService" style="margin-top: 30px;" />
|
<BusinessStructure :currentService="currentService" style="margin-top: 30px;" />
|
||||||
@ -160,7 +170,7 @@ const handleChangePageTab = (value: number) => {
|
|||||||
<div class="content1692st" v-if="selectPageTab === 2">
|
<div class="content1692st" v-if="selectPageTab === 2">
|
||||||
<div class="content1692stLeft">
|
<div class="content1692stLeft">
|
||||||
<!-- 消息轮播框 -->
|
<!-- 消息轮播框 -->
|
||||||
<NoticeListBox />
|
<NoticeListBox style="margin-top: 20px;" />
|
||||||
<!-- 核心经营数据 -->
|
<!-- 核心经营数据 -->
|
||||||
<modalTitle :title="'核心经营数据'" style="margin-top: 20px;" />
|
<modalTitle :title="'核心经营数据'" style="margin-top: 20px;" />
|
||||||
<CoreBusinessData style="position: relative;z-index: 9;" :noTitle="true" />
|
<CoreBusinessData style="position: relative;z-index: 9;" :noTitle="true" />
|
||||||
@ -220,7 +230,7 @@ const handleChangePageTab = (value: number) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="content1692stRight">
|
<div class="content1692stRight">
|
||||||
<!-- 时间天气等内容 -->
|
<!-- 时间天气等内容 -->
|
||||||
<BasicMessageBox />
|
<BasicMessageBox style="margin-top: 19px;" />
|
||||||
<!-- 电商模块 -->
|
<!-- 电商模块 -->
|
||||||
<modalTitle :title="'电商模块'" style="margin-top: 20px;" />
|
<modalTitle :title="'电商模块'" style="margin-top: 20px;" />
|
||||||
|
|
||||||
@ -291,7 +301,44 @@ const handleChangePageTab = (value: number) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content1693stItem">
|
<div class="content1693stItem">
|
||||||
|
<!-- 经营数据同比分析 -->
|
||||||
|
<BusinessCase :currentService="currentService" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分区四 -->
|
||||||
|
<div class="content1694st" v-if="selectPageTab === 4">
|
||||||
|
<div class="content1694stItem">
|
||||||
|
<!-- 客群特征分析 -->
|
||||||
|
<CustomerGroup />
|
||||||
|
|
||||||
|
<!-- 客群消费偏好 -->
|
||||||
|
<CustomerConsumptionPreferences style="margin-top: 140px;" />
|
||||||
|
|
||||||
|
<!-- 车型停留分析/日均 -->
|
||||||
|
<VehicleStayAnalysis style="margin-top: 130px;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content1694stItem">
|
||||||
|
<!-- 商户类别比例图 和 下面的列表 -->
|
||||||
|
<BrandDetail />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content1694stItem">
|
||||||
|
<!-- 在线服务区和在线收银机 -->
|
||||||
|
<TodayTrend />
|
||||||
|
|
||||||
|
<!-- 交易预警 -->
|
||||||
|
<TradingAlert />
|
||||||
|
|
||||||
|
<!-- 考核打分排行榜 -->
|
||||||
|
<AssessmentScoring style="margin-top: 130px;" />
|
||||||
|
</div>
|
||||||
|
<div class="content1694stItem">
|
||||||
|
|
||||||
|
<!-- 服务区概况 -->
|
||||||
|
<OverviewOfServiceArea />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -287,3 +287,93 @@ export async function handleGetCombineBrandList(params: any) {
|
|||||||
}
|
}
|
||||||
return data.Result_Data.List
|
return data.Result_Data.List
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取营收同比数据
|
||||||
|
export async function handleCodeGetRevenueCompare(params: any) {
|
||||||
|
const data: any = await requestCode.get('/Revenue/GetRevenueCompare', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取营收趋势图
|
||||||
|
export async function handleGetRevenueTrend(params: any) {
|
||||||
|
const data: any = await requestCode.get('/Revenue/GetRevenueTrend', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data.List
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取客群特征分析
|
||||||
|
export async function handleGetCustomerGroupRatio(params: any) {
|
||||||
|
const data: any = await requestCode.get('/Customer/GetCustomerGroupRatio', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data.List
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取客群消费偏好数据
|
||||||
|
export async function handleGetCustomerSaleRatio(params: any) {
|
||||||
|
const data: any = await requestCode.get('/Customer/GetCustomerSaleRatio', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取服务区车辆时段停留时长分析
|
||||||
|
export async function handleGetBayonetSTAList(params: any) {
|
||||||
|
const data: any = await requestCode.get('/Revenue/GetBayonetSTAList', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data.List
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 查询经营业态树
|
||||||
|
export async function handleGetBusinessTradeTree(params: any) {
|
||||||
|
const data: any = await request.get('/BaseInfo/GetBusinessTradeTree', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return wrapTreeNode(data.Result_Data.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取品牌表列表
|
||||||
|
export async function handleGetBrandList(params: any) {
|
||||||
|
const data: any = await request.post('/BaseInfo/GetBrandList', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data.List
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 拿枚举
|
||||||
|
export async function handleGetFieldEnumTree(params: any) {
|
||||||
|
const data: any = await request.get('/FrameWork/GetFieldEnumTree', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return wrapTreeNode(data.Result_Data.List)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取月度车流分析数据
|
||||||
|
export async function handleGetMonthAnalysis(params: any) {
|
||||||
|
const data: any = await requestCode.get('/BigData/GetMonthAnalysis', params)
|
||||||
|
if (data.Result_Code !== 100) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data.Result_Data.List
|
||||||
|
}
|
||||||
@ -256,29 +256,38 @@
|
|||||||
|
|
||||||
.content169 {
|
.content169 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 48px);
|
// height: calc(100% - 48px);
|
||||||
|
height: calc(100% - 86px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0 20px 35px;
|
// padding: 0 20px 35px;
|
||||||
|
padding: 0 35px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.content169Left {
|
.content169Left {
|
||||||
width: 22%;
|
width: calc((100% - 105px) / 4);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 20px;
|
padding-top: 21px;
|
||||||
|
// padding-top: 20px;
|
||||||
|
|
||||||
|
.content169LeftContent {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 21px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
.leftContentBox {
|
.leftContentBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 20px 11px 0;
|
padding: 20px 11px 0;
|
||||||
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
backdrop-filter: blur(10px);
|
// backdrop-filter: blur(10px);
|
||||||
/* 高斯模糊效果 */
|
/* 高斯模糊效果 */
|
||||||
-webkit-backdrop-filter: blur(10px);
|
// -webkit-backdrop-filter: blur(10px);
|
||||||
/* Safari 兼容 */
|
/* Safari 兼容 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +309,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content169Center {
|
.content169Center {
|
||||||
width: 47%;
|
width: calc((100% - 105px) / 4 * 2 + 35px);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 66px;
|
padding-top: 66px;
|
||||||
@ -309,21 +318,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content169Right {
|
.content169Right {
|
||||||
width: 22%;
|
width: calc((100% - 105px) / 4);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 20px;
|
padding-top: 21px;
|
||||||
|
|
||||||
.rightContentBox {
|
.rightContentBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 20px 11px 0;
|
padding: 20px 11px 0;
|
||||||
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||||
backdrop-filter: blur(10px);
|
// backdrop-filter: blur(10px);
|
||||||
/* 高斯模糊效果 */
|
/* 高斯模糊效果 */
|
||||||
-webkit-backdrop-filter: blur(10px);
|
// -webkit-backdrop-filter: blur(10px);
|
||||||
/* Safari 兼容 */
|
/* Safari 兼容 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +344,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 48px);
|
height: calc(100% - 48px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 20px 35px;
|
padding: 0 20px 35px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -374,7 +383,7 @@
|
|||||||
width: 22%;
|
width: 22%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 46px;
|
padding-top: 66px;
|
||||||
|
|
||||||
.left4stContent {
|
.left4stContent {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -426,4 +435,24 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content1694st {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 48px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px 35px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.content1694stItem {
|
||||||
|
width: 22%;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||