|
|
@@ -8,6 +8,13 @@
|
|
|
<div class="top-title"></div>
|
|
|
<div class="system-title">数字孪生黑林小流域</div>
|
|
|
|
|
|
+ <!-- 顶部功能按钮 -->
|
|
|
+ <div class="top-function-buttons">
|
|
|
+ <div class="function-btn" @click="goToPatrol">巡查</div>
|
|
|
+ <div class="function-btn" @click="goToInspection">巡检</div>
|
|
|
+ <div class="function-btn" @click="goToMeasurement">巡测</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 顶部按钮 -->
|
|
|
<div class="sub-title left-1" @click="goBack">
|
|
|
首页
|
|
|
@@ -24,238 +31,12 @@
|
|
|
|
|
|
<!-- 主要内容区域 -->
|
|
|
<div class="main-content">
|
|
|
- <!-- 左侧面板区域 -->
|
|
|
- <div class="left-sidebar">
|
|
|
- <!-- 左侧数据框容器 -->
|
|
|
- <div class="left-container">
|
|
|
- <!-- 左侧面板1:设备状态 -->
|
|
|
- <div class="data-card station-intro">
|
|
|
- <div class="panel-header">
|
|
|
- <h3>设备状态</h3>
|
|
|
- <span class="more-btn" @click="showDetailModal = true">更多</span>
|
|
|
- </div>
|
|
|
- <div class="panel-content">
|
|
|
- <div class="device-status-section">
|
|
|
- <!-- 顶部状态指标 -->
|
|
|
- <div class="top-status-indicators">
|
|
|
- <div class="status-circle">
|
|
|
- <div class="circle-inner">
|
|
|
- <div class="circle-percentage">100%</div>
|
|
|
- <div class="circle-label">回传</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="status-icon-item">
|
|
|
- <div class="status-icon">🤖</div>
|
|
|
- <div class="status-text">机器人</div>
|
|
|
- <div class="status-state">工作中</div>
|
|
|
- </div>
|
|
|
- <div class="status-icon-item">
|
|
|
- <div class="status-icon">🏢</div>
|
|
|
- <div class="status-text">基站</div>
|
|
|
- <div class="status-state">运行中</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 详细信息 -->
|
|
|
- <div class="device-details">
|
|
|
- <div class="detail-row">
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">名称:</span>
|
|
|
- <span class="detail-value">巡检机器人</span>
|
|
|
- </div>
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">类型:</span>
|
|
|
- <span class="detail-value">智能巡检型</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="detail-row">
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">空调:</span>
|
|
|
- <span class="detail-value">制冷</span>
|
|
|
- </div>
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">网速:</span>
|
|
|
- <span class="detail-value">513.8 kb/s</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="detail-row">
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">电池:</span>
|
|
|
- <span class="detail-value">91%</span>
|
|
|
- </div>
|
|
|
- <div class="detail-item">
|
|
|
- <span class="detail-label">卫星:</span>
|
|
|
- <span class="detail-value">6</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 机器人图片 -->
|
|
|
- <div class="robot-status-container">
|
|
|
- <div class="robot-bg">
|
|
|
- <img src="/src/assets/images/Heilin/机器人.png" alt="巡检机器人" class="robot-image" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 左侧面板 2:视觉巡查 -->
|
|
|
- <div class="data-card video-monitor">
|
|
|
- <div class="panel-header">
|
|
|
- <h3>视觉巡查</h3>
|
|
|
- </div>
|
|
|
- <div class="panel-content">
|
|
|
- <!-- 巡查视角选择 -->
|
|
|
- <div class="view-buttons">
|
|
|
- <div class="sub-title view-btn" @click="selectView('map')">
|
|
|
- 地图
|
|
|
- </div>
|
|
|
- <div class="sub-title view-btn" @click="selectView('robot')">
|
|
|
- 机器人
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 视角显示区域 -->
|
|
|
- <div class="view-display">
|
|
|
- <div class="view-image-wrapper">
|
|
|
- <img v-if="selectedView === 'map'" src="/src/assets/images/Heilin/导航.png" alt="地图视角" class="view-image" />
|
|
|
- <img v-else-if="selectedView === 'robot'" src="/src/assets/images/Heilin/机器人视角.png" alt="机器人视角" class="view-image" />
|
|
|
- <div v-else class="view-placeholder">
|
|
|
- 请选择巡查视角
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 中间空间 -->
|
|
|
- <div class="center-space">
|
|
|
- <div class="poi-container">
|
|
|
- <div class="poi-item" style="left: 512px; top: 704px;">
|
|
|
- <div class="poi-label">巡检机器人</div>
|
|
|
- <img src="/src/assets/images/Heilin/POI.png" alt="POI图标" class="poi-icon" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <!-- 动态加载不同的视图组件 -->
|
|
|
+ <InspectionView v-if="currentMode === 'inspection'" />
|
|
|
+ <PatrolView v-else-if="currentMode === 'patrol'" />
|
|
|
+ <MeasurementView v-else-if="currentMode === 'measurement'" />
|
|
|
+ <InspectionView v-else />
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 右侧面板区域 -->
|
|
|
- <div class="right-sidebar">
|
|
|
- <!-- 右侧数据框容器 -->
|
|
|
- <div class="right-container">
|
|
|
- <!-- 右侧面板 1:任务详情 -->
|
|
|
- <div class="data-card data-card-1">
|
|
|
- <div class="panel-header">
|
|
|
- <h3>任务详情</h3>
|
|
|
- </div>
|
|
|
- <div class="panel-content">
|
|
|
- <div class="task-detail-container">
|
|
|
- <!-- 左侧:图标和文字 -->
|
|
|
- <div class="task-detail-left">
|
|
|
- <div class="task-status">执行中..</div>
|
|
|
- <div class="task-icon">
|
|
|
- <img src="/src/assets/images/Heilin/icon/cap/缆道.png" alt="缆道图标" />
|
|
|
- </div>
|
|
|
- <div class="task-time">开始时间:2026-03-11 10:00</div>
|
|
|
- <div class="task-name">缆道巡检任务</div>
|
|
|
- </div>
|
|
|
- <!-- 右侧:仪表盘 -->
|
|
|
- <div class="task-detail-right">
|
|
|
- <div id="taskGauge" class="gauge-container"></div>
|
|
|
- <div class="task-location">当前位置-水位自己台</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 历史任务表格 -->
|
|
|
- <div class="history-table-header">
|
|
|
- <div class="history-table-col history-id-col">任务编号</div>
|
|
|
- <div class="history-table-col history-area-col">巡检区域</div>
|
|
|
- <div class="history-table-col history-time-col">执行时间</div>
|
|
|
- <div class="history-table-col history-status-col">完成状态</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-container">
|
|
|
- <div class="history-table">
|
|
|
- <div class="history-table-body">
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260310001</div>
|
|
|
- <div class="history-table-col history-area-col">全部区域</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-10 14:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260310002</div>
|
|
|
- <div class="history-table-col history-area-col">测验设备区</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-10 09:30</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260309001</div>
|
|
|
- <div class="history-table-col history-area-col">1号监测断面</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-09 16:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260308001</div>
|
|
|
- <div class="history-table-col history-area-col">汇水区</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-08 11:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260307001</div>
|
|
|
- <div class="history-table-col history-area-col">全部区域</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-07 15:30</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260306001</div>
|
|
|
- <div class="history-table-col history-area-col">测验设备区</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-06 10:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260305001</div>
|
|
|
- <div class="history-table-col history-area-col">1号监测断面</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-05 13:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- <div class="history-table-row">
|
|
|
- <div class="history-table-col history-id-col">T20260304001</div>
|
|
|
- <div class="history-table-col history-area-col">汇水区</div>
|
|
|
- <div class="history-table-col history-time-col">2026-03-04 09:00</div>
|
|
|
- <div class="history-table-col history-status-col">已完成</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 右侧面板 2:测流结果 -->
|
|
|
- <div class="data-card data-card-2">
|
|
|
- <div class="panel-header">
|
|
|
- <h3>测流结果</h3>
|
|
|
- </div>
|
|
|
- <div class="panel-content">
|
|
|
- <!-- 任务选择 -->
|
|
|
- <div class="task-selection">
|
|
|
- <select v-model="selectedTask" class="task-select" @change="updateFlowChart">
|
|
|
- <option value="task1">任务1 - 2026-03-11 08:00</option>
|
|
|
- <option value="task2">任务2 - 2026-03-11 10:30</option>
|
|
|
- <option value="task3">任务3 - 2026-03-11 14:00</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 测流成果图表 -->
|
|
|
- <div class="flow-chart-container">
|
|
|
- <div ref="flowChart" class="flow-chart"></div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
|
|
|
<!-- 渐变装饰层(四周暗角) -->
|
|
|
<GradientOverlay />
|
|
|
@@ -357,34 +138,18 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
+import { ref } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
import GradientOverlay from '../components/gradient-overlay.vue'
|
|
|
-import * as echarts from 'echarts'
|
|
|
+import InspectionView from './InspectionView.vue'
|
|
|
+import PatrolView from './PatrolView.vue'
|
|
|
+import MeasurementView from './MeasurementView.vue'
|
|
|
|
|
|
const router = useRouter()
|
|
|
const showDetailModal = ref(false)
|
|
|
|
|
|
-// 视觉巡查相关变量
|
|
|
-const selectedView = ref('robot')
|
|
|
-const selectView = (view) => {
|
|
|
- selectedView.value = view
|
|
|
-}
|
|
|
-
|
|
|
-// 巡检任务相关变量
|
|
|
-const selectedRoute = ref('route1')
|
|
|
-const taskArea = ref('all')
|
|
|
-const taskFrequency = ref('once')
|
|
|
-const taskItems = ref({
|
|
|
- camera: true,
|
|
|
- flow: true,
|
|
|
- water: true
|
|
|
-})
|
|
|
-
|
|
|
-// 测流结果相关变量
|
|
|
-const selectedTask = ref('task1')
|
|
|
-const flowChart = ref(null)
|
|
|
-let flowChartInstance = null
|
|
|
+// 模式切换相关变量
|
|
|
+const currentMode = ref('inspection') // default, patrol, inspection, measurement
|
|
|
|
|
|
const goBack = () => {
|
|
|
router.push('/')
|
|
|
@@ -402,271 +167,20 @@ const goToHeilinStation = () => {
|
|
|
router.push('/heilin-station')
|
|
|
}
|
|
|
|
|
|
-const closeModal = () => {
|
|
|
- showDetailModal.value = false
|
|
|
+const goToPatrol = () => {
|
|
|
+ currentMode.value = 'patrol'
|
|
|
}
|
|
|
|
|
|
-const issueTask = () => {
|
|
|
- // 这里可以添加任务下达的逻辑
|
|
|
- console.log('下达任务:', {
|
|
|
- area: taskArea.value,
|
|
|
- frequency: taskFrequency.value,
|
|
|
- items: taskItems.value
|
|
|
- })
|
|
|
- // 模拟任务下达成功
|
|
|
- alert('任务下达成功!')
|
|
|
+const goToInspection = () => {
|
|
|
+ currentMode.value = 'inspection'
|
|
|
}
|
|
|
|
|
|
-// 任务选择变化时更新图表
|
|
|
-const updateFlowChart = () => {
|
|
|
- if (flowChartInstance) {
|
|
|
- const option = getFlowChartOption(selectedTask.value)
|
|
|
- flowChartInstance.setOption(option)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 获取测流图表配置
|
|
|
-const getFlowChartOption = (taskId) => {
|
|
|
- // 不同任务的流量数据(虚构的波动较大的数据)
|
|
|
- const flowData = {
|
|
|
- task1: [120, 190, 300, 250, 400, 350, 280, 420, 380, 500, 450, 320],
|
|
|
- task2: [80, 200, 150, 300, 220, 400, 300, 250, 350, 280, 420, 380],
|
|
|
- task3: [150, 250, 200, 350, 280, 450, 320, 300, 400, 350, 480, 420]
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- tooltip: {
|
|
|
- trigger: 'axis',
|
|
|
- axisPointer: {
|
|
|
- type: 'cross',
|
|
|
- label: {
|
|
|
- backgroundColor: '#6a7985'
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- grid: {
|
|
|
- left: '3%',
|
|
|
- right: '4%',
|
|
|
- bottom: '3%',
|
|
|
- containLabel: true
|
|
|
- },
|
|
|
- xAxis: [
|
|
|
- {
|
|
|
- type: 'category',
|
|
|
- boundaryGap: false,
|
|
|
- data: ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'],
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- color: 'rgba(0, 212, 255, 0.6)'
|
|
|
- }
|
|
|
- },
|
|
|
- axisLabel: {
|
|
|
- color: '#ffffff'
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- yAxis: [
|
|
|
- {
|
|
|
- type: 'value',
|
|
|
- name: '流量 (m³/s)',
|
|
|
- nameTextStyle: {
|
|
|
- color: '#00d5ff'
|
|
|
- },
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- color: 'rgba(0, 212, 255, 0.6)'
|
|
|
- }
|
|
|
- },
|
|
|
- axisLabel: {
|
|
|
- color: '#ffffff'
|
|
|
- },
|
|
|
- splitLine: {
|
|
|
- lineStyle: {
|
|
|
- color: 'rgba(0, 212, 255, 0.2)'
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- series: [
|
|
|
- {
|
|
|
- name: '流量',
|
|
|
- type: 'line',
|
|
|
- stack: 'Total',
|
|
|
- areaStyle: {
|
|
|
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
- { offset: 0, color: 'rgba(0, 212, 255, 0.5)' },
|
|
|
- { offset: 1, color: 'rgba(0, 212, 255, 0.1)' }
|
|
|
- ])
|
|
|
- },
|
|
|
- emphasis: {
|
|
|
- focus: 'series'
|
|
|
- },
|
|
|
- lineStyle: {
|
|
|
- color: '#00d5ff',
|
|
|
- width: 3,
|
|
|
- shadowColor: 'rgba(0, 212, 255, 0.5)',
|
|
|
- shadowBlur: 10
|
|
|
- },
|
|
|
- itemStyle: {
|
|
|
- color: '#00d5ff',
|
|
|
- borderColor: '#ffffff',
|
|
|
- borderWidth: 2
|
|
|
- },
|
|
|
- data: flowData[taskId]
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
+const goToMeasurement = () => {
|
|
|
+ currentMode.value = 'measurement'
|
|
|
}
|
|
|
|
|
|
-// 初始化测流图表
|
|
|
-const initFlowChart = () => {
|
|
|
- if (flowChart.value) {
|
|
|
- // 清理旧实例
|
|
|
- if (flowChartInstance) {
|
|
|
- flowChartInstance.dispose()
|
|
|
- flowChartInstance = null
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化ECharts实例
|
|
|
- flowChartInstance = echarts.init(flowChart.value)
|
|
|
-
|
|
|
- // 设置图表选项
|
|
|
- const option = getFlowChartOption(selectedTask.value)
|
|
|
- flowChartInstance.setOption(option)
|
|
|
-
|
|
|
- // 监听窗口大小变化
|
|
|
- window.addEventListener('resize', () => {
|
|
|
- if (flowChartInstance) {
|
|
|
- flowChartInstance.resize()
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-let taskGaugeChart = null
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- // 页面加载时的初始化逻辑
|
|
|
- console.log('智能巡检页面加载完成')
|
|
|
-
|
|
|
- // 初始化仪表盘
|
|
|
- initTaskGauge()
|
|
|
-
|
|
|
- // 初始化测流图表
|
|
|
- setTimeout(() => {
|
|
|
- initFlowChart()
|
|
|
- }, 100)
|
|
|
-})
|
|
|
-
|
|
|
-onUnmounted(() => {
|
|
|
- // 清理ECharts实例
|
|
|
- if (taskGaugeChart) {
|
|
|
- taskGaugeChart.dispose()
|
|
|
- taskGaugeChart = null
|
|
|
- }
|
|
|
-
|
|
|
- if (flowChartInstance) {
|
|
|
- flowChartInstance.dispose()
|
|
|
- flowChartInstance = null
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-const initTaskGauge = () => {
|
|
|
- // 获取仪表盘容器
|
|
|
- const gaugeContainer = document.getElementById('taskGauge')
|
|
|
- if (gaugeContainer) {
|
|
|
- console.log('Gauge container found:', gaugeContainer)
|
|
|
- console.log('Container width:', gaugeContainer.clientWidth)
|
|
|
- console.log('Container height:', gaugeContainer.clientHeight)
|
|
|
-
|
|
|
- // 确保容器有足够的高度
|
|
|
- if (gaugeContainer.clientHeight === 0) {
|
|
|
- gaugeContainer.style.height = '150px'
|
|
|
- console.log('Set container height to 150px')
|
|
|
- }
|
|
|
-
|
|
|
- // 清理旧实例
|
|
|
- if (taskGaugeChart) {
|
|
|
- taskGaugeChart.dispose()
|
|
|
- taskGaugeChart = null
|
|
|
- }
|
|
|
-
|
|
|
- // 初始化ECharts实例
|
|
|
- taskGaugeChart = echarts.init(gaugeContainer)
|
|
|
- console.log('ECharts instance initialized:', taskGaugeChart)
|
|
|
-
|
|
|
- // 配置仪表盘选项
|
|
|
- const option = {
|
|
|
- series: [
|
|
|
- {
|
|
|
- type: 'gauge',
|
|
|
- startAngle: 180,
|
|
|
- endAngle: 0,
|
|
|
- pointer: {
|
|
|
- show: true
|
|
|
- },
|
|
|
- progress: {
|
|
|
- show: true,
|
|
|
- overlap: false,
|
|
|
- roundCap: true,
|
|
|
- clip: false,
|
|
|
- itemStyle: {
|
|
|
- color: '#00d5ff'
|
|
|
- }
|
|
|
- },
|
|
|
- axisLine: {
|
|
|
- lineStyle: {
|
|
|
- width: 10
|
|
|
- }
|
|
|
- },
|
|
|
- splitLine: {
|
|
|
- show: false
|
|
|
- },
|
|
|
- axisTick: {
|
|
|
- show: false
|
|
|
- },
|
|
|
- axisLabel: {
|
|
|
- show: false
|
|
|
- },
|
|
|
- detail: {
|
|
|
- valueAnimation: true,
|
|
|
- fontSize: 20,
|
|
|
- offsetCenter: [0, '70%'],
|
|
|
- color: '#00d5ff'
|
|
|
- },
|
|
|
- data: [
|
|
|
- {
|
|
|
- value: 75,
|
|
|
- name: '任务进度',
|
|
|
- title: {
|
|
|
- show: true,
|
|
|
- fontSize: 12,
|
|
|
- offsetCenter: [0, '30%'],
|
|
|
- color: '#ffffff'
|
|
|
- }
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
-
|
|
|
- // 设置选项
|
|
|
- taskGaugeChart.setOption(option)
|
|
|
- console.log('Chart option set')
|
|
|
-
|
|
|
- // 立即调整图表大小
|
|
|
- taskGaugeChart.resize()
|
|
|
- console.log('Chart resized')
|
|
|
-
|
|
|
- // 监听窗口大小变化,调整图表大小
|
|
|
- window.addEventListener('resize', () => {
|
|
|
- if (taskGaugeChart) {
|
|
|
- taskGaugeChart.resize()
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- console.error('Gauge container not found!')
|
|
|
- }
|
|
|
+const closeModal = () => {
|
|
|
+ showDetailModal.value = false
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -737,6 +251,47 @@ const initTaskGauge = () => {
|
|
|
pointer-events: none;
|
|
|
}
|
|
|
|
|
|
+/* 顶部功能按钮 */
|
|
|
+.top-function-buttons {
|
|
|
+ position: absolute;
|
|
|
+ top: 90px;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ display: flex;
|
|
|
+ gap: 30px;
|
|
|
+ z-index: 5;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.function-btn {
|
|
|
+ width: 120px;
|
|
|
+ height: 50px;
|
|
|
+ background-image: url('/src/assets/images/顶部小标题.png');
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-position: center;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ padding-top: 8px;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #e0fcff;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.8);
|
|
|
+ cursor: pointer;
|
|
|
+ transition: transform 0.3s ease, opacity 0.3s ease;
|
|
|
+ padding: 8px 0 0 0;
|
|
|
+ margin: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.function-btn:hover {
|
|
|
+ transform: scale(1.05);
|
|
|
+ opacity: 0.9;
|
|
|
+}
|
|
|
+
|
|
|
/* 顶部按钮样式 */
|
|
|
.sub-title {
|
|
|
position: absolute;
|
|
|
@@ -802,7 +357,7 @@ const initTaskGauge = () => {
|
|
|
.left-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 20px;
|
|
|
+ gap: 10px;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
}
|
|
|
@@ -812,13 +367,13 @@ const initTaskGauge = () => {
|
|
|
width: 400px;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 20px;
|
|
|
+ gap: 10px;
|
|
|
}
|
|
|
|
|
|
.right-container {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 20px;
|
|
|
+ gap: 10px;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
}
|
|
|
@@ -884,7 +439,7 @@ const initTaskGauge = () => {
|
|
|
.device-status-section {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 20px;
|
|
|
+ gap: 10px;
|
|
|
}
|
|
|
|
|
|
/* 顶部状态指标 */
|
|
|
@@ -1014,10 +569,8 @@ const initTaskGauge = () => {
|
|
|
}
|
|
|
|
|
|
.robot-image {
|
|
|
- width: 200px;
|
|
|
- height: 200px;
|
|
|
- object-fit: contain;
|
|
|
- opacity: 0.9;
|
|
|
+ width: 180px;
|
|
|
+ height: 180px;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
|
|
|
@@ -1603,6 +1156,311 @@ const initTaskGauge = () => {
|
|
|
background: rgba(0, 212, 255, 0.8);
|
|
|
}
|
|
|
|
|
|
+/* 状态颜色编码 */
|
|
|
+.status-normal {
|
|
|
+ color: #00ff88;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 255, 136, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.status-warning {
|
|
|
+ color: #ffaa00;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 170, 0, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.status-abnormal {
|
|
|
+ color: #ff4444;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 68, 68, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+/* 巡查路线信息样式 */
|
|
|
+.route-info {
|
|
|
+ margin-top: 10px;
|
|
|
+ padding: 10px;
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.route-item {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.route-label {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #00d5ff;
|
|
|
+ margin-right: 10px;
|
|
|
+ min-width: 40px;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.route-value {
|
|
|
+ color: #ffffff;
|
|
|
+ flex: 1;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 255, 255, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+/* 巡查路线卡片样式 */
|
|
|
+.route-card {
|
|
|
+ margin-top: 10px;
|
|
|
+ padding: 10px;
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 6px;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.route-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.route-info-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 5px;
|
|
|
+ font-size: 13px;
|
|
|
+}
|
|
|
+
|
|
|
+.route-info-label {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #00d5ff;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.route-info-value {
|
|
|
+ color: #ffffff;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 255, 255, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+.route-path {
|
|
|
+ margin-top: 8px;
|
|
|
+ padding-top: 8px;
|
|
|
+ border-top: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+.route-path-label {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #00d5ff;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.route-path-value {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: bold;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+/* 环境卡片样式 */
|
|
|
+.environment-cards {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.env-card {
|
|
|
+ flex: 1;
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 10px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.env-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #00d5ff;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.env-value {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #00ff88;
|
|
|
+ text-shadow: 0 0 8px rgba(0, 255, 136, 0.8);
|
|
|
+}
|
|
|
+
|
|
|
+/* 告警容器样式 */
|
|
|
+.alerts-container {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.alerts-scroll {
|
|
|
+ max-height: 120px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.alerts-scroll::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.alerts-scroll::-webkit-scrollbar-track {
|
|
|
+ background: rgba(0, 20, 40, 0.3);
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.alerts-scroll::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(0, 212, 255, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.alerts-scroll::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: rgba(0, 212, 255, 0.8);
|
|
|
+}
|
|
|
+
|
|
|
+/* 巡检概况样式 */
|
|
|
+.inspection-overview {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.overview-stats {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 10px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-item {
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 10px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #00d5ff;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.stat-value {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.key-areas-status h4,
|
|
|
+.recognition-results h4,
|
|
|
+.latest-alerts h4 {
|
|
|
+ color: #00d5ff;
|
|
|
+ font-size: 14px;
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.key-areas-status h4::before,
|
|
|
+.recognition-results h4::before,
|
|
|
+.latest-alerts h4::before {
|
|
|
+ content: '●';
|
|
|
+ font-size: 10px;
|
|
|
+ color: #00d5ff;
|
|
|
+ animation: pulse 2s infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.area-status-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.area-status-item {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px;
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.area-name {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 13px;
|
|
|
+}
|
|
|
+
|
|
|
+.area-status {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+/* 实时识别与告警样式 */
|
|
|
+.real-time-results {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.recognition-results {
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.result-item {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px;
|
|
|
+ background: linear-gradient(135deg, rgba(0, 20, 40, 0.6), rgba(0, 10, 20, 0.6));
|
|
|
+ border: 1px solid rgba(0, 212, 255, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.result-label {
|
|
|
+ color: #00d5ff;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: bold;
|
|
|
+ text-shadow: 0 0 5px rgba(0, 212, 255, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.result-value {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 13px;
|
|
|
+}
|
|
|
+
|
|
|
+.latest-alerts {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.alert-item {
|
|
|
+ background: linear-gradient(135deg, rgba(40, 0, 0, 0.6), rgba(20, 0, 0, 0.6));
|
|
|
+ border: 1px solid rgba(255, 68, 68, 0.3);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 10px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ border-left: 3px solid #ff4444;
|
|
|
+}
|
|
|
+
|
|
|
+.alert-time {
|
|
|
+ color: #ff4444;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ text-shadow: 0 0 5px rgba(255, 68, 68, 0.5);
|
|
|
+}
|
|
|
+
|
|
|
+.alert-content {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 1.4;
|
|
|
+}
|
|
|
+
|
|
|
/* 中间空间 */
|
|
|
.center-space {
|
|
|
flex: 1;
|