This commit is contained in:
ylj20011123 2025-06-25 19:36:01 +08:00
parent d829c7bc93
commit b1da1d2bd6
60 changed files with 1339 additions and 1079 deletions

View File

@ -1,21 +1,24 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8" /> <head>
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="icon" type="image/svg+xml" href="/YNIcon.png" />
<title>AI全景图</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/"> <!-- 确保这里匹配你的部署路径 --> <title>云南高速服务区智慧数智大屏</title>
</head> <base href="/"> <!-- 确保这里匹配你的部署路径 -->
<body> </head>
<div id="app"></div>
</body> <body>
<script type="module" src="/src/main.ts"></script> <div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script> </body>
<style> <script type="module" src="/src/main.ts"></script>
*{ <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
margin: 0; <style>
padding: 0; * {
} margin: 0;
</style> padding: 0;
}
</style>
</html> </html>

15
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@antv/l7": "^2.22.3", "@antv/l7": "^2.22.3",
"@antv/l7-maps": "^2.22.3", "@antv/l7-maps": "^2.22.3",
"axios": "^1.7.7", "axios": "^1.7.7",
"crypto-js": "^4.2.0",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"element-plus": "^2.8.8", "element-plus": "^2.8.8",
"marked": "^15.0.6", "marked": "^15.0.6",
@ -21,6 +22,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.15.0", "@eslint/js": "^9.15.0",
"@types/crypto-js": "^4.2.2",
"@types/node": "^22.9.0", "@types/node": "^22.9.0",
"@vitejs/plugin-vue": "^5.2.0", "@vitejs/plugin-vue": "^5.2.0",
"@vue/eslint-config-typescript": "^14.1.3", "@vue/eslint-config-typescript": "^14.1.3",
@ -827,6 +829,13 @@
"url": "https://opencollective.com/turf" "url": "https://opencollective.com/turf"
} }
}, },
"node_modules/@types/crypto-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.6", "version": "1.0.6",
"license": "MIT" "license": "MIT"
@ -1624,6 +1633,12 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"license": "MIT"
},
"node_modules/csscolorparser": { "node_modules/csscolorparser": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",

View File

@ -12,6 +12,7 @@
"@antv/l7": "^2.22.3", "@antv/l7": "^2.22.3",
"@antv/l7-maps": "^2.22.3", "@antv/l7-maps": "^2.22.3",
"axios": "^1.7.7", "axios": "^1.7.7",
"crypto-js": "^4.2.0",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"element-plus": "^2.8.8", "element-plus": "^2.8.8",
"marked": "^15.0.6", "marked": "^15.0.6",
@ -22,6 +23,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.15.0", "@eslint/js": "^9.15.0",
"@types/crypto-js": "^4.2.2",
"@types/node": "^22.9.0", "@types/node": "^22.9.0",
"@vitejs/plugin-vue": "^5.2.0", "@vitejs/plugin-vue": "^5.2.0",
"@vue/eslint-config-typescript": "^14.1.3", "@vue/eslint-config-typescript": "^14.1.3",

BIN
public/YNIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -117,7 +117,10 @@ const handleGoMounted = async () => {
barWidth: 10, barWidth: 10,
itemStyle: { itemStyle: {
borderRadius: [3, 3, 0, 0], borderRadius: [3, 3, 0, 0],
color: '#008CFF' // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#46B8F3' }, //
{ offset: 1, color: '#1A4AF6' } //
])
}, },
label: { label: {
show: true, show: true,
@ -137,7 +140,7 @@ const handleGoMounted = async () => {
barWidth: 10, barWidth: 10,
itemStyle: { itemStyle: {
borderRadius: [3, 3, 0, 0], borderRadius: [3, 3, 0, 0],
color: '#69BCFF' // color: "#3CD495"
} }
} }
], ],

View File

@ -0,0 +1,40 @@
.AreaLegendBox {
width: 100%;
height: 47px;
// background-image: url('../../../../assets/image/AreaLegendBg.png');
// background-repeat: no-repeat;
// background-size: 100% 100%;
.AreaLegendBoxList {
width: 100%;
height: 100%;
display: flex;
align-items: center;
.AreaLegendBoxItem {
display: flex;
align-items: center;
box-sizing: border-box;
padding-left: 30px;
.AreaLegendBoxItemIcon {
width: 20px;
height: 20px;
margin-right: 8px;
border-radius: 50%;
}
.AreaLegendBoxItemLabel {
font-family: OPPOSans, OPPOSans;
font-weight: normal;
font-size: 14px;
color: #E4F3FF;
line-height: 18px;
text-align: left;
font-style: normal;
}
}
}
}

View File

@ -0,0 +1,40 @@
<script setup lang="ts">
import { watch } from 'vue';
import './AreaLegend.less'
//
let colorList1 = [
"#4F83FA",
"#A39BFF",
"#63B6FC",
"#88DFB2",
"#88C3BF",
"#d9dcf3",
];
const props = defineProps<{
mapLegend?: any
}>();
watch(
() => props.mapLegend,
(newVal, oldVal) => {
console.log('newValnewValnewVal', newVal);
},
{ deep: true }
);
</script>
<template>
<div class="AreaLegendBox">
<div class="AreaLegendBoxList" v-if="props.mapLegend && props.mapLegend.length > 0">
<div class="AreaLegendBoxItem" :style="{ width: `calc(100% / ${props.mapLegend.length})` }"
v-for="(item, index) in props.mapLegend" :key="index">
<div class="AreaLegendBoxItemIcon" :style="{ background: item.value }"></div>
<div class="AreaLegendBoxItemLabel">{{ item.label }}</div>
</div>
</div>
</div>
</template>

View File

