feat 监控大屏、安全检测

This commit is contained in:
duanliang
2024-12-18 10:42:20 +08:00
24 changed files with 1379 additions and 117 deletions

View File

@@ -1,33 +1,22 @@
<template>
<div class="pie" :id="id" />
<div class="age-ratio" id="age-ratio" />
</template>
<script setup>
import * as echarts from 'echarts'
import { fitChartSize } from '@/utils/dataUtil'
const props = defineProps({
id: {
type: String,
default: () => ''
}
})
let ageChart = null
let gaugeChart = null
onMounted(() => {
init()
})
const init = () => {
// domecharts
gaugeChart = echarts.init(document.getElementById(props.id))
gaugeChart.setOption({
ageChart = echarts.init(document.getElementById('age-ratio'))
ageChart.setOption({
tooltip: {
trigger: 'item'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['30%', '40%'],
itemStyle: {
@@ -59,15 +48,20 @@
window.addEventListener('resize', resize)
}
const resize = () => {
if (gaugeChart) {
gaugeChart.dispose()
if (ageChart) {
ageChart.dispose()
ageChart = null
init()
}
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
.pie {
.age-ratio {
width: vw(253);
height: vh(100);
}

View File

@@ -1,93 +0,0 @@
<template>
<div class="box-1">
<div class="title">核心景区视频</div>
<ul class="list">
<li
class="item"
:style="{ backgroundImage: `url(${index == 0 ? item1 : item2})` }"
v-for="(item, index) in 10"
:key="index"
>
<p class="item-title">三峡之巅-最新异常名称</p>
<img class="item-img" src="@/assets/images/cover.png" />
</li>
</ul>
</div>
</template>
<script setup>
import item1 from '@/assets/images/item-1.png'
import item2 from '@/assets/images/item-2.png'
</script>
<style lang="scss" scoped>
.box-1 {
margin: vh(10);
width: vw(326);
border-radius: vw(2);
background-image: url('@/assets/images/bg-1.png');
background-size: 100% 100%;
.title {
width: vw(260);
height: vh(26);
text-align: center;
line-height: vh(26);
margin-left: vw(32.5);
font-size: vw(16);
font-weight: 800;
color: #fff;
background-image: url('@/assets/images/title-1.png');
background-size: 100% 100%;
}
.list {
overflow-y: auto;
overflow-x: hidden;
height: vh(1026);
padding: vw(8);
/* 滚动条整体样式 */
&::-webkit-scrollbar {
width: vw(0); /* 滚动条的宽度 */
}
/* 滚动条轨道 */
&::-webkit-scrollbar-track {
background: #f1f1f1; /* 轨道的背景色 */
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: #888; /* 滑块的背景色 */
border-radius: 5px; /* 滑块的圆角 */
}
/* 当鼠标悬停在滚动条上时滑块的样式 */
&::-webkit-scrollbar-thumb:hover {
background: #555; /* 滑块的背景色 */
}
}
.item {
margin-bottom: vh(13);
background-size: 100% 100%;
&-title {
margin-bottom: vh(6);
margin-left: vw(45);
color: #fff;
font-size: vw(16);
height: vh(24);
line-height: vh(24);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&-img {
width: 100%;
height: vh(164);
display: block;
object-fit: cover;
}
}
}
</style>

View File

@@ -91,7 +91,7 @@
<div class="flex">
<div class="box-1">
<Title3 title="年龄/性别占比" />
<pie id="pie" />
<age-ratio />
<div class="count">总人数<countup endVal="124563" /></div>
<div class="cell pt-20">
<img class="icon" src="@/assets/images/man.png" />
@@ -138,7 +138,7 @@
<script setup>
import countup from 'vue-countup-v3'
import pie from './pie.vue'
import AgeRatio from './age-ratio.vue'
import top from './top.vue'
import gauge from './gauge.vue'
import ticket from './ticket.vue'

View File

@@ -44,7 +44,7 @@
<div class="footer">
<div class="left">
<div>
<div class="flex">
<div class="flex justify-center pt-10">
<div class="item">
<p class="label">今日工单总条数</p>
<countup :endVal="1234" />
@@ -54,10 +54,21 @@
<countup :endVal="1234" />
</div>
</div>
<p>工单完成数</p>
<div class="progress-box">
<span class="text">工单完成数</span>
<div class="progress">
<el-progress
:percentage="50"
:show-text="false"
color="linear-gradient( to right,
#00C4F9 0%, #00C4F9 100%)"
/>
</div>
<span class="value">50%</span>
</div>
</div>
<div>
<div class="flex">
<div class="flex justify-center pt-10">
<div class="item">
<p class="label">紧急工单数</p>
<countup :endVal="1234" />
@@ -67,7 +78,18 @@
<countup :endVal="1234" />
</div>
</div>
<p>工单完成数</p>
<div class="progress-box">
<span class="text">工单完成数</span>
<div class="progress">
<el-progress
:percentage="50"
:show-text="false"
color="linear-gradient( to right,
#DA3637 0%, #DA3637 100%)"
/>
</div>
<span class="value">50%</span>
</div>
</div>
</div>
<div class="right">
@@ -166,9 +188,11 @@
.left {
flex: 1;
display: flex;
margin-top: vh(4);
& > div {
flex: 1;
height: vh(110);
margin-right: vw(6);
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
.item {
@@ -189,6 +213,27 @@
font-size: vw(28);
font-weight: bold;
}
.progress-box {
margin-top: vh(10);
display: flex;
align-items: center;
justify-content: center;
.text {
margin-right: vw(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
.progress {
width: vw(100);
}
.value {
margin-left: vw(10);
font-weight: 400;
font-size: vw(14);
color: #ffffff;
}
}
}
}
.right {
@@ -242,4 +287,8 @@
}
}
}
</style>
<<<<<<< HEAD
</style>
=======
</style>
>>>>>>> 1108aafed493fffba8fdd2e63eae89a9092ef6e5

View File

@@ -1,6 +1,6 @@
<template>
<div class="box-4">
<!-- <Title1 title="交通信息" />
<Title1 title="交通信息" />
<div class="flex justify-evenly pt-10">
<div v-for="item in list" class="cell">
<img class="icon" :src="item.icon" alt="" width="64" height="64" />
@@ -97,7 +97,7 @@
<div class="flex-1">
<Title1 title="酒店信息" class="title1" />
</div>
</div> -->
</div>
<div class="flex">
<div class="car-ship">
<div class="mb-6">
@@ -114,9 +114,19 @@
<div>空余</div>
</div>
<div class="cell">
<div class="label">车牌号</div>
<div>车长</div>
<div>车速</div>
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
</div>
</div>
@@ -126,12 +136,56 @@
<div class="flex align-center">
<countup class="value" :end-val="130" /> <span class="unit"></span>
</div>
<div class="table">
<div class="header">
<div>景区</div>
<div>调度</div>
<div>空余</div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
<div class="cell">
<div>白帝城</div>
<div>5<span class="unit-1"></span></div>
<div>1<span class="unit-1"></span></div>
</div>
</div>
</div>
</div>
</div>
<div class="hotel">
<div> 3 </div>
<div> 4 </div>
<div>
<div class="item">
<div class="label">车库总数</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">房间总数</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">总入住</div>
<countup class="value" :end-val="500" />
</div>
<div class="item">
<div class="label">总入住率</div>
<countup class="value" :end-val="500" />
</div>
</div>
<div>
<div class="pt-6">
<Title3 title="酒店入住人数及入住率" />
</div>
<lodging-ratio />
</div>
</div>
</div>
</div>
@@ -139,8 +193,10 @@
<script setup>
import jam from './jam.vue'
import TrafficFlow from './traffic-flow.vue'
import vacancy from './vacancy.vue'
import TrafficFlow from './traffic-flow.vue'
import LodgingRatio from './lodging-ratio.vue'
import countup from 'vue-countup-v3'
import icon1 from '@/assets/images/icon-1.png'
import icon2 from '@/assets/images/icon-2.png'
@@ -227,10 +283,10 @@
}
& > div {
flex: 1;
height: vh(70);
display: flex;
align-items: center;
justify-content: space-evenly;
height: vh(70);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.label {
@@ -263,10 +319,12 @@
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.icon {
padding-left: vw(90);
width: vw(352);
height: vh(70);
padding-top: vh(10);
padding-left: vw(90);
display: flex;
flex-direction: column;
justify-content: center;
background-size: 100% 100%;
box-sizing: border-box;
}
@@ -298,7 +356,7 @@
.table {
position: absolute;
left: vw(160);
width: vw(200);
width: vw(220);
height: vh(100);
z-index: 2;
.header {
@@ -316,19 +374,73 @@
}
.cell {
display: flex;
height: vh(30);
line-height: vh(30);
height: vh(27);
line-height: vh(27);
text-align: center;
background: #074686;
&:nth-child(2n + 1) {
background: rgba(0, 150, 255, 0.1);
}
& > div {
flex: 1;
}
& > div:nth-child(1) {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
& > div:nth-child(2) {
font-weight: bold;
font-size: vw(18);
color: #ffffff;
}
& > div:nth-child(3) {
font-weight: bold;
font-size: vw(18);
color: #02f9fa;
}
.unit-1 {
font-size: vw(12);
}
}
}
}
}
.hotel {
flex: 1;
margin-left: vw(6);
& > div:nth-child(1) {
display: flex;
width: vw(360);
height: vh(70);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
.item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.label {
font-weight: 400;
font-size: vw(14);
color: rgba(255, 255, 255, 0.9);
}
.value {
margin-top: vh(10);
font-weight: bold;
font-size: vw(24);
color: #ffffff;
}
}
}
& > div:nth-child(2) {
margin-top: vh(10);
width: vw(360);
height: vh(140);
background-image: url('@/assets/images/bg-4.png');
background-size: 100% 100%;
}
}
}
</style>

View File

@@ -44,15 +44,15 @@
roundCap: true,
width: fitChartSize(6)
},
pointer: {
show: false
},
axisLine: {
roundCap: true,
lineStyle: {
width: fitChartSize(6)
}
},
pointer: {
show: false
},
axisTick: {
show: false
},

View File

@@ -0,0 +1,188 @@
<template>
<div class="lodging-ratio" id="lodging-ratio" />
</template>
<script setup>
import { fitChartSize } from '@/utils/dataUtil'
import * as echarts from 'echarts'
let topChart = null
let result = [
{ name: '酒店1', value: 86 },
{ name: '酒店2', value: 83 },
{ name: '酒店3', value: 73 }
]
let option = {
backgroundColor: 'transparent',
tooltip: {
show: false
},
legend: {
show: false
},
grid: {
left: '4%',
right: '4%',
top: '16%',
bottom: '-10%',
containLabel: true
},
xAxis: [
{
splitLine: {
show: false
},
type: 'value',
show: false
}
],
yAxis: [
{
splitLine: {
show: false
},
axisLine: {
show: false
},
type: 'category',
axisTick: {
show: false
},
data: result.map((item) => item.name),
axisLabel: {
show: false
}
},
{
type: 'category',
inverse: true,
axisTick: 'none',
axisLine: 'none',
show: true,
axisLabel: {
textStyle: {
color: '#fff',
fontSize: fitChartSize(12)
},
verticalAlign: 'bottom',
padding: [0, 0, 6, 0],
inside: true,
formatter: function (value) {
return `{value|${value}}`
},
rich: {
name: {
align: 'center',
color: '#D3E5FF',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
},
value: {
align: 'center',
color: '#fff',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN'
}
}
},
data: result.map((item) => item.value)
}
],
series: [
{
name: '',
type: 'bar',
barWidth: fitChartSize(4),
MaxSize: 0,
showBackground: true,
barBorderRadius: [30, 0, 0, 30],
backgroundStyle: {
color: 'rgba(0, 150, 255, 0.15)'
},
label: {
show: true,
offset: [10, -13],
color: '#D3E5FF',
fontWeight: 500,
position: 'left',
align: 'left',
fontSize: fitChartSize(14),
fontFamily: 'Source Han Sans CN',
formatter: function (params) {
return params.data.name
}
},
data: result.map((item, index) => {
return {
name: item.name,
value: item.value,
itemStyle: {
barBorderRadius: [3, 0, 0, 3],
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(255, 112, 33, 0)'
},
{
offset: 1,
color: 'rgba(255, 112, 33, 1)'
}
]
}
}
}
})
},
{
name: '外圆',
type: 'scatter',
emphasis: {
scale: false
},
showSymbol: true,
symbol: 'circle',
symbolSize: fitChartSize(10),
z: 2,
data: result.map((item, index) => {
return {
name: item.name,
value: item.value,
itemStyle: {
color: '#fff',
opacity: 1
}
}
}),
animationDelay: 500
}
]
}
const init = () => {
topChart = echarts.init(document.getElementById('lodging-ratio'))
topChart.setOption(option)
}
const resize = () => {
if (topChart) {
topChart.dispose()
topChart = null
init()
}
}
onMounted(() => {
init()
window.addEventListener('resize', resize)
})
</script>
<style scoped lang="scss">
.lodging-ratio {
width: 100%;
height: vh(110);
}
</style>

View File

@@ -1,4 +1,5 @@
<template>
<<<<<<< HEAD
<main class="wrapper">
<box1 />
<div class="header">
@@ -19,79 +20,21 @@
<box3 />
<box4 />
</main>
=======
<Header title="奉节县旅游指挥调度中心" is-skip :nav-left="navLeft" :nav-right="navRight" />
<CoreVideo />
<box2 />
<box3 />
<box4 />
<Correspondence />
>>>>>>> 1108aafed493fffba8fdd2e63eae89a9092ef6e5
</template>
<script setup>
import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
import box3 from './components/box-3.vue'
import box4 from './components/box-4.vue'
const navLeft = [{ name: '安全' }, { name: '景区', path: '/scenic' }, { name: '交通' }]
const navRight = [{ name: '停车' }, { name: '工单' }, { name: '舆情' }, { name: '酒店' }]
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(630);
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>

View File

@@ -0,0 +1,250 @@
<template>
<div class="box-1">
<div class="header">
<div>
<div class="label">今年总游客数</div>
<countup v-for="item in count" :endVal="item" />
</div>
<div>
<div>
<div class="label">接待状态</div>
<p class="value">安全</p>
</div>
<div>
<div class="label">景区安全</div>
<p class="value">安全</p>
</div>
<div>
<div class="label">景区游玩舒适</div>
<p class="value error">排队</p>
</div>
<div>
<div class="label">通景交通</div>
<p class="value">安全</p>
</div>
<div>
<div class="label">停车场负荷度</div>
<p class="value error">超负荷</p>
</div>
</div>
</div>
<div class="main"> </div>
<div class="footer">
<div class="flex">
<div class="item">
<pie :width="140" :height="70" />
<div>
<div class="bg">
<span class="label">今日工单总条数</span>
<span class="value"> <countup :endVal="1234" /></span>
</div>
<div class="bg">
<span class="label">工单完成数</span>
<span class="value"> <countup :endVal="1234" /></span>
</div>
</div>
</div>
<div class="item">
<pie :width="140" :height="70" />
<div>
<div class="bg">
<span class="label">今日工单总条数</span>
<span class="value"> <countup :endVal="1234" /></span>
</div>
<div class="bg">
<span class="label">工单完成数</span>
<span class="value"> <countup :endVal="1234" /></span>
</div>
</div>
</div>
</div>
<div class="flex align-center justify-between">
<div>
<div class="cell">
<span class="tag tag--success">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
<div class="cell">
<span class="tag tag--error">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
<div class="cell">
<span class="tag tag--primary">普通</span>
<p class="content">
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工单信息工工单信息工单信息工单信息工单信息工单信息
</p>
</div>
</div>
<div class="more">查看更多</div>
</div>
</div>
</div>
</template>
<script setup>
import countup from 'vue-countup-v3'
import pie from './pie.vue'
let count = ref('58459')
</script>
<style scoped lang="scss">
.box-1 {
margin-top: vh(120);
width: vw(810);
height: vh(950);
padding: vw(10);
box-sizing: border-box;
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
.header {
display: flex;
margin-top: vh(10);
& > div:nth-child(1) {
width: vw(300) !important;
}
& > div:nth-child(2) {
flex: 1;
display: flex;
justify-content: space-between;
}
.label {
font-weight: 400;
font-size: vw(16);
color: #ffffff;
}
.value {
font-weight: bold;
font-size: vw(28);
color: #02f9fa;
text-align: center;
line-height: vh(60);
}
.error {
color: #ff4400;
}
.countup-wrap {
margin-top: vh(10);
display: inline-block;
width: vw(40);
height: vh(40);
margin-right: vw(4);
border-radius: vw(4);
color: #ffffff;
font-size: vw(28);
font-weight: bold;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #00b7ff 0%, #0033ff 100%);
}
}
.main {
width: 100%;
height: vh(600);
}
.footer {
.item {
flex: 1;
height: vh(120);
display: flex;
align-items: center;
background-image: url('@/assets/images/bg-3.png');
background-size: 100% 100%;
&:nth-child(1) {
margin-right: vw(10);
}
.bg {
padding-left: vw(20);
width: vw(243);
height: vh(40);
display: flex;
align-items: center;
background: linear-gradient(90deg, rgba(0, 150, 255, 0.34) 0%, rgba(0, 150, 255, 0) 100%);
&:nth-child(1) {
margin-bottom: vh(4);
}
.label {
font-weight: 400;
font-size: vw(14);
color: #fff;
}
.value {
font-weight: bold;
font-size: vw(28);
color: #02f9fa;
}
}
}
.cell {
display: flex;
margin-left: vw(4);
margin-top: vh(12);
&:nth-last-child(1) {
margin-bottom: 0;
}
.tag {
padding: 0 vw(16);
font-weight: bold;
font-size: vw(14);
display: flex;
align-items: center;
justify-content: center;
border-radius: vw(2);
&--success {
color: #02f9fa;
border: 1px solid #02f9fa;
box-shadow: inset 0 0 vw(8) 0 #0be1ab;
}
&--error {
color: #ee2c2c;
border: 1px solid #ee2c2c;
box-shadow: inset 0 0 vw(8) 0 #ee2c2c;
}
&--primary {
color: #00aaff;
border: 1px solid #00aaff;
box-shadow: inset 0 0 vw(8) 0 #00aaff;
}
}
.content {
margin-left: vw(4);
padding: 0 vw(10);
width: vw(660);
height: vh(24);
line-height: vh(24);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 400;
font-size: vw(14);
color: #ffffff;
border-radius: vw(2);
background: rgba(0, 150, 255, 0.28);
}
}
.more {
cursor: pointer;
margin-top: vh(12);
width: vw(26);
height: vh(98);
font-weight: 400;
font-size: vw(14);
line-height: vh(10);
color: #ffffff;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
background: #034e99;
}
}
}
</style>

View File

@@ -0,0 +1,69 @@
<template>
<div class="container">
<div class="flex">
<div class="box mr-10">
<Title1 title="排队信息" />
<div class="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" />
</div>
<div class="pt-10">
<Title3 title="景区排队人数" />
</div>
<Line :width="540" :height="340" />
</div>
<div class="box mr-10">
<Title1 title="景区承载" />
<div class="flex">
<pie :width="160" :height="50" />
<div class="flex flex-1 justify-between">
<count-item label="景区当前人数" :count="35600" suffix="张" />
<count-item label="景区最大承载" :count="35600" suffix="人" />
</div>
</div>
<div class="pt-10">
<Title3 title="景区排队人数" />
</div>
<Line :width="540" :height="300" />
</div>
<div class="box-1 mr-10">
<Title1 title="停车信息" />
</div>
<div class="box-2">
<Title1 title="安全信息 " />
</div>
</div>
</div>
</template>
<script setup>
import CountItem from './count-item.vue'
import pie from './pie.vue'
</script>
<style scoped lang="scss">
.container {
flex: 1;
margin: vh(120) vw(10) 0 vw(10);
.bg {
background: linear-gradient(321deg, #0b2f64 0%, #062b57 100%);
}
.box {
@extend .bg;
width: vw(575);
height: vh(475);
}
.box-1 {
@extend .bg;
width: vw(770);
height: vh(475);
}
.box-2 {
@extend .bg;
width: vw(440);
height: vh(475);
}
}
</style>

View File

@@ -0,0 +1,70 @@
<template>
<div class="count-item">
<div class="flex align-center">
<img src="@/assets/images/dian.svg" />
<span class="label">{{ label }}</span>
</div>
<div class="count">
<img class="bg" src="@/assets/images/count-bg.svg" />
<div class="flex align-center">
<countup class="value" :end-val="count" />
<span class="suffix">{{ suffix }}</span>
</div>
</div>
</div>
</template>
<script setup>
import countup from 'vue-countup-v3'
let props = defineProps({
label: {
type: Number,
default: ''
},
count: {
type: Number,
default: 0
},
suffix: {
type: String,
default: ''
}
})
</script>
<style scoped lang="scss">
.count-item {
flex: 1;
.label {
font-weight: 400;
font-size: vw(14);
margin-left: vw(4);
color: rgba(255, 255, 255, 0.9);
}
.count {
position: relative;
margin-top: vh(10);
z-index: 1;
.value {
padding-left: vw(20);
font-weight: bold;
font-size: vw(28);
color: #02f9fa;
}
.suffix {
margin-top: vh(4);
font-weight: bold;
font-size: vw(12);
color: #02f9fa;
}
.bg {
width: 100%;
height: vh(40);
position: absolute;
left: 0;
top: 0;
z-index: -1;
}
}
}
</style>

View File

@@ -0,0 +1,178 @@
<template>
<div
class="gauge"
:id="id"
:style="{
width: styleUtil.px2vw(width),
height: styleUtil.px2vh(height)
}"
/>
</template>
<script setup>
import * as echarts from 'echarts'
import { guid } from '@/utils/util'
import styleUtil from '@/utils/styleUtil'
import { fitChartSize } from '@/utils/dataUtil'
const props = defineProps({
width: {
type: Number,
default: () => 0
},
height: {
type: Number,
default: () => 0
}
})
let gaugeChart = null
let id = ref(guid())
let defaultCofig = {
title: [
{
text: '45.5%',
x: 'center',
top: '34%',
textStyle: {
color: '#00D0FF',
fontSize: fitChartSize(12)
}
},
{
text: '完成率',
x: 'center',
top: '56%',
textStyle: {
color: '#fff',
fontSize: fitChartSize(12)
}
}
],
series: [
// 内侧环
{
type: 'gauge',
radius: '100%',
center: ['50%', '60%'],
min: 0,
max: 100,
startAngle: 180,
endAngle: 0,
itemStyle: {
color: '#00D0FF'
},
axisLine: {
show: true,
roundCap: false,
lineStyle: {
color: [
[0, '#075199'],
[1, '#075199']
],
width: fitChartSize(6)
}
},
progress: {
show: true,
roundCap: false,
width: fitChartSize(6)
},
pointer: {
// 指针
show: false
},
axisTick: {
// 刻度
show: false
},
splitLine: {
// 分割线
show: false
},
axisLabel: {
// 刻度标签
show: false
},
detail: {
// 仪表盘详情
show: false
},
data: [
{
value: 50
}
]
},
{
type: 'gauge',
radius: '90%',
center: ['50%', '60%'],
min: 0,
max: 100,
startAngle: 180,
endAngle: 0,
itemStyle: {
color: '#057EB9'
},
axisLine: {
roundCap: false,
lineStyle: {
color: [
[0, '#075199'],
[1, '#075199']
],
width: fitChartSize(6)
}
},
progress: {
show: true,
roundCap: false,
width: fitChartSize(6)
},
pointer: {
// 指针
show: false
},
axisTick: {
// 刻度
show: false
},
splitLine: {
// 分割线
show: false
},
axisLabel: {
// 刻度标签
show: false
},
detail: {
// 仪表盘详情
show: false
},
data: [
{
value: 50
}
]
}
]
}
onMounted(() => {
init()
})
const init = () => {
// 基于准备好的dom初始化echarts实例
gaugeChart = echarts.init(document.getElementById(id.value))
gaugeChart.setOption({ ...defaultCofig })
window.addEventListener('resize', resize)
}
const resize = () => {
if (gaugeChart) {
gaugeChart.dispose()
init()
}
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,21 @@
<template>
<Header :current="current" :nav-left="navLeft" @on-change="onChange" />
<CoreVideo />
<box1 />
<box2 />
<Correspondence />
</template>
<script setup>
import box1 from './components/box-1.vue'
import box2 from './components/box-2.vue'
const navLeft = [{ name: '奉节县' }, { name: '龙桥河' }, { name: '山峡之巅' }]
let current = ref(0)
const onChange = (e) => {
current.value = e
}
</script>
<style scoped lang="scss"></style>