feat:重新对接首页接口
This commit is contained in:
@@ -11,8 +11,8 @@ export function getWeatherApi() {
|
|||||||
// 核心景区视频
|
// 核心景区视频
|
||||||
export function getVideoListApi(data) {
|
export function getVideoListApi(data) {
|
||||||
return request({
|
return request({
|
||||||
url: 'http://36.138.38.16:6180/fjtcc-api/api/video/list',
|
url: '/api/largeScreen/video/list',
|
||||||
method: 'get',
|
method: 'post',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -20,8 +20,8 @@ export function getVideoListApi(data) {
|
|||||||
// 刷新播放地址
|
// 刷新播放地址
|
||||||
export function postRefreshApi(data) {
|
export function postRefreshApi(data) {
|
||||||
return request({
|
return request({
|
||||||
url: 'http://36.138.38.16:6180/fjtcc-api/api/video/refresh',
|
url: '/api/largeScreen/video/refresh',
|
||||||
method: 'POST',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import axios from 'axios'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
//
|
||||||
|
let devToken =
|
||||||
|
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImE1OWFmNWYwLTU3OWItNDJkNy1hZDJhLTY0Y2JlODA5ZWI1NiJ9.BTxvu6jUWbN0qONWf5K6VzXopE8T8qXzKuX-mij21VJT4U0LdgnqToyqeNDQ2OyJ6cvpdJBzQ9mEEb-dnwrTpQ'
|
||||||
|
let proToken =
|
||||||
|
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImE1OWFmNWYwLTU3OWItNDJkNy1hZDJhLTY0Y2JlODA5ZWI1NiJ9.dSLZekRsYf5ZZDCYqFEOgHTi4GeHD0m10gGHXrbgpc-hD52Zt7Vw05cxhQ-lzY29yf2IxH0oYi28DBfHdtf9SA'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,11 +14,11 @@ const router = useRouter()
|
|||||||
*/
|
*/
|
||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
// baseURL: 'http://36.138.38.16:6180/fjtcc-api',
|
// baseURL: 'http://36.138.38.16:6180/fjtcc-api',
|
||||||
baseURL: 'http://36.138.38.16:8001/fjtcc-api',
|
// baseURL: 'http://36.138.38.16:8001/fjtcc-api',
|
||||||
|
baseURL: ' http://172.22.15.170/fjtcc-api',
|
||||||
timeout: 100000,
|
timeout: 100000,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization:
|
Authorization: proToken,
|
||||||
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImE1OWFmNWYwLTU3OWItNDJkNy1hZDJhLTY0Y2JlODA5ZWI1NiJ9.BTxvu6jUWbN0qONWf5K6VzXopE8T8qXzKuX-mij21VJT4U0LdgnqToyqeNDQ2OyJ6cvpdJBzQ9mEEb-dnwrTpQ',
|
|
||||||
'Content-Type': 'application/json;charset=UTF-8'
|
'Content-Type': 'application/json;charset=UTF-8'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -55,16 +55,13 @@
|
|||||||
list.value.forEach(async (item, index) => {
|
list.value.forEach(async (item, index) => {
|
||||||
var video = document.getElementById(`video${index}`)
|
var video = document.getElementById(`video${index}`)
|
||||||
let res1 = await postRefreshApi({
|
let res1 = await postRefreshApi({
|
||||||
|
type: 'hls',
|
||||||
businessVideoDisplayPosition: item.businessVideoDisplayPosition,
|
businessVideoDisplayPosition: item.businessVideoDisplayPosition,
|
||||||
cameraIndexCode: item.cameraIndexCode
|
cameraIndexCode: item.cameraIndexCode
|
||||||
})
|
})
|
||||||
let hlsUrl = res1.data.hlsUrl.replace(
|
item.hlsUrl = res1.data.hlsUrl
|
||||||
'http://172.22.15.170:8050',
|
|
||||||
'http://36.138.38.16:6150'
|
|
||||||
)
|
|
||||||
item.hlsUrl = hlsUrl
|
|
||||||
const hls = new Hls()
|
const hls = new Hls()
|
||||||
hls.loadSource(hlsUrl)
|
hls.loadSource(res1.data.hlsUrl)
|
||||||
hls.attachMedia(video)
|
hls.attachMedia(video)
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
video.play()
|
video.play()
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
height: vh(28);
|
height: vh(28);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(12);
|
font-size: vw(12);
|
||||||
color: #0096ff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
background: linear-gradient(180deg, rgba(0, 99, 255, 0) 0%, #0063ff 100%);
|
background: linear-gradient(180deg, rgba(0, 99, 255, 0) 0%, #0063ff 100%);
|
||||||
& > div {
|
& > div {
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
const toOrderNum = (num) => {
|
const toOrderNum = (num) => {
|
||||||
num = num.toString()
|
num = num.toString()
|
||||||
orderNum.value = num.split('') // 将其便变成数据,渲染至滚动数组
|
orderNum.value = num.split('') // 将其便变成数据,渲染至滚动数组
|
||||||
nextTick(() => {
|
setTimeout(() => {
|
||||||
setNumberTransform()
|
setNumberTransform()
|
||||||
})
|
}, 500)
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => props.count,
|
() => props.count,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
|
const homeStore = useHomeStore()
|
||||||
|
|
||||||
export function useWebSocket(url) {
|
export function useWebSocket(url) {
|
||||||
let socket = ref(null) // socket对象
|
let socket = ref(null) // socket对象
|
||||||
let data = ref(null) // 存储接收到的数据
|
|
||||||
let isConnected = ref(false) // 是否连接成功
|
let isConnected = ref(false) // 是否连接成功
|
||||||
|
|
||||||
const connectWebSocket = () => {
|
const connectWebSocket = () => {
|
||||||
@@ -21,9 +23,47 @@ export function useWebSocket(url) {
|
|||||||
}
|
}
|
||||||
socket.value.onmessage = (message) => {
|
socket.value.onmessage = (message) => {
|
||||||
// 处理接收到的消息
|
// 处理接收到的消息
|
||||||
console.log('Received message:', JSON.parse(message.data))
|
|
||||||
if (JSON.parse(message.data)) {
|
if (JSON.parse(message.data)) {
|
||||||
data.value = JSON.parse(message.data)
|
let data = JSON.parse(message.data)
|
||||||
|
console.log(data, '接收到的消息')
|
||||||
|
switch (data.type) {
|
||||||
|
case 'userPortrait':
|
||||||
|
homeStore.setUserPortraitData(data.data)
|
||||||
|
break
|
||||||
|
case 'admission':
|
||||||
|
homeStore.setScenicData(data)
|
||||||
|
break
|
||||||
|
case 'queuingInScenicSpots':
|
||||||
|
homeStore.setScenicQueueData(data)
|
||||||
|
break
|
||||||
|
case 'queuingScenicSpots':
|
||||||
|
homeStore.setScenicBearData(data)
|
||||||
|
break
|
||||||
|
case 'visitorInfo':
|
||||||
|
homeStore.setVisitorInfoData(data.data)
|
||||||
|
break
|
||||||
|
case 'visitorDataInfo':
|
||||||
|
homeStore.setVisitorInfoList(data.data)
|
||||||
|
break
|
||||||
|
case 'baiduMap':
|
||||||
|
homeStore.setBaiduMapData(data.data)
|
||||||
|
break
|
||||||
|
case 'wordkOrderlist':
|
||||||
|
homeStore.setWordkOrderList(data.data)
|
||||||
|
break
|
||||||
|
case 'trafficInformation':
|
||||||
|
homeStore.setTrafficInfoData(data)
|
||||||
|
break
|
||||||
|
case 'carStopInfo':
|
||||||
|
homeStore.setCarStopInfoData(data)
|
||||||
|
break
|
||||||
|
case 'carShipData':
|
||||||
|
homeStore.setCarShipData(data.data)
|
||||||
|
break
|
||||||
|
case 'hotelData':
|
||||||
|
homeStore.setHotelData(data.data)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.value.onclose = () => {
|
socket.value.onclose = () => {
|
||||||
@@ -47,5 +87,5 @@ export function useWebSocket(url) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return { socket, data, isConnected, connectWebSocket, sendMessage }
|
return { socket, isConnected, connectWebSocket, sendMessage }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import { ref, computed } from 'vue'
|
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useCounterStore = defineStore('counter', () => {
|
|
||||||
const count = ref(0)
|
|
||||||
const doubleCount = computed(() => count.value * 2)
|
|
||||||
function increment() {
|
|
||||||
count.value++
|
|
||||||
}
|
|
||||||
|
|
||||||
return { count, doubleCount, increment }
|
|
||||||
})
|
|
||||||
143
src/stores/home.js
Normal file
143
src/stores/home.js
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useHomeStore = defineStore('home', () => {
|
||||||
|
// 景区信息数据
|
||||||
|
let scenicData = ref({
|
||||||
|
scenicSpot: [
|
||||||
|
{ value: 0, name: '全县景区数量' },
|
||||||
|
{ value: 0, name: '核心景区数' },
|
||||||
|
{ value: 0, name: '低感景区总数' }
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{ name: '当日购票量:', value: 0 },
|
||||||
|
{ name: '未来3天购票量:', value: 0 },
|
||||||
|
{ name: '3天后购票量:', value: 0 }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
// 景区排队数据
|
||||||
|
let scenicQueueData = ref({
|
||||||
|
dataList: [],
|
||||||
|
info: []
|
||||||
|
})
|
||||||
|
// 景区承载量
|
||||||
|
let scenicBearData = ref({
|
||||||
|
dataList: [],
|
||||||
|
info: []
|
||||||
|
})
|
||||||
|
// 用户画像数据
|
||||||
|
let userPortraitData = ref({
|
||||||
|
genderRate: [],
|
||||||
|
provinceRate: [],
|
||||||
|
channel: [],
|
||||||
|
ageRate: []
|
||||||
|
})
|
||||||
|
// 景区游客统计
|
||||||
|
let visitorInfoData = ref({
|
||||||
|
total_count_this_year: 0,
|
||||||
|
total_count_today: 0,
|
||||||
|
total_count_today_within_three_hours: 0
|
||||||
|
})
|
||||||
|
// 景区拥堵情况统计
|
||||||
|
let visitorInfoList = ref([])
|
||||||
|
// 百度地图数据
|
||||||
|
let baiduMapData = ref(null)
|
||||||
|
// 工单列表
|
||||||
|
let wordkOrderList = ref([])
|
||||||
|
// 交通信息
|
||||||
|
let trafficInfoData = ref({
|
||||||
|
data: {
|
||||||
|
congestion: [],
|
||||||
|
congestionList: [],
|
||||||
|
countItem: {
|
||||||
|
max_congestion_duration: 0,
|
||||||
|
now_yongdu_sum: 0,
|
||||||
|
yongdu_luduan_count: 0,
|
||||||
|
yongdu_sum: 0
|
||||||
|
},
|
||||||
|
countRate: [],
|
||||||
|
timeRate: []
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
dqydld: 0,
|
||||||
|
ldzs: 0,
|
||||||
|
zdydsc: 0,
|
||||||
|
zydcs: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 停车信息
|
||||||
|
let carStopInfoData = ref({
|
||||||
|
countInfo: { ckzs: 0, ysycws: 0, zcws: 0 },
|
||||||
|
dataList: [],
|
||||||
|
dataList1: [],
|
||||||
|
dataList2: [],
|
||||||
|
spotInfo: []
|
||||||
|
})
|
||||||
|
// 车船信息
|
||||||
|
let carShipData = ref(null)
|
||||||
|
// 酒店数据
|
||||||
|
let hotelData = ref(null)
|
||||||
|
|
||||||
|
const setVisitorInfoList = (val) => {
|
||||||
|
visitorInfoList.value = val
|
||||||
|
}
|
||||||
|
const setHotelData = (val) => {
|
||||||
|
hotelData.value = val
|
||||||
|
}
|
||||||
|
const setCarShipData = (val) => {
|
||||||
|
carShipData.value = val
|
||||||
|
}
|
||||||
|
const setCarStopInfoData = (val) => {
|
||||||
|
carStopInfoData.value = val
|
||||||
|
}
|
||||||
|
const setTrafficInfoData = (val) => {
|
||||||
|
trafficInfoData.value = val
|
||||||
|
}
|
||||||
|
const setVisitorInfoData = (val) => {
|
||||||
|
visitorInfoData.value = val
|
||||||
|
}
|
||||||
|
const setScenicBearData = (val) => {
|
||||||
|
scenicBearData.value = val
|
||||||
|
}
|
||||||
|
const setScenicQueueData = (val) => {
|
||||||
|
scenicQueueData.value = val
|
||||||
|
}
|
||||||
|
const setWordkOrderList = (val) => {
|
||||||
|
wordkOrderList.value = val
|
||||||
|
}
|
||||||
|
const setBaiduMapData = (val) => {
|
||||||
|
baiduMapData.value = val
|
||||||
|
}
|
||||||
|
const setScenicData = (val) => {
|
||||||
|
scenicData.value = val
|
||||||
|
}
|
||||||
|
const setUserPortraitData = (val) => {
|
||||||
|
userPortraitData.value = val
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
scenicData,
|
||||||
|
userPortraitData,
|
||||||
|
baiduMapData,
|
||||||
|
wordkOrderList,
|
||||||
|
scenicQueueData,
|
||||||
|
scenicBearData,
|
||||||
|
visitorInfoData,
|
||||||
|
visitorInfoList,
|
||||||
|
trafficInfoData,
|
||||||
|
carStopInfoData,
|
||||||
|
carShipData,
|
||||||
|
hotelData,
|
||||||
|
setScenicData,
|
||||||
|
setUserPortraitData,
|
||||||
|
setBaiduMapData,
|
||||||
|
setWordkOrderList,
|
||||||
|
setScenicQueueData,
|
||||||
|
setScenicBearData,
|
||||||
|
setVisitorInfoData,
|
||||||
|
setVisitorInfoList,
|
||||||
|
setTrafficInfoData,
|
||||||
|
setCarStopInfoData,
|
||||||
|
setCarShipData,
|
||||||
|
setHotelData
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -5,18 +5,19 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import { useEchart } from '@/hooks/echart'
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
|
const homeStore = useHomeStore()
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
|
||||||
|
|
||||||
let params = null
|
let params = null
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => homeData.value?.userPortrait?.ageRate,
|
() => homeStore.userPortraitData?.ageRate,
|
||||||
() => {
|
(val) => {
|
||||||
init()
|
if (val.length > 0) init()
|
||||||
}
|
},
|
||||||
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
const init = () => {
|
const init = () => {
|
||||||
if (!params) {
|
if (!params) {
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
itemWidth: fitChartSize(8),
|
itemWidth: fitChartSize(8),
|
||||||
itemGap: fitChartSize(10),
|
itemGap: fitChartSize(10),
|
||||||
formatter: function (name) {
|
formatter: function (name) {
|
||||||
let obj = homeData.value?.userPortrait?.ageRate.find((item) => item.name == name)
|
let obj = homeStore.userPortraitData?.ageRate.find((item) => item.name == name)
|
||||||
return '{name|' + name + '} {value|' + obj.value + '}{value|%}'
|
return '{name|' + name + '} {value|' + obj.value + '}{value|%}'
|
||||||
},
|
},
|
||||||
textStyle: {
|
textStyle: {
|
||||||
@@ -63,7 +64,7 @@
|
|||||||
color: '#D3F0FE',
|
color: '#D3F0FE',
|
||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
data: homeData.value?.userPortrait?.ageRate || []
|
data: homeStore.userPortraitData?.ageRate || []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
@@ -81,7 +82,7 @@
|
|||||||
color: '#D3F0FE',
|
color: '#D3F0FE',
|
||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
data: homeData.value?.userPortrait?.ageRate || []
|
data: homeStore.userPortraitData?.ageRate || []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
</template>
|
</template>
|
||||||
</Title1>
|
</Title1>
|
||||||
<div class="list flex pt-20">
|
<div class="list flex pt-20">
|
||||||
<div class="item" v-for="(item, index) in scenicSpot" :key="index">
|
<div class="item" v-for="(item, index) in homeStore.scenicData.scenicSpot" :key="index">
|
||||||
<img v-if="index == 0" class="item-icon" src="@/assets/images/core.png" />
|
<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 == 1" class="item-icon" src="@/assets/images/queue.png" />
|
||||||
<img v-if="index == 2" class="item-icon" src="@/assets/images/congestion.png" />
|
<img v-if="index == 2" class="item-icon" src="@/assets/images/congestion.png" />
|
||||||
<span class="item-label">{{ item.name }}</span>
|
<span class="item-label">{{ item.name }}</span>
|
||||||
<div class="item-value flex align-end rela">
|
<div class="item-value flex align-end rela">
|
||||||
<countup :end-val="item.value || 0" /><span class="unit">个</span>
|
<countup :end-val="item.value" /><span class="unit">个</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,90 +20,44 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<Title2 title="景区排队人数" />
|
<Title2 title="景区排队人数" />
|
||||||
<div class="statistic">
|
<div class="statistic">
|
||||||
<div class="statistic-item">
|
<div
|
||||||
<span class="statistic-title">三峡之巅</span>
|
class="statistic-item"
|
||||||
<span class="statistic-value">
|
v-for="(item, index) in homeStore.scenicQueueData.info"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<span class="statistic-title">{{ item.name }}</span>
|
||||||
|
<span v-if="item.value > 0" class="statistic-value">
|
||||||
<span class="prefix">排队</span>
|
<span class="prefix">排队</span>
|
||||||
<span class="value">100</span>
|
<!-- <span class="value">{{ item.value }}</span> -->
|
||||||
|
<countup class="value" :end-val="item.value" />
|
||||||
<span class="suffix">人</span>
|
<span class="suffix">人</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
<span v-else class="statistic-value">{{ item.value }}</span>
|
||||||
<div class="statistic-item">
|
|
||||||
<span class="statistic-title">白帝城</span>
|
|
||||||
<span class="statistic-value">通畅</span>
|
|
||||||
</div>
|
|
||||||
<div class="statistic-item">
|
|
||||||
<span class="statistic-title">天坑地缝</span>
|
|
||||||
<span class="statistic-value">通畅</span>
|
|
||||||
</div>
|
|
||||||
<div class="statistic-item">
|
|
||||||
<span class="statistic-title">永安宫</span>
|
|
||||||
<span class="statistic-value">通畅</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex rela">
|
<div class="flex rela">
|
||||||
<Title3 title="景区排队人数" />
|
<Title3 title="景区排队人数" />
|
||||||
<div class="dropdown">
|
|
||||||
<Dropdown
|
|
||||||
label="选择排队景区"
|
|
||||||
:options="[
|
|
||||||
{ label: '山峡之巅', value: 100 },
|
|
||||||
{ label: '白帝城', value: 100 },
|
|
||||||
{ label: '龙桥河', value: 100 }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-20">
|
<div class="pt-20">
|
||||||
<Line
|
<Line
|
||||||
:width="370"
|
:width="370"
|
||||||
:height="140"
|
:height="140"
|
||||||
:config="{ legend: false }"
|
:config="{ legend: false }"
|
||||||
:data="[
|
:data="scenicQueueList"
|
||||||
{
|
:xAxisData="scenicQueueXAxisData"
|
||||||
name: '企业数',
|
|
||||||
data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
:xAxisData="[
|
|
||||||
'12-16 10:00',
|
|
||||||
'12-16 14:00',
|
|
||||||
'12-16 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-17 02:00',
|
|
||||||
'12-17 06:00',
|
|
||||||
'12-17 10:00',
|
|
||||||
'12-17 14:00',
|
|
||||||
'12-17 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-18 02:00',
|
|
||||||
'12-18 06:00',
|
|
||||||
'12-8 10:00',
|
|
||||||
'12-18 14:00',
|
|
||||||
'12-18 16:00',
|
|
||||||
'12-18 20:00'
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<Title2 title="景区承载量" />
|
<Title2 title="景区承载量" />
|
||||||
<div class="statistic">
|
<div class="statistic">
|
||||||
<div class="statistic-item">
|
<div
|
||||||
<gauge :value="80" />
|
class="statistic-item"
|
||||||
<span class="statistic-title">三峡之巅</span>
|
v-for="(item, index) in homeStore.scenicBearData.info"
|
||||||
</div>
|
:key="index"
|
||||||
<div class="statistic-item">
|
>
|
||||||
<gauge :value="50" />
|
<gauge :value="item.value" />
|
||||||
<span class="statistic-title">三峡之巅</span>
|
<span class="statistic-title">{{ item.name }}</span>
|
||||||
</div>
|
|
||||||
<div class="statistic-item">
|
|
||||||
<gauge :value="50" />
|
|
||||||
<span class="statistic-title">三峡之巅</span>
|
|
||||||
</div>
|
|
||||||
<div class="statistic-item">
|
|
||||||
<gauge :value="50" />
|
|
||||||
<span class="statistic-title">三峡之巅</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Title3 title="今日景区承载量" />
|
<Title3 title="今日景区承载量" />
|
||||||
@@ -112,30 +66,8 @@
|
|||||||
:width="370"
|
:width="370"
|
||||||
:height="140"
|
:height="140"
|
||||||
:config="{ legend: false }"
|
:config="{ legend: false }"
|
||||||
:data="[
|
:data="scenicBearList"
|
||||||
{
|
:xAxisData="scenicBearXAxisData"
|
||||||
name: '企业数',
|
|
||||||
data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
:xAxisData="[
|
|
||||||
'12-16 10:00',
|
|
||||||
'12-16 14:00',
|
|
||||||
'12-16 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-17 02:00',
|
|
||||||
'12-17 06:00',
|
|
||||||
'12-17 10:00',
|
|
||||||
'12-17 14:00',
|
|
||||||
'12-17 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-18 02:00',
|
|
||||||
'12-18 06:00',
|
|
||||||
'12-8 10:00',
|
|
||||||
'12-18 14:00',
|
|
||||||
'12-18 16:00',
|
|
||||||
'12-18 20:00'
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -145,7 +77,7 @@
|
|||||||
<Title2 title="景区购票数" />
|
<Title2 title="景区购票数" />
|
||||||
<div class="ticket-wrap">
|
<div class="ticket-wrap">
|
||||||
<img src="@/assets/images/ticket.png" />
|
<img src="@/assets/images/ticket.png" />
|
||||||
<div v-for="(item, index) in admission" :key="index">
|
<div v-for="(item, index) in homeStore.scenicData.data" :key="index">
|
||||||
<span class="label">{{ item.name }}:</span><countup :end-val="item.value" />
|
<span class="label">{{ item.name }}:</span><countup :end-val="item.value" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,10 +88,10 @@
|
|||||||
<div class="age-box">
|
<div class="age-box">
|
||||||
<Title3 title="年龄/性别占比" />
|
<Title3 title="年龄/性别占比" />
|
||||||
<div class="mt-8"> <age /></div>
|
<div class="mt-8"> <age /></div>
|
||||||
<div class="count">总人数:<countup :end-val="ageRateTotal" /></div>
|
<div v-if="ageRateTotal > 0" class="count">总人数:<countup :end-val="ageRateTotal" /></div>
|
||||||
<div
|
<div
|
||||||
class="cell pt-20"
|
class="cell pt-20"
|
||||||
v-for="(item, index) in homeData?.userPortrait.genderRate"
|
v-for="(item, index) in homeStore?.userPortraitData.genderRate"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<img v-if="item.name == '男'" class="icon" src="@/assets/images/man.png" />
|
<img v-if="item.name == '男'" class="icon" src="@/assets/images/man.png" />
|
||||||
@@ -179,14 +111,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<Title3 title="客源地分析TOP5" />
|
<Title3 title="客源地分析TOP5" />
|
||||||
<top />
|
<top />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<Title3 title="购票来源" />
|
<Title3 title="购票来源" />
|
||||||
<div class="count">游客总数:<countup :end-val="channelTotal" /></div>
|
<div v-if="channelTotal > 0" class="count">
|
||||||
<ticket :list="channelData" />
|
游客总数:<countup :end-val="channelTotal" />
|
||||||
|
</div>
|
||||||
|
<ticket />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -198,41 +134,39 @@
|
|||||||
import gauge from './gauge.vue'
|
import gauge from './gauge.vue'
|
||||||
import ticket from './ticket.vue'
|
import ticket from './ticket.vue'
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
const homeStore = useHomeStore()
|
||||||
|
|
||||||
// 景区信息
|
// 今日景区承载量
|
||||||
const scenicSpot = computed(() => {
|
const scenicBearList = computed(() => {
|
||||||
if (homeData.value) return homeData.value?.scenicSpot
|
return [{ data: homeStore.scenicBearData.dataList.map((item) => item.value) }]
|
||||||
return [
|
|
||||||
{ value: 0, name: '全县景区数量' },
|
|
||||||
{ value: 0, name: '核心景区数' },
|
|
||||||
{ value: 0, name: '低感景区总数' }
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
// 景区购票数
|
|
||||||
const admission = computed(() => {
|
const scenicBearXAxisData = computed(() => {
|
||||||
if (homeData.value) return homeData.value?.admission
|
return homeStore.scenicBearData.dataList.map((item) => item.name)
|
||||||
return [
|
|
||||||
{ name: '当日购票量:', value: 0 },
|
|
||||||
{ name: '未来3天购票量:', value: 0 },
|
|
||||||
{ name: '3天后购票量:', value: 0 }
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
// 年龄占比
|
|
||||||
|
// 今日景区排队量
|
||||||
|
const scenicQueueList = computed(() => {
|
||||||
|
return [{ data: homeStore.scenicQueueData.dataList.map((item) => item.value) }]
|
||||||
|
})
|
||||||
|
|
||||||
|
const scenicQueueXAxisData = computed(() => {
|
||||||
|
return homeStore.scenicQueueData.dataList.map((item) => item.name)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 年龄占比 - 游客总数
|
||||||
const ageRateTotal = computed(() => {
|
const ageRateTotal = computed(() => {
|
||||||
return homeData.value?.userPortrait.genderRate.reduce(
|
return homeStore?.userPortraitData?.genderRate.reduce(
|
||||||
(total, current) => Number(current.count) + total,
|
(total, current) => Number(current.count) + total,
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
// 年龄占比
|
|
||||||
const channelData = computed(() => {
|
// 购票来源 - 游客总数
|
||||||
if (homeData.value) return homeData.value?.userPortrait.channel
|
|
||||||
return []
|
|
||||||
})
|
|
||||||
const channelTotal = computed(() => {
|
const channelTotal = computed(() => {
|
||||||
return homeData.value?.userPortrait?.channel.reduce(
|
return homeStore.userPortraitData?.channel.reduce(
|
||||||
(total, current) => Number(current.count) + total,
|
(total, current) => Number(current.count) + total,
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
@@ -326,14 +260,16 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
&-title {
|
&-title {
|
||||||
font-size: vw(18);
|
font-size: vw(16);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: #fff;
|
||||||
}
|
}
|
||||||
&-value {
|
&-value {
|
||||||
margin-top: vh(10);
|
margin-top: vh(10);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: vw(24);
|
font-size: vw(20);
|
||||||
color: #02f9fa;
|
color: #02f9fa;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
.value {
|
.value {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -344,6 +280,7 @@
|
|||||||
.suffix {
|
.suffix {
|
||||||
color: #ff4400;
|
color: #ff4400;
|
||||||
font-size: vw(12);
|
font-size: vw(12);
|
||||||
|
margin-bottom: vh(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +303,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.count {
|
.count {
|
||||||
margin: vw(20) vw(20) 0 vw(20);
|
margin: vh(10) vw(20) 0 vw(20);
|
||||||
height: vh(24);
|
height: vh(24);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: vw(14);
|
font-size: vw(14);
|
||||||
|
|||||||
@@ -5,37 +5,26 @@
|
|||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">今年总游客数</div>
|
<div class="label">今年总游客数</div>
|
||||||
<scroll-number :count="visitorInfo.total_count_this_year" prefix="1" />
|
<scroll-number :count="homeStore.visitorInfoData.total_count_this_year" prefix="1" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">全县景区总游客人数</div>
|
<div class="label">全县景区总游客人数</div>
|
||||||
<scroll-number :count="visitorInfo.total_count_today" prefix="2" />
|
<scroll-number :count="homeStore.visitorInfoData.total_count_today" prefix="2" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">总在园人数</div>
|
<div class="label">总在园人数</div>
|
||||||
<scroll-number :count="visitorInfo.total_count_today_within_three_hours" prefix="3" />
|
<scroll-number
|
||||||
|
:count="homeStore.visitorInfoData.total_count_today_within_three_hours"
|
||||||
|
prefix="3"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="item">
|
<div class="item" v-for="(item, index) in homeStore.visitorInfoList" :key="index">
|
||||||
<div class="label">安全度</div>
|
<div class="label">{{ item.name }}</div>
|
||||||
<div class="value">安全</div>
|
<div :class="[item.type == 1 ? 'value--error' : 'value--primary']">{{
|
||||||
</div>
|
item.value
|
||||||
<div class="item">
|
}}</div>
|
||||||
<div class="label">舒适度</div>
|
|
||||||
<div class="value">舒适</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<div class="label">接待情况</div>
|
|
||||||
<div class="value">排队</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<div class="label">交通拥挤度</div>
|
|
||||||
<div class="value">舒适</div>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<div class="label">停车场负荷度</div>
|
|
||||||
<div class="value">超负荷</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -104,28 +93,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div>
|
||||||
<div class="item">
|
<vue3-seamless-scroll
|
||||||
<span class="item-tag--warning">重要</span>
|
class="right"
|
||||||
<p class="content">
|
:list="homeStore.wordkOrderList"
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
:limitScrollNum="3"
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
:hover="true"
|
||||||
</p>
|
:step="0.2"
|
||||||
</div>
|
:wheel="true"
|
||||||
<div class="item">
|
:isWatch="true"
|
||||||
<span class="item-tag--error">紧急</span>
|
>
|
||||||
<p class="content">
|
<div class="item" v-for="(item, index) in homeStore.wordkOrderList" :key="index">
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
<span :class="`item-tag--${item.level}`">{{ item.level_text }}</span>
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
<p class="content">
|
||||||
</p>
|
{{ item.title }}
|
||||||
</div>
|
</p>
|
||||||
<div class="item">
|
</div>
|
||||||
<span class="item-tag--primary">普通</span>
|
</vue3-seamless-scroll>
|
||||||
<p class="content">
|
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
|
||||||
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,6 +117,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
|
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
|
||||||
import ScrollNumber from '@/components/ScrollNumber/index.vue'
|
import ScrollNumber from '@/components/ScrollNumber/index.vue'
|
||||||
import { getSpotListApi, getBaiduMapCrowdedApi } from '@/api/home'
|
import { getSpotListApi, getBaiduMapCrowdedApi } from '@/api/home'
|
||||||
|
|
||||||
@@ -142,22 +127,14 @@
|
|||||||
import icon11 from '@/assets/images/icon-11.png'
|
import icon11 from '@/assets/images/icon-11.png'
|
||||||
|
|
||||||
import { useMap } from '@/hooks/map'
|
import { useMap } from '@/hooks/map'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
|
const homeStore = useHomeStore()
|
||||||
|
|
||||||
let emit = defineEmits(['switch-spot'])
|
let emit = defineEmits(['switch-spot'])
|
||||||
|
|
||||||
const { map, initMap, addMarker } = useMap()
|
const { map, initMap, addMarker } = useMap()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
|
||||||
|
|
||||||
const visitorInfo = computed(() => {
|
|
||||||
if (homeData.value) return homeData.value?.visitorInfo.data
|
|
||||||
return {
|
|
||||||
total_count_this_year: 0,
|
|
||||||
total_count_today: 0,
|
|
||||||
total_count_today_within_three_hours: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let spotList = ref([])
|
let spotList = ref([])
|
||||||
|
|
||||||
let list = ref([
|
let list = ref([
|
||||||
@@ -185,13 +162,13 @@
|
|||||||
const getSpotList = async () => {
|
const getSpotList = async () => {
|
||||||
let res = await getSpotListApi()
|
let res = await getSpotListApi()
|
||||||
spotList.value = res.data
|
spotList.value = res.data
|
||||||
let res1 = await getBaiduMapCrowdedApi({
|
// let res1 = await getBaiduMapCrowdedApi({
|
||||||
nodeId: res.data[0].nodeid
|
// nodeId: res.data[0].nodeid
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => homeData.value?.baiduMap,
|
() => homeStore?.baiduMapData,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) init(val)
|
if (val) init(val)
|
||||||
},
|
},
|
||||||
@@ -245,7 +222,7 @@
|
|||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
.left {
|
.left {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: vw(890);
|
width: vw(740);
|
||||||
margin-top: vh(20);
|
margin-top: vh(20);
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
@@ -264,8 +241,15 @@
|
|||||||
.value {
|
.value {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: vw(28);
|
font-size: vw(28);
|
||||||
color: #02f9fa;
|
|
||||||
line-height: vh(33);
|
line-height: vh(33);
|
||||||
|
&--error {
|
||||||
|
@extend .value;
|
||||||
|
color: #ff4400;
|
||||||
|
}
|
||||||
|
&--primary {
|
||||||
|
@extend .value;
|
||||||
|
color: #02f9fa;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.countup-wrap {
|
.countup-wrap {
|
||||||
@@ -331,7 +315,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: vh(120);
|
height: vh(120);
|
||||||
background-image: url('@/assets/images/bg-3.png');
|
background-image: url('@/assets/images/bg-3.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 400%;
|
||||||
.left {
|
.left {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -400,13 +384,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.right {
|
.right {
|
||||||
padding: vh(10) vw(24);
|
margin-top: vh(8);
|
||||||
|
padding: vh(10) vw(10);
|
||||||
|
height: vh(106);
|
||||||
|
width: vw(1040);
|
||||||
|
overflow: hidden;
|
||||||
.item {
|
.item {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: vh(12);
|
margin-bottom: vh(10);
|
||||||
&:nth-last-child(1) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
&-tag {
|
&-tag {
|
||||||
padding: 0 vw(16);
|
padding: 0 vw(16);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -417,22 +402,22 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: vw(2);
|
border-radius: vw(2);
|
||||||
}
|
}
|
||||||
&-tag--warning {
|
&-tag--important {
|
||||||
@extend .item-tag;
|
@extend .item-tag;
|
||||||
background: #feae00;
|
background: #feae00;
|
||||||
}
|
}
|
||||||
&-tag--error {
|
&-tag--warn {
|
||||||
@extend .item-tag;
|
@extend .item-tag;
|
||||||
background: #d9011b;
|
background: #d9011b;
|
||||||
}
|
}
|
||||||
&-tag--primary {
|
&-tag--normal {
|
||||||
@extend .item-tag;
|
@extend .item-tag;
|
||||||
background: #2380fb;
|
background: #2380fb;
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
margin-left: vw(4);
|
margin-left: vw(4);
|
||||||
padding: 0 vw(10);
|
padding: 0 vw(10);
|
||||||
width: vw(900);
|
width: vw(950);
|
||||||
height: vh(24);
|
height: vh(24);
|
||||||
line-height: vh(24);
|
line-height: vh(24);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -3,30 +3,30 @@
|
|||||||
<Title1 title="交通信息" />
|
<Title1 title="交通信息" />
|
||||||
<div class="traffic-info flex justify-evenly pt-10 pb-20">
|
<div class="traffic-info flex justify-evenly pt-10 pb-20">
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<img class="icon" :src="icon1" alt="" />
|
<img class="icon" src="@/assets/images/icon-1.png" alt="" />
|
||||||
<div>
|
<div>
|
||||||
<countup :end-val="countItems.now_yongdu_sum" />
|
<countup :end-val="homeStore.trafficInfoData.info.ldzs" />
|
||||||
<div class="label">路段总数</div>
|
<div class="label">路段总数</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<img class="icon" :src="icon2" alt="" />
|
<img class="icon" src="@/assets/images/icon-2.png" alt="" />
|
||||||
<div>
|
<div>
|
||||||
<countup :end-val="countItems.yongdu_luduan_count" />
|
<countup :end-val="homeStore.trafficInfoData.info.dqydld" />
|
||||||
<div class="label">当前拥堵路段</div>
|
<div class="label">当前拥堵路段</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<img class="icon" :src="icon3" alt="" />
|
<img class="icon" src="@/assets/images/icon-3.png" alt="" />
|
||||||
<div>
|
<div>
|
||||||
<countup :end-val="countItems.yongdu_sum" />
|
<countup :end-val="homeStore.trafficInfoData.info.zydcs" />
|
||||||
<div class="label">总拥堵次数</div>
|
<div class="label">总拥堵次数</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<img class="icon" :src="icon4" alt="" />
|
<img class="icon" src="@/assets/images/icon-4.png" alt="" />
|
||||||
<div>
|
<div>
|
||||||
<countup :end-val="countItems.max_congestion_duration" />
|
<countup :end-val="homeStore.trafficInfoData.info.zdydsc" />
|
||||||
<div class="label">最大拥堵时长 </div>
|
<div class="label">最大拥堵时长 </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,13 +47,13 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="pt-10">
|
<div class="pt-10">
|
||||||
<Title3 title="拥堵次数占比" />
|
<Title3 title="拥堵次数占比" />
|
||||||
<jam-count :list="countRate" />
|
<jam-count :list="homeStore.trafficInfoData.data.countRate" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="pt-10">
|
<div class="pt-10">
|
||||||
<Title3 title="拥堵时长" />
|
<Title3 title="拥堵时长" />
|
||||||
<jam-duration :list="timeRate" />
|
<jam-duration :list="homeStore.trafficInfoData.data.timeRate" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,36 +63,27 @@
|
|||||||
<img class="icon" src="@/assets/images/icon-5.png" alt="" />
|
<img class="icon" src="@/assets/images/icon-5.png" alt="" />
|
||||||
<div>
|
<div>
|
||||||
<div class="label">车库总数</div>
|
<div class="label">车库总数</div>
|
||||||
<countup class="value" :end-val="500" />
|
<countup class="value" :end-val="homeStore.carStopInfoData.countInfo.ckzs" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">总车位数</div>
|
<div class="label">总车位数</div>
|
||||||
<countup class="value" :end-val="500" />
|
<countup class="value" :end-val="homeStore.carStopInfoData.countInfo.zcws" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="label">已使用车位数</div>
|
<div class="label">已使用车位数</div>
|
||||||
<countup class="value" :end-val="500" />
|
<countup class="value" :end-val="homeStore.carStopInfoData.countInfo.ysycws" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div v-for="item in homeStore.carStopInfoData.spotInfo">
|
||||||
<div class="label">三峡之巅</div>
|
<div class="label">{{ item.name }}</div>
|
||||||
<div class="value error">已满</div>
|
<div class="value" :class="{ error: item.type == 1, success: item.type == 0 }">
|
||||||
</div>
|
{{ item.value }}
|
||||||
<div>
|
</div>
|
||||||
<div class="label">白帝城</div>
|
|
||||||
<div class="value error">已满</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">天坑地缝</div>
|
|
||||||
<div class="value success">空余</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">永安宫</div>
|
|
||||||
<div class="value success">空余</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex pt-10">
|
<div class="flex pt-10">
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<div class="pt-10">
|
<div class="pt-10">
|
||||||
@@ -102,30 +93,8 @@
|
|||||||
:width="250"
|
:width="250"
|
||||||
:height="150"
|
:height="150"
|
||||||
:config="{ legend: false }"
|
:config="{ legend: false }"
|
||||||
:data="[
|
:data="parkData"
|
||||||
{
|
:xAxisData="parkXAxisData"
|
||||||
name: '企业数',
|
|
||||||
data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
:xAxisData="[
|
|
||||||
'12-16 10:00',
|
|
||||||
'12-16 14:00',
|
|
||||||
'12-16 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-17 02:00',
|
|
||||||
'12-17 06:00',
|
|
||||||
'12-17 10:00',
|
|
||||||
'12-17 14:00',
|
|
||||||
'12-17 16:00',
|
|
||||||
'12-16 22:00',
|
|
||||||
'12-18 02:00',
|
|
||||||
'12-18 06:00',
|
|
||||||
'12-8 10:00',
|
|
||||||
'12-18 14:00',
|
|
||||||
'12-18 16:00',
|
|
||||||
'12-18 20:00'
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,16 +102,17 @@
|
|||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<div class="pt-10">
|
<div class="pt-10">
|
||||||
<Title3 title="车源地" />
|
<Title3 title="车源地" />
|
||||||
<traffic />
|
<vehicle-source :list="homeStore.carStopInfoData.dataList1" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-1">
|
<div class="box-1">
|
||||||
<div class="pt-10">
|
<div class="pt-10">
|
||||||
<Title3 title="景区停车场空位" />
|
<Title3 title="景区停车场空位" />
|
||||||
<vacancy />
|
<vacancy :list="homeStore.carStopInfoData.dataList2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<Title1 title="车船信息" class="title1" />
|
<Title1 title="车船信息" class="title1" />
|
||||||
@@ -151,13 +121,14 @@
|
|||||||
<Title1 title="酒店信息" class="title1" />
|
<Title1 title="酒店信息" class="title1" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="car-ship">
|
<div class="car-ship">
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<div class="car">
|
<div class="car">
|
||||||
<div class="label">车总数</div>
|
<div class="label">车总数</div>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<countup class="value" :end-val="homeData?.carShipData?.car?.count || 0" />
|
<countup class="value" :end-val="homeStore.carShipData?.car?.count || 0" />
|
||||||
<span class="unit">辆</span>
|
<span class="unit">辆</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -169,16 +140,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<vue3-seamless-scroll
|
<vue3-seamless-scroll
|
||||||
:list="homeData?.carShipData?.car.info"
|
v-model="carMove"
|
||||||
|
:list="homeStore.carShipData?.car?.info"
|
||||||
:limitScrollNum="3"
|
:limitScrollNum="3"
|
||||||
:hover="true"
|
:hover="true"
|
||||||
:step="0.2"
|
:step="0.2"
|
||||||
|
:copy-num="0"
|
||||||
:wheel="true"
|
:wheel="true"
|
||||||
:isWatch="true"
|
:isWatch="true"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="cell"
|
class="cell"
|
||||||
v-for="(item, index) in homeData?.carShipData?.car.info"
|
v-for="(item, index) in homeStore.carShipData?.car?.info"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<div>{{ item.name }}</div>
|
<div>{{ item.name }}</div>
|
||||||
@@ -193,7 +166,7 @@
|
|||||||
<div class="ship">
|
<div class="ship">
|
||||||
<div class="label">船总数</div>
|
<div class="label">船总数</div>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<countup class="value" :end-val="homeData?.carShipData?.ship?.count || 0" />
|
<countup class="value" :end-val="homeStore.carShipData?.ship?.count || 0" />
|
||||||
<span class="unit">辆</span>
|
<span class="unit">辆</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -205,16 +178,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<vue3-seamless-scroll
|
<vue3-seamless-scroll
|
||||||
:list="homeData?.carShipData?.car.info"
|
v-model="shipMove"
|
||||||
|
:list="homeStore.carShipData?.ship?.info"
|
||||||
:limitScrollNum="3"
|
:limitScrollNum="3"
|
||||||
:hover="true"
|
:hover="true"
|
||||||
:step="0.2"
|
:step="0.2"
|
||||||
|
:copy-num="0"
|
||||||
:wheel="true"
|
:wheel="true"
|
||||||
:isWatch="true"
|
:isWatch="true"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="cell"
|
class="cell"
|
||||||
v-for="(item, index) in homeData?.carShipData?.ship.info"
|
v-for="(item, index) in homeStore.carShipData?.ship?.info"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<div>{{ item.name }}</div>
|
<div>{{ item.name }}</div>
|
||||||
@@ -230,17 +205,17 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">酒店总数</div>
|
<div class="label">酒店总数</div>
|
||||||
<countup class="value" :end-val="homeData?.hotelData.info.hotel_count || 0" />
|
<countup class="value" :end-val="homeStore.hotelData?.info?.hotel_count || 0" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">房间总数</div>
|
<div class="label">房间总数</div>
|
||||||
<countup class="value" :end-val="homeData?.hotelData.info.total_room_count || 0" />
|
<countup class="value" :end-val="homeStore.hotelData?.info?.total_room_count || 0" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">总入住</div>
|
<div class="label">总入住</div>
|
||||||
<countup
|
<countup
|
||||||
class="value success"
|
class="value success"
|
||||||
:end-val="homeData?.hotelData.info.total_guest_count || 0"
|
:end-val="homeStore.hotelData?.info?.total_guest_count || 0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
@@ -248,7 +223,7 @@
|
|||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<countup
|
<countup
|
||||||
class="value success"
|
class="value success"
|
||||||
:end-val="homeData?.hotelData.info.occupancy_rate || 0"
|
:end-val="homeStore.hotelData?.info?.occupancy_rate || 0"
|
||||||
/>
|
/>
|
||||||
<span class="suffix">%</span>
|
<span class="suffix">%</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -258,7 +233,7 @@
|
|||||||
<div class="occupancy">
|
<div class="occupancy">
|
||||||
<Title3 title="酒店入住人数及入住率" />
|
<Title3 title="酒店入住人数及入住率" />
|
||||||
</div>
|
</div>
|
||||||
<occupancy />
|
<occupancy :list="homeStore.hotelData?.list" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -270,51 +245,32 @@
|
|||||||
import jamCount from './jam-count.vue'
|
import jamCount from './jam-count.vue'
|
||||||
import vacancy from './vacancy.vue'
|
import vacancy from './vacancy.vue'
|
||||||
import occupancy from './occupancy.vue'
|
import occupancy from './occupancy.vue'
|
||||||
import traffic from './traffic.vue'
|
import vehicleSource from './vehicle-source.vue'
|
||||||
import countup from 'vue-countup-v3'
|
import countup from 'vue-countup-v3'
|
||||||
import icon1 from '@/assets/images/icon-1.png'
|
|
||||||
import icon2 from '@/assets/images/icon-2.png'
|
|
||||||
import icon3 from '@/assets/images/icon-3.png'
|
|
||||||
import icon4 from '@/assets/images/icon-4.png'
|
|
||||||
|
|
||||||
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
|
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
const homeStore = useHomeStore()
|
||||||
|
|
||||||
|
const carMove = computed(() => {
|
||||||
|
return homeStore.carShipData?.car?.info.length > 3
|
||||||
|
})
|
||||||
|
const shipMove = computed(() => {
|
||||||
|
return homeStore.carShipData?.ship?.info.length > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
const parkData = computed(() => {
|
||||||
|
return [{ data: homeStore.carStopInfoData.dataList.map((item) => item.value) }]
|
||||||
|
})
|
||||||
|
const parkXAxisData = computed(() => {
|
||||||
|
return homeStore.carStopInfoData.dataList.map((item) => item.name)
|
||||||
|
})
|
||||||
|
|
||||||
const congestionData = computed(() => {
|
const congestionData = computed(() => {
|
||||||
if (homeData.value) {
|
return [{ data: homeStore.trafficInfoData.data.congestion.map((item) => item.value) }]
|
||||||
return [{ data: homeData.value?.trafficInformation?.congestion.map((item) => item.value) }]
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
})
|
})
|
||||||
const congestionXAxisData = computed(() => {
|
const congestionXAxisData = computed(() => {
|
||||||
if (homeData.value) {
|
return homeStore.trafficInfoData.data.congestion.map((item) => item.name)
|
||||||
return homeData.value?.trafficInformation?.congestion.map((item) => item.name)
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
})
|
|
||||||
const countItems = computed(() => {
|
|
||||||
if (homeData.value) {
|
|
||||||
return homeData.value?.trafficInformation?.countItem
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
max_congestion_duration: 0, // 最大拥堵时长
|
|
||||||
now_yongdu_sum: 0,
|
|
||||||
yongdu_luduan_count: 0,
|
|
||||||
yongdu_sum: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const countRate = computed(() => {
|
|
||||||
if (homeData.value) {
|
|
||||||
return homeData.value?.trafficInformation?.countRate
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
})
|
|
||||||
const timeRate = computed(() => {
|
|
||||||
if (homeData.value) {
|
|
||||||
return homeData.value?.trafficInformation?.timeRate
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -466,7 +422,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: vw(12);
|
font-size: vw(12);
|
||||||
color: #52b8ff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
@@ -492,9 +448,12 @@
|
|||||||
line-height: vh(27);
|
line-height: vh(27);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: #074686;
|
background: #074686;
|
||||||
&:nth-child(2n + 1) {
|
&:nth-child(odd) {
|
||||||
background: rgba(0, 150, 255, 0.1);
|
background: rgba(0, 150, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
&:nth-child(even) {
|
||||||
|
background: #074686;
|
||||||
|
}
|
||||||
& > div {
|
& > div {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!-- 景区承载量 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="gauge" :id="id" />
|
<div class="gauge" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
@@ -23,9 +24,14 @@
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
() => {
|
(val) => {
|
||||||
init()
|
if (val) {
|
||||||
}
|
nextTick(() => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
@@ -97,12 +103,12 @@
|
|||||||
},
|
},
|
||||||
rich: {
|
rich: {
|
||||||
value: {
|
value: {
|
||||||
fontSize: fitChartSize(18),
|
fontSize: fitChartSize(14),
|
||||||
fontWeight: 'bolder',
|
fontWeight: 'bolder',
|
||||||
color: '#02F9FA'
|
color: '#02F9FA'
|
||||||
},
|
},
|
||||||
unit: {
|
unit: {
|
||||||
fontSize: fitChartSize(18),
|
fontSize: fitChartSize(14),
|
||||||
color: '#02F9FA'
|
color: '#02F9FA'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,10 +126,6 @@
|
|||||||
}
|
}
|
||||||
setOption(params)
|
setOption(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
init()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!-- 拥堵次数占比 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="jam-count" :id="id" />
|
<div class="jam-count" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
@@ -15,7 +16,8 @@
|
|||||||
|
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
var colorList = ['#FDC40A', '#FF5232', '#50F0A6']
|
let params = null
|
||||||
|
const colorList = ['#FDC40A', '#FF5232', '#50F0A6']
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.list,
|
() => props.list,
|
||||||
@@ -27,7 +29,7 @@
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const setSeriesData = () => {
|
const getSeriesData = () => {
|
||||||
return props.list.map((item) => {
|
return props.list.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
@@ -41,75 +43,80 @@
|
|||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
const init = () => {
|
const init = () => {
|
||||||
setOption({
|
if (!params) {
|
||||||
color: colorList,
|
params = {
|
||||||
grid: {
|
color: colorList,
|
||||||
left: '4%',
|
grid: {
|
||||||
right: '4%',
|
left: '4%',
|
||||||
top: '4%',
|
right: '4%',
|
||||||
bottom: '4%',
|
top: '4%',
|
||||||
containLabel: true
|
bottom: '4%',
|
||||||
},
|
containLabel: true
|
||||||
legend: {
|
|
||||||
orient: 'horizontal',
|
|
||||||
x: 'center',
|
|
||||||
bottom: '-2%',
|
|
||||||
itemHeight: fitChartSize(16),
|
|
||||||
itemWidth: fitChartSize(16),
|
|
||||||
itemGap: fitChartSize(10),
|
|
||||||
formatter: (name) => {
|
|
||||||
let obj = props.list.find((item) => item.name == name)
|
|
||||||
return '{name|' + name + '} {value|' + obj?.count + '}{value|%}'
|
|
||||||
},
|
},
|
||||||
textStyle: {
|
legend: {
|
||||||
rich: {
|
orient: 'horizontal',
|
||||||
name: {
|
x: 'center',
|
||||||
color: '#fff',
|
bottom: '-3%',
|
||||||
fontSize: fitChartSize(12)
|
itemHeight: fitChartSize(12),
|
||||||
},
|
itemWidth: fitChartSize(12),
|
||||||
value: {
|
itemGap: fitChartSize(6),
|
||||||
color: '#00D5F6',
|
formatter: (name) => {
|
||||||
fontSize: fitChartSize(12)
|
let obj = props.list.find((item) => item.name == name)
|
||||||
}
|
return '{name|' + name + '} {value|' + obj?.count + '}{value|%}'
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
center: ['50%', '40%'],
|
|
||||||
radius: ['45%', '60%'],
|
|
||||||
itemStyle: {
|
|
||||||
borderWidth: fitChartSize(4),
|
|
||||||
borderColor: '#093672'
|
|
||||||
},
|
},
|
||||||
label: {
|
textStyle: {
|
||||||
show: true,
|
|
||||||
position: 'center',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
formatter: function (o) {
|
|
||||||
return `{label|拥堵次数}` + '\n' + `{value|${calcCount()}}`
|
|
||||||
},
|
|
||||||
rich: {
|
rich: {
|
||||||
label: {
|
name: {
|
||||||
color: '#7894A8',
|
color: '#fff',
|
||||||
padding: [0, 0, 5, 0],
|
|
||||||
fontSize: fitChartSize(12)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
color: '#fff',
|
color: '#00D5F6',
|
||||||
fontSize: fitChartSize(18),
|
fontSize: fitChartSize(12)
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
labelLine: {
|
},
|
||||||
show: false
|
series: [
|
||||||
},
|
{
|
||||||
data: setSeriesData()
|
type: 'pie',
|
||||||
}
|
center: ['50%', '40%'],
|
||||||
]
|
radius: ['45%', '60%'],
|
||||||
})
|
itemStyle: {
|
||||||
|
borderWidth: fitChartSize(4),
|
||||||
|
borderColor: '#093672'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
formatter: function (o) {
|
||||||
|
return `{label|拥堵次数}` + '\n' + `{value|${calcCount()}}`
|
||||||
|
},
|
||||||
|
rich: {
|
||||||
|
label: {
|
||||||
|
color: '#7894A8',
|
||||||
|
padding: [0, 0, 5, 0],
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(16),
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: getSeriesData()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.series[0].data = getSeriesData()
|
||||||
|
}
|
||||||
|
setOption(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
{
|
{
|
||||||
name: '',
|
name: '',
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: fitChartSize(4),
|
barWidth: fitChartSize(8),
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
barBorderRadius: [0, 0, 0, 0],
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!-- 酒店入住人数及入住率 -->
|
|
||||||
<template>
|
<template>
|
||||||
<div class="lodging-ratio" :id="id" />
|
<!-- 酒店入住人数及入住率 -->
|
||||||
|
<div class="occupancy" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -9,24 +9,29 @@
|
|||||||
|
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
let props = defineProps({
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.list,
|
||||||
|
(val) => {
|
||||||
|
if (val.length > 0) init()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
let params = null
|
let params = null
|
||||||
|
|
||||||
watch(
|
|
||||||
() => homeData.value?.hotelData?.list,
|
|
||||||
() => {
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const setSeriesData = () => {
|
const setSeriesData = () => {
|
||||||
return homeData.value?.hotelData?.list.map((item) => {
|
return props.list.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item.hotel_name,
|
name: item.hotel_name,
|
||||||
value: item.occupancy_rate,
|
value: item.occupancy_rate,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
barBorderRadius: [0, 0, 0, 0],
|
|
||||||
color: {
|
color: {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
x: 0,
|
x: 0,
|
||||||
@@ -40,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
offset: 1,
|
offset: 1,
|
||||||
color: parseFloat(item.occupancy_rate) > 50 ? '#FF7021' : '#00CCFF'
|
color: '#FF7021'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -48,9 +53,8 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const setScatterData = () => {
|
||||||
const setCircleData = () => {
|
return props.list.map((item) => {
|
||||||
return homeData.value?.hotelData?.list.map((item) => {
|
|
||||||
return {
|
return {
|
||||||
name: item.hotel_name,
|
name: item.hotel_name,
|
||||||
value: item.occupancy_rate,
|
value: item.occupancy_rate,
|
||||||
@@ -61,7 +65,9 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const setYAxisData = () => {
|
||||||
|
return props.list.map((item) => item.occupancy_rate)
|
||||||
|
}
|
||||||
const init = () => {
|
const init = () => {
|
||||||
if (!params) {
|
if (!params) {
|
||||||
params = {
|
params = {
|
||||||
@@ -75,30 +81,40 @@
|
|||||||
grid: {
|
grid: {
|
||||||
left: '4%',
|
left: '4%',
|
||||||
right: '4%',
|
right: '4%',
|
||||||
top: '20%',
|
top: '16%',
|
||||||
bottom: '-10%',
|
bottom: '-10%',
|
||||||
containLabel: true
|
containLabel: true
|
||||||
},
|
},
|
||||||
xAxis: [{ max: 100, show: false }],
|
xAxis: [
|
||||||
|
{
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
max: 100,
|
||||||
|
type: 'value',
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
],
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: 'category',
|
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
|
type: 'category',
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
|
data: [],
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: false
|
show: false
|
||||||
},
|
}
|
||||||
data: homeData.value?.hotelData?.list.map((item) => item.hotel_name)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
inverse: true,
|
||||||
axisTick: 'none',
|
axisTick: 'none',
|
||||||
axisLine: 'none',
|
axisLine: 'none',
|
||||||
show: true,
|
show: true,
|
||||||
@@ -111,29 +127,25 @@
|
|||||||
padding: [0, 0, 6, 0],
|
padding: [0, 0, 6, 0],
|
||||||
inside: true,
|
inside: true,
|
||||||
formatter: function (value) {
|
formatter: function (value) {
|
||||||
return `{value|${value}} {value|%}`
|
return `{value|${value}}{value|%}`
|
||||||
},
|
},
|
||||||
rich: {
|
rich: {
|
||||||
name: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#D3E5FF',
|
|
||||||
fontSize: fitChartSize(14)
|
|
||||||
},
|
|
||||||
value: {
|
value: {
|
||||||
align: 'center',
|
align: 'center',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
fontWeight: 600,
|
||||||
fontSize: fitChartSize(14)
|
fontSize: fitChartSize(14)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: homeData.value?.hotelData?.list.map((item) => item.occupancy_rate)
|
data: setYAxisData()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '内圆',
|
name: '',
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: 4,
|
barWidth: fitChartSize(8),
|
||||||
showBackground: true,
|
showBackground: true,
|
||||||
barBorderRadius: [0, 0, 0, 0],
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
backgroundStyle: {
|
backgroundStyle: {
|
||||||
@@ -141,8 +153,8 @@
|
|||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
offset: [6, -10],
|
offset: [10, -10],
|
||||||
color: '#D3E5FF',
|
color: '#fff',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
position: 'left',
|
position: 'left',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
@@ -163,22 +175,22 @@
|
|||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: fitChartSize(10),
|
symbolSize: fitChartSize(10),
|
||||||
z: 2,
|
z: 2,
|
||||||
data: setCircleData(),
|
data: setScatterData(),
|
||||||
animationDelay: 500
|
animationDelay: 500
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
params.series[0].data = setSeriesData()
|
params.series[0].data = setSeriesData()
|
||||||
params.series[1].data = setCircleData()
|
params.series[1].data = setScatterData()
|
||||||
}
|
}
|
||||||
setOption(params)
|
setOption(params)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.lodging-ratio {
|
.occupancy {
|
||||||
width: 100%;
|
width: vw(360);
|
||||||
height: vh(130);
|
height: vh(120);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,30 +1,24 @@
|
|||||||
|
<!-- 购票来源 -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="ticket" :id="id" />
|
||||||
<div class="ticket" :id="id" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import { useEchart } from '@/hooks/echart'
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
|
||||||
let props = defineProps({
|
import { useHomeStore } from '@/stores/home'
|
||||||
list: {
|
|
||||||
type: Array,
|
const homeStore = useHomeStore()
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
|
||||||
|
|
||||||
let x = 15
|
let x = 15
|
||||||
let y = 25
|
let y = 25
|
||||||
let params = null
|
let params = null
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.list,
|
() => homeStore.userPortraitData.channel,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val.length > 0) init()
|
if (val.length > 0) init()
|
||||||
},
|
},
|
||||||
@@ -34,7 +28,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
const setSeries = () => {
|
const setSeries = () => {
|
||||||
return props.list.map((item, index) => {
|
return homeStore.userPortraitData.channel.map((item, index) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
@@ -71,21 +65,21 @@
|
|||||||
y: 'bottom',
|
y: 'bottom',
|
||||||
itemHeight: fitChartSize(12),
|
itemHeight: fitChartSize(12),
|
||||||
itemWidth: fitChartSize(12),
|
itemWidth: fitChartSize(12),
|
||||||
itemGap: fitChartSize(10),
|
itemGap: fitChartSize(6),
|
||||||
formatter: function (name) {
|
formatter: function (name) {
|
||||||
let obj = props.list.find((item) => item.name == name)
|
let obj = homeStore.userPortraitData.channel.find((item) => item.name == name)
|
||||||
return '{name|' + name + '} {value|' + obj?.value + '}{value|%}'
|
return '{name|' + name + '} {value|' + obj?.value + '}{value|%}'
|
||||||
},
|
},
|
||||||
textStyle: {
|
textStyle: {
|
||||||
rich: {
|
rich: {
|
||||||
name: {
|
name: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
fontSize: fitChartSize(14)
|
fontSize: fitChartSize(12)
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
color: '#00D5F6',
|
color: '#00D5F6',
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: fitChartSize(14)
|
fontSize: fitChartSize(12)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +97,7 @@
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.ticket {
|
.ticket {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: vh(200);
|
height: vh(230);
|
||||||
}
|
}
|
||||||
.legend {
|
.legend {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<!-- 客源地分析TOP5 -->
|
||||||
<template>
|
<template>
|
||||||
<div class="top" :id="id" />
|
<div class="top" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
@@ -5,11 +6,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import { useEchart } from '@/hooks/echart'
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
import { useHomeStore } from '@/stores/home'
|
||||||
|
|
||||||
|
const homeStore = useHomeStore()
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
const homeData = inject('homeData')
|
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
setOption({
|
setOption({
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
@@ -67,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: homeData.value?.userPortrait?.provinceRate.map((item) => Number(item.value))
|
data: homeStore?.userPortraitData?.provinceRate.map((item) => Number(item.value))
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
@@ -91,7 +92,7 @@
|
|||||||
return params.data.name ?? '其他'
|
return params.data.name ?? '其他'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: homeData.value?.userPortrait?.provinceRate.map((item) => {
|
data: homeStore?.userPortraitData?.provinceRate.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
value: Number(item.value),
|
value: Number(item.value),
|
||||||
@@ -107,9 +108,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => homeData.value?.userPortrait?.provinceRate,
|
() => homeStore?.userPortraitData?.provinceRate,
|
||||||
() => {
|
(val) => {
|
||||||
init()
|
if (val.length > 0) init()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="traffic-flow" id="traffic-flow" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
|
||||||
import * as echarts from 'echarts'
|
|
||||||
|
|
||||||
let trafficChart = null
|
|
||||||
|
|
||||||
let option = {
|
|
||||||
grid: {
|
|
||||||
left: '4%',
|
|
||||||
right: '4%',
|
|
||||||
top: '10%',
|
|
||||||
bottom: '10%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
boundaryGap: true,
|
|
||||||
type: 'category',
|
|
||||||
data: ['河北', '山西', '河南', '内蒙', '辽宁'],
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: 'rgba(5, 72, 134, 1)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: fitChartSize(12),
|
|
||||||
color: 'rgba(255,255,255,0.9)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: fitChartSize(12),
|
|
||||||
color: 'rgba(255,255,255,0.9)'
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: 'rgba(0, 150, 255,0.4)',
|
|
||||||
type: 'dashed'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: [820, 932, 901, 934, 1290],
|
|
||||||
type: 'bar',
|
|
||||||
showBackground: true,
|
|
||||||
barWidth: fitChartSize(8),
|
|
||||||
itemStyle: {
|
|
||||||
barBorderRadius: [3, 3, 0, 0],
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 1,
|
|
||||||
colorStops: [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(0, 208, 255, 0)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: 'rgba(0, 208, 255, 1)'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
backgroundStyle: {
|
|
||||||
color: 'rgba(0, 150, 255, 0.15)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const init = () => {
|
|
||||||
trafficChart = echarts.init(document.getElementById('traffic-flow'))
|
|
||||||
trafficChart.setOption(option)
|
|
||||||
window.addEventListener('resize', resize)
|
|
||||||
}
|
|
||||||
const resize = () => {
|
|
||||||
if (trafficChart) {
|
|
||||||
trafficChart.dispose()
|
|
||||||
trafficChart = null
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
init()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.traffic-flow {
|
|
||||||
width: 100%;
|
|
||||||
height: vh(160);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,189 +1,194 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="vacancy" id="vacancy" />
|
<!-- 景区停车场空位 -->
|
||||||
|
<div class="vacancy" :id="id" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { fitChartSize } from '@/utils/dataUtil'
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
import * as echarts from 'echarts'
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
|
||||||
let topChart = null
|
const { id, setOption } = useEchart()
|
||||||
let result = [
|
|
||||||
{ name: '三峡之颠', value: 86 },
|
let props = defineProps({
|
||||||
{ name: '白帝城', value: 83 },
|
list: {
|
||||||
{ name: '瞿塘峡', value: 73 },
|
type: Array,
|
||||||
{ name: '天坑地缝', value: 61 }
|
default: () => []
|
||||||
]
|
}
|
||||||
let option = {
|
})
|
||||||
backgroundColor: 'transparent',
|
|
||||||
tooltip: {
|
watch(
|
||||||
show: false
|
() => props.list,
|
||||||
|
(val) => {
|
||||||
|
if (val.length > 0) init()
|
||||||
},
|
},
|
||||||
legend: {
|
{ immediate: true }
|
||||||
show: false
|
)
|
||||||
},
|
|
||||||
grid: {
|
let params = null
|
||||||
left: '4%',
|
|
||||||
right: '4%',
|
const getSeriesData = () => {
|
||||||
top: '20%',
|
return props.list.map((item) => {
|
||||||
bottom: '-4%',
|
return {
|
||||||
containLabel: true
|
...item,
|
||||||
},
|
itemStyle: {
|
||||||
xAxis: [
|
color: {
|
||||||
{
|
type: 'linear',
|
||||||
splitLine: {
|
x: 0,
|
||||||
show: false
|
y: 0,
|
||||||
},
|
x2: 1,
|
||||||
type: 'value',
|
y2: 1,
|
||||||
show: false
|
colorStops: [
|
||||||
}
|
{
|
||||||
],
|
offset: 0,
|
||||||
yAxis: [
|
color: 'rgba(255, 112, 33, 0)'
|
||||||
{
|
},
|
||||||
splitLine: {
|
{
|
||||||
show: false
|
offset: 1,
|
||||||
},
|
color: '#00CCFF'
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: 'category',
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: result.map((item) => item.name),
|
|
||||||
axisLabel: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'category',
|
|
||||||
inverse: true,
|
|
||||||
axisTick: 'none',
|
|
||||||
axisLine: 'none',
|
|
||||||
show: true,
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(12)
|
|
||||||
},
|
|
||||||
verticalAlign: 'bottom',
|
|
||||||
padding: [0, 0, fitChartSize(6), 0],
|
|
||||||
inside: true,
|
|
||||||
formatter: function (value) {
|
|
||||||
return `{label|余} {value|${value}}`
|
|
||||||
},
|
|
||||||
rich: {
|
|
||||||
label: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
align: 'center',
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: result.map((item) => item.value)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
type: 'bar',
|
|
||||||
barWidth: fitChartSize(4),
|
|
||||||
MaxSize: 0,
|
|
||||||
showBackground: true,
|
|
||||||
barBorderRadius: [30, 0, 0, 30],
|
|
||||||
backgroundStyle: {
|
|
||||||
color: 'rgba(0, 150, 255, 0.15)'
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
offset: [10, -13],
|
|
||||||
color: '#D3E5FF',
|
|
||||||
fontWeight: 500,
|
|
||||||
position: 'left',
|
|
||||||
align: 'left',
|
|
||||||
fontSize: fitChartSize(14),
|
|
||||||
fontFamily: 'Source Han Sans CN',
|
|
||||||
formatter: function (params) {
|
|
||||||
return params.data.name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: result.map((item, index) => {
|
|
||||||
return {
|
|
||||||
name: item.name,
|
|
||||||
value: item.value,
|
|
||||||
itemStyle: {
|
|
||||||
barBorderRadius: [3, 0, 0, 3],
|
|
||||||
color: {
|
|
||||||
type: 'linear',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
x2: 1,
|
|
||||||
y2: 1,
|
|
||||||
colorStops: [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(0, 204, 255, 0)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: 'rgba(0, 204, 255, 1)'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '外圆',
|
|
||||||
type: 'scatter',
|
|
||||||
emphasis: {
|
|
||||||
scale: false
|
|
||||||
},
|
|
||||||
showSymbol: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: fitChartSize(10),
|
|
||||||
z: 2,
|
|
||||||
data: result.map((item, index) => {
|
|
||||||
return {
|
|
||||||
name: item.name,
|
|
||||||
value: item.value,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
animationDelay: 500
|
|
||||||
}
|
}
|
||||||
]
|
})
|
||||||
|
}
|
||||||
|
const getScatterData = () => {
|
||||||
|
return props.list.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getYAxisData = () => {
|
||||||
|
return props.list.map((item) => item.value)
|
||||||
}
|
}
|
||||||
const init = () => {
|
const init = () => {
|
||||||
topChart = echarts.init(document.getElementById('vacancy'))
|
if (!params) {
|
||||||
topChart.setOption(option)
|
params = {
|
||||||
}
|
backgroundColor: 'transparent',
|
||||||
const resize = () => {
|
tooltip: {
|
||||||
if (topChart) {
|
show: false
|
||||||
topChart.dispose()
|
},
|
||||||
topChart = null
|
legend: {
|
||||||
init()
|
show: false
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '4%',
|
||||||
|
right: '4%',
|
||||||
|
top: '16%',
|
||||||
|
bottom: '-10%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
type: 'value',
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
type: 'category',
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [],
|
||||||
|
axisLabel: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
inverse: true,
|
||||||
|
axisTick: 'none',
|
||||||
|
axisLine: 'none',
|
||||||
|
show: true,
|
||||||
|
axisLabel: {
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
},
|
||||||
|
verticalAlign: 'bottom',
|
||||||
|
padding: [0, 0, 6, 0],
|
||||||
|
inside: true,
|
||||||
|
formatter: function (value) {
|
||||||
|
return `{value|余}{value|${value}}`
|
||||||
|
},
|
||||||
|
rich: {
|
||||||
|
value: {
|
||||||
|
align: 'center',
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: fitChartSize(14)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: getYAxisData()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: fitChartSize(8),
|
||||||
|
showBackground: true,
|
||||||
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
|
backgroundStyle: {
|
||||||
|
color: 'rgba(0, 150, 255, 0.15)'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
offset: [10, -10],
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 500,
|
||||||
|
position: 'left',
|
||||||
|
align: 'left',
|
||||||
|
fontSize: fitChartSize(14),
|
||||||
|
formatter: function (params) {
|
||||||
|
return params.data.name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: getSeriesData()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '外圆',
|
||||||
|
type: 'scatter',
|
||||||
|
emphasis: {
|
||||||
|
scale: false
|
||||||
|
},
|
||||||
|
showSymbol: true,
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: fitChartSize(10),
|
||||||
|
z: 2,
|
||||||
|
animationDelay: 500,
|
||||||
|
data: getScatterData()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.yAxis[1].data = getYAxisData()
|
||||||
|
params.series[0].data = getSeriesData()
|
||||||
|
params.series[1].data = getScatterData()
|
||||||
}
|
}
|
||||||
|
setOption(params)
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
|
||||||
init()
|
|
||||||
window.addEventListener('resize', resize)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.vacancy {
|
.vacancy {
|
||||||
width: 100%;
|
width: vw(250);
|
||||||
height: vh(170);
|
height: vh(160);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
119
src/views/home/components/vehicle-source.vue
Normal file
119
src/views/home/components/vehicle-source.vue
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<!-- 车源地 -->
|
||||||
|
<template>
|
||||||
|
<div class="vehicle-source" :id="id" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { fitChartSize } from '@/utils/dataUtil'
|
||||||
|
import { useEchart } from '@/hooks/echart'
|
||||||
|
|
||||||
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
|
let props = defineProps({
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.list,
|
||||||
|
(val) => {
|
||||||
|
if (val.length > 0) init()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
let params = null
|
||||||
|
|
||||||
|
const getSeriesData = () => {
|
||||||
|
return props.list.map((item) => item.value)
|
||||||
|
}
|
||||||
|
const getXAxisData = () => {
|
||||||
|
return props.list.map((item) => item.name)
|
||||||
|
}
|
||||||
|
const init = () => {
|
||||||
|
if (!params) {
|
||||||
|
params = {
|
||||||
|
grid: {
|
||||||
|
left: '4%',
|
||||||
|
right: '4%',
|
||||||
|
top: '10%',
|
||||||
|
bottom: '10%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
boundaryGap: true,
|
||||||
|
type: 'category',
|
||||||
|
data: getXAxisData(),
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(5, 72, 134, 1)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: fitChartSize(12),
|
||||||
|
color: 'rgba(255,255,255,0.9)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: fitChartSize(12),
|
||||||
|
color: 'rgba(255,255,255,0.9)'
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(0, 150, 255,0.4)',
|
||||||
|
type: 'dashed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: getSeriesData(),
|
||||||
|
type: 'bar',
|
||||||
|
showBackground: true,
|
||||||
|
barWidth: fitChartSize(8),
|
||||||
|
itemStyle: {
|
||||||
|
barBorderRadius: [0, 0, 0, 0],
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgba(0, 208, 255, 0)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgba(0, 208, 255, 1)'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backgroundStyle: {
|
||||||
|
color: 'rgba(0, 150, 255, 0.15)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.xAxis.data = getXAxisData()
|
||||||
|
params.series[0].data = getSeriesData()
|
||||||
|
}
|
||||||
|
setOption(params)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.vehicle-source {
|
||||||
|
width: 100%;
|
||||||
|
height: vh(160);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -10,14 +10,13 @@
|
|||||||
import box3 from './components/box-3.vue'
|
import box3 from './components/box-3.vue'
|
||||||
import { useWebSocket } from '@/hooks/socket'
|
import { useWebSocket } from '@/hooks/socket'
|
||||||
|
|
||||||
const { data, isConnected, sendMessage } = useWebSocket('ws://36.138.38.16:81/ws/third-party')
|
const { isConnected, sendMessage } = useWebSocket('ws://36.138.38.16:81/ws/third-party')
|
||||||
|
|
||||||
provide('homeData', data)
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isConnected.value,
|
() => isConnected.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
|
console.log('--------------------------------------------')
|
||||||
sendMessage(
|
sendMessage(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
action: 'start',
|
action: 'start',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<main class="wrapper">
|
<main class="wrapper">
|
||||||
<CoreVideo />
|
<CoreVideo />
|
||||||
<box5/>
|
<box5 />
|
||||||
<box3 />
|
<box3 />
|
||||||
<Header title="三峡之巅-安全检测" is-skip :nav-left="navLeft" :nav-right="navRight" />
|
<Header title="三峡之巅-安全检测" is-skip :nav-left="navLeft" :nav-right="navRight" />
|
||||||
<Correspondence />
|
<Correspondence />
|
||||||
</main>
|
</main>
|
||||||
@@ -11,39 +11,42 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import box3 from './components/box-3.vue'
|
import box3 from './components/box-3.vue'
|
||||||
import box5 from './components/box-5.vue'
|
import box5 from './components/box-5.vue'
|
||||||
const navLeft = [{
|
const navLeft = [
|
||||||
name: '奉节县',
|
{
|
||||||
path: '/sceneTesting'
|
name: '奉节县',
|
||||||
},
|
path: '/sceneTesting'
|
||||||
{
|
},
|
||||||
name: '三峡之巅',
|
{
|
||||||
path: '/sceneTesting'
|
name: '三峡之巅',
|
||||||
},
|
path: '/sceneTesting'
|
||||||
{
|
},
|
||||||
name: '白帝城',
|
{
|
||||||
path: '/sceneTesting'
|
name: '白帝城',
|
||||||
}, {
|
path: '/sceneTesting'
|
||||||
name: '龙河桥',
|
},
|
||||||
path: '/sceneTesting'
|
{
|
||||||
}
|
name: '龙河桥',
|
||||||
]
|
path: '/sceneTesting'
|
||||||
const navRight = [{
|
}
|
||||||
name: '路段',
|
]
|
||||||
path: '/roadTesting'
|
const navRight = [
|
||||||
},
|
{
|
||||||
{
|
name: '路段',
|
||||||
name: '路段',
|
path: '/roadTesting'
|
||||||
path: '/roadTesting'
|
},
|
||||||
},
|
{
|
||||||
{
|
name: '路段',
|
||||||
name: '路段',
|
path: '/roadTesting'
|
||||||
path: '/roadTesting'
|
},
|
||||||
},
|
{
|
||||||
{
|
name: '路段',
|
||||||
name: '路段',
|
path: '/roadTesting'
|
||||||
path: '/roadTesting'
|
},
|
||||||
}
|
{
|
||||||
]
|
name: '路段',
|
||||||
|
path: '/roadTesting'
|
||||||
|
}
|
||||||
|
]
|
||||||
onMounted(() => {})
|
onMounted(() => {})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -54,6 +57,5 @@ const navLeft = [{
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #0a254b;
|
background-color: #0a254b;
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
<p class="value">{{ item.value }}%</p>
|
<p class="value">{{ item.value }}%</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="alarm">
|
<div v-if="pointRankData.length > 0" class="alarm">
|
||||||
<Title2 title="异常点位告警排名" />
|
<Title2 title="异常点位告警排名" />
|
||||||
<ul class="alarm__wrapper">
|
<ul class="alarm__wrapper">
|
||||||
<li class="alarm-item" v-for="(item, index) in pointRankData" :key="index">
|
<li class="alarm-item" v-for="(item, index) in pointRankData" :key="index">
|
||||||
@@ -154,7 +154,6 @@
|
|||||||
const getNewsPointRank = async () => {
|
const getNewsPointRank = async () => {
|
||||||
let res = await getNewsPointRankApi()
|
let res = await getNewsPointRankApi()
|
||||||
pointRankData.value = res.data
|
pointRankData.value = res.data
|
||||||
console.log(res, '1111')
|
|
||||||
}
|
}
|
||||||
const getTypeRate = async () => {
|
const getTypeRate = async () => {
|
||||||
let res = await getTypeRateApi()
|
let res = await getTypeRateApi()
|
||||||
|
|||||||
@@ -5,49 +5,54 @@
|
|||||||
<div class="statistics">
|
<div class="statistics">
|
||||||
<div class="statistics-item">
|
<div class="statistics-item">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img class="statistics-item__icon" src="@/assets/images/dot-primary.svg" alt="" />
|
<img class="statistics-item__icon" src="@/assets/images/dot-primary.svg" />
|
||||||
<span class="statistics-item__label">今日消息总条数</span>
|
<span class="statistics-item__label">今日消息总条数</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item__value--primary">
|
<div class="statistics-item__value--primary">
|
||||||
<countup end-val="45678" />
|
<countup :end-val="countInfo.total" />
|
||||||
<span class="statistics-item__value-suffix">条</span>
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item">
|
<div class="statistics-item">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img class="statistics-item__icon" src="@/assets/images/dot-error.svg" alt="" />
|
<img class="statistics-item__icon" src="@/assets/images/dot-error.svg" />
|
||||||
<span class="statistics-item__label">紧急消息</span>
|
<span class="statistics-item__label">紧急消息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item__value--error">
|
<div class="statistics-item__value--error">
|
||||||
<countup end-val="45678" />
|
<countup :end-val="countInfo.warn" />
|
||||||
<span class="statistics-item__value-suffix">条</span>
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item">
|
<div class="statistics-item">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img class="statistics-item__icon" src="@/assets/images/dot-warning.svg" alt="" />
|
<img class="statistics-item__icon" src="@/assets/images/dot-warning.svg" />
|
||||||
<span class="statistics-item__label">重要消息</span>
|
<span class="statistics-item__label">重要消息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item__value--warning">
|
<div class="statistics-item__value--warning">
|
||||||
<countup end-val="45678" />
|
<countup :end-val="countInfo.important" />
|
||||||
<span class="statistics-item__value-suffix">条</span>
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item">
|
<div class="statistics-item">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img class="statistics-item__icon" src="@/assets/images/dot-success.svg" alt="" />
|
<img class="statistics-item__icon" src="@/assets/images/dot-success.svg" />
|
||||||
<span class="statistics-item__label">普通消息</span>
|
<span class="statistics-item__label">普通消息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics-item__value--success">
|
<div class="statistics-item__value--success">
|
||||||
<countup end-val="45678" />
|
<countup :end-val="countInfo.normal" />
|
||||||
<span class="statistics-item__value-suffix">条</span>
|
<span class="statistics-item__value-suffix">条</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-box">
|
<div class="chart-box">
|
||||||
<pie :width="150" :height="150" />
|
<pie
|
||||||
<pie :width="150" :height="150" />
|
v-for="(item, index) in newsStateList"
|
||||||
<pie :width="150" :height="150" />
|
:key="index"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.name"
|
||||||
|
:width="150"
|
||||||
|
:height="150"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="work-box-1">
|
<div class="work-box-1">
|
||||||
@@ -75,14 +80,22 @@
|
|||||||
import pie from './pie.vue'
|
import pie from './pie.vue'
|
||||||
import { getNewsListApi, getNewsStateApi, getNewsTotalApi } from '@/api/news'
|
import { getNewsListApi, getNewsStateApi, getNewsTotalApi } from '@/api/news'
|
||||||
|
|
||||||
const list = ref([])
|
let list = ref([])
|
||||||
|
let countInfo = ref({
|
||||||
|
important: 0,
|
||||||
|
normal: 0,
|
||||||
|
total: 0,
|
||||||
|
warn: 0
|
||||||
|
})
|
||||||
|
let newsStateList = ref([])
|
||||||
const getNewsTotal = async () => {
|
const getNewsTotal = async () => {
|
||||||
let res = await getNewsTotalApi()
|
let res = await getNewsTotalApi()
|
||||||
console.log(res, '============')
|
countInfo.value = res.data
|
||||||
}
|
}
|
||||||
const getNewsState = async () => {
|
const getNewsState = async () => {
|
||||||
let res = await getNewsStateApi()
|
let res = await getNewsStateApi()
|
||||||
|
newsStateList.value = res.data
|
||||||
|
console.log(newsStateList.value, '=================')
|
||||||
}
|
}
|
||||||
const getNewsList = async () => {
|
const getNewsList = async () => {
|
||||||
let res = await getNewsListApi()
|
let res = await getNewsListApi()
|
||||||
|
|||||||
@@ -8,145 +8,169 @@
|
|||||||
|
|
||||||
const { id, setOption } = useEchart()
|
const { id, setOption } = useEchart()
|
||||||
|
|
||||||
let option = {
|
let props = defineProps({
|
||||||
backgroundColor: 'transparent',
|
value: {
|
||||||
title: [
|
type: Number,
|
||||||
{
|
default: () => 0
|
||||||
text: '45.5%',
|
},
|
||||||
x: 'center',
|
label: {
|
||||||
top: '42%',
|
type: String,
|
||||||
textStyle: {
|
default: () => ''
|
||||||
color: '#02F9FA',
|
}
|
||||||
fontSize: fitChartSize(24)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '完成率',
|
|
||||||
x: 'center',
|
|
||||||
top: '54%',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: fitChartSize(12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'gauge',
|
|
||||||
radius: '100%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
startAngle: 90,
|
|
||||||
endAngle: 450,
|
|
||||||
clockwise: false,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#00D0FF'
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: [
|
|
||||||
[0, '#075199'],
|
|
||||||
[1, '#075199']
|
|
||||||
],
|
|
||||||
width: fitChartSize(6)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
progress: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
width: fitChartSize(6)
|
|
||||||
},
|
|
||||||
pointer: {
|
|
||||||
// 指针
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
// 刻度
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
// 分割线
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
// 刻度标签
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
detail: {
|
|
||||||
// 仪表盘详情
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'gauge',
|
|
||||||
radius: '95%',
|
|
||||||
center: ['50%', '50%'],
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
startAngle: 90,
|
|
||||||
endAngle: 450,
|
|
||||||
clockwise: false,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#057EB9'
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
roundCap: false,
|
|
||||||
lineStyle: {
|
|
||||||
color: [
|
|
||||||
[0, '#075199'],
|
|
||||||
[1, '#075199']
|
|
||||||
],
|
|
||||||
width: fitChartSize(10)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
progress: {
|
|
||||||
show: true,
|
|
||||||
roundCap: false,
|
|
||||||
width: fitChartSize(10)
|
|
||||||
},
|
|
||||||
pointer: {
|
|
||||||
// 指针
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
// 刻度
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
// 分割线
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
// 刻度标签
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
detail: {
|
|
||||||
// 仪表盘详情
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
value: 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const init = () => {
|
|
||||||
setOption(option)
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
init()
|
|
||||||
})
|
})
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
nextTick(() => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
let params = null
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
if (!params) {
|
||||||
|
params = {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
text: `${(props.value * 100).toFixed(2)}%`,
|
||||||
|
x: 'center',
|
||||||
|
top: '40%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#02F9FA',
|
||||||
|
fontSize: fitChartSize(24)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: props.label,
|
||||||
|
x: 'center',
|
||||||
|
top: '56%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: fitChartSize(12)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
radius: '100%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
startAngle: 90,
|
||||||
|
endAngle: 450,
|
||||||
|
clockwise: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#00D0FF'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: [
|
||||||
|
[0, '#075199'],
|
||||||
|
[1, '#075199']
|
||||||
|
],
|
||||||
|
width: fitChartSize(6)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
width: fitChartSize(6)
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
// 指针
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
// 刻度
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
// 分割线
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
// 刻度标签
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
// 仪表盘详情
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: props.value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'gauge',
|
||||||
|
radius: '95%',
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
startAngle: 90,
|
||||||
|
endAngle: 450,
|
||||||
|
clockwise: false,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#057EB9'
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
roundCap: false,
|
||||||
|
lineStyle: {
|
||||||
|
color: [
|
||||||
|
[0, '#075199'],
|
||||||
|
[1, '#075199']
|
||||||
|
],
|
||||||
|
width: fitChartSize(10)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
progress: {
|
||||||
|
show: true,
|
||||||
|
roundCap: false,
|
||||||
|
width: fitChartSize(10)
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
// 指针
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
// 刻度
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
// 分割线
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
// 刻度标签
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
// 仪表盘详情
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: props.value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.series[0].data[0].value = props.value
|
||||||
|
}
|
||||||
|
setOption(params)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user