feat: 空天地大屏
This commit is contained in:
parent
972e35f278
commit
e57b9b4865
45
packages/screen/src/views/airSkyLand/AirSkyLand.scss
Normal file
45
packages/screen/src/views/airSkyLand/AirSkyLand.scss
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
.air-sky-land {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgb(17, 38, 61);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-section {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-section {
|
||||||
|
position: absolute;
|
||||||
|
left: vw(45);
|
||||||
|
top: vw(25);
|
||||||
|
bottom: vw(25);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 遥感监控区
|
||||||
|
.remote-monitor-section {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无人机监控区
|
||||||
|
.aircraft-monitor-section {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 常规监控区
|
||||||
|
.common-monitor-section {
|
||||||
|
position: absolute;
|
||||||
|
right: vw(45);
|
||||||
|
top: 25px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
38
packages/screen/src/views/airSkyLand/AirSkyLand.vue
Normal file
38
packages/screen/src/views/airSkyLand/AirSkyLand.vue
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<div class="air-sky-land">
|
||||||
|
<!-- 地图 -->
|
||||||
|
<div class="map-section">
|
||||||
|
<MapCenter />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="left-section">
|
||||||
|
<div class="remote-monitor-section">
|
||||||
|
<SectionTitle title="遥感监控(空)" />
|
||||||
|
<!-- 遥感监控 -->
|
||||||
|
<RemoteMonitor />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="aircraft-monitor-section">
|
||||||
|
<SectionTitle title="无人机检测(天)" />
|
||||||
|
<!-- 无人机检测 -->
|
||||||
|
<AircraftMonitor />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="common-monitor-section">
|
||||||
|
<SectionTitle title="常规检测(地)" />
|
||||||
|
<!-- 常规检测 -->
|
||||||
|
<CommonMonitor />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import SectionTitle from './components/SectionTitle/SectionTitle.vue';
|
||||||
|
import RemoteMonitor from './components/RemoteMonitor/RemoteMonitor.vue';
|
||||||
|
import CommonMonitor from './components/CommonMonitor/CommonMonitor.vue';
|
||||||
|
import AircraftMonitor from './components/AircraftMonitor/AircraftMonitor.vue';
|
||||||
|
import MapCenter from './components/MapCenter/MapCenter.vue';
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss" src="./AirSkyLand.scss"></style>
|
||||||
3
packages/screen/src/views/airSkyLand/README.md
Normal file
3
packages/screen/src/views/airSkyLand/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# 空天地-一体化智能检测-大屏展示
|
||||||
|
|
||||||
|
#### 该页面来自于WuRenJi 项目的YLZG页面,对其进行vue化的改造。
|
||||||
7
packages/screen/src/views/airSkyLand/api/index.js
Normal file
7
packages/screen/src/views/airSkyLand/api/index.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { request } from '@shared/utils/request'
|
||||||
|
export function getBaseMapLayer() {
|
||||||
|
return request({
|
||||||
|
url: '/api/v1/DataDirectory/QueryCatalog',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<!-- 无人机监测 -->
|
||||||
|
<template>
|
||||||
|
<div class="aircraft-monitor-section">
|
||||||
|
<!-- 每日快速巡检 -->
|
||||||
|
<QuickInspection />
|
||||||
|
|
||||||
|
<!-- 关键点经常性检查 -->
|
||||||
|
<KeyInspection />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import QuickInspection from './QuickInspection.vue';
|
||||||
|
import KeyInspection from './KeyInspection.vue';
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
<!-- 每日巡检 -->
|
||||||
|
<template>
|
||||||
|
<div class="key-inspection">
|
||||||
|
<div class="title-block">
|
||||||
|
<div class="title-text">关键点经常性检查</div>
|
||||||
|
<div class="date-text">巡查月份: {{ date }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="content-block">
|
||||||
|
<div class="item-box-list">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="left-side">
|
||||||
|
<div class="main-field-item-box">
|
||||||
|
<img />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="sub-field-item-box">
|
||||||
|
<img />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sub-field-item-box">
|
||||||
|
<img />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const date = ref('2025/10/10')
|
||||||
|
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '边坡总数',
|
||||||
|
name: '',
|
||||||
|
icon: '',
|
||||||
|
completeLabel: '完成率',
|
||||||
|
completeIcon: '',
|
||||||
|
completeValue: '',
|
||||||
|
countLabel: '派单数',
|
||||||
|
countIcon: '',
|
||||||
|
countValue: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '边坡总数',
|
||||||
|
name: '',
|
||||||
|
icon: '',
|
||||||
|
completeLabel: '完成率',
|
||||||
|
completeIcon: '',
|
||||||
|
completeValue: '',
|
||||||
|
countLabel: '派单数',
|
||||||
|
countIcon: '',
|
||||||
|
countValue: ''
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
.key-inspection {}
|
||||||
|
|
||||||
|
.item-box-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-field-item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
<!-- 每日快速巡检 -->
|
||||||
|
<template>
|
||||||
|
<div class="everyday-inspection">
|
||||||
|
<div class="title-block">
|
||||||
|
<div class="title-text">每日快速巡检</div>
|
||||||
|
<div class="date-text">巡检日期: {{ date }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="content-block">
|
||||||
|
<div class="item-box-list">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="left-side">
|
||||||
|
<img />
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const date = ref('2025/10/10')
|
||||||
|
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '路线总里程 (公里)',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '完成率',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '复核率',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '派单数',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
.everyday-inspection {}
|
||||||
|
|
||||||
|
.item-box-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div class="common-monitor-section">
|
||||||
|
<div class="common-monitor-area">
|
||||||
|
<div class="area-title">日常巡检</div>
|
||||||
|
<StateRoad />
|
||||||
|
<CountryRoad />
|
||||||
|
</div>
|
||||||
|
<div class="common-monitor-area">
|
||||||
|
<div class="area-title">智能巡查</div>
|
||||||
|
<SmartInspection />
|
||||||
|
</div>
|
||||||
|
<div class="common-monitor-area">
|
||||||
|
<div class="area-title">智能监测</div>
|
||||||
|
<SmartMonitor />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import StateRoad from './StateRoad.vue';
|
||||||
|
import CountryRoad from './CountryRoad.vue';
|
||||||
|
import SmartMonitor from './SmartMonitor.vue';
|
||||||
|
import SmartInspection from './SmartInspection.vue'
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
<!-- 农村公路路障数值化履职 -->
|
||||||
|
<template>
|
||||||
|
<div class="country-road">
|
||||||
|
<div class="top-side">
|
||||||
|
<div class="info-item-box">
|
||||||
|
<img class="icon" />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ '' }}<span class="special">人</span></div>
|
||||||
|
<div class="label-text">{{ '农村公路巡检总人数' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bottom-side">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="bottom-item-box">
|
||||||
|
<img class="icon" />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text" :class="{special: item.special}">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '事件总数 (件)',
|
||||||
|
special: true,
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '处置数 (件)',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '处置中 (件)',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
|
||||||
|
.info-item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.icon {}
|
||||||
|
|
||||||
|
.special {}
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.icon {}
|
||||||
|
|
||||||
|
.special {}
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<!-- 智能巡查 -->
|
||||||
|
<template>
|
||||||
|
<div class="smart-inspection">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="left-side">
|
||||||
|
<img class="icon" />
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="field-item title">
|
||||||
|
<div class="label-text">{{ item.label }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="field-item expection">
|
||||||
|
<div class="label-text">异常数</div>
|
||||||
|
<div class="value-text">{{ data[item.expection] }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="field-item dispatch">
|
||||||
|
<div class="label-text">派单数</div>
|
||||||
|
<div class="value-text">{{ data[item.dispatch] }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="field-item online">
|
||||||
|
<div class="label-text">总数 / 在线数</div>
|
||||||
|
<div class="value-text">{{ data[item.online] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '视频巡查',
|
||||||
|
icon: '',
|
||||||
|
expection: '',
|
||||||
|
dispatch: '',
|
||||||
|
online: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '公交巡查',
|
||||||
|
icon: '',
|
||||||
|
expection: '',
|
||||||
|
dispatch: '',
|
||||||
|
online: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '专业巡查',
|
||||||
|
icon: '',
|
||||||
|
expection: '',
|
||||||
|
dispatch: '',
|
||||||
|
online: ''
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.smart-inspection {
|
||||||
|
display: flexx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.icon {}
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<!-- 智能监测 -->
|
||||||
|
<template>
|
||||||
|
<div class="smart-monitor">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="left-side">
|
||||||
|
<img class="icon" />
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="field-item title">
|
||||||
|
<div class="label-text">{{ item.label }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="count-item">
|
||||||
|
{{ data[item.count] }}
|
||||||
|
</div>
|
||||||
|
<div class="field-item alert">
|
||||||
|
<div class="label-text">预警数</div>
|
||||||
|
<div class="value-text">{{ data[item.alert] }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="field-item dispatch">
|
||||||
|
<div class="label-text">派单数</div>
|
||||||
|
<div class="value-text">{{ data[item.dispatch] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '桥梁监测',
|
||||||
|
icon: '',
|
||||||
|
count: '',
|
||||||
|
countSubfix: '座',
|
||||||
|
alert: '',
|
||||||
|
dispatch: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '隧道监测',
|
||||||
|
icon: '',
|
||||||
|
count: '',
|
||||||
|
countSubfix: '座',
|
||||||
|
alert: '',
|
||||||
|
dispatch: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '边坡监测',
|
||||||
|
icon: '',
|
||||||
|
count: '',
|
||||||
|
countSubfix: '处',
|
||||||
|
alert: '',
|
||||||
|
dispatch: '',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.smart-monitor {}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
<!-- 国省通风险管控 -->
|
||||||
|
<template>
|
||||||
|
<div class="state-road">
|
||||||
|
<div class="top-bar">
|
||||||
|
<div class="top-item-box">
|
||||||
|
<img class="icon" />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data }}</div>
|
||||||
|
<div class="label-text">国道巡检总人数</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="top-item-box">
|
||||||
|
<img class="icon" />
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data }}%</div>
|
||||||
|
<div class="label-text">履职率</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bottom-bar">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="top-side">{{ item['title'] }}</div>
|
||||||
|
<div class="bottom-side">
|
||||||
|
<div>
|
||||||
|
<div class="person-block">{{ data[item.person] }} <span class="person-text">人</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<img />
|
||||||
|
<div class="">巡查履职完成率</div>
|
||||||
|
<div>
|
||||||
|
<span class="percent-text">{{ data[item.percent] }}%</span>{{ item.percentSubfix }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
title: '交通主管部门责任人',
|
||||||
|
icon: '',
|
||||||
|
person: '',
|
||||||
|
percent: '',
|
||||||
|
percentSubfix: '1次/半年',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '公路机构责任人',
|
||||||
|
icon: '',
|
||||||
|
person: '',
|
||||||
|
percent: '',
|
||||||
|
percentSubfix: '1次/1月',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '养护站(道班)责任人',
|
||||||
|
icon: '',
|
||||||
|
person: '',
|
||||||
|
percent: '',
|
||||||
|
percentSubfix: '1次/半年',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路段护路员',
|
||||||
|
icon: '',
|
||||||
|
person: '',
|
||||||
|
percent: '',
|
||||||
|
percentSubfix: '1次/2周',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<div class="">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
//["事件", "线路", "专业巡查", "公交巡查", "边坡", "桥梁", "隧道", "服务点", "清除"]
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
@ -0,0 +1,208 @@
|
|||||||
|
<template>
|
||||||
|
<div class="map-center">
|
||||||
|
<div class="map-container" ref="mapContainer" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { getBaseMapLayer } from '../../api'
|
||||||
|
import * as Cesium from 'cesium'
|
||||||
|
import { useMapStore } from '../../../../map/index.js'
|
||||||
|
|
||||||
|
const emit = defineEmits()
|
||||||
|
const mapStore = useMapStore()
|
||||||
|
|
||||||
|
const ionToken = import.meta.env.VITE_CESIUM_ION_TOKEN
|
||||||
|
if (ionToken) {
|
||||||
|
Cesium.Ion.defaultAccessToken = ionToken
|
||||||
|
}
|
||||||
|
const mapContainer = ref(null);
|
||||||
|
const viewerRef = ref(null);
|
||||||
|
|
||||||
|
const initCesium = () => {
|
||||||
|
if (!mapContainer.value) return;
|
||||||
|
if (viewerRef.value) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
viewerRef.value = new Cesium.Viewer(mapContainer.value, {
|
||||||
|
// 基本配置
|
||||||
|
timeline: false,
|
||||||
|
animation: false,
|
||||||
|
fullscreenButton: false,
|
||||||
|
vrButton: false,
|
||||||
|
geocoder: false,
|
||||||
|
homeButton: false,
|
||||||
|
infoBox: false,
|
||||||
|
sceneModePicker: true,
|
||||||
|
selectionIndicator: false,
|
||||||
|
shadows: true,
|
||||||
|
shouldAnimate: true,
|
||||||
|
navigationHelpButton: false,
|
||||||
|
imageryProvider: false,
|
||||||
|
baseLayerPicker: false,
|
||||||
|
sceneModePicker: false,
|
||||||
|
|
||||||
|
// 使用高分辨率渲染
|
||||||
|
useBrowserRecommendedResolution: false,
|
||||||
|
maximumScreenSpaceError: 2,
|
||||||
|
|
||||||
|
// 添加基础图层
|
||||||
|
// imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
|
||||||
|
// url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
|
||||||
|
viewerRef.value.cesiumWidget.creditContainer.style.display = 'none'
|
||||||
|
mapStore.destroy()
|
||||||
|
mapStore.init(viewerRef.value)
|
||||||
|
|
||||||
|
loadBaseMap()
|
||||||
|
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error('初始化 Cesium 失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setViewToCoordinates = (longitude, latitude, height) => {
|
||||||
|
if (!viewerRef.value) return
|
||||||
|
viewerRef.value.camera.setView({
|
||||||
|
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
|
||||||
|
orientation: {
|
||||||
|
heading: Cesium.Math.toRadians(0), // 方向角
|
||||||
|
pitch: Cesium.Math.toRadians(-90), // 俯仰角(-90 为垂直向下看)
|
||||||
|
roll: 0 // 翻滚角
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
clearAllEntities()
|
||||||
|
|
||||||
|
// addDeviceMarker(longitude, latitude, 0, {
|
||||||
|
// label: device.value.DName
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 添加设备图标标记
|
||||||
|
// const addDeviceMarker = (longitude, latitude, height = 0, options = {}) => {
|
||||||
|
// if (!viewerRef.value) return null;
|
||||||
|
|
||||||
|
// const entity = viewerRef.value.entities.add({
|
||||||
|
// id: options.id || `device-${Date.now()}`,
|
||||||
|
// position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
|
||||||
|
// billboard: {
|
||||||
|
// image: '/src/assets/images/device.png',
|
||||||
|
// width: 42,
|
||||||
|
// height: 42,
|
||||||
|
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||||
|
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||||
|
// heightReference: options.clampToGround
|
||||||
|
// ? Cesium.HeightReference.CLAMP_TO_GROUND
|
||||||
|
// : Cesium.HeightReference.NONE,
|
||||||
|
// disableDepthTestDistance: Number.POSITIVE_INFINITY, // 始终显示在最上层
|
||||||
|
// color: options.color ? Cesium.Color.fromCssColorString(options.color) : Cesium.Color.WHITE
|
||||||
|
// },
|
||||||
|
// label: options.label ? {
|
||||||
|
// text: options.label,
|
||||||
|
// font: options.font || '14px sans-serif',
|
||||||
|
// fillColor: Cesium.Color.BLACK,
|
||||||
|
// outlineWidth: 0,
|
||||||
|
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||||
|
// verticalOrigin: Cesium.VerticalOrigin.TOP,
|
||||||
|
// pixelOffset: new Cesium.Cartesian2(0, 2),
|
||||||
|
// showBackground: true,
|
||||||
|
// backgroundColor: Cesium.Color.WHITE,
|
||||||
|
// backgroundPadding: new Cesium.Cartesian2(5, 8),
|
||||||
|
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 200000.0) // 距离显示条件
|
||||||
|
// } : undefined
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return entity;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 清除所有设备标记
|
||||||
|
const clearAllEntities = () => {
|
||||||
|
if (!viewerRef.value) return;
|
||||||
|
entityMap = {}
|
||||||
|
// 移除所有实体或只移除设备标记
|
||||||
|
viewerRef.value.entities.removeAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setDevice = (_device) => {
|
||||||
|
device.value = _device
|
||||||
|
const { Lng, Lat } = _device
|
||||||
|
setViewToCoordinates(Lng, Lat, 1600)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载天地图,也就是最基础的图层,如果没有该图层,就只会看到一个蓝色球体
|
||||||
|
async function loadBaseMap() {
|
||||||
|
const { layer } = mapStore.services()
|
||||||
|
try {
|
||||||
|
const currentGroupId = mapStore.getCurrentBaseMapGroupId()
|
||||||
|
console.log('当前底图组ID:', currentGroupId)
|
||||||
|
if (!currentGroupId) return
|
||||||
|
for (const group of mapStore.baseMapGroups) {
|
||||||
|
const groupId = group.Attribute?.rid || group.Rid
|
||||||
|
const visible = groupId === currentGroupId
|
||||||
|
const layers = mapStore.getBaseMapLayersForGroup(groupId)
|
||||||
|
for (const cfg of layers) {
|
||||||
|
await layer.addLayer({
|
||||||
|
id: cfg.id,
|
||||||
|
type: cfg.type,
|
||||||
|
url: cfg.url,
|
||||||
|
options: { visible },
|
||||||
|
meta: cfg.meta
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('底图加载失败', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetchBaseMapLayers()
|
||||||
|
initCesium()
|
||||||
|
})
|
||||||
|
|
||||||
|
const fetchBaseMapLayers = async () => {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
pcatalog: 'DDT'
|
||||||
|
}
|
||||||
|
const res = await getBaseMapLayer(params)
|
||||||
|
|
||||||
|
// const response = await axiosApi('/api/v1/DataDirectory/QueryCatalog', 'GET', {
|
||||||
|
// pcatalog: 'DDT'
|
||||||
|
// })
|
||||||
|
|
||||||
|
// if (!response?.data) {
|
||||||
|
// console.error('获取底图服务失败:无效的响应数据结构。')
|
||||||
|
// return createDefaultResult()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const loadBaseMap = response.data.length > 0 ? response.data : defaultBaseMapLayers
|
||||||
|
// const layerConfigs = processLayerConfigs(collectLayerConfigs(loadBaseMap))
|
||||||
|
|
||||||
|
// return { layerConfigs, rawBaseMapData: loadBaseMap }
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取底图图层时出错:', error)
|
||||||
|
// return createDefaultResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.map-center {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.map-container {
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 6px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
<!-- 遥感监测 -->
|
||||||
|
<template>
|
||||||
|
<div class="remote-monitor">
|
||||||
|
<div class="item-box-list">
|
||||||
|
<template v-for="(item, index) in columnConfig" :key="index">
|
||||||
|
<div class="item-box">
|
||||||
|
<div class="left-side">
|
||||||
|
<img class="icon" />
|
||||||
|
</div>
|
||||||
|
<div class="right-side">
|
||||||
|
<div class="number-label-text">{{ data[item.name] }}</div>
|
||||||
|
<div class="label-text">{{ item['label'] }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const columnConfig = ref([
|
||||||
|
{
|
||||||
|
label: '当月隐患点总数',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '区县确认数',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '派单数',
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
.item-box-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-label-text {}
|
||||||
|
|
||||||
|
.label-text {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div class="section-title">
|
||||||
|
<span class="title-text">{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
const props = defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@use '@/styles/mixins.scss' as *;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
background-image: url("../../assets/img/common-panel-header-bg.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
width: vw(327);
|
||||||
|
height: vw(55);
|
||||||
|
padding-left: vw(40);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: vw(24);
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user