update
@ -7,6 +7,7 @@
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import './assets/css/fonts.less'
|
||||
|
||||
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 {
|
||||
width: 100%;
|
||||
height: 25px;
|
||||
|
||||
.rightBox {
|
||||
// position: absolute;
|
||||
@ -26,14 +27,15 @@
|
||||
white-space: nowrap;
|
||||
|
||||
.weatherIcon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.weatherText {
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
font-size: 19px;
|
||||
line-height: 19px;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
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 {
|
||||
width: 100%;
|
||||
height: 106px;
|
||||
background-image: url('../../../../assets/image/businessCenterBg.png');
|
||||
// background-image: url('../../../../assets/image/businessCenterBg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
box-sizing: border-box;
|
||||
@ -93,7 +93,7 @@
|
||||
.busninessItemValue {
|
||||
font-family: Impact, Impact;
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
color: #FFFFFF;
|
||||
letter-spacing: 2px;
|
||||
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>
|
||||
<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="busninessItemLeft">
|
||||
@ -168,9 +232,6 @@ const handleGetPonitFixed = (str: string) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 油品消耗 -->
|
||||
<div class="busninessItem">
|
||||
<div class="busninessItemLeft">
|
||||
@ -222,9 +283,6 @@ const handleGetPonitFixed = (str: string) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 尿素 -->
|
||||
<div class="busninessItem">
|
||||
<div class="busninessItemLeft">
|
||||
@ -250,7 +308,6 @@ const handleGetPonitFixed = (str: string) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 充电次数 -->
|
||||
<div class="busninessItem">
|
||||
<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: 20px 10px 30px;
|
||||
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 兼容 */
|
||||
|
||||
.FestivalRevenue {
|
||||
|
||||
@ -111,10 +111,11 @@ onMounted(async () => {
|
||||
|
||||
const data = params[0];
|
||||
return `
|
||||
<div style="font-weight:bold">${data.name}服务区</div>
|
||||
<div>销售量:${data.value + '笔'} </div>
|
||||
<div style="font-weight:bold">${data.name}</div>
|
||||
<div>销售量:${data.value} </div>
|
||||
`;
|
||||
}
|
||||
// + '笔'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,89 @@
|
||||
.MerchantRatingRankingBox {
|
||||
width: 100%;
|
||||
|
||||
.MerchantRatingRankingCharts {
|
||||
// .MerchantRatingRankingCharts {
|
||||
// width: 100%;
|
||||
// height: 196px;
|
||||
// margin-top: 10px;
|
||||
// }
|
||||
|
||||
|
||||
.MerchantRatingRankingList {
|
||||
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">
|
||||
import SmallTitle from '../smallTitle/smallTitle.vue'
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
import { onMounted, onBeforeUnmount, ref } from 'vue';
|
||||
import * as echarts from 'echarts/core';
|
||||
import { BarChart } from 'echarts/charts';
|
||||
import {
|
||||
@ -26,7 +26,8 @@ echarts.use([
|
||||
|
||||
let myChart: echarts.ECharts;
|
||||
|
||||
|
||||
// 排行列表
|
||||
let rankList = ref<any>()
|
||||
|
||||
// 拿到传入的数据
|
||||
const props = defineProps<{
|
||||
@ -38,89 +39,89 @@ onMounted(async () => {
|
||||
const res = await handleGetData()
|
||||
|
||||
|
||||
const chartDom = document.getElementById('MerchantRatingRanking');
|
||||
if (!chartDom) return;
|
||||
// const chartDom = document.getElementById('MerchantRatingRanking');
|
||||
// if (!chartDom) return;
|
||||
|
||||
myChart = echarts.init(chartDom);
|
||||
// myChart = echarts.init(chartDom);
|
||||
|
||||
const option = {
|
||||
yAxis: { // 改为 yAxis 显示分类数据
|
||||
type: 'category',
|
||||
data: res.category,
|
||||
axisLabel: {
|
||||
width: 80,
|
||||
overflow: 'truncate',
|
||||
ellipsis: '...',
|
||||
interval: 0
|
||||
}
|
||||
},
|
||||
xAxis: { // 改为 xAxis 显示数值
|
||||
type: 'value',
|
||||
name: "笔",
|
||||
splitLine: { show: false }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: res.seriesData,
|
||||
realData: res.seriesData,
|
||||
type: 'bar',
|
||||
barWidth: '6', // 现在是柱子的高度
|
||||
showBackground: true,
|
||||
backgroundStyle: {
|
||||
borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||
color: 'rgba(23, 42, 70, 1)'
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||
color: function (params: any) {
|
||||
const index = params.dataIndex;
|
||||
if (index > 6) {
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0, 0, 1, 0, // 渐变方向改为水平
|
||||
[
|
||||
{ offset: 0, color: '#FF4F00' },
|
||||
{ offset: 1, color: '#D3B70E' }
|
||||
]
|
||||
);
|
||||
}
|
||||
else {
|
||||
// const option = {
|
||||
// yAxis: { // 改为 yAxis 显示分类数据
|
||||
// type: 'category',
|
||||
// data: res.category,
|
||||
// axisLabel: {
|
||||
// width: 80,
|
||||
// overflow: 'truncate',
|
||||
// ellipsis: '...',
|
||||
// interval: 0
|
||||
// }
|
||||
// },
|
||||
// xAxis: { // 改为 xAxis 显示数值
|
||||
// type: 'value',
|
||||
// name: "笔",
|
||||
// splitLine: { show: false }
|
||||
// },
|
||||
// series: [
|
||||
// {
|
||||
// data: res.seriesData,
|
||||
// realData: res.seriesData,
|
||||
// type: 'bar',
|
||||
// barWidth: '6', // 现在是柱子的高度
|
||||
// showBackground: true,
|
||||
// backgroundStyle: {
|
||||
// borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||
// color: 'rgba(23, 42, 70, 1)'
|
||||
// },
|
||||
// itemStyle: {
|
||||
// borderRadius: [0, 4, 4, 0], // 调整圆角方向
|
||||
// color: function (params: any) {
|
||||
// const index = params.dataIndex;
|
||||
// if (index > 6) {
|
||||
// return new echarts.graphic.LinearGradient(
|
||||
// 0, 0, 1, 0, // 渐变方向改为水平
|
||||
// [
|
||||
// { offset: 0, color: '#FF4F00' },
|
||||
// { offset: 1, color: '#D3B70E' }
|
||||
// ]
|
||||
// );
|
||||
// }
|
||||
// else {
|
||||
|
||||
return new echarts.graphic.LinearGradient(
|
||||
0, 0, 1, 0, // 渐变方向改为水平
|
||||
[
|
||||
{ offset: 0, color: '#018FFF' },
|
||||
{ offset: 1, color: '#00F4FF' }
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
grid: {
|
||||
left: '0', // 左侧留更多空间给y轴标签
|
||||
right: '10%',
|
||||
bottom: '5%',
|
||||
top: '0',
|
||||
containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'shadow' },
|
||||
formatter: function (params: any) {
|
||||
// return new echarts.graphic.LinearGradient(
|
||||
// 0, 0, 1, 0, // 渐变方向改为水平
|
||||
// [
|
||||
// { offset: 0, color: '#018FFF' },
|
||||
// { offset: 1, color: '#00F4FF' }
|
||||
// ]
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// ],
|
||||
// grid: {
|
||||
// left: '0', // 左侧留更多空间给y轴标签
|
||||
// right: '10%',
|
||||
// bottom: '5%',
|
||||
// top: '0',
|
||||
// containLabel: true
|
||||
// },
|
||||
// tooltip: {
|
||||
// trigger: 'axis',
|
||||
// axisPointer: { type: 'shadow' },
|
||||
// formatter: function (params: any) {
|
||||
|
||||
const data = params[0];
|
||||
return `
|
||||
<div style="font-weight:bold">${data.name}服务区</div>
|
||||
<div>销售量:${data.value + '笔'} </div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
};
|
||||
// const data = params[0];
|
||||
// return `
|
||||
// <div style="font-weight:bold">${data.name}服务区</div>
|
||||
// <div>销售量:${data.value + '笔'} </div>
|
||||
// `;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
myChart.setOption(option);
|
||||
window.addEventListener('resize', resizeChart);
|
||||
// myChart.setOption(option);
|
||||
// window.addEventListener('resize', resizeChart);
|
||||
});
|
||||
|
||||
// 拿到热门商品榜单
|
||||
@ -143,21 +144,42 @@ const handleGetData = async () => {
|
||||
return res
|
||||
}
|
||||
|
||||
const resizeChart = () => {
|
||||
myChart?.resize();
|
||||
};
|
||||
// const resizeChart = () => {
|
||||
// myChart?.resize();
|
||||
// };
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeChart);
|
||||
myChart?.dispose();
|
||||
});
|
||||
// onBeforeUnmount(() => {
|
||||
// window.removeEventListener('resize', resizeChart);
|
||||
// myChart?.dispose();
|
||||
// });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="MerchantRatingRankingBox">
|
||||
<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>
|
||||
</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 {
|
||||
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)
|
||||
|
||||
|
||||
// 客单数据
|
||||
let customerOrder = data.TransactionList
|
||||
|
||||
|
||||
@ -47,159 +47,159 @@ onMounted(async () => {
|
||||
|
||||
handleGetOnlineData()
|
||||
|
||||
const res: any = await handleGetData()
|
||||
// const res: any = await handleGetData()
|
||||
|
||||
const chartDom = document.getElementById('TodayTrend');
|
||||
if (!chartDom) return;
|
||||
// const chartDom = document.getElementById('TodayTrend');
|
||||
// if (!chartDom) return;
|
||||
|
||||
myChart = echarts.init(chartDom);
|
||||
// myChart = echarts.init(chartDom);
|
||||
|
||||
const option = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: res.category,
|
||||
// boundaryGap: true,
|
||||
axisLabel: {
|
||||
interval: 3,
|
||||
showMinLabel: true,
|
||||
showMaxLabel: true
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '营收',
|
||||
nameTextStyle: {
|
||||
color: '#00FFFF'
|
||||
},
|
||||
splitLine: { show: false },
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#00FFFF'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#00FFFF',
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '客单',
|
||||
nameTextStyle: {
|
||||
color: '#FFA500'
|
||||
},
|
||||
splitLine: { show: false },
|
||||
position: 'right',
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#FFA500'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#FFA500',
|
||||
formatter: '{value}'
|
||||
},
|
||||
offset: 0
|
||||
}
|
||||
],
|
||||
grid: {
|
||||
left: '10',
|
||||
right: '10',
|
||||
bottom: '10',
|
||||
top: '10',
|
||||
containLabel: true
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '营收',
|
||||
data: res.seriesData.map((value: any, index: any) => ({
|
||||
value: value,
|
||||
symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||
symbolSize: 6
|
||||
})),
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#00FFFF'
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#00FFFF'
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(0, 255, 255, 0.3)'
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(0, 255, 255, 0.1)'
|
||||
}
|
||||
])
|
||||
},
|
||||
yAxisIndex: 0
|
||||
},
|
||||
{
|
||||
name: '客单',
|
||||
data: res.seriesDataSecond.map((value: any, index: any) => ({
|
||||
value: value,
|
||||
symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||
symbolSize: 6
|
||||
})),
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#FFA500'
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#FFA500'
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(255, 165, 0, 0.3)'
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(255, 165, 0, 0.1)'
|
||||
}
|
||||
])
|
||||
},
|
||||
yAxisIndex: 1
|
||||
}
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'line',
|
||||
snap: true, // 关键点:启用吸附
|
||||
lineStyle: {
|
||||
color: '#FFF', // 可选:调整竖线颜色
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
formatter: function (params: any) {
|
||||
let tip = `<div style="font-weight:bold">${params[0].name}</div>`;
|
||||
params.forEach((param: any) => {
|
||||
const unit = param.seriesName === '营收' ? '元' : '单';
|
||||
let value = param.seriesName === '营收' ? res.seriesData[param.dataIndex] : res.seriesDataSecond[param.dataIndex]
|
||||
tip += `<div>${param.seriesName}: ${value ? value.toLocaleString() : ''}${unit}</div>`;
|
||||
});
|
||||
// const option = {
|
||||
// xAxis: {
|
||||
// type: 'category',
|
||||
// data: res.category,
|
||||
// // boundaryGap: true,
|
||||
// axisLabel: {
|
||||
// interval: 3,
|
||||
// showMinLabel: true,
|
||||
// showMaxLabel: true
|
||||
// }
|
||||
// },
|
||||
// yAxis: [
|
||||
// {
|
||||
// type: 'value',
|
||||
// name: '营收',
|
||||
// nameTextStyle: {
|
||||
// color: '#00FFFF'
|
||||
// },
|
||||
// splitLine: { show: false },
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: '#00FFFF'
|
||||
// }
|
||||
// },
|
||||
// axisLabel: {
|
||||
// color: '#00FFFF',
|
||||
// formatter: '{value}'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// type: 'value',
|
||||
// name: '客单',
|
||||
// nameTextStyle: {
|
||||
// color: '#FFA500'
|
||||
// },
|
||||
// splitLine: { show: false },
|
||||
// position: 'right',
|
||||
// axisLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: '#FFA500'
|
||||
// }
|
||||
// },
|
||||
// axisLabel: {
|
||||
// color: '#FFA500',
|
||||
// formatter: '{value}'
|
||||
// },
|
||||
// offset: 0
|
||||
// }
|
||||
// ],
|
||||
// grid: {
|
||||
// left: '10',
|
||||
// right: '10',
|
||||
// bottom: '10',
|
||||
// top: '10',
|
||||
// containLabel: true
|
||||
// },
|
||||
// series: [
|
||||
// {
|
||||
// name: '营收',
|
||||
// data: res.seriesData.map((value: any, index: any) => ({
|
||||
// value: value,
|
||||
// symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||
// symbolSize: 6
|
||||
// })),
|
||||
// type: 'line',
|
||||
// smooth: true,
|
||||
// lineStyle: {
|
||||
// width: 2,
|
||||
// color: '#00FFFF'
|
||||
// },
|
||||
// itemStyle: {
|
||||
// color: '#00FFFF'
|
||||
// },
|
||||
// areaStyle: {
|
||||
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
// {
|
||||
// offset: 0,
|
||||
// color: 'rgba(0, 255, 255, 0.3)'
|
||||
// },
|
||||
// {
|
||||
// offset: 1,
|
||||
// color: 'rgba(0, 255, 255, 0.1)'
|
||||
// }
|
||||
// ])
|
||||
// },
|
||||
// yAxisIndex: 0
|
||||
// },
|
||||
// {
|
||||
// name: '客单',
|
||||
// data: res.seriesDataSecond.map((value: any, index: any) => ({
|
||||
// value: value,
|
||||
// symbol: index % 3 === 0 ? 'circle' : 'none',
|
||||
// symbolSize: 6
|
||||
// })),
|
||||
// type: 'line',
|
||||
// smooth: true,
|
||||
// lineStyle: {
|
||||
// width: 2,
|
||||
// color: '#FFA500'
|
||||
// },
|
||||
// itemStyle: {
|
||||
// color: '#FFA500'
|
||||
// },
|
||||
// areaStyle: {
|
||||
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
// {
|
||||
// offset: 0,
|
||||
// color: 'rgba(255, 165, 0, 0.3)'
|
||||
// },
|
||||
// {
|
||||
// offset: 1,
|
||||
// color: 'rgba(255, 165, 0, 0.1)'
|
||||
// }
|
||||
// ])
|
||||
// },
|
||||
// yAxisIndex: 1
|
||||
// }
|
||||
// ],
|
||||
// tooltip: {
|
||||
// trigger: 'axis',
|
||||
// axisPointer: {
|
||||
// type: 'line',
|
||||
// snap: true, // 关键点:启用吸附
|
||||
// lineStyle: {
|
||||
// color: '#FFF', // 可选:调整竖线颜色
|
||||
// width: 1
|
||||
// }
|
||||
// },
|
||||
// formatter: function (params: any) {
|
||||
// let tip = `<div style="font-weight:bold">${params[0].name}</div>`;
|
||||
// params.forEach((param: any) => {
|
||||
// const unit = param.seriesName === '营收' ? '元' : '单';
|
||||
// let value = param.seriesName === '营收' ? res.seriesData[param.dataIndex] : res.seriesDataSecond[param.dataIndex]
|
||||
// tip += `<div>${param.seriesName}: ${value ? value.toLocaleString() : ''}${unit}</div>`;
|
||||
// });
|
||||
|
||||
return tip
|
||||
}
|
||||
}
|
||||
};
|
||||
// return tip
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
myChart.setOption(option);
|
||||
myChart.resize();
|
||||
window.addEventListener('resize', resizeChart);
|
||||
// myChart.setOption(option);
|
||||
// myChart.resize();
|
||||
// window.addEventListener('resize', resizeChart);
|
||||
})
|
||||
|
||||
// 修改选择的季月年
|
||||
@ -276,29 +276,29 @@ const handleGetOnlineData = async () => {
|
||||
onlineCashRegisterValue.value = handleGetFiveNumber(res.MACHINECOUNT)
|
||||
}
|
||||
|
||||
const resizeChart = () => {
|
||||
myChart?.resize();
|
||||
};
|
||||
// const resizeChart = () => {
|
||||
// myChart?.resize();
|
||||
// };
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeChart);
|
||||
myChart?.dispose();
|
||||
});
|
||||
// onBeforeUnmount(() => {
|
||||
// window.removeEventListener('resize', resizeChart);
|
||||
// myChart?.dispose();
|
||||
// });
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="TodayTrendBox">
|
||||
<SmallTitle :title="'今日走势图'"></SmallTitle>
|
||||
<!-- <SmallTitle :title="'今日走势图'"></SmallTitle> -->
|
||||
|
||||
<div class="TodayTrendUnit">
|
||||
<!-- <div class="TodayTrendUnit">
|
||||
<span>元</span>
|
||||
<span>单</span>
|
||||
</div>
|
||||
<div class="TodayTrendContent">
|
||||
</div> -->
|
||||
<!-- <div class="TodayTrendContent">
|
||||
<div class="TodayTrend" id="TodayTrend"></div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="onlineServiceBox">
|
||||
<div class="onlineServiceItem">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
.TrendOfTrafficFlowCharts {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
margin-top: 15px;
|
||||
position: relative;
|
||||
|
||||
.trafficFlowCarUnit {
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
.TrendOfTrafficFlow {
|
||||
width: 100%;
|
||||
height: 134px;
|
||||
height: 133px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,8 @@ const handleGoMounted = async () => {
|
||||
smooth: true,
|
||||
backgroundStyle: {
|
||||
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: {
|
||||
borderRadius: [4, 4, 0, 0],
|
||||
@ -133,7 +134,7 @@ const handleGoMounted = async () => {
|
||||
let realData = res.realData[params[0].dataIndex]
|
||||
|
||||
return `
|
||||
<div style="font-weight:bold">${data.name}服务区</div>
|
||||
<div style="font-weight:bold">${data.name}</div>
|
||||
<div>车流量:${realData ? realData + '辆' : data.value + '万辆'} </div>
|
||||
`;
|
||||
}
|
||||
@ -148,7 +149,8 @@ const handleGoMounted = async () => {
|
||||
// 拿到断面流量数据
|
||||
const handleGetSectionFlowCount = async () => {
|
||||
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 || "",
|
||||
SortStr: "SectionFlow_Count desc",
|
||||
ProvinceCode: "530000"
|
||||
@ -188,7 +190,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<template>
|
||||
<div class="TrendOfTrafficFlowBox">
|
||||
<SmallTitle :title="'车流断面趋势'" />
|
||||
<SmallTitle :title="`车流断面趋势(04月)`" />
|
||||
|
||||
<div class="TrendOfTrafficFlowCharts">
|
||||
<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 {
|
||||
width: 100%;
|
||||
height: 134px;
|
||||
// height: 134px;
|
||||
height: 167px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ import SmallTitle from '../smallTitle/smallTitle.vue'
|
||||
import './VehiclesEntering.less'
|
||||
import { onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import * as echarts from 'echarts/core';
|
||||
import { BarChart } from 'echarts/charts';
|
||||
import { BarChart, LineChart } from 'echarts/charts';
|
||||
import {
|
||||
GridComponent,
|
||||
TitleComponent,
|
||||
@ -12,11 +12,12 @@ import {
|
||||
} from 'echarts/components';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import moment from 'moment';
|
||||
import { handleGetSPBayonetList } from '../../service';
|
||||
import { handleGetMonthAnalysis, handleGetSPBayonetList } from '../../service';
|
||||
|
||||
// 注册组件
|
||||
echarts.use([
|
||||
BarChart,
|
||||
LineChart,
|
||||
GridComponent,
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
@ -50,47 +51,102 @@ const handleGoMounted = async () => {
|
||||
const chartDom = document.getElementById('VehiclesEntering');
|
||||
if (!chartDom) return;
|
||||
myChart = echarts.init(chartDom);
|
||||
|
||||
|
||||
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: {
|
||||
type: 'category',
|
||||
boundaryGap: true,
|
||||
data: res.category
|
||||
data: res.category,
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitLine: { show: false } // 隐藏刻度线
|
||||
},
|
||||
grid: {
|
||||
left: '0', // 左侧间距
|
||||
right: '0', // 右侧间距
|
||||
bottom: '0', // 底部间距
|
||||
top: '10', // 顶部间距
|
||||
containLabel: true // 确保坐标轴标签在grid内
|
||||
},
|
||||
series: [
|
||||
yAxis: [
|
||||
{
|
||||
data: res.seriesData,
|
||||
realData: res.realData,
|
||||
type: 'bar',
|
||||
smooth: true,
|
||||
barWidth: '18',
|
||||
type: 'value',
|
||||
name: '车流量(万辆)',
|
||||
splitLine: { show: false },
|
||||
axisLabel: {
|
||||
formatter: '{value}'
|
||||
},
|
||||
splitNumber: 4
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '交易金额(万元)',
|
||||
splitLine: { show: false },
|
||||
axisLabel: {
|
||||
formatter: '{value}'
|
||||
},
|
||||
splitNumber: 4
|
||||
}
|
||||
],
|
||||
tooltip: { // 新增 tooltip 配置
|
||||
trigger: 'axis', // 触发类型:坐标轴触发
|
||||
axisPointer: { // 坐标轴指示器配置
|
||||
type: 'shadow' // 阴影指示器(适合柱状图)
|
||||
series: [
|
||||
{
|
||||
name: `${res.currentYear}年车流量`,
|
||||
type: 'bar',
|
||||
barWidth: '6',
|
||||
data: res.seriesDataCar,
|
||||
yAxisIndex: 0
|
||||
},
|
||||
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>
|
||||
`;
|
||||
{
|
||||
name: `${res.yesYear}年车流量`,
|
||||
type: 'bar',
|
||||
smooth: true,
|
||||
data: res.yesSeriesDataCar,
|
||||
yAxisIndex: 0,
|
||||
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.resize();
|
||||
@ -99,49 +155,74 @@ const handleGoMounted = async () => {
|
||||
|
||||
// 拿到入区车辆的趋势
|
||||
const handleGetSectionFlowCount = async () => {
|
||||
const req: any = {
|
||||
Province_Code: '340000',
|
||||
Statistics_Date: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||
GroupType: 2,
|
||||
Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
||||
}
|
||||
const data = await handleGetSPBayonetList(req)
|
||||
// 小型车总数
|
||||
let smallCar: number = 0
|
||||
// 中型车总数
|
||||
let middleCar: number = 0
|
||||
// 大型车总数
|
||||
let bigCar: number = 0
|
||||
// const req: any = {
|
||||
// Province_Code: '340000',
|
||||
// Statistics_Date: moment().subtract(1, 'd').format('YYYY-MM-DD'),
|
||||
// GroupType: 2,
|
||||
// Serverpart_ID: props.currentService?.SERVERPART_ID || "",
|
||||
// }
|
||||
// const data = await handleGetSPBayonetList(req)
|
||||
|
||||
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) {
|
||||
data.forEach((item: any) => {
|
||||
smallCar += item.MinVehicle_Count
|
||||
middleCar += item.MediumVehicle_Count
|
||||
bigCar += item.LargeVehicle_Count
|
||||
category.push(`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}`)
|
||||
seriesDataCar.push(item.Vehicle_Count / 10000)
|
||||
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 = {
|
||||
category: ["小型车", "中型车", "大型车"],// x轴的内容
|
||||
seriesData: [{
|
||||
value: Number((smallCar / 10000).toFixed(2)),
|
||||
itemStyle: {
|
||||
color: '#7D4CD2'
|
||||
}
|
||||
},
|
||||
{
|
||||
value: Number((middleCar / 10000).toFixed(2)),
|
||||
itemStyle: {
|
||||
color: '#0094FF'
|
||||
}
|
||||
},
|
||||
{
|
||||
value: Number((bigCar / 10000).toFixed(2)),
|
||||
itemStyle: {
|
||||
color: '#FF9500'
|
||||
}
|
||||
},
|
||||
],// y轴的数据
|
||||
realData: [smallCar.toLocaleString(), middleCar.toLocaleString(), bigCar.toLocaleString()]// 真实数据
|
||||
category: category,// x轴的内容
|
||||
seriesDataCar: seriesDataCar, // 入区车流量 万
|
||||
seriesDataRevenue: seriesDataRevenue,// 营收 万
|
||||
realDataCar: realDataCar,// 入区车流量 实际
|
||||
realDataRevenue: realDataRevenue,// 营收 实际
|
||||
yesSeriesDataCar: yesSeriesDataCar,// 入区车流量 万 去年
|
||||
yesSeriesDataRevenue: yesSeriesDataRevenue,// 营收 万 去年
|
||||
yesRealDataCar: yesRealDataCar,// 入区车流量 实际 去年
|
||||
yesRealDataRevenue: yesRealDataRevenue,// 营收 实际 去年
|
||||
currentYear: moment().format('YYYY'), // 当前年份
|
||||
yesYear: moment().subtract(1, 'y').format('YYYY')// 去年年份
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -163,7 +244,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<template>
|
||||
<div class="VehiclesEnteringBox">
|
||||
<SmallTitle :title="'入区车辆趋势'">
|
||||
<SmallTitle :title="'月度车流累计'">
|
||||
<!-- <template #extra>
|
||||
<div class="legendBox" style="display: flex;align-items: center;">
|
||||
<div class="legendItem" style="display: flex;align-items: center;margin-right: 20px;">
|
||||
@ -189,7 +270,7 @@ onBeforeUnmount(() => {
|
||||
</SmallTitle>
|
||||
|
||||
<div class="VehiclesEnteringCharts">
|
||||
<div class="VehiclesEnteringUnit">辆</div>
|
||||
<!-- <div class="VehiclesEnteringUnit">辆</div> -->
|
||||
<div class="VehiclesEntering" id="VehiclesEntering"></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 {
|
||||
width: 100%;
|
||||
height: 25px;
|
||||
// background: rgba(255, 255, 255, 1);
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.noticeIcon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.noticeListBox {
|
||||
height: 26px; // 2条高度,按你需求调整
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
|
||||
.noticeList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.scrolling {
|
||||
animation: scrollAnimation 20s linear infinite;
|
||||
}
|
||||
white-space: nowrap;
|
||||
transition: none;
|
||||
position: relative;
|
||||
|
||||
.noticeItem {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 6px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 15px; // 调整item之间的间距
|
||||
|
||||
.icon {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #fff;
|
||||
transform: rotate(45deg);
|
||||
margin-right: 8px;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: #1989FA;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.contentMessage {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
line-height: 26px;
|
||||
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||
font-weight: 400;
|
||||
font-size: 19px;
|
||||
line-height: 19px;
|
||||
color: #FFFFFF;
|
||||
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">
|
||||
import './noticeListBox.less'
|
||||
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'
|
||||
|
||||
|
||||
@ -11,6 +11,8 @@ let noticeList = reactive<any>([]);
|
||||
let currentIndex = ref<number>(0)
|
||||
// 滚动的计时器
|
||||
let scrollInterval = ref<any>(null)
|
||||
let isScrolling = ref<boolean>(false);
|
||||
let scrollDuration = ref('10s'); // 动态动画时长
|
||||
|
||||
onMounted(async () => {
|
||||
// 获取播报数据
|
||||
@ -52,44 +54,94 @@ const handleGetNoticeList = async () => {
|
||||
|
||||
noticeList.length = 0;
|
||||
list && list.forEach((item: any) => noticeList.push(item));
|
||||
if (list && list.length > 0) {
|
||||
startScrolling()
|
||||
}
|
||||
console.log('noticeList:', noticeList); // 添加这行
|
||||
nextTick(() => {
|
||||
// 数据加载完成后启动滚动
|
||||
startScrolling();
|
||||
})
|
||||
}
|
||||
|
||||
// 开始滚动的方法
|
||||
const startScrolling = () => {
|
||||
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);
|
||||
isScrolling.value = false;
|
||||
nextTick(() => {
|
||||
const listEl = document.querySelector('.noticeList') as HTMLElement;
|
||||
if (listEl) {
|
||||
const originWidth = listEl.scrollWidth / 2;
|
||||
const speed = 100; // px/s
|
||||
const duration = originWidth / speed;
|
||||
scrollDuration.value = duration + 's';
|
||||
|
||||
// 动态插入 keyframes
|
||||
const styleId = 'dynamic-scroll-keyframes';
|
||||
let styleEl = document.getElementById(styleId) as HTMLStyleElement;
|
||||
if (!styleEl) {
|
||||
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 = () => {
|
||||
isScrolling.value = false;
|
||||
if (scrollInterval.value) {
|
||||
clearInterval(scrollInterval.value)
|
||||
scrollInterval.value = null
|
||||
}
|
||||
// if (scrollInterval.value) {
|
||||
// clearInterval(scrollInterval.value)
|
||||
// scrollInterval.value = null
|
||||
// }
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<!-- 横向滚动 -->
|
||||
<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" />
|
||||
<div class="noticeListBox">
|
||||
<div :class="noticeList.length > 1 ? 'noticeList scrolling' : 'noticeList'">
|
||||
@ -101,7 +153,7 @@ const stopScrolling = () => {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-else>
|
||||
<div class="noticeItem" v-for="(item, index) in noticeList" :key="index">
|
||||
<div class="icon"></div>
|
||||
<div class="contentMessage">
|
||||
@ -109,7 +161,7 @@ const stopScrolling = () => {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</template>
|
||||
@ -165,22 +165,27 @@
|
||||
|
||||
.pageTop169 {
|
||||
width: 100vw;
|
||||
height: 48px;
|
||||
background: linear-gradient(180deg, #182950 0%, #18223F 100%);
|
||||
border-bottom: 1px solid #0E789A;
|
||||
// height: 48px;
|
||||
height: 86px;
|
||||
// background: linear-gradient(180deg, #182950 0%, #18223F 100%);
|
||||
// border-bottom: 1px solid #0E789A;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// align-items: center;
|
||||
justify-content: space-between;
|
||||
background-image: url('../../../../assets/image/allPageTopBg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
// padding: 0 30px;
|
||||
|
||||
.centerBox {
|
||||
width: 40%;
|
||||
height: 80px;
|
||||
background-image: url('../../../../assets//image/pageTitle.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
// background-image: url('../../../../assets//image/pageTitle.png');
|
||||
// background-image: url('../../../../assets/image/newPageTitle.png');
|
||||
// background-repeat: no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
// left: 50%;
|
||||
@ -210,19 +215,20 @@
|
||||
|
||||
.leftTabBox {
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
// height: 100%;
|
||||
height: 48px;
|
||||
box-sizing: border-box;
|
||||
padding-left: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// align-items: center;
|
||||
|
||||
.pageTopTabItem {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
font-family: Inter, Inter;
|
||||
font-weight: 400;
|
||||
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
color: #5D6780;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
display: flex;
|
||||
@ -232,8 +238,8 @@
|
||||
}
|
||||
|
||||
.selectPageTopTabItem {
|
||||
color: #FFFFFF;
|
||||
background-image: url('../../../../assets//image/pageTabBg.png');
|
||||
color: #4CA9EF;
|
||||
background-image: url('../../../../assets//image/newSelectPageTop.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
@ -123,7 +123,6 @@ const handleGetNowWeather = async () => {
|
||||
weatherInfo.value = weatherObj
|
||||
}
|
||||
|
||||
|
||||
// 改变页面显示状态
|
||||
const emit = defineEmits<{
|
||||
(e: "handleChangePageType"): void; // 切换页面样式
|
||||
@ -187,8 +186,8 @@ onBeforeUnmount(() => {
|
||||
<div :class="props.pageType === 'left' ? 'centerBox leftBgBox' : 'centerBox'"
|
||||
:style="{ left: props.pageType === 'left' ? '0' : '50%', transform: props.pageType === 'left' ? 'translateX(-50px)' : 'translateX(-50%)' }">
|
||||
<!-- @click="handleChangePageType" -->
|
||||
<img class="pageLogo" :src="cyyLogo" />
|
||||
<span class="pageTitle">云南高速服务区智慧数智大屏</span>
|
||||
<!-- <img class="pageLogo" :src="cyyLogo" /> -->
|
||||
<!-- <span class="pageTitle">云南高速服务区智慧数智大屏</span> -->
|
||||
</div>
|
||||
|
||||
<!-- 最初版的内容 -->
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
.smallTitleBox {
|
||||
height: 28px;
|
||||
// height: 28px;
|
||||
height: 20px;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 10px;
|
||||
background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||
border-left: 1px solid #01F0FE;
|
||||
// padding: 4px 10px;
|
||||
// background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||
// border-left: 1px solid #01F0FE;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 10px;
|
||||
|
||||
.title {
|
||||
font-family: "Microsoft YaHei";
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
font-family: Microsoft YaHei, Microsoft YaHei;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
color: #FFFFFF;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
@ -4,7 +4,7 @@ import './smallTitle.less'
|
||||
// 拿到传入的数据
|
||||
const props = defineProps<{
|
||||
pageType?: any;
|
||||
title: string
|
||||
title?: string
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
@ -42,6 +42,14 @@ import MerchantRatingRanking from './components/MerchantRatingRanking/MerchantRa
|
||||
import HighQualityMerchants from './components/HighQualityMerchants/HighQualityMerchants.vue'
|
||||
import ThisMonthBenefits from './components/ThisMonthBenefits/ThisMonthBenefits.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")
|
||||
@ -92,15 +100,16 @@ const handleChangePageTab = (value: number) => {
|
||||
<!-- 消息轮播框 -->
|
||||
<NoticeListBox :currentService="currentService" />
|
||||
|
||||
<modalTitle :title="'流量趋势'" style="margin-top: 20px;" />
|
||||
<div class="leftContentBox">
|
||||
<!-- <modalTitle :title="'流量趋势'" style="margin-top: 20px;" /> -->
|
||||
<NewBigTitleBox title="流量趋势" style="margin-top: 37px;" />
|
||||
|
||||
<div class="content169LeftContent">
|
||||
<div class="leftContentBoxItem">
|
||||
<!-- 车流断面趋势 -->
|
||||
<TrendOfTrafficFlow :currentService="currentService" />
|
||||
</div>
|
||||
|
||||
<div class="leftContentBoxItem" style="margin-top: 20px;">
|
||||
<div class="leftContentBoxItem" style="margin-top: 30px;">
|
||||
<!-- 入区车辆趋势 -->
|
||||
<VehiclesEntering :currentService="currentService" />
|
||||
</div>
|
||||
@ -112,6 +121,7 @@ const handleChangePageTab = (value: number) => {
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<modalTitle :title="'节假日营收分析'" style="margin-top: 20px;">
|
||||
<template #extra>
|
||||
<div class="FestivalBox">
|
||||
@ -148,7 +158,7 @@ const handleChangePageTab = (value: number) => {
|
||||
<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;" />
|
||||
@ -160,7 +170,7 @@ const handleChangePageTab = (value: number) => {
|
||||
<div class="content1692st" v-if="selectPageTab === 2">
|
||||
<div class="content1692stLeft">
|
||||
<!-- 消息轮播框 -->
|
||||
<NoticeListBox />
|
||||
<NoticeListBox style="margin-top: 20px;" />
|
||||
<!-- 核心经营数据 -->
|
||||
<modalTitle :title="'核心经营数据'" style="margin-top: 20px;" />
|
||||
<CoreBusinessData style="position: relative;z-index: 9;" :noTitle="true" />
|
||||
@ -220,7 +230,7 @@ const handleChangePageTab = (value: number) => {
|
||||
</div>
|
||||
<div class="content1692stRight">
|
||||
<!-- 时间天气等内容 -->
|
||||
<BasicMessageBox />
|
||||
<BasicMessageBox style="margin-top: 19px;" />
|
||||
<!-- 电商模块 -->
|
||||
<modalTitle :title="'电商模块'" style="margin-top: 20px;" />
|
||||
|
||||
@ -291,7 +301,44 @@ const handleChangePageTab = (value: number) => {
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
@ -287,3 +287,93 @@ export async function handleGetCombineBrandList(params: any) {
|
||||
}
|
||||
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 {
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
// height: calc(100% - 48px);
|
||||
height: calc(100% - 86px);
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px 35px;
|
||||
// padding: 0 20px 35px;
|
||||
padding: 0 35px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.content169Left {
|
||||
width: 22%;
|
||||
width: calc((100% - 105px) / 4);
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
box-sizing: border-box;
|
||||
padding-top: 20px;
|
||||
padding-top: 21px;
|
||||
// padding-top: 20px;
|
||||
|
||||
.content169LeftContent {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 21px 11px;
|
||||
}
|
||||
|
||||
.leftContentBox {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 11px 0;
|
||||
background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
|
||||
// backdrop-filter: blur(10px);
|
||||
/* 高斯模糊效果 */
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
// -webkit-backdrop-filter: blur(10px);
|
||||
/* Safari 兼容 */
|
||||
}
|
||||
|
||||
@ -300,7 +309,7 @@
|
||||
}
|
||||
|
||||
.content169Center {
|
||||
width: 47%;
|
||||
width: calc((100% - 105px) / 4 * 2 + 35px);
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-top: 66px;
|
||||
@ -309,21 +318,21 @@
|
||||
}
|
||||
|
||||
.content169Right {
|
||||
width: 22%;
|
||||
width: calc((100% - 105px) / 4);
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
box-sizing: border-box;
|
||||
padding-top: 20px;
|
||||
padding-top: 21px;
|
||||
|
||||
.rightContentBox {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 11px 0;
|
||||
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 兼容 */
|
||||
}
|
||||
|
||||
@ -335,7 +344,7 @@
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
box-sizing: border-box;
|
||||
padding: 20px 35px;
|
||||
padding: 0 20px 35px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -374,7 +383,7 @@
|
||||
width: 22%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-top: 46px;
|
||||
padding-top: 66px;
|
||||
|
||||
.left4stContent {
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||