feat:对接消息相关接口

This commit is contained in:
zjc
2025-01-08 18:05:12 +08:00
parent ab1ab210a9
commit 9ee304c8c2
39 changed files with 2081 additions and 1926 deletions

View File

@@ -48,6 +48,7 @@
series: [
{
type: 'pie',
clockwise: false,
silent: true,
center: ['30%', '50%'],
radius: ['60%', '70%'],
@@ -65,6 +66,7 @@
},
{
type: 'pie',
clockwise: false,
silent: true,
center: ['30%', '50%'],
radius: ['54%', '58%'],
@@ -82,6 +84,7 @@
},
{
type: 'pie',
clockwise: false,
silent: true,
center: ['30%', '50%'],
radius: ['0', '40%'],
@@ -95,6 +98,7 @@
},
{
type: 'pie',
clockwise: false,
silent: true,
center: ['30%', '50%'],
radius: ['0', '26%'],
@@ -116,7 +120,7 @@
<style lang="scss" scoped>
.age {
width: vw(290);
width: vw(300);
height: vh(120);
}
</style>

View File

@@ -5,14 +5,14 @@
<img class="more" src="@/assets/images/more.png" />
</template>
</Title1>
<div class="flex pt-20">
<div class="item" v-for="(item, index) in homeData?.scenicSpot" :key="index">
<div class="list flex pt-20">
<div class="item" v-for="(item, index) in scenicSpot" :key="index">
<img v-if="index == 0" class="item-icon" src="@/assets/images/core.png" />
<img v-if="index == 1" class="item-icon" src="@/assets/images/queue.png" />
<img v-if="index == 2" class="item-icon" src="@/assets/images/congestion.png" />
<span class="item-label">{{ item.name }}</span>
<div class="item-value flex align-end rela">
<countup :end-val="item.value" /><span class="unit"></span>
<countup :end-val="item.value || 0" /><span class="unit"></span>
</div>
</div>
</div>
@@ -145,7 +145,7 @@
<Title2 title="景区购票数" />
<div class="ticket-wrap">
<img src="@/assets/images/ticket.png" />
<div v-for="(item, index) in homeData?.admission" :key="index">
<div v-for="(item, index) in admission" :key="index">
<span class="label">{{ item.name }}</span><countup :end-val="item.value" />
</div>
</div>
@@ -155,7 +155,7 @@
<div class="flex">
<div class="age-box">
<Title3 title="年龄/性别占比" />
<age />
<div class="mt-8"> <age /></div>
<div class="count">总人数<countup :end-val="ageRateTotal" /></div>
<div
class="cell pt-20"
@@ -193,14 +193,32 @@
</template>
<script setup>
import countup from 'vue-countup-v3'
import top from './top.vue'
import age from './age.vue'
import gauge from './gauge.vue'
import ticket from './ticket.vue'
import countup from 'vue-countup-v3'
const homeData = inject('homeData')
// 景区信息
const scenicSpot = computed(() => {
if (homeData.value) return homeData.value?.scenicSpot
return [
{ value: 0, name: '全县景区数量' },
{ value: 0, name: '核心景区数' },
{ value: 0, name: '低感景区总数' }
]
})
const admission = computed(() => {
if (homeData.value) return homeData.value?.admission
return [
{ name: '当日购票量:', value: 0 },
{ name: '未来3天购票量', value: 0 },
{ name: '3天后购票量', value: 0 }
]
})
// 年龄占比
const ageRateTotal = computed(() => {
return homeData.value?.userPortrait.genderRate.reduce(
(total, current) => Number(current.count) + total,
@@ -208,9 +226,9 @@
)
})
const channelTotal = computed(() => {
return (
homeData.value?.userPortrait?.channel ||
[].reduce((total, current) => Number(current.count) + total, 0)
return homeData.value?.userPortrait?.channel.reduce(
(total, current) => Number(current.count) + total,
0
)
})
</script>
@@ -238,6 +256,9 @@
bottom: -30%;
z-index: 990;
}
.list {
height: vh(72);
}
.item {
position: relative;
height: vh(52);
@@ -258,8 +279,8 @@
left: vw(70);
top: vh(-10);
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.7);
font-size: vw(16);
color: #ffffff;
}
&-value {
position: absolute;
@@ -299,7 +320,7 @@
justify-content: center;
}
&-title {
font-size: vw(14);
font-size: vw(18);
color: rgba(255, 255, 255, 0.9);
}
&-value {
@@ -321,8 +342,8 @@
}
}
.age-box {
width: vw(290);
height: vh(290);
width: vw(320);
height: vh(296);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
@@ -330,8 +351,8 @@
}
}
.box-1 {
width: vw(240);
height: vh(290);
width: vw(230);
height: vh(296);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(2) {
@@ -374,7 +395,7 @@
color: rgba(255, 255, 255, 0.9);
}
.progress {
width: vw(170);
width: vw(150);
margin-left: vw(4);
:deep(.el-progress-bar__outer) {
background-color: #0858ae !important;

View File

@@ -49,7 +49,19 @@
</li>
</ul>
</div>
<Map />
<div class="map" id="map"></div>
<div class="spot-wrap">
<ul class="spot-list">
<li
class="spot-item"
v-for="(item, index) in spotList"
:key="index"
@click="handleMap(item.scenicSpotId)"
>
<img :src="`http://36.138.38.16:8001/fjtcc-api${item.img}`" />
</li>
</ul>
</div>
</div>
<div class="footer">
<div class="left">
@@ -122,12 +134,24 @@
<script setup>
import countup from 'vue-countup-v3'
import ScrollNumber from '@/components/ScrollNumber/index.vue'
import { getSpotListApi, getBaiduMapCrowdedApi } from '@/api/home'
import icon8 from '@/assets/images/icon-8.png'
import icon9 from '@/assets/images/icon-9.png'
import icon10 from '@/assets/images/icon-10.png'
import icon11 from '@/assets/images/icon-11.png'
let count = ref('6945959')
import { useMap } from '@/hooks/map'
let emit = defineEmits(['switch-spot'])
const { map, initMap, addMarker } = useMap()
const homeData = inject('homeData')
let count = ref(69459)
let spotList = ref([])
let list = ref([
{
label: '安全异常',
@@ -146,14 +170,65 @@
icon: icon11
}
])
const handleMap = (e) => {
emit('switch-spot', e)
// map.value.centerAndZoom(new BMapGL.Point('108.704166', '30.94776'), 16)
}
const getSpotList = async () => {
let res = await getSpotListApi()
spotList.value = res.data
let res1 = await getBaiduMapCrowdedApi({
nodeId: res.data[0].nodeid
})
console.log(res1, 'res1')
}
watch(
() => homeData.value?.baiduMap,
(val) => {
if (val) init(val)
},
{ immediate: true }
)
const init = (val) => {
initMap('map', val.index.lng, val.index.lat, 15, false)
val.list.map((item) => {
item.map((i) => {
// 创建折线
let arr = []
i.path.map((j) => {
arr.push(new BMapGL.Point(j[0], j[1]))
})
var polyline = new BMapGL.Polyline(arr, {
strokeColor: '#1EBA29',
strokeWeight: 4,
strokeOpacity: 0.8
})
map.value.addOverlay(polyline)
})
})
}
onMounted(() => {
getSpotList()
})
</script>
<style lang="scss" scoped>
:deep(.BMap_cpyCtrl) {
display: none;
}
:deep(.anchorBL) {
display: none;
}
.map {
width: 100%;
height: vh(700);
background-color: transparent;
}
.box-3 {
width: vw(1614);
height: vh(950);
margin-top: vh(120);
.header {
width: vw(1614);
height: vh(128);
@@ -163,7 +238,7 @@
background-size: 100% 100%;
.left {
display: flex;
width: vw(950);
width: vw(890);
margin-top: vh(20);
}
.right {
@@ -176,7 +251,7 @@
.label {
margin-bottom: vh(20);
font-weight: 400;
font-size: vw(16);
font-size: vw(18);
color: rgba(255, 255, 255, 0.9);
}
.value {
@@ -224,6 +299,26 @@
}
}
}
.spot-wrap {
position: absolute;
bottom: vw(20);
left: vw(20);
z-index: 99999;
}
.spot-list {
display: flex;
align-items: center;
}
.spot-item {
cursor: pointer;
width: vw(80);
height: vw(80);
margin-right: vw(10);
> img {
width: 100%;
height: 100%;
}
}
.footer {
display: flex;
width: 100%;

View File

@@ -204,7 +204,7 @@
v-for="(item, index) in homeData?.carShipData?.car.info"
:key="index"
>
<div>{{ item.scenic_area }}</div>
<div>{{ item.name }}</div>
<div>{{ item.started_count }}<span class="unit-1"></span></div>
<div>{{ item.not_started_count }}<span class="unit-1"></span></div>
</div>
@@ -213,7 +213,7 @@
</div>
<div>
<div class="ship">
<div class="label">总数</div>
<div class="label">总数</div>
<div class="flex align-center">
<countup class="value" :end-val="homeData?.carShipData?.ship?.count || 0" />
<span class="unit"></span>
@@ -231,7 +231,7 @@
v-for="(item, index) in homeData?.carShipData.ship.info"
:key="index"
>
<div>白帝城</div>
<div>{{ item.name }}</div>
<div>{{ item.started_count }}<span class="unit-1"></span></div>
<div>{{ item.not_started_count }}<span class="unit-1"></span></div>
</div>
@@ -366,7 +366,7 @@
}
.stop-box {
display: flex;
gap: vw(20);
gap: vw(8);
& > div {
flex: 1;

View File

@@ -90,21 +90,19 @@
},
detail: {
width: '100%',
lineHeight: 20,
height: 20,
offsetCenter: [0, '20%'],
valueAnimation: true,
formatter: function (value) {
return '{value|' + value.toFixed(0) + '}{unit|%}'
return '{value|' + value + '}{unit|%}'
},
rich: {
value: {
fontSize: fitChartSize(12),
fontSize: fitChartSize(18),
fontWeight: 'bolder',
color: '#02F9FA'
},
unit: {
fontSize: fitChartSize(12),
fontSize: fitChartSize(18),
color: '#02F9FA'
}
}

View File

@@ -1,3 +1,4 @@
<!-- 酒店入住人数及入住率 -->
<template>
<div class="lodging-ratio" :id="id" />
</template>
@@ -9,10 +10,61 @@
const { id, setOption } = useEchart()
const homeData = inject('homeData')
let params = null
watch(
() => homeData.value?.hotelData?.list,
() => {
setOption({
init()
}
)
const setSeriesData = () => {
return homeData.value?.hotelData?.list.map((item) => {
return {
name: item.hotel_name,
value: item.occupancy_rate,
itemStyle: {
barBorderRadius: [0, 0, 0, 0],
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(255, 112, 33, 0)'
},
{
offset: 1,
color: parseFloat(item.occupancy_rate) > 50 ? '#FF7021' : '#00CCFF'
}
]
}
}
}
})
}
const setCircleData = () => {
return homeData.value?.hotelData?.list.map((item) => {
return {
name: item.hotel_name,
value: item.occupancy_rate,
itemStyle: {
color: '#fff',
opacity: 1
}
}
})
}
const init = () => {
if (!params) {
params = {
backgroundColor: 'transparent',
tooltip: {
show: false
@@ -30,20 +82,20 @@
xAxis: [{ max: 100, show: false }],
yAxis: [
{
type: 'category',
splitLine: {
show: false
},
axisLine: {
show: false
},
type: 'category',
axisTick: {
show: false
},
data: homeData.value?.hotelData?.list.map((item) => item.hotel_name),
axisLabel: {
show: false
}
},
data: homeData.value?.hotelData?.list.map((item) => item.hotel_name)
},
{
type: 'category',
@@ -56,23 +108,21 @@
fontSize: fitChartSize(12)
},
verticalAlign: 'bottom',
padding: [0, 0, fitChartSize(6), 0],
padding: [0, 0, 6, 0],
inside: true,
formatter: function (value) {
return `{value|${value}}`
return `{value|${value}} {value|%}`
},
rich: {
name: {
align: 'center',
color: '#D3E5FF',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
fontSize: fitChartSize(14)
},
value: {
align: 'center',
color: '#fff',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
fontSize: fitChartSize(14)
}
}
},
@@ -81,54 +131,27 @@
],
series: [
{
name: '',
name: '内圆',
type: 'bar',
barWidth: fitChartSize(4),
MaxSize: 0,
barWidth: 4,
showBackground: true,
barBorderRadius: [30, 0, 0, 30],
barBorderRadius: [0, 0, 0, 0],
backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)'
},
label: {
show: true,
offset: [fitChartSize(10), -fitChartSize(20)],
offset: [6, -10],
color: '#D3E5FF',
fontWeight: 500,
position: 'left',
align: 'left',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN',
formatter: function (params) {
return params.data.name
}
},
data: homeData.value?.hotelData?.list.map((item) => {
return {
name: item.hotel_name,
value: item.occupancy_rate,
itemStyle: {
barBorderRadius: [3, 0, 0, 3],
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(255, 112, 33, 0)'
},
{
offset: 1,
color: 'rgba(255, 112, 33, 1)'
}
]
}
}
}
})
data: setSeriesData()
},
{
name: '外圆',
@@ -140,22 +163,17 @@
symbol: 'circle',
symbolSize: fitChartSize(10),
z: 2,
data: homeData.value?.hotelData?.list.map((item) => {
return {
name: item.hotel_name,
value: item.occupancy_rate,
itemStyle: {
color: '#fff',
opacity: 1
}
}
}),
data: setCircleData(),
animationDelay: 500
}
]
})
}
} else {
params.series[0].data = setSeriesData()
params.series[1].data = setCircleData()
}
)
setOption(params)
}
</script>
<style scoped lang="scss">

