From 4801a4a6f26d62e3c0aa92332805d676ee918db3 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Mon, 14 Apr 2025 17:01:41 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard
---
src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue | 16
src/views/SignMachineNest/MachineRight/MachineMonitor.vue | 2
src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue | 104 +++++++
src/views/Home/RSide.vue | 177 ++++++------
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue | 51 ---
src/views/SignMachineNest/SignMachineNest.vue | 2
src/styles/element-ui.scss | 56 +++
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue | 46 +-
/dev/null | 81 -----
src/utils/cesium/mapUtil.js | 19 +
src/components/LiveVideo.vue | 9
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue | 74 +----
src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue | 175 ++++++++++++
src/views/Home/HomeLeft/components/MachineNestTotal.vue | 2
src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue | 17
src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue | 9
16 files changed, 518 insertions(+), 322 deletions(-)
diff --git a/src/components/LiveVideo.vue b/src/components/LiveVideo.vue
index 77a7c5d..be0c852 100644
--- a/src/components/LiveVideo.vue
+++ b/src/components/LiveVideo.vue
@@ -20,6 +20,7 @@
let liveVideoRef = ref(null);
const play = (url) => {
+ pause();
webrtcPlayer = new window.ZLMRTCClient.Endpoint({
element: liveVideoRef.value, // video 标签
debug: true, // 是否打印日志
@@ -73,6 +74,7 @@
)
};
+// 销毁
const pause = () => {
if (webrtcPlayer) {
webrtcPlayer.close();
@@ -84,7 +86,6 @@
(newValue) => {
if (!newValue) return;
nextTick(() => {
- pause();
play(newValue);
});
},
@@ -92,6 +93,10 @@
immediate: true
}
);
+
+onBeforeUnmount(() => {
+ pause()
+})
onMounted(() => {
if (props.videoUrl) {
@@ -113,4 +118,4 @@
object-fit: cover;
}
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss
index 9358c27..878186d 100644
--- a/src/styles/element-ui.scss
+++ b/src/styles/element-ui.scss
@@ -167,7 +167,7 @@
color: var(--text-color);
}
.el-select__wrapper {
- background-color: transparent;
+ background-color: #021022;
box-shadow: none;
border: var(--border);
}
@@ -270,3 +270,57 @@
}
}
}
+// 弹框-dialog
+.ztzf-dialog {
+
+ background: #0f1929;
+ box-shadow: inset 0px -50px 50px 0px rgba(27, 148, 255, 0.13);
+ border-radius: 20px 0px 0px 0px;
+ border: 2px solid;
+ padding: 0 !important;
+
+ 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;
+ // 头部
+ .el-dialog__header {
+ width: 100%;
+ height: 47px;
+ margin-bottom: 14px;
+ background: url('/src/assets/images/home/homeLeft/inspection-vector.png') no-repeat center;
+ background-size: 100% 100%;
+ font-weight: bold;
+ font-size: 16px;
+ line-height: 47px;
+ }
+ .el-dialog__title {
+ width: 112px;
+ height: 19px;
+ font-family: Segoe UI, Segoe UI;
+ font-weight: bold;
+ font-size: 16px;
+ line-height: 16px;
+ text-shadow: 0px 0px 5px rgba(154, 218, 255, 0.6);
+ text-align: left;
+ font-style: normal;
+ text-transform: none;
+ background: linear-gradient(90deg, #fbfdff 0%, #86d4ff 100%);
+ margin-left: 16px;
+ -webkit-background-clip: text; /* 背景被裁剪成文字的前景色 */
+ -webkit-text-fill-color: transparent; /* 文字填充颜色变透明 */
+ }
+ .el-dialog .el-dialog__header {
+ /* margin: 0px !important; */
+ padding: 0px !important;
+ padding-left: 0px !important;
+ }
+ .el-scrollbar__thumb {
+ background: #13c6ff !important;
+ }
+}
+
diff --git a/src/utils/cesium/mapUtil.js b/src/utils/cesium/mapUtil.js
index 176ecca..73b9fbf 100644
--- a/src/utils/cesium/mapUtil.js
+++ b/src/utils/cesium/mapUtil.js
@@ -347,3 +347,22 @@
return true
}
}
+
+/**
+ * 飞到中心点并且所有点在可视范围
+ * @param lngLatArr
+ * @param viewer
+ * @param rangeMultiple 范围倍数越大飞的越高默认2
+ */
+export function flyVisual(lngLatArr,viewer,rangeMultiple = 2) {
+ if (!Array.isArray(lngLatArr) || lngLatArr.length === 0) return
+ const positions = lngLatArr.map(([lon, lat]) =>
+ Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat))
+ )
+ // 计算包围盒 BoundingSphere(所有点的外接球)
+ const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)
+ viewer.camera.flyToBoundingSphere(boundingSphere, {
+ duration: 0,
+ offset: new Cesium.HeadingPitchRange(0, 0, boundingSphere.radius * rangeMultiple),
+ })
+}
diff --git a/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue b/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
index 0b5fc93..43638a5 100644
--- a/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
+++ b/src/views/Home/EventOverviewDetail/EventOverviewDetailRight.vue
@@ -68,13 +68,7 @@
<div class="eventListItem" v-for="item in list">
<img
class="eventListItemImg"
- :src="
- item.photo_url
- ? item.photo_url.substring(0, item.photo_url.lastIndexOf('.')) +
- '_small' +
- item.photo_url.substring(item.photo_url.lastIndexOf('.'))
- : ''
- "
+ :src="getSmallImg(item.photo_url)"
alt=""
/>
<div class="eventListItemPosition" :title="item.address" @click="positioning(item)">
@@ -138,6 +132,10 @@
current: 1,
size: 8,
})
+
+const getSmallImg = (url) => {
+ return url ? url.substring(0, url.lastIndexOf('.')) + '_small' + url.substring(url.lastIndexOf('.')) : ''
+}
const isMore = ref(false)
const leftArrowFun = () => {
@@ -234,7 +232,7 @@
}
getEventPage(params.value, pageParams).then(res => {
const resData = res.data.data
- list.value = resData?.records || []
+ list.value = (resData?.records || [])
total.value = resData.total
})
}
@@ -280,7 +278,7 @@
.leftArrow {
position: absolute;
- left: 0;
+ left: -11px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
diff --git a/src/views/Home/HomeLeft/components/MachineNestTotal.vue b/src/views/Home/HomeLeft/components/MachineNestTotal.vue
index 9a49e07..7476dee 100644
--- a/src/views/Home/HomeLeft/components/MachineNestTotal.vue
+++ b/src/views/Home/HomeLeft/components/MachineNestTotal.vue
@@ -7,7 +7,7 @@
<div class="name">机巢总数</div>
</div>
<div class="status">
- <div class="item" v-for="(item, index) in listNum">
+ <div class="item" v-for="(item, index) in listNum" >
<div>
<div :style="{ color: item.color }" class="value">{{ item.value }}</div>
<div class="name">{{ item.name }}</div>
diff --git a/src/views/Home/RSide.vue b/src/views/Home/RSide.vue
index 606c3c1..be82d71 100644
--- a/src/views/Home/RSide.vue
+++ b/src/views/Home/RSide.vue
@@ -1,35 +1,33 @@
<template>
- <div class="ai-chat">
- <el-popover
- placement="bottom"
- :visible="visible"
- :width="200"
- trigger="click"
- >
- <template #reference>
- <div class="chat" id="chatID" v-drag:chatID @mousedown="handleMouseDown"
- @mouseup="handleMouseUp"/>
- </template>
- <div>
- 快和我对话吧
- <el-input/>
- </div>
- </el-popover>
- <img class="chat-bottom" src="../../assets/images/chat-bottom.png" alt="">
- </div>
- <div class="r-side">
- <img v-for="(item, index) in images"
- :key="index" :class="item.class"
- :src="activeIndex === index ? item.activeSrc : item.src" alt=""
- @click="activeChange(index)"
- @mouseenter="enterHover(index)"
- @mouseleave="logIndex=3"
- >
- </div>
- <div v-if="logIndex===0" class="r-side-positioning">返回当前位置</div>
- <div v-if="logIndex===1" class="r-side-measuring">量尺</div>
- <div v-if="logIndex===2" class="r-side-layer">切换地图模式</div>
- <MeasuringDistance v-if="activeIndex === 1"/>
+ <div class="ai-chat">
+ <el-popover placement="bottom" :visible="visible" :width="200" trigger="click">
+ <template #reference>
+ <div class="chat" id="chatID" v-drag:chatID @mousedown="handleMouseDown" @mouseup="handleMouseUp" />
+ </template>
+ <div>
+ 快和我对话吧
+ <el-input />
+ </div>
+ </el-popover>
+ <img class="chat-bottom" src="../../assets/images/chat-bottom.png" alt="" />
+ </div>
+ <div class="r-side">
+ <img
+ v-for="(item, index) in images"
+ :key="index"
+ :class="item.class"
+ :src="activeIndex === index ? item.activeSrc : item.src"
+ alt=""
+ @click="activeChange(index)"
+ @mouseenter="enterHover(index)"
+ @mouseleave="logIndex = 3"
+ />
+ </div>
+ <div v-if="logIndex === 0" class="r-side-positioning">返回当前位置</div>
+ <div v-if="logIndex === 1" class="r-side-measuring">量尺</div>
+ <div v-if="logIndex === 2" class="r-side-layer">切换地图模式</div>
+ <MeasuringDistance v-if="activeIndex === 1" />
+
</template>
<script setup>
@@ -43,45 +41,48 @@
import tc1 from '@/assets/images/rSide/tc1.png'
import cesiumOperation from '@/utils/cesium-tsa'
-let logIndex = ref(3);
-const enterHover = (value) => {
- logIndex.value = value;
+let logIndex = ref(3)
+const enterHover = value => {
+ logIndex.value = value
}
const { flyTo } = cesiumOperation()
-const store = useStore();
-const currentAreaPosition = computed(() => store.state.home.currentAreaPosition);
+const store = useStore()
+const currentAreaPosition = computed(() => store.state.home.currentAreaPosition)
-let activeIndex = ref(null);
-const activeChange = (value) => {
- if(value === 0) {
+let activeIndex = ref(null)
+const activeChange = value => {
+ if (value === 0) {
flyTo(currentAreaPosition.value, 0, currentAreaPosition.value.height)
}
- if (value === 1){
- activeIndex.value = activeIndex.value === 1 ? null : value;
+ if (value === 1) {
+ activeIndex.value = activeIndex.value === 1 ? null : value
+ }
+ if (value === 2) {
+ activeIndex.value = activeIndex.value === 2 ? null : value
}
}
-const visible = ref(false);
-let pressStart = 0;
+const visible = ref(false)
+let pressStart = 0
const handleMouseDown = () => {
- pressStart = Date.now(); // 记录按下时间
-};
+ pressStart = Date.now() // 记录按下时间
+}
const handleMouseUp = () => {
- const pressDuration = Date.now() - pressStart; // 计算按下时长
- if (pressDuration < 150) {
- // 如果按下时间小于200ms,认为是点击
- visible.value = !visible.value;
- }
-};
+ const pressDuration = Date.now() - pressStart // 计算按下时长
+ if (pressDuration < 150) {
+ // 如果按下时间小于200ms,认为是点击
+ visible.value = !visible.value
+ }
+}
// 添加: 定义图片数组
const images = [
- { class: 'positioning', src: dw,activeSrc:dw1 },
- { class: 'measuring-scale', src: lc,activeSrc:lc1 },
- { class: 'layer', src: tc,activeSrc:tc1 }
-];
+ { class: 'positioning', src: dw, activeSrc: dw1 },
+ { class: 'measuring-scale', src: lc, activeSrc: lc1 },
+ { class: 'layer', src: tc, activeSrc: tc1 },
+]
</script>
<style scoped lang="scss">
@@ -106,45 +107,47 @@
}
}
.r-side {
- position: absolute;
- bottom: 122px;
- right: 463px;
- cursor: pointer;
- img {
- display: block;
- width: 48px;
- height: 48px;
- }
- .positioning {
- position: relative;
- bottom: 24px;
- }
- .measuring-scale {
- position: relative;
- bottom: 12px;
- }
+ position: absolute;
+ bottom: 122px;
+ right: 463px;
+ cursor: pointer;
+ img {
+ display: block;
+ width: 48px;
+ height: 48px;
+ }
+ .positioning {
+ position: relative;
+ bottom: 24px;
+ }
+ .measuring-scale {
+ position: relative;
+ bottom: 12px;
+ }
}
-.r-side-positioning, .r-side-measuring, .r-side-layer {
- position: absolute;
- right: 514px;
- width: 130px;
- height: 48px;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- font-size: 18px;
- color: #FFFFFF;
- line-height: 48px;
- text-align: center;
- background: url('@/assets/images/cursor.png');
+.r-side-positioning,
+.r-side-measuring,
+.r-side-layer {
+ position: absolute;
+ right: 514px;
+ width: 130px;
+ height: 48px;
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 400;
+ font-size: 18px;
+ color: #ffffff;
+ line-height: 48px;
+ text-align: center;
+ background: url('@/assets/images/cursor.png');
}
.r-side-positioning {
- bottom: 242px;
+ bottom: 242px;
}
.r-side-measuring {
- bottom: 182px;
+ bottom: 182px;
}
.r-side-layer {
- bottom: 122px;
+ bottom: 122px;
}
</style>
diff --git a/src/views/SignMachineNest/MachineRight/MachineMonitor.vue b/src/views/SignMachineNest/MachineRight/MachineMonitor.vue
index d8ca2db..4692c33 100644
--- a/src/views/SignMachineNest/MachineRight/MachineMonitor.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineMonitor.vue
@@ -78,4 +78,4 @@
justify-content: space-between;
padding: 12px 10px 0;
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue
index 62b17e1..e5eb341 100644
--- a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceEvent.vue
@@ -18,28 +18,22 @@
</el-table-column>
<el-table-column prop="id" label="事件编号" />
<el-table-column prop="event_name" label="事件名称" />
- <el-table-column prop="event_name" label="所属单位 " />
- <el-table-column show-overflow-tooltip prop="media_type" label="事件内容" />
+ <el-table-column prop="create_user" label="所属单位 " />
+ <el-table-column show-overflow-tooltip prop="remark" label="事件内容" />
<el-table-column show-overflow-tooltip prop="ai_types" label="关联算法" />
<el-table-column prop="status" label="事件状态">
<template #default="scope">
- <el-tag v-if="scope.row.status === 0" type="info">待处理</el-tag>
- <el-tag v-if="scope.row.status === 1" type="success">待分拨</el-tag>
- <el-tag v-if="scope.row.status === 2" type="warning">待处理</el-tag>
- <el-tag v-if="scope.row.status === 3" type="success">处理中</el-tag>
- <el-tag v-if="scope.row.status === 4" type="success">已完成</el-tag>
- <el-tag v-if="scope.row.status === 5" type="success">已完结</el-tag>
+ <div class="pending" v-if="scope.row.status === 0">待处理</div>
+ <div class="reviewed" v-if="scope.row.status === 2">待审核</div>
+ <div class="processing" v-if="scope.row.status === 3">处理中</div>
+ <div class="done" v-if="scope.row.status === 4">已完成</div>
+ <div class="ended" v-if="scope.row.status === 5">已完结</div>
</template>
</el-table-column>
-
<el-table-column label="操作" width="80">
<template #default="scope">
<div class="ztzf-view" @click="distribution(scope.row)">查看</div>
</template>
- <!-- <template #default="scope" >
- <el-button type="success" link @click="examine(scope.row)">审核</el-button>
- <el-button type="primary" link @click="distribution(scope.row)">查看</el-button>
- </template> -->
</el-table-column>
</el-table>
</div>
@@ -49,7 +43,7 @@
:page-sizes="[10, 20, 30, 50]"
v-model:current-page="sizeParams.current"
v-model:page-size="sizeParams.size"
- layout="prev, pager, next, jumper"
+ layout="prev, pager, next,sizes, jumper"
:total="total"
@change="pageChange"
/>
@@ -145,10 +139,24 @@
background: center center no-repeat none !important;
color: #8eb8ea !important;
}
-
-:deep(.el-tag){
-background: none !important;
-border:none !important
+// 待处理
+.pending{
+color: #FF7411;
}
-
+// 待审核
+.reviewed{
+color: #8CFEA7;
+}
+// 处理中
+.processing{
+color: #FFC398;
+}
+// 已完成
+.done{
+color: #AFD9FB;
+}
+// 已完结
+.ended{
+color: #11C4FF;
+}
</style>
diff --git a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue
index c84fc5e..89a9c0d 100644
--- a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJob.vue
@@ -28,7 +28,6 @@
<el-table-column label="操作" width="80">
<template #default="scope">
<div class="ztzf-view" @click="viewJob(scope.row)">查看</div>
- <!-- <el-button type="warning" link @click="viewJob(scope.row)">查看</el-button> -->
</template>
</el-table-column>
</el-table>
@@ -39,7 +38,7 @@
:page-sizes="[10, 20, 30, 50]"
v-model:current-page="sizeParams.current"
v-model:page-size="sizeParams.size"
- layout=" prev, pager, next, jumper"
+ layout=" prev, pager, next,sizes, jumper"
:total="total"
@change="pageChange"
/>
@@ -96,12 +95,6 @@
getList()
})
</script>
-<style lang="scss">
-.devicejob-container {
- // 表格
-
-}
-</style>
<style scoped lang="scss">
// 标题
.machineTableDetailsTitle {
diff --git a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
index 998cb74..bb9a920 100644
--- a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
@@ -8,44 +8,12 @@
import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz'
import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
import lineImg from '@/assets/images/arrow-right-blue.png'
-import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
import rwqfdImg from '@/assets/images/signMachineNest/rwqfd.png'
import endPointImg from '@/assets/images/EndPointicon.png'
import { addBlueFilter } from '@/utils/cesium/common'
+import { flyVisual } from '@/utils/cesium/mapUtil'
const props = defineProps(['detailsData'])
-
-
-const filterLayer = (options,viewer) => {
- const { bInvertColor, bFilterColor, filterColor } = options
- const color = new Cesium.Color.fromCssColorString(filterColor)
- const filterRGB = [
- Math.round(color.red * 255),
- Math.round(color.green * 255),
- Math.round(color.blue * 255)
- ]
- let fragShader = viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
- for (let i = 0; i < fragShader.length; i++) {
- const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
- let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n'
- if (bInvertColor) {
- strT += `
- color.r = 1.0 - color.r;
- color.g = 1.0 - color.g;
- color.b = 1.0 - color.b;
- `
- }
- if (bFilterColor) {
- strT += `
- color.r = color.r * ${filterRGB[0]}.0/255.0;
- color.g = color.g * ${filterRGB[1]}.0/255.0;
- color.b = color.b * ${filterRGB[2]}.0/255.0;
- `
- }
- fragShader[i] = fragShader[i].replace(strS, strT)
- }
-}
-
const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({
url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
@@ -131,20 +99,6 @@
})
}
-// 飞到中心点
-function flyToPoints(lngLatArr) {
- if (!Array.isArray(lngLatArr) || lngLatArr.length === 0) return
- const positions = lngLatArr.map(([lon, lat]) =>
- Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat))
- )
- // 计算包围盒 BoundingSphere(所有点的外接球)
- const boundingSphere = Cesium.BoundingSphere.fromPoints(positions)
- viewer.camera.flyToBoundingSphere(boundingSphere, {
- duration: 0,
- offset: new Cesium.HeadingPitchRange(0, 0, boundingSphere.radius * 2),
- })
-}
-
// 异步解析kmz文件
const analysis = async url => {
return new Promise(async resolve => {
@@ -160,11 +114,10 @@
const drawLine = async () => {
const res = await Promise.all(props.detailsData.way_lines.map(item => analysis(item.url)))
res.map(item => renderingLine(item))
- console.log(res,'jiexi')
const allPoint = res
.flatMap(item => item.Placemark)
.map(item => item.Point.coordinates.split(','))
- flyToPoints(allPoint)
+ flyVisual(allPoint,viewer)
}
const removeMap = () => {
diff --git a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue
index 2d2e393..f4f104f 100644
--- a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/MachineTableDetails.vue
@@ -1,12 +1,11 @@
<!-- 机巢列表详情 -->
<template>
<el-dialog
- class="machineTableDetails"
+ class="machineTableDetails ztzf-dialog"
v-model="isShowDetails"
:width="pxToRem(1500)"
:close-on-click-modal="false"
:destroy-on-close="true"
-
>
<template #header="{ titleId, titleClass }">
<div class="my-header">
@@ -18,25 +17,28 @@
<div class="machineTableDetailsTitle"><span>详情</span></div>
<div class="infoBox">
<div class="itemBox" v-for="(item, index) in infoList" :key="index">
- <div class="itemTitle">{{ item.name }} : </div>
+ <div class="itemTitle">{{ item.name }} :</div>
+ <div v-if="item.name == '任务成果'" class="missionOutcomes">
+ <span>{{item.value ? item.value :0}}</span>
+ 个
+ </div>
<div
+ v-if="item.name == '机巢状态'"
:class="{
active: item.value === 'WORKING',
freetime: item.value === 'LEISURE',
offine: item.value === 'OFFLINE',
}"
- v-if="item.name == '机巢状态'"
>
{{ item.value === 'OFFLINE' ? '离线中' : item.value === 'WORKING' ? '作业中' : '空闲中' }}
</div>
- <div class="itemValue" v-else> {{ item.value }}</div>
+ <div class="itemValue" v-else>{{ item.value }}</div>
</div>
</div>
</div>
<DeviceJob v-if="isShowDetails" />
<DeviceEvent v-if="isShowDetails" />
</el-dialog>
-
</template>
<script setup>
@@ -68,22 +70,9 @@
<style lang="scss">
.machineTableDetails {
-width: 1270px;
+ width: 1270px;
height: 856px;
- background: #0f1929;
- box-shadow: inset 0px -50px 50px 0px rgba(27, 148, 255, 0.13);
- border-radius: 20px 0px 0px 0px;
- border: 2px solid;
- padding: 0 !important;
- 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;
.el-pagination {
text-align: left;
padding: 20px 20px 0 20px;
@@ -93,46 +82,10 @@
vertical-align: middle;
margin-left: 12px;
}
-
- /* 头部 */
- .el-dialog__header {
- width: 1270px;
- height: 47px;
- margin-bottom: 14px;
- background: url('/src/assets/images/home/homeLeft/inspection-vector.png') no-repeat center;
- background-size: 100% 100%;
- font-weight: bold;
- font-size: 16px;
- line-height: 47px;
- }
-
- .el-dialog .el-dialog__header {
- /* margin: 0px !important; */
- padding: 0px !important;
- padding-left: 0px !important;
- }
- /* 头部 */
- .el-dialog__title {
- width: 112px;
- height: 19px;
- font-family: Segoe UI, Segoe UI;
- font-weight: bold;
- font-size: 16px;
- line-height: 16px;
- text-shadow: 0px 0px 5px rgba(154, 218, 255, 0.6);
- text-align: left;
- font-style: normal;
- text-transform: none;
- background: linear-gradient(90deg, #fbfdff 0%, #86d4ff 100%);
- margin-left: 16px;
- -webkit-background-clip: text; /* 背景被裁剪成文字的前景色 */
- -webkit-text-fill-color: transparent; /* 文字填充颜色变透明 */
- }
}
</style>
<style lang="scss" scoped>
-
.infoBox {
display: flex;
justify-content: space-between;
@@ -144,7 +97,7 @@
display: flex;
align-items: center;
.itemTitle {
- margin-right: 5px;
+ margin-right: 5px;
}
}
@@ -175,6 +128,13 @@
margin-bottom: 8px;
}
}
+.missionOutcomes {
+ span {
+ color: #ffa500;
+ font-size: 14px;
+ font-weight: bold;
+ }
+}
// 离线中
.offine {
width: 53px;
diff --git a/src/views/SignMachineNest/SignMachineNest.vue b/src/views/SignMachineNest/SignMachineNest.vue
index c23ce1d..bfec7ce 100644
--- a/src/views/SignMachineNest/SignMachineNest.vue
+++ b/src/views/SignMachineNest/SignMachineNest.vue
@@ -6,7 +6,7 @@
<script setup>
import MachineLeft from '@/views/SignMachineNest/MachineLeft/MachineLeft.vue'
import MachineRight from '@/views/SignMachineNest/MachineRight/MachineRight.vue';
-import { useConnectWebSocket } from '../../utils/websocket/connect-websocket';
+import { useConnectWebSocket } from '@/utils/websocket/connect-websocket';
import { getWebsocketUrl } from '@/websocket/util/config';
import { EBizCode } from '@/utils/staticData/enums.js';
import { EModeCode } from '@/utils/staticData/device.js';
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue
deleted file mode 100644
index 15f4358..0000000
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-<!--当前任务详情-->
-<template>
- <el-dialog
- modal-class="current-task-details"
- v-model="isShowCurrentTaskDetails"
- title="当前任务详情"
- :width="pxToRem(1500)"
- :close-on-click-modal="false"
- :destroy-on-close="true"
- @opened="handleDialogOpened">
- <div class="content-container">
- <!-- 视频直播 -->
- <div class="video-container">
- <LiveVideo />
- </div>
- <!-- 展示地图 -->
- <div id="CurrentTaskMap" class="map-container"></div>
- </div>
- </el-dialog>
-</template>
-
-<script setup>
-import { pxToRem } from '@/utils/rem';
-import LiveVideo from '@/components/LiveVideo.vue';
-import { liveStart } from '@/api/home/machineNest';
-import { getJobDetails } from '@/api/home/task';
-import cesiumOperation from '@/utils/cesium-tsa';
-import { useStore } from 'vuex';
-
-import { initPointWayline } from './initPointWayline';
-
-const { parsingFiles } = initPointWayline()
-
-const { _init, viewerDestory } = cesiumOperation()
-
-
-const isShowCurrentTaskDetails = defineModel('show');
-const props = defineProps({
- rowData: { // 任务列表row数据
- type: Object,
- default: () => ({})
- }
-});
-
-// 获取直播地址
-const getVideoUrl = () => {
- liveStart(props.rowData.deviceSns).then(res => {
- if (res.data.code !== 0) return;
- airPortUrl.value = res.data.data.rtcs_url;
- });
-};
-
-// 获取任务详情获取航线文件
-const getTaskDetails = () => {
- getJobDetails({ wayLineJobInfoId: props.rowData.id }).then(res => {
- if (res.data.data.way_lines && res.data.data.way_lines.length === 1) {
- // console.log(window.$viewer,'顶顶顶顶')
- parsingFiles(res.data.data.way_lines[0].url, window.$viewer);
- }
- })
-}
-
-const handleDialogOpened = () => {
- nextTick(() => {
- _init('CurrentTaskMap');
- });
-};
-
-// 监听 rowData 变化
-watch(() => props.rowData, (newVal) => {
- if (newVal && Object.keys(newVal).length) {
- // getVideoUrl();
- getTaskDetails();
- }
-}, { deep: true, immediate: true });
-
-onUnmounted(() => {
- viewerDestory();
-});
-
-onMounted(() => {
-});
-</script>
-
-<style lang="scss" scoped>
-.current-task-details {
- display: flex;
- justify-content: space-between;
- .content-container {
- display: flex;
- // gap: 20px;
- height: 600px;
-
- .video-container {
- width: 50%;
- padding-right: 10px;
- }
-
- .map-container {
- width: 50%;
- padding-left: 10px;
- height: 100%;
- }
- }
- #CurrentTaskMap {
- :deep() {
- .cesium-viewer {
- width: 100%;
- height: 100%;
- overflow: hidden;
-
- .cesium-viewer-cesiumWidgetContainer {
- width: 100%;
- height: 100%;
-
- .cesium-widget {
- width: 100%;
- height: 100%;
-
- canvas {
- width: 100%;
- height: 100%;
- }
- }
- }
- }
-
- .cesium-viewer-bottom {
- display: none;
- }
- }
- }
-}
-</style>
\ No newline at end of file
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
new file mode 100644
index 0000000..9c0173f
--- /dev/null
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -0,0 +1,104 @@
+<!--当前任务详情-->
+<template>
+ <el-dialog
+ modal-class="current-task-details"
+ v-model="isShow"
+ title="当前任务详情"
+ :width="pxToRem(1500)"
+ :close-on-click-modal="false"
+ :destroy-on-close="true">
+ <div class="content-container" v-if="isShow">
+ <!-- 视频直播 -->
+ <div class="video-container">
+ <LiveVideo :videoUrl="machineNestUrl"/>
+ </div>
+ <!-- 展示地图 -->
+ <RealTimeMap />
+ </div>
+ </el-dialog>
+</template>
+
+<script setup>
+import { pxToRem } from '@/utils/rem';
+import LiveVideo from '@/components/LiveVideo.vue';
+import { liveStart } from '@/api/home/machineNest';
+import { getJobDetails } from '@/api/home/task';
+
+import RealTimeMap from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue'
+import { getWebsocketUrl } from '@/websocket/util/config'
+import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'
+
+
+const isShow = defineModel('show');
+const props = defineProps({
+ rowData: { // 任务列表row数据
+ type: Object,
+ default: () => ({})
+ }
+});
+let taskDetails = ref({})
+const machineNestUrl = ref('');
+provide('taskDetails', taskDetails);
+
+// 获取机巢直播地址
+const getVideoUrl = (deviceSn) => {
+ liveStart(deviceSn).then(res => {
+ if (res.data.code !== 0) return;
+ machineNestUrl.value = res.data.data.rtcs_url;
+ });
+};
+// 获取任务详情获取航线文件
+const getTaskDetails = () => {
+ getJobDetails({ wayLineJobInfoId: props.rowData.id }).then(res => {
+ taskDetails.value = res.data.data
+ getVideoUrl(taskDetails.value.device_sns[0]);
+ console.log('taskDetails', taskDetails.value)
+ createWsConnect(taskDetails.value.way_lines[0].workspace_id)
+ })
+}
+const messageHandler = (result) => {
+ let payload = JSON.parse(result) // 为了兼容聊天消息
+ console.log('result,6666666', payload)
+}
+let connectWs
+const createWsConnect = (workspaceId) => {
+ let webSocketUrl = getWebsocketUrl() + '&workspace-id=' + workspaceId;
+ // 监听ws 消息
+ connectWs = useConnectWebSocket(messageHandler, webSocketUrl);
+};
+
+
+// 监听 rowData 变化
+watch(isShow, (newVal) => {
+ if (newVal) {
+ getTaskDetails();
+ }else{
+ connectWs?.close();
+ }
+});
+
+onBeforeUnmount(() => {
+ connectWs?.close();
+})
+
+onMounted(() => {
+});
+</script>
+
+<style lang="scss" scoped>
+.current-task-details {
+ display: flex;
+ justify-content: space-between;
+ .content-container {
+ display: flex;
+ // gap: 20px;
+ height: 600px;
+
+ .video-container {
+ width: 50%;
+ padding-right: 10px;
+ }
+ }
+
+}
+</style>
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue
new file mode 100644
index 0000000..f42cfd6
--- /dev/null
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue
@@ -0,0 +1,175 @@
+
+
+<template>
+ <div id="currentTaskMap">
+
+
+ </div>
+</template>
+<script setup>
+
+import * as Cesium from 'cesium'
+import AmapMercatorTilingScheme from '@/utils/cesium/AmapMercatorTilingScheme'
+import { Cartesian3, Terrain, Viewer } from 'cesium'
+import endPointImg from '@/assets/images/EndPointicon.png'
+import startPointImg from '@/assets/images/Startingpointicon.png'
+import { addBlueFilter } from '@/utils/cesium/common'
+import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz'
+import rwqfdImg from '@/assets/images/signMachineNest/rwqfd.png'
+import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
+import lineImg from '@/assets/images/arrow-right-blue.png'
+import { flyVisual } from '@/utils/cesium/mapUtil'
+
+const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({
+ url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
+ layer: 'tdtVecBasicLayer',
+ style: 'default',
+ format: 'image/png',
+ tileMatrixSetID: 'GoogleMapsCompatible',
+ subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
+ maximumLevel: 18,
+ tilingScheme: new AmapMercatorTilingScheme(),
+ credit: 'amap_SL',
+})
+let viewer = null
+const initMap = () => {
+ viewer = new Viewer('currentTaskMap', {
+ terrain: Terrain.fromWorldTerrain(),
+ infoBox: false, // 禁用沙箱,解决控制台报错
+ animation: false, // 左下角的动画仪表盘
+ baseLayerPicker: false, // 右上角的图层选择按钮
+ geocoder: false, // 搜索框
+ homeButton: false, // home按钮
+ sceneModePicker: false, // 模式切换按钮
+ timeline: false, // 底部的时间轴
+ navigationHelpButton: false, // 右上角的帮助按钮,
+ selectionIndicator: false, // 是否显示选择指示器
+ baseLayer: false,
+ fullscreenButton: false,
+ })
+ const gdLayer = viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
+ const options = {
+ bInvertColor: true,
+ bFilterColor: true,
+ filterColor: '#4e70a6'
+ }
+ // 添加蓝色滤镜
+ addBlueFilter(options,viewer,gdLayer)
+ viewer.scene.morphTo2D(0)
+ //设置默认点
+ viewer.camera.setView({
+ destination: Cartesian3.fromDegrees(115.763819, 28.787374,5000),
+ })
+}
+
+
+const drawWayline = lineObj => {
+ const positions = lineObj.Placemark.map(item => {
+ const [lon, lat] = item.Point.coordinates.split(',')
+ return Cartesian3.fromDegrees(Number(lon), Number(lat))
+ })
+ // 起点
+ viewer.entities.add({
+ position: positions[0],
+ billboard: {
+ image: new Cesium.ConstantProperty(rwqfdImg),
+ width: 70,
+ height: 70,
+ },
+ })
+ // 终点
+ viewer.entities.add({
+ position: positions[positions.length-1],
+ billboard: {
+ image: new Cesium.ConstantProperty(endPointImg),
+ width: 30,
+ height: 30,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 底部对齐
+ },
+ })
+ // 路径线
+ viewer.entities.add({
+ polyline: {
+ width: 4,
+ positions: positions,
+ material: new ImageTrailMaterial({
+ color: { alpha: 1, blue: 1, green: 1, red: 1 },
+ speed: 20,
+ image: lineImg,
+ repeat: { x: Math.floor(40), y: 1 },
+ }),
+ clampToGround: false,
+ },
+ })
+}
+
+
+// 解析kmz文件
+const parsingFiles = async (url) => {
+ const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
+ const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
+ const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document'];
+ const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
+ if (!waylinesXMLObj.Placemark.length) return;
+ const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
+ flyVisual(allPoint,viewer)
+ drawWayline(waylinesXMLObj)
+};
+
+const removeMap = () => {
+ viewer.entities.removeAll()
+ viewer.destroy()
+}
+
+const taskDetails = inject('taskDetails')
+
+watch(taskDetails, () => {
+ if (taskDetails.value.way_lines.length){
+ parsingFiles(taskDetails.value.way_lines[0].url)
+ }
+})
+
+onBeforeUnmount(() => {
+ removeMap()
+})
+
+onMounted(() => {
+ nextTick(() => {
+ initMap()
+ })
+})
+
+</script>
+<style scoped lang="scss">
+#currentTaskMap {
+ width: 50%;
+ padding-left: 10px;
+ height: 100%;
+ :deep() {
+ .cesium-viewer {
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+ .cesium-viewer-cesiumWidgetContainer {
+ width: 100%;
+ height: 100%;
+
+ .cesium-widget {
+ width: 100%;
+ height: 100%;
+
+ canvas {
+ width: 100%;
+ height: 100%;
+ }
+ }
+ }
+ }
+
+ .cesium-viewer-bottom {
+ display: none;
+ }
+ }
+}
+</style>
diff --git a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
index 104e7af..da720d5 100644
--- a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
@@ -19,9 +19,9 @@
<el-table-column prop="ai_type_str" label="关联算法" show-overflow-tooltip />
<el-table-column label="任务状态" >
<template #default="scope">
- <span :style="{
- color: scope.row.status === 1 ? '#e36913' :
- scope.row.status === 2 ? '#ffc398' :
+ <span :style="{
+ color: scope.row.status === 1 ? '#e36913' :
+ scope.row.status === 2 ? '#ffc398' :
scope.row.status === 3 ? '#afd9fb' :
scope.row.status === 4 ? '#11c4ff' : '8cfea7'
}">
@@ -65,8 +65,9 @@
<script setup>
import SearchBox from '../SearchBox.vue';
import AddTask from './AddTask.vue';
-import CurrentTaskDetails from './CurrentTaskDetails.vue';
+import CurrentTaskDetails from './CurrentTaskDetails/CurrentTaskDetails.vue';
import { jobList } from '@/api/home/task';
+import { ElMessage } from 'element-plus'
const jobListParams = reactive({
current: 1,
@@ -100,8 +101,12 @@
let isShowCurrentTaskDetails = ref(false);
let rowData = ref({});
const handleDetail = (row) => {
- isShowCurrentTaskDetails.value = true;
- rowData.value = row? row : {};
+ if (row.device_sns.length === 1){
+ isShowCurrentTaskDetails.value = true;
+ rowData.value = row? row : {};
+ }else{
+ ElMessage.warning('即将跳转到集群调度');
+ }
};
// 分页大小改变
diff --git a/src/views/TaskManage/TaskIntermediateContent/initPlanarWayline.js b/src/views/TaskManage/TaskIntermediateContent/initPlanarWayline.js
deleted file mode 100644
index e69de29..0000000
--- a/src/views/TaskManage/TaskIntermediateContent/initPlanarWayline.js
+++ /dev/null
diff --git a/src/views/TaskManage/TaskIntermediateContent/initPointWayline.js b/src/views/TaskManage/TaskIntermediateContent/initPointWayline.js
deleted file mode 100644
index dd007f5..0000000
--- a/src/views/TaskManage/TaskIntermediateContent/initPointWayline.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import * as Cesium from 'cesium';
-import cesiumOperation from '@/utils/cesium-tsa';
-import { analyzeKmzFile, XMLToJSON } from '@/utils/cesium/kmz.js'
-import { cartesian3Convert, getCenterPoint, getLnglatDist } from '@/utils/cesium/mapUtil.js'
-import { getLnglatAltitude, getPositionsHeight } from '@/utils/cesium/mapUtil'
-
-const {
- addPoint,
- getEntityById,
- removeById,
- removeAllPoint,
- addLeftClickEvent,
- removeLeftClickEvent,
- addRightClickEvent,
- removeRightClickEvent,
- flyTo,
- pointInitEvent,
- pointUnInitEvent
-} = cesiumOperation()
-/**
- *
- * @param { 单点航线 相关功能} url
- */
-export const initPointWayline = () => {
-
- let viewer = null;
-
-
- // 解析kmz文件
- const parsingFiles = async (url,viewer) => {
- viewer = viewer;
- console.log('initPointWayline', viewer);
- const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
- const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
- const xmlJson = XMLToJSON(waylinesXML)?.['Document'];
- if (xmlJson.Folder.Placemark.length) return;
- drawWayline(xmlJson)
- };
- // 在地图上画线
- const drawWayline = (xmlJson) => {
- let positions = [];
- // 获取点的位置
- const points = xmlJson.Folder.Placemark;
- console.log('points', points);
- getPositionsHeight(points, viewer, 100).then((result) => {
- console.log(result);
- positions = result.map((item) => {
- return Cesium.Cartesian3.fromDegrees(
- Number(item.longitude),
- Number(item.latitude),
- item.FinalHeight,
- )
- });
- result.forEach((item, index) => {
- let setting = {};
- setting = {
- id: 'route_point_' + index,
- position: positions[index],
-
- label: {
- text: `${index + 1}`,
- font: 'bold 14px serif',
- style: globalCesium.LabelStyle.FILL,
- verticalOrigin: globalCesium.VerticalOrigin.CENTER, // 垂直居中
- horizontalOrigin: globalCesium.HorizontalOrigin.CENTER, // 水平居中
- pixelOffset: new globalCesium.Cartesian2(0, 0), // 根据需要调整偏移量
- eyeOffset: new globalCesium.Cartesian3(0, 0, -10) // 使标签在点的上方
- },
-
- point: {
- pixelSize: 24,
- color: new globalCesium.Color.fromBytes(255, 186, 0, 255),
- },
- }
- viewer.entities.add(setting)
- });
- });
- };
-
- return { parsingFiles };
-};
\ No newline at end of file
--
Gitblit v1.9.3