feat:完善功能

This commit is contained in:
zjc
2025-01-16 12:37:23 +08:00
parent ef5cb642ca
commit 2a11f91d36
43 changed files with 2644 additions and 3108 deletions

View File

@@ -38,8 +38,8 @@
</li>
</ul>
</div>
<div class="map" id="map"></div>
<div class="spot-wrap">
<div class="map" id="map" />
<!-- <div class="spot-wrap">
<ul class="spot-list">
<li
class="spot-item"
@@ -50,7 +50,7 @@
<img :src="`http://36.138.38.16:8001/fjtcc-api${item.img}`" />
</li>
</ul>
</div>
</div> -->
</div>
<div class="footer">
<div class="left">
@@ -315,11 +315,11 @@
}
}
.footer {
margin-top: vh(4);
display: flex;
width: 100%;
height: vh(120);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 400%;
background-image: url('@/assets/images/bg-2.png');
background-size: 100% 100%;
.left {
flex: 1;
display: flex;

View File

@@ -2,13 +2,13 @@
<div class="box-4">
<Title1 title="交通信息" />
<div class="traffic-info flex justify-evenly pt-10 pb-20">
<div class="cell">
<!-- <div class="cell">
<img class="icon" src="@/assets/images/icon-1.png" alt="" />
<div>
<countup :end-val="homeStore.trafficInfoData.info.ldzs" />
<div class="label">路段总数</div>
</div>
</div>
</div> -->
<div class="cell">
<img class="icon" src="@/assets/images/icon-2.png" alt="" />
<div>

View File

@@ -91,6 +91,7 @@
},
xAxis: [
{
// max: 10000,
splitLine: {
show: false
},
@@ -117,7 +118,7 @@
},
{
type: 'category',
inverse: true,
inverse: false,
axisTick: 'none',
axisLine: 'none',
show: true,

View File

@@ -118,7 +118,7 @@
},
{
type: 'category',
inverse: true,
inverse: false,
axisTick: 'none',
axisLine: 'none',
show: true,

View File

@@ -115,7 +115,7 @@
},
{
type: 'category',
inverse: true,
inverse: false,
axisTick: 'none',
axisLine: 'none',
show: true,

View File

@@ -16,7 +16,6 @@
() => isConnected.value,
(val) => {
if (val) {
console.log('--------------------------------------------')
sendMessage(
JSON.stringify({
action: 'start',

View File

@@ -0,0 +1,86 @@
<template>
<div class="alarm">
<p class="alarm-title">异常点位告警排名</p>
<ul class="alarm-list">
<li class="alarm-item" v-for="(item, index) in 10" :key="index">
<div class="alarm-item__rank">{{ index + 1 }}</div>
<p class="alarm-item__label">核心监控点1</p>
</li>
</ul>
</div>
</template>
<script setup></script>
<style scoped lang="scss">
.alarm {
&-title {
padding-bottom: vh(10);
font-weight: bold;
font-size: vw(14);
color: #37d8fc;
}
&-list {
width: vw(140);
height: vh(160);
overflow-y: auto;
&::-webkit-scrollbar {
width: vw(4); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: 'transparent'; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
}
&-item {
margin-bottom: vh(10);
display: flex;
align-items: center;
background: linear-gradient(90deg, #1b5ec7 0%, rgba(27, 94, 199, 0) 100%);
&:nth-child(1) {
background: linear-gradient(90deg, #ffc10b 0%, rgba(255, 209, 44, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-1.png');
background-size: 100% 100%;
}
}
&:nth-child(2) {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-2.png');
background-size: 100% 100%;
}
}
&:nth-child(3) {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-3.png');
background-size: 100% 100%;
}
}
}
&-item__rank {
width: vw(24);
height: vw(24);
font-weight: bold;
font-size: vw(14);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/rk-4.png');
background-size: 100% 100%;
}
&-item__label {
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<div class="alarmRate" :id="id" />
</template>
<script setup>
import { fitChartSize } from '@/utils/dataUtil'
import { useEchart } from '@/hooks/echart'
const props = defineProps({
config: {
type: Object,
default: () => {
return {}
}
},
dataList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: () => 123456
},
colors: {
type: Array,
default: () => ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
}
})
const { id, setOption } = useEchart()
var defaultCofig = {
color: [],
legend: {
orient: 'vertical',
bottom: 'center',
left: '50%',
itemWidth: fitChartSize(12),
itemHeight: fitChartSize(12),
itemGap: fitChartSize(10),
textStyle: {
color: '#ffffff',
fontSize: fitChartSize(16)
}
},
series: [
{
type: 'pie',
center: ['30%', '50%'],
radius: ['30%', '40%'],
itemStyle: {
borderWidth: fitChartSize(4),
borderColor: '#093672'
},
label: {
show: true,
position: 'center',
fontWeight: 'bold',
rich: {
value: {
color: '#fff',
fontSize: fitChartSize(16),
fontWeight: 'bold',
padding: [0, 0, 5, 0]
},
name: {
color: '#7894A8',
fontSize: fitChartSize(12)
}
}
},
labelLine: {
show: false
},
data: []
}
]
}
watch(
() => props.dataList,
(newVal) => {
if (newVal.length > 0) {
nextTick(() => {
defaultCofig.color = props.colors
defaultCofig.series[0].data = props.dataList
defaultCofig.series[0].label.formatter = () => {
return `{value|${props.total}}` + '\n' + `{name|工单总数}`
}
setOption({
...defaultCofig,
...props.config
})
})
}
},
{ immediate: true }
)
</script>
<style scoped lang="scss">
.alarmRate {
width: vw(240);
height: vh(200);
}
</style>

View File

@@ -0,0 +1,398 @@
<template>
<div class="box-1">
<Title1 title="交通信息" />
<div class="traffic">
<div class="traffic-item">
<span class="traffic-item__title">总核心监控点位</span>
<countup class="traffic-item__value--primary" end-val="895" />
</div>
<div class="traffic-item">
<span class="traffic-item__title">总核心监控点位</span>
<countup class="traffic-item__value--success" end-val="895" />
</div>
<div class="traffic-item">
<span class="traffic-item__title">总核心监控点位</span>
<countup class="traffic-item__value--error" end-val="895" />
</div>
</div>
<Title1 title="景区信息" />
<div class="scenic">
<div class="scenic-item">
<span class="scenic-item__label">核心路段监控点位</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">核心景区分析点位</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">异常点位</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">异常告警</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">已处理</span>
<countup class="scenic-item__value" end-val="895" />
</div>
</div>
<div class="flex pt-20">
<div class="box">
<Title3 title="异常告警" />
<Line
:width="370"
:height="180"
: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 class="box">
<Title3 title="异常告警占比" />
<div class="flex">
<alarmRate :dataList="dataList" />
<alarmList />
</div>
</div>
</div>
<Title1 title="交通信息" />
<div class="scenic">
<div class="scenic-item">
<span class="scenic-item__label">核心路段监控点位</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">核心景区分析点位</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">拥堵路段</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">拥堵告警</span>
<countup class="scenic-item__value" end-val="895" />
</div>
<div class="scenic-item">
<span class="scenic-item__label">已处理</span>
<countup class="scenic-item__value" end-val="895" />
</div>
</div>
<div class="flex pt-20">
<div class="box">
<Title3 title="异常告警" />
<Line
:width="370"
:height="180"
: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 class="box">
<Title3 title="异常告警占比" />
<div class="flex">
<alarmRate :dataList="dataList" />
<alarmList />
</div>
</div>
</div>
</div>
</template>
<script setup>
import countup from 'vue-countup-v3'
import alarmRate from './alarmRate'
import alarmList from './alarmList'
const dataList = ref([
{
name: '云阳',
value: 20
},
{
name: '奉节',
value: 10
},
{
name: '巫山',
value: 70
}
])
</script>
<style scoped lang="scss">
:deep(.el-select__wrapper) {
background: linear-gradient(270deg, rgba(8, 41, 86, 0.16) 0%, #0b61b4 100%);
border: none;
box-shadow: none;
border-top-left-radius: vh(30);
border-bottom-left-radius: vh(30);
font-size: vw(14);
color: #fff;
}
.line-chart {
width: 100%;
height: vh(200);
}
.box-1 {
margin-top: vh(120);
width: vw(800);
height: vh(950);
padding: vw(8);
box-sizing: border-box;
background-image: url('@/assets/images/bg-2.png');
background-size: 100% 100%;
.traffic {
margin-top: vh(20);
height: vh(72);
display: flex;
align-items: center;
justify-content: space-evenly;
&-item {
width: vw(229);
height: vw(72);
font-weight: 400;
font-size: vw(14);
color: #fff;
padding-left: vw(84);
display: flex;
flex-direction: column;
justify-content: center;
&:nth-child(1) {
background-image: url('@/assets/images/m-t-1.png');
background-size: 100% 100%;
}
&:nth-child(2) {
background-image: url('@/assets/images/m-t-2.png');
background-size: 100% 100%;
}
&:nth-child(3) {
background-image: url('@/assets/images/m-t-3.png');
background-size: 100% 100%;
}
}
&-item__title {
margin-bottom: vh(6);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
&-item__value--primary {
font-weight: bold;
font-size: vw(24);
color: #12b5fd;
}
&-item__value--success {
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
&-item__value--error {
font-weight: bold;
font-size: vw(24);
color: #f15a25;
}
}
.scenic {
display: flex;
align-items: center;
height: vh(106);
gap: vw(20);
&-item {
width: vw(142);
height: vw(106);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&:nth-child(1) {
background-image: url('/src/assets/images/four-t-1.png');
background-size: 100% 100%;
.scenic-item__value {
color: #02f9fa;
}
}
&:nth-child(2) {
background-image: url('/src/assets/images/four-t-1.png');
background-size: 100% 100%;
.scenic-item__value {
color: #02f9fa;
}
}
&:nth-child(3) {
background-image: url('/src/assets/images/four-t-2.png');
background-size: 100% 100%;
.scenic-item__value {
color: #f15a25;
}
}
&:nth-child(4) {
background-image: url('/src/assets/images/four-t-3.png');
background-size: 100% 100%;
.scenic-item__value {
color: #f15a25;
}
}
&:nth-child(5) {
background-image: url('/src/assets/images/four-t-4.png');
background-size: 100% 100%;
.scenic-item__value {
color: #12b5fd;
}
}
}
&-item__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
&-item__value {
font-weight: bold;
font-size: vw(24);
margin-top: vh(10);
}
}
.unit {
color: #02f9fa;
font-size: vw(14);
margin-bottom: vh(4);
}
.box {
width: vw(394);
height: vh(220);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
.title-2 {
width: vw(253);
height: vh(28);
display: flex;
align-items: center;
background-image: url('@/assets/images/title-5.png');
background-size: 100% 100%;
& > span {
padding-left: vw(22);
font-weight: bold;
font-size: vw(15);
background-image: linear-gradient(to bottom, #ffffff 0%, #75c1ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
.statistic {
display: flex;
margin-top: vh(12);
width: 100%;
height: vh(88);
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;
}
&-title {
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
&-value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.count {
font-weight: bold;
font-size: vw(28);
color: #ff4400 !important;
}
.prefix,
.suffix {
color: #ff4400;
font-size: vw(12);
}
}
.title-3 {
position: relative;
width: vw(344);
height: vh(12);
margin-top: vh(20);
background-image: url('@/assets/images/title-6.png');
background-size: 100% 100%;
& > span {
position: absolute;
bottom: vh(4);
left: vw(20);
font-size: vw(15);
font-weight: bold;
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
}
}
</style>

View File

@@ -1,692 +1,33 @@
<template>
<!-- 视频 -->
<div class="box-2">
<div class="header">
<div class="title"> <span>交通信息</span> </div>
</div>
<div class="flex pt-20 p-box">
<div class="item core">
<span class="title-1">总核心监控点位</span>
<div class="flex align-end color1"> <countup endVal="895" /><span class="unit"></span></div>
</div>
<div class="item queue">
<span class="title-1">总核心分析点位</span>
<div class="flex align-end color2"> <countup endVal="895" /><span class="unit"></span></div>
</div>
<div class="item congestion">
<span class="title-1">总异常点位</span>
<div class="flex align-end color3"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="header">
<div class="title"> <span>景区信息</span> </div>
</div>
<div class="flex-four">
<div class="item item1">
<div class="box1">
核心路段监控点位
<div class="item-num color1"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item2">
<div class="box1">
核心景区分析点位
<div class="item-num color1"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item3">
<div class="box1">
异常点位
<div class="item-num color2"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item4">
<div class="box1">
异常告警
<div class="item-num color3"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item5">
<div class="box1">
已处理
<div class="item-num color4"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
</div>
<div class="flex pt-20 p-box">
<div class="box">
<div class="title-3"><span>异常告警</span></div>
<div class="pt-20 chart-p">
<Line
:width="370"
:height="180"
: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="title-3"><span>异常告警占比</span></div>
<div class="pt-20 h-flex">
<div class="left">
<v-chart class="chart" :option="option1" autoresize />
</div>
<div class="right">
<div class="li li-1"><span class="rk-img">1</span> 核心监控1</div>
<div class="li li-2"><span class="rk-img">1</span>核心监控1</div>
<div class="li li-3"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控</div>
</div>
</div>
</div>
</div>
<div class="header">
<div class="title"> <span>交通信息</span> </div>
</div>
<div class="flex-four">
<div class="item item1">
<div class="box1">
核心路段监控点位
<div class="item-num color1"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item2">
<div class="box1">
核心景区分析点位
<div class="item-num color1"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item3">
<div class="box1">
异常点位
<div class="item-num color2"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item4">
<div class="box1">
异常告警
<div class="item-num color3"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
<div class="item item5">
<div class="box1">
已处理
<div class="item-num color4"> <countup endVal="895" /><span class="unit"></span></div>
</div>
</div>
</div>
<div class="flex pt-20 p-box">
<div class="box">
<div class="title-3"><span>异常告警</span></div>
<div class="pt-20 chart-p">
<Line
:width="370"
:height="180"
: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="title-3"><span>异常告警占比</span></div>
<div class="pt-20 h-flex">
<div class="left">
<v-chart class="chart" :option="option1" autoresize />
</div>
<div class="right">
<div class="li li-1"><span class="rk-img">1</span> 核心监控1</div>
<div class="li li-2"><span class="rk-img">1</span>核心监控1</div>
<div class="li li-3"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控</div>
</div>
</div>
</div>
</div>
<Nav />
<!-- 视频 -->
<Monitor />
</div>
</template>
<script setup>
import * as echarts from 'echarts'
import countup from 'vue-countup-v3'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { GaugeChart } from 'echarts/charts'
import { PieChart } from 'echarts/charts'
import { LineChart } from 'echarts/charts'
import { fitChartSize } from '@/utils/dataUtil'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import VChart, { THEME_KEY } from 'vue-echarts'
import { ref, provide } from 'vue'
import Nav from '@/components/Nav/index.vue'
import Monitor from '@/components/Monitor/index.vue'
import { getVideoListApi, postRefreshApi } from '@/api/home'
use([
LineChart,
GaugeChart,
CanvasRenderer,
PieChart,
TitleComponent,
TooltipComponent,
LegendComponent
])
const getVideoList = async () => {
let res = await getVideoListApi({
businessVideoDisplayPosition: ''
})
console.log(res, 'res')
}
provide(THEME_KEY, 'dark')
let selectSpot = ref('')
const option1 = ref({
backgroundColor: 'transparent',
tooltip: {
trigger: 'item'
},
legend: {
type: 'scroll',
orient: 'vertical',
right: -10,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
textStyle: {
fontSize: fitChartSize(12)
}
},
series: [
{
name: 'Access From',
type: 'pie',
left: -25,
top: -20,
width: fitChartSize(230),
height: fitChartSize(230),
radius: ['40%', '50%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: fitChartSize(10),
fontWeight: 'bold',
color: '#fff'
}
},
labelLine: {
show: true
},
data: [
{ value: 200, name: '异常状况1' },
{ value: 500, name: '异常状况2' },
{ value: 234, name: '异常状况3' },
{ value: 135, name: '异常状况4' },
{ value: 100, name: '异常状况5' },
{ value: 777, name: '异常状况6' },
{ value: 777, name: '其他' }
]
}
]
onMounted(() => {
getVideoList()
})
const optionLine = ref({
backgroundColor: 'transparent',
grid: {
top: '50',
bottom: '20',
left: '4%',
containLabel: true
},
xAxis: {
nameLocation: 'middle',
type: 'category',
boundaryGap: false,
axisLabel: {
fontSize: fitChartSize(10),
interval: 0, // 显示所有标签
rotate: 0 // 旋转标签45度
},
data: ['10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00'],
axisTisk: {
show: true,
// 设置刻度长度
length: 1,
lineStyle: {
type: 'dashed', // 设置为虚线
width: 0
}
},
axisLine: {
lineStyle: {
color: '#0096FF' // 设置横线颜色
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 45,
interval: 15,
axisLabel: {
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
color: 'rgba(255,255,255,0.9)'
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#00D0FF'
}
}
},
series: [
{
data: [0, 23, 30, 24, 40, 30, 45, 26],
type: 'line',
smooth: true,
label: {
show: false //隐藏坐标点
},
itemStyle: {
color: 'transparent'
},
markLine: {
symbol: ['none', 'none'],
label: { show: false }
},
lineStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: '#7DE7FF'
},
{
offset: 0.5,
color: '#02F9FA'
},
{
offset: 1,
color: '#009DFF'
}
]),
width: 3
}
}
]
})
onMounted(() => {})
</script>
<style scoped lang="scss">
:deep(.el-select__wrapper) {
background: linear-gradient(270deg, rgba(8, 41, 86, 0.16) 0%, #0b61b4 100%);
border: none;
box-shadow: none;
border-top-left-radius: vh(30);
border-bottom-left-radius: vh(30);
font-size: vw(14);
color: #fff;
}
.line-chart {
width: 100%;
height: vh(200);
}
<style lang="scss" scoped>
.box-2 {
width: vw(2356);
height: vh(965);
margin-top: vh(120);
width: vw(800);
height: vh(950);
padding: vw(8);
box-sizing: border-box;
// background-image: url('@/assets/images/bg-2.png');
background-size: 100% 100%;
.p-box {
padding-top: vh(5) !important;
justify-content: space-between;
.chart-p {
position: relative;
.check-box {
position: absolute;
right: vw(30);
top: vh(10);
width: vw(120);
z-index: 19;
}
}
}
.h-flex {
display: flex;
justify-content: space-between;
.left {
flex: 1;
width: vw(260);
}
.right {
margin-left: vw(20);
width: vw(120);
.li {
position: relative;
font-weight: 400;
font-size: vw(14);
color: #ffffff;
line-height: 16px;
text-align: left;
font-style: normal;
text-transform: none;
position: relative;
padding-left: vw(30);
padding: 0 vw(10);
padding-left: vw(15);
background: linear-gradient(90deg, #1b5ec7 0%, rgba(27, 94, 199, 0) 100%);
border-radius: 0px 0px 0px 0px;
height: vh(24);
line-height: vh(24);
margin-bottom: vh(8);
// opacity: 0.4;
.rk-img {
position: absolute;
width: vw(24);
height: vh(24);
line-height: vh(24);
left: vw(-12);
top: 50%;
display: block;
background-image: url('/src/assets/images/rk-4.png');
background-size: 100% 100%;
transform: translateY(-50%);
text-align: center;
}
}
.li-1 {
background: linear-gradient(90deg, #ffc10b 0%, rgba(255, 209, 44, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-1.png');
}
}
.li-2 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-2.png');
}
}
.li-3 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-3.png');
}
}
}
}
.flex-four {
display: flex;
justify-content: center;
align-items: center;
.item {
margin: vw(10);
width: vw(142);
height: vh(106);
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
line-height: 16px;
text-align: center;
font-style: normal;
text-transform: none;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
margin-top: 0;
.box1 {
width: vw(142);
}
.item-num {
margin-top: vh(10);
}
.color1 {
color: #02f9fa;
}
.color2 {
color: #f15a25;
}
.color3 {
color: #e21b1b;
}
.color4 {
color: #12b5fd;
}
}
.item1,
.item2 {
background-image: url('/src/assets/images/four-t-1.png');
background-size: 100% 100%;
}
.item3 {
background-image: url('/src/assets/images/four-t-2.png');
}
.item4 {
background-image: url('/src/assets/images/four-t-3.png');
}
.item5 {
background-image: url('/src/assets/images/four-t-4.png');
}
}
.header {
position: relative;
.title {
margin: vh(5) auto;
width: vw(468);
height: vh(32);
font-weight: 800;
font-size: vw(16);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/title-4.png');
background-size: 100% 100%;
span {
font-weight: 800;
color: transparent;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
}
}
.more {
position: absolute;
top: vh(0);
right: vw(20);
cursor: pointer;
width: vw(60);
height: vh(24);
background-image: url('@/assets/images/more.png');
background-size: 100% 100%;
}
}
.item {
position: relative;
flex: 1;
padding-left: vw(100);
width: vw(230);
height: vh(70);
display: flex;
align-items: center;
background-size: 100% 100%;
.align-end {
margin-top: vh(10);
}
.color1 {
color: #12b5fd;
}
.color2 {
color: #02f9fa;
}
.color3 {
color: #f15a25;
}
}
.title-1 {
position: absolute;
top: vh(10);
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.7);
}
.countup-wrap {
font-size: vw(28);
font-weight: bold;
}
.unit {
color: #02f9fa;
font-size: vw(14);
margin-bottom: vh(4);
}
.core {
background-image: url('@/assets/images/m-t-1.png');
background-size: 100% 100%;
}
.queue {
background-image: url('@/assets/images/m-t-2.png');
background-size: 100% 100%;
}
.congestion {
background-image: url('@/assets/images/m-t-2.png');
background-size: 100% 100%;
}
.box {
width: vw(384);
// height: vh(360);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
.title-2 {
width: vw(253);
height: vh(28);
display: flex;
align-items: center;
background-image: url('@/assets/images/title-5.png');
background-size: 100% 100%;
& > span {
padding-left: vw(22);
font-weight: bold;
font-size: vw(15);
background-image: linear-gradient(to bottom, #ffffff 0%, #75c1ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
.statistic {
display: flex;
margin-top: vh(12);
width: 100%;
height: vh(88);
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;
}
&-title {
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
&-value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.count {
font-weight: bold;
font-size: vw(28);
color: #ff4400 !important;
}
.prefix,
.suffix {
color: #ff4400;
font-size: vw(12);
}
}
.title-3 {
position: relative;
width: vw(344);
height: vh(12);
margin-top: vh(20);
background-image: url('@/assets/images/title-6.png');
background-size: 100% 100%;
& > span {
position: absolute;
bottom: vh(4);
left: vw(20);
font-size: vw(15);
font-weight: bold;
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
}
display: flex;
}
</style>

View File

@@ -1,28 +0,0 @@
<template>
<!-- 视频 -->
<div class="box-3-content">
<navLeft></navLeft>
<!-- 视频 -->
<monitor></monitor>
</div>
</template>
<script setup>
import { fitChartSize } from '@/utils/dataUtil'
import navLeft from '@/components/navLeft/index.vue'
import monitor from '@/components/monitor/index.vue'
</script>
<style lang="scss" scoped>
.box-3-content{
width:vw(2356);
height:vh(965);
margin-top: vh(120);
display: flex;
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<box1 />
<box2 />
<box3 />
</template>
<script setup>
import box3 from './components/box-3.vue'
import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
onMounted(() => {})

View File

@@ -6,14 +6,31 @@
import { fitChartSize } from '@/utils/dataUtil'
import { useEchart } from '@/hooks/echart'
const { id, setOption } = useEchart()
let params = null
onMounted(() => {
init()
let props = defineProps({
list: {
type: Array,
default: () => []
}
})
const { id, setOption } = useEchart()
let params = null
watch(
() => props.list,
(val) => {
if (val.length > 0) {
setTimeout(() => {
init()
}, 1000)
}
},
{ immediate: true }
)
const getSeriesData = () => {
return props.list
}
const init = () => {
if (!params) {
const center = ['50%', '40%']
@@ -58,13 +75,7 @@
color: '#D3F0FE',
fontSize: fitChartSize(12)
},
data: [
{ value: 484, name: '19岁以下' },
{ value: 300, name: '18-30岁' },
{ value: 1048, name: '30-40岁' },
{ value: 580, name: '40-60岁' },
{ value: 735, name: '60岁以上' }
]
data: getSeriesData()
},
{
type: 'pie',
@@ -81,13 +92,7 @@
color: '#D3F0FE',
fontSize: fitChartSize(12)
},
data: [
{ value: 484, name: '19岁以下' },
{ value: 300, name: '18-30岁' },
{ value: 1048, name: '30-40岁' },
{ value: 580, name: '40-60岁' },
{ value: 735, name: '60岁以上' }
]
data: getSeriesData()
},
{
type: 'pie',
@@ -118,7 +123,10 @@
]
}
} else {
params.series[0].data = getSeriesData()
params.series[1].data = getSeriesData()
}
console.log(params, 'params')
setOption(params)
}
</script>

View File

@@ -3,17 +3,13 @@
<div class="header">
<div class="header__left">
<img src="@/assets/images/ticket.png" />
<div class="header__left-item">
<div class="label">当日购票量</div>
<countup :endVal="1234" />
</div>
<div class="header__left-item">
<div class="label">未来3天购票量</div>
<countup :endVal="1234" />
</div>
<div class="header__left-item">
<div class="label">3天后购票量</div>
<countup :endVal="1234" />
<div
class="header__left-item"
v-for="(item, index) in scenicStore.scenicSpotData"
:key="index"
>
<div class="label">{{ item.name }}</div>
<countup :end-val="item.value" />
</div>
</div>
<div>
@@ -101,6 +97,9 @@
<script setup>
import countup from 'vue-countup-v3'
import { useScenicStore } from '@/stores/scenic'
const scenicStore = useScenicStore()
</script>
<style scoped lang="scss">

View File

@@ -4,16 +4,37 @@
<div class="box mr-8">
<Title1 title="排队信息" />
<div class="count-box flex justify-between">
<count-item label="今日出票" :count="35600" suffix="张" />
<count-item label="今日接待人数" :count="35600" suffix="人" />
<count-item label="排队人数" :count="35600" suffix="人" />
<count-item label="排队持续时间" :count="35600" suffix="S" />
<count-item
label="今日出票"
:count="scenicStore.scenicQueueData.header.jrcp"
suffix="张"
/>
<count-item
label="今日接待人数"
:count="scenicStore.scenicQueueData.header.jrjdrs"
suffix="人"
/>
<count-item
label="排队人数"
:count="scenicStore.scenicQueueData.header.pdrs"
suffix="人"
/>
<count-item
label="排队持续时间"
:count="scenicStore.scenicQueueData.header.pdcxsj"
suffix="分钟"
/>
</div>
<div class="border">
<div class="pt-10">
<Title3 title="景区排队人数" />
</div>
<Line :width="520" :height="300" />
<Line
:width="490"
:height="300"
:data="scenicQueueData"
:xAxisData="scenicQueueXAxisData"
/>
</div>
</div>
<div class="box mr-8">
@@ -21,15 +42,28 @@
<div class="flex">
<circle-progress :width="200" :height="70" />
<div class="flex flex-1 justify-between">
<count-item label="景区当前人数" :count="35600" suffix="张" />
<count-item label="景区最大承载" :count="35600" suffix="人" />
<count-item
label="景区当前人数"
:count="scenicStore.scenicBearData.header.jrjdrs"
suffix="人"
/>
<count-item
label="景区最大承载"
:count="scenicStore.scenicBearData.header.jqzdcz"
suffix="人"
/>
</div>
</div>
<div class="border">
<div class="pt-10">
<Title3 title="景区排队人数" />
<Title3 title="今日景区承载量" />
</div>
<Line :width="520" :height="300" />
<Line
:width="490"
:height="300"
:data="scenicBearData"
:xAxisData="scenicBearXAxisData"
/>
</div>
</div>
<div class="box-1 mr-8">
@@ -41,8 +75,8 @@
<circle-progress :width="140" :height="70" />
</div>
<div class="ml-20 flex flex-1 justify-between">
<count-item label="总停车场数" :count="561" suffix="个" />
<count-item label="总停车位数" :count="15" suffix="个" />
<count-item label="总车位数" :count="561" suffix="个" />
<count-item label="剩余车位数" :count="15" suffix="个" />
</div>
</div>
<div class="flex">
@@ -50,13 +84,19 @@
<div class="pt-10">
<Title3 title="今日景区承载量" />
</div>
<Line :width="360" :height="300" />
<Line :width="360" :height="300" :data="carBearData" :xAxisData="carBearXAxisData" />
</div>
<div class="border flex-1">
<div class="pt-10">
<Title3 title="车辆归属地占比" />
</div>
<PieRow :width="360" :height="300" />
<PieRow
label="停车总数"
:dataList="scenicStore.stopCarData.dataLists"
:total="carTotal"
:width="360"
:height="300"
/>
</div>
</div>
</div>
@@ -69,9 +109,15 @@
</div>
<div class="border flex-1">
<div class="pt-10">
<Title3 title="今日景区承载量" />
<Title3 title="异常告警占比" />
</div>
<PieRow :width="350" :height="300" />
<PieRow
label="安全告警占比"
:dataList="scenicStore.secureData.dataList"
:total="alarmTotal"
:width="350"
:height="300"
/>
</div>
</div>
</div>
@@ -79,39 +125,42 @@
<div class="box-3 mr-8">
<Title1 title="交通信息" />
<div class="count-box flex">
<count-item label="总通景路段" :count="35600" suffix="张" />
<count-item label="通景路段拥堵数" :count="35600" suffix="人" />
<count-item label="拥堵开始时间" :count="35600" suffix="人" />
<count-item label="拥堵持续时间" :count="35600" suffix="S" />
<count-item
v-for="(item, index) in scenicStore.trafficData.infoList"
:key="index"
:label="item.name"
:count="item.value"
suffix="张"
/>
</div>
<div class="flex">
<div class="border mr-8">
<Title3 title="今日交通负载" />
<traffic-flow />
<traffic-flow :list="scenicStore.trafficData.data.congestion" />
</div>
<div class="border mr-8">
<Title3 title="拥堵次数占比" />
<jam :width="220" :height="160" />
<div class="legend">
<!-- <div class="legend">
<ul class="legend__wrapper">
<li class="legend-item" v-for="(item, index) in 6" :key="index">
<p class="legend-item-label">路段1</p>
<p class="legend-item-value">10%</p>
</li>
</ul>
</div>
</div> -->
</div>
<div class="border">
<Title3 title="拥堵次数占比" />
<Title3 title="拥堵时长占比" />
<jam :width="220" :height="160" />
<div class="legend">
<!-- <div class="legend">
<ul class="legend__wrapper">
<li class="legend-item" v-for="(item, index) in 6" :key="index">
<p class="legend-item-label">路段1</p>
<p class="legend-item-value">10%</p>
</li>
</ul>
</div>
</div> -->
</div>
</div>
</div>
@@ -121,34 +170,29 @@
<div class="flex">
<div class="border mr-8 flex-1">
<Title3 title="年龄/性别占比" />
<age-ratio />
<div class="count">总人数<countup endVal="124563" /></div>
<div class="cell pt-20">
<img class="icon" src="@/assets/images/man.png" />
<age :list="scenicStore.userPortraitData.data.ageRate" />
<div class="count">总人数<countup :end-val="ageTotal" /></div>
<div
class="cell pt-20"
v-for="(item, index) in scenicStore.userPortraitData.data.genderRate"
:key="index"
>
<img v-if="item.name == '男'" class="icon" src="@/assets/images/man.png" />
<img v-if="item.name == '女'" class="icon" src="@/assets/images/woman.png" />
<div class="bg">
<span class="text">男性</span>
<span class="text">{{ item.name }}</span>
<div class="progress">
<el-progress
:percentage="50"
:percentage="item.value"
:show-text="false"
color="linear-gradient( to right, #074D90 0%, #55E0FF 100%)"
:color="
item.name == '女'
? 'linear-gradient( to right, #0A4482 0%, #FF7021 100%)'
: 'linear-gradient( to right, #074D90 0%, #55E0FF 100%)'
"
/>
</div>
<span class="man">50%</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="50"
:show-text="false"
color="linear-gradient( to right, #0A4482 0%, #FF7021 100%)"
/>
</div>
<span class="woman">50%</span>
<span :class="[item.name == '男' ? 'man' : 'woman']">{{ item.value }}%</span>
</div>
</div>
</div>
@@ -168,7 +212,7 @@
<Title1 title="车船信息" />
<div class="flex mb-6">
<div class="border mr-8 pt-10 pb-10">
<Title2 title="车车车车车车" />
<Title2 title="景区车辆" />
<div class="car-box mt-10">
<img class="icon" src="@/assets/images/icon-6.png" />
<div class="car-item pr-20">
@@ -193,11 +237,11 @@
</div>
</div>
<div class="border pt-10 pb-10">
<Title2 title="船船船船船船" />
<Title2 title="景区船只" />
<div class="car-box mt-10">
<img class="icon" src="@/assets/images/icon-6.png" />
<div class="car-item pr-20">
<div class="label">总数</div>
<div class="label">总数</div>
<div class="value">130</div>
</div>
<div class="car-item">
@@ -229,17 +273,61 @@
</template>
<script setup>
import { useMap } from '@/hooks/map'
import carIcon from '@/assets/images/car.png'
import shipIcon from '@/assets/images/ship.png'
import BigCarShipMap from './big-car-ship-map.vue'
import AgeRatio from './age-ratio.vue'
import top from './top.vue'
import jam from './jam.vue'
import ticket from './ticket.vue'
import TrafficFlow from './traffic-flow.vue'
import age from './age'
import top from './top'
import jam from './jam'
import ticket from './ticket'
import TrafficFlow from './traffic-flow'
import BigCarShipMap from './big-car-ship-map'
import countup from 'vue-countup-v3'
import { useMap } from '@/hooks/map'
import { useScenicStore } from '@/stores/scenic'
const scenicStore = useScenicStore()
const { initMap, addMarker } = useMap()
const ageTotal = computed(() => {
return scenicStore.userPortraitData.data.genderRate.reduce((pre, cur) => {
return pre + parseInt(cur.count)
}, 0)
})
const alarmTotal = computed(() => {
return scenicStore.secureData.dataList.reduce((pre, cur) => {
return pre + cur.count
}, 0)
})
const carTotal = computed(() => {
return scenicStore.stopCarData.dataLists.reduce((pre, cur) => {
return pre + cur.count
}, 0)
})
const carBearData = computed(() => {
return [{ data: scenicStore.stopCarData.dataList.map((item) => item.value) }]
})
const carBearXAxisData = computed(() => {
return scenicStore.stopCarData.dataList.map((item) => item.name)
})
const scenicBearData = computed(() => {
return [{ data: scenicStore.scenicBearData.dataList.map((item) => item.value) }]
})
const scenicBearXAxisData = computed(() => {
return scenicStore.scenicBearData.dataList.map((item) => item.name)
})
const scenicQueueData = computed(() => {
return [{ data: scenicStore.scenicQueueData.dataList.map((item) => item.value) }]
})
const scenicQueueXAxisData = computed(() => {
return scenicStore.scenicQueueData.dataList.map((item) => item.name)
})
let show = ref(false)
onMounted(() => {
initMap('car-ship', 109.491961, 31.024285, 13)
@@ -341,7 +429,7 @@
color: #ffffff;
}
.progress {
width: vw(100);
width: vw(70);
}
.value {
margin-left: vw(10);
@@ -469,7 +557,7 @@
color: rgba(255, 255, 255, 0.9);
}
.progress {
width: vw(120);
width: vw(110);
margin-left: vw(4);
}
.man {

View File

@@ -8,76 +8,109 @@
const { id, setOption } = useEchart()
let option = {
grid: {
left: '4%',
right: '4%',
top: '10%',
bottom: '10%',
containLabel: true
},
xAxis: {
boundaryGap: true,
type: 'category',
data: ['10:00', '10:05', '10:10', '10:15', '10:20'],
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: 'rgba(5, 72, 134, 1)'
}
},
axisLabel: {
fontSize: fitChartSize(12),
color: 'rgba(255,255,255,0.9)'
let props = defineProps({
list: {
type: Array,
default: () => []
}
})
watch(
() => props.list,
(val) => {
if (val.length) {
setTimeout(() => {
init()
}, 1000)
}
},
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: [45, 53, 23, 45, 12],
type: 'bar',
showBackground: true,
barWidth: fitChartSize(16),
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 1,
colorStops: [
{
offset: 0,
color: 'rgba(0, 99, 255, 1)'
},
{
offset: 1,
color: 'rgba(2, 249, 250, 1)'
}
]
}
},
backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)'
}
}
]
{
immediate: true
}
)
let params = null
const getXAxisData = () => {
return props.list.map((item) => item.name)
}
const getSeriesData = () => {
return props.list.map((item) => item.value)
}
const init = () => {
setOption(option)
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: [
{
type: 'bar',
showBackground: true,
barWidth: fitChartSize(16),
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 1,
colorStops: [
{
offset: 0,
color: 'rgba(0, 99, 255, 1)'
},
{
offset: 1,
color: 'rgba(2, 249, 250, 1)'
}
]
}
},
backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)'
},
data: getSeriesData()
}
]
}
} else {
params.xAxis.data = getXAxisData()
params.series[0].data = getSeriesData()
}
setOption(params)
}
onMounted(() => {

View File

@@ -6,6 +6,51 @@
<script setup>
import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
import { useWebSocket } from '@/hooks/socket'
import { useScenicStore } from '@/stores/scenic'
const scenicStore = useScenicStore()
const { isConnected, sendMessage, dataRes } = useWebSocket('ws://36.138.38.16:81/ws/scenic-spot')
watch(
() => isConnected.value,
(val) => {
if (val) {
sendMessage(JSON.stringify({ action: 'start', type: '', scenicSpotId: '1' }))
}
}
)
watch(
() => dataRes.value,
(val) => {
if (val) {
console.log(val, '接受消息')
switch (val.type) {
case 'scenicSpotData':
scenicStore.setScenicSpotData(val.data)
break
case 'scenicSppotLineUp':
scenicStore.setScenicQueueData(val)
break
case 'scenicSppotLoad':
scenicStore.setScenicBearData(val)
break
case 'stopCarData':
scenicStore.setStopCarData(val)
break
case 'secureData':
scenicStore.setSecureData(val)
break
case 'trafficInformation':
scenicStore.setTrafficData(val)
break
case 'userPortrait':
scenicStore.setUserPortraitData(val)
break
}
}
}
)
</script>
<style scoped lang="scss"></style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="select-box">
<Select v-model="params.id" :options="options" @on-change="initChart" />
<Select v-model="params.id" label="选择景区" :options="options" @on-change="initChart" />
</div>
<div class="area" :id="id" />
</template>

View File

@@ -44,7 +44,12 @@
<div class="box-2 mr-8 rela">
<Title1 title="舆情指数" />
<div class="select-box">
<Select v-model="params.id" :options="options" @on-change="getLineChart" />
<Select
v-model="params.id"
label="选择景区"
:options="options"
@on-change="getLineChart"
/>
</div>
<Line
:width="1560"

View File

@@ -0,0 +1,86 @@
<template>
<div class="alarm">
<p class="alarm-title">异常点位告警排名</p>
<ul class="alarm-list">
<li class="alarm-item" v-for="(item, index) in 10" :key="index">
<div class="alarm-item__rank">{{ index + 1 }}</div>
<p class="alarm-item__label">核心监控点1</p>
</li>
</ul>
</div>
</template>
<script setup></script>
<style scoped lang="scss">
.alarm {
&-title {
padding-bottom: vh(10);
font-weight: bold;
font-size: vw(14);
color: #37d8fc;
}
&-list {
width: vw(140);
height: vh(160);
overflow-y: auto;
&::-webkit-scrollbar {
width: vw(4); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: 'transparent'; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(0, 150, 255, 0.63); /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
}
&-item {
margin-bottom: vh(10);
display: flex;
align-items: center;
background: linear-gradient(90deg, #1b5ec7 0%, rgba(27, 94, 199, 0) 100%);
&:nth-child(1) {
background: linear-gradient(90deg, #ffc10b 0%, rgba(255, 209, 44, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-1.png');
background-size: 100% 100%;
}
}
&:nth-child(2) {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-2.png');
background-size: 100% 100%;
}
}
&:nth-child(3) {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.alarm-item__rank {
background-image: url('@/assets/images/rk-3.png');
background-size: 100% 100%;
}
}
}
&-item__rank {
width: vw(24);
height: vw(24);
font-weight: bold;
font-size: vw(14);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/rk-4.png');
background-size: 100% 100%;
}
&-item__label {
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<div class="alarmRate" :id="id" />
</template>
<script setup>
import { fitChartSize } from '@/utils/dataUtil'
import { useEchart } from '@/hooks/echart'
const props = defineProps({
config: {
type: Object,
default: () => {
return {}
}
},
dataList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: () => 123456
},
colors: {
type: Array,
default: () => ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
}
})
const { id, setOption } = useEchart()
var defaultCofig = {
color: [],
legend: {
orient: 'vertical',
bottom: 'center',
left: '50%',
itemWidth: fitChartSize(12),
itemHeight: fitChartSize(12),
itemGap: fitChartSize(10),
textStyle: {
color: '#ffffff',
fontSize: fitChartSize(16)
}
},
series: [
{
type: 'pie',
center: ['30%', '50%'],
radius: ['30%', '40%'],
itemStyle: {
borderWidth: fitChartSize(4),
borderColor: '#093672'
},
label: {
show: true,
position: 'center',
fontWeight: 'bold',
rich: {
value: {
color: '#fff',
fontSize: fitChartSize(16),
fontWeight: 'bold',
padding: [0, 0, 5, 0]
},
name: {
color: '#7894A8',
fontSize: fitChartSize(12)
}
}
},
labelLine: {
show: false
},
data: []
}
]
}
watch(
() => props.dataList,
(newVal) => {
if (newVal.length > 0) {
nextTick(() => {
defaultCofig.color = props.colors
defaultCofig.series[0].data = props.dataList
defaultCofig.series[0].label.formatter = () => {
return `{value|${props.total}}` + '\n' + `{name|工单总数}`
}
setOption({
...defaultCofig,
...props.config
})
})
}
},
{ immediate: true }
)
</script>
<style scoped lang="scss">
.alarmRate {
width: vw(240);
height: vh(200);
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<div class="alarmToday" :id="id" />
</template>
<script setup>
import { fitChartSize } from '@/utils/dataUtil'
import { useEchart } from '@/hooks/echart'
const props = defineProps({
config: {
type: Object,
default: () => {
return {}
}
},
dataList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: () => 123456
},
colors: {
type: Array,
default: () => ['#FDC40A', '#FF5232', '#50F0A6', '#5FDFFA']
}
})
const { id, setOption } = useEchart()
const color = ['#409eff', '#29c9c8', '#f6b936']
var params = {
color: ['#70bfe5', '#eb6a6c', '#f9c942', '#91c974', '#5a6ac0'],
// legend: {
// data: ['1月', '2月', '3月', '4月', '5月'],
// itemGap: 15,
// itemWidth: 10, // 设置宽度
// itemHeight: 10,
// top: '40',
// right: '30',
// textStyle: {
// color: '#595959'
// }
// },
grid: {
left: '4%',
right: '4%',
bottom: '5%',
top: '12%',
containLabel: true
},
xAxis: [
{
name: '月份',
type: 'category',
axisTick: {
alignWithLabel: false
},
axisLabel: {
padding: [25, 0, 0, 0]
},
data: ['1月', '2月', '3月', '4月', '5月']
}
],
yAxis: [
{
type: 'value',
axisLabel: {
formatter: function (params) {
return params
}
}
}
],
series: []
}
var datas = [
[
[10, 1, 1, 2, 3],
[2, 11, 7, 1, 1],
[5, 7, 5, 1, 1]
],
[
[1, 1, 1, 2, 3],
[2, 5, 7, 1, 1],
[5, 7, 5, 1, 1]
],
[
[1, 1, 1, 2, 3],
[2, 5, 7, 1, 1],
[5, 7, 5, 1, 1]
]
]
// 变量和循环处理
var categories = ['1月', '2月', '3月']
var years = ['应完成xxx']
for (var i = 0; i < years.length; i++) {
var yearData = datas[i] // 获取对应年份的数据
var seriesData = [] // 用于存储每个年份对应的系列数据
for (var j = 0; j < categories.length; j++) {
var itemData = []
for (var k = 0; k < yearData[j].length; k++) {
itemData.push(yearData[j][k])
}
seriesData.push({
type: 'bar',
stack: 'stack' + (i + 1),
barGap: 0.5,
barWidth: 20,
label: {
show: true,
// position: 'insideTop',
align: 'center',
formatter: function (param) {
return param.value
}
},
data: itemData,
name: categories[j]
})
}
Array.prototype.push.apply(params.series, seriesData)
}
const init = () => {
setOption(params)
}
// watch(
// () => props.dataList,
// (newVal) => {
// if (newVal.length > 0) {
// nextTick(() => {
// defaultCofig.color = props.colors
// defaultCofig.series[0].data = props.dataList
// defaultCofig.series[0].label.formatter = () => {
// return `{value|${props.total}}` + '\n' + `{name|工单总数}`
// }
// setOption({
// ...defaultCofig,
// ...props.config
// })
// })
// }
// },
// { immediate: true }
// )
onMounted(() => {
init()
})
</script>
<style scoped lang="scss">
.alarmToday {
width: vw(400);
height: vh(200);
}
</style>

View File

@@ -0,0 +1,193 @@
<template>
<!-- 安全检测 -->
<div class="box-1">
<div class="detection-top">
<img class="map-img" src="@/assets/images/map-img-1.jpg" />
</div>
<div class="flex">
<div class="monitor">
<div class="t-title">
<span>监控点位统计</span>
</div>
<div class="monitor-statistics">
<img class="monitor-statistics-icon" src="@/assets/images/t-ico-0.png" />
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">监控点位</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">核心点位</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">拥堵次数</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
</div>
<div class="bg">
<Title3 title="今日安全告警" />
<alarmToday />
</div>
</div>
<div class="traffic">
<div class="t-title">
<span>交通信息</span>
</div>
<div class="traffic-statistics">
<img class="traffic-statistics-icon" src="@/assets/images/t-ico-2.png" />
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">当前告警总数</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">安全告警总数</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">已解除告警数</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
</div>
<div class="bg">
<Title3 title="异常告警占比" />
<div class="flex">
<alarmRate :dataList="dataList" />
<alarmList />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import countup from 'vue-countup-v3'
import alarmRate from './alarmRate'
import alarmList from './alarmList'
import alarmToday from './alarmToday'
const dataList = ref([
{
name: '云阳',
value: 20
},
{
name: '奉节',
value: 10
},
{
name: '巫山',
value: 70
}
])
onMounted(() => {})
</script>
<style lang="scss" scoped>
.box-1 {
margin-top: vh(120);
width: vw(820);
height: vh(950);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 91%, rgba(5, 40, 79, 0) 100%);
border-radius: 0px 0px 0px 0px;
.detection-top {
width: 100%;
height: vh(580);
background-color: #fff;
.map-img {
width: 100%;
height: 100%;
}
}
.monitor {
width: vw(405);
margin-right: vw(8);
&-statistics {
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
}
&-statistics-icon {
width: vw(45);
height: vw(48);
}
&-statistics-item {
&__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
&__value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #ffffff;
}
&:nth-child(4) {
.monitor-statistics-item__value {
color: #e21b1b;
}
}
}
}
.traffic {
width: vw(405);
&-statistics {
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
}
&-statistics-icon {
width: vw(45);
height: vw(48);
}
&-statistics-item {
&__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
&__value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #e21b1b;
text-align: center;
}
&:nth-child(4) {
.traffic-statistics-item__value {
color: rgba(167, 0, 0, 0.6);
}
}
}
}
.bg {
padding: vw(5);
margin-top: vh(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
}
.t-title {
margin: vh(10) auto;
width: 100%;
height: vh(32);
font-weight: 800;
font-size: vw(16);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/title-4.png');
background-size: 100% 100%;
}
}
</style>

View File

@@ -1,628 +1,19 @@
<template>
<!-- 安全检测 -->
<div class="box-detection">
<!-- 地图 -->
<div class="detection-top">
<Map />
</div>
<div class="detection-bom flex">
<!-- 数据 -->
<div class="d-left">
<div class="t-title">
<span>监控点位统计</span>
</div>
<div class="t-census flex">
<img class="t-icon" src="@/assets/images/t-ico-0.png" alt="" />
<div class="item">
监控点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
核心点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
拥堵次数 <div class="color2"><countup endVal="895" /></div>
</div>
</div>
<div class="box">
<div class="title-3"><span>异常告警占比</span></div>
<div class="pt-20 h-flex">
<div class="left">
<v-chart class="chart" :option="option1" autoresize />
</div>
<!-- <div class="right">
<div class="li li-1"><span class="rk-img" >1</span> 核心监控1</div>
<div class="li li-2"><span class="rk-img" >1</span>核心监控1</div>
<div class="li li-3"><span class="rk-img" >1</span>核心监控1</div>
<div class="li"><span class="rk-img" >1</span>核心监控1</div>
<div class="li"><span class="rk-img" >1</span>核心监控1</div>
<div class="li"><span class="rk-img" >1</span>核心监控</div>
</div> -->
</div>
</div>
</div>
<div class="d-right">
<div class="t-title">
<span>交通信息</span>
</div>
<div class="t-census flex">
<img class="t-icon" src="@/assets/images/t-ico-1.png" alt="" />
<div class="item">
监控点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
核心点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
拥堵次数 <div class="color1"><countup endVal="895" /></div>
</div>
</div>
<div class="box">
<div class="title-3"><span>异常告警占比</span></div>
<div class="pt-20 chart-p">
<div class="check-label">
<span class="active">平均</span>
<span>最大</span>
<span>最小</span>
</div>
<!-- <div class="check-box">
<el-select v-model="selectSpot" slot="prepend" placeholder="选择景区">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
</div> -->
<v-chart class="line-chart" :option="optionLine" autoresize />
</div>
</div>
</div>
</div>
<div class="box-2">
<Nav />
<Monitor />
</div>
</template>
<script setup>
import * as echarts from 'echarts'
import countup from 'vue-countup-v3'
import { fitChartSize } from '@/utils/dataUtil'
import Map from '@/components/Map/marker.vue'
import VChart, { THEME_KEY } from 'vue-echarts'
import { ref, provide } from 'vue'
provide(THEME_KEY, 'dark')
const option1 = ref({
backgroundColor: 'transparent',
tooltip: {
trigger: 'item'
},
legend: {
type: 'scroll',
orient: 'vertical',
right: 10,
top: 20,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
textStyle: {
fontSize: fitChartSize(14)
}
},
series: [
{
name: 'Access From',
type: 'pie',
left: -30,
top: -50,
width: fitChartSize(350),
height: fitChartSize(350),
// width:200,
// height:200,
radius: ['40%', '50%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: fitChartSize(10),
fontWeight: 'bold',
color: '#fff'
}
},
labelLine: {
show: true
},
data: [
{ value: 200, name: '异常状况1' },
{ value: 500, name: '异常状况2' },
{ value: 234, name: '异常状况3' },
{ value: 135, name: '异常状况4' },
{ value: 100, name: '异常状况5' },
{ value: 777, name: '异常状况6' },
{ value: 777, name: '其他' }
]
}
]
})
const optionLine = ref({
backgroundColor: 'transparent',
grid: {
top: '50',
bottom: '50',
left: '4%',
containLabel: true
},
xAxis: {
nameLocation: 'middle',
type: 'category',
boundaryGap: false,
axisLabel: {
fontSize: 10,
interval: 0, // 显示所有标签
rotate: 0 // 旋转标签45度
},
data: ['10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00'],
axisTisk: {
show: true,
// 设置刻度长度
length: 1,
lineStyle: {
type: 'dashed', // 设置为虚线
width: 0
}
},
axisLine: {
lineStyle: {
color: '#0096FF' // 设置横线颜色
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 45,
interval: 15,
axisLabel: {
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
color: 'rgba(255,255,255,0.9)'
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#00D0FF'
}
}
},
series: [
{
data: [0, 23, 30, 24, 40, 30, 45, 26],
type: 'line',
smooth: true,
label: {
show: false //隐藏坐标点
},
itemStyle: {
color: 'transparent'
},
markLine: {
symbol: ['none', 'none'],
label: { show: false }
},
lineStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: '#7DE7FF'
},
{
offset: 0.5,
color: '#02F9FA'
},
{
offset: 1,
color: '#009DFF'
}
]),
width: 3
}
}
]
})
const optionBar = ref({
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
// type: 'scroll',
// orient: 'vertical',
right: 0,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5
},
grid: {
left: '3%',
right: '4%',
bottom: '20%',
containLabel: true,
show: false
},
xAxis: [
{
nameLocation: 'middle',
type: 'category',
boundaryGap: true,
axisLabel: {
fontSize: fitChartSize(10),
interval: 0, // 显示所有标签
rotate: 0 // 旋转标签45度
},
minorTisk: {
show: false
},
data: ['10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00'],
axisTisk: {
alignWithLabel: true,
show: false,
// 设置刻度长度
length: 0,
lineStyle: {
type: 'dashed', // 设置为虚线
width: 0
}
}
}
],
yAxis: [
{
type: 'value',
min: 0,
max: 45,
interval: 15,
axisLabel: {
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
color: 'rgba(255,255,255,0.9)',
offset: 10
},
splitLine: {
show: false,
lineStyle: {
type: 'dashed',
color: '#00D0FF'
}
}
}
],
series: [
{
itemStyle: {
// 设置柱状图颜色
color: '#0D53FF'
},
name: '三峡之巅',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: [10, 0, 16, 10, 22, 11, 9, 30],
barWidth: '45%' // 设置柱体粗细,可以是百分比或者像素值
},
{
name: '白帝城',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
itemStyle: {
// 设置柱状图颜色
color: '#05FFB9'
},
data: [20, 5, 14, 14, 0, 20, 11, 2]
},
{
name: '龙河桥',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
itemStyle: {
// 设置柱状图颜色
color: '#FFCB39'
},
data: [15, 20, 8, 19, 20, 5, 22, 13]
}
]
})
onMounted(() => {})
import Nav from '@/components/Nav/index.vue'
import Monitor from '@/components/Monitor/index.vue'
</script>
<style lang="scss" scoped>
.line-chart {
width: 100%;
height: vh(240);
}
.chart-p {
position: relative;
.check-label {
position: absolute;
right: vw(20);
top: vh(15);
span {
min-width: vw(55);
padding: vw(5);
background: linear-gradient(270deg, rgba(8, 41, 86, 0.16) 0%, #0b61b4 100%);
border-radius: vw(50);
// border: 1px solid rgba(0,114,220,0.3);
margin-left: vw(5);
display: inline-block;
font-weight: 400;
font-size: vw(13);
color: #0084ff;
text-align: center;
font-style: normal;
text-transform: none;
}
.active {
background: linear-gradient(270deg, #37d8fc 0%, #0084ff 100%);
border-radius: vw(50);
border: 1px solid rgba(0, 114, 220, 0.3);
color: #fff;
}
}
}
.box-detection {
.box-2 {
margin-top: vh(120);
width: vw(820);
height: vh(950);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 91%, rgba(5, 40, 79, 0) 100%);
border-radius: 0px 0px 0px 0px;
.detection-top {
width: 100%;
height: vh(580);
background-color: #fff;
.map-img {
width: 100%;
height: 100%;
}
}
.detection-bom {
justify-content: space-between;
.d-left {
width: vw(405);
.left {
width: 100%;
height: vh(240);
}
}
.d-right {
width: vw(405);
}
.box {
width: 100%;
padding: vw(5);
margin-top: vh(5);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
.title-2 {
width: vw(253);
height: vh(28);
display: flex;
align-items: center;
background-image: url('@/assets/images/title-5.png');
background-size: 100% 100%;
& > span {
padding-left: vw(22);
font-weight: bold;
font-size: vw(15);
background-image: linear-gradient(to bottom, #ffffff 0%, #75c1ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
.statistic {
display: flex;
margin-top: vh(12);
width: 100%;
height: vh(88);
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;
}
&-title {
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
&-value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.count {
font-weight: bold;
font-size: vw(28);
color: #ff4400 !important;
}
.prefix,
.suffix {
color: #ff4400;
font-size: vw(12);
}
}
.title-3 {
position: relative;
width: vw(344);
height: vh(12);
margin-top: vh(20);
background-image: url('@/assets/images/title-6.png');
background-size: 100% 100%;
& > span {
position: absolute;
bottom: vh(4);
left: vw(20);
font-size: vw(15);
font-weight: bold;
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
}
.t-title {
margin: vh(10) auto;
width: 100%;
height: vh(32);
font-weight: 800;
font-size: vw(16);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/title-4.png');
background-size: 100% 100%;
}
.t-census {
justify-content: center;
align-items: center;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
padding: vw(10);
.t-icon {
width: vw(45);
height: vh(48);
}
.item {
flex: 1;
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
line-height: vh(16);
text-align: center;
font-style: normal;
text-transform: none;
.color1 {
display: block;
font-weight: bold;
font-size: vw(24);
color: #ffffff;
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
}
.color2 {
display: block;
font-weight: bold;
font-size: vw(24);
color: #f15a25;
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
}
.color3 {
display: block;
font-weight: bold;
font-size: vw(24);
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
color: #a70000;
}
}
}
}
}
.h-flex {
width: vw(2353);
height: vh(964);
display: flex;
justify-content: space-between;
.left {
flex: 1;
width: vw(260);
}
.right {
margin-left: vw(20);
width: vw(120);
.li {
position: relative;
font-weight: 400;
font-size: vw(14);
color: #ffffff;
line-height: 16px;
text-align: left;
font-style: normal;
text-transform: none;
position: relative;
padding-left: vw(30);
padding: 0 vw(10);
padding-left: vw(15);
background: linear-gradient(90deg, #1b5ec7 0%, rgba(27, 94, 199, 0) 100%);
border-radius: 0px 0px 0px 0px;
height: vh(24);
line-height: vh(24);
margin-bottom: vh(8);
// opacity: 0.4;
.rk-img {
position: absolute;
width: vw(24);
height: vh(24);
line-height: vh(24);
left: vw(-12);
top: 50%;
display: block;
background-image: url('/src/assets/images/rk-4.png');
background-size: 100% 100%;
transform: translateY(-50%);
text-align: center;
}
}
.li-1 {
background: linear-gradient(90deg, #ffc10b 0%, rgba(255, 209, 44, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-1.png');
}
}
.li-2 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-2.png');
}
}
.li-3 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-3.png');
}
}
}
}
</style>

View File

@@ -1,25 +1,210 @@
<template>
<!-- 视频 -->
<div class="box-3-content">
<navLeft></navLeft>
<!-- 视频 -->
<monitor></monitor>
</div>
<!-- 安全检测 -->
<div class="box-detection">
<!-- 地图 -->
<div class="detection-top">
<!-- <Map /> -->
</div>
<div class="detection-bom flex">
<!-- 数据 -->
<div class="monitor">
<div class="t-title">
<span>监控点位统计</span>
</div>
<div class="monitor-statistics">
<img class="monitor-statistics-icon" src="@/assets/images/t-ico-0.png" />
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">监控点位</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">核心点位</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
<div class="monitor-statistics-item">
<span class="monitor-statistics-item__label">拥堵次数</span>
<countup class="monitor-statistics-item__value" end-val="895" />
</div>
</div>
<div class="bg">
<Title3 title="核心点位拥堵次数" />
<alarmRate />
</div>
</div>
<div class="traffic">
<div class="t-title">
<span>交通信息</span>
</div>
<div class="traffic-statistics">
<img class="traffic-statistics-icon" src="@/assets/images/t-ico-2.png" />
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">当前拥堵节点</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">最大车流量</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
<div class="traffic-statistics-item">
<span class="traffic-statistics-item__label">最大车速</span>
<countup class="traffic-statistics-item__value" end-val="895" />
</div>
</div>
<div class="bg">
<Title3 title="车流量" />
<div class="pt-20 chart-p">
<div class="check-label">
<span class="active">平均</span>
<span>最大</span>
<span>最小</span>
</div>
<Line />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import navLeft from '@/components/navLeft/index.vue'
import monitor from '@/components/monitor/index.vue'
import alarmRate from './alarmRate.vue'
import countup from 'vue-countup-v3'
onMounted(() => {})
</script>
<style lang="scss" scoped>
.box-3-content{
width:vw(2353);
height:vh(964);
// background-image: url('/src/assets/images/monotir-bg-1.png');
background-size: 100% 100%;
margin-top: vh(120);
display: flex;
}
</style>
.chart-p {
position: relative;
.check-label {
position: absolute;
right: vw(20);
top: vh(15);
span {
min-width: vw(55);
padding: vw(5);
background: linear-gradient(270deg, rgba(8, 41, 86, 0.16) 0%, #0b61b4 100%);
border-radius: vw(50);
margin-left: vw(5);
display: inline-block;
font-weight: 400;
font-size: vw(13);
color: #0084ff;
text-align: center;
font-style: normal;
text-transform: none;
}
.active {
background: linear-gradient(270deg, #37d8fc 0%, #0084ff 100%);
border-radius: vw(50);
border: 1px solid rgba(0, 114, 220, 0.3);
color: #fff;
}
}
}
.box-detection {
margin-top: vh(120);
width: vw(820);
height: vh(950);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 91%, rgba(5, 40, 79, 0) 100%);
border-radius: 0px 0px 0px 0px;
.detection-top {
width: 100%;
height: vh(580);
background-color: #fff;
.map-img {
width: 100%;
height: 100%;
}
}
.monitor {
width: vw(405);
margin-right: vw(8);
&-statistics {
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
}
&-statistics-icon {
width: vw(45);
height: vw(48);
}
&-statistics-item {
&__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
&__value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #ffffff;
}
&:nth-child(4) {
.monitor-statistics-item__value {
color: #e21b1b;
}
}
}
}
.traffic {
width: vw(405);
&-statistics {
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
}
&-statistics-icon {
width: vw(45);
height: vw(48);
}
&-statistics-item {
&__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
&__value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #e21b1b;
text-align: center;
}
&:nth-child(4) {
.traffic-statistics-item__value {
color: rgba(167, 0, 0, 0.6);
}
}
}
}
.bg {
padding: vw(5);
margin-top: vh(8);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
}
.t-title {
margin: vh(10) auto;
width: 100%;
height: vh(32);
font-weight: 800;
font-size: vw(16);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/title-4.png');
background-size: 100% 100%;
}
}
</style>

View File

@@ -1,592 +0,0 @@
<template>
<!-- 安全检测 -->
<div class="box-detection">
<!-- 地图 -->
<div class="detection-top">
<img class="map-img" src="@/assets/images/map-img-1.jpg" alt="" />
<!-- <Map /> -->
</div>
<div class="detection-bom flex">
<!-- 数据 -->
<div class="d-left">
<div class="t-title">
<span>监控点位统计</span>
</div>
<div class="t-census flex">
<img class="t-icon" src="@/assets/images/t-ico-0.png" alt="" />
<div class="item">
监控点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
核心点位 <div class="color1"><countup endVal="895" /></div>
</div>
<div class="item">
拥堵次数 <div class="color2"><countup endVal="895" /></div>
</div>
</div>
<div class="box">
<div class="title-3"><span>异常告警占比</span></div>
<div class="pt-20 h-flex">
<div class="left">
<v-chart class="chart" :option="optionBar" autoresize />
<!-- <v-chart class="chart" :option="option1" autoresize /> -->
</div>
</div>
</div>
</div>
<div class="d-right">
<div class="t-title">
<span>交通信息</span>
</div>
<div class="t-census flex">
<img class="t-icon" src="@/assets/images/t-ico-2.png" alt="" />
<div class="item">
监控点位 <div class="color1 color2"><countup endVal="895" /></div>
</div>
<div class="item">
核心点位 <div class="color1 color2"><countup endVal="895" /></div>
</div>
<div class="item">
拥堵次数 <div class="color1 color3"><countup endVal="895" /></div>
</div>
</div>
<div class="box">
<div class="title-3"><span>异常告警占比</span></div>
<div class="pt-20 h-flex">
<div class="left">
<v-chart class="chart" :option="option1" autoresize />
</div>
<div class="right">
<div class="li li-1"><span class="rk-img">1</span> 核心监控1</div>
<div class="li li-2"><span class="rk-img">1</span>核心监控1</div>
<div class="li li-3"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控1</div>
<div class="li"><span class="rk-img">1</span>核心监控</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import * as echarts from 'echarts'
import countup from 'vue-countup-v3'
import { fitChartSize } from '@/utils/dataUtil'
import Map from '@/components/Map/marker.vue'
import VChart, { THEME_KEY } from 'vue-echarts'
import { ref, provide } from 'vue'
provide(THEME_KEY, 'dark')
const option1 = ref({
backgroundColor: 'transparent',
tooltip: {
trigger: 'item'
},
legend: {
type: 'scroll',
orient: 'vertical',
right: -10,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
textStyle: {
fontSize: fitChartSize(12)
}
},
series: [
{
name: 'Access From',
type: 'pie',
left: -25,
top: 0,
width: fitChartSize(250),
height: fitChartSize(250),
radius: ['40%', '50%'],
avoidLabelOverlap: false,
padAngle: 5,
itemStyle: {
borderRadius: 2
},
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: fitChartSize(10),
fontWeight: 'bold',
color: '#fff'
}
},
labelLine: {
show: true
},
data: [
{ value: 200, name: '异常状况1' },
{ value: 500, name: '异常状况2' },
{ value: 234, name: '异常状况3' },
{ value: 135, name: '异常状况4' },
{ value: 100, name: '异常状况5' },
{ value: 777, name: '异常状况6' },
{ value: 777, name: '其他' }
]
}
]
})
const optionLine = ref({
backgroundColor: 'transparent',
grid: {
top: '50',
bottom: '50',
left: '4%',
containLabel: true
},
xAxis: {
nameLocation: 'middle',
type: 'category',
boundaryGap: false,
axisLabel: {
fontSize: 10,
interval: 0, // 显示所有标签
rotate: 0 // 旋转标签45度
},
data: ['10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00'],
axisTisk: {
show: true,
// 设置刻度长度
length: 1,
lineStyle: {
type: 'dashed', // 设置为虚线
width: 0
}
},
axisLine: {
lineStyle: {
color: '#0096FF' // 设置横线颜色
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 45,
interval: 15,
axisLabel: {
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
color: 'rgba(255,255,255,0.9)'
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#00D0FF'
}
}
},
series: [
{
data: [0, 23, 30, 24, 40, 30, 45, 26],
type: 'line',
smooth: true,
label: {
show: false //隐藏坐标点
},
itemStyle: {
color: 'transparent'
},
markLine: {
symbol: ['none', 'none'],
label: { show: false }
},
lineStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: '#7DE7FF'
},
{
offset: 0.5,
color: '#02F9FA'
},
{
offset: 1,
color: '#009DFF'
}
]),
width: 3
}
}
]
})
const optionBar = ref({
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
// type: 'scroll',
// orient: 'vertical',
right: 0,
top: 0,
bottom: 20,
itemWidth: 5,
itemHeight: 5,
textStyle: {
fontSize: fitChartSize(12)
}
},
grid: {
left: '3%',
right: '4%',
bottom: '20%',
containLabel: true,
show: false
},
xAxis: [
{
nameLocation: 'middle',
type: 'category',
boundaryGap: true,
axisLabel: {
fontSize: fitChartSize(10),
interval: 0, // 显示所有标签
rotate: 0 // 旋转标签45度
},
minorTisk: {
show: false
},
data: ['10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00', '10:00'],
axisTisk: {
alignWithLabel: true,
show: false,
// 设置刻度长度
length: 0,
lineStyle: {
type: 'dashed', // 设置为虚线
width: 0
}
}
}
],
yAxis: [
{
type: 'value',
min: 0,
max: 45,
interval: 15,
axisLabel: {
fontSize: fitChartSize(12), // 设置Y轴刻度字体大小
color: 'rgba(255,255,255,0.9)',
offset: 10
},
splitLine: {
show: false,
lineStyle: {
type: 'dashed',
color: '#00D0FF'
}
}
}
],
series: [
{
itemStyle: {
// 设置柱状图颜色
color: '#0D53FF'
},
name: '三峡之巅',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: [10, 0, 16, 10, 22, 11, 9, 30],
barWidth: '45%' // 设置柱体粗细,可以是百分比或者像素值
},
{
name: '白帝城',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
itemStyle: {
// 设置柱状图颜色
color: '#05FFB9'
},
data: [20, 5, 14, 14, 0, 20, 11, 2]
},
{
name: '龙河桥',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
itemStyle: {
// 设置柱状图颜色
color: '#FFCB39'
},
data: [15, 20, 8, 19, 20, 5, 22, 13]
}
]
})
onMounted(() => {})
</script>
<style lang="scss" scoped>
.line-chart {
width: 100%;
height: vh(240);
}
.box-detection {
margin-top: vh(120);
width: vw(820);
height: vh(950);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 91%, rgba(5, 40, 79, 0) 100%);
border-radius: 0px 0px 0px 0px;
.detection-top {
width: 100%;
height: vh(580);
background-color: #fff;
.map-img {
width: 100%;
height: 100%;
}
}
.detection-bom {
justify-content: space-between;
.d-left {
width: vw(405);
.left {
width: 100%;
height: vh(240);
}
}
.d-right {
width: vw(405);
}
.box {
width: 100%;
padding: vw(5);
margin-top: vh(5);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
.title-2 {
width: vw(253);
height: vh(28);
display: flex;
align-items: center;
background-image: url('@/assets/images/title-5.png');
background-size: 100% 100%;
& > span {
padding-left: vw(22);
font-weight: bold;
font-size: vw(15);
background-image: linear-gradient(to bottom, #ffffff 0%, #75c1ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
.statistic {
display: flex;
margin-top: vh(12);
width: 100%;
height: vh(88);
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;
}
&-title {
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
&-value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
}
.count {
font-weight: bold;
font-size: vw(28);
color: #ff4400 !important;
}
.prefix,
.suffix {
color: #ff4400;
font-size: vw(12);
}
}
.title-3 {
position: relative;
width: vw(344);
height: vh(12);
margin-top: vh(20);
background-image: url('@/assets/images/title-6.png');
background-size: 100% 100%;
& > span {
position: absolute;
bottom: vh(4);
left: vw(20);
font-size: vw(15);
font-weight: bold;
background-image: linear-gradient(to bottom, #ffffff 0%, #0096ff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; /* 兼容WebKit内核浏览器 */
color: transparent; /* 兼容其他浏览器 */
}
}
}
.t-title {
margin: vh(10) auto;
width: 100%;
height: vh(32);
font-weight: 800;
font-size: vw(16);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background-image: url('@/assets/images/title-4.png');
background-size: 100% 100%;
}
.t-census {
justify-content: center;
align-items: center;
background-image: url('@/assets/images/i-data-bg-1.png');
background-size: 100% 100%;
padding: vw(10);
.t-icon {
width: vw(45);
height: vh(48);
}
.item {
flex: 1;
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
line-height: vh(16);
text-align: center;
font-style: normal;
text-transform: none;
.color1 {
display: block;
font-weight: bold;
font-size: vw(24);
color: #ffffff;
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
}
.color2 {
display: block;
font-weight: bold;
font-size: vw(24);
color: #f15a25;
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
}
.color3 {
display: block;
font-weight: bold;
font-size: vw(24);
line-height: 28px;
text-align: center;
font-style: normal;
text-transform: none;
color: #a70000;
}
}
}
}
}
.h-flex {
display: flex;
justify-content: space-between;
.left {
flex: 1;
width: vw(260);
}
.right {
margin-left: vw(20);
width: vw(120);
.li {
position: relative;
font-weight: 400;
font-size: vw(14);
color: #ffffff;
line-height: 16px;
text-align: left;
font-style: normal;
text-transform: none;
position: relative;
padding-left: vw(30);
padding: 0 vw(10);
padding-left: vw(15);
background: linear-gradient(90deg, #1b5ec7 0%, rgba(27, 94, 199, 0) 100%);
border-radius: 0px 0px 0px 0px;
height: vh(24);
line-height: vh(24);
margin-bottom: vh(8);
// opacity: 0.4;
.rk-img {
position: absolute;
width: vw(24);
height: vh(24);
line-height: vh(24);
left: vw(-12);
top: 50%;
display: block;
background-image: url('/src/assets/images/rk-4.png');
background-size: 100% 100%;
transform: translateY(-50%);
text-align: center;
}
}
.li-1 {
background: linear-gradient(90deg, #ffc10b 0%, rgba(255, 209, 44, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-1.png');
}
}
.li-2 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-2.png');
}
}
.li-3 {
background: linear-gradient(90deg, #919191 0%, rgba(175, 175, 175, 0) 100%);
.rk-img {
background-image: url('/src/assets/images/rk-3.png');
}
}
}
}
</style>

View File

@@ -1,61 +1,12 @@
<template>
<main class="wrapper">
<CoreVideo />
<box5 />
<box3 />
<Header title="三峡之巅-安全检测" is-skip :nav-left="navLeft" :nav-right="navRight" />
<Correspondence />
</main>
<box1 />
<box2 />
</template>
<script setup>
import box3 from './components/box-3.vue'
import box5 from './components/box-5.vue'
const navLeft = [
{
name: '奉节县',
path: '/sceneTesting'
},
{
name: '三峡之巅',
path: '/sceneTesting'
},
{
name: '白帝城',
path: '/sceneTesting'
},
{
name: '龙河桥',
path: '/sceneTesting'
}
]
const navRight = [
{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
}
]
import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
onMounted(() => {})
</script>
<style lang="scss" scoped>
.wrapper {
display: flex;
width: 100vw;
height: 100vh;
overflow: hidden;
background-color: #0a254b;
}
</style>
<style lang="scss" scoped></style>

View File

@@ -1,114 +1,13 @@
<template>
<main class="wrapper">
<CoreVideo />
<box2/>
<box3 />
<Header title="核心路段-安全检测" is-skip :nav-left="navLeft" :nav-right="navRight" />
<Correspondence />
</main>
<box3 />
<box2 />
</template>
<script setup>
import box3 from './components/box-3.vue'
import box2 from './components/box-2.vue'
const navLeft = [{
name: '奉节县',
path: '/sceneTesting'
},
{
name: '三峡之巅',
path: '/sceneTesting'
},
{
name: '白帝城',
path: '/sceneTesting'
}, {
name: '龙河桥',
path: '/sceneTesting'
}
]
const navRight = [{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
},
{
name: '路段',
path: '/roadTesting'
}
]
onMounted(() => {})
</script>
<style lang="scss" scoped>
.wrapper {
display: flex;
width: 100vw;
height: 100vh;
overflow: hidden;
background-color: #0a254b;
.header {
position: absolute;
left: vw(326);
.title {
width: vw(3133);
height: vh(120);
font-size: vw(48);
font-weight: 800;
text-align: center;
padding-top: vh(20);
color: #fff;
letter-spacing: vw(10);
box-sizing: border-box;
text-shadow: 0px 4px 7px rgba(0, 150, 255, 0.75);
background-image: url('@/assets/images/title.png');
background-size: 100% 100%;
}
.nav-left {
position: absolute;
left: vw(380);
top: vh(34);
display: flex;
&-item {
cursor: pointer;
margin-left: vh(-10);
width: vw(210);
height: vh(56);
padding-top: vh(10);
font-weight: 600;
font-size: vw(28);
text-align: center;
color: rgba(208, 236, 255, 0.9);
background-image: url('@/assets/images/title-2.png');
background-size: 100% 100%;
}
}
.nav-right {
position: absolute;
right: vw(424);
top: vh(34);
display: flex;
&-item {
cursor: pointer;
margin-right: vh(-10);
width: vw(210);
height: vh(56);
padding-top: vh(10);
font-weight: 600;
font-size: vw(28);
text-align: center;
color: rgba(208, 236, 255, 0.9);
background-image: url('@/assets/images/title-3.png');
background-size: 100% 100%;
}
}
}
}
</style>
<style lang="scss" scoped></style>

View File

@@ -1,28 +1,28 @@
<template>
<div class="traffic-box-1">
<div class="title-num">
<div class="box-1">
<div class="statistics">
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />总路段 </div>
<div class="item-num"
><span><countup endVal="88895" /> </span>
<div class="item-num">
<span><countup endVal="334600" /> </span>
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />总路段 </div>
<div class="item-num"
><span><countup endVal="88895" /> </span>
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵路段 </div>
<div class="item-num">
<span><countup endVal="35600" /> </span>
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />路段 </div>
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />核心路段 </div>
<div class="item-num"
><span><countup endVal="88895" /></span>
><span><countup endVal="15000" /></span>
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />总路段 </div>
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵路口 </div>
<div class="item-num"
><span><countup endVal="88895" /></span>
><span><countup endVal="2345" /></span>
</div>
</div>
</div>
@@ -61,85 +61,85 @@
</script>
<style lang="scss" scoped>
.chart {
display: flex;
flex-wrap: wrap;
gap: vw(8);
padding: vw(8);
.box-1 {
margin-top: vh(120);
width: vw(940);
height: vh(950);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
&-item {
width: vw(444);
height: vh(420);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
&__inner {
.chart {
display: flex;
align-items: center;
}
&__legend {
flex: 1;
flex-wrap: wrap;
gap: vw(8);
padding: 0 vw(8);
&-item {
position: relative;
width: 100%;
height: vh(40);
width: vw(456);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
}
&__inner {
display: flex;
align-items: center;
margin-bottom: vh(8);
background: linear-gradient(90deg, rgba(0, 150, 255, 0.34) 0%, rgba(0, 150, 255, 0) 100%);
height: vh(380);
}
&::before {
position: absolute;
content: '';
width: vw(4);
&__legend {
flex: 1;
&-item {
position: relative;
width: 100%;
height: vh(40);
background-color: #0096ff;
}
display: flex;
align-items: center;
margin-bottom: vh(8);
background: linear-gradient(90deg, rgba(0, 150, 255, 0.34) 0%, rgba(0, 150, 255, 0) 100%);
.dot {
width: vw(4);
height: vw(4);
margin: 0 vw(16);
}
&::before {
position: absolute;
content: '';
width: vw(4);
height: vh(40);
background-color: #0096ff;
}
.name {
font-weight: 400;
font-size: vw(12);
color: #ffffff;
width: vw(130);
}
.dot {
width: vw(4);
height: vw(4);
margin: 0 vw(16);
}
.value {
font-weight: bold;
font-size: vw(15);
color: #ffffff;
.name {
font-weight: 400;
font-size: vw(12);
color: #ffffff;
width: vw(130);
}
.value {
font-weight: bold;
font-size: vw(15);
color: #ffffff;
}
}
}
}
}
.traffic-box-1 {
position: relative;
margin-top: vh(120);
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
.title-num {
.statistics {
padding: 0 vw(40);
height: vh(110);
display: flex;
justify-content: flex-start;
padding: vw(40);
align-items: center;
.item-box {
flex: 1;
.item-t {
display: flex;
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.8);
color: #fff;
text-align: left;
font-style: normal;
text-transform: none;
margin-bottom: vh(20);
img {
margin-right: vw(5);

View File

@@ -1,30 +1,26 @@
<template>
<div class="n-box-traffic">
<!-- nav -->
<div class="left-nav">
<div class="top-box">
<div class="ul">
<div class="li active">路段1</div>
<div class="li">路段1</div>
<div class="li">路段1</div>
<div class="li">路段1</div>
<div class="li">路段1</div>
<div class="box-2">
<ul class="nav">
<li
class="nav-item"
:class="{ active: current == index }"
v-for="(item, index) in 20"
:key="index"
@click="handleNav(index)"
>路段{{ index + 1 }}
</li>
</ul>
<div class="map-box">
<Map />
<div class="video-list">
<div class="li">
<vue3VideoPlay v-bind="options" />
</div>
</div>
</div>
<div class="traffic-box-2">
<div class="map-box">
<Map></Map>
<!-- 视频 -->
<div class="video-list">
<div class="li">
<vue3VideoPlay v-bind="options" />
</div>
<div class="li">
<vue3VideoPlay v-bind="options" />
</div>
<div class="menu">查看更多</div>
<div class="li">
<vue3VideoPlay v-bind="options" />
</div>
<div class="menu">查看更多</div>
</div>
</div>
</div>
@@ -32,6 +28,7 @@
<script setup>
import Map from '@/components/Map/marker.vue'
let current = ref(0)
const options = reactive({
src: 'http://192.168.1.60:8080/live/340200000013200000011_34020000001320000001/hls.m3u8', //视频源
type: 'm3u8', //视频类型
@@ -59,56 +56,47 @@
'fullScreen'
] //显示所有按钮,
})
const handleNav = (e) => {
current.value = e
}
</script>
<style lang="scss" scoped>
.n-box-traffic {
.box-2 {
display: flex;
margin-top: vh(120);
}
.left-nav {
.nav {
margin-left: vw(10);
// margin-top:vh(35);
// width:vw(250);
.top-box {
text-align: left;
font-weight: 400;
overflow: auto;
height: vh(950);
&::-webkit-scrollbar {
width: vw(0); /* 滚动条的宽度 */
}
&-item {
cursor: pointer;
margin-bottom: vw(15);
width: vw(120);
height: vh(54);
font-weight: bold;
font-size: vw(18);
color: rgba(255, 255, 255, 0.7);
line-height: 21px;
text-align: left;
font-style: normal;
text-transform: none;
.title {
font-weight: 600;
font-size: vw(15);
text-align: left;
font-style: normal;
text-transform: none;
height: vh(35);
line-height: vh(34);
padding-left: vw(20);
// background: linear-gradient(90deg, #FFFFFF 0%, #75C1FF 100%);
}
.ul {
.li {
background: url('/src/assets/images/m-nav-bg-1.png');
background-size: 100% 100%;
width: vw(120);
height: vh(58);
line-height: vh(58);
text-align: center;
margin-bottom: vh(15);
}
.active {
background: url('/src/assets/images/m-nav-bg-2.png');
background-size: 100% 100%;
// width:vw(178);
}
}
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
background: url('/src/assets/images/m-nav-bg-1.png');
background-size: 100% 100%;
}
.active {
background: url('/src/assets/images/m-nav-bg-2.png');
background-size: 100% 100%;
}
}
.traffic-box-2 {
.map-box {
position: relative;
z-index: 9;
width: vw(1290);
@@ -118,41 +106,36 @@
box-sizing: border-box;
background-image: url('/src/assets/images/map-bg-2.png');
background-size: 100% 100%;
.map-box {
width: 100%;
height: 100%;
position: relative;
.video-list {
width: vw(320);
height: vh(120);
background: #0a254b;
border-radius: 0px 0px 0px 0px;
position: absolute;
bottom: vw(10);
right: vw(10);
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
.li {
width: vw(140);
height: vh(105);
background-image: url('/src/assets/images/small-v-bg.png');
background-size: 100% 100%;
margin-right: vw(6);
}
.menu {
width: vw(12);
height: vh(60);
font-family: Inter, Inter;
font-weight: 400;
font-size: vw(12);
color: #ffffff;
line-height: vh(14);
text-align: left;
font-style: normal;
text-transform: none;
}
.video-list {
width: vw(320);
height: vh(120);
background: #0a254b;
border-radius: 0px 0px 0px 0px;
position: absolute;
bottom: vw(40);
right: vw(40);
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
.li {
width: vw(140);
height: vh(105);
background-image: url('/src/assets/images/small-v-bg.png');
background-size: 100% 100%;
margin-right: vw(6);
}
.menu {
width: vw(12);
height: vh(60);
font-family: Inter, Inter;
font-weight: 400;
font-size: vw(12);
color: #ffffff;
line-height: vh(14);
text-align: left;
font-style: normal;
text-transform: none;
}
}
}

View File

@@ -1,116 +1,65 @@
<template>
<div class="traffic-box-3">
<!-- 1 -->
<div class="content-1">
<div class="tp-title">
<div class="box-1">
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="" />
<div class="xl-title">施家梁子大桥</div>
<div class="tp-item">3摄像机</div>
<div class="tp-item item-bg-2">3号点位</div>
<div class="box-3">
<div class="item" v-for="(item, index) in 2" :key="index">
<div class="header">
<div class="header-left">
<img src="@/assets/images/work-icon-xl-1.png" />
<div class="header-left__title">施家梁子大桥</div>
<div class="header-left__camera">3号摄像机</div>
<div class="header-left__point">3点位</div>
</div>
<div class="rt-text">严重拥堵</div>
<div class="header-status">严重拥堵</div>
</div>
<div class="title-num">
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />路段长度 </div>
<div class="item-num"
><span>
<countup endVal="88895" />
</span>
<div class="statistics">
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />路段长度
</div>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />平均车速 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />平均车速
</div>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵距离 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵距离
</div>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵次数 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵次数
</div>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex">
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵开始时间
</div>
<div class="item-num"><span>12:00:00</span></div>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex">
<div class="statistics-item">
<div class="statistics-item__label">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵持续时长
</div>
<div class="item-num"><span>1h30S</span></div>
</div>
</div>
<!-- chart -->
<div class="chart-item">
<div class="title-3"><span>拥堵频次占比</span></div>
<div class="chart-box">
<v-chart class="chart" :option="option1" autoresize />
</div>
</div>
</div>
<!-- 2 -->
<div class="content-1 content-2">
<div class="tp-title">
<div class="box-1">
<img class="icon-xl" src="@/assets/images/work-icon-xl-1.png" alt="" />
<div class="xl-title">施家梁子大桥</div>
<div class="tp-item">3号摄像机</div>
<div class="tp-item item-bg-2">3号点位</div>
</div>
<div class="rt-text rt-text-2">常规拥堵</div>
</div>
<div class="title-num">
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />路段长度 </div>
<div class="item-num"
><span>
<countup endVal="88895" />
</span>
<div class="statistics-item__value">
<countup end-val="88895" />
</div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />平均车速 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵距离 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
</div>
<div class="item-box">
<div class="item-t flex"> <img src="@/assets/images/t-icon-1.png" alt="" />拥堵次数 </div>
<div class="item-num"
><span> <countup endVal="88895" /> </span
></div>
</div>
<div class="item-box">
<div class="item-t flex">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵开始时间
</div>
<div class="item-num"><span>12:00:00</span></div>
</div>
<div class="item-box">
<div class="item-t flex">
<img src="@/assets/images/t-icon-1.png" alt="" />拥堵持续时长
</div>
<div class="item-num"><span>1h30S</span></div>
</div>
</div>
<!-- chart -->
<div class="chart-item">
<div class="title-3"><span>拥堵频次占比</span></div>
<div class="chart-box">
@@ -285,19 +234,82 @@
</script>
<style lang="scss" scoped>
.traffic-box-3 {
.box-3 {
width: vw(813);
padding: 0 vw(8);
margin-top: vh(120);
width: vw(818);
height: vh(480);
padding: vw(8);
position: relative;
z-index: 9;
background: linear-gradient(330deg, #0b2f64 0%, #062b57 100%);
.content-2 {
margin-top: vh(20);
}
.content-1 {
.item {
margin-bottom: vh(10);
background-image: url('@/assets/images/bg-2.png');
background-size: 100% 100%;
.header {
height: vh(72);
display: flex;
align-items: center;
&-left {
flex: 1;
display: flex;
align-items: center;
> img {
width: vw(30);
height: auto;
margin-right: vw(15);
}
}
&-left__title {
margin-right: vw(20);
font-size: vw(28);
font-weight: bold;
color: transparent;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
}
&-left__camera {
width: vw(120);
height: vw(72);
background-image: url('/src/assets/images/t-a-1.png');
background-size: 100% 100%;
font-weight: 600;
font-size: vw(15);
color: #ffffff;
padding-left: vw(42);
text-align: left;
font-style: normal;
text-transform: none;
display: flex;
align-items: center;
margin: 0 vw(20);
}
&-left__point {
margin: 0 vw(20);
width: vw(120);
height: vw(72);
font-weight: 600;
font-size: vw(15);
color: #ffffff;
padding-left: vw(42);
display: flex;
align-items: center;
background-image: url('/src/assets/images/t-a-2.png');
background-size: 100% 100%;
}
&-status {
width: vw(120);
height: vw(40);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
display: flex;
align-items: center;
padding-left: vw(40);
background-image: url('/src/assets/images/t-b-1.png');
background-size: 100% 100%;
}
}
.chart-item {
margin-top: vh(10);
height: vh(293);
@@ -337,28 +349,36 @@
}
}
.title-num {
.statistics {
height: vh(90);
display: flex;
justify-content: flex-start;
padding: vw(20);
background: radial-gradient(70% at 99% 50%, #0a4190 0%, rgba(0, 77, 136, 0.6) 100%);
border-radius: 0px 0px 0px 0px;
border: 1px solid;
border-image: linear-gradient(180deg, rgba(0, 150, 255, 1), rgba(0, 90, 153, 0)) 1 1;
align-items: center;
justify-content: space-evenly;
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&-item__label {
font-weight: 400;
font-size: vw(14);
color: #fff;
margin-bottom: vh(10);
}
&-item__value {
padding-left: vw(15);
height: vh(30);
font-weight: bold;
font-size: vw(24);
color: #02f9fa;
background-image: url('@/assets/images/t-box-title-bg-1.png');
background-size: 100% 100%;
}
.item-box {
flex: 1;
.item-t {
display: flex;
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.8);
text-align: left;
font-style: normal;
text-transform: none;
margin-bottom: vh(20);
img {
margin-right: vw(5);
width: vw(8);
@@ -389,74 +409,6 @@
}
}
}
.tp-title {
height: vh(72);
display: flex;
align-items: center;
.box-1 {
flex: 1;
display: flex;
align-items: center;
.icon-xl {
width: vw(30);
height: vh(22);
margin-right: vw(15);
}
.xl-title {
font-size: vw(28);
font-weight: bold;
color: transparent;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to bottom, #ffffff 0%, #87c9ff 100%);
margin-right: vw(20);
}
.tp-item {
width: vw(120);
height: vw(72);
background-image: url('/src/assets/images/t-a-1.png');
background-size: 100% 100%;
font-weight: 600;
font-size: vw(15);
color: #ffffff;
padding-left: vw(42);
text-align: left;
font-style: normal;
text-transform: none;
display: flex;
align-items: center;
margin: 0 vw(20);
}
.item-bg-2 {
background-image: url('/src/assets/images/t-a-2.png');
background-size: 100% 100%;
}
}
.rt-text {
width: vw(116);
height: vw(40);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
text-align: left;
line-height: vw(40);
padding-left: vw(40);
background-image: url('/src/assets/images/t-b-1.png');
background-size: 100% 100%;
}
.rt-text-2 {
background-image: url('/src/assets/images/t-b-2.png');
background-size: 100% 100%;
}
}
}
}
</style>