View File

@@ -1,5 +1,19 @@
<template>
<div class="ticket" :id="id" />
<div>
<div class="ticket" :id="id" />
<!-- <div class="legend">
<ul class="legend__wrapper">
<li
class="legend-item"
v-for="(item, index) in homeData?.userPortrait?.channel"
:key="index"
>
<p class="legend-item-label">{{ item.name }}</p>
<p class="legend-item-value">{{ item.value }}%</p>
</li>
</ul>
</div> -->
</div>
</template>
<script setup>
@@ -12,13 +26,51 @@
let x = 15
let y = 25
let params = null
watch(
() => homeData.value?.userPortrait?.channel,
() => {
setOption({
(val) => {
if (val) init()
},
{
immediate: true
}
)
const setSeries = () => {
return homeData.value?.userPortrait?.channel.map((item, index) => {
return {
name: item.name,
clockwise: false,
type: 'pie',
radius: [`${x * (index + 1)}%`, `${y + index * 15}%`],
center: ['50%', '40%'],
label: { show: false },
labelLine: { show: false },
emphasis: { show: false },
data: [
{
value: parseFloat(item.value),
name: item.name
},
{
value: 100,
itemStyle: {
color: '#07439C'
}
}
]
}
})
}
const init = () => {
if (!params) {
params = {
backgroundColor: 'transparent',
legend: {
show: true,
x: 'center',
y: 'bottom',
itemHeight: fitChartSize(8),
@@ -41,35 +93,13 @@
}
},
color: ['#F15A25', '#01FEFE', '#12B5FD'],
series:
homeData.value?.userPortrait?.channel ||
[].map((item, index) => {
return {
name: item.name,
type: 'pie',
clockwise: false, //顺时加载
radius: [`${x * (index + 1)}%`, `${y + index * 15}%`],
center: ['50%', '40%'],
label: { show: false },
labelLine: { show: false },
emphasis: { show: false },
data: [
{
value: parseFloat(item.value),
name: item.name
},
{
value: 100,
itemStyle: {
color: '#07439C'
}
}
]
}
})
})
series: setSeries()
}
} else {
params.series = setSeries()
}
)
setOption(params)
}
</script>
<style scoped lang="scss">
@@ -77,4 +107,69 @@
width: 100%;
height: vh(200);
}
.legend {
display: flex;
align-items: center;
justify-content: center;
@mixin icon($column) {
padding: 0 vw(10);
height: vh(70);
display: flex;
flex-direction: $column;
align-items: center;
justify-content: center;
}
&__wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: vw(8);
}
&-item {
color: #fff;
}
&-item:nth-child(1) {
@include icon(column);
background-image: url('@/assets/images/legend-item-1.png');
background-size: 100% 100%;
}
&-item:nth-child(2) {
@include icon(column);
background-image: url('@/assets/images/legend-item-1.png');
background-size: 100% 100%;
}
&-item:nth-child(3) {
@include icon(column);
background-image: url('@/assets/images/legend-item-1.png');
background-size: 100% 100%;
}
&-item:nth-child(4) {
@include icon(column-reverse);
background-image: url('@/assets/images/legend-item-2.png');
background-size: 100% 100%;
}
&-item:nth-child(5) {
@include icon(column-reverse);
background-image: url('@/assets/images/legend-item-2.png');
background-size: 100% 100%;
}
&-item:nth-child(6) {
@include icon(column-reverse);
background-image: url('@/assets/images/legend-item-2.png');
background-size: 100% 100%;
}
&-item-label {
font-weight: 400;
font-size: vw(12);
line-height: vh(14);
}
&-item-value {
font-weight: bold;
font-size: vw(16);
line-height: vh(18);
}
}
</style>

