From 2800fa4f32f3900509cb4d6eefaf2bfaf54efdd7 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Mon, 21 Apr 2025 18:29:09 +0800
Subject: [PATCH] fix: 天气显示
---
src/views/Home/AINowFly.vue | 356 +++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 295 insertions(+), 61 deletions(-)
diff --git a/src/views/Home/AINowFly.vue b/src/views/Home/AINowFly.vue
index a11981f..427a365 100644
--- a/src/views/Home/AINowFly.vue
+++ b/src/views/Home/AINowFly.vue
@@ -1,29 +1,60 @@
<template>
<div class="AINowFly">
- <div>智引即飞</div>
+ <div class="title">智引即飞<img @click="closeClick" src="@/assets/images/aiNowFly/close.png"/></div>
<el-form ref="ruleFormRef" :model="params" :rules="rules" label-width="auto" size="small" status-icon>
- <el-form-item label="任务名称" prop="taskName">
- <el-input v-model="params.taskName" />
+ <el-form-item label="任务名称" prop="name">
+ <el-input class="ztzf-input" v-model="params.name" />
</el-form-item>
<el-form-item label="关联算法" prop="ai_types">
- <el-select v-model="params.ai_types" placeholder="请选择">
+ <el-select :teleported="false" class="ztzf-select" v-model="params.ai_types" placeholder="请选择" multiple collapse-tags collapse-tags-tooltip>
<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-input disabled type="text" v-model="di" />
+ <el-form-item label="地址">
+ <el-input class="ztzf-input" disabled type="text" v-model="di" placeholder="地名&经纬度"/>
+ </el-form-item>
+ <!-- todo-->
+ <el-form-item label="飞行事件">
+ <div class="event">
+ <img src="../../assets/images/aiNowFly/event/startRecord.png" alt="">
+ <div class="img-close" v-show="isPhoto">
+ <img @click="isPhoto=false" class="close" src="@/assets/images/aiNowFly/close.png" alt="">
+ <img src="../../assets/images/aiNowFly/event/takePhoto.png" alt="">
+ </div>
+ <div class="img-close" v-show="isStop">
+ <img @click="isStop=false" class="close" src="@/assets/images/aiNowFly/close.png" alt="">
+ <img src="../../assets/images/aiNowFly/event/hover.png" alt="">
+ </div>
+ <div class="add-event" @click="isShowEvent = !isShowEvent">+
+ <div class="event-select" v-show="isShowEvent">
+ <div class="photo" @click="isPhoto=true">拍照</div>
+ <div class="stop" @click="isStop=true">悬停</div>
+ </div>
+ </div>
+ </div>
</el-form-item>
</el-form>
- <div>可用机巢列表</div>
- <el-table :data="list" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" />
- <el-table-column type="index" label="序号" />
- <el-table-column prop="nickname" label="机巢名称" />
- <el-table-column prop="minute" label="预计飞行时长(分钟)" />
- <el-table-column prop="exe_distance" label="预计飞行距离(m)" />
- </el-table>
- <el-button type="primary" @click="nowFly">迅速起飞</el-button>
+ <div class="title-list">可飞行机巢列表:</div>
+ <div class="tabledata">
+ <div class="table-content">
+ <div class="tabler-item">
+ <el-checkbox v-model="isCheckAll" @change="checkedAll"/>
+ </div>
+ <div class="table-item">机巢名称</div>
+ <div class="table-item">可飞行时间</div>
+ <div class="table-item">可飞行距离</div>
+ </div>
+ <div class="table-content" v-for="item in list">
+ <div class="tabler-item">
+ <el-checkbox v-model="item.checked" @change="handleItemCheck"/>
+ </div>
+ <div class="table-item">{{ item.nickname }}</div>
+ <div class="table-item">{{ item.minute }}(min)</div>
+ <div class="table-item">{{ item.exe_distance }}(km)</div>
+ </div>
+ </div>
+ <div class="btn-submit" @click="nowFly"><img src="@/assets/images/aiNowFly/fly.png" alt=""></div>
</div>
</template>
<script setup>
@@ -33,6 +64,9 @@
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
import { Cartesian3 } from 'cesium'
import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
+import endingImg from '@/assets/images/aiNowFly/ending.png'
+import endingHighImg from '@/assets/images/aiNowFly/ending-high.png'
+import startingImg from '@/assets/images/aiNowFly/starting.png'
import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
import lineImg from '@/assets/images/arrow-right-blue.png'
import _ from 'lodash'
@@ -40,23 +74,32 @@
import dayjs from 'dayjs'
import { useStore } from 'vuex'
-
-
-const now = dayjs().format('YYYY/MM/DD HH:mm')
+const now = dayjs().format('YYYYMMDDHHmm')
+const nowTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
const paramsInit = {
- taskName: `智引即飞 ${now}`,
+ name: `智引即飞${now}`,
ai_types: '',
longitude: '',
latitude: '',
dock_sns: [],
+ type: 1,
+ begin_time: nowTime,
+ end_time: nowTime,
+ action_modes: [{action_actuator_func: 'startRecord'}],
}
const params = ref(_.cloneDeep(paramsInit))
const di = computed(() => params.value.longitude + ',' + params.value.latitude)
+// 事件默认隐藏
+const isShowEvent = ref(false);
+
+// 添加事件
+const isPhoto = ref(false)
+const isStop = ref(false)
const rules = ref({
- taskName: [
+ name: [
{ required: true, message: '请输入任务名称', trigger: 'blur' },
{ min: 3, max: 50, message: '长度在 3 到 20 个字符', trigger: 'blur' },
],
@@ -79,11 +122,22 @@
await ruleFormRef.value.validate()
if (!params.value.dock_sns.length) return ElMessage.warning('请选择将要飞行的机巢')
if (!params.value.longitude) return ElMessage.warning('请选择飞行的点')
- if (params.value.dock_sns.length === 1){
- store.commit('setSingleUavHome', { device_sn: params.value.dock_sns[0]})
- }else{
- store.commit('setFootActiveIndex', 0)
+ // 先清除,再push
+ params.value.action_modes = [{action_actuator_func:'startRecord'}]
+ if (isPhoto.value) {
+ params.value.action_modes.push({action_actuator_func:'takePhoto'})
}
+ if (isStop.value) {
+ params.value.action_modes.push({action_actuator_func:'hover'})
+ }
+ createTask(params.value).then(res => {
+ ElMessage.success('起飞成功')
+ if (params.value.dock_sns.length === 1) {
+ store.commit('setSingleUavHome', { device_sn: params.value.dock_sns[0] })
+ } else {
+ store.commit('setFootActiveIndex', 0)
+ }
+ })
}
const renderingLine = () => {
@@ -92,18 +146,35 @@
const start = Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude))
const end = Cartesian3.fromDegrees(Number(longitude), Number(latitude))
const positionsList = [start, end]
+ // 计算中点位置
+ const midpoint = Cartesian3.midpoint(start, end, new Cartesian3())
+ // 计算线段方向
+ const direction = Cartesian3.subtract(end, start, new Cartesian3())
+ Cartesian3.normalize(direction, direction)
// 线
+ // 添加中点文字标签
+ viewer.entities.add({
+ id: `AINow-time-${index}`,
+ position: midpoint,
+ label: {
+ text: `预计${item.minute}分钟`,
+ font: 'bold 16px Source Han Sans CN', // 加粗并增大字号
+ // fillColor: new Cesium.Color(27/255, 179/255, 255/255, 1.0),
+ // fillColor: Cesium.Color.WHITE,
+ // style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+ // verticalOrigin: Cesium.VerticalOrigin.CENTER,
+ // horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+ // eyeOffset: new Cesium.Cartesian3(0, 0, -10),
+ // pixelOffset: new Cesium.Cartesian2(0, -10),
+ rotation: 12.785398, // 修改旋转计算方式
+ }
+ })
viewer.entities.add({
id: `AINow-line-${index}`,
polyline: {
- width: 4,
+ width: 2,
positions: positionsList,
- material: new ImageTrailMaterial({
- color: { alpha: 1, blue: 1, green: 1, red: 1 },
- speed: 20,
- image: lineImg,
- repeat: { x: Math.floor(40), y: 1 },
- }),
+ material: index === 0 ? new Cesium.Color(2/255, 192/255, 255/255, 1) : new Cesium.Color(27/255, 179/255, 255/255, 0.4),
clampToGround: false,
},
})
@@ -111,20 +182,20 @@
viewer.entities.add({
id: `AINow-point-${index}`,
position: start,
- label: {
- text: item.nickname,
- font: '12pt Source Han Sans CN',
- fillColor: Cesium.Color.WHITE,
- outlineColor: Cesium.Color.BLACK,
- outlineWidth: 2,
- style: Cesium.LabelStyle.FILL_AND_OUTLINE,
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- pixelOffset: new Cesium.Cartesian2(0, -9),
- },
+ // label: {
+ // text: item.nickname,
+ // font: '12pt Source Han Sans CN',
+ // fillColor: Cesium.Color.WHITE,
+ // outlineColor: Cesium.Color.BLACK,
+ // outlineWidth: 2,
+ // style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+ // verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+ // pixelOffset: new Cesium.Cartesian2(0, -9),
+ // },
billboard: {
- image: new Cesium.ConstantProperty(uavImg),
- width: 24,
- height: 24,
+ image: new Cesium.ConstantProperty(index === 0 ? endingHighImg : endingImg),
+ width: 40,
+ height: 40,
},
properties: {
customData: {
@@ -149,16 +220,15 @@
viewer.entities.add({
position: earthPosition,
id: `AINow-event-0`,
- point: {
- pixelSize: 10,
- color: Cesium.Color.RED,
- outlineColor: Cesium.Color.WHITE,
- outlineWidth: 2,
- },
+ billboard: {
+ image: new Cesium.ConstantProperty(startingImg),
+ width: 40,
+ height: 40,
+ }
})
const { longitude, latitude } = cartesian3Convert(earthPosition, viewer)
eventPoint = { longitude, latitude }
- params.value = {...params.value,longitude, latitude}
+ params.value = { ...params.value, longitude, latitude }
getFJList()
}
@@ -171,17 +241,43 @@
})
}
+let pagingParams = ref({
+ current: 1,
+ size: 10
+});
+
+const isCheckAll = ref(false);
// 获取飞机列表
const getFJList = async () => {
- params.value.dock_sns = []
- const getListParams = { ...eventPoint, page: 1, limit: 9999, type: 1 }
- const res = await getFlyingNestBy(getListParams)
+ let pageParams = ref({
+ ...eventPoint,
+ type: 1,
+ });
+ params.value.dock_sns = [];
+ const res = await getFlyingNestBy(pageParams.value, pagingParams.value)
list.value = (res.data?.data || []).map(item => ({
...item,
+ checked: false,
minute: _.round(item.estimated_arrival_time / 60, 0),
}))
if (!list.value.length) ElMessage.warning('附近暂无可用无人机')
renderingLine()
+}
+
+// 单个选择框变化
+const handleItemCheck = () => {
+ const allChecked = list.value.every(item => item.checked)
+ const someChecked = list.value.some(item => item.checked)
+ isCheckAll.value = allChecked
+ params.value.dock_sns = list.value.filter(item => item.checked).map(item => item.device_sn)
+}
+
+// 全选
+const checkedAll = () => {
+ list.value.forEach(item => {
+ item.checked = isCheckAll.value
+ })
+ params.value.dock_sns = isCheckAll.value ? list.value.map(item => item.device_sn) : []
}
const initMap = () => {
@@ -194,6 +290,17 @@
handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
handler?.destroy()
handler = null
+}
+
+// 关闭
+const closeClick = () => {
+ removeAll()
+ params.value = _.cloneDeep(paramsInit)
+ list.value = []
+ eventPoint = {}
+ store.commit('setFootActiveIndex', 0)
+ // 显示相关的按钮
+ store.commit('setHideBottomIcon', true)
}
onBeforeUnmount(() => {
@@ -209,12 +316,139 @@
<style scoped lang="scss">
.AINowFly {
position: absolute;
- top: 200px;
- right: 0;
- width: 400px;
- height: 700px;
- background: white;
- color: black;
- font-size: 20px;
+ top: 263px;
+ right: 74px;
+ width: 320px;
+ height: 518.6px;
+ font-size: 14px;
+ color: #FFFFFF;
+ background: url('@/assets/images/aiNowFly/ai-fly-bg.png') no-repeat center / 100% 100%;
+ .title {
+ height: 50px;
+ line-height: 50px;
+ margin-left: 20px;
+ font-family: Segoe UI, Segoe UI;
+ font-weight: bold;
+ font-size: 20px;
+ letter-spacing: 2px;
+ background: linear-gradient(180deg, #FFFFFF 50%, #35D0FF 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ img {
+ position: absolute;
+ cursor: pointer;
+ width: 16px;
+ height: 16px;
+ right: 15px;
+ top: 15px;
+ }
+ }
+ .el-form {
+ padding: 20px 16px 13px 11px;
+ :deep(.el-form-item__label) {
+ color: #FFFFFF;
+ }
+ :deep(.el-input__wrapper),
+ :deep(.el-select),
+ :deep(.el-select__wrapper) {
+ background-color: #021740;
+ &.is-focus {
+ box-shadow: 0 0 0 1px #026AD6;
+ }
+ }
+:deep(.el-tag, .el-tag.el-tag--primary),
+:deep(.el-tag.el-tag--info) {
+ --el-tag-bg-color: none !important;
+ --el-tag-border-color: none !important;
+ --el-tag-hover-color: none !important;
+}
+ :deep(.el-input__wrapper.is-disabled) {
+ background-color: #021740;
+ box-shadow: 0 0 0 1px #026AD6;
+ }
+ .event {
+ display: flex;
+ img {
+ width: 40px;
+ height: 34px;
+ margin-right: 10px;
+ }
+ .img-close {
+ position: relative;
+ .close {
+ cursor: pointer;
+ width: 8px;
+ height: 8px;
+ position: absolute;
+ top: -8px;
+ right: 1px;
+ }
+ }
+ .add-event {
+ width: 38px;
+ height: 38px;
+ background: rgba(83,179,255,0.16);
+ border-radius: 8px 8px 8px 8px;
+ border: 1px dashed;
+ text-align: center;
+ line-height: 38px;
+ color: #11C4FF;
+ position: relative;
+ cursor: pointer;
+ // border-image: linear-gradient(180deg, rgba(17, 196, 255, 1), rgba(255, 255, 255, 1)) 1 1;
+ .event-select {
+ z-index: 10;
+ position: absolute;
+ top: 40px;
+ width: 72px;
+ height: 70px;
+ background: #0F1929;
+ box-shadow: inset 0px -50px 50px 0px rgba(27,148,255,0.13);
+ border-radius: 8px 8px 8px 8px;
+ border: 1px solid #51A8FF;
+ text-align: center;
+ color: #D3E9FF;
+ .photo {
+ height: 36px;
+ border-bottom: 1px solid #51A8FF;
+ }
+ }
+ }
+ }
+ }
+ .title-list {
+ padding: 0 0 14px 11px;
+ }
+ .tabledata {
+ min-height: 120px;
+ border: 1px dashed #fff;
+ margin: 0px 10px;
+ .table-content {
+ padding: 0 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ &:not(:last-child) {
+ border-bottom: 1px dashed #fff;
+ }
+ }
+ .table-item {
+ width: 100px;
+ text-align: center;
+ height: 32px;
+ line-height: 32px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+ .btn-submit {
+ cursor: pointer;
+ margin-left: 88px;
+ margin-top: 12px;
+ img { width: 138px; height: 38px; }
+ }
}
</style>
--
Gitblit v1.9.3