From dfac8531d4ed65183ebffcbc7f88aea16f6ac64b Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Fri, 18 Apr 2025 19:53:09 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard
---
src/page/login/index.vue | 2
src/views/Home/HomeRight/EventOverview.vue | 695 ++++++++++++------------
src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue | 268 ++++++---
src/views/TaskManage/SearchBox.vue | 17
src/const/drc.js | 3
src/api/payload.js | 12
src/components/CurrentTaskDetails/TaskDetailsLeft.vue | 9
src/styles/element-ui.scss | 136 ++++
src/assets/images/home/useEventOperate/point.png | 0
src/components/CurrentTaskDetails/CurrentTaskDetails.vue | 55 +
src/assets/images/home/useEventOperate/point-active.png | 0
src/components/CurrentTaskDetails/RealTimeMap.vue | 45
src/hooks/controlDrone/useManualControl.js | 9
src/views/Home/HomeLeft/OverviewNext.vue | 5
src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue | 117 +++
src/hooks/controlDrone/useMqtt.js | 1
src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue | 59 +
src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue | 29
src/views/TaskManage/components/TaskAlgorithmBusiness.vue | 4
src/components/CurrentTaskDetails/TaskDetailsHead.vue | 176 +++++-
src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue | 6
21 files changed, 1,085 insertions(+), 563 deletions(-)
diff --git a/src/api/payload.js b/src/api/payload.js
index aa4796a..8bc5a14 100644
--- a/src/api/payload.js
+++ b/src/api/payload.js
@@ -44,7 +44,7 @@
// 拍照和录像
export async function callPhotoAndVideoCmd(sn, type) {
return await request({
- url:`/drone-device-core/droneAirport/liveStreamApi/${sn}/payload/photoAndVideoCmd/${type}`,
+ url:`${API_PREFIX}/devices/${sn}/payload/photoAndVideoCmd/${type}`,
method:'get',
})
}
@@ -132,4 +132,14 @@
};
+// 无人机开启ai
+export const getLiveAiLinkApi = (data) => {
+ return request({
+ url:`/drone-device-core/manage/api/v1/live/streams/start/ai`,
+ method: 'post',
+ data,
+ });
+};
+
+
diff --git a/src/assets/images/home/useEventOperate/point-active.png b/src/assets/images/home/useEventOperate/point-active.png
index 3f5c556..c5869c7 100644
--- a/src/assets/images/home/useEventOperate/point-active.png
+++ b/src/assets/images/home/useEventOperate/point-active.png
Binary files differ
diff --git a/src/assets/images/home/useEventOperate/point.png b/src/assets/images/home/useEventOperate/point.png
index b574793..9caf3bd 100644
--- a/src/assets/images/home/useEventOperate/point.png
+++ b/src/assets/images/home/useEventOperate/point.png
Binary files differ
diff --git a/src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue b/src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
similarity index 97%
rename from src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue
rename to src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
index 8ec1d8b..5685ca1 100644
--- a/src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue
+++ b/src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
@@ -3,7 +3,7 @@
<div class="left-img" :data-text="`${attitude_pitch}°`">
<div class="scaleImg">
<p class="scale" :style="{ top: 45 + ScaleTop + 'px' }"></p>
- <img src="../../../assets/images/rightmapidentification.png" />
+ <img src="../../../../assets/images/rightmapidentification.png" />
</div>
</div>
<div class="instrument-center">
@@ -14,13 +14,13 @@
</div>
</div>
<div class="center-show">
- <img src="../../../assets/images/mapidentification.png" />
+ <img src="../../../../assets/images/mapidentification.png" />
</div>
<div class="rotat-btn"></div>
</div>
<div class="right-img" :data-text="`${height}m`">
<div class="ident-arrow">
- <img src="../../../assets/images/leftmapidentification.png" />
+ <img src="../../../../assets/images/leftmapidentification.png" />
<div class="arrow-box" :style="{ bottom: realHeight }">
<div class="arrow"></div>
</div>
diff --git a/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue b/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
index 546ab80..901d30d 100644
--- a/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
+++ b/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
@@ -126,7 +126,7 @@
</div>
</template>
<script setup>
-import ControlComPass from '../ControlComPass/ControlComPass.vue'
+import ControlComPass from '@/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue'
import { KeyCode, useManualControl } from '@/hooks/controlDrone/useManualControl'
import { droneController, exitController, postDrc, returnHome, returnHomeCancel } from '@/api/drc'
import { ElMessage } from 'element-plus'
@@ -144,12 +144,13 @@
RefreshLeft,
RefreshRight,
} from '@element-plus/icons-vue'
-
+import _ from 'lodash'
import BaseControl from '@/components/CurrentTaskDetails/ControlPanel/BaseControl.vue'
import EventBus from '@/event-bus'
import { getPayloadControlApi, ptzControlApi } from '@/api/payload'
const deviceOsdInfo = inject('deviceOsdInfo')
+const host = computed(() => deviceOsdInfo?.value?.data?.host || {})
const taskDetails = inject('taskDetails')
const dockSn = inject('dockSn')
const droneSn = inject('droneSn')
@@ -183,18 +184,106 @@
{ name: '左', key: KeyCode.ARROW_LEFT, operate: 'left', style: { left: '-70%' } },
]
-const list4 = [
- [
- { name: '焦距倍数', value: '0' },
- { name: '俯仰角度', value: '0.0°' },
- { name: '横向角度', value: '0.0°' },
- ],
- [
- { name: '储存', value: '64.5G' },
- { name: '方向', value: '正北' },
- { name: '方向', value: '正北' },
- ],
-]
+const list4 = computed(() => {
+ const { longitude, latitude, height, payloads } = host?.value || {}
+ const { gimbal_pitch } = payloads?.[0] || {} //俯仰角度
+ return [
+ [
+ { name: '焦距倍数', value: '0' },
+ { name: '俯仰角度', value: pitchAngle.value.angle },
+ { name: '横向角度', value: yawAngle.value.angle },
+ ],
+ [
+ { name: '储存', value: '64.5G' },
+ { name: '方向', value: pitchAngle.value.direction },
+ { name: '方向', value: yawAngle.value.direction },
+ ],
+ ]
+})
+const pitchAngle = computed(() => {
+ const { longitude, latitude, height, payloads } = host?.value || {}
+ const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0
+ let direction = ''
+ if (gimbal_pitch > -2 && gimbal_pitch < 2) {
+ direction = '正前'
+ } else if (gimbal_pitch >= 2 && gimbal_pitch < 90) {
+ direction = '斜上'
+ } else if (gimbal_pitch === 90) {
+ direction = '正上'
+ } else if (gimbal_pitch <= -2 && gimbal_pitch > -90) {
+ direction = '斜下'
+ } else if (gimbal_pitch === -90 || gimbal_pitch < -90) {
+ direction = '正下'
+ }
+ return {
+ angle: _.round(gimbal_pitch || 0, 1) + '°',
+ direction,
+ }
+})
+
+const yawAngle = computed(() => {
+ let { longitude, latitude, height, payloads, attitude_head } = host?.value || {}
+ const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0
+ const gimbal_yaw = payloads?.[0]?.gimbal_yaw || 0
+ attitude_head = attitude_head || 0
+ let yaw = ''
+ if (gimbal_yaw > 180) {
+ yaw = gimbal_yaw
+ } else {
+ yaw = gimbal_yaw - attitude_head
+ }
+ let result = 0
+ if (yaw < 0) {
+ result = yaw + 360
+ }
+ if (yaw > 0) {
+ result = yaw
+ }
+ if ((yaw > -2 && yaw < 2) || parseInt(attitude_head) === parseInt(gimbal_yaw)) {
+ result = attitude_head < 0 ? 180 + (180 + attitude_head) : attitude_head
+ }
+ let direction = ''
+ const roundResult = Math.round(result)
+ if (roundResult === 0) {
+ direction = '正北'
+ } else if (roundResult > 0 && roundResult < 45) {
+ direction = '北偏东'
+ } else if (roundResult === 45) {
+ direction = '东北'
+ } else if (roundResult > 45 && roundResult < 90) {
+ direction = '北偏东'
+ } else if (roundResult === 90) {
+ direction = '正东'
+ } else if (roundResult > 90 && roundResult < 135) {
+ direction = '东偏南'
+ } else if (roundResult === 135) {
+ direction = '东南'
+ } else if (roundResult > 135 && roundResult < 180) {
+ direction = '南偏东'
+ } else if (roundResult === 180) {
+ direction = '正南'
+ } else if (roundResult > 180 && roundResult < 225) {
+ direction = '南偏西'
+ } else if (roundResult === 225) {
+ direction = '西南'
+ } else if (roundResult > 225 && roundResult < 270) {
+ direction = '西偏南'
+ } else if (roundResult === 270) {
+ direction = '正西'
+ } else if (roundResult > 270 && roundResult < 315) {
+ direction = '西偏北'
+ } else if (roundResult === 315) {
+ direction = '西北'
+ } else if (roundResult > 315 && roundResult < 360) {
+ direction = '北偏西'
+ } else if (roundResult === 360) {
+ direction = '正北'
+ }
+ return {
+ angle: _.round(result, 1) + '°',
+ direction,
+ }
+})
const deviceTopicInfo = ref({
pubTopic: '',
diff --git a/src/components/CurrentTaskDetails/CurrentTaskDetails.vue b/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
index 1d8f12c..d259b64 100644
--- a/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
+++ b/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -47,21 +47,29 @@
import { ElMessage } from 'element-plus'
import EventBus from '@/event-bus'
import { updateDroneQualityApi } from '@/api/drc'
+import { getLiveAiLinkApi } from '@/api/payload'
+import { CURRENT_CONFIG } from '@/utils/http/config'
const isAutoControl = ref(true)
const lineQuality = ref(1) //1流畅,2标清
provide('isAutoControl', isAutoControl)
provide('lineQuality', lineQuality)
+const taskDetailsViewer = ref(null)
+provide('taskDetailsViewer', taskDetailsViewer)
+
let taskDetails = ref({})
-const deviceOsdInfo = ref({})
provide('taskDetails', taskDetails)
+const deviceOsdInfo = ref({})
provide('deviceOsdInfo', deviceOsdInfo)
const dockSn = computed(() => taskDetails?.value?.device_sns?.[0])
const droneSn = computed(() => deviceOsdInfo?.value?.data?.sn)
provide('dockSn', dockSn)
provide('droneSn', droneSn)
+
+const isAiLive = ref(false)
+provide('isAiLive', isAiLive)
const isShow = defineModel('show')
const props = defineProps(['id'])
@@ -70,19 +78,27 @@
const isMaxMap = ref(false)
let droneWebSocket //WS实例
-// 机巢直播
+const video_id = ref('')
+provide('video_id', video_id)
+
+// 获取机巢直播
const getDeviceLiveUrl = async () => {
const res = await liveStart(dockSn.value, 2)
currentLiveUrl.value = res.data.data.rtcs_url
}
-const video_id = ref('')
+const getAiLiveUrl = ()=>{
+ const res = getLiveAiLinkApi({ original_stream_url: `${CURRENT_CONFIG.rtmpURL}${video_id.value}`, video_id:video_id.value })
+ currentLiveUrl.value = res.data.data.rtcs_url
+ isAiLive.value = true
+}
// 获取无人机直播url
async function getDroneLiveUrl() {
const res = await liveStart(droneSn.value, lineQuality.value)
currentLiveUrl.value = res.data.data.rtcs_url
video_id.value = res.data.data.video_id
+ isAiLive.value = false
}
// 无人机直播画质切换
@@ -113,14 +129,41 @@
})
}
+const dockOsdInfo = ref({})
+provide('dockOsdInfo', dockOsdInfo)
+
+const wsInfo = ref({})
+provide('wsInfo', wsInfo)
// websocket 的消息回调
const messageHandler = result => {
let payload = JSON.parse(result)
+ wsInfo.value[payload.biz_code] = payload
switch (payload.biz_code) {
+ // 无人机
case EBizCode.DeviceOsd: {
deviceOsdInfo.value = payload
setCurrentLiveUrl()
- console.log(deviceOsdInfo.value, 'device_osd信息')
+ console.log(payload, 'DeviceOsd--信息')
+ break
+ }
+ // 遥控器
+ case EBizCode.GatewayOsd: {
+ console.log(payload, 'GatewayOsd--信息')
+ break
+ }
+ // 机巢
+ case EBizCode.DockOsd: {
+ console.log(payload, 'DockOsd--信息')
+ break
+ }
+ // PsdkWidgetValues
+ case EBizCode.PsdkWidgetValues: {
+ console.log(payload, 'PsdkWidgetValues--信息')
+ break
+ }
+ // VideoSurveillance
+ case EBizCode.VideoSurveillance: {
+ console.log(payload, 'VideoSurveillance--信息')
break
}
default:
@@ -140,6 +183,8 @@
onMounted(() => {
getTaskDetails()
EventBus.on('CurrentTaskDetails-timeStop', changeLineQuality)
+ EventBus.on('CurrentTaskDetails-getAiLiveUrl', getAiLiveUrl)
+ EventBus.on('CurrentTaskDetails-getDroneLiveUrl', getDroneLiveUrl)
})
onBeforeUnmount(() => {
@@ -147,6 +192,8 @@
deviceOsdInfo.value = {}
droneWebSocket = null
EventBus.off('CurrentTaskDetails-timeStop', changeLineQuality)
+ EventBus.off('CurrentTaskDetails-getAiLiveUrl', getAiLiveUrl)
+ EventBus.off('CurrentTaskDetails-getDroneLiveUrl', getDroneLiveUrl)
})
</script>
diff --git a/src/components/CurrentTaskDetails/RealTimeMap.vue b/src/components/CurrentTaskDetails/RealTimeMap.vue
index 4a63684..c5c01bc 100644
--- a/src/components/CurrentTaskDetails/RealTimeMap.vue
+++ b/src/components/CurrentTaskDetails/RealTimeMap.vue
@@ -26,12 +26,14 @@
tilingScheme: new AmapMercatorTilingScheme(),
credit: 'amap_SL',
})
-let viewer = null
+
+const taskDetailsViewer = inject('taskDetailsViewer')
+
const taskDetails = inject('taskDetails')
const deviceOsdInfo = inject('deviceOsdInfo')
const initMap = () => {
- viewer = new Viewer('currentTaskMap', {
+ taskDetailsViewer.value = new Viewer('currentTaskMap', {
terrain: Terrain.fromWorldTerrain(),
infoBox: false, // 禁用沙箱,解决控制台报错
animation: false, // 左下角的动画仪表盘
@@ -45,17 +47,17 @@
baseLayer: false,
fullscreenButton: false,
})
- const gdLayer = viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
+ const gdLayer = taskDetailsViewer?.value.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
const options = {
bInvertColor: true,
bFilterColor: true,
filterColor: '#4e70a6',
}
// 添加蓝色滤镜
- addBlueFilter(options, viewer, gdLayer)
- viewer.scene.morphTo2D(0)
+ addBlueFilter(options, taskDetailsViewer?.value, gdLayer)
+ taskDetailsViewer?.value.scene.morphTo2D(0)
//设置默认点
- viewer.camera.setView({
+ taskDetailsViewer?.value.camera.setView({
destination: Cartesian3.fromDegrees(115.763819, 28.787374, 5000),
})
}
@@ -66,7 +68,7 @@
return Cartesian3.fromDegrees(Number(lon), Number(lat))
})
// 起点
- viewer.entities.add({
+ taskDetailsViewer?.value.entities.add({
position: positions[0],
billboard: {
image: new Cesium.ConstantProperty(rwqfdImg),
@@ -75,7 +77,7 @@
},
})
// 终点
- viewer.entities.add({
+ taskDetailsViewer?.value.entities.add({
position: positions[positions.length - 1],
billboard: {
image: new Cesium.ConstantProperty(endPointImg),
@@ -85,7 +87,7 @@
},
})
// 路径线
- viewer.entities.add({
+ taskDetailsViewer?.value.entities.add({
polyline: {
width: 4,
positions: positions,
@@ -108,29 +110,28 @@
const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
if (!waylinesXMLObj.Placemark.length) return
const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
- flyVisual(allPoint, viewer)
+ flyVisual(allPoint, taskDetailsViewer?.value)
drawWayline(waylinesXMLObj)
}
const removeMap = () => {
- viewer.entities.removeAll()
- viewer.destroy()
+ taskDetailsViewer?.value.entities.removeAll()
+ taskDetailsViewer?.value.destroy()
}
-
let viewInfoFrustum
// 设置视椎
const setCreateFrustum = () => {
- const deviceInfo = deviceOsdInfo.value?.data?.host
- if (!deviceInfo) return
+ const host = deviceOsdInfo.value?.data?.host
+ if (!host) return
viewInfoFrustum?.clear()
- if ([14, 0].includes(deviceInfo.mode_code)) return
- const attitude_head = 180 + deviceInfo.attitude_head
- const gimbal_pitch = 90 - Number(deviceInfo?.payloads[0]?.gimbal_pitch) || 0
- viewInfoFrustum = new CreateFrustum(viewer, {
+ if ([14, 0].includes(host.mode_code)) return
+ const attitude_head = 180 + host.attitude_head
+ const gimbal_pitch = 90 - Number(host?.payloads[0]?.gimbal_pitch) || 0
+ viewInfoFrustum = new CreateFrustum(taskDetailsViewer?.value, {
position: {
- longitude: deviceInfo.longitude,
- latitude: deviceInfo.latitude,
- altitude: deviceInfo.height,
+ longitude: host.longitude,
+ latitude: host.latitude,
+ altitude: host.height,
},
width: 30,
height: 30,
diff --git a/src/components/CurrentTaskDetails/TaskDetailsHead.vue b/src/components/CurrentTaskDetails/TaskDetailsHead.vue
index 91ed227..19f7ca0 100644
--- a/src/components/CurrentTaskDetails/TaskDetailsHead.vue
+++ b/src/components/CurrentTaskDetails/TaskDetailsHead.vue
@@ -1,17 +1,19 @@
<template>
<div class="detailsHead">
- <div class="droneName">小蓝工业园</div>
+ <div class="droneName" :title="taskDetails.name">{{ taskDetails.name }}</div>
<div class="infoListBox">
<div v-for="item in infoList">
- <div class="infoValue">{{ item.value }}</div>
+ <div class="infoValue" :title="item.value">{{ item.value }}{{ item.unit }}</div>
<div class="infoTitle">{{ item.title }}</div>
</div>
</div>
<div class="controlBtn">
- <el-icon class="refresh"><Refresh /></el-icon>
+ <el-icon class="refresh" @click="refreshLive">
+ <Refresh />
+ </el-icon>
<div class="switchBtn" @click="switchBtn">
- <div :class="{ open: open }">NO</div>
- <div :class="{ open: !open }">OFF</div>
+ <div :class="{ open: !isAiLive }">OFF</div>
+ <div :class="{ open: isAiLive }">ON</div>
</div>
</div>
</div>
@@ -19,26 +21,117 @@
<script setup>
import { Refresh } from '@element-plus/icons-vue'
+import { getFlightStatistics } from '@/api/home/machineNest'
+import _, { throttle } from 'lodash'
+import { getLnglatAltitude, getLnglatDist } from '@/utils/cesium/mapUtil'
+import { fourGQuality, SDRQuality } from '@/const/drc'
+import { ElMessage } from 'element-plus'
+import EventBus from '@/event-bus'
-const open = ref(true)
+const taskDetailsViewer = inject('taskDetailsViewer')
+const wsInfo = inject('wsInfo')
+const dockSn = inject('dockSn')
+const taskDetails = inject('taskDetails')
+const isAiLive = inject('isAiLive')
+const singleTotal = ref({})
+
+// 不要随意更换顺序,有联动
+const infoList = ref([
+ { index: 0, title: '实时真高', value: 0, unit: 'M' },
+ { index: 1, title: '绝对高度', value: 0, unit: 'M' },
+ { index: 2, title: '水平速度', value: 0, unit: 'M/s' },
+ { index: 3, title: '垂直速度', value: 0, unit: 'M/s' },
+ { index: 4, title: '经度', value: 0, unit: '°' },
+ { index: 5, title: '纬度', value: 0, unit: '°' },
+ { index: 6, title: '风速', value: 0, unit: 'M/s' },
+ { index: 7, title: '4G信号', value: 0, unit: '' },
+ { index: 8, title: 'SDR信号', value: 0, unit: '' },
+ { index: 9, title: 'GPS搜星数', value: 0, unit: '' },
+ { index: 10, title: 'RTK搜星数', value: 0, unit: '' },
+ { index: 11, title: '距离机场', value: 0, unit: 'M' },
+ { index: 12, title: '飞行时长', value: 0, unit: '小时' },
+ { index: 13, title: '电池电量', value: 0, unit: '%' },
+])
+
const switchBtn = () => {
- open.value = !open.value
+ if (isAiLive.value) {
+ EventBus.emit('CurrentTaskDetails-getDroneLiveUrl')
+ } else {
+ EventBus.emit('CurrentTaskDetails-getAiLiveUrl')
+ }
}
-const infoList = [
- { title: '实时真高', value: '0' },
- { title: '绝对高度', value: '0' },
- { title: '水平速度', value: '0' },
- { title: '垂直速度', value: '0' },
- { title: '经度', value: '0' },
- { title: '纬度', value: '0' },
- { title: '4G信号', value: '0' },
- { title: 'SDR信号', value: '0' },
- { title: 'GPS搜星数', value: '0' },
- { title: 'RTK搜星数', value: '0' },
- { title: '距离机场', value: '0' },
- { title: '飞行时长', value: '0' },
- { title: '电池电量', value: '0' },
-]
+
+function refreshLive(){
+ EventBus.emit('CurrentTaskDetails-getDroneLiveUrl')
+}
+
+function getFlightStatisticsFun() {
+ if (!dockSn.value) return
+ getFlightStatistics(dockSn.value).then(res => {
+ singleTotal.value = res.data.data
+ })
+}
+
+function getRealTimeReallyHigh() {
+ if (!taskDetailsViewer?.value) return
+ const device_osd_host = wsInfo?.value?.device_osd?.data?.host || {}
+ const { latitude, longitude, height } = device_osd_host
+ if (!latitude) return
+ getLnglatAltitude(longitude, latitude, taskDetailsViewer.value).then(res => {
+ const last = height - res?.height
+ infoList.value[0].value = last ? infoList.value[0].value : _.round(height - res?.height, 1)
+ })
+}
+
+function getHeadInfo() {
+ const device_osd_host = wsInfo?.value?.device_osd?.data?.host || {}
+ const dock_osd_host = wsInfo?.value?.dock_osd?.data?.host || {}
+ const { longitude, latitude, height, horizontal_speed, vertical_speed, wind_speed, battery } = device_osd_host
+ const { longitude: dockLon, latitude: dockLat, wireless_link } = dock_osd_host
+
+ let dist = infoList.value[11].value
+ if (longitude && latitude && dockLon && dockLat) {
+ dist = _.round(getLnglatDist(longitude, latitude, dockLon, dockLat), 0)
+ }
+
+ const newGPSNum = dock_osd_host?.position_state?.gps_number
+ const newRTKNum = dock_osd_host?.position_state?.rtk_number
+ const newFourG = wireless_link?.['4g_quality']
+ const newSdr = wireless_link?.['sdr_quality']
+
+ infoList.value[1].value = _.round(height || 0, 1)
+ infoList.value[2].value = _.round(horizontal_speed || 0, 0)
+ infoList.value[3].value = _.round(vertical_speed || 0, 0)
+ infoList.value[4].value = _.round(longitude || 0, 2)
+ infoList.value[5].value = _.round(latitude || 0, 2)
+ infoList.value[6].value = _.round(wind_speed || 0, 0)
+ if (newFourG !== undefined) infoList.value[7].value = fourGQuality[newFourG]
+ if (newSdr !== undefined) infoList.value[8].value = SDRQuality[newSdr]
+ if (newGPSNum !== undefined) infoList.value[9].value = newGPSNum
+ if (newRTKNum !== undefined) infoList.value[10].value = newRTKNum
+ infoList.value[11].value = dist
+ infoList.value[12].value = _.round(singleTotal.value?.hour_count || 0, 1)
+ infoList.value[13].value = battery?.capacity_percent || 0
+ getRealTimeReallyHigh()
+}
+
+const getHeadInfoThrottle = throttle(getHeadInfo, 1000, { leading: true, trailing: true })
+
+watch(
+ wsInfo,
+ () => {
+ getHeadInfoThrottle()
+ },
+ { immediate: true, deep: true }
+)
+
+watch(
+ dockSn,
+ () => {
+ getFlightStatisticsFun()
+ },
+ { immediate: true }
+)
</script>
<style scoped lang="scss">
@@ -48,7 +141,7 @@
z-index: 5;
width: 100%;
height: 68px;
- background: rgb(0,0,0,.4); /* 半透明背景 */
+ background: rgb(0, 0, 0, 0.4); /* 半透明背景 */
backdrop-filter: blur(5px);
padding: 0 31px;
display: flex;
@@ -67,6 +160,10 @@
color: #ededed;
text-align: center;
line-height: 42px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding: 0 10px;
}
.infoListBox {
@@ -74,21 +171,30 @@
flex: 1;
display: flex;
align-items: center;
- justify-content: space-around;
+ justify-content: space-evenly;
font-family: Segoe UI, Segoe UI;
font-weight: 400;
+ margin-left: 15px;
- .infoValue {
- font-size: 20px;
- color: #ffffff;
- line-height: 15px;
- margin-bottom: 10px;
- }
+ > div {
+ width: 90px;
- .infoTitle {
- font-size: 12px;
- color: #d2e8fa;
- line-height: 15px;
+ .infoValue {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-size: 20px;
+ color: #ffffff;
+ line-height: 18px;
+ margin-bottom: 10px;
+
+ }
+
+ .infoTitle {
+ font-size: 12px;
+ color: #d2e8fa;
+ line-height: 15px;
+ }
}
}
@@ -98,7 +204,7 @@
align-items: center;
justify-content: space-between;
- .refresh{
+ .refresh {
color: white;
font-size: 30px;
cursor: pointer;
diff --git a/src/components/CurrentTaskDetails/TaskDetailsLeft.vue b/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
index 1f80069..0e39eca 100644
--- a/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
+++ b/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
@@ -143,7 +143,7 @@
// 修改相机参数
function cameraParamsChange() {
- const { camera_type, zoom_factor} = cameraParams.value
+ const { camera_type, zoom_factor } = cameraParams.value
cameraParamsChangeApi({
sn: dockSn.value,
...cameraParams.value,
@@ -176,7 +176,7 @@
const msg = isRecording.value ? '停止录像' : '开始录像'
const emitType = isRecording.value ? 'controlPanel-timeStop' : 'controlPanel-timeStart'
- callPhotoAndVideoCmd(droneSn.value, type).then(res => {
+ callPhotoAndVideoCmd(dockSn.value, type).then(res => {
ElMessage.success(msg)
EventBus.emit(emitType)
isRecording.value = !isRecording.value
@@ -185,8 +185,11 @@
// 拍照
function takePictures() {
+ if (isRecording.value) {
+ return ElMessage.warning('请先结束录像')
+ }
// photo拍照,video_start开始录像,video_stop结束录像
- callPhotoAndVideoCmd(droneSn.value, 'photo').then(res => {
+ callPhotoAndVideoCmd(dockSn.value, 'photo').then(res => {
ElMessage.success('拍照成功')
})
}
diff --git a/src/const/drc.js b/src/const/drc.js
index 1c601b5..c4a4ad1 100644
--- a/src/const/drc.js
+++ b/src/const/drc.js
@@ -7,3 +7,6 @@
HSI_INFO_PUSH: 'hsi_info_push', // 避障信息上报
DELAY_TIME_INFO_PUSH: 'delay_info_push', // 图传链路延时信息上报
}
+
+export const fourGQuality = { 0: '无信号', 1: '差', 2: '较差', 3: '一般', 4: '较好', 5: '好' }
+export const SDRQuality = { 0: '无信号', 1: '差', 2: '较差', 3: '一般', 4: '较好', 5: '好' }
diff --git a/src/hooks/controlDrone/useManualControl.js b/src/hooks/controlDrone/useManualControl.js
index 4ccce9f..c21c5c6 100644
--- a/src/hooks/controlDrone/useManualControl.js
+++ b/src/hooks/controlDrone/useManualControl.js
@@ -38,7 +38,7 @@
export function useManualControl(mqttState,deviceTopicInfo, isCurrentFlightController,paramsRef) {
let activeCodeKey = null
let genPortOne = true //是一代机场
- const mqttHooks = useMqtt(mqttState,deviceTopicInfo)
+ let mqttHooks = useMqtt(mqttState,deviceTopicInfo)
let seq = 0
const keysPressed = [
{key: 'KeyQ', value: false},
@@ -281,11 +281,10 @@
{ immediate: true }
)
- onBeforeUnmount(()=>{
- mqttHooks?.d
- })
-
onUnmounted(() => {
+ deviceTopicInfo.subTopic = ''
+ deviceTopicInfo.pubTopic = ''
+ mqttHooks = null
closeKeyboardManualControl()
})
diff --git a/src/hooks/controlDrone/useMqtt.js b/src/hooks/controlDrone/useMqtt.js
index caaff48..8ac4679 100644
--- a/src/hooks/controlDrone/useMqtt.js
+++ b/src/hooks/controlDrone/useMqtt.js
@@ -67,6 +67,7 @@
// 2.发心跳
publishDrcPing(deviceTopicInfo.sn)
} else {
+ console.log('清除pingInterval')
clearInterval(state.heartState.get(deviceTopicInfo.sn)?.pingInterval)
state.heartState.delete(deviceTopicInfo.sn)
heartBeatSeq.value = 0
diff --git a/src/page/login/index.vue b/src/page/login/index.vue
index 426e960..1049488 100644
--- a/src/page/login/index.vue
+++ b/src/page/login/index.vue
@@ -3,7 +3,7 @@
<div class="login-header">
<div class="title">中图智飞低空智能感知网平台</div>
</div>
- <div class="login-left-title">中国图强 智领飞跃</div>
+ <!-- <div class="login-left-title">中国图强 智领飞跃</div> -->
<div class="login-left"></div>
<userLogin v-if="activeName === 'user'"></userLogin>
</div>
diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss
index 878186d..5668e7c 100644
--- a/src/styles/element-ui.scss
+++ b/src/styles/element-ui.scss
@@ -236,9 +236,68 @@
.el-range-separator {
color: #ffffff;
}
+
+
}
+ // 日期下拉框
+.custom-date-picker {
+ background: #012350 !important;
+ border: 1px solid !important;
+ border-radius: 0px 0px 8px 8px;
+ border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
+ /* 修改箭头样式 */
+ .el-popper__arrow {
+ &::before {
+ background: #0d3556 !important;
+ border: 1px solid #0d3556 !important;
+ box-sizing: border-box;
+ }
+ }
+ /* 修改头部背景色 */
+ .custom-date-picker .el-picker-panel__header {
+ background: linear-gradient(180deg, rgba(13, 53, 86, 0.85) 0%, rgba(1, 35, 80, 0.85) 100%) !important;
+ color: #fff !important;
+ }
+ .el-date-table {
+ th {
+ color: #fff !important; /* 星期标题颜色 */
+ }
+ }
+ /* 修改日期单元格悬停/选中状态 */
+ .custom-date-picker .el-date-table td:hover,
+ .custom-date-picker .el-date-table td.current:not(.disabled) {
+ background: rgba(60, 121, 202) !important;
+ color: white !important;
+ }
+ // 头部按钮
+ .el-date-table td.start-date span,
+ .el-date-table td.start-date span,
+ .el-date-table td.end-date span {
+ background-color: #012350 !important;
+ }
+ .el-date-table td.in-range div,
+ .el-date-table td.in-range div:hover,
+ .el-date-table.is-week-mode .el-date-table__row.current div,
+ .el-date-table.is-week-mode .el-date-table__row:hover div {
+ background-color: rgba(60, 121, 202) !important;
+ }
+ .el-picker-panel__icon-btn {
+ color: #fff !important;
+
+ &:hover {
+ color: var(--el-color-primary) !important;
+ }
+
+ .el-icon {
+ &::before {
+ color: inherit !important;
+ }
+ }
+ }
+}
//下拉
+// :teleported="false"
.ztzf-select {
.el-select__wrapper {
background: #012A50;
@@ -254,6 +313,83 @@
color: #ffffff;
}
}
+
+
+ // 下拉框
+ .el-select-dropdown__empty {
+ background: #012A50;
+ border-radius: 0px 0px 8px 8px;
+ border: 1px solid;
+ border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
+ }
+ .el-select-dropdown__list {
+ padding: 0 !important;
+ }
+ .el-select-dropdown {
+ overflow-x: hidden !important;
+
+ .el-select-dropdown__wrap {
+ overflow-x: hidden !important;
+ margin-right: 0 !important;
+ }
+ }
+ .el-select-dropdown__wrap {
+ overflow-x: hidden !important;
+ margin-right: 0 !important;
+ }
+ /* 箭头样式 */
+ .el-popper__arrow::before {
+ background: #0d3556 !important;
+ border: 1px solid #0d3556 !important;
+ }
+ .el-select {
+ --el-select-border-color-hover: rgb(0, 162, 255) !important;
+ /* // 修改下拉框hover的默认样式 */
+ }
+
+ .el-input {
+ --el-border-color: rgb(0, 162, 255);
+ /* // 修改下拉框的边框 */
+ }
+
+ .el-select .el-input__wrapper {
+ background-color: #012350 !important;
+ /* // 外层下拉框背景 */
+ }
+
+ .el-input__wrapper {
+ --el-input-text-color: #012350 !important; /* // 修改外层下拉框的颜色 */
+ }
+
+ .el-select__popper.el-popper {
+ border: rgba(0, 27, 63) !important;
+ /* // 修改内部下拉框的边框颜色 */
+ }
+
+ .el-select-dropdown__wrap {
+ background: linear-gradient(180deg, rgba(13, 53, 86, 0.85) 0%, rgba(1, 35, 80, 0.85) 100%);
+ border-radius: 0px 0px 8px 8px;
+ border: 1px solid;
+ border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
+ /* // 下拉框背景色 */
+ }
+
+ .el-select-dropdown__item {
+ background: rgba(0, 27, 63) !important; /* // 下拉框选项的颜色 */
+ }
+
+ .el-select-dropdown__item {
+ color: white;
+ }
+
+ .el-select-dropdown__item.hover {
+ background-color: rgba(0, 120, 233, 0.63) !important;
+ color: white;
+ }
+ .el-select-dropdown__item.selected {
+ color: #8ac3fd !important;
+ font-weight: 700;
+ }
}
.ztzf-input{
diff --git a/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue b/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
index 9d4161f..502ccc2 100644
--- a/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
+++ b/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
@@ -1,9 +1,15 @@
<template>
<div class="event-overviewdetail-right" :class="{ isMore }">
- <CommonTitle title="事件概况" :style="{width: isMore?pxToRem(820):pxToRem(404)}" />
+ <CommonTitle title="事件概况" :style="{ width: isMore ? pxToRem(820) : pxToRem(404) }" />
<div class="content">
- <img class="leftArrow" :class="isMore?'rightArrow':''" :src="isMore ? rightArrowImg : leftArrowImg" @click="leftArrowFun" alt="" />
+ <img
+ class="leftArrow"
+ :class="isMore ? 'rightArrow' : ''"
+ :src="isMore ? rightArrowImg : leftArrowImg"
+ @click="leftArrowFun"
+ alt=""
+ />
<el-date-picker
class="ztzf-date-picker"
@@ -50,7 +56,7 @@
<img class="statusItemImg" :src="item.img" alt="" />
<div class="statusItemInfo">
<div class="statusItemName">{{ item.name }}</div>
- <div class="statusItemNum" :style="{ color:item.color }">{{ item.num || 0 }}</div>
+ <div class="statusItemNum" :style="{ color: item.color }">{{ item.num || 0 }}</div>
</div>
</div>
</div>
@@ -66,12 +72,7 @@
<div class="eventList">
<div class="eventListItem" v-for="item in list">
- <img
- class="eventListItemImg"
- :src="getSmallImg(item.photo_url)"
- alt=""
- @click="getFindImgHistory(item)"
- />
+ <img class="eventListItemImg" :src="getSmallImg(item.photo_url)" alt="" @click="getFindImgHistory(item)" />
<div class="eventListItemPosition" :title="item.address" @click="positioning(item)">
<img :src="positioningImg" alt="" title="点击定位" />
<!-- <div class="address">{{ item.address }}</div> -->
@@ -96,23 +97,32 @@
</div>
</div>
</div>
- <div class="image-list" v-if="isShowBigImg" :style="{ right: isMore?pxToRem(840):pxToRem(460) }">
+ <div class="image-list" v-if="isShowBigImg" :style="{ right: isMore ? pxToRem(838) : pxToRem(460) }">
<div class="title">
- <img @click="isShowBigImg=false" src="@/assets/images/home/useEventOperate/close.png" alt="">
+ <img @click="isShowBigImg = false" src="@/assets/images/home/useEventOperate/close.png" alt="" />
</div>
<div class="content">
- <img :src="clickImgSrc" alt="">
+ <img :src="clickImgSrc" alt="" />
</div>
<div class="card">
- <div v-for="(item,index) in imageList">
- <div class="time-top" :class="index===selectedImgIndex?'active':''" @click="clickWeekTime(item,index)">{{ item.create_time_str }}</div>
- <div class="time-point">
- <img v-if="index===selectedImgIndex" src="@/assets/images/home/useEventOperate/point-active.png" alt="">
- <img v-else src="@/assets/images/home/useEventOperate/point.png" alt="">
+ <div class="card-content">
+ <div v-for="(item, index) in imageList">
+ <div class="time-top" :class="index === selectedImgIndex ? 'active' : ''" @click="clickWeekTime(item, index)">
+ {{ item.create_time_str }}
+ </div>
+ <div class="time-point">
+ <img
+ class="active"
+ v-if="index === selectedImgIndex"
+ src="@/assets/images/home/useEventOperate/point-active.png"
+ alt=""
+ />
+ <img v-else src="@/assets/images/home/useEventOperate/point.png" alt="" />
+ </div>
+ <div class="time-bottom">{{ item.create_time }}</div>
</div>
- <div class="time-bottom">{{ item.create_time }}</div>
+ <div class="time-line"></div>
</div>
- <div class="time-line"></div>
</div>
</div>
</template>
@@ -159,7 +169,7 @@
size: 8,
})
-const getSmallImg = (url) => {
+const getSmallImg = url => {
return url ? url.substring(0, url.lastIndexOf('.')) + '_small' + url.substring(url.lastIndexOf('.')) : ''
}
@@ -195,16 +205,16 @@
})
}
const { flyTo } = cesiumOperation()
-const longitudeOffset = ref(0);
+const longitudeOffset = ref(0)
const positioning = row => {
const longitude = Number(row.longitude)
const latitude = Number(row.latitude)
- flyTo({ longitude: longitude, latitude:latitude + 0.0002 }, 1, 1000);
+ flyTo({ longitude: longitude, latitude: latitude + 0.0008 }, 1, 1000)
}
// 事件状态+数量
const statusList = ref([
- { name: '全部状态', img: status0Img, id: undefined,few: true, color: '#FFD509' },
+ { name: '全部状态', img: status0Img, id: undefined, few: true, color: '#FFD509' },
{ name: '待审核', img: status1Img, id: 2, color: '#8CFEA7' },
{ name: '待处理', img: status2Img, id: 0, few: true, color: '#FF7411' },
{ name: '处理中', img: status3Img, id: 3, few: true, color: '#FFC398' },
@@ -241,7 +251,7 @@
params.value.start_date = start_date
params.value.end_date = end_date
// 提交数据,更新聚合
- store.commit('setEventTimeRang', timeArr.value);
+ store.commit('setEventTimeRang', timeArr.value)
// 重置
getEventStatusNumFun()
getEventList()
@@ -263,49 +273,53 @@
}
getEventPage(params.value, pageParams).then(res => {
const resData = res.data.data
- list.value = (resData?.records || [])
+ list.value = resData?.records || []
total.value = resData.total
})
}
const isShowBigImg = ref(false)
-const imageList = ref([]);
-const clickImgSrc = ref('');
-const selectedImgIndex = ref(0);
+const imageList = ref([])
+const clickImgSrc = ref('')
+const selectedImgIndex = ref(0)
// 点击图片放大 显示详细信息
-const getFindImgHistory = (item) => {
+const getFindImgHistory = item => {
// 下半部分隐藏 右侧隐藏
isShowBigImg.value = true
store.commit('setHideBottomIcon', false)
- findImgHistory(item.id).then((res) => {
+ findImgHistory(item.id).then(res => {
if (res.data.code !== 0) return
imageList.value = res.data.data
- clickImgSrc.value = res.data.data[0]?.url;
+ clickImgSrc.value = res.data.data[0]?.url
})
- positioning(item);
+ positioning(item)
}
// 点击周期
-const clickWeekTime = (item,index) => {
+const clickWeekTime = (item, index) => {
clickImgSrc.value = item.url
selectedImgIndex.value = index
}
const getDateRange = unit => {
- if (unit === 'today') {
- return [dayjs().format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')];
- }
- return [dayjs().startOf(unit).format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf(unit).format('YYYY-MM-DD HH:mm:ss')];
-};
+ if (unit === 'today') {
+ return [dayjs().format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]
+ }
+ return [dayjs().startOf(unit).format('YYYY-MM-DD HH:mm:ss'), dayjs().endOf(unit).format('YYYY-MM-DD HH:mm:ss')]
+}
// 监听事件时间范围变化
-watch(() => store.state.home.eventTimeType, (newVal) => {
- timeArr.value = getDateRange(newVal);
- const [start_date, end_date] = getDateRange(newVal);
- params.value.start_date = start_date
- params.value.end_date = end_date
- getEventStatusNumFun()
- getEventList()
- getList()
-}, { immediate: false,deep: true })
+watch(
+ () => store.state.home.eventTimeType,
+ newVal => {
+ timeArr.value = getDateRange(newVal)
+ const [start_date, end_date] = getDateRange(newVal)
+ params.value.start_date = start_date
+ params.value.end_date = end_date
+ getEventStatusNumFun()
+ getEventList()
+ getList()
+ },
+ { immediate: false, deep: true }
+)
onMounted(() => {
getDeviceList()
@@ -340,11 +354,7 @@
.content {
width: 390px;
height: 877px;
- background: linear-gradient(
- 270deg,
- rgba(31, 62, 122, 0) 0%,
- rgba(31, 62, 122, 0.35) 21%,
- #1f3e7a 100%);
+ background: linear-gradient(270deg, rgba(31, 62, 122, 0) 0%, rgba(31, 62, 122, 0.35) 21%, #1f3e7a 100%);
display: flex;
justify-content: space-between;
align-content: start;
@@ -384,7 +394,14 @@
// margin-right: 4px;
&.active {
- background: linear-gradient( 180deg, rgba(19,80,141,0) 0%, rgba(22,56,91,0.48) 48%, #053462 98%, #259DFF 98%, #259DFF 98%);
+ background: linear-gradient(
+ 180deg,
+ rgba(19, 80, 141, 0) 0%,
+ rgba(22, 56, 91, 0.48) 48%,
+ #053462 98%,
+ #259dff 98%,
+ #259dff 98%
+ );
}
.statusItemImg {
@@ -531,30 +548,46 @@
display: flex;
justify-content: center;
}
+
.image-list {
- border: 1px solid red;
position: absolute;
- z-index: 1;
+ top: 148px;
+
right: 460px;
- top: 122px;
- width: 540px;
- height: 420px;
- background: #0F1929;
- // box-shadow: inset 0px -50px 50px 0px rgba(27,148,255,0.13);
- // border-radius: 0px 0px 0px 0px;
- border: 2px solid;
- border-image: linear-gradient(180deg, rgba(81, 168, 255, 0), rgba(48, 111, 202, 1), rgba(255, 255, 255, 1), rgba(27, 148, 255, 1)) 2 2;
+
+ width: 632px;
+ height: 476px;
+ border: solid;
+ background: #0f1929;
+ z-index: 1;
+
+ border: solid 2px transparent;
+ border-radius: 20px;
+ background-image: linear-gradient(#fff, #fff), linear-gradient(180deg, rgba(81, 168, 255, 1), rgba(189, 228, 255, 1));
+ background-origin: border-box;
+ background-clip: content-box, border-box;
+
+ overflow: hidden;
.title {
+ display: flex;
+ align-items: center;
+ justify-content: center;
position: absolute;
text-align: right;
- right: 12px;
- // top: 12px;
+ top: 0;
+ right: 0;
+ width: 45px;
+ height: 44px;
+ background: rgba(0, 0, 0, 0.5);
+ border-radius: 0px 20px 0px 8px;
+
img {
- width: 10px;
- height: 10px;
+ width: 10.55px;
+ height: 10.55px;
cursor: pointer;
}
}
+
.content {
img {
width: 100%;
@@ -562,43 +595,80 @@
border-radius: 10px 10px 10px 10px;
}
}
+
.card {
- background: linear-gradient( 180deg, rgba(13,30,70,0.72) 0%, #142E6B 100%);
- padding: 0px 10px 0px 10px;
- color: #BECBEA;
- display: flex;
- justify-content: space-between;
position: absolute;
bottom: 0px;
width: 100%;
- .time-top {
- width: 50px;
- height: 30px;
- line-height: 30px;
- text-align: center;
- color: #ffffff;
- background: linear-gradient( 180deg, rgba(13,30,70,0.72) 0%, #142E6B 100%);
- border: 1px solid #0054D3;
- cursor: pointer;
- }
- .active {
- background: linear-gradient( 180deg, rgba(13,48,131,0.72) 0%, #023DC8 100%);
- border: 1px solid;
- border-image: linear-gradient(180deg, rgba(0, 84, 211, 1), rgba(146, 186, 245, 1)) 1 1;
- }
- .time-point {
- text-align: center;
- img {
- width: 8px;
- height: 12px;
- }
- }
- .time-line {
+ height: 67px;
+ background: rgba(0, 0, 0, 0.42);
+ border-radius: 0px 0px 20px 20px;
+ padding: 0px 6px 0px 29px;
+
+ color: #d5d5d5;
+ font-size: 14px;
+
+ .card-content {
+ display: flex;
+ justify-content: space-between;
+
position: absolute;
- background: linear-gradient( 82deg, rgba(23,40,79,0) 0%, #576D9F 17%, #576D9F 86%, rgba(23,40,79,0) 100%);
- height: 2px;
- top: 38px;
- width: 100%;
+ left: 29px;
+ width: calc(100% - 29px - 6px);
+ height: 100%;
+
+ & > div {
+ position: relative;
+ }
+
+ .time-top {
+ margin-top: 10px;
+ line-height: 1;
+ text-align: center;
+ cursor: pointer;
+ }
+
+ .active {
+ font-weight: 400;
+ color: #ffffff;
+ }
+
+ .time-point {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: absolute;
+ top: 28px;
+ left: 50%;
+ width: 18px;
+ height: 18px;
+ z-index: 1;
+ transform: translate(-50%, 0);
+
+ img {
+ width: 11.2px;
+ height: 11.2px;
+ }
+
+ img.active {
+ width: 16.89px;
+ height: 16.89px;
+ }
+ }
+
+ .time-bottom {
+ margin-top: 20px;
+ }
+
+ .time-line {
+ position: absolute;
+ top: 35px;
+ width: 100%;
+ width: 595px;
+ border-radius: 0px 0px 0px 0px;
+ border: 1px solid rgba(237, 237, 237, 0.6);
+ z-index: 0;
+ }
}
}
}
diff --git a/src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue b/src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue
index c74eacf..67c4236 100644
--- a/src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue
+++ b/src/views/Home/HomeLeft/InspectionRaskDetails/InspectionRaskDetailsDialog.vue
@@ -20,19 +20,19 @@
<el-input class="ztzf-input" v-model="searchForm.key_word" placeholder="请输入任务/机巢名称" clearable />
</el-form-item>
<el-form-item label="关联算法">
- <el-select class="ztzf-select" v-model="searchForm.ai_types" placeholder="请选择">
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.ai_types" placeholder="请选择">
<el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" />
</el-select>
</el-form-item>
<el-form-item label="任务状态">
- <el-select class="ztzf-select" v-model="searchForm.status" placeholder="请选择" clearable>
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.status" placeholder="请选择" clearable>
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</div>
<div class="search-row">
<el-form-item label="选择机巢">
- <el-select class="ztzf-select" v-model="searchForm.device_sn" placeholder="请选择">
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.device_sn" placeholder="请选择">
<el-option
v-for="item in deviceList"
:label="item.nickname"
@@ -43,6 +43,7 @@
</el-form-item>
<el-form-item>
<el-date-picker
+ popper-class="custom-date-picker"
class="ztzf-date-picker"
v-model="dateRange"
type="daterange"
@@ -88,7 +89,9 @@
? 'finish '
: scope.row.status === 5
? 'fail '
- : ' '">
+ : ' '
+ "
+ >
{{
scope.row.status === 1
? '待执行'
@@ -110,7 +113,11 @@
<span>{{ scope.row.event_number ? scope.row.event_number : '/' }}</span>
</template>
</el-table-column>
- <el-table-column label="操作" width="80"><div class="ztzf-view">查看</div></el-table-column>
+ <el-table-column label="操作" width="80">
+ <template #default="scope">
+ <div class="ztzf-view" @click="viewDetail(scope.row)">查看</div>
+ </template>
+ </el-table-column>
</el-table>
</div>
<!-- 分页 -->
@@ -128,6 +135,18 @@
/>
</div>
</el-dialog>
+ <!-- 当前任务详情 -->
+ <CurrentTaskDetails
+ v-if="isShowCurrentTaskDetails"
+ v-model:show="isShowCurrentTaskDetails"
+ :id="currentTaskDetailsId"
+ />
+ <!-- 历史任务详情 -->
+ <DeviceJobDetails
+ v-if="deviceJobDetailsShow"
+ v-model:show="deviceJobDetailsShow"
+ :wayLineJodInfoId="wayLineJodInfoId"
+ />
</template>
<script setup>
import { pxToRem } from '@/utils/rem'
@@ -135,6 +154,8 @@
import { getDictionary } from '@/api/system/dict'
import { selectDevicePage } from '@/api/home/machineNest'
import { getMultipleDictionary } from '@/api/system/dictbiz'
+import CurrentTaskDetails from '@/components/CurrentTaskDetails/CurrentTaskDetails.vue'
+import DeviceJobDetails from '@/components/DeviceJobDetails/DeviceJobDetails.vue'
const isShowDetailsDialog = defineModel('show')
const dateRange = ref('')
const searchForm = reactive({
@@ -148,7 +169,7 @@
const statusOptions = [
{ label: '待执行', value: 1 },
{ label: '执行中', value: 2 },
- { label: '已完成', value: 3 },
+ { label: '已执行', value: 3 },
{ label: '执行失败', value: 5 },
]
@@ -215,7 +236,6 @@
}
// 获取任务列表
const getJobList = () => {
- // 事件状态:0 =待处理,1=待分拨,2=待处理,3=处理中,4=已完成 5=已完结
jobList(taskDetailParams).then(res => {
if (res.data.code !== 0) return
taskDetailData.value = res.data.data.records
@@ -251,12 +271,35 @@
return 'success-row'
}
}
+// 查看
+const isShowCurrentTaskDetails = ref(false)
+const currentTaskDetailsId = ref(null)
+const deviceJobDetailsShow = ref(false)
+const wayLineJodInfoId = ref(null)
+const viewDetail = row => {
+ if (row.status === 1 || row.status === 2) {
+ currentTaskDetailsId.value = row.id
+ isShowCurrentTaskDetails.value = true
+ }
+ if (row.status === 3 || row.status === 5) {
+ wayLineJodInfoId.value = row.id
+ deviceJobDetailsShow.value = true
+ }
+}
onMounted(() => {
requestDictionary()
getJobList()
getDeviceList()
})
</script>
+<style lang="scss">
+/* 修改日期单元格背景色 */
+.custom-date-picker .el-picker-panel__body {
+ background: #012350 !important;
+ color: #fff !important;
+}
+
+</style>
<style scoped lang="scss">
.search-row {
display: flex;
@@ -331,7 +374,7 @@
}
// 执行中
.distributed {
- color: #FFA768;
+ color: #ffa768;
}
// 已执行
.finish {
diff --git a/src/views/Home/HomeLeft/OverviewNext.vue b/src/views/Home/HomeLeft/OverviewNext.vue
index a1e4e07..5b090e7 100644
--- a/src/views/Home/HomeLeft/OverviewNext.vue
+++ b/src/views/Home/HomeLeft/OverviewNext.vue
@@ -155,11 +155,11 @@
margin-bottom: 13px;
.name {
margin-left: 46px;
+
}
}
.table-body {
height: 190px;
-
overflow: auto;
&::-webkit-scrollbar {
width: 0;
@@ -211,8 +211,7 @@
}
.active {
color: #ffa768;
- background: linear-gradient(90deg, rgba(12, 45, 92, 1) 0%, #154671 50%, rgba(12, 45, 92, 1) 100%),
- linear-gradient(90deg, rgba(12, 45, 92, 1) 0%, rgba(12, 45, 92, 1) 50%, rgba(12, 45, 92, 1) 100%);
+
}
.idle-active {
color: #8effac;
diff --git a/src/views/Home/HomeRight/EventOverview.vue b/src/views/Home/HomeRight/EventOverview.vue
index 5ddff84..d608a20 100644
--- a/src/views/Home/HomeRight/EventOverview.vue
+++ b/src/views/Home/HomeRight/EventOverview.vue
@@ -1,420 +1,415 @@
<template>
- <CommonTitle title="事件概况" @Details="details"/>
- <div :style="{ marginLeft: pxToRem(14) }">
- <div class="eventOverview">
- <div class="overviewData">
- <div class="totalBox">
- <div class="totalNumber">{{ eventTotal }}</div>
- <div class="totalLabel">总事件数</div>
- </div>
- <div class="contentBox">
- <div class="overviewItem" v-for="item in eventTypeList" :key="item.name">
- <div class="itemName"><img :src="item.img" alt="" />{{ item.name }}</div>
- <div class="itemValue" :style="{ color: item.color }">{{ item.value }}</div>
- </div>
- </div>
- </div>
- <CommonDateTime class="dateTime" v-model="timeArr" @change="timeChange" />
+ <CommonTitle title="事件概况" @Details="details" />
+ <div :style="{ marginLeft: pxToRem(14) }">
+ <div class="eventOverview">
+ <div class="overviewData">
+ <div class="totalBox">
+ <div class="totalNumber">{{ eventTotal }}</div>
+ <div class="totalLabel">总事件数</div>
+ </div>
+ <div class="contentBox">
+ <div class="overviewItem" v-for="item in eventTypeList" :key="item.name">
+ <div class="itemName">
+ <img :src="item.img" alt="" />
+ {{ item.name }}
+ </div>
+ <div class="itemValue" :style="{ color: item.color }">{{ item.value }}</div>
+ </div>
+ </div>
+ </div>
+ <CommonDateTime class="dateTime" v-model="timeArr" @change="timeChange" />
- <el-select
- class="homeRightSelect"
- v-model="params.device_sn"
- placeholder="请选择"
- size="large"
- filterable
- :remote-method="remoteMethod"
- remote-show-suffix
- remote
- clearable
- popper-class="uavHomePopper"
- v-select-load:uavHomePopper="scrollEvent"
- @change="selectChange"
- >
- <el-option
- v-for="item in deviceList"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- <div class="completion">
- <img class="completion-left-img" :src="completionLeft" alt="" />
- <div class="completion-text">事件类型完成率情况</div>
- <div class="completion-separator"></div>
- <img class="completion-left-img" :src="completionLeft" alt="" />
- </div>
+ <el-select
+ :teleported="false"
+ class="homeRightSelect ztzf-select"
+ v-model="params.device_sn"
+ placeholder="请选择机巢"
+ size="large"
+ filterable
+ :remote-method="remoteMethod"
+ remote-show-suffix
+ remote
+ clearable
+ popper-class="uavHomePopper"
+ v-select-load:uavHomePopper="scrollEvent"
+ @change="selectChange"
+ >
+ <el-option v-for="item in deviceList" :key="item.value" :label="item.label" :value="item.value" />
+ </el-select>
+ <div class="completion">
+ <img class="completion-left-img" :src="completionLeft" alt="" />
+ <div class="completion-text">事件类型完成率情况</div>
+ <div class="completion-separator"></div>
+ <img class="completion-left-img" :src="completionLeft" alt="" />
+ </div>
- <div class="chart" ref="echartsRef"></div>
- </div>
- </div>
+ <div class="chart" ref="echartsRef"></div>
+ </div>
+ </div>
</template>
<script setup>
-import CommonTitle from '@/components/CommonTitle.vue';
-import overviewImg1 from '@/assets/images/home/homeRight/overview1.png';
-import overviewImg2 from '@/assets/images/home/homeRight/overview2.png';
-import overviewImg3 from '@/assets/images/home/homeRight/overview3.png';
-import overviewImg4 from '@/assets/images/home/homeRight/overview4.png';
-import overviewImg5 from '@/assets/images/home/homeRight/overview5.png';
-import overviewImg6 from '@/assets/images/home/homeRight/overview6.png';
-import completionLeft from '@/assets/images/home/homeRight/completionLeft.png';
-import * as echarts from 'echarts';
-import CommonDateTime from '@/components/CommonDateTime.vue';
-import VSelectLoad from '@/directive/selectLoad';
-import { getJobEventBrokerLine, getJobEventByStatus, getJobEventTotal } from '@/api/home';
-import dayjs from 'dayjs';
-import { selectDevicePage } from '@/api/home/machineNest';
+import CommonTitle from '@/components/CommonTitle.vue'
+import overviewImg1 from '@/assets/images/home/homeRight/overview1.png'
+import overviewImg2 from '@/assets/images/home/homeRight/overview2.png'
+import overviewImg3 from '@/assets/images/home/homeRight/overview3.png'
+import overviewImg4 from '@/assets/images/home/homeRight/overview4.png'
+import overviewImg5 from '@/assets/images/home/homeRight/overview5.png'
+import overviewImg6 from '@/assets/images/home/homeRight/overview6.png'
+import completionLeft from '@/assets/images/home/homeRight/completionLeft.png'
+import * as echarts from 'echarts'
+import CommonDateTime from '@/components/CommonDateTime.vue'
+import VSelectLoad from '@/directive/selectLoad'
+import { getJobEventBrokerLine, getJobEventByStatus, getJobEventTotal } from '@/api/home'
+import dayjs from 'dayjs'
+import { selectDevicePage } from '@/api/home/machineNest'
import { useStore } from 'vuex'
import useEchartsResize from '@/hooks/useEchartsResize'
const echartsOption = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow',
- },
- },
- grid: {
- top: '5%',
- left: 0,
- right: 0,
- bottom: 0,
- containLabel: true,
- },
- xAxis: {
- type: 'category',
- axisLabel: {
- rotate: -45, // 旋转角度
- interval: 0, // 显示所有标签
- color: '#FFFFFF',
- fontFamily: 'Source Han Sans CN, Source Han Sans CN',
- fontWeight: 400,
- fontSize: 10,
- },
- data: [],
- },
- yAxis: [
- {
- type: 'value',
- axisLabel: {
- interval: 0, // 显示所有标签
- color: '#FFFFFF',
- fontFamily: 'Source Han Sans CN, Source Han Sans CN',
- fontWeight: 400,
- fontSize: 10,
- },
- axisLine: {
- lineStyle: {
- color: '#ffffff',
- },
- },
- splitLine: {
- lineStyle: {
- color: 'rgba(255, 255, 255, 0.1)',
- type: 'dashed', // 设置为虚线
- },
- },
- },
- ],
- series: [],
-};
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow',
+ },
+ },
+ grid: {
+ top: '5%',
+ left: 0,
+ right: 0,
+ bottom: 0,
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'category',
+ axisLabel: {
+ rotate: -45, // 旋转角度
+ interval: 0, // 显示所有标签
+ color: '#FFFFFF',
+ fontFamily: 'Source Han Sans CN, Source Han Sans CN',
+ fontWeight: 400,
+ fontSize: 10,
+ },
+ data: [],
+ },
+ yAxis: [
+ {
+ type: 'value',
+ axisLabel: {
+ interval: 0, // 显示所有标签
+ color: '#FFFFFF',
+ fontFamily: 'Source Han Sans CN, Source Han Sans CN',
+ fontWeight: 400,
+ fontSize: 10,
+ },
+ axisLine: {
+ lineStyle: {
+ color: '#ffffff',
+ },
+ },
+ splitLine: {
+ lineStyle: {
+ color: 'rgba(255, 255, 255, 0.1)',
+ type: 'dashed', // 设置为虚线
+ },
+ },
+ },
+ ],
+ series: [],
+}
const eventTypeList = ref([
- { name: '待审核', value: 0, img: overviewImg1, color: '#8CFEA7', status: '2' },
- // { name: '待分拨', value: 0, img: overviewImg2, color: '#6FCAFF', status: '1' },
- { name: '待处理', value: 0, img: overviewImg3, color: '#E36913', status: '0' },
- { name: '处理中', value: 0, img: overviewImg4, color: '#FFC398', status: '3' },
- { name: '已完成', value: 0, img: overviewImg5, color: '#AFD9FB', status: '4' },
- { name: '已完结', value: 0, img: overviewImg6, color: '#11C4FF', status: '5' },
-]);
-const seriesObj = {};
+ { name: '待审核', value: 0, img: overviewImg1, color: '#8CFEA7', status: '2' },
+ // { name: '待分拨', value: 0, img: overviewImg2, color: '#6FCAFF', status: '1' },
+ { name: '待处理', value: 0, img: overviewImg3, color: '#E36913', status: '0' },
+ { name: '处理中', value: 0, img: overviewImg4, color: '#FFC398', status: '3' },
+ { name: '已完成', value: 0, img: overviewImg5, color: '#AFD9FB', status: '4' },
+ { name: '已完结', value: 0, img: overviewImg6, color: '#11C4FF', status: '5' },
+])
+const seriesObj = {}
eventTypeList.value.forEach(item => {
- seriesObj[item.status] = {
- type: 'bar',
- stack: 'Ad',
- emphasis: {
- focus: 'series',
- },
- name: item.name,
- itemStyle: { color: item.color },
- data: [],
- };
-});
-const echartsRef = ref(null);
+ seriesObj[item.status] = {
+ type: 'bar',
+ stack: 'Ad',
+ emphasis: {
+ focus: 'series',
+ },
+ name: item.name,
+ itemStyle: { color: item.color },
+ data: [],
+ }
+})
+const echartsRef = ref(null)
let { chart } = useEchartsResize(echartsRef)
-const deviceList = ref([]);
-const today = dayjs().format('YYYY-MM-DD');
-const timeArr = ref([today, today]);
+const deviceList = ref([])
+const today = dayjs().format('YYYY-MM-DD')
+const timeArr = ref([today, today])
const completionRateSeries = {
- name: '完成率',
- type: 'line',
- itemStyle: {
- color: '#0CEBF7', // 设置颜色
- },
- lineStyle: {
- width: 2, // 线条宽度
- type: 'solid', // 线条类型
- },
- symbol: 'circle', // 数据点符号
- symbolSize: 6, // 数据点符号大小
- emphasis: {
- focus: 'series',
- },
- data: [], // 示例数据,根据实际完成率计算
-};
+ name: '完成率',
+ type: 'line',
+ itemStyle: {
+ color: '#0CEBF7', // 设置颜色
+ },
+ lineStyle: {
+ width: 2, // 线条宽度
+ type: 'solid', // 线条类型
+ },
+ symbol: 'circle', // 数据点符号
+ symbolSize: 6, // 数据点符号大小
+ emphasis: {
+ focus: 'series',
+ },
+ data: [], // 示例数据,根据实际完成率计算
+}
-const eventTotal = ref(0);
-let deviceTotal = 0;
+const eventTotal = ref(0)
+let deviceTotal = 0
const devicePageParams = ref({
- current: 1,
- size: 10,
- total: 0,
- nickname: '',
-});
+ current: 1,
+ size: 10,
+ total: 0,
+ nickname: '',
+})
const params = ref({
- date_enum: 'TODAY',
- device_sn: '',
- end_date: undefined,
- start_date: undefined,
-});
+ date_enum: 'TODAY',
+ device_sn: '',
+ end_date: undefined,
+ start_date: undefined,
+})
const store = useStore()
-const details = () =>{
- store.commit('setFootActiveIndex',1)
- store.commit('setIsEventOverviewDetail',true)
+const details = () => {
+ store.commit('setFootActiveIndex', 1)
+ store.commit('setIsEventOverviewDetail', true)
}
// 远程查询
const remoteMethod = nickname => {
- devicePageParams.value.nickname = nickname;
- devicePageParams.value.current = 1;
- devicePageParams.value.size = 10;
- deviceList.value = [];
- getTableList();
-};
+ devicePageParams.value.nickname = nickname
+ devicePageParams.value.current = 1
+ devicePageParams.value.size = 10
+ deviceList.value = []
+ getTableList()
+}
// 滚动查询
const scrollEvent = () => {
- const { current, size } = devicePageParams.value;
- if (current * size < deviceTotal) {
- devicePageParams.value.current = current + 1;
- getTableList();
- }
-};
+ const { current, size } = devicePageParams.value
+ if (current * size < deviceTotal) {
+ devicePageParams.value.current = current + 1
+ getTableList()
+ }
+}
// 机巢列表数据
const getTableList = async () => {
- const res = await selectDevicePage({ ...devicePageParams.value, type: 1 });
- const arr = res?.data?.data?.records || [];
- deviceList.value = deviceList.value.concat(
- arr.map(item => ({
- value: item.device_sn,
- label: item.nickname,
- }))
- );
- deviceTotal = res?.data?.data?.total || 0;
-};
+ const res = await selectDevicePage({ ...devicePageParams.value, type: 1 })
+ const arr = res?.data?.data?.records || []
+ deviceList.value = deviceList.value.concat(
+ arr.map(item => ({
+ value: item.device_sn,
+ label: item.nickname,
+ }))
+ )
+ deviceTotal = res?.data?.data?.total || 0
+}
// 下拉变化
const selectChange = val => {
- getData();
-};
+ getData()
+}
// 时间变化
const timeChange = (value, date_enum) => {
- params.value = {
- ...params.value,
- date_enum,
- };
- getData();
-};
+ params.value = {
+ ...params.value,
+ date_enum,
+ }
+ getData()
+}
// 获取柱状图数据
const getBarChartData = () => {
- getJobEventBrokerLine(params.value).then(res => {
- const list = res?.data?.data || [];
- echartsOption.xAxis.data = list.map(item => item.name);
+ getJobEventBrokerLine(params.value).then(res => {
+ const list = res?.data?.data || []
+ echartsOption.xAxis.data = list.map(item => item.name)
// 赋值前清空数据
- Object.keys(seriesObj).forEach(key => {seriesObj[key].data = []})
- list.forEach(item => {
- item.data.forEach((item1, index) => {
+ Object.keys(seriesObj).forEach(key => {
+ seriesObj[key].data = []
+ })
+ list.forEach(item => {
+ item.data.forEach((item1, index) => {
if (!seriesObj?.[item1.status]) return
- seriesObj[item1.status].data.push(item1.value);
- });
- });
- completionRateSeries.data = list.map(item => item.rate);
- echartsOption.series = Object.values(seriesObj);
- echartsOption.series.push(completionRateSeries);
- chart.value.setOption(echartsOption);
- });
-};
+ seriesObj[item1.status].data.push(item1.value)
+ })
+ })
+ completionRateSeries.data = list.map(item => item.rate)
+ echartsOption.series = Object.values(seriesObj)
+ echartsOption.series.push(completionRateSeries)
+ chart.value.setOption(echartsOption)
+ })
+}
// 事件类型数据
const getTypeData = () => {
- getJobEventByStatus(params.value).then(res => {
- const resList = res?.data?.data || [];
- resList.forEach(item => {
- eventTypeList.value.forEach(item1 => {
- if (item1.name === item.name) {
- item1.value = item.num;
- }
- });
- });
- });
-};
+ getJobEventByStatus(params.value).then(res => {
+ const resList = res?.data?.data || []
+ resList.forEach(item => {
+ eventTypeList.value.forEach(item1 => {
+ if (item1.name === item.name) {
+ item1.value = item.num
+ }
+ })
+ })
+ })
+}
// 获取事件概括数据
const getData = () => {
- getTypeData();
- getBarChartData();
-};
+ getTypeData()
+ getBarChartData()
+}
onMounted(() => {
- getJobEventTotal().then(res => {
- eventTotal.value = res?.data?.data || 0;
- });
- getData();
- getTableList();
-});
+ getJobEventTotal().then(res => {
+ eventTotal.value = res?.data?.data || 0
+ })
+ getData()
+ getTableList()
+})
</script>
-
<style scoped lang="scss">
.homeRightSelect {
- width: 356px;
+ width: 356px;
- :deep() {
- .el-select__wrapper {
- background: linear-gradient(90deg, #195bad 0%, rgba(25, 91, 173, 0) 100%);
- min-height: 28px;
- height: 28px;
- box-shadow: none;
- border: 1px solid #306fca;
- }
+ :deep() {
+ .el-select__wrapper {
+ background: linear-gradient(90deg, #195bad 0%, rgba(25, 91, 173, 0) 100%);
+ min-height: 28px;
+ height: 28px;
+ box-shadow: none;
+ border: 1px solid #306fca;
+ }
- .el-select__placeholder {
- font-family: Microsoft YaHei, Microsoft YaHei, serif;
- color: #ffffff;
- font-size: 14px;
- }
- }
+ .el-select__placeholder {
+ font-family: Microsoft YaHei, Microsoft YaHei, serif;
+ color: #ffffff;
+ font-size: 14px;
+ }
+ }
}
.eventOverview {
- width: 390px;
- height: 445px;
- background: linear-gradient(
- 270deg,
- #1f3e7a 0%,
- rgba(31, 62, 122, 0.35) 79%,
- rgba(31, 62, 122, 0) 100%
- );
- border-radius: 0px 0px 0px 0px;
- opacity: 0.85;
- margin: 3px 0 0 0;
- padding-top: 15px;
- display: flex;
- flex-direction: column;
- align-items: center;
+ width: 390px;
+ height: 445px;
+ background: linear-gradient(270deg, #1f3e7a 0%, rgba(31, 62, 122, 0.35) 79%, rgba(31, 62, 122, 0) 100%);
+ border-radius: 0px 0px 0px 0px;
+ opacity: 0.85;
+ margin: 3px 0 0 0;
+ padding-top: 15px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
- .dateTime {
- width: 356px;
- margin: 15px 0 8px 0;
- }
+ .dateTime {
+ width: 356px;
+ margin: 15px 0 8px 0;
+ }
- .overviewData {
- width: 360px;
- height: 122px;
- background: url('@/assets/images/home/homeRight/overviewBg.png') no-repeat center / 100% 100%;
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding-left: 11px;
+ .overviewData {
+ width: 360px;
+ height: 122px;
+ background: url('@/assets/images/home/homeRight/overviewBg.png') no-repeat center / 100% 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding-left: 11px;
- .totalBox {
- width: 77px;
+ .totalBox {
+ width: 77px;
- .totalNumber {
- font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
- font-weight: 400;
- font-size: 26px;
- color: #ffffff;
- line-height: 30px;
- text-align: center;
- }
+ .totalNumber {
+ font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
+ font-weight: 400;
+ font-size: 26px;
+ color: #ffffff;
+ line-height: 30px;
+ text-align: center;
+ }
- .totalLabel {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- font-size: 14px;
- color: #ffffff;
- line-height: 20px;
- text-align: center;
- }
- }
+ .totalLabel {
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 400;
+ font-size: 14px;
+ color: #ffffff;
+ line-height: 20px;
+ text-align: center;
+ }
+ }
- .contentBox {
- width: 246px;
- display: flex;
- flex-wrap: wrap;
- gap: 13px 0;
- font-family: Source Han Sans CN, Source Han Sans CN, serif;
- font-weight: 400;
- font-size: 14px;
- color: #ffffff;
- line-height: 14px;
+ .contentBox {
+ width: 246px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 13px 0;
+ font-family: Source Han Sans CN, Source Han Sans CN, serif;
+ font-weight: 400;
+ font-size: 14px;
+ color: #ffffff;
+ line-height: 14px;
- .overviewItem {
- width: calc(100% / 3);
+ .overviewItem {
+ width: calc(100% / 3);
- .itemName {
- display: flex;
- align-items: center;
- margin-bottom: 6px;
+ .itemName {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
- img {
- width: 16px;
- height: 16px;
- }
- }
+ img {
+ width: 16px;
+ height: 16px;
+ }
+ }
- .itemValue {
- font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
- font-weight: 400;
- font-size: 24px;
- line-height: 18px;
- }
- }
- }
- }
+ .itemValue {
+ font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
+ font-weight: 400;
+ font-size: 24px;
+ line-height: 18px;
+ }
+ }
+ }
+ }
- .completion {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 356px;
- height: 23px;
- margin-top: 16px;
+ .completion {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 356px;
+ height: 23px;
+ margin-top: 16px;
- &--left-img {
- width: 16px;
- height: 16px;
- }
+ &--left-img {
+ width: 16px;
+ height: 16px;
+ }
- &-text {
- font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
- font-weight: 400;
- font-size: 18px;
- color: #ffffff;
- line-height: 21px;
- }
+ &-text {
+ font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
+ font-weight: 400;
+ font-size: 18px;
+ color: #ffffff;
+ line-height: 21px;
+ }
- &-separator {
- width: 149px;
- height: 0px;
- border: 1px solid #4ca6ff;
- opacity: 0.2;
- }
- }
+ &-separator {
+ width: 149px;
+ height: 0px;
+ border: 1px solid #4ca6ff;
+ opacity: 0.2;
+ }
+ }
- .chart {
- width: 356px;
- height: 190px;
- }
+ .chart {
+ width: 356px;
+ height: 190px;
+ }
}
</style>
diff --git a/src/views/TaskManage/SearchBox.vue b/src/views/TaskManage/SearchBox.vue
index ceef403..6205201 100644
--- a/src/views/TaskManage/SearchBox.vue
+++ b/src/views/TaskManage/SearchBox.vue
@@ -6,17 +6,18 @@
<el-input class="ztzf-input" v-model="searchForm.key_word" placeholder="请输入任务/机巢名称" clearable />
</el-form-item>
<el-form-item label="行政区划:">
- <el-select class="ztzf-select" v-model="searchForm.area_code" @change="deptChange" placeholder="请选择部门" clearable>
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.area_code" @change="deptChange" placeholder="请选择部门" clearable>
<el-option v-for="item in deptTreeData" :key="item.area_code" :label="item.area_name" :value="item.area_code" />
</el-select>
</el-form-item>
<el-form-item label="所属机巢:">
- <el-select class="ztzf-select" v-model="searchForm.device_sn" placeholder="请选择机巢" clearable>
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.device_sn" placeholder="请选择机巢" clearable>
<el-option v-for="item in machineData" :key="item.device_sn" :label="item.nickname" :value="item.device_sn" />
</el-select>
</el-form-item>
<el-form-item>
<el-date-picker
+ popper-class="custom-date-picker"
class="ztzf-date-picker"
v-model="dateRange"
type="daterange"
@@ -43,12 +44,12 @@
<TaskAlgorithmBusiness :setWidth="186" :showAlgorithm="true" @algorithmChange="algorithmChange"/>
</el-form-item>
<el-form-item label="所属部门:" v-if="isExpand">
- <el-select class="ztzf-select" v-model="searchForm.create_dept" placeholder="请选择部门" clearable>
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.create_dept" placeholder="请选择部门" clearable>
<el-option v-for="item in deptData" :key="item.id" :label="item.deptName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="任务状态:" v-if="isExpand">
- <el-select class="ztzf-select" v-model="searchForm.status" placeholder="请选择状态" clearable>
+ <el-select :teleported="false" class="ztzf-select" v-model="searchForm.status" placeholder="请选择状态" clearable>
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
@@ -208,7 +209,13 @@
handleSearch();
});
</script>
-
+<style lang="scss">
+/* 修改日期单元格背景色 */
+.custom-date-picker .el-picker-panel__body {
+ background: #012350 !important;
+ color: #fff !important;
+}
+</style>
<style lang="scss" scoped>
.search-box-test {
transition: all 0.3s;
diff --git a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
index a4aa8c4..8ed3524 100644
--- a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
@@ -20,10 +20,10 @@
<el-table-column label="任务状态" >
<template #default="scope">
<span :style="{
- color: scope.row.status === 1 ? '#e36913' :
- scope.row.status === 2 ? '#ffc398' :
- scope.row.status === 3 ? '#afd9fb' :
- scope.row.status === 4 ? '#11c4ff' : '8cfea7'
+ color: scope.row.status === 1 ? '#ffe17e' :
+ scope.row.status === 2 ? '#ffa768' :
+ scope.row.status === 3 ? '#8effac' :
+ scope.row.status === 5 ? '#ff8e8e':''
}">
{{ scope.row.status ? getStatusText(scope.row.status) : '' }}
</span>
@@ -59,7 +59,15 @@
<!-- 添加任务 -->
<AddTask v-model:show="isShowAddTask" @refresh="searchClick"/>
<!-- 当前任务详情 -->
- <CurrentTaskDetails v-if="isShowCurrentTaskDetails" v-model:show="isShowCurrentTaskDetails" :id="rowData.id"/>
+ <CurrentTaskDetails
+ v-if="isShowCurrentTaskDetails"
+ v-model:show="isShowCurrentTaskDetails"
+ :id="rowData.id"/>
+ <!-- 历史人物详情 -->
+ <DeviceJobDetails
+ v-if="isShowDeviceJobDetails"
+ v-model:show="isShowDeviceJobDetails"
+ :wayLineJodInfoId="wayLineJodInfoId"/>
</template>
<script setup>
@@ -68,6 +76,7 @@
import CurrentTaskDetails from '@/components/CurrentTaskDetails/CurrentTaskDetails.vue';
import { jobList } from '@/api/home/task';
import { ElMessage } from 'element-plus'
+import DeviceJobDetails from '@/components/DeviceJobDetails/DeviceJobDetails.vue'
const jobListParams = reactive({
current: 1,
@@ -76,6 +85,9 @@
});
const jobListData = ref([]);
const total = ref(0);
+let wayLineJodInfoId = ref('')
+let isShowDeviceJobDetails = ref(false);
+let isShowCurrentTaskDetails = ref(false);
// 获取任务列表
const getJobList = () => {
@@ -90,7 +102,7 @@
const statusMap = {
1: '待执行',
2: '执行中',
- 3: '已完成',
+ 3: '已执行',
4: '已取消',
5: '执行失败'
};
@@ -98,15 +110,16 @@
};
// 查看当前任务详情 如果是一台机则显示详情 如果是多台机则进入集群调度(暂未开发)
-let isShowCurrentTaskDetails = ref(true);
let rowData = ref({});
const handleDetail = (row) => {
if (row.device_sns.length === 1){
+ console.log(row)
if (row.status === 2 || row.status === 1){
rowData.value = row? row : {};
isShowCurrentTaskDetails.value = true;
} else{
- ElMessage.warning('todo 跳历史任务详情')
+ wayLineJodInfoId.value = row.id
+ isShowDeviceJobDetails.value = true
}
}else{
ElMessage.warning('即将跳转到集群调度');
diff --git a/src/views/TaskManage/components/TaskAlgorithmBusiness.vue b/src/views/TaskManage/components/TaskAlgorithmBusiness.vue
index d508c4b..01f1524 100644
--- a/src/views/TaskManage/components/TaskAlgorithmBusiness.vue
+++ b/src/views/TaskManage/components/TaskAlgorithmBusiness.vue
@@ -1,12 +1,12 @@
<!-- 关联算法和综合业务 -->
<template>
<div class="task-algorithm" v-if="showAlgorithm">
- <el-select class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="ai_types" multiple collapse-tags collapse-tags-tooltip placeholder="请选择算法" clearable @change="handleAlgorithmChange">
+ <el-select :teleported="false" class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="ai_types" multiple collapse-tags collapse-tags-tooltip placeholder="请选择算法" clearable @change="handleAlgorithmChange">
<el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" />
</el-select>
</div>
<div class="task-business" v-if="showBusiness">
- <el-select class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="industry_type" placeholder="请选择类型" clearable @change="handleBusinessChange">
+ <el-select :teleported="false" class="ztzf-select" :style="{ width: pxToRem(setWidth) }" v-model="industry_type" placeholder="请选择类型" clearable @change="handleBusinessChange">
<el-option v-for="item in taskBusiness" :key="item.id" :label="item.dictValue" :value="item.dictKey" />
</el-select>
</div>
--
Gitblit v1.9.3