View File

@@ -51,26 +51,19 @@
axisLabel: {
textStyle: {
color: '#fff',
fontSize: fitChartSize(12)
fontSize: fitChartSize(18)
},
verticalAlign: 'bottom',
padding: [0, 0, fitChartSize(10), 0],
padding: [0, -fitChartSize(10), fitChartSize(10), 0],
inside: true,
formatter: function (value) {
return `{value|${value}}%`
},
rich: {
name: {
align: 'center',
color: '#D3E5FF',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
},
value: {
align: 'center',
color: '#fff',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
fontSize: fitChartSize(14)
}
}
},
@@ -79,51 +72,32 @@
],
series: [
{
name: '',
type: 'bar',
barWidth: fitChartSize(12),
MaxSize: 0,
showBackground: true,
barBorderRadius: [fitChartSize(30), 0, 0, fitChartSize(30)],
barBorderRadius: [0, 0, 0, 0],
backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)'
},
label: {
show: true,
offset: [fitChartSize(10), -fitChartSize(17)],
offset: [fitChartSize(12), -fitChartSize(20)],
color: '#D3E5FF',
fontWeight: 500,
position: 'left',
align: 'left',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN',
formatter: function (params) {
return params.data.name
return params.data.name ?? '其他'
}
},
data: homeData.value?.userPortrait?.provinceRate.map((item, index) => {
data: homeData.value?.userPortrait?.provinceRate.map((item) => {
return {
name: item.name,
value: Number(item.value),
itemStyle: {
barBorderRadius: [3, 0, 0, 3],
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: 'transparent'
},
{
offset: 1,
color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
}
]
}
barBorderRadius: [0, 0, 0, 0],
color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
}
}
})