@ -8,8 +8,8 @@
.brandChartBox { .brandChartBox {
width: 100%; width: 100%;
height: 132px; height: 220px;
margin-top: 35px; margin-top: 15px;
position: relative; position: relative;
} }
@ -73,13 +73,13 @@
.brandItem { .brandItem {
width: 100%; width: 100%;
height: 86px; height: 86px;
margin-bottom: 10px;
background-color: #0F1625; background-color: #0F1625;
box-sizing: border-box; box-sizing: border-box;
padding: 10px; padding: 10px;
display: flex; display: flex;
align-items: center; align-items: center;
border-radius: 8px; border-radius: 8px;
margin-bottom: 5px;
.brandLeft { .brandLeft {
width: 66px; width: 66px;

View File

@ -69,7 +69,7 @@ const handleGoMounted = async () => {
const option = { const option = {
legend: { legend: {
orient: 'vertical', // orient: 'vertical', //
left: '50%', // 5% left: 200, // 5%
top: 'center', // top: 'center', //
itemWidth: 12, // itemWidth: 12, //
itemHeight: 12, // itemHeight: 12, //
@ -108,7 +108,7 @@ const handleGoMounted = async () => {
{ {
name: 'Access From', name: 'Access From',
type: 'pie', type: 'pie',
radius: ['0%', '100%'], radius: ['0%', '70%'],
center: ['25%', '50%'], center: ['25%', '50%'],
avoidLabelOverlap: false, avoidLabelOverlap: false,
itemStyle: { itemStyle: {
@ -132,6 +132,8 @@ const handleGoMounted = async () => {
myChart.setOption(option); myChart.setOption(option);
myChart.resize(); myChart.resize();
window.addEventListener('resize', resizeChart); window.addEventListener('resize', resizeChart);
handleBrandTabList()
} }
// //
@ -189,6 +191,18 @@ const handleGetData = async () => {
// }) // })
// await handleGetTableData(tableList[0].value)
let res: any = {
category: category,// x
pieData: pieData,// y
// realData: realData//
}
return res
}
//
const handleBrandTabList = async () => {
let BrandTab = sessionStorage.getItem('BrandTab') let BrandTab = sessionStorage.getItem('BrandTab')
let BrandTabList = sessionStorage.getItem('BrandTabList') let BrandTabList = sessionStorage.getItem('BrandTabList')
let listData: any = [] let listData: any = []
@ -197,6 +211,7 @@ const handleGetData = async () => {
let list: any = JSON.parse(BrandTabList) let list: any = JSON.parse(BrandTabList)
allBrandObjData.value = obj allBrandObjData.value = obj
brandListData.value = obj[list[0].value] brandListData.value = obj[list[0].value]
tabList.value = list
} else { } else {
listData = await handleGetBusinessTradeTree({ listData = await handleGetBusinessTradeTree({
PROVINCE_CODE: "530000", PROVINCE_CODE: "530000",
@ -211,6 +226,7 @@ const handleGetData = async () => {
tableList.push({ label: item.AUTOSTATISTICS_NAME, value: item.AUTOSTATISTICS_ID }) tableList.push({ label: item.AUTOSTATISTICS_NAME, value: item.AUTOSTATISTICS_ID })
}) })
} }
console.log('tableListtableListtableListtableListtableList', tableList);
tabList.value = tableList tabList.value = tableList
sessionStorage.setItem("BrandTabList", JSON.stringify(tableList)) sessionStorage.setItem("BrandTabList", JSON.stringify(tableList))
@ -233,19 +249,6 @@ const handleGetData = async () => {
brandListData.value = obj[tableList[0].value] brandListData.value = obj[tableList[0].value]
} }
// await handleGetTableData(tableList[0].value)
let res: any = {
category: category,// x
pieData: pieData,// y
// realData: realData//
}
return res
} }
// //

View File

@ -1,5 +1,13 @@
.BusinessCaseBox { .BusinessCaseBox {
width: 100%; width: 100%;
position: relative;
height: 425px;
.BusinessCaseBoxContent {
position: absolute;
top: 15px;
left: 0;
}
.BusinessCaseTabBox { .BusinessCaseTabBox {
// width: 100%; // width: 100%;
@ -262,13 +270,12 @@
.featureAnalysisBox { .featureAnalysisBox {
width: 100%; width: 100%;
height: 390px; height: 425px;
} }
.featureAnalysisBottom { .featureAnalysisBottom {
width: 100%; width: 100%;
height: 390px; height: 425px;
margin-top: 18px;
} }
} }
} }

View File

@ -248,7 +248,7 @@ const handleShowData = async (value: number) => {
const option = { const option = {
legend: { legend: {
top: 15, top: 15,
right: 10, right: 0,
textStyle: { textStyle: {
color: '#ffffff' // color: '#ffffff' //
} }
@ -290,7 +290,7 @@ const handleShowData = async (value: number) => {
}, },
nameTextStyle: { nameTextStyle: {
color: '#fff', // color: '#fff', //
padding: [0, 0, 0, 30] // padding: [0, 0, 35, 30] //
} }
}, },
series: [{ series: [{
@ -315,7 +315,7 @@ const handleShowData = async (value: number) => {
left: '0', // left: '0', //
right: '0', // right: '0', //
bottom: '0', // bottom: '0', //
top: '50', // top: '120', //
containLabel: true // grid containLabel: true // grid
}, },
}; };
@ -334,7 +334,7 @@ const handleShowBottomData = async (res: any) => {
const option = { const option = {
legend: { legend: {
top: 0, // top: 10, //
right: 0, right: 0,
itemWidth: 20, // itemWidth: 20, //
itemHeight: 10, // itemHeight: 10, //
@ -383,7 +383,7 @@ const handleShowBottomData = async (res: any) => {
left: '10', // left: '10', //
right: '10', // right: '10', //
bottom: '0', bottom: '0',
top: '30', top: '80',
containLabel: true containLabel: true
}, },
series: [ series: [
@ -454,8 +454,9 @@ onBeforeUnmount(() => {
<template> <template>
<div class="BusinessCaseBox"> <div class="BusinessCaseBox">
<SmallTitle title="营收特征"> <div class="BusinessCaseBoxContent">
<!-- <template #extra> <SmallTitle title="营收特征">
<!-- <template #extra>
<div class="BusinessCaseTabBox"> <div class="BusinessCaseTabBox">
<div :class="selectTab === item.value ? 'BusinessCaseItem selectBusinessCaseItem' : 'BusinessCaseItem'" <div :class="selectTab === item.value ? 'BusinessCaseItem selectBusinessCaseItem' : 'BusinessCaseItem'"
v-for="(item, index) in tabList" :key="index" @click="handleChangeTab(item.value)"> v-for="(item, index) in tabList" :key="index" @click="handleChangeTab(item.value)">
@ -463,7 +464,9 @@ onBeforeUnmount(() => {
</div> </div>
</div> </div>
</template> --> </template> -->
</SmallTitle> </SmallTitle>
</div>
<!-- 营收同比 --> <!-- 营收同比 -->
<div class="BusinessCaseRevenueYOY" v-if="false"> <div class="BusinessCaseRevenueYOY" v-if="false">

View File

@ -5,9 +5,9 @@
.BusinessStructureCharts { .BusinessStructureCharts {
width: 100%; width: 100%;
height: 210px; height: 220px;
box-sizing: border-box; box-sizing: border-box;
padding: 52px 0 0 31px; // padding: 52px 0 0 31px;
.BusinessStructureUnit { .BusinessStructureUnit {
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
@ -23,7 +23,7 @@
width: 100%; width: 100%;
// width: 132px; // width: 132px;
height: 132px; height: 220px;
display: inline-block; display: inline-block;
} }

View File

@ -87,7 +87,7 @@ const handleGoMounted = async () => {
{ {
name: 'Access From', name: 'Access From',
type: 'pie', type: 'pie',
radius: ['85%', '100%'], radius: ['55%', '70%'],
center: ['20%', '50%'], // center: ['20%', '50%'], //
avoidLabelOverlap: false, avoidLabelOverlap: false,
itemStyle: { itemStyle: {
@ -107,7 +107,7 @@ const handleGoMounted = async () => {
], ],
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 160, left: 200,
top: 'center', top: 'center',
align: 'left', align: 'left',
itemGap: 10, itemGap: 10,
@ -160,8 +160,8 @@ const handleGetData = async () => {
const req: any = { const req: any = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'), // StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
// StatisticsDate: '2025-04-30', StatisticsDate: '2025-04-30',
BusinessTradeIds: -1, BusinessTradeIds: -1,
ServerpartId: props.currentService?.SERVERPART_ID || "" ServerpartId: props.currentService?.SERVERPART_ID || ""
} }

View File

@ -127,12 +127,20 @@
padding: 3px 55px; padding: 3px 55px;
.newCoreBusinessItemLabel { .newCoreBusinessItemLabel {
font-family: Microsoft YaHei, Microsoft YaHei; // font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold; // font-weight: bold;
font-size: 12px; // font-size: 12px;
color: #C1ECF7; // color: #C1ECF7;
text-align: center; // text-align: center;
// font-style: normal;
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 18px;
color: #FDFEFF;
line-height: 29px;
text-align: left;
font-style: normal; font-style: normal;
} }
.newCoreBusinessItemValueBox { .newCoreBusinessItemValueBox {
@ -145,9 +153,16 @@
font-weight: 400; font-weight: 400;
font-size: 25px; font-size: 25px;
line-height: 30px; line-height: 30px;
color: #48A9F6; // color: #48A9F6;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
background: linear-gradient(180deg, #32E8FA, #A9EFDB);
/* 可以调整渐变方向和颜色 */
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
} }
.newCoreBusinessItemUnit { .newCoreBusinessItemUnit {

View File

@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import moment from 'moment';
import { handleGetFiveNumber } from '../../../../options/serveice'; import { handleGetFiveNumber } from '../../../../options/serveice';
import { handleGetRealData } from '../../service'; import { handleGetMonthlyBusinessRevenue, handleGetRealData } from '../../service';
import CenterTitle from '../CenterTitle/CenterTitle.vue'; import CenterTitle from '../CenterTitle/CenterTitle.vue';
import './CoreBusinessData.less' import './CoreBusinessData.less'
import { onMounted, onBeforeUnmount, ref, reactive, watch } from 'vue'; import { onMounted, onBeforeUnmount, ref, reactive, watch } from 'vue';
@ -148,16 +149,85 @@ const handleGetMapRealData = async () => {
sessionStorage.setItem("CoreBusinessDataAI", JSON.stringify(aiObj)) sessionStorage.setItem("CoreBusinessDataAI", JSON.stringify(aiObj))
} }
//
let monthReq: any = {
ProvinceCode: "530000",
StartMonth: moment().startOf('y').format('YYYYMM'),
EndMonth: moment().format('YYYYMM'),
DataType: "1000,2000,3000,4000,5000",
ServerpartId: ""
}
let CoreBusinessDataMonth = sessionStorage.getItem('CoreBusinessDataMonth')
let monthData: any = []
if (CoreBusinessDataMonth) {
monthData = JSON.parse(CoreBusinessDataMonth)
} else {
monthData = await handleGetMonthlyBusinessRevenue(monthReq)
sessionStorage.setItem("CoreBusinessDataMonth", JSON.stringify(monthData))
}
let aiObjMonthSum: any = {}
if (monthData && monthData.length > 0) {
monthData.forEach((item: any) => {
let aiObjMonth: any = {}
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
//
if (subItem.DataType === 1000) {
let obj: any = {
value: handleGetPonitFixed(subItem.RevenueAmount),
unit: subItem.totalAmountUnit
}
aiObjMonth["门店营收"] = `${obj.value}万元`
} else if (subItem.DataType === 2000) {
//
let obj: any = {
value: handleGetPonitFixed(subItem.RevenueAmount),
unit: subItem.totalCountUnit
}
aiObjMonth["油品消耗"] = `${obj.value}万元`
} else if (subItem.DataType === 3000) {
//
let obj: any = {
value: handleGetPonitFixed(subItem.RevenueAmount),
}
aiObjMonth["加水量"] = `${obj.value}万元`
} else if (subItem.DataType === 4000) {
// 尿
let obj: any = {
value: handleGetPonitFixed(subItem.RevenueAmount),
unit: subItem.totalCountUnit
}
aiObjMonth["尿素"] = `${obj.value}万元`
} else if (subItem.DataType === 5000) {
//
let obj: any = {
value: handleGetPonitFixed(subItem.RevenueAmount),
unit: subItem.totalTicketUnit
}
aiObjMonth["充电次数"] = `${obj.value}万元`
}
})
}
aiObjMonthSum[`${item.StatisticsMonth}`] = aiObjMonth
})
}
let CoreBusinessDataMonthAI = sessionStorage.getItem('CoreBusinessDataMonthAI')
if (CoreBusinessDataMonthAI) { } else {
sessionStorage.setItem("CoreBusinessDataMonthAI", JSON.stringify(aiObjMonthSum))
}
} }
// //
const handleGetPonitFixed = (str: string) => { const handleGetPonitFixed = (str: string) => {
const num = parseFloat(str); // number const num = parseFloat(str); // number
return isNaN(num) ? "0.00" : num.toFixed(2); return isNaN(num) ? "0.00" : num.toFixed(2);
} }
</script> </script>

View File

@ -2,22 +2,27 @@
width: calc((100% - 28px) / 4); width: calc((100% - 28px) / 4);
display: inline-block; display: inline-block;
height: 210px; height: 210px;
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
padding: 10px 10px 18px;
background-size: 100% 100%;
box-sizing: border-box;
position: relative;
.SmallTitleContent {
position: absolute;
}
.CustomerAgeGroupCharts { .CustomerAgeGroupCharts {
width: 100%; width: 100%;
height: 182px; height: 200px;
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%); // background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
// box-sizing: border-box; // box-sizing: border-box;
// padding: 20px 20px 18px; // padding: 20px 20px 18px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
// margin-top: 5px; // margin-top: 10px;
box-sizing: border-box;
padding: 10px 10px 18px;
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
.CustomerAgeGroupUnit { .CustomerAgeGroupUnit {
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
@ -33,7 +38,7 @@
.CustomerAgeGroup { .CustomerAgeGroup {
width: 100%; width: 100%;
height: 154px; height: 200px;
} }
.legendBox { .legendBox {

View File

@ -94,7 +94,7 @@ onMounted(async () => {
left: '10', // left: '10', //
right: '10', // right: '10', //
bottom: '20', bottom: '20',
top: '30', top: '60',
containLabel: true containLabel: true
}, },
series: [ series: [
@ -158,8 +158,10 @@ onMounted(async () => {
], ],
legend: { legend: {
data: ['男性', '女性'], // seriesname data: ['男性', '女性'], // seriesname
bottom: 0, // 10px top: -0,
left: 'center', // right: 0,
// bottom: 0, // 10px
// left: 'center', //
itemWidth: 12, // itemWidth: 12, //
itemHeight: 12, // itemHeight: 12, //
itemGap: 20, // itemGap: 20, //
@ -277,7 +279,9 @@ onUnmounted(() => {
<template> <template>
<div class="CustomerAgeGroupBox"> <div class="CustomerAgeGroupBox">
<SmallTitle :title="'年龄'" :pageType="'center'"></SmallTitle> <div class="SmallTitleContent">
<SmallTitle :title="'年龄'"></SmallTitle>
</div>
<div class="CustomerAgeGroupCharts"> <div class="CustomerAgeGroupCharts">
<!-- <div class="CustomerAgeGroupUnit">万人</div> --> <!-- <div class="CustomerAgeGroupUnit">万人</div> -->

View File

@ -2,7 +2,7 @@
width: 100%; width: 100%;
// height: 250px; // height: 250px;
box-sizing: border-box; box-sizing: border-box;
padding: 20px 11px 0; // padding: 20px 11px 0;
// padding: 35px 20px 40px; // 老的 // padding: 35px 20px 40px; // 老的
// padding: 20px 10px 30px; // padding: 20px 10px 30px;
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%); // background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
@ -13,7 +13,7 @@
.FestivalRevenueSumInfo { .FestivalRevenueSumInfo {
width: 100%; width: 100%;
height: 260px; height: 316px;
// margin-top: 20px; margin-top: 30px;
} }
} }

View File

@ -24,6 +24,9 @@ echarts.use([
CanvasRenderer CanvasRenderer
]); ]);
let bigDataColor: any = ["#007CFF", "#00FFFF"]
let smallDataColor: any = ["#FF2F7C", "#417EE0", "#00BE8F", "#4E6384", "#FFD900", "#7D4CD2", "#00FF7C", "#FF9500"]
let myChart: echarts.ECharts; let myChart: echarts.ECharts;
@ -67,7 +70,7 @@ const handleGoMounted = async () => {
const option = { const option = {
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)' formatter: '{b}'
}, },
legend: [ // 使legend legend: [ // 使legend
// //
@ -91,7 +94,8 @@ const handleGoMounted = async () => {
orient: 'horizontal', orient: 'horizontal',
top: 'bottom', top: 'bottom',
left: 'center', left: 'center',
textStyle: { color: '#fff' } textStyle: { color: '#fff' },
padding: [0, 0, 0, 0], //
} }
], ],
series: [ series: [
@ -99,9 +103,12 @@ const handleGoMounted = async () => {
{ {
name: '外圈数据', name: '外圈数据',
type: 'pie', type: 'pie',
radius: ['50%', '65%'], radius: ['55%', '65%'],
center: ['50%', '35%'], // center: ['50%', '35%'], //
data: res.bigData, data: res.bigData.map((item: any, index: any) => ({
...item,
itemStyle: { color: bigDataColor[index] } //
})),
// data: [ // data: [
// { value: 335, name: 'A' }, // { value: 335, name: 'A' },
// { value: 310, name: 'B' }, // { value: 310, name: 'B' },
@ -114,9 +121,12 @@ const handleGoMounted = async () => {
{ {
name: '内圈数据', name: '内圈数据',
type: 'pie', type: 'pie',
radius: ['0%', '30%'], radius: ['0%', '40%'],
center: ['50%', '35%'], // center: ['50%', '35%'], //
data: res.smallData, data: res.smallData.map((item: any, index: any) => ({
...item,
itemStyle: { color: smallDataColor[index] } //
})),
// data: [ // data: [
// { value: 100, name: '1' }, // { value: 100, name: '1' },
// { value: 200, name: '2' }, // { value: 200, name: '2' },

View File

@ -2,16 +2,25 @@
width: calc((100% - 28px) / 4); width: calc((100% - 28px) / 4);
display: inline-block; display: inline-block;
height: 210px; height: 210px;
position: relative;
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
// padding: 20px 54px 18px;
padding: 10px;
.GenderCustomerGroupBoxTitle {
position: absolute;
top: 10px;
left: 10px;
}
.GenderCustomerGroupCharts { .GenderCustomerGroupCharts {
width: 100%; width: 100%;
height: 182px; height: 200px;
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%); // background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
padding: 20px 54px 18px;
.GenderCustomerGroupUnit { .GenderCustomerGroupUnit {
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
@ -26,11 +35,11 @@
.GenderCustomerGroupContent { .GenderCustomerGroupContent {
width: 100%; width: 100%;
height: 145px; height: 200px;
.GenderCustomerGroup { .GenderCustomerGroup {
width: 100%; width: 100%;
height: 145px; height: 200px;
} }
.legendBox { .legendBox {

View File

@ -43,7 +43,7 @@ onMounted(async () => {
// center20%50% // center20%50%
const centerX = width * 0.5; const centerX = width * 0.5;
const centerY = height * 0.4; const centerY = height * 0.65;
const option = { const option = {
@ -68,11 +68,11 @@ onMounted(async () => {
type: 'image', type: 'image',
style: { style: {
image: GenderCenter, image: GenderCenter,
width: 43, width: 60,
height: 43 height: 60
}, },
left: centerX - 21.5, left: centerX - 30,
top: centerY - 21.5, top: centerY - 30,
z: 10 z: 10
} }
] ]
@ -81,8 +81,8 @@ onMounted(async () => {
{ {
name: 'Access From', name: 'Access From',
type: 'pie', type: 'pie',
radius: ['55%', '70%'], radius: ['60%', '70%'],
center: ['50%', '40%'], // [, ] center: ['50%', '65%'], // [, ]
avoidLabelOverlap: false, avoidLabelOverlap: false,
itemStyle: { itemStyle: {
color: function (params: any) { color: function (params: any) {
@ -103,8 +103,10 @@ onMounted(async () => {
], ],
legend: { legend: {
data: res.legendData, data: res.legendData,
bottom: 0, // bottom: 0,
left: 'center', // left: 'center',
top: 0,
right: 0,
orient: 'horizontal', // orient: 'horizontal', //
textStyle: { textStyle: {
color: '#fff' color: '#fff'
@ -186,7 +188,9 @@ onBeforeUnmount(() => {
<template> <template>
<div class="GenderCustomerGroupBox"> <div class="GenderCustomerGroupBox">
<SmallTitle :title="'性别'" :pageType="'center'"></SmallTitle> <div class="GenderCustomerGroupBoxTitle">
<SmallTitle :title="'性别'"></SmallTitle>
</div>
<div class="GenderCustomerGroupCharts"> <div class="GenderCustomerGroupCharts">
<!-- <div class="GenderCustomerGroupUnit">万元</div> --> <!-- <div class="GenderCustomerGroupUnit">万元</div> -->

View File

@ -9,7 +9,7 @@
.MallOrderStatistics { .MallOrderStatistics {
width: 100%; width: 100%;
height: 153px; height: 180px;
margin-top: 10px; margin-top: 10px;
} }

View File

@ -92,7 +92,7 @@
.OverviewOfServiceAreaBusyContent { .OverviewOfServiceAreaBusyContent {
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
padding: 10px 11px 0; padding: 20px 11px 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;

View File

@ -33,6 +33,8 @@ let currentService = ref<any>()
const props = defineProps<{ const props = defineProps<{
selectPointServicePart?: any selectPointServicePart?: any
mapClickComeForm?: string
noticeMessageObj?: any
}>(); }>();
@ -128,6 +130,9 @@ const handleGetServiceList = async () => {
SPREGIONTYPECOLORList = SPREGIONTYPECOLORLIST; SPREGIONTYPECOLORList = SPREGIONTYPECOLORLIST;
SPREGIONTYPECOLOR.value = SPREGIONTYPETYPEObj; SPREGIONTYPECOLOR.value = SPREGIONTYPETYPEObj;
emit("handleGetMapLegend", SPREGIONTYPECOLORLIST)
} }
} }
@ -151,7 +156,7 @@ const handleAllServiceMarkedPoint = async () => {
}, },
}); });
pointLayer.shape("circle"); pointLayer.shape("circle");
pointLayer.size(10); pointLayer.size(8);
pointLayer.color("SPREGIONTYPETYPE", (value) => { pointLayer.color("SPREGIONTYPETYPE", (value) => {
return colorList1[value]; return colorList1[value];
}); });
@ -159,12 +164,19 @@ const handleAllServiceMarkedPoint = async () => {
opacity: 0.6, opacity: 0.6,
}); });
pointLayer.on("mousemove", (ev: any) => { pointLayer.on("mousemove", (ev: any) => {
console.log('props?.noticeMessageObj', props?.noticeMessageObj);
const detail: any = ev.feature; const detail: any = ev.feature;
console.log('detail.SERVERPART_ID', detail.SERVERPART_ID);
hoverPoint.value.style.maxWidth = `500px`;
hoverPoint.value.style.top = `${ev.y + 5}px`; hoverPoint.value.style.top = `${ev.y + 5}px`;
hoverPoint.value.style.left = `${ev.x + 5}px`; hoverPoint.value.style.left = `${ev.x + 5}px`;
hoverPoint.value.style.transform = `translate(-100%,-100%)`;
hoverPoint.value.style.display = "block"; hoverPoint.value.style.display = "block";
hoverPoint.value.innerHTML = `<div> hoverPoint.value.innerHTML = `<div>
<div>${detail?.SERVERPART_NAME || ""}</div> ${props?.mapClickComeForm === 'notice' ? `<div>招商信息:</div><div>${props?.noticeMessageObj && props?.noticeMessageObj[Number(detail.SERVERPART_ID)] ? props?.noticeMessageObj[Number(detail.SERVERPART_ID)] : ""}</div>` : `<div>${detail?.SERVERPART_NAME || ""}</div>`}
</div>` </div>`
}) })
@ -182,7 +194,7 @@ const handleAllServiceMarkedPoint = async () => {
pointLayer.on("unclick", () => { pointLayer.on("unclick", () => {
handleLayerToDefault(); handleLayerToDefault();
emit("handleChangeComeForm", "")
}); });
@ -226,6 +238,9 @@ const handleHighLightServerpartIds = (idList: number[]) => {
handleDeleteLayer("lightPointLayer"); handleDeleteLayer("lightPointLayer");
handleAllPonitToGray() handleAllPonitToGray()
console.log('idList', idList);
let selectServerpartDetailList: any = [] let selectServerpartDetailList: any = []
if (defaultServerPartList && defaultServerPartList.length > 0) { if (defaultServerPartList && defaultServerPartList.length > 0) {
defaultServerPartList.forEach((item: any) => { defaultServerPartList.forEach((item: any) => {
@ -266,8 +281,10 @@ const handleClickPointLayer = async (detail: any) => {
if (detail.SERVERPART_ID === currentService.value?.SERVERPART_ID) { if (detail.SERVERPART_ID === currentService.value?.SERVERPART_ID) {
} else { } else {
handleDeleteLayer("lightPointLayer"); if (props.mapClickComeForm !== 'notice') {
handleAddSelect(detail) handleDeleteLayer("lightPointLayer");
handleAddSelect(detail)
}
} }
} }
@ -282,7 +299,7 @@ const handleAddSelect = (detail: any) => {
const lightPointLayer = new PointLayer({}); const lightPointLayer = new PointLayer({});
lightPointLayer.name = "lightPointLayer"; lightPointLayer.name = "lightPointLayer";
lightPointLayer.shape("circle"); lightPointLayer.shape("circle");
lightPointLayer.size(15); lightPointLayer.size(12);
lightPointLayer.color("#efff19"); lightPointLayer.color("#efff19");
lightPointLayer.style({ lightPointLayer.style({
opacity: 0.6, opacity: 0.6,
@ -294,10 +311,8 @@ const handleAddSelect = (detail: any) => {
y: "SERVERPART_Y", y: "SERVERPART_Y",
}, },
}); });
scene.value.addLayer(lightPointLayer); scene.value.addLayer(lightPointLayer);
let allLayers: any = scene.value.getLayers(); let allLayers: any = scene.value.getLayers();
} }
@ -350,6 +365,8 @@ const handleLayerToDefault = () => {
const emit = defineEmits<{ const emit = defineEmits<{
(e: "handleGetCurrentService", obj: any): void; (e: "handleGetCurrentService", obj: any): void;
(e: "handleMapToChangeNotice"): void; (e: "handleMapToChangeNotice"): void;
(e: "handleGetMapLegend", list: any): void;
(e: "handleChangeComeForm", str: string): void;
}>(); }>();
@ -357,7 +374,7 @@ const emit = defineEmits<{
<template> <template>
<div class="PageMapBox"> <div class="PageMapBox" style="position: relative;">
<div class="mapContent" id="map"></div> <div class="mapContent" id="map"></div>
</div> </div>
</template> </template>

View File

@ -3,17 +3,23 @@
width: calc((100% - 28px) / 4 * 2); width: calc((100% - 28px) / 4 * 2);
display: inline-block; display: inline-block;
height: 210px; height: 210px;
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
// padding: 11px 20px 16px;
padding: 10px;
.PreferenceTypeBoxContent {
position: absolute;
}
.PreferenceTypeCharts { .PreferenceTypeCharts {
width: 100%; width: 100%;
height: 182px; height: 200px;
// background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%); // background: linear-gradient(0deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
background-image: url('../../../../assets/image/smallModalBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
padding: 11px 20px 16px;
.PreferenceTypeUnit { .PreferenceTypeUnit {
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";

View File

@ -54,8 +54,8 @@ onMounted(async () => {
indicator: res.category, indicator: res.category,
shape: 'circle', shape: 'circle',
splitNumber: 5, splitNumber: 5,
radius: '40%', // radius: '60%', //
center: ['50%', '45%'], // 2. center: ['50%', '65%'], // 2.
axisName: { axisName: {
color: 'rgb(255, 255, 255)', color: 'rgb(255, 255, 255)',
padding: 10 padding: 10
@ -120,8 +120,10 @@ onMounted(async () => {
textStyle: { textStyle: {
color: '#fff' color: '#fff'
}, },
bottom: -5, top: 0,
left: 'center', right: 0
// bottom: -5,
// left: 'center',
}, },
}; };
@ -240,7 +242,9 @@ onBeforeUnmount(() => {
<template> <template>
<div class="PreferenceTypeBox"> <div class="PreferenceTypeBox">
<SmallTitle :title="'偏好类型'" :pageType="'center'"></SmallTitle> <div class="PreferenceTypeBoxContent">
<SmallTitle :title="'偏好类型'"></SmallTitle>
</div>
<div class="PreferenceTypeCharts"> <div class="PreferenceTypeCharts">
<!-- <div class="PreferenceTypeUnit">万元</div> --> <!-- <div class="PreferenceTypeUnit">万元</div> -->

View File

@ -49,22 +49,22 @@
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
// padding: 30px; // padding: 30px;
padding: 25px 26px 20px 31px; // padding: 25px 26px 20px 31px;
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 22px;
.RegionalRevenueChartsContent { .RegionalRevenueChartsContent {
width: 100%; width: 100%;
// height: 132px; // height: 132px;
height: 210px; height: 220px;
display: flex; display: flex;
align-items: center; align-items: center;
.RegionalRevenue { .RegionalRevenue {
// width: 132px; // width: 132px;
width: 100%; width: 100%;
height: 132px; height: 220px;
} }
.RegionalRevenueDataBoxList { .RegionalRevenueDataBoxList {

View File

@ -79,7 +79,7 @@ const handleGoMounted = async () => {
{ {
name: 'Access From', name: 'Access From',
type: 'pie', type: 'pie',
radius: ['0%', '100%'], radius: ['0%', '70%'],
center: ['20%', '50%'], // center: ['20%', '50%'], //
avoidLabelOverlap: false, avoidLabelOverlap: false,
itemStyle: { itemStyle: {
@ -99,7 +99,7 @@ const handleGoMounted = async () => {
], ],
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 160, left: 200,
top: 'center', top: 'center',
align: 'left', align: 'left',
itemGap: 10, itemGap: 10,
@ -233,7 +233,7 @@ onBeforeUnmount(() => {
<template> <template>
<div class="RegionalRevenueBox"> <div class="RegionalRevenueBox">
<SmallTitle :title="'区域营收占比'"> <SmallTitle :title="'区域营收占比'" style="margin-top: 17px;">
<!-- <template #extra> <!-- <template #extra>
<div class="RegionalRevenueSelect"> <div class="RegionalRevenueSelect">
<div :class="selectDataType === 1 ? 'RegionalRevenueItem RegionalRevenueItemLeft selectRegionalRevenueItem' : 'RegionalRevenueItem RegionalRevenueItemLeft'" <div :class="selectDataType === 1 ? 'RegionalRevenueItem RegionalRevenueItemLeft selectRegionalRevenueItem' : 'RegionalRevenueItem RegionalRevenueItemLeft'"

View File

@ -63,11 +63,10 @@
.CoreCategoryCharts { .CoreCategoryCharts {
width: 100%; width: 100%;
margin-top: 26px;
.CoreCategory { .CoreCategory {
width: 100%; width: 100%;
height: 132px; height: 220px;
} }
} }
} }

View File

@ -47,7 +47,7 @@ onMounted(async () => {
const height = rect.height; const height = rect.height;
// center20%50% // center20%50%
const centerX = width * 0.2; const centerX = width * 0.21;
const centerY = height * 0.5; const centerY = height * 0.5;
myChart = echarts.init(chartDom); myChart = echarts.init(chartDom);
@ -67,8 +67,8 @@ onMounted(async () => {
legend: { // legend: { //
show: true, // show: true, //
orient: 'vertical', // orient: 'vertical', //
left: '40%', // left: 200, //
top: 0, // top: 'center', //
// type: 'scroll', // type: 'scroll',
textStyle: { // textStyle: { //
color: '#fff', // color: '#fff', //
@ -102,8 +102,8 @@ onMounted(async () => {
{ {
name: 'Access From', name: 'Access From',
type: 'pie', type: 'pie',
radius: ['85%', '100%'], radius: ['55%', '70%'],
center: ['20%', '50%'], center: ['21%', '50%'], //
avoidLabelOverlap: false, avoidLabelOverlap: false,
// itemStyle: { // itemStyle: {
// color: function (params: any) { // color: function (params: any) {

View File

@ -6,7 +6,7 @@
.TradingAlertNewBox { .TradingAlertNewBox {
width: 100%; width: 100%;
margin-top: 21px; // margin-top: 21px;
box-sizing: border-box; box-sizing: border-box;
padding: 20px; padding: 20px;
display: flex; display: flex;

View File

@ -52,7 +52,7 @@ const handleGetData = async () => {
// ai // ai
let AIData: any = [] let AIData: any = []
if (data.List && data.List.length > 0) { if (data.List && data.List.length > 0) {
let list = data.List.slice(0, 6) let list = data.List.slice(0, 7)
TradingAlertList.length = 0; TradingAlertList.length = 0;
list && list.forEach((item: any) => { list && list.forEach((item: any) => {
TradingAlertList.push(item) TradingAlertList.push(item)

View File

@ -22,7 +22,7 @@
.TrendOfTrafficFlow { .TrendOfTrafficFlow {
width: 100%; width: 100%;
height: 150px; height: 160px;
} }
} }
} }

View File

@ -34,7 +34,7 @@
.TrendCustomerRevenue { .TrendCustomerRevenue {
width: 100%; width: 100%;
height: 140px; height: 145px;
} }
} }
} }

View File

@ -15,6 +15,8 @@ let isScrolling = ref<boolean>(false);
let scrollDuration = ref('10s'); // let scrollDuration = ref('10s'); //
// id // id
let serverpartId = ref<number[]>([]) let serverpartId = ref<number[]>([])
//
let noticeMessageObj = ref<any>()
onMounted(async () => { onMounted(async () => {
// //
@ -30,14 +32,13 @@ const props = defineProps<{
// //
const emit = defineEmits<{ const emit = defineEmits<{
(e: "handelGetNoticeListAllId", idList: number[]): void; // (e: "handelGetNoticeListAllId", idList: number[], type: string, obj: any): void; //
}>(); }>();
// //
watch( watch(
() => props.currentService, () => props.currentService,
(newVal, oldVal) => { (newVal, oldVal) => {
// //
handleGetNoticeList() handleGetNoticeList()
}, },
@ -55,6 +56,7 @@ watch(
{ deep: true } { deep: true }
); );
// //
const handleGetNoticeList = async () => { const handleGetNoticeList = async () => {
const req = { const req = {
@ -78,61 +80,136 @@ const handleGetNoticeList = async () => {
data = await handleGetGDNearServiceList(req) data = await handleGetGDNearServiceList(req)
sessionStorage.setItem("noticeListBox", JSON.stringify(data)) sessionStorage.setItem("noticeListBox", JSON.stringify(data))
} }
console.log('11121', data);
// let list: any = data // let list: any = data
let list: any = [ let list: any = [
{ {
NOTICEINFO_TITLE: "云南省蒙新高速蒙自服务区(下行)招商信息公告", NOTICEINFO_TITLE: "云南省蒙新高速蒙自服务区(下行)招商信息公告",
SERVERPART_ID: 1187 SERVERPART_ID: 1187,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势地处昆河高速与蒙文砚高速交汇处是连接昆明文山河口的重要交通枢纽周边拥有碧色寨火车站西南联大蒙自分校旧址等历史文化资源以及南湖公园长桥海国家级湿地公园等自然景观同时依托蒙自石榴枇杷等特色农产品发展潜力巨大
招商范围综合楼普通餐饮地方特色小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
综合楼285汽修225`
}, },
{ {
NOTICEINFO_TITLE: "云南省景海高速景洪服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省景海高速景洪服务区(双侧)招商信息公告",
SERVERPART_ID: 1176 SERVERPART_ID: 1176,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于西双版纳州景洪市靠近中国-东盟自由贸易区的重要节点是中老中缅贸易的交通枢纽进出口货物运输频繁为服务区带来大量人流物流和商机周边有热带雨林傣族村寨等独特风光可感受东南亚风情附近的告庄西双景曼听公园等特色景点展示了傣族文化和边境地区的发展成果
招商范围综合楼地方特色餐饮地方特色小吃便利店
面积实际面积存在差异具体以现场测量为准
景洪服务区上行综合楼1410
景洪服务区下行综合楼1410`
}, },
{ {
NOTICEINFO_TITLE: "云南省景海高速勐海服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省景海高速勐海服务区(双侧)招商信息公告",
SERVERPART_ID: 1177 SERVERPART_ID: 1177,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于西双版纳州勐海县靠近打洛口岸是中国与缅甸边境贸易的重要通道进出口货物运输频繁为服务区带来大量人流物流和商机周边有独特的边境风光可感受中缅边境的异域风情附近的勐景来景区独树成林等特色景点展示了傣族文化和边境地区的发展成果吸引众多游客前来观光体验
招商范围综合楼普通餐饮普通小吃便利店
面积实际面积存在差异具体以现场测量为准
勐海服务区上行综合楼50
勐海服务区下行综合楼1391`
}, },
{ {
NOTICEINFO_TITLE: "云南省大南高速大仓服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省大南高速大仓服务区(双侧)招商信息公告",
SERVERPART_ID: 971 SERVERPART_ID: 971,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于大理州巍山县地处大理至临沧高速沿线是大理通往滇西南地区的重要交通节点车流量大区位优势明显周边有巍山古城巍宝山等历史文化景点可感受南诏文化和彝族风情附近的特色农产品和民族手工艺品资源丰富为服务区带来商机同时展示了当地民族文化和经济发展成果
招商范围综合楼普通餐饮普通小吃便利店
面积实际面积存在差异具体以现场测量为准
大仓服务区上行综合楼254
大仓服务区下行综合楼254`
}, },
{ {
NOTICEINFO_TITLE: "云南省大南高速巍山服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省大南高速巍山服务区(双侧)招商信息公告",
SERVERPART_ID: 973 SERVERPART_ID: 973,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于大理州巍山县地处大理至南涧高速沿线地理位置优越毗邻大理丽江等旅游热点交通便利辐射滇西经济圈周边自然资源丰富民族文化独特巍山古城为南诏文化发源地具备深厚的历史底蕴与旅游吸引力服务区可依托区域特色及高速路网优势发展文旅物流等产业助力区域经济协同发展
招商范围综合楼普通餐饮普通小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
巍山服务区上行综合楼979
巍山服务区下行综合楼1183汽修127`
}, },
{ {
NOTICEINFO_TITLE: "云南省南景高速拥翠服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省南景高速拥翠服务区(双侧)招商信息公告",
SERVERPART_ID: 970 SERVERPART_ID: 970,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于大理白族自治州南涧县地处G5611大临高速沿线周边生态环境优越毗邻无量山国家级自然保护区自然资源丰富适宜发展生态旅游及康养产业区域民族文化特色鲜明彝族文化底蕴深厚具备文旅融合潜力服务区可依托高速交通优势结合生态与人文资源推动特色农产品文化旅游及物流产业发展促进区域经济多元化升级
招商范围综合楼普通餐饮普通小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
拥翠服务区上行综合楼951汽修198
拥翠服务区下行综合楼951汽修198`
}, },
{ {
NOTICEINFO_TITLE: "云南省南景高速三岔河服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省南景高速三岔河服务区(双侧)招商信息公告",
SERVERPART_ID: 1109 SERVERPART_ID: 1109,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势地处滇西南交通枢纽周边自然资源丰富毗邻无量山哀牢山国家级自然保护区生态环境优越景东县为普洱茶核心产区之一茶文化底蕴深厚具备特色农业及文旅开发潜力服务区可依托高速交通优势及区域资源发展生态旅游茶产业及物流服务助力区域经济可持续发展
招商范围综合楼普通餐饮普通小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
三岔河服务区上行综合楼828汽修198
三岔河服务区下行综合楼828汽修198`
}, },
{ {
NOTICEINFO_TITLE: "云南省南景高速景东北停车区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省南景高速景东北停车区(双侧)招商信息公告",
SERVERPART_ID: 1110 SERVERPART_ID: 1110,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势位于普洱市景东彝族自治县地处G5611大临高速沿线周边自然资源丰富毗邻无量山哀牢山国家级自然保护区生态环境优越生物多样性显著景东县为普洱茶主产区之一茶文化底蕴深厚具备特色农业开发潜力停车区可依托高速交通优势及生态资源发展生态旅游茶产业及物流服务助力区域经济可持续发展
招商范围综合楼普通餐饮普通小吃便利店
面积实际面积存在差异具体以现场测量为准
景东北服务区上行综合楼846
景东北服务区下行综合楼846`
}, },
{ {
NOTICEINFO_TITLE: "云南省思澜高速龙潭服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省思澜高速龙潭服务区(双侧)招商信息公告",
SERVERPART_ID: 1161 SERVERPART_ID: 1161,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势思澜高速全长约131.5公里设计时速80公里双向四车道茫茫龙潭大山植被丰富有热带雨林植物花卉服务区按花园式景区建设有傣族拉祜族佤族建筑样式等能为过往驾乘人员提供舒适的休憩环境
招商范围综合楼普通餐饮普通小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
龙潭服务区上行综合楼1499汽修210
龙潭服务区下行综合楼1597汽修210`
}, },
{ {
NOTICEINFO_TITLE: "云南省思澜高速糯扎渡服务区(双侧)招商信息公告", NOTICEINFO_TITLE: "云南省思澜高速糯扎渡服务区(双侧)招商信息公告",
SERVERPART_ID: 1163 SERVERPART_ID: 1163,
NOTICEINFO_CONTENT: `【合作模式】保底收益或提点取高
运营方式餐饮小吃加盟滇食坊品牌商超加盟彩云驿购品牌 供应链统一供货
周边资源及优势思澜高速全长约131.5公里设计时速80公里双向四车道位于昆磨高速等重要交通干道上是连接昆明普洱西双版纳等城市的关键节点车流量大客源稳定
招商范围综合楼普通餐饮普通小吃便利店汽修
面积实际面积存在差异具体以现场测量为准
糯扎渡服务区上行综合楼2735汽修167
糯扎渡服务区下行综合楼2010汽修167`
} }
] ]
let allServerpartId: number[] = [] let allServerpartId: number[] = []
let obj: any = {}
noticeList.length = 0; noticeList.length = 0;
list && list.forEach((item: any) => { list && list.forEach((item: any) => {
noticeList.push(item) noticeList.push(item)
allServerpartId.push(item.SERVERPART_ID) allServerpartId.push(item.SERVERPART_ID)
obj[Number(item.SERVERPART_ID)] = item.NOTICEINFO_CONTENT
}); });
serverpartId.value = allServerpartId serverpartId.value = allServerpartId
console.log('noticeList:', noticeList); // console.log('noticeList:', noticeList); //
noticeMessageObj.value = obj
nextTick(() => { nextTick(() => {
// //
startScrolling(); startScrolling();
@ -202,7 +279,7 @@ const stopScrolling = () => {
// //
const handleClickBigBox = () => { const handleClickBigBox = () => {
console.log('serverpartId.valueserverpartId.valueserverpartId.value', serverpartId.value); console.log('serverpartId.valueserverpartId.valueserverpartId.value', serverpartId.value);
emit('handelGetNoticeListAllId', serverpartId.value) emit('handelGetNoticeListAllId', serverpartId.value, 'notice', noticeMessageObj.value)
} }
onUnmounted(() => { onUnmounted(() => {

View File

@ -204,7 +204,8 @@ onBeforeUnmount(() => {
<div class="leftTabBox"> <div class="leftTabBox">
<div :class="selectPageTab === 3 ? 'pageTopTabItem selectPageTopTabItem' : 'pageTopTabItem'" <div :class="selectPageTab === 3 ? 'pageTopTabItem selectPageTopTabItem' : 'pageTopTabItem'"
@click="handleChangePageTab(3)">财务中枢</div> >财务中枢</div>
<!-- @click="handleChangePageTab(3)" -->
<div :class="selectPageTab === 4 ? 'pageTopTabItem selectPageTopTabItem' : 'pageTopTabItem'" <div :class="selectPageTab === 4 ? 'pageTopTabItem selectPageTopTabItem' : 'pageTopTabItem'"
@click="handleChangePageTab(4)">彩云驿出行</div> @click="handleChangePageTab(4)">彩云驿出行</div>
<!-- @click="handleChangePageTab(4)" --> <!-- @click="handleChangePageTab(4)" -->

View File

@ -10,16 +10,27 @@
justify-content: space-between; justify-content: space-between;
padding-left: 10px; padding-left: 10px;
.title { .leftBox {
font-family: Microsoft YaHei, Microsoft YaHei; display: flex;
font-weight: bold; align-items: center;
font-size: 15px; .smallTitleIcon{
// color: #FFFFFF; width: 13px;
color: #C1ECF7; height: 16px;
text-align: left; margin-right: 8px;
font-style: normal; }
.title {
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold;
font-size: 15px;
// color: #FFFFFF;
color: #FFFFFF;
text-align: left;
font-style: normal;
}
} }
.changeTypeBox { .changeTypeBox {
display: flex; display: flex;
align-items: center; align-items: center;
@ -59,12 +70,14 @@
// background-repeat: no-repeat; // background-repeat: no-repeat;
// background-size: 100% 100%; // background-size: 100% 100%;
// background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%); // background: linear-gradient(90deg, rgba(0, 148, 255, 0.1) 0%, rgba(0, 148, 255, 0) 100%);
.title { .leftBox {
font-family: Microsoft YaHei, Microsoft YaHei; .title {
font-weight: bold; font-family: Microsoft YaHei, Microsoft YaHei;
font-size: 15px; font-weight: bold;
color: #FFFFFF; font-size: 15px;
text-align: center; color: #FFFFFF;
font-style: normal; text-align: center;
font-style: normal;
}
} }
} }

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import './smallTitle.less' import './smallTitle.less'
import smallTitleIcon from '../../../../assets/image/smallTitleIcon.png'
// //
const props = defineProps<{ const props = defineProps<{
@ -11,7 +12,10 @@ const props = defineProps<{
<template> <template>
<div :class="pageType === 'center' ? 'smallTitleBoxCenter' : 'smallTitleBox'"> <div :class="pageType === 'center' ? 'smallTitleBoxCenter' : 'smallTitleBox'">
<div class="title">{{ props.title }}</div> <div class="leftBox">
<img class="smallTitleIcon" :src="smallTitleIcon" />
<div class="title">{{ props.title }}</div>
</div>
<slot name="extra"></slot> <slot name="extra"></slot>
</div> </div>
</template> </template>

View File

@ -111,6 +111,49 @@
} }
} }
} }
.supplierMessageBox {
width: 100%;
.supplierMessageBoxTop {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.supplierMessageBoxTopItem {
width: calc((100% - 20px) / 2);
// width: 100%;
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%;
.supplierMessageBoxTopItemLabel {
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold;
font-size: 14px;
color: #FFFFFF;
text-align: center;
font-style: normal;
}
.supplierMessageBoxTopItem {
font-family: Bahnschrift, Bahnschrift;
font-weight: 400;
font-size: 28px;
color: #56BCE6;
text-align: center;
font-style: normal;
}
}
}
}
} }
.supplierListBox::-webkit-scrollbar { .supplierListBox::-webkit-scrollbar {

View File

@ -2,11 +2,13 @@
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import './supplierListBox.less' import './supplierListBox.less'
import shopIcon from '../../../../assets/image/shopIcon.png' import shopIcon from '../../../../assets/image/shopIcon.png'
import { handleGetSupplierList, handleGetSupplierListChain } from '../../service'; import { handleGetSupplierList, handleGetSupplierListChain, handleGetSupplierTypeList } from '../../service';
import supplierIcon from '../../../../assets/image/supplierIcon.png' import supplierIcon from '../../../../assets/image/supplierIcon.png'
// //
let supplierList = ref<any>([]) let supplierList = ref<any>([])
//
let supplierObj = ref<any>()
onMounted(async () => { onMounted(async () => {
@ -35,6 +37,38 @@ const handleGetData = async () => {
console.log('handleGetSupplierListChainhandleGetSupplierListChain', data); console.log('handleGetSupplierListChainhandleGetSupplierListChain', data);
supplierList.value = data.slice(0, 11) supplierList.value = data.slice(0, 11)
const req2: any = {
ProvinceCode: "530000",
}
let supplierListBox2 = sessionStorage.getItem('supplierListBox2')
let data2: any = []
if (supplierListBox2) {
data2 = JSON.parse(supplierListBox2)
} else {
data2 = await handleGetSupplierTypeList(req2)
sessionStorage.setItem("supplierListBox2", JSON.stringify(data2))
}
console.log('data2data2data2data2', data2);
let obj: any = {}
if (data2 && data2.length > 0) {
data2.forEach((item: any) => {
if (item.SupplierType_Name === "经销商") {
obj.dealer = item.Supplier_count
} else if (item.SupplierType_Name === "品牌方") {
obj.brandSide = item.Supplier_count
} else if (item.SupplierType_Name === "自有品牌水") {
obj.privateLabelWater = item.Supplier_count
} else if (item.SupplierType_Name === "零售批发类") {
obj.retailAndWholesale = item.Supplier_count
}
})
}
supplierObj.value = obj
} }
@ -42,27 +76,61 @@ const handleGetData = async () => {
<template> <template>
<div class="supplierListBox"> <div class="supplierListBox">
<div class="supplierListItem" v-for="(item, index) in supplierList" :key="index"> <div class="supplierMessageBox" style="margin-top: 10px;">
<!-- <div class="supplierListLeft"> <div class="supplierMessageBoxTop">
<img class="supplierIcon" :src="item.Icon" /> <div class="supplierMessageBoxTopItem">
</div> --> <div class="supplierMessageBoxTopItemLabel">经销商/</div>
<div class="supplierMessageBoxTopItemvalue" style="color: #56BCE6;">{{ supplierObj?.dealer || "0" }}
<div class="supplierListRight"> </div>
<div class="supplierListNamebox">
<img class="supplierListIcon" :src="supplierIcon" />
<div class="supplierListName">{{ item.SupplierName || '' }}</div>
</div> </div>
<div class="supplierMessageBoxTopItem">
<div class="supplierMessageBoxTopItemLabel">品牌方/</div>
<div class="supplierMessageBoxTopItemvalue" style="color: #ef5a0d;">{{ supplierObj?.brandSide || "0"
}}
</div>
</div>
</div>
<div class="supplierListContent"> <div class="supplierMessageBoxTop" style="margin-top: 10px;">
<!-- <img class="shopIcon" :src="shopIcon" /> --> <div class="supplierMessageBoxTopItem">
<span class="shopValue">{{ item.VarietyCount }}</span> <div class="supplierMessageBoxTopItemLabel">自有品牌水/</div>
<span class="shopUnit"></span> <div class="supplierMessageBoxTopItemvalue" style="color: #56BCE6;">{{
supplierObj?.privateLabelWater || "0" }}
<!-- <span class="shopLabel">送达率</span> </div>
<span class="shopValue">{{ item.DeliverRate || '-' }}</span> </div>
<span class="shopUnit">%</span> --> <div class="supplierMessageBoxTopItem">
<div class="supplierMessageBoxTopItemLabel">零售批发类/</div>
<div class="supplierMessageBoxTopItemvalue" style="color: #ef5a0d;">{{
supplierObj?.retailAndWholesale || "0" }}
</div>
</div> </div>
</div> </div>
</div> </div>
<div style="margin-top: 20px;">
<div class="supplierListItem" v-for="(item, index) in supplierList" :key="index">
<!-- <div class="supplierListLeft">
<img class="supplierIcon" :src="item.Icon" />
</div> -->
<div class="supplierListRight">
<div class="supplierListNamebox">
<img class="supplierListIcon" :src="supplierIcon" />
<div class="supplierListName">{{ item.SupplierName || '' }}</div>
</div>
<div class="supplierListContent">
<!-- <img class="shopIcon" :src="shopIcon" /> -->
<span class="shopValue">{{ item.VarietyCount }}</span>
<span class="shopUnit"></span>
<!-- <span class="shopLabel">送达率</span>
<span class="shopValue">{{ item.DeliverRate || '-' }}</span>
<span class="shopUnit">%</span> -->
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>

View File

@ -22,7 +22,7 @@ import TradingAlert from './components/TradingAlert/TradingAlert.vue'
import PrivateRideService from './components/PrivateRideService/PrivateRideService.vue' import PrivateRideService from './components/PrivateRideService/PrivateRideService.vue'
import RegionalRevenue from './components/RegionalRevenue/RegionalRevenue.vue' import RegionalRevenue from './components/RegionalRevenue/RegionalRevenue.vue'
import PageMap from './components/PageMap/PageMap.vue' import PageMap from './components/PageMap/PageMap.vue'
import { ref } from 'vue'; import { onMounted, ref } from 'vue';
import FestivalRevenue from './components/FestivalRevenue/FestivalRevenue.vue'; import FestivalRevenue from './components/FestivalRevenue/FestivalRevenue.vue';
import ConsumptionConversion from './components/ConsumptionConversion/ConsumptionConversion.vue' import ConsumptionConversion from './components/ConsumptionConversion/ConsumptionConversion.vue'
import ConsumptionLevel from './components/ConsumptionLevel/ConsumptionLevel.vue'; import ConsumptionLevel from './components/ConsumptionLevel/ConsumptionLevel.vue';
@ -60,9 +60,15 @@ import AssessmentScoringRanking from './components/AssessmentScoringRanking/Asse
import SmallTitle from './components/smallTitle/smallTitle.vue'; import SmallTitle from './components/smallTitle/smallTitle.vue';
import FestivalRevenueSumInfo from './components/FestivalRevenueSumInfo/FestivalRevenueSumInfo.vue' import FestivalRevenueSumInfo from './components/FestivalRevenueSumInfo/FestivalRevenueSumInfo.vue'
import AIIcon from '../../assets/image/AIIcon.png' import AIIcon from '../../assets/image/AIIcon.png'
import showMapIcon from '../../assets/image/showMapIcon.png'
import MemberMall from './components/MemberMall/index.vue' import MemberMall from './components/MemberMall/index.vue'
import AnalysisOfMember from './components/AnalysisOfMember/AnalysisOfMember.vue' import AnalysisOfMember from './components/AnalysisOfMember/AnalysisOfMember.vue'
import AreaLegend from './components/AreaLegend/AreaLegend.vue';
import { useRouter } from 'vue-router'; //
const router = useRouter()
// //
let pageType = ref<string>("center") let pageType = ref<string>("center")
// //
@ -99,6 +105,20 @@ let showDialogBox = ref<boolean>(false)
let searchText = ref<string>('') let searchText = ref<string>('')
// //
let isPrinting = ref<boolean>(false) let isPrinting = ref<boolean>(false)
//
let mapLegend = ref<any>()
//
let mapClickComeForm = ref<string>("")
//
let noticeMessageObj = ref<any>()
onMounted(() => {
let currentUser: any = sessionStorage.getItem('currentUser')
if (!currentUser) {
router.push('/login')
}
})
// //
@ -122,8 +142,12 @@ const handleChangePageTab = (value: number) => {
} }
// id // id
const handelGetNoticeListAllId = (idList: number[]) => { const handelGetNoticeListAllId = (idList: number[], type: string, obj: any) => {
noticeAllServicePartId.value = idList noticeAllServicePartId.value = idList
mapClickComeForm.value = type
console.log('objobj', obj);
noticeMessageObj.value = obj
} }
// //
@ -155,6 +179,18 @@ const handleChangeTab = async (value: number) => {
selectTab.value = value selectTab.value = value
} }
//
const handleGetMapLegend = (list: any) => {
console.log('handleGetMapLegendhandleGetMapLegendhandleGetMapLegend', list);
mapLegend.value = list
}
//
const handleChangeComeForm = (str: string) => {
mapClickComeForm.value = str
}
// //
const handleSubmit = () => { const handleSubmit = () => {
@ -198,7 +234,7 @@ const handleStopPrint = () => {
<!-- <BusyTradingRanking style="margin-top: 11px;" /> --> <!-- <BusyTradingRanking style="margin-top: 11px;" /> -->
<!-- 交易预警 --> <!-- 交易预警 -->
<TradingAlert style="margin-top: 11px;" /> <TradingAlert />
</div> </div>
</div> </div>
@ -226,9 +262,23 @@ const handleStopPrint = () => {
<div v-show="selectPageTab === 1 && !showDialogBox"> <div v-show="selectPageTab === 1 && !showDialogBox">
<!-- 地图 --> <!-- 地图 -->
<PageMap @handleGetCurrentService="handleGetCurrentService" <PageMap @handleGetCurrentService="handleGetCurrentService" :noticeMessageObj="noticeMessageObj"
:selectPointServicePart="noticeAllServicePartId" :selectPointServicePart="noticeAllServicePartId" :mapClickComeForm="mapClickComeForm"
@handleMapToChangeNotice="handleMapToChangeNotice" /> @handleMapToChangeNotice="handleMapToChangeNotice" @handleGetMapLegend="handleGetMapLegend"
@handleChangeComeForm="handleChangeComeForm" />
<div class="AreaLegend">
<div class="AreaLegendContent">
<!-- 图例组件 -->
<AreaLegend :mapLegend="mapLegend" />
</div>
<!-- AI图标对话 -->
<div class="AIBox" @click="handleClickAIBox" v-if="false">
<img v-if="!showDialogBox" class="AIIcon" :src="AIIcon" />
<img v-if="showDialogBox" class="AIIcon" :src="showMapIcon" />
</div>
</div>
</div> </div>
<div class="AIDialogBox" v-show="selectPageTab === 1 && showDialogBox"> <div class="AIDialogBox" v-show="selectPageTab === 1 && showDialogBox">
<!-- <div class="dialogBox"></div> <!-- <div class="dialogBox"></div>
@ -247,16 +297,21 @@ const handleStopPrint = () => {
<!-- <iframe src="http://10.104.1.171:5174/deepseek/?comeForm=YNMap" <!-- <iframe src="http://10.104.1.171:5174/deepseek/?comeForm=YNMap"
style="width: 100%;height: 100%;overflow: hidden;" frameborder="0" style="width: 100%;height: 100%;overflow: hidden;" frameborder="0"
@load="handleIframeLoad"></iframe> --> @load="handleIframeLoad"></iframe> -->
<div class="AreaLegendDialog">
<div class="AIBox" @click="handleClickAIBox">
<img v-if="!showDialogBox" class="AIIcon" :src="AIIcon" />
<img v-if="showDialogBox" class="AIIcon" :src="showMapIcon" />
</div>
</div>
</div> </div>
<!-- 公告主题 --> <!-- 公告主题 -->
<!-- <AnnouncementTopic style="position: relative;z-index: 9;" /> --> <!-- <AnnouncementTopic style="position: relative;z-index: 9;" /> -->
<!-- AI图标对话 -->
<div class="AIBox" @click="handleClickAIBox">
<img class="AIIcon" :src="AIIcon" />
</div>
</div> </div>
<div class="content169Right"> <div class="content169Right">
@ -312,7 +367,6 @@ const handleStopPrint = () => {
</div> </div>
<div class="pageBottom" v-if="selectPageTab === 1"> <div class="pageBottom" v-if="selectPageTab === 1">
</div> </div>
<!-- 分区二 --> <!-- 分区二 -->
@ -370,7 +424,7 @@ const handleStopPrint = () => {
</template> </template>
</NewBigTitleBox> </NewBigTitleBox>
<div class="left3stBottom" style="margin-top: 0;"> <div class="left3stBottom" style="margin-top: 0;display: flex;align-items: center;">
<div class="left3stBottomItemLeft"> <div class="left3stBottomItemLeft">
<div class="left3stBottomItem"> <div class="left3stBottomItem">
<!-- 消费转化率对比图 --> <!-- 消费转化率对比图 -->
@ -432,10 +486,11 @@ const handleStopPrint = () => {
<!-- <MultiIndustryIncome style="margin-top: 34px;" :currentService="currentService" /> --> <!-- <MultiIndustryIncome style="margin-top: 34px;" :currentService="currentService" /> -->
<!-- 业态结构占比 --> <!-- 业态结构占比 -->
<BusinessStructure :currentService="currentService" style="margin-top: 22px;" /> <!-- style="margin-top: 22px;" -->
<BusinessStructure :currentService="currentService" />
</div> </div>
<NewBigTitleBox :title="'节假日营收'" style="margin-top: 44px;"> <NewBigTitleBox :title="'节假日营收'">
<!-- <template #extra> <!-- <template #extra>
<div class="FestivalBox"> <div class="FestivalBox">
<el-select class="festivalSelect" v-model="FestivalValue" placeholder="Select" <el-select class="festivalSelect" v-model="FestivalValue" placeholder="Select"
@ -619,7 +674,7 @@ const handleStopPrint = () => {
<!-- 核心品类占比 --> <!-- 核心品类占比 -->
<!-- <CoreCategory style="margin-top: 10px;" /> --> <!-- <CoreCategory style="margin-top: 10px;" /> -->
<NewBigTitleBox :title="'会员消费数据分析'" style="margin-top: 28px;" /> <NewBigTitleBox :title="'会员消费数据分析'" />
<AnalysisOfMember /> <AnalysisOfMember />
<!-- 商户评分排行榜 --> <!-- 商户评分排行榜 -->

View File

@ -181,6 +181,16 @@ export async function handleGetRealData(params: any) {
return data.Result_Data return data.Result_Data
} }
// 拿到实时数据 月度
export async function handleGetMonthlyBusinessRevenue(params: any) {
const data: any = await requestPos.post('/Revenue/GetMonthlyBusinessRevenue', params)
if (data.Result_Code !== 100) {
return data
}
return wrapTreeNode(data.Result_Data.List)
}
// 今日趋势图新的 // 今日趋势图新的
export async function handleGetRevenueTrendChart(params: any) { export async function handleGetRevenueTrendChart(params: any) {
@ -475,6 +485,15 @@ export async function handleGetSupplierListChain(params: any) {
return data.Result_Data.List return data.Result_Data.List
} }
// 获取供应商的分类数据
export async function handleGetSupplierTypeList(params: any) {
const data: any = await requestPos.post('/SupplyChain/GetSupplierTypeList', params)
if (data.Result_Code !== 100) {
return data
}
return data.Result_Data.List
}
// 获取供应商的列表数据 // 获取供应商的列表数据
export async function handleGetMallOrderSummary(params: any) { export async function handleGetMallOrderSummary(params: any) {

View File

@ -320,24 +320,14 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.AIBox {
position: absolute;
bottom: 100px;
right: calc((100% - 90px) / 4 + 30px);
z-index: 10;
cursor: pointer;
.AIIcon {
width: 40px;
height: 40px;
}
}
.AIDialogBox { .AIDialogBox {
width: 100%; width: 100%;
height: calc(100% - 108px); height: calc(100% - 75px);
box-sizing: border-box; box-sizing: border-box;
padding: 32px 32px 32px 8px; padding: 32px 32px 32px 8px;
position: relative;
.dialogBox { .dialogBox {
width: 100%; width: 100%;
@ -372,6 +362,52 @@
cursor: pointer; cursor: pointer;
} }
} }
.AreaLegendDialog {
position: absolute;
bottom: 50px;
right: 0;
.AIBox {
right: 0;
bottom: 0;
position: absolute;
z-index: 11;
cursor: pointer;
.AIIcon {
width: 40px;
height: 40px;
}
}
}
}
.AreaLegend {
width: calc((100% - 90px) / 4 * 2 + 30px);
position: absolute;
bottom: 50px;
.AreaLegendContent {
width: calc((100% - 50px));
z-index: 10;
position: absolute;
bottom: 0px;
}
.AIBox {
right: 0;
bottom: 0;
position: absolute;
z-index: 11;
cursor: pointer;
.AIIcon {
width: 40px;
height: 40px;
}
}
} }
} }

75
src/page/login/login.less Normal file
View File

@ -0,0 +1,75 @@
.loginMain {
width: 100vw;
height: 100vh;
// background-color: #f3f2f2;
background-image: url('../../assets/image/loginBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
position: relative;
// .contentTopImg {
// width: 600px;
// height: 55px;
// position: fixed;
// top: 100px;
// left: 280px;
// }
.content {
width: 550px;
height: 500px;
background-color: #fff;
border: 1px solid #f5f5f5;
box-shadow: 0 4px 18px 0 hsla(0, 0%, 68.6%, 0.43);
position: absolute;
top: 50%;
left: 60%;
transform: translate(0, -50%);
border-radius: 4px;
.contentTop {
width: 100%;
box-sizing: border-box;
padding: 80px 24px 0;
color: rgba(0, 0, 0, 0.85);
font-size: 32px;
text-align: center;
font-family: Avenir, "Helvetica Neue", Arial, Helvetica, sans-serif;
// border-bottom: 1px solid #d7d8d9;
font-weight: 600;
}
.contentBottom {
width: 100%;
box-sizing: border-box;
padding: 32px 0 24px;
display: flex;
justify-content: center;
.loginForm {
width: 328px;
margin-top: 30px;
.accountNumber {
height: 40px;
font-size: 18px;
color: #000;
}
.password {
height: 40px;
font-size: 18px;
color: #000;
margin-top: 20px;
}
.submitBtn {
width: 100%;
height: 50px;
margin-top: 30px;
font-size: 22px;
}
}
}
}
}

94
src/page/login/login.vue Normal file
View File

@ -0,0 +1,94 @@
<script setup lang="ts">
import { ref } from 'vue';
import './login.less'
import { User, Lock } from '@element-plus/icons-vue'
import { handleGetGDNearServiceList } from './service';
import CryptoJs from 'crypto-js';
import { ElMessage } from 'element-plus';
import YNLoginTop from '../../assets/image/YNLoginTop.png'
import { useRouter } from 'vue-router'; //
const router = useRouter()
let accountNumber = ref<string>('')
let password = ref<string>('')
let btnLoading = ref<boolean>(false)
//
let accountError = ref<string>('')
let passwordError = ref<string>('')
//
const handleGetLogin = async () => {
accountError.value = ''
passwordError.value = ''
let valid = true
if (!accountNumber.value) {
accountError.value = '请输入账号'
valid = false
}
if (!password.value) {
passwordError.value = '请输入密码'
valid = false
}
if (!valid) return
btnLoading.value = true
// ...
const req: any = {
UserPassport: accountNumber.value,
UserPassWord: CryptoJs.MD5(password.value + accountNumber.value).toString()
}
console.log('req', req);
const data = await handleGetGDNearServiceList(req)
console.log('datadatadatadata', data);
btnLoading.value = false
if (data.Result_Code === 100) {
sessionStorage.setItem("currentUser", JSON.stringify(data.Result_Data))
ElMessage({
message: '登录成功',
type: 'success',
})
router.push('/')
} else {
ElMessage.error(data.Result_Desc)
}
}
</script>
<template>
<div class="loginMain">
<!-- <img class="contentTopImg" :src="YNLoginTop" /> -->
<div class="content">
<div class="contentTop">
<!-- <img class="contentTopImg" :src="YNLoginTop" /> -->
欢迎登录
</div>
<div class="contentBottom">
<div class="loginForm">
<el-form>
<el-form-item :error="accountError">
<el-input class="accountNumber" v-model="accountNumber" placeholder="账号" :prefix-icon="User"
@input="accountError = ''" />
</el-form-item>
<el-form-item :error="passwordError">
<el-input class="password" type="password" v-model="password" placeholder="密码"
:prefix-icon="Lock" show-password @input="passwordError = ''"
@keyup.enter="handleGetLogin" />
</el-form-item>
<el-form-item>
<el-button class="submitBtn" type="primary" :loading="btnLoading"
@click="handleGetLogin"> </el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</template>

21
src/page/login/service.ts Normal file
View File

@ -0,0 +1,21 @@
import request from "../../request/request"
// 获得高速头条的内容
export async function handleGetGDNearServiceList(params: any) {
const formData = new FormData()
Object.keys(params).forEach(key => {
formData.append(key, params[key])
})
const data: any = await request.post('/Logging/UserLogin', formData, {
headers: {
'Content-Type': 'multipart/form-data',
'provincecode': '530000' // 保持原有自定义头
}
})
if (data.Result_Code !== 100) {
return data
}
return data
}

View File

@ -43,7 +43,7 @@ const errorHandler = (error: any): any => {
// 创建 axios 实例 // 创建 axios 实例
const instance = axios.create({ const instance = axios.create({
baseURL: 'http://cloud.eshangtech.com/MobileServicePlatform/Handler/handler_ajax.ashx', // 默认请求前缀 baseURL: 'https://cloud.eshangtech.com/MobileServicePlatform/Handler/handler_ajax.ashx', // 默认请求前缀
timeout: 60000, // 请求超时时间 timeout: 60000, // 请求超时时间
headers: { headers: {
'Content-Type': 'text/plain', 'Content-Type': 'text/plain',

View File

@ -71,10 +71,10 @@ instance.interceptors.response.use(
// 封装的请求方法 // 封装的请求方法
const request = { const request = {
get: (url: string, params?: any) => instance.get(url, { params }), get: (url: string, params?: any, config?: AxiosRequestConfig) => instance.get(url, { params, ...config }),
post: (url: string, data?: any) => instance.post(url, data), post: (url: string, data?: any, config?: AxiosRequestConfig) => instance.post(url, data, config),
put: (url: string, data?: any) => instance.put(url, data), put: (url: string, data?: any, config?: AxiosRequestConfig) => instance.put(url, data, config),
delete: (url: string, params?: any) => instance.delete(url, { params }), delete: (url: string, params?: any, config?: AxiosRequestConfig) => instance.delete(url, { params, ...config }),
}; };
export default request; export default request;

View File

@ -71,6 +71,7 @@ instance.interceptors.response.use(
errorHandler errorHandler
); );
// 封装的请求方法 // 封装的请求方法
const request = { const request = {
get: (url: string, params?: any) => instance.get(url, { get: (url: string, params?: any) => instance.get(url, {

View File

@ -1,6 +1,7 @@
import { createRouter, createWebHashHistory } from 'vue-router'; import { createRouter, createWebHashHistory } from 'vue-router';
// import Map from '@/components/map/index.vue'; // 你的 Map 组件 // import Map from '@/components/map/index.vue'; // 你的 Map 组件
import Map from '@/page/index/index.vue' import Map from '@/page/index/index.vue'
import Login from '@/page/login/login.vue'
const routes = [ const routes = [
// { // {
@ -8,6 +9,11 @@ const routes = [
// name: 'home', // name: 'home',
// component: Map, // component: Map,
// }, // },
{
path: '/login',
name: 'login',
component: Login
},
{ {
path: '/', path: '/',
name: 'map', name: 'map',

View File

@ -1 +1 @@
{"root":["./src/main.ts","./src/shims-vue.d.ts","./src/vite-env.d.ts","./src/options/serveice.ts","./src/page/index/service.ts","./src/request/newrequest.ts","./src/request/request.ts","./src/request/requestcode.ts","./src/request/requestconfig.ts","./src/request/requestlocal.ts","./src/request/requestpos.ts","./src/request/requesttest.ts","./src/router/index.ts","./src/stores/counter.ts","./src/app.vue","./src/page/index/index.vue","./src/page/index/components/accountsreceivablewarning/accountsreceivablewarning.vue","./src/page/index/components/analysisofmember/analysisofmember.vue","./src/page/index/components/announcementtopic/announcementtopic.vue","./src/page/index/components/annualaccountsreceivable/annualaccountsreceivable.vue","./src/page/index/components/assessmentscoring/assessmentscoring.vue","./src/page/index/components/assessmentscoringranking/assessmentscoringranking.vue","./src/page/index/components/basicmessagebox/basicmessagebox.vue","./src/page/index/components/brandconsumptionlevel/brandconsumptionlevel.vue","./src/page/index/components/branddetail/branddetail.vue","./src/page/index/components/brandlisttbox/brandlisttbox.vue","./src/page/index/components/businesscase/businesscase.vue","./src/page/index/components/businessstructure/businessstructure.vue","./src/page/index/components/busytradingranking/busytradingranking.vue","./src/page/index/components/centertitle/centertitle.vue","./src/page/index/components/consumptionconversion/consumptionconversion.vue","./src/page/index/components/consumptionlevel/consumptionlevel.vue","./src/page/index/components/consumptionperiod/consumptionperiod.vue","./src/page/index/components/contractinformation/contractinformation.vue","./src/page/index/components/corebusinessdata/corebusinessdata.vue","./src/page/index/components/corecategory/corecategory.vue","./src/page/index/components/customeragegroup/customeragegroup.vue","./src/page/index/components/customerconsumptionpreferences/customerconsumptionpreferences.vue","./src/page/index/components/customergroup/customergroup.vue","./src/page/index/components/customergroupstay/customergroupstay.vue","./src/page/index/components/dailyinspection/dailyinspection.vue","./src/page/index/components/deductiontype/deductiontype.vue","./src/page/index/components/detailedpayment/detailedpayment.vue","./src/page/index/components/festivalrevenue/festivalrevenue.vue","./src/page/index/components/festivalrevenuesuminfo/festivalrevenuesuminfo.vue","./src/page/index/components/gendercustomergroup/gendercustomergroup.vue","./src/page/index/components/highqualitymerchants/highqualitymerchants.vue","./src/page/index/components/hotproductlist/hotproductlist.vue","./src/page/index/components/mallorderstatistics/mallorderstatistics.vue","./src/page/index/components/membermall/index.vue","./src/page/index/components/merchantcategory/merchantcategory.vue","./src/page/index/components/merchantratingranking/merchantratingranking.vue","./src/page/index/components/multiindustryincome/multiindustryincome.vue","./src/page/index/components/overviewofservicearea/overviewofservicearea.vue","./src/page/index/components/pagemap/pagemap.vue","./src/page/index/components/passengerflowchanges/passengerflowchanges.vue","./src/page/index/components/paymentprogress/paymentprogress.vue","./src/page/index/components/preferencetype/preferencetype.vue","./src/page/index/components/privaterideservice/privaterideservice.vue","./src/page/index/components/regionalrevenue/regionalrevenue.vue","./src/page/index/components/returnrate/returnrate.vue","./src/page/index/components/salescomparison/salescomparison.vue","./src/page/index/components/signedclients/signedclients.vue","./src/page/index/components/thismonthbenefits/thismonthbenefits.vue","./src/page/index/components/todaytrend/todaytrend.vue","./src/page/index/components/totalaccountsreceivable/totalaccountsreceivable.vue","./src/page/index/components/tradingalert/tradingalert.vue","./src/page/index/components/trendoftrafficflow/trendoftrafficflow.vue","./src/page/index/components/vehiclemodelstay/vehiclemodelstay.vue","./src/page/index/components/vehiclestayanalysis/vehiclestayanalysis.vue","./src/page/index/components/vehiclesentering/vehiclesentering.vue","./src/page/index/components/modaltitle/modaltitle.vue","./src/page/index/components/newbigtitlebox/newbigtitlebox.vue","./src/page/index/components/noticelistbox/noticelistbox.vue","./src/page/index/components/pagetop/pagetop.vue","./src/page/index/components/smalltitle/smalltitle.vue","./src/page/index/components/supplierlistbox/supplierlistbox.vue"],"version":"5.6.3"} {"root":["./src/main.ts","./src/shims-vue.d.ts","./src/vite-env.d.ts","./src/options/serveice.ts","./src/page/index/service.ts","./src/page/login/service.ts","./src/request/newrequest.ts","./src/request/request.ts","./src/request/requestcode.ts","./src/request/requestconfig.ts","./src/request/requestlocal.ts","./src/request/requestpos.ts","./src/request/requesttest.ts","./src/router/index.ts","./src/stores/counter.ts","./src/app.vue","./src/page/index/index.vue","./src/page/index/components/accountsreceivablewarning/accountsreceivablewarning.vue","./src/page/index/components/analysisofmember/analysisofmember.vue","./src/page/index/components/announcementtopic/announcementtopic.vue","./src/page/index/components/annualaccountsreceivable/annualaccountsreceivable.vue","./src/page/index/components/arealegend/arealegend.vue","./src/page/index/components/assessmentscoring/assessmentscoring.vue","./src/page/index/components/assessmentscoringranking/assessmentscoringranking.vue","./src/page/index/components/basicmessagebox/basicmessagebox.vue","./src/page/index/components/brandconsumptionlevel/brandconsumptionlevel.vue","./src/page/index/components/branddetail/branddetail.vue","./src/page/index/components/brandlisttbox/brandlisttbox.vue","./src/page/index/components/businesscase/businesscase.vue","./src/page/index/components/businessstructure/businessstructure.vue","./src/page/index/components/busytradingranking/busytradingranking.vue","./src/page/index/components/centertitle/centertitle.vue","./src/page/index/components/consumptionconversion/consumptionconversion.vue","./src/page/index/components/consumptionlevel/consumptionlevel.vue","./src/page/index/components/consumptionperiod/consumptionperiod.vue","./src/page/index/components/contractinformation/contractinformation.vue","./src/page/index/components/corebusinessdata/corebusinessdata.vue","./src/page/index/components/corecategory/corecategory.vue","./src/page/index/components/customeragegroup/customeragegroup.vue","./src/page/index/components/customerconsumptionpreferences/customerconsumptionpreferences.vue","./src/page/index/components/customergroup/customergroup.vue","./src/page/index/components/customergroupstay/customergroupstay.vue","./src/page/index/components/dailyinspection/dailyinspection.vue","./src/page/index/components/deductiontype/deductiontype.vue","./src/page/index/components/detailedpayment/detailedpayment.vue","./src/page/index/components/festivalrevenue/festivalrevenue.vue","./src/page/index/components/festivalrevenuesuminfo/festivalrevenuesuminfo.vue","./src/page/index/components/gendercustomergroup/gendercustomergroup.vue","./src/page/index/components/highqualitymerchants/highqualitymerchants.vue","./src/page/index/components/hotproductlist/hotproductlist.vue","./src/page/index/components/mallorderstatistics/mallorderstatistics.vue","./src/page/index/components/membermall/index.vue","./src/page/index/components/merchantcategory/merchantcategory.vue","./src/page/index/components/merchantratingranking/merchantratingranking.vue","./src/page/index/components/multiindustryincome/multiindustryincome.vue","./src/page/index/components/overviewofservicearea/overviewofservicearea.vue","./src/page/index/components/pagemap/pagemap.vue","./src/page/index/components/passengerflowchanges/passengerflowchanges.vue","./src/page/index/components/paymentprogress/paymentprogress.vue","./src/page/index/components/preferencetype/preferencetype.vue","./src/page/index/components/privaterideservice/privaterideservice.vue","./src/page/index/components/regionalrevenue/regionalrevenue.vue","./src/page/index/components/returnrate/returnrate.vue","./src/page/index/components/salescomparison/salescomparison.vue","./src/page/index/components/signedclients/signedclients.vue","./src/page/index/components/thismonthbenefits/thismonthbenefits.vue","./src/page/index/components/todaytrend/todaytrend.vue","./src/page/index/components/totalaccountsreceivable/totalaccountsreceivable.vue","./src/page/index/components/tradingalert/tradingalert.vue","./src/page/index/components/trendoftrafficflow/trendoftrafficflow.vue","./src/page/index/components/vehiclemodelstay/vehiclemodelstay.vue","./src/page/index/components/vehiclestayanalysis/vehiclestayanalysis.vue","./src/page/index/components/vehiclesentering/vehiclesentering.vue","./src/page/index/components/modaltitle/modaltitle.vue","./src/page/index/components/newbigtitlebox/newbigtitlebox.vue","./src/page/index/components/noticelistbox/noticelistbox.vue","./src/page/index/components/pagetop/pagetop.vue","./src/page/index/components/smalltitle/smalltitle.vue","./src/page/index/components/supplierlistbox/supplierlistbox.vue","./src/page/login/login.vue"],"version":"5.6.3"}

1176
yarn.lock

File diff suppressed because it is too large Load Diff