feat:对接接口、完善功能

This commit is contained in:
zjc
2024-12-26 18:30:52 +08:00
parent 809c950301
commit dc1ad009c7
16 changed files with 1085 additions and 1246 deletions

View File

@@ -106,7 +106,6 @@ const instance = axios.create({
*/ */
instance.interceptors.request.use( instance.interceptors.request.use(
(config) => { (config) => {
console.log(config, 'config')
// 规范写法 不可随意自定义 // 规范写法 不可随意自定义
let urlParams = {} let urlParams = {}
if (config.params) { if (config.params) {

View File

@@ -50,10 +50,11 @@ export function getLineChartApi(data) {
} }
// 地域分析 // 地域分析
export function getAreaApi() { export function getAreaApi(data) {
return request({ return request({
url: '/api/largeScreen/gsdata/area', url: '/api/largeScreen/gsdata/area',
method: 'post' method: 'get',
params: data
}) })
} }

View File

@@ -38,18 +38,29 @@
default: () => {} default: () => {}
} }
}) })
const { id, setOption, initChart } = useEchart()
const { id, setOption } = useEchart()
let timer = null let timer = null
let currentIndex = -1 let currentIndex = -1
let params = null
var defaultColors = ['#06E2FF', '#02FFB8', '#FF465F', '#FFCA36', '#9A4BFC', '#044EFF'] var defaultColors = ['#06E2FF', '#02FFB8', '#FF465F', '#FFCA36', '#9A4BFC', '#044EFF']
const defaultSeriesConfig = (index) => {
let defaultSeriesConfig = { return {
type: 'line', type: 'line',
smooth: true, smooth: true,
symbol: 'none', symbol: 'none',
symbolSize: fitChartSize(8) symbolSize: fitChartSize(8),
itemStyle: {
color: '#0B2F63',
borderColor: defaultColors[index],
borderWidth: fitChartSize(4)
},
lineStyle: {
color: defaultColors[index]
}
}
} }
let defaultConfig = { let defaultConfig = {
colors: defaultColors, colors: defaultColors,
@@ -57,9 +68,9 @@
trigger: 'axis', trigger: 'axis',
backgroundColor: 'transparent', backgroundColor: 'transparent',
borderWidth: 0, borderWidth: 0,
formatter: (params) => { formatter: (e) => {
let valueStr = '' let valueStr = ''
params.map((item) => { e.map((item) => {
valueStr += `<div>${item.seriesName}${item.value}</div>` valueStr += `<div>${item.seriesName}${item.value}</div>`
}) })
let str = `<div style=" let str = `<div style="
@@ -92,8 +103,7 @@
textStyle: { textStyle: {
color: '#ffffff', color: '#ffffff',
fontSize: fitChartSize(12) fontSize: fitChartSize(12)
}, }
data: []
}, },
title: { title: {
show: false show: false
@@ -130,31 +140,39 @@
}, },
series: [] series: []
} }
const init = () => { const updateOption = () => {
initChart() if (params) {
props.data.map((item, index) => {
params.series[index].data = item.data
})
} else {
defaultConfig.xAxis.data = props.xAxisData defaultConfig.xAxis.data = props.xAxisData
props.data.map((item, index) => { props.data.map((item, index) => {
defaultConfig.series.push({ defaultConfig.series.push({
...defaultSeriesConfig, ...defaultSeriesConfig(index),
...props.seriesConfig, ...props.seriesConfig,
name: item.name, name: item.name,
data: item.data, data: item.data
itemStyle: {
color: '#0B2F63',
borderColor: defaultColors[index],
borderWidth: fitChartSize(4)
},
lineStyle: {
color: defaultColors[index]
}
}) })
defaultConfig.legend.data.push(item.name)
}) })
setOption({ params = {
...defaultConfig, ...defaultConfig,
...props.config ...props.config
})
} }
}
setOption(params)
}
watch(
[() => props.data, () => props.xAxisData],
(val) => {
if (val[0].length > 0 && val[1].length > 0) {
setTimeout(() => {
updateOption()
}, 500)
}
},
{ immediate: true }
)
// // 切换tooltip // // 切换tooltip
// const switchTooltip = () => { // const switchTooltip = () => {
// // 取消之前高亮的图形 // // 取消之前高亮的图形

View File

@@ -98,7 +98,6 @@
(newVal) => { (newVal) => {
if (newVal.length > 0) { if (newVal.length > 0) {
nextTick(() => { nextTick(() => {
initChart()
defaultCofig.legend.formatter = (name) => { defaultCofig.legend.formatter = (name) => {
let percent = props.dataList.find((item) => item.name == name).value let percent = props.dataList.find((item) => item.name == name).value
return name + '\u3000' + `${percent}%` return name + '\u3000' + `${percent}%`

View File

@@ -3,26 +3,27 @@ import * as echarts from 'echarts'
import { guid } from '@/utils/util' import { guid } from '@/utils/util'
export function useEchart() { export function useEchart() {
let chart = ref(null) let chart = null
let id = ref(guid()) let id = ref(guid())
const initChart = () => { const initChart = () => {
const dom = document.getElementById(id.value) const dom = document.getElementById(id.value)
chart.value = echarts.init(dom) chart = echarts.init(dom)
} }
const setOption = (params) => { const setOption = (params) => {
chart.value.setOption(params) chart.setOption(params)
} }
const resize = () => { const dispose = () => {
if (chart) {
chart.dispose() chart.dispose()
chart = null chart = null
initChart()
} }
const resize = () => {
chart.resize()
} }
onMounted(() => { onMounted(() => {
initChart()
// 监听窗口大小变化 // 监听窗口大小变化
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
}) })
return { id, chart, setOption, initChart } return { id, chart, setOption, dispose, initChart }
} }

View File

@@ -1,17 +1,24 @@
<template> <template>
<div class="age-ratio" id="age-ratio" /> <div class="age-ratio" :id="id" />
</template> </template>
<script setup> <script setup>
import * as echarts from 'echarts'
import { fitChartSize } from '@/utils/dataUtil' import { fitChartSize } from '@/utils/dataUtil'
import { useEchart } from '@/hooks/echart'
let ageChart = null const { id, setOption } = useEchart()
const homeData = inject('homeData')
watch(
() => homeData.value?.userPortrait?.ageRate,
() => {
init()
}
)
const init = () => { const init = () => {
// domecharts setOption({
ageChart = echarts.init(document.getElementById('age-ratio'))
ageChart.setOption({
tooltip: { tooltip: {
trigger: 'item' trigger: 'item'
}, },
@@ -19,16 +26,15 @@
orient: 'vertical', orient: 'vertical',
left: '60%', left: '60%',
y: 'center', y: 'center',
data: ['19岁以下', '18-30岁', '30-40岁', '40-60岁', '60岁以上'],
itemHeight: fitChartSize(8), itemHeight: fitChartSize(8),
itemWidth: fitChartSize(8), itemWidth: fitChartSize(8),
itemGap: fitChartSize(10), itemGap: fitChartSize(10),
formatter: function (name) { formatter: function (name) {
return '{title|' + name + '}' return '{name|' + name + '}'
}, },
textStyle: { textStyle: {
rich: { rich: {
title: { name: {
color: '#fff', color: '#fff',
fontSize: fitChartSize(14) fontSize: fitChartSize(14)
}, },
@@ -54,36 +60,11 @@
color: '#D3F0FE', color: '#D3F0FE',
fontSize: fitChartSize(12) fontSize: fitChartSize(12)
}, },
labelLine: { data: homeData.value?.userPortrait?.ageRate || []
normal: {
lineStyle: {
type: 'dashed'
}
}
},
data: [
{ value: 484, name: '19岁以下' },
{ value: 300, name: '18-30岁' },
{ value: 1048, name: '30-40岁' },
{ value: 580, name: '40-60岁' },
{ value: 735, name: '60岁以上' }
]
} }
] ]
}) })
window.addEventListener('resize', resize)
} }
const resize = () => {
if (ageChart) {
ageChart.dispose()
ageChart = null
init()
}
}
onMounted(() => {
init()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -6,17 +6,15 @@
</template> </template>
</Title1> </Title1>
<div class="flex pt-20"> <div class="flex pt-20">
<div class="item core"> <div
<span class="label">全县景区数</span> v-for="(item, index) in homeData?.scenicSpot"
<div class="flex align-end"> <countup endVal="895" /><span class="unit"></span></div> class="item"
:class="{ core: index == 0, queue: index == 1, congestion: index == 2 }"
>
<span class="label">{{ item.name }}</span>
<div class="flex align-end">
<countup :end-val="item.value" /><span class="unit"></span>
</div> </div>
<div class="item queue">
<span class="label">核心景区数</span>
<div class="flex align-end"> <countup endVal="895" /><span class="unit"></span></div>
</div>
<div class="item congestion">
<span class="label">低感景区总数</span>
<div class="flex align-end"> <countup endVal="895" /><span class="unit"></span></div>
</div> </div>
</div> </div>
<div class="flex pt-20"> <div class="flex pt-20">
@@ -68,7 +66,24 @@
data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118] data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
} }
]" ]"
:xAxisData="xAxisData" :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>
@@ -138,39 +153,25 @@
</div> </div>
<Title1 title="游客画像" /> <Title1 title="游客画像" />
<div class="flex"> <div class="flex">
<div class="box-1"> <div class="box-1">
<Title3 title="年龄/性别占比" /> <Title3 title="年龄/性别占比" />
<age-ratio /> <age />
<div class="count">总人数<countup endVal="124563" /></div> <div class="count">总人数<countup endVal="124563" /></div>
<div class="cell pt-20"> <div class="cell pt-20" v-for="item in homeData?.userPortrait.genderRate">
<img class="icon" src="@/assets/images/man.png" /> <img class="icon" src="@/assets/images/man.png" />
<div class="bg"> <div class="bg">
<span class="text"></span> <span class="text">{{ item.name }}</span>
<div class="progress"> <div class="progress">
<el-progress <el-progress
:percentage="genderRate['男']" :percentage="Number(item.value)"
:show-text="false" :show-text="false"
color="linear-gradient( to right, #074D90 0%, #55E0FF 100%)" :color="`linear-gradient( to right, ${
item.name == '男' ? '#074D90' : '#0A4482'
} 0%, ${item.name == '男' ? '#55E0FF' : '#FF7021'} 100%)`"
/> />
</div> </div>
<span class="man">{{ genderRate['男'] }}%</span> <span class="man">{{ item.value }}%</span>
</div>
</div>
<div class="cell pt-20">
<img class="icon" src="@/assets/images/woman.png" />
<div class="bg">
<span class="text">女性</span>
<div class="progress">
<el-progress
:percentage="genderRate['女']"
:show-text="false"
color="linear-gradient( to right,
#0A4482 0%, #FF7021 100%)"
/>
</div>
<span class="woman">{{ genderRate['女'] }}%</span>
</div> </div>
</div> </div>
</div> </div>
@@ -190,40 +191,11 @@
<script setup> <script setup>
import countup from 'vue-countup-v3' import countup from 'vue-countup-v3'
import top from './top.vue' import top from './top.vue'
import age from './age.vue'
import gauge from './gauge.vue' import gauge from './gauge.vue'
import ticket from './ticket.vue' import ticket from './ticket.vue'
import ageRatio from './age-ratio.vue'
let props = defineProps({ const homeData = inject('homeData')
data: {
type: Object,
default: () => ({})
}
})
let genderRate = computed(() => {
if (props.data?.userPortrait) return props.data?.userPortrait.genderRate
return {
: 0,
: 0
}
})
let xAxisData = ref([
'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'
])
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -0,0 +1,350 @@
<template>
<div class="box-3">
<div class="header">
<div class="flex">
<div class="left">
<div class="item">
<div class="label">今年总游客数</div>
<ScrollNumber :count="count" prefix="1" />
</div>
<div class="item">
<div class="label">全县景区总游客人数</div>
<ScrollNumber :count="count" prefix="2" />
</div>
<div class="item">
<div class="label">总在园人数</div>
<ScrollNumber :count="count" prefix="3" />
</div>
</div>
<div class="right">
<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 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 class="rela">
<div class="alarm-box">
<ul class="flex">
<li class="alarm-item" v-for="(item, index) in list" :key="index">
<img class="icon" :src="item.icon" />
<span>{{ item.label }}</span>
</li>
</ul>
</div>
<Map />
</div>
<div class="footer">
<div class="left">
<div>
<div class="flex justify-center pt-10">
<div class="item">
<p class="label">今日工单总条数</p>
<countup :endVal="1234" />
</div>
<div class="item">
<p class="label">工单完成数</p>
<countup :endVal="1234" />
</div>
</div>
<div class="progress-box">
<span class="text">工单完成数</span>
<div class="progress-1">
<el-progress :percentage="50" :show-text="false" />
</div>
<span class="value">50%</span>
</div>
</div>
<div>
<div class="flex justify-center pt-10">
<div class="item">
<p class="label">紧急工单数</p>
<countup :endVal="1234" />
</div>
<div class="item">
<p class="label">紧急工单完成数</p>
<countup :endVal="1234" />
</div>
</div>
<div class="progress-box">
<span class="text">工单完成数</span>
<div class="progress-2">
<el-progress :percentage="50" :show-text="false" />
</div>
<span class="value">50%</span>
</div>
</div>
</div>
<div class="right">
<div class="item">
<span class="tag tag--success">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
<div class="item">
<span class="tag tag--error">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
<div class="item">
<span class="tag tag--primary">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
</div>
</div>
</div>
</template>
<script setup>
import countup from 'vue-countup-v3'
import ScrollNumber from '@/components/ScrollNumber/index.vue'
import icon8 from '@/assets/images/icon-8.png'
import icon9 from '@/assets/images/icon-9.png'
import icon10 from '@/assets/images/icon-10.png'
import icon11 from '@/assets/images/icon-11.png'
let count = ref('6945959')
let list = ref([
{
label: '安全异常',
icon: icon8
},
{
label: '排队异常',
icon: icon9
},
{
label: '停车异常',
icon: icon10
},
{
label: '舆论异常',
icon: icon11
}
])
</script>
<style lang="scss" scoped>
.box-3 {
width: vw(1614);
height: vh(950);
margin-top: vh(120);
.header {
width: vw(1614);
height: vh(128);
padding: 0 vw(90);
box-sizing: border-box;
background-image: url('@/assets/images/group.png');
background-size: 100% 100%;
.left {
display: flex;
width: vw(950);
margin-top: vh(20);
}
.right {
flex: 1;
display: flex;
margin-top: vh(20);
}
.item {
flex: 1;
.label {
margin-bottom: vh(20);
font-weight: 400;
font-size: vw(16);
color: rgba(255, 255, 255, 0.9);
}
.value {
font-weight: bold;
font-size: vw(28);
color: #02f9fa;
line-height: vh(33);
}
}
.countup-wrap {
display: inline-block;
width: vw(40);
height: vh(40);
margin-right: vw(4);
border-radius: vw(4);
color: #ffffff;
font-size: vw(28);
font-weight: bold;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #00b7ff 0%, #0033ff 100%);
}
}
.alarm-box {
position: absolute;
top: vw(20);
left: vw(20);
z-index: 99999;
.alarm-item {
width: vw(110);
height: vh(40);
margin-right: vw(4);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom, rgba(238, 44, 44, 0) 0%, #ee2c2c 100%);
.icon {
width: vw(20);
height: vw(20);
margin-right: vw(4);
}
}
}
.footer {
display: flex;
width: 100%;
height: vh(120);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
.left {
flex: 1;
display: flex;
margin-top: vh(4);
& > div {
flex: 1;
height: vh(110);
margin-right: vw(6);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
.item {
padding: vh(10) vw(24);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.label {
font-weight: 400;
font-size: vw(14);
margin-bottom: vh(10);
color: rgba(255, 255, 255, 0.9);
}
.countup-wrap {
color: #02f9fa;
font-size: vw(28);
font-weight: bold;
}
.progress-box {
margin-top: vh(10);
display: flex;
align-items: center;
justify-content: center;
.text {
margin-right: vw(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
.progress {
width: vw(100);
:deep(.el-progress-bar__outer) {
background-color: #0858ae !important;
}
}
.progress-1 {
@extend .progress;
:deep(.el-progress-bar__inner) {
background: linear-gradient(to right, #0566bb 0%, #00c4f9 100%);
}
}
.progress-2 {
@extend .progress;
:deep(.el-progress-bar__inner) {
background: linear-gradient(to right, #0566bb 0%, #d6383a 100%);
}
}
.value {
margin-left: vw(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
}
}
}
.right {
padding: vh(10) vw(24);
.item {
display: flex;
margin-bottom: vh(12);
&:nth-last-child(1) {
margin-bottom: 0;
}
.tag {
padding: 0 vw(16);
font-weight: bold;
font-size: vw(14);
display: flex;
align-items: center;
justify-content: center;
border-radius: vw(2);
&--success {
color: #02f9fa;
border: 1px solid #02f9fa;
box-shadow: inset 0 0 vw(8) 0 #0be1ab;
}
&--error {
color: #ee2c2c;
border: 1px solid #ee2c2c;
box-shadow: inset 0 0 vw(8) 0 #ee2c2c;
}
&--primary {
color: #00aaff;
border: 1px solid #00aaff;
box-shadow: inset 0 0 vw(8) 0 #00aaff;
}
}
.content {
margin-left: vw(4);
padding: 0 vw(10);
width: vw(900);
height: vh(24);
line-height: vh(24);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 400;
font-size: vw(14);
color: #ffffff;
border-radius: vw(2);
background: rgba(0, 150, 255, 0.28);
}
}
}
}
}
</style>

View File

@@ -1,118 +1,268 @@
<template> <template>
<div class="box-3"> <div class="box-4">
<div class="header"> <Title1 title="交通信息" />
<div class="flex justify-evenly pt-10 pb-20">
<div v-for="item in list" class="cell">
<img class="icon" :src="item.icon" alt="" width="64" height="64" />
<div>
<countup :end-val="item.value" />
<div class="label">{{ item.label }}</div>
</div>
</div>
</div>
<div class="flex"> <div class="flex">
<div class="left"> <div class="box">
<div class="item"> <div class="pt-10">
<div class="label">今年总游客数</div> <Title3 title="拥堵路段总数" />
<ScrollNumber :count="count" prefix="1" /> <div class="">
</div> <Line
<div class="item"> :width="250"
<div class="label">全县景区总游客人数</div> :height="150"
<ScrollNumber :count="count" prefix="2" /> :config="{ legend: false }"
</div> :data="[
<div class="item"> {
<div class="label">总在园人数</div> name: '企业数',
<ScrollNumber :count="count" prefix="3" /> data: [64, 159, 112, 86, 151, 131, 118, 232, 23, 64, 159, 112, 86, 151, 131, 118]
</div> }
</div> ]"
<div class="right"> :xAxisData="[
<div class="item"> '12-16 10:00',
<div class="label">安全度</div> '12-16 14:00',
<div class="value">安全</div> '12-16 16:00',
</div> '12-16 22:00',
<div class="item"> '12-17 02:00',
<div class="label">舒适度</div> '12-17 06:00',
<div class="value">舒适</div> '12-17 10:00',
</div> '12-17 14:00',
<div class="item"> '12-17 16:00',
<div class="label">接待情况</div> '12-16 22:00',
<div class="value">排队</div> '12-18 02:00',
</div> '12-18 06:00',
<div class="item"> '12-8 10:00',
<div class="label">交通拥挤度</div> '12-18 14:00',
<div class="value">舒适</div> '12-18 16:00',
</div> '12-18 20:00'
<div class="item"> ]"
<div class="label">停车场负荷度</div> />
<div class="value">超负荷</div>
</div> </div>
</div> </div>
</div> </div>
<div class="box">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<Line
:width="250"
:height="150"
:config="{ legend: false }"
:data="[
{
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 class="rela">
<div class="alarm-box">
<ul class="flex">
<li class="alarm-item" v-for="(item, index) in list" :key="index">
<img class="icon" :src="item.icon" />
<span>{{ item.label }}</span>
</li>
</ul>
</div> </div>
<Map /> <div class="box">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<jam :width="250" :height="200" />
</div> </div>
<div class="footer"> </div>
<div class="left"> </div>
<Title1 title="停车信息" />
<div class="stop-box">
<div> <div>
<div class="flex justify-center pt-10"> <img class="icon" src="@/assets/images/icon-5.png" alt="" />
<div class="item"> <div>
<p class="label">今日工单总条</p> <div class="label">车库总</div>
<countup :endVal="1234" /> <countup class="value" :end-val="500" />
</div> </div>
<div class="item"> <div>
<p class="label">工单完成</p> <div class="label">车库总</div>
<countup :endVal="1234" /> <countup class="value" :end-val="500" />
</div> </div>
</div> <div>
<div class="progress-box"> <div class="label">已使用车位数</div>
<span class="text">工单完成数</span> <countup class="value" :end-val="500" />
<div class="progress-1">
<el-progress :percentage="50" :show-text="false" />
</div>
<span class="value">50%</span>
</div> </div>
</div> </div>
<div> <div>
<div class="flex justify-center pt-10"> <div>
<div class="label">三峡之巅</div>
<div class="value error">已满</div>
</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 class="flex pt-10">
<div class="box-1">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<div class="pt-20">
<Line
:width="250"
:height="120"
:config="{ legend: false }"
:data="[
{
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 class="box-1">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<traffic-flow />
</div>
</div>
<div class="box-1">
<div class="pt-10">
<Title3 title="景区停车场空位" />
<vacancy />
</div>
</div>
</div>
<div class="flex">
<div class="flex-1">
<Title1 title="车船信息" class="title1" />
</div>
<div class="flex-1">
<Title1 title="酒店信息" class="title1" />
</div>
</div>
<div class="flex">
<div class="car-ship">
<div class="mb-6">
<div class="car">
<div class="label">车总数</div>
<div class="flex align-center">
<countup class="value" :end-val="homeData?.carShipData.car.count" />
<span class="unit"></span>
</div>
</div>
<div class="table">
<div class="header">
<div>景区</div>
<div>调度</div>
<div>空余</div>
</div>
<div class="cell" v-for="item in homeData?.carShipData.car.info" :key="index">
<div>{{ item.scenic_area }}</div>
<div>{{ item.started_count }}<span class="unit-1"></span></div>
<div>{{ item.not_started_count }}<span class="unit-1"></span></div>
</div>
</div>
</div>
<div>
<div class="ship">
<div class="label">车总数</div>
<div class="flex align-center">
<countup class="value" :end-val="homeData?.carShipData.ship.count" />
<span class="unit"></span>
</div>
<div class="table">
<div class="header">
<div>景区</div>
<div>调度</div>
<div>空余</div>
</div>
<div
class="cell"
v-for="(item, index) in homeData?.carShipData.ship.info"
:key="index"
>
<div>白帝城</div>
<div>{{ item.started_count }}<span class="unit-1"></span></div>
<div>{{ item.not_started_count }}<span class="unit-1"></span></div>
</div>
</div>
</div>
</div>
</div>
<div class="hotel">
<div>
<div class="item"> <div class="item">
<p class="label">紧急工单</p> <div class="label">酒店总</div>
<countup :endVal="1234" /> <countup class="value" :end-val="homeData?.hotelData.info.hotel_count || 0" />
</div> </div>
<div class="item"> <div class="item">
<p class="label">紧急工单完成</p> <div class="label">房间总</div>
<countup :endVal="1234" /> <countup class="value" :end-val="homeData?.hotelData.info.total_room_count || 0" />
</div>
</div>
<div class="progress-box">
<span class="text">工单完成数</span>
<div class="progress-2">
<el-progress :percentage="50" :show-text="false" />
</div>
<span class="value">50%</span>
</div>
</div>
</div>
<div class="right">
<div class="item">
<span class="tag tag--success">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div> </div>
<div class="item"> <div class="item">
<span class="tag tag--error">普通</span> <div class="label">总入住</div>
<p class="content"> <countup
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息 class="value"
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息 color="#02F9FA"
</p> :end-val="homeData?.hotelData.info.total_guest_count || 0"
/>
</div> </div>
<div class="item"> <div class="item">
<span class="tag tag--primary">普通</span> <div class="label">总入住率</div>
<p class="content"> <countup
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息 class="value"
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息 color="#02F9FA"
</p> :end-val="homeData?.hotelData.info.occupancy_rate || 0"
/>
</div>
</div>
<div>
<div class="lodging">
<Title3 title="酒店入住人数及入住率" />
</div>
<occupancy />
</div> </div>
</div> </div>
</div> </div>
@@ -120,231 +270,263 @@
</template> </template>
<script setup> <script setup>
import jam from './jam.vue'
import vacancy from './vacancy.vue'
import occupancy from './occupancy.vue'
import TrafficFlow from './traffic-flow.vue'
import countup from 'vue-countup-v3' import countup from 'vue-countup-v3'
import ScrollNumber from '@/components/ScrollNumber/index.vue' import icon1 from '@/assets/images/icon-1.png'
import icon8 from '@/assets/images/icon-8.png' import icon2 from '@/assets/images/icon-2.png'
import icon9 from '@/assets/images/icon-9.png' import icon3 from '@/assets/images/icon-3.png'
import icon10 from '@/assets/images/icon-10.png' import icon4 from '@/assets/images/icon-4.png'
import icon11 from '@/assets/images/icon-11.png'
const homeData = inject('homeData')
let count = ref('6945959')
let list = ref([ let list = ref([
{ {
label: '安全异常', label: '路段总数',
icon: icon8 value: '1234',
icon: icon1
}, },
{ {
label: '排队异常', label: '当前拥堵路段',
icon: icon9 value: '1234',
icon: icon2
}, },
{ {
label: '停车异常', label: '总拥堵次数',
icon: icon10 value: '1234',
icon: icon3
}, },
{ {
label: '舆论异常', label: '最大拥堵时长',
icon: icon11 value: '1234',
icon: icon4
} }
]) ])
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.box-3 { .box-4 {
width: vw(1614);
height: vh(950);
margin-top: vh(120); margin-top: vh(120);
width: vw(750);
.header { height: vh(950);
width: vw(1614); padding: vw(8);
height: vh(128);
padding: 0 vw(90);
box-sizing: border-box; box-sizing: border-box;
background-image: url('@/assets/images/group.png'); background-image: url('@/assets/images/bg-5.png');
background-size: 100% 100%; background-size: 100% 100%;
.left { .cell {
display: flex; display: flex;
width: vw(950); align-items: center;
margin-top: vh(20); .icon {
width: vw(64);
height: auto;
} }
.right { .countup-wrap {
flex: 1; color: #02f9fa;
display: flex; font-size: vw(24);
margin-top: vh(20); font-weight: bold;
} }
.item {
flex: 1;
.label { .label {
margin-bottom: vh(20);
font-weight: 400; font-weight: 400;
font-size: vw(16); font-size: vw(14);
margin-top: vh(10);
color: rgba(255, 255, 255, 0.9);
}
}
.box {
width: vw(250);
height: vh(200);
margin-right: vw(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
.box-1 {
width: vw(250);
height: vh(200);
margin-right: vw(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
.stop-box {
display: flex;
gap: vw(20);
.icon {
width: vw(45);
height: auto;
}
& > div {
flex: 1;
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9);
} }
.value { .value {
margin-top: vh(10);
font-weight: bold; font-weight: bold;
font-size: vw(28); font-size: vw(24);
color: #ffffff;
}
.error {
color: #e21b1b;
}
.success {
color: #02f9fa; color: #02f9fa;
line-height: vh(33);
}
}
.countup-wrap {
display: inline-block;
width: vw(40);
height: vh(40);
margin-right: vw(4);
border-radius: vw(4);
color: #ffffff;
font-size: vw(28);
font-weight: bold;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #00b7ff 0%, #0033ff 100%);
}
}
.alarm-box {
position: absolute;
top: vw(20);
left: vw(20);
z-index: 99999;
.alarm-item {
width: vw(110);
height: vh(40);
margin-right: vw(4);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom, rgba(238, 44, 44, 0) 0%, #ee2c2c 100%);
.icon {
width: vw(20);
height: vw(20);
margin-right: vw(4);
} }
} }
} }
.footer { .car-ship {
display: flex;
width: 100%;
height: vh(120);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
.left {
flex: 1; flex: 1;
display: flex;
margin-top: vh(4);
& > div { & > div {
position: relative;
flex: 1; flex: 1;
height: vh(110); height: vh(110);
margin-right: vw(6); display: flex;
background-image: url('@/assets/images/bg-3.png'); align-items: center;
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.icon {
padding-left: vw(90);
width: vw(352);
height: vh(70);
display: flex;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
}
.car {
@extend .icon;
background-image: url('@/assets/images/icon-6.png');
background-size: 100% 100%;
}
.ship {
@extend .icon;
background-image: url('@/assets/images/icon-7.png');
background-size: 100% 100%;
}
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
margin-bottom: vh(6);
}
.value {
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.unit {
font-weight: bold;
font-size: vw(14);
color: #02f9fa;
margin-top: vh(6);
}
.table {
position: absolute;
left: vw(160);
width: vw(200);
height: vh(100);
z-index: 2;
.header {
display: flex;
height: vh(18);
line-height: vh(18);
text-align: center;
background: rgba(0, 150, 255, 0.4);
& > div {
flex: 1;
font-weight: 400;
font-size: vw(12);
color: #52b8ff;
}
}
.cell {
display: flex;
height: vh(27);
line-height: vh(27);
text-align: center;
background: #074686;
&:nth-child(2n + 1) {
background: rgba(0, 150, 255, 0.1);
}
& > div {
flex: 1;
}
& > div:nth-child(1) {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
& > div:nth-child(2) {
font-weight: bold;
font-size: vw(18);
color: #ffffff;
}
& > div:nth-child(3) {
font-weight: bold;
font-size: vw(18);
color: #02f9fa;
}
.unit-1 {
font-size: vw(12);
}
}
}
}
}
.hotel {
flex: 1;
margin-left: vw(6);
& > div:nth-child(1) {
display: flex;
width: vw(360);
height: vh(70);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%; background-size: 100% 100%;
.item { .item {
padding: vh(10) vw(24); flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
}
.label { .label {
font-weight: 400; font-weight: 400;
font-size: vw(14); font-size: vw(14);
margin-bottom: vh(10);
color: rgba(255, 255, 255, 0.9); color: rgba(255, 255, 255, 0.9);
} }
.countup-wrap {
color: #02f9fa;
font-size: vw(28);
font-weight: bold;
}
.progress-box {
margin-top: vh(10);
display: flex;
align-items: center;
justify-content: center;
.text {
margin-right: vw(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
.progress {
width: vw(100);
:deep(.el-progress-bar__outer) {
background-color: #0858ae !important;
}
}
.progress-1 {
@extend .progress;
:deep(.el-progress-bar__inner) {
background: linear-gradient(to right, #0566bb 0%, #00c4f9 100%);
}
}
.progress-2 {
@extend .progress;
:deep(.el-progress-bar__inner) {
background: linear-gradient(to right, #0566bb 0%, #d6383a 100%);
}
}
.value { .value {
margin-left: vw(10); margin-top: vh(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
}
}
}
.right {
padding: vh(10) vw(24);
.item {
display: flex;
margin-bottom: vh(12);
&:nth-last-child(1) {
margin-bottom: 0;
}
.tag {
padding: 0 vw(16);
font-weight: bold; font-weight: bold;
font-size: vw(14); font-size: vw(24);
display: flex;
align-items: center;
justify-content: center;
border-radius: vw(2);
&--success {
color: #02f9fa;
border: 1px solid #02f9fa;
box-shadow: inset 0 0 vw(8) 0 #0be1ab;
}
&--error {
color: #ee2c2c;
border: 1px solid #ee2c2c;
box-shadow: inset 0 0 vw(8) 0 #ee2c2c;
}
&--primary {
color: #00aaff;
border: 1px solid #00aaff;
box-shadow: inset 0 0 vw(8) 0 #00aaff;
}
}
.content {
margin-left: vw(4);
padding: 0 vw(10);
width: vw(900);
height: vh(24);
line-height: vh(24);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 400;
font-size: vw(14);
color: #ffffff; color: #ffffff;
border-radius: vw(2);
background: rgba(0, 150, 255, 0.28);
} }
} }
} }
& > div:nth-child(2) {
padding-top: vh(10);
margin-top: vh(8);
width: vw(360);
height: vh(140);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
}
}
}
.lodging {
:deep(.title-3) {
margin-top: vh(10);
}
}
.title1 {
:deep(.title) {
width: vw(300) !important;
} }
} }
</style> </style>

View File

@@ -1,536 +0,0 @@
<template>
<div class="box-4">
<Title1 title="交通信息" />
<div class="flex justify-evenly pt-10 pb-20">
<div v-for="item in list" class="cell">
<img class="icon" :src="item.icon" alt="" width="64" height="64" />
<div>
<countup :end-val="item.value" />
<div class="label">{{ item.label }}</div>
</div>
</div>
</div>
<div class="flex">
<div class="box">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<div class="">
<Line
:width="250"
:height="150"
:config="{ legend: false }"
:data="[
{
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 class="box">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<Line
:width="250"
:height="150"
:config="{ legend: false }"
:data="[
{
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 class="box">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<jam :width="250" :height="200" />
</div>
</div>
</div>
<Title1 title="停车信息" />
<div class="stop-box">
<div>
<img class="icon" src="@/assets/images/icon-5.png" alt="" />
<div>
<div class="label">车库总数</div>
<countup class="value" :end-val="500" />
</div>
<div>
<div class="label">车库总数</div>
<countup class="value" :end-val="500" />
</div>
<div>
<div class="label">已使用车位数</div>
<countup class="value" :end-val="500" />
</div>
</div>
<div>
<div>
<div class="label">三峡之巅</div>
<div class="value error">已满</div>
</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 class="flex pt-10">
<div class="box-1">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<div class="pt-20">
<Line
:width="250"
:height="120"
:config="{ legend: false }"
:data="[
{
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 class="box-1">
<div class="pt-10">
<Title3 title="拥堵路段总数" />
<traffic-flow />
</div>
</div>
<div class="box-1">
<div class="pt-10">
<Title3 title="景区停车场空位" />
<vacancy />
</div>
</div>
</div>
<div class="flex">
<div class="flex-1">
<Title1 title="车船信息" class="title1" />
</div>
<div class="flex-1">
<Title1 title="酒店信息" class="title1" />
</div>
</div>
<div class="flex">
<div class="car-ship">
<div class="mb-6">
<div class="car">
<div class="label">车总数</div>
<div class="flex align-center">
<countup class="value" :end-val="130" /> <span class="unit"></span>
</div>
</div>
<div class="table">
<div class="header">
<div>景区</div>
<div>调度</div>
<div>空余</div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
</div>
</div>
<div>
<div class="ship">
<div class="label">车总数</div>
<div class="flex align-center">
<countup class="value" :end-val="130" /> <span class="unit"></span>
</div>
<div class="table">
<div class="header">
<div>景区</div>
<div>调度</div>
<div>空余</div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
</div>
</div>
</div>
</div>
<div class="hotel">
<div>
<div class="item">
<div class="label">车库总数</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">房间总数</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">总入住</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">总入住率</div>
<countup class="value" :end-val="500" />
</div>
</div>
<div>
<div class="lodging">
<Title3 title="酒店入住人数及入住率" />
</div>
<lodging-ratio />
</div>
</div>
</div>
</div>
</template>
<script setup>
import jam from './jam.vue'
import vacancy from './vacancy.vue'
import LodgingRatio from './lodging-ratio.vue'
import TrafficFlow from './traffic-flow.vue'
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'
let list = ref([
{
label: '路段总数',
value: '1234',
icon: icon1
},
{
label: '当前拥堵路段',
value: '1234',
icon: icon2
},
{
label: '总拥堵次数',
value: '1234',
icon: icon3
},
{
label: '最大拥堵时长',
value: '1234',
icon: icon4
}
])
</script>
<style lang="scss" scoped>
.box-4 {
margin-top: vh(120);
width: vw(750);
height: vh(950);
padding: vw(8);
box-sizing: border-box;
background-image: url('@/assets/images/bg-5.png');
background-size: 100% 100%;
.cell {
display: flex;
align-items: center;
.icon {
width: vw(64);
height: auto;
}
.countup-wrap {
color: #02f9fa;
font-size: vw(24);
font-weight: bold;
}
.label {
font-weight: 400;
font-size: vw(14);
margin-top: vh(10);
color: rgba(255, 255, 255, 0.9);
}
}
.box {
width: vw(250);
height: vh(200);
margin-right: vw(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
.box-1 {
width: vw(250);
height: vh(200);
margin-right: vw(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
.stop-box {
display: flex;
gap: vw(20);
.icon {
width: vw(45);
height: auto;
}
& > div {
flex: 1;
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
.value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #ffffff;
}
.error {
color: #e21b1b;
}
.success {
color: #02f9fa;
}
}
}
.car-ship {
flex: 1;
& > div {
position: relative;
flex: 1;
height: vh(110);
display: flex;
align-items: center;
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.icon {
padding-left: vw(90);
width: vw(352);
height: vh(70);
display: flex;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
}
.car {
@extend .icon;
background-image: url('@/assets/images/icon-6.png');
background-size: 100% 100%;
}
.ship {
@extend .icon;
background-image: url('@/assets/images/icon-7.png');
background-size: 100% 100%;
}
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
margin-bottom: vh(6);
}
.value {
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.unit {
font-weight: bold;
font-size: vw(14);
color: #02f9fa;
margin-top: vh(6);
}
.table {
position: absolute;
left: vw(160);
width: vw(200);
height: vh(100);
z-index: 2;
.header {
display: flex;
height: vh(18);
line-height: vh(18);
text-align: center;
background: rgba(0, 150, 255, 0.4);
& > div {
flex: 1;
font-weight: 400;
font-size: vw(12);
color: #52b8ff;
}
}
.cell {
display: flex;
height: vh(27);
line-height: vh(27);
text-align: center;
background: #074686;
&:nth-child(2n + 1) {
background: rgba(0, 150, 255, 0.1);
}
& > div {
flex: 1;
}
& > div:nth-child(1) {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
& > div:nth-child(2) {
font-weight: bold;
font-size: vw(18);
color: #ffffff;
}
& > div:nth-child(3) {
font-weight: bold;
font-size: vw(18);
color: #02f9fa;
}
.unit-1 {
font-size: vw(12);
}
}
}
}
}
.hotel {
flex: 1;
margin-left: vw(6);
& > div:nth-child(1) {
display: flex;
width: vw(360);
height: vh(70);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
.value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #ffffff;
}
}
}
& > div:nth-child(2) {
padding-top: vh(10);
margin-top: vh(8);
width: vw(360);
height: vh(140);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
}
}
}
.lodging {
:deep(.title-3) {
margin-top: vh(10);
}
}
.title1 {
:deep(.title) {
width: vw(300) !important;
}
}
</style>

View File

@@ -27,15 +27,7 @@
bottom: '-10%', bottom: '-10%',
containLabel: true containLabel: true
}, },
xAxis: [ xAxis: [{ max: 100, show: false }],
{
splitLine: {
show: false
},
type: 'value',
show: false
}
],
yAxis: [ yAxis: [
{ {
splitLine: { splitLine: {
@@ -55,7 +47,6 @@
}, },
{ {
type: 'category', type: 'category',
inverse: true,
axisTick: 'none', axisTick: 'none',
axisLine: 'none', axisLine: 'none',
show: true, show: true,
@@ -65,7 +56,7 @@
fontSize: fitChartSize(12) fontSize: fitChartSize(12)
}, },
verticalAlign: 'bottom', verticalAlign: 'bottom',
padding: [0, 0, 6, 0], padding: [0, 0, fitChartSize(6), 0],
inside: true, inside: true,
formatter: function (value) { formatter: function (value) {
return `{value|${value}}` return `{value|${value}}`
@@ -101,7 +92,7 @@
}, },
label: { label: {
show: true, show: true,
offset: [10, -13], offset: [fitChartSize(10), -fitChartSize(20)],
color: '#D3E5FF', color: '#D3E5FF',
fontWeight: 500, fontWeight: 500,
position: 'left', position: 'left',

View File

@@ -1,51 +1,24 @@
<template> <template>
<div class="top" id="top" /> <div class="top" :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 colorList = [
'rgba(255, 38, 38, 1)', const homeData = inject('homeData')
'rgba(255, 96, 0, 1)',
'rgba(255, 165, 7, 1)', watch(
'rgba(0, 234, 255, 1)', () => homeData.value?.userPortrait?.provinceRate,
'rgba(0, 132, 255, 1)', () => {
'#2379FF' init()
] }
let colorListA = [ )
'rgba(255, 38, 38, 0.1)',
'rgba(255, 96, 0, 0.1)', const init = () => {
'rgba(255, 165, 7, 0.1)', setOption({
'rgba(0, 234, 255, 0.1)',
'rgba(0, 132, 255, 0.1)',
'#49B1FF'
]
let colorListB = [
'rgba(249, 136, 136, 1)',
'rgba(255, 162, 106, 1)',
'rgba(255, 210, 130, 1)',
'rgba(142, 255, 206, 1)',
'rgba(165, 232, 255, 1)'
]
let colorListC = [
'rgba(249, 136, 136, 0.1)',
'rgba(255, 162, 106, 0.1)',
'rgba(255, 210, 130, 0.1)',
'rgba(142, 255, 206, 0.1)',
'rgba(165, 232, 255, 0.1)'
]
let result = [
{ name: '河北', value: 86 },
{ name: '山西', value: 83 },
{ name: '河南', value: 73 },
{ name: '内蒙', value: 61 },
{ name: '辽宁', value: 61 }
]
let option = {
color: colorList,
backgroundColor: 'transparent', backgroundColor: 'transparent',
tooltip: { tooltip: {
show: false show: false
@@ -56,19 +29,11 @@
grid: { grid: {
left: '4%', left: '4%',
right: '4%', right: '4%',
top: '6%', top: '10%',
bottom: '-4%', bottom: '-4%',
containLabel: true containLabel: true
}, },
xAxis: [ xAxis: [{ max: 100, show: false }],
{
splitLine: {
show: false
},
type: 'value',
show: false
}
],
yAxis: [ yAxis: [
{ {
splitLine: { splitLine: {
@@ -81,14 +46,12 @@
axisTick: { axisTick: {
show: false show: false
}, },
data: result.map((item) => item.name),
axisLabel: { axisLabel: {
show: false show: false
} }
}, },
{ {
type: 'category', type: 'category',
inverse: true,
axisTick: 'none', axisTick: 'none',
axisLine: 'none', axisLine: 'none',
show: true, show: true,
@@ -98,10 +61,10 @@
fontSize: fitChartSize(12) fontSize: fitChartSize(12)
}, },
verticalAlign: 'bottom', verticalAlign: 'bottom',
padding: [0, 0, 10, 0], padding: [0, 0, fitChartSize(10), 0],
inside: true, inside: true,
formatter: function (value) { formatter: function (value) {
return `{value|${value}}` return `{value|${value}}%`
}, },
rich: { rich: {
name: { name: {
@@ -118,7 +81,7 @@
} }
} }
}, },
data: result.map((item) => item.value) data: homeData.value?.userPortrait?.provinceRate.map((item) => Number(item.value))
} }
], ],
series: [ series: [
@@ -128,13 +91,13 @@
barWidth: fitChartSize(12), barWidth: fitChartSize(12),
MaxSize: 0, MaxSize: 0,
showBackground: true, showBackground: true,
barBorderRadius: [30, 0, 0, 30], barBorderRadius: [fitChartSize(30), 0, 0, fitChartSize(30)],
backgroundStyle: { backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)' color: 'rgba(0, 150, 255, 0.15)'
}, },
label: { label: {
show: true, show: true,
offset: [10, -17], offset: [fitChartSize(10), -fitChartSize(17)],
color: '#D3E5FF', color: '#D3E5FF',
fontWeight: 500, fontWeight: 500,
position: 'left', position: 'left',
@@ -145,10 +108,10 @@
return params.data.name return params.data.name
} }
}, },
data: result.map((item, index) => { data: homeData.value?.userPortrait?.provinceRate.map((item, index) => {
return { return {
name: item.name, name: item.name,
value: item.value, value: Number(item.value),
itemStyle: { itemStyle: {
barBorderRadius: [3, 0, 0, 3], barBorderRadius: [3, 0, 0, 3],
color: { color: {
@@ -160,11 +123,11 @@
colorStops: [ colorStops: [
{ {
offset: 0, offset: 0,
color: colorListA[index] color: 'transparent'
}, },
{ {
offset: 1, offset: 1,
color: colorList[index] color: parseFloat(item.value) > 50 ? '#FF7021' : '#00CCFF'
} }
] ]
} }
@@ -172,75 +135,9 @@
} }
}) })
} }
// {
// name: '外圆',
// type: 'scatter',
// emphasis: {
// scale: false
// },
// showSymbol: true,
// symbol: 'circle',
// symbolSize: 8, // 进度条白点
// z: 2,
// data: result.map((item, index) => {
// return {
// name: item.name,
// value: item.value,
// itemStyle: {
// color: colorListB[index],
// borderColor: colorListC[index],
// borderWidth: 12,
// shadowColor: colorListC[index],
// shadowBlur: 10,
// opacity: 1
// }
// }
// }),
// animationDelay: 500
// },
// {
// name: '外圆',
// type: 'scatter',
// emphasis: {
// scale: false
// },
// showSymbol: true,
// symbol: 'circle',
// symbolSize: 3, // 进度条白点
// z: 3,
// data: result.map((item, index) => {
// return {
// name: item.name,
// value: item.value,
// itemStyle: {
// color: colorListB[index],
// borderColor: colorListC[index],
// borderWidth: 30,
// shadowColor: colorListC[index],
// shadowBlur: 10,
// opacity: 1
// }
// }
// }),
// animationDelay: 500
// }
] ]
}
const init = () => {
topChart = echarts.init(document.getElementById('top'))
topChart.setOption(option)
}
const resize = () => {
if (topChart) {
topChart.dispose()
topChart = null
init()
}
}
onMounted(() => {
init()
window.addEventListener('resize', resize)
}) })
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -2,20 +2,22 @@
<Header title="奉节县旅游指挥调度中心" is-skip :nav-left="navLeft" :nav-right="navRight" /> <Header title="奉节县旅游指挥调度中心" is-skip :nav-left="navLeft" :nav-right="navRight" />
<CoreVideo /> <CoreVideo />
<box1 :data="data" /> <box1 :data="data" />
<box2 />
<box3 /> <box3 />
<box4 />
<Correspondence /> <Correspondence />
</template> </template>
<script setup> <script setup>
import box1 from './components/box-1.vue' import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
import box3 from './components/box-3.vue' import box3 from './components/box-3.vue'
import box4 from './components/box-4.vue'
import { useWebSocket } from '@/hooks/socket' import { useWebSocket } from '@/hooks/socket'
const { data, sendMessage } = useWebSocket('ws://36.138.38.16:81/ws/third-party') const { data, sendMessage } = useWebSocket('ws://36.138.38.16:81/ws/third-party')
provide('homeData', data)
const navLeft = [ const navLeft = [
{ name: '安全', path: '/monitor' }, { name: '安全', path: '/monitor' },
{ name: '景区', path: '/scenic' }, { name: '景区', path: '/scenic' },

View File

@@ -1,18 +1,16 @@
<template> <template>
<div class="area" id="area" /> <div class="area" :id="id" />
</template> </template>
<script setup> <script setup>
import * as echarts from 'echarts' import { useEchart } from '@/hooks/echart'
import { fitChartSize } from '@/utils/dataUtil' import { fitChartSize } from '@/utils/dataUtil'
import { getAreaApi } from '@/api/sentiment.js' import { getAreaApi } from '@/api/sentiment.js'
let areaChart = null const { id, setOption } = useEchart()
const initChart = async () => { const initChart = async () => {
const dom = document.getElementById('area')
areaChart = echarts.init(dom)
let res = await getAreaApi() let res = await getAreaApi()
areaChart.setOption({ setOption({
legend: { legend: {
top: 'top', top: 'top',
itemWidth: fitChartSize(30), itemWidth: fitChartSize(30),
@@ -43,16 +41,8 @@
] ]
}) })
} }
const resize = () => {
if (areaChart) {
areaChart.dispose()
areaChart = null
initChart()
}
}
onMounted(() => { onMounted(() => {
initChart() initChart()
window.addEventListener('resize', resize)
}) })
</script> </script>

View File

@@ -1,20 +1,17 @@
<template> <template>
<div class="wordCloud" id="wordCloud" /> <div class="wordCloud" :id="id" />
</template> </template>
<script setup> <script setup>
import * as echarts from 'echarts'
import 'echarts-wordcloud' import 'echarts-wordcloud'
import { fitChartSize } from '@/utils/dataUtil' import { fitChartSize } from '@/utils/dataUtil'
import { getHotWordApi } from '@/api/sentiment' import { getHotWordApi } from '@/api/sentiment'
import { useEchart } from '@/hooks/echart'
let wordChart = null const { id, setOption } = useEchart()
const initChart = async () => { const initChart = async () => {
const dom = document.getElementById('wordCloud')
wordChart = echarts.init(dom)
let res = await getHotWordApi() let res = await getHotWordApi()
wordChart.setOption({ setOption({
//你的代码
series: [ series: [
{ {
type: 'wordCloud', type: 'wordCloud',
@@ -52,16 +49,8 @@
] ]
}) })
} }
const resize = () => {
if (wordChart) {
wordChart.dispose()
wordChart = null
initChart()
}
}
onMounted(() => { onMounted(() => {
initChart() initChart()
window.addEventListener('resize', resize)
}) })
</script> </script>

View File

@@ -36,9 +36,9 @@
</div> </div>
</div> </div>
<div class="flex mt-10"> <div class="flex mt-10">
<div class="box-2 mr-10"> <div class="box-2 mr-10 rela">
<Title1 title="舆情指数" /> <Title1 title="舆情指数" />
<Dropdown :options="options" @on-change="onChange" /> <div class="dropdown"> <Dropdown :options="options" @on-change="onChange" /> </div>
<Line <Line
:width="1560" :width="1560"
:height="400" :height="400"
@@ -81,7 +81,6 @@
let stateList = ref([]) let stateList = ref([])
let options = ref([]) let options = ref([])
const onChange = (e) => { const onChange = (e) => {
console.log(e, '===')
getLineChart(e.id) getLineChart(e.id)
} }
const getStop = async () => { const getStop = async () => {
@@ -97,7 +96,6 @@
const getState = async () => { const getState = async () => {
let res = await getStateApi() let res = await getStateApi()
stateList.value = res.data stateList.value = res.data
console.log(stateList.value, '------')
} }
const getLineChart = async (id) => { const getLineChart = async (id) => {
let res = await getLineChartApi({ id }) let res = await getLineChartApi({ id })
@@ -118,6 +116,11 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.dropdown {
position: absolute;
z-index: 9999;
right: vw(10);
}
.container { .container {
margin-top: vh(120); margin-top: vh(120);
.bg { .bg {