From 576f21549181a8dca5b96dcf462a2a1cc7d6b1af Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Wed, 04 Feb 2026 10:40:30 +0800
Subject: [PATCH] feat: 删除无用代码
---
applications/mobile-web-view/src/appComponents/error-page/404.vue | 2
applications/mobile-web-view/src/main.js | 4
/dev/null | 535 -----------------------------------------------------
applications/mobile-web-view/src/router/views/index.js | 3
applications/mobile-web-view/src/appComponents/error-page/403.vue | 2
applications/mobile-web-view/src/appComponents/SvgIcon.vue | 0
applications/mobile-web-view/src/appComponents/error-page/style.scss | 0
applications/mobile-web-view/src/router/page/index.js | 37 ---
applications/mobile-web-view/src/appComponents/index.js | 0
applications/mobile-web-view/src/appComponents/error-page/500.vue | 2
10 files changed, 11 insertions(+), 574 deletions(-)
diff --git a/applications/mobile-web-view/src/components/SvgIcon.vue b/applications/mobile-web-view/src/appComponents/SvgIcon.vue
similarity index 100%
rename from applications/mobile-web-view/src/components/SvgIcon.vue
rename to applications/mobile-web-view/src/appComponents/SvgIcon.vue
diff --git a/applications/mobile-web-view/src/components/error-page/403.vue b/applications/mobile-web-view/src/appComponents/error-page/403.vue
similarity index 95%
rename from applications/mobile-web-view/src/components/error-page/403.vue
rename to applications/mobile-web-view/src/appComponents/error-page/403.vue
index aca4544..dd6f9d6 100644
--- a/applications/mobile-web-view/src/components/error-page/403.vue
+++ b/applications/mobile-web-view/src/appComponents/error-page/403.vue
@@ -19,5 +19,5 @@
};
</script>
<style lang="scss" scoped>
-@use './style.scss';
+@use 'style';
</style>
diff --git a/applications/mobile-web-view/src/components/error-page/404.vue b/applications/mobile-web-view/src/appComponents/error-page/404.vue
similarity index 95%
rename from applications/mobile-web-view/src/components/error-page/404.vue
rename to applications/mobile-web-view/src/appComponents/error-page/404.vue
index c6a7f28..f7d3fdb 100644
--- a/applications/mobile-web-view/src/components/error-page/404.vue
+++ b/applications/mobile-web-view/src/appComponents/error-page/404.vue
@@ -19,5 +19,5 @@
};
</script>
<style lang="scss" scoped>
-@use './style.scss';
+@use 'style';
</style>
diff --git a/applications/mobile-web-view/src/components/error-page/500.vue b/applications/mobile-web-view/src/appComponents/error-page/500.vue
similarity index 95%
rename from applications/mobile-web-view/src/components/error-page/500.vue
rename to applications/mobile-web-view/src/appComponents/error-page/500.vue
index 05df75c..ebe9342 100644
--- a/applications/mobile-web-view/src/components/error-page/500.vue
+++ b/applications/mobile-web-view/src/appComponents/error-page/500.vue
@@ -19,5 +19,5 @@
};
</script>
<style lang="scss" scoped>
-@use './style.scss';
+@use 'style';
</style>
diff --git a/applications/mobile-web-view/src/components/error-page/style.scss b/applications/mobile-web-view/src/appComponents/error-page/style.scss
similarity index 100%
rename from applications/mobile-web-view/src/components/error-page/style.scss
rename to applications/mobile-web-view/src/appComponents/error-page/style.scss
diff --git a/applications/mobile-web-view/src/components/index.js b/applications/mobile-web-view/src/appComponents/index.js
similarity index 100%
rename from applications/mobile-web-view/src/components/index.js
rename to applications/mobile-web-view/src/appComponents/index.js
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/DroneConsole/DroneConsole.vue b/applications/mobile-web-view/src/appPages/inspectionTask/DroneConsole/DroneConsole.vue
deleted file mode 100644
index 9c8e82a..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/DroneConsole/DroneConsole.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-<template>
- <div style="width: 100%; height: 100%">
- <CurrentTaskDetails
- :class="{ 'narrowScreen': narrowScreen }"
- v-model:show="isShowCurrentTaskDetails"
- :wayLineJobInfoId="route.query.wayLineJobInfoId"
- :selectDockSn="route.query.dockSn"
- :batchNo="route.query?.batchNo"
- />
- </div>
-</template>
-
-<script setup>
-import { useRoute } from 'vue-router'
-import CurrentTaskDetails from '@/components/CurrentTaskDetails/CurrentTaskDetails.vue'
-const route = useRoute()
-const isShowCurrentTaskDetails = ref(true)
-
-// 窄屏检测
-const narrowScreen = ref(true)
-const landscapeMode = ref(false)
-provide('landscapeMode',landscapeMode)
-const narrowScreenFun = () => {
- narrowScreen.value = window.innerWidth / window.innerHeight < 16 / 9
- landscapeMode.value = !narrowScreen.value
- if (landscapeMode.value) {
- document.body.classList.add('landscapeMode');
- } else {
- document.body.classList.remove('landscapeMode')
- }
-}
-
-onMounted(() => {
- narrowScreenFun()
- window.addEventListener('resize', narrowScreenFun)
- window.screen.orientation.addEventListener('change', narrowScreenFun)
-})
-
-onBeforeUnmount(() => {
- window.removeEventListener('resize', narrowScreenFun)
- window.screen.orientation.removeEventListener('change', narrowScreenFun)
-})
-</script>
-
-<style scoped lang="scss">
-.narrowScreen{
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskContent.vue b/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskContent.vue
deleted file mode 100644
index 71db8cb..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskContent.vue
+++ /dev/null
@@ -1,109 +0,0 @@
-
-<template>
- <div class="taskContentParent">
- <div class="taskContent">
- <div class="title">任务内容</div>
- <div v-for="item in list" class="itemBox">
- <div class="itemName">{{ item.name }}:</div>
- <div class="itemValue" v-if="item.name !== '飞行事件'">{{ item.value }}</div>
- <div class="flightEvents" v-else>
- <template v-if="flightEvents.length > 0">
- <img v-for="item in flightEvents" alt="" :src="item.imgUrl" :title="item.label"></img>
- </template>
- <span v-else>--</span>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<script setup>
-import { getFindAction } from '@/utils/cesium/pointWayLineUtils'
-
-const flightEvents = ref([])
-const hasAiTypeStr = ref(false)
-const list = ref([
- { name: '任务编号', value: '--', field: 'job_info_num' },
- { name: '任务名称', value: '--', field: 'name' },
- { name: '任务类型', value: '--', field: 'rep_rule_type' },
- { name: '飞行事件', value: '--', field: '' },
- { name: '所属部门', value: '--', field: 'dept_name' },
- { name: '所属机巢', value: '--', field: 'device_names' },
- { name: '任务时间', value: '--', field: 'begin_time' },
- { name: '任务频次', value: '--', field: 'rep_rule_type rep_rule_val' },
- { name: '关联算法', value: '--', field: 'ai_type_str' },
- { name: '任务描述', value: '--', field: 'remark' },
-])
-const props = defineProps(['taskDetails'])
-function setListParams() {
- list.value.forEach(item => {
- item.value = props.taskDetails?.[item.field] || '--'
- if (item.name === '任务频次') {
- const { rep_rule_type = '', final_cycle_frequency = '' } = props.taskDetails || {}
- item.value = rep_rule_type ? final_cycle_frequency : '1次'
- }
- if (item.name === '任务类型') {
- const val = props.taskDetails?.[item.field]
- item.value = val ? '周期任务' : '临时任务'
- }
- if (item.name === '飞行事件') {
- const { action_modes = [] } = props.taskDetails || {}
- flightEvents.value = action_modes.flatMap((item) => getFindAction(item, 'app'))
- }
- if (item.name === '关联算法'){
- hasAiTypeStr.value = !!props.taskDetails?.[item.field]
- }
- })
-}
-
-watch(()=>props.taskDetails,setListParams,
- {
- immediate: true,
- deep: true,
- }
-)
-
-</script>
-
-
-<style scoped lang="scss">
-.taskContentParent{
- width: 100%;
- padding: 0 12px;
- .taskContent{
- background: #FFFFFF;
- padding: 10px 10px 20px 10px;
- border-radius: 6px 6px 6px 6px;
-
- .title{
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: bold;
- font-size: 16px;
- color: #222324;
- }
- .itemBox{
- min-height: 48px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: 1px solid #F5F5F5;
-
- .itemName{
- flex-shrink: 0;
- }
-
- .flightEvents{
- display: flex;
- align-items: center;
- gap: 5px;
-
- >img{
- width: 26px;
- height: 26px;
- }
- }
- }
-
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskInProgress.vue b/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskInProgress.vue
deleted file mode 100644
index f4e5d19..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/TaskInProgress/TaskInProgress.vue
+++ /dev/null
@@ -1,214 +0,0 @@
-<template>
- <div class="taskDetails">
- <LiveVideo v-if="liveSuccess" :videoUrl="currentLiveUrl" :controls="false" @videoClick="fullScreen" />
- <div v-else class="liveErr">
- <div class="liveErrBg" />
- </div>
- <div
- v-for="item in taskWayLineDetails"
- class="task-list"
- :class="{ active: activeDock.device_sn === item.device_sn }"
- @click="switchDevice(item)"
- >
- <div>{{ item.name }}</div>
- </div>
- <TaskContent :taskDetails="taskDetails" />
- </div>
-</template>
-
-<script setup>
-import { useRoute } from 'vue-router'
-import { getUserInfo } from '@/api/system/user'
-import LiveVideo from '@/components/LiveVideo.vue'
-import { useTaskDetails } from '@/hooks/useTaskDetails/useTaskDetails'
-import { getDeviceDetail, liveStart } from '@/api/home/machineNest'
-import { ElMessage } from 'element-plus'
-import { useDroneWS } from '@/hooks/useDroneWS'
-import TaskContent from '@/appPages/inspectionTask/TaskInProgress/TaskContent.vue'
-import { exitFullScreen, reqFullScreen } from '@/utils/util'
-import { showToast } from 'vant'
-import {getJobWayLineDetails} from '@ztzf/apis'
-import { getJobDetails, getJobsByJobInfoIdApi } from '@/api/home/task'
-
-const route = useRoute()
-const isShowCurrentTaskDetails = ref(false)
-const activeDock = ref(null) //选中的
-const dockSn = computed(() => activeDock.value?.device_sn) //机巢sn
-const workspace_id = computed(() => activeDock.value?.workspace_id)
-const isDroneLive = ref(false)
-const isTakeOff = ref(false)
-const currentLiveUrl = ref('') // 当前直播地址
-const video_id = ref('') // 直播视频id
-const isAiLive = ref(false) // 是ai直播
-const lineQuality = ref(1) //1流畅,2标清
-const liveSuccess = ref(true) //直播正常
-const droneSn = computed(() => wsInfo.value?.device_osd?.data?.sn) //无人机sn
-const taskDetails = ref({})
-const taskWayLineDetails = ref([])
-const currentMinJob = ref(null) //当前小任务信息
-const isCurFlightTask = ref(false) //是否是当前飞行任务
-let wayLineJobInfoId = null
-let batchNo = null
-
-let { wsInfo } = useDroneWS(workspace_id)
-
-// 获取无人机直播url
-async function getDroneLiveUrl(reset = false, sn) {
- try {
- await nextTick()
- const res = await liveStart(sn || droneSn.value, lineQuality.value)
- currentLiveUrl.value = res.data.data.rtcs_url
- video_id.value = res.data.data.video_id
- isAiLive.value = false
- reset && ElMessage.success('刷新成功')
- liveSuccess.value = true
- } catch (e) {
- liveSuccess.value = false
- }
-}
-
-// 获取机巢直播
-const getDeviceLiveUrl = async () => {
- try {
- const res = await liveStart(dockSn.value, 2)
- currentLiveUrl.value = res.data.data.rtcs_url
- video_id.value = null
- liveSuccess.value = true
- } catch (e) {
- liveSuccess.value = false
- }
-}
-
-// 初始化直播
-async function initLiveFun() {
- const dockInfoRes = await getDeviceDetail(dockSn.value)
- const result = dockInfoRes.data.data
- isDroneLive.value = ![undefined, 0, 14, -1].includes(result?.children?.mode_code)
- isTakeOff.value = !!isDroneLive.value
- if (isDroneLive.value && isCurFlightTask.value) {
- await getDroneLiveUrl(false, dockInfoRes.data.data.child_device_sn)
- } else {
- await getDeviceLiveUrl()
- }
-}
-
-function switchDevice(row) {
- activeDock.value = row
- geiMinJobInfo()
- initLiveFun()
-}
-
-// 设置当前直播地址
-const setCurrentLiveUrl = async () => {
- const deviceInfo = wsInfo.value?.device_osd?.data?.host
- if (!deviceInfo) return
- const currentIsTakeOff = ![14, 0].includes(deviceInfo?.mode_code)
- // 如果还是之前的状态,不切换
- if (isTakeOff.value === currentIsTakeOff) return
- isTakeOff.value = currentIsTakeOff;
- (isTakeOff.value && isCurFlightTask.value) ? await getDroneLiveUrl() : await getDeviceLiveUrl()
-}
-
-function fullScreen() {
- const transmitData = { data: { type: 'control', dockSn: dockSn.value } }
- wx.miniProgram.navigateTo({ url: `/subPackages/droneConsole/index?wayLineJobInfoId=${wayLineJobInfoId}&dockSn=${dockSn.value}` })
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-
-watch(wsInfo, setCurrentLiveUrl, { deep: true })
-watch(
- () => wsInfo.value?.flighttask_progress?.data?.bid,
- val => {
- const flightTaskId = currentMinJob.value.job_id
- isCurFlightTask.value = flightTaskId ? val === flightTaskId : true
- }
-)
-
-async function geiMinJobInfo() {
- const minJobListRes = await getJobsByJobInfoIdApi({ jobInfoId: wayLineJobInfoId })
- let minJobList = minJobListRes.data.data || []
- if (batchNo !== null && batchNo !== undefined){
- minJobList = minJobList.filter(item => item.batch_no === Number(batchNo))
- }
- currentMinJob.value = minJobList.find(item => item.dock_sn === activeDock.value.device_sn)
- isCurFlightTask.value = currentMinJob.value?.status === 2
- console.log(isCurFlightTask.value,'isCurFlightTask.value')
-}
-
-onMounted(async () => {
- wayLineJobInfoId = route.query.wayLineJobInfoId
- batchNo = route.query.batchNo
- const params = { wayLineJobInfoId: wayLineJobInfoId,batchNo }
- const res = await getJobDetails(params)
-
- taskDetails.value = res.data.data
-
- const wayLineDetails = await getJobWayLineDetails(params)
-
- taskWayLineDetails.value = wayLineDetails.data.data
-
- activeDock.value = taskWayLineDetails.value[0]
- await geiMinJobInfo()
- await initLiveFun()
- isShowCurrentTaskDetails.value = true
- getUserInfo()
-})
-</script>
-
-<style scoped lang="scss">
-#videoId {
- width: 100%;
-}
-
-.taskDetails {
- width: 100%;
- padding-bottom: 10px;
-
- .liveErr {
- position: relative;
- width: 100%;
- height: calc(100vw * 0.5625);
- background: rgba(31, 31, 31, 0.6);
-
- .liveErrBg {
- position: relative;
- width: 100%;
- height: 100%;
- background: url(@/assets/images/offLine.svg) no-repeat center / 80% 80%;
- color: #ededed;
- font-size: 16px;
- }
- }
-
- .task-list {
- width: 90%;
- height: 36px;
- line-height: 36px;
- background: #ffffff;
- box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.03);
- border-radius: 20px 20px 20px 20px;
- border: 1px solid #e9e9e9;
- display: flex;
- justify-content: space-around;
- margin: 8px auto;
-
- &.active {
- background: #1d6fe9;
- color: white;
- }
- }
-
- :deep() {
- .live-video {
- width: 100%;
- height: 205px;
- margin-bottom: 10px;
- }
- }
-}
-
-.back {
- font-size: 20px;
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/addTask/index.vue b/applications/mobile-web-view/src/appPages/inspectionTask/addTask/index.vue
deleted file mode 100644
index 484ead5..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/addTask/index.vue
+++ /dev/null
@@ -1,701 +0,0 @@
-<template>
- <div class="add-task">
- <div class="task-map" :class="{ 'fullscreen': isFullscreen }">
- <div class="sf-img" @click="handleMapClick"><img :src="isFullscreen ? suoSvg : fangSvg" alt="" /></div>
- <div id="taskMap"></div>
- </div>
- <div class="task-form" v-if="!isFullscreen">
- <div class="task-title">任务内容</div>
- <van-form>
- <div class="card">
- <div class="label">
- <span>*</span>
- 任务名称
- </div>
- <van-field v-model="formParams.name" placeholder="请输入" />
- </div>
- <div class="card">
- <div class="label">
- <span>*</span>
- 日期选择
- </div>
- <van-field v-model="time" is-link readonly name="datePicker" placeholder="请选择"
- @click="timeShow = true" />
- <van-popup v-model:show="timeShow" destroy-on-close position="bottom">
- <van-picker-group title="预约日期" :tabs="['选择日期', '选择时间']" next-step-text="下一步"
- @confirm="onTimeConfirm" @cancel="timeShow = false">
- <van-date-picker v-model="timeDate" :min-date="minDate" />
- <van-time-picker v-model="formParams.execute_time_arr" />
- </van-picker-group>
- </van-popup>
- </div>
- <div class="card">
- <div class="label">关联算法</div>
- <van-field v-model="sfValue" is-link readonly name="picker" placeholder="请选择"
- @click="sfShow = true" />
- <van-popup v-model:show="sfShow" position="bottom" :style="{ height: '50%' }"
- @click-overlay="onClickOverlay">
- <!-- 直接在 popup 标签内添加内容 -->
- <div class="popup-content">
- <div class="item" v-for="item in taskAlgorithm">
- <div class="item-content" @click="handleCheckboxChange(item)">
- <img v-if="item.checked" :src="gouSvg" alt="" />
- <div v-else class="empty"></div>
- <div class="text">{{ item.text }}</div>
- </div>
- <!-- <van-checkbox v-model="item.checked" @update:model-value="handleCheckboxChange(item, index)">{{ item.text }}</van-checkbox>-->
- </div>
- </div>
- </van-popup>
- <!-- <van-popup v-model:show="sfShow" destroy-on-close position="bottom">-->
- <!-- <van-picker-->
- <!-- :columns="taskAlgorithm"-->
- <!-- :v-model="formParams.ai_types"-->
- <!-- @confirm="onSfConfirm"-->
- <!-- @cancel="sfShow = false"-->
- <!-- />-->
- <!-- </van-popup>-->
- </div>
- <div class="card">
- <div class="label">
- <span>*</span>
- 选择航线
- </div>
- <van-field v-model="lineName" is-link readonly name="picker" placeholder="请选择"
- @click="lineShow = true" />
- <van-popup v-model:show="lineShow" destroy-on-close position="bottom">
- <van-picker :columns="routeOptions" :model-value="lineValue" @confirm="onConfirm"
- @cancel="lineShow = false" />
- </van-popup>
- </div>
- <div class="card">
- <div class="label">任务描述</div>
- <van-field rows="1" autosize type="textarea" show-word-limit v-model="formParams.remark"
- placeholder="请输入" />
- </div>
- </van-form>
- <div class="task-title">可飞行机巢列表</div>
- <div class="task-list" :class="item.checked ? 'active' : ''" v-for="(item, index) in tableData" :key="index"
- @click="checkedTable(item)">
- <div class="name">{{ item.nickname }}</div>
- <div>预计到达{{ item.estimated_arrival_time }}(min)</div>
- <div>执行里程{{ item.flight_range }}(km)</div>
- </div>
- <div class="task-btn">
- <van-button round block type="primary" color="#1D6FE9" :loading="loading" loading-text="发布中..."
- @click="handleSubmit">
- 任务发布
- </van-button>
- </div>
- </div>
- </div>
-</template>
-<script setup>
-import { newGetWorkspacesPage } from '@/api/routePlan'
-import { getMultipleDictionary } from '@/api/system/dictbiz'
-import { getFlyingNestBy, getWaylineSplit, createTask } from '@/api/home/task'
-import { analysisPointLineKmz, handlePointListForKmz } from '@/utils/cesium/pointWayLineUtils'
-import { getWaylineSplitApi } from '@/api/routePlan'
-import _ from 'lodash'
-import dayjs from 'dayjs'
-import L from 'leaflet'
-import 'leaflet/dist/leaflet.css'
-import EventBus from '@/utils/eventBus'
-import sl from '@/appDataSource/leafletMapIcon/sl.svg'
-import yx from '@/appDataSource/leafletMapIcon/yx.svg'
-import droneIconSvg from '@/appDataSource/leafletMapIcon/drone-icon.svg'
-import suoSvg from '@/appDataSource/inspectionTask/suo-bg.svg'
-import fangSvg from '@/appDataSource/inspectionTask/fang-bg.svg'
-import startImg from '@/assets/images/signMachineNest/rwqfd.png'
-import endPointImg from '@/assets/images/EndPointicon.png'
-import gouSvg from '@/appDataSource/inspectionTask/gou.svg'
-import { showNotify } from 'vant'
-import { useRoute } from 'vue-router'
-import {
- basemapLayer0,
- basemapLayer1,
- basemapLayer2,
- basemapLayer3,
- polylineOptions0,
- polylineOptions1,
- polylineOptions2,
-} from '@/const/leafletConst'
-import 'leaflet-ant-path'
-import { useAreaBoundary } from '@/hooks/useAreaBoundary'
-import error from '@/error'
-
-const route = useRoute()
-
-const isFullscreen = ref(false)
-let originalPosition = null
-
-const basemap0 = L.layerGroup([basemapLayer0, basemapLayer1])
-const basemap1 = L.layerGroup([basemapLayer2, basemapLayer3])
-const layers = [
- {
- src: sl,
- name: '天地图电子',
- key: 1,
- map: basemap0,
- },
- {
- src: yx,
- name: '天地图影像',
- key: 2,
- map: basemap1,
- },
-]
-let map = null
-let currentPolylineArr = []
-let markersArr = []
-let isDisabled = ref(false)
-
-console.log(route.query, '单机巢数据')
-
-const loading = ref(false)
-const time = ref('')
-const minDate = ref(new Date())
-const timeDate = ref([dayjs().year(), dayjs().month() + 1, dayjs().date()])
-const lineName = ref('')
-const lineValue = ref([])
-const hours = dayjs().hour().toString().padStart(2, '0')
-const minutes = dayjs().minute().toString().padStart(2, '0')
-const formParams = ref({
- name: '',
- ai_types: [],
- dock_sns: [],
- execute_time_arr: [hours, minutes],
- file_id: '',
- remark: '',
- rth_altitude: 120,
- type: 0,
- begin_time: '',
- end_time: '',
-})
-const timeShow = ref(false)
-const sfValue = ref('')
-const sfShow = ref(false)
-const lineShow = ref(false)
-
-function onTimeConfirm (value) {
- time.value = `${value[0].selectedOptions[0].text}-${value[0].selectedOptions[1].text}-${value[0].selectedOptions[2].text} ${value[1].selectedOptions[0].text}:${value[1].selectedOptions[1].text}`
- timeDate.value = [
- value[0].selectedOptions[0].text,
- value[0].selectedOptions[1].text,
- value[0].selectedOptions[2].text,
- ]
- formParams.value.execute_time_arr = [`${value[1].selectedOptions[0].text}:${value[1].selectedOptions[1].text}`]
- timeShow.value = false
-}
-// 获取航线
-const routeOptions = ref([])
-const getRouteList = async () => {
- const formData = {
- name: '',
- waylineType: undefined,
- current: 1,
- size: 99999999,
- descs: 'update_time',
- dockSn: route.query.device_sn,
- isSplit: route.query.device_sn === '' ? '' : 0,
- }
- const res = await newGetWorkspacesPage(formData)
- if (res.data.code === 0) {
- routeOptions.value = res.data.data.records.map(item => ({
- text: item.name,
- value: item.wayline_id,
- url: `${item.domain_url}${item.object_key}`,
- is_split: item.is_split,
- id: item.id,
- wayline_type: item.wayline_type,
- }))
- }
-}
-
-let savePointList = []
-async function onConfirm ({ selectedValues, selectedOptions }) {
- lineShow.value = false
- lineValue.value = selectedValues
- lineName.value = selectedOptions[0].text
- formParams.value.file_id = selectedOptions[0].value
- isDisabled.value = false
- pageParams.value.type = 0
- pageParams.value.polygon = []
- const { pointList, polygonList } = await analysisPointLineKmz(selectedOptions[0].url)
- if (selectedOptions[0].is_split) {
- splitLine(selectedOptions[0].id)
- lineShow.value = false
- return
- } else {
- if ([2, 4, 5, 6, 7, 10].includes(Number(selectedOptions[0].wayline_type))) {
- pageParams.value.type = 2
- pageParams.value.polygon = polygonList
- }
- await getTableList()
- }
-
- savePointList = _.clone(pointList)
- // pointList.unshift({ latitude: tableData.value[0].latitude, longitude: tableData.value[0].longitude });
- let points = pointList.map(item => {
- return [item.latitude, item.longitude]
- })
- if (currentPolylineArr && currentPolylineArr.length > 0) {
- currentPolylineArr.map(item => {
- map.removeLayer(item)
- })
- }
- if (markersArr && markersArr.length > 0) {
- markersArr.map(item => {
- map.removeLayer(item)
- })
- }
- // 连接到机巢
- const checkedSn = tableData.value.filter(item => item.checked)
- points.unshift([checkedSn[0].latitude, checkedSn[0].longitude])
- renderLineAndPoint(points, 0)
-}
-
-// 拆分航线显示
-function splitLine (id) {
- if (currentPolylineArr && currentPolylineArr.length > 0) {
- currentPolylineArr.map(item => {
- map.removeLayer(item)
- })
- }
- if (markersArr && markersArr.length > 0) {
- markersArr.map(item => {
- map.removeLayer(item)
- })
- }
- getWaylineSplitApi(id).then(async res => {
- // 拆分大航线
- let url = `${res.data.data.domain_url}${res.data.data.object_key}`
- const { pointList } = await analysisPointLineKmz(url)
- console.log(pointList)
- // 请求拆分列表
- getSplitTableList(pointList)
- res.data.data.wayline_file_list.forEach(async (item, index) => {
- let url = `${item.domain_url}${item.object_key}`
- const { pointList } = await analysisPointLineKmz(url)
- let points = pointList.map(item => {
- return [item.latitude, item.longitude]
- })
- renderLineAndPoint(points, index)
- })
- })
-}
-
-// 渲染线和点
-function renderLineAndPoint (points, index) {
- const colors = [polylineOptions0, polylineOptions1, polylineOptions2]
- const currentPolyline = L.polyline.antPath(points, colors[index]).addTo(map)
- currentPolylineArr.push(currentPolyline)
- // 创建起点图标
- const startIcon = L.icon({
- iconUrl: droneIconSvg, // 起点图片路径
- iconSize: [28, 28], // 图标大小
- })
-
- // 创建终点图标
- const endIcon = L.icon({
- iconUrl: endPointImg, // 终点图片路径
- iconSize: [28, 28],
- iconAnchor: [16, 28],
- popupAnchor: [0, -28],
- })
- // 添加起点标记
- let startMarker = L.marker(points[0], { icon: startIcon }).addTo(map)
- // 添加终点标记
- let endMarker = L.marker(points[points.length - 1], { icon: endIcon }).addTo(map)
- markersArr.push(startMarker, endMarker)
- // 调整地图视图显示整个航线
- map.fitBounds(currentPolyline.getBounds().pad(0.1))
-}
-
-// 请求算法字典字段
-const taskAlgorithm = ref([])
-const requestDictionary = () => {
- getMultipleDictionary('SF').then(res => {
- if (res.code !== 0) {
- // 处理数据
- let result = res.data.data['SF']
- taskAlgorithm.value = result.map(item => ({
- checked: false,
- text: item.dictValue,
- value: item.dictKey,
- }))
- }
- })
-}
-function onClickOverlay () {
- taskAlgorithm.value
- sfValue.value = taskAlgorithm.value.filter(item => item.checked).map(item => item.text)
- formParams.value.ai_types = taskAlgorithm.value.filter(item => item.checked).map(item => item.value)
- sfShow.value = false
-}
-function handleCheckboxChange (item, index) {
- item.checked = !item.checked
- let result = taskAlgorithm.value.filter(item => item.checked)
- if (item.checked && result.length > 3) {
- nextTick(() => {
- item.checked = false
- })
- }
-}
-// 获取列表
-let pageParams = ref({
- wayline_id: '',
- type: 0,
- polygon: [],
- map_lat_lng_list: [],
- safe_height: 120,
- point_height: 120,
- sn: route.query.device_sn,
-})
-let pagingParams = ref({
- current: 1,
- size: 10,
-})
-let tableData = ref([])
-async function getTableList () {
- pageParams.value.wayline_id = formParams.value.file_id
- await getFlyingNestBy(pageParams.value, pagingParams.value).then(res => {
- if (res.data.data && res.data.data.length > 0) {
- tableData.value = res.data.data.map((item, index) => ({
- ...item,
- checked: index === 0 ? true : false,
- estimated_arrival_time: `${item.estimated_arrival_time > 0 ? _.round(item.estimated_arrival_time / 60, 0) : 0}`,
- flight_range: `${item.flight_range > 0 ? _.round(item.flight_range / 1000, 0) : 0}`,
- minute: item.estimated_arrival_time > 0 ? _.round(item.estimated_arrival_time / 60, 0) : 0,
- }))
- formParams.value.dock_sns = [tableData.value[0].device_sn]
- }
- })
-}
-// 航线拆分请求
-async function getSplitTableList (arr) {
- let paramsXYZ = arr.map(item => ({
- x: item.longitude,
- y: item.latitude,
- }))
- const res = await getWaylineSplit({
- points: paramsXYZ,
- sns: [],
- type: 0,
- safe_height: 120,
- point_height: 120,
- })
- isDisabled.value = true
- tableData.value = (res.data?.data || []).map((item, index) => ({
- ...item,
- checked: item.drone_wayline && item.drone_wayline.length > 0 ? true : false,
- estimated_arrival_time: `${item.estimated_arrival_time > 0 ? _.round(item.estimated_arrival_time / 60, 0) : 0}`,
- flight_range: `${item.flight_range > 0 ? _.round(item.flight_range / 1000, 0) : 0}`,
- minute: item.estimated_arrival_time > 0 ? _.round(item.estimated_arrival_time / 60, 0) : 0,
- }))
- formParams.value.dock_sns = tableData.value.filter(item => item.checked).map(item => item.device_sn)
-}
-
-function checkedTable (item) {
- if (isDisabled.value) {
- return showNotify({ type: 'warning', message: '该航线需要多台无人机共同完成!' })
- }
- // 全部设置成false
- tableData.value.forEach(i => {
- i.checked = false
- })
- item.checked = true
- formParams.value.dock_sns = [item.device_sn]
- // 清除航线 针对单航线切换
- if (currentPolylineArr && currentPolylineArr.length > 0) {
- currentPolylineArr.map(item => {
- map.removeLayer(item)
- })
- }
- if (markersArr && markersArr.length > 0) {
- markersArr.map(item => {
- map.removeLayer(item)
- })
- }
- const pointList = _.clone(savePointList)
- pointList.unshift({ latitude: item.latitude, longitude: item.longitude })
- let points = pointList.map(item => {
- return [item.latitude, item.longitude]
- })
- renderLineAndPoint(points, 0)
-}
-
-function handleSubmit () {
- if (loading.value) return
- if (formParams.value.name === '') {
- showNotify({ type: 'warning', message: '请输入任务名称' })
- return
- }
- if (time.value === '') {
- showNotify({ type: 'warning', message: '请选择日期' })
- return
- }
- if (lineName.value === '') {
- showNotify({ type: 'warning', message: '请选择航线' })
- return
- }
- formParams.value.begin_time = `${timeDate.value[0]}-${timeDate.value[1]}-${timeDate.value[2]} 00:00:00`
- formParams.value.end_time = `${timeDate.value[0]}-${timeDate.value[1]}-${timeDate.value[2]} 23:59:59`
-
- const now = new Date()
- const selectedDate = `${timeDate.value[0]}-${timeDate.value[1]}-${timeDate.value[2]}`
- if (dayjs(now).isSame(selectedDate, 'day')) {
- const nowTime = dayjs().format('HH:mm')
- if (nowTime > formParams.value.execute_time_arr[0]) {
- showNotify({ type: 'warning', message: '任务执行时间已超时,请重新选择时间' })
- return
- }
- }
-
- loading.value = true
- createTask(formParams.value)
- .then(res => {
- if (res.data.code === 0) {
- showNotify({ type: 'success', message: '发布成功' })
- loading.value = false
- const transmitData = { data: { type: 'submitSuccess', fun: 'add' } }
- wx.miniProgram.switchTab({ url: `/pages/inspectionTask/index` })
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
- }
- })
- .finally(() => {
- loading.value = false
- })
-}
-let markersLayer = null
-// 全屏地图
-async function handleMapClick () {
- toggleFullscreen()
-}
-
-async function toggleFullscreen () {
- if (isFullscreen.value) {
- exitFullscreen()
- } else {
- enterFullscreen()
- }
-}
-async function enterFullscreen () {
- originalPosition = {
- center: map.getCenter(),
- zoom: map.getZoom(),
- }
- isFullscreen.value = true
-
- await nextTick()
-
- setTimeout(() => {
- refreshMap()
- }, 350)
-}
-
-async function exitFullscreen () {
- isFullscreen.value = false
- nextTick(() => {
- setTimeout(() => {
- refreshMap()
- // 恢复原始位置
- if (originalPosition) {
- map.setView(originalPosition.center, originalPosition.zoom)
- }
- }, 350)
- })
-}
-
-function refreshMap () {
- if (map) {
- map.invalidateSize()
- // map.fire('resize');
- setTimeout(() => {
- // map.setView(map.getCenter());
- }, 50)
- }
-}
-let boundaryInstance = useAreaBoundary()
-const initMap = async () => {
- if (map) return
- map = L.map('taskMap', {
- preferCanvas: true,
- crs: L.CRS.EPSG4326,
- zoomControl: false,
- attributionControl: false,
- doubleClickZoom: false,
- editable: true, //绘制控件
- }).setView([25.992338, 114.823254], 3)
- boundaryInstance.initBoundary(map).then(res => {
- if (route.query.latitude && route.query.longitude) {
- map.setView([route.query.latitude, route.query.longitude], 13)
- } else {
- boundaryInstance.flyMaxBoundary()
- }
- })
-
- markersLayer = L.layerGroup().addTo(map) // 创建一个标注层,便于管理和移除
-}
-
-onMounted(async () => {
- requestDictionary()
- getRouteList()
- await nextTick()
- initMap()
- map.addLayer(layers[0].map)
-})
-
-onUnmounted(() => {
- // EventBus.off('mapSetView', mapSetView)
-})
-</script>
-<style scoped lang="scss">
-.add-task {
- width: 100%;
- height: 100vh;
- overflow: auto;
-
- .task-map {
- position: relative;
- width: 100%;
- height: 206px;
-
- .sf-img {
- position: absolute;
- top: 8px;
- right: 11px;
- z-index: 999;
- }
- }
-
- #taskMap {
- width: 100%;
- height: 100%;
- }
-
- .fullscreen {
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- height: 100vh;
- z-index: 997;
- }
-
- .task-form {
- z-index: 0;
- font-family: Source Han Sans CN, Source Han Sans CN;
-
- .task-title {
- height: 32px;
- line-height: 32px;
- font-weight: bold;
- font-size: 16px;
- color: #222324;
- padding-left: 12px;
- padding-top: 6px;
- }
-
- .card {
- margin: 12px;
- background: #ffffff;
- border-radius: 6px 6px 6px 6px;
-
- .label {
- padding-top: 8px;
- padding-left: 12px;
- color: #222324;
-
- span {
- color: red;
- }
- }
-
- .van-cell {
- border-radius: 6px 6px 6px 6px;
- }
-
- :deep(.van-field__value) {
- border-bottom: 1px solid #efefef;
- }
-
- :deep(.van-cell__right-icon) {
- margin-left: 0px;
- border-bottom: 1px solid #efefef;
- }
-
- .popup-content {
- margin: 12px;
- padding: 8px;
-
- .item-content {
- display: flex;
- align-items: center;
-
- img {
- width: 20px;
- height: 20px;
- }
-
- .empty {
- width: 20px;
- height: 20px;
- border: 1px solid #f5f5f5;
- }
-
- .text {
- margin-left: 18px;
- height: 40px;
- line-height: 40px;
- width: 80%;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- font-size: 14px;
- color: #222324;
- border-bottom: 1px solid #f5f5f5;
- }
- }
- }
- }
-
- .task-list {
- border: 1px solid greenyellow;
- width: 90%;
- height: 38px;
- line-height: 38px;
- background: #ffffff;
- box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.03);
- border-radius: 20px 20px 20px 20px;
- border: 1px solid #e9e9e9;
- font-weight: 400;
- display: flex;
- justify-content: space-around;
- margin: 14px auto;
- }
-
- .name {
- font-weight: bold;
- }
-
- .active {
- background: #1d6fe9;
- color: white;
- }
-
- .task-btn {
- text-align: center;
- margin: 10px auto;
- margin-bottom: 20px;
- height: 38px;
- width: 60%;
-
- :deep(.van-button) {
- height: 38px;
- line-height: 38px;
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/cancelExecution.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/cancelExecution.vue
deleted file mode 100644
index 1a63125..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/cancelExecution.vue
+++ /dev/null
@@ -1,283 +0,0 @@
-<template>
- <div class="cancelExecution">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [7],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = false
- params.value.status_list = [7]
- loading.value = true
- finished.value = false
- getJobList()
-}
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 6) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.cancelExecution {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
-.card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
- .left {
- color: #222324;
- }
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
-}
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executeing.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executeing.vue
deleted file mode 100644
index 9685abe..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executeing.vue
+++ /dev/null
@@ -1,300 +0,0 @@
-<template>
- <div class="executeing">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [2],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = false
- params.value.status_list = [2]
- loading.value = true
- finished.value = false
- getJobList()
-}
-// 监听props.currentTab
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 2) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.executeing {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
-
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
-
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
-
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
-
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
-
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
-
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
-
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
-
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
-
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
-
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- .text {
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
-
- .left {
- color: #222324;
- }
-
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executionError.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executionError.vue
deleted file mode 100644
index 89a8662..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executionError.vue
+++ /dev/null
@@ -1,350 +0,0 @@
-<template>
- <div class="executionError">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" @click.stop="errorClick(item.reason)" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <van-dialog v-model:show="showDialog" :show-confirm-button="false" :show-cancel-button="false">
- <template #title>
- <div class="custom-header">
- <div class="ts">提示</div>
- <div class="close-icon">
- <van-icon name="cross" @click="showDialog = false" />
- </div>
- </div>
- </template>
- <div class="dialog-content">
- <p class="reason">{{ reasonRe || '暂无原因' }}</p>
- </div>
- </van-dialog>
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-import { showToast } from 'vant'
-
-const showDialog = ref(false)
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [5],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-let reasonRe = ref('')
-function errorClick(reason) {
- // showToast(reason)
- reasonRe.value = reason
- showDialog.value = true
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = false
- params.value.status_list = [5]
- loading.value = true
- finished.value = false
- getJobList()
-}
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 5) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.executionError {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- img {
- width: 16px;
- height: 16px;
- margin-right: 2px;
- }
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- .text {
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
- .left {
- color: #222324;
- }
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
- :deep(.van-dialog) {
- min-height: 70px;
- width: 234px;
- border-radius: 8px 8px 8px 8px;
- .van-dialog__header {
- padding-top: 4px;
- }
- .custom-header {
- display: flex;
- justify-items: center;
- justify-content: space-between;
- height: 24px;
- line-height: 24px;
- padding: 0 10px 0 11px;
- .close-icon {
- width: 11px;
- height: 11px;
- }
- .ts {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: bolder;
- font-size: 14px;
- color: #222222;
- }
- }
- .dialog-content {
- position: relative;
- font-size: 14px;
- height: 100%;
- p {
- //margin: 6px auto;
- padding: 6px 17px 11px 17px;
- width: 100%;
- min-height: 30px;
- text-align: justify
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executioned.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executioned.vue
deleted file mode 100644
index 1e64e25..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/executioned.vue
+++ /dev/null
@@ -1,299 +0,0 @@
-<template>
- <div class="executioned">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [3],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = false
- params.value.status_list = [3]
- loading.value = true
- finished.value = false
- getJobList()
-}
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 4) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.executioned {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
-
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
-
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
-
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
-
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
-
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
-
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
-
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
-
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
-
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
-
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- .text {
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
-
- .left {
- color: #222324;
- }
-
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/myTask.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/myTask.vue
deleted file mode 100644
index 75e9b5c..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/myTask.vue
+++ /dev/null
@@ -1,353 +0,0 @@
-<template>
- <div class="myTask">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" @click.stop="errorClick(item.reason)" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <van-dialog v-model:show="showDialog" :show-confirm-button="false" :show-cancel-button="false">
- <template #title>
- <div class="custom-header">
- <div class="ts">提示</div>
- <div class="close-icon">
- <van-icon name="cross" @click="showDialog = false" />
- </div>
- </div>
- </template>
- <div class="dialog-content">
- <p class="reason">{{ reasonRe || '暂无原因' }}</p>
- </div>
- </van-dialog>
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-import { useStore } from 'vuex'
-const store = useStore()
-
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: true,
- app_key_word: '',
- status_list: [],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-let reasonRe = ref('')
-const showDialog = ref(false)
-function errorClick(reason) {
- reasonRe.value = reason
- showDialog.value = true
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = true
- params.value.status_list = []
- loading.value = true
- finished.value = false
- getJobList()
-}
-const consoleShow = computed(() => store?.state?.task?.consoleShow)
-const jobUpdateKey = computed(() => store.state.common.jobUpdateKey)
-const deviceUpdateKey = computed(() => store.state.common.deviceUpdateKey)
-watch([jobUpdateKey, deviceUpdateKey], () => {
- if (consoleShow.value) return
- refreshData()
-})
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 0) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.myTask {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
-
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- img {
- margin-right: 2px;
- width: 16px;
- height: 16px;
- }
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
- :deep(.van-dialog) {
- min-height: 70px;
- width: 234px;
- border-radius: 8px 8px 8px 8px;
- .van-dialog__header {
- padding-top: 4px;
- }
- .custom-header {
- display: flex;
- justify-items: center;
- justify-content: space-between;
- height: 24px;
- line-height: 24px;
- padding: 0 10px 0 11px;
- .close-icon {
- width: 11px;
- height: 11px;
- }
- .ts {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: bolder;
- font-size: 14px;
- color: #222222;
- }
- }
- .dialog-content {
- position: relative;
- font-size: 14px;
- height: 100%;
- p {
- //margin: 6px auto;
- padding: 6px 17px 11px 17px;
- width: 100%;
- min-height: 30px;
- text-align: justify
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/pendingExecution.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/pendingExecution.vue
deleted file mode 100644
index eb5d20d..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/pendingExecution.vue
+++ /dev/null
@@ -1,295 +0,0 @@
-<template>
- <div class="pendingExecution">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <!-- </van-pull-refresh>-->
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { getDeviceJobList } from '@/api/home/task'
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [1],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
- params.value.app_key_word = props.searchTxt
- params.value.my_task = false
- params.value.status_list = [1]
- loading.value = true
- finished.value = false
- getJobList()
-}
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 3) {
- refreshData()
- }
- }
-)
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.pendingExecution {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
-
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
-
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
-
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN, Source Han Sans CN;
-
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
-
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
-
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
-
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
-
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
-
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
-
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- .text {
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
-
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
-
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/planExecute.vue b/applications/mobile-web-view/src/appPages/inspectionTask/compoment/planExecute.vue
deleted file mode 100644
index 7c8871e..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/compoment/planExecute.vue
+++ /dev/null
@@ -1,380 +0,0 @@
-<template>
- <div class="planExecute">
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id">
- <div class="drone_svg">
- <img :src="taskDrone" alt="" />
- </div>
- <div class="drone-right" @click="taskClick(item)">
- <div class="c-top">
- <div class="name">{{ item.name }}</div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" @click.stop="errorClick(item.reason)" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- <div class="c-center">
- <div class="create-name">{{ item.creator_name }}</div>
- <div class="device">
- <img :src="flySvg" alt="" />
- <span class="text">{{ item.device_names }}</span>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item left">{{ item.job_info_num }}</div>
- <div class="item right">
- <div class="value">{{ item.cycle_time_value }}</div>
- <div class="jump" @click="taskClick(item)"><img :src="linkSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <!-- </van-pull-refresh>-->
- <van-dialog v-model:show="showDialog" :show-confirm-button="false" :show-cancel-button="false">
- <template #title>
- <div class="custom-header">
- <div class="ts">提示</div>
- <div class="close-icon">
- <van-icon name="cross" @click="showDialog = false" />
- </div>
- </div>
- </template>
- <div class="dialog-content">
- <p class="reason">{{ reasonRe || '暂无原因' }}</p>
- </div>
- </van-dialog>
- </div>
-</template>
-
-<script setup>
-import taskDrone from '@/appDataSource/inspectionTask/task_drone.png'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import { getDeviceJobList } from '@/api/home/task'
-import linkSvg from '@/appDataSource/inspectionTask/link.svg'
-import { showToast } from 'vant'
-import { useRoute } from 'vue-router'
-import { useStore } from 'vuex'
-const store = useStore()
-const route = useRoute()
-const props = defineProps(['indexTab', 'searchTxt'])
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- app_key_word: '',
- status_list: [1, 2, 3, 5, 7],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-const emit = defineEmits(['taskDetails'])
-function taskClick(row) {
- emit('taskDetails', row)
-}
-const showDialog = ref(false)
-let reasonRe = ref('')
-function errorClick(reason) {
- // showToast(reason)
- reasonRe.value = reason
- showDialog.value = true
-}
-function refreshData() {
- list.value = []
- sizeParams.value.current = 1
-
- params.value.my_task = false
- params.value.status_list = [1, 2, 3, 5, 7]
- loading.value = true
- finished.value = false
- getJobList()
-}
-// 监听props.currentTab
-watch(
- () => props.searchTxt,
- (newValue, oldValue) => {
- params.value.app_key_word = props.searchTxt
- refreshData()
- }
-)
-watch(
- () => props.indexTab,
- (newValue, oldValue) => {
- if (newValue.name === 1) {
- params.value.app_key_word = props.searchTxt
- refreshData()
- }
- }
-)
-// watch(
-// () => route.query,
-// (newValue, oldValue) => {
-// if (newValue.sxListKey) {
-// refreshData()
-// }
-// },
-// { deep: true })
-watch(
- () => route.query,
- (newValue, oldValue) => {
- if (newValue.updateKey) {
- params.value.app_key_word = ''
- refreshData()
- }
- // 监听
- console.log(newValue.sxListKey, '888')
- if (newValue.sxListKey) {
- refreshData()
- }
- },
- { deep: true })
-onMounted(() => {
- refreshData()
-})
-</script>
-<style scoped lang="scss">
-.planExecute {
- //height: calc(100vh - 54px - 74px);
- //overflow: auto;
-
- .card {
- margin: 12px;
- padding: 13px 9px 12px 8px;
- height: 93px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
- .drone_svg {
- margin-right: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- width: 55px;
- height: 68px;
-
- background: rgba(251, 251, 251, 0.54);
- box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.06);
- border-radius: 12px 12px 12px 12px;
- border: 1px solid rgba(212, 212, 212, 0.99);
-
- img {
- width: 49.63px;
- height: 33.67px;
- }
- }
- .drone-right {
- width: calc(100% - 55px - 8px);
- font-family: Source Han Sans CN;
- .c-top {
- height: 20px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 7px;
- .name {
- width: 68%;
- font-weight: 500;
- font-size: 16px;
- color: #191919;
- line-height: 20px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- img {
- width: 16px;
- height: 16px;
- margin-right: 2px;
- }
- .status {
- padding: 0 4px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: #ffffff;
- font-size: 14px;
- font-weight: 500;
- border-radius: 4px 4px 4px 4px;
- }
- }
- .c-center {
- height: 21px;
- display: flex;
- align-items: center;
- margin-bottom: 5px;
- .device {
- display: flex;
- align-items: center;
- min-width: 88px;
- height: 21px;
- background: rgba(174, 185, 255, 0.38);
- border-radius: 4px 4px 4px 4px;
- padding: 0 8px;
- img {
- width: 15px;
- height: 15px;
- margin-right: 4px;
- }
- font-weight: 500;
- font-size: 13px;
- color: #2160ff;
- line-height: 21px;
- .text {
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .create-name {
- padding: 0 8px;
- width: 58px;
- height: 21px;
- background: #dae6ff;
- border-radius: 4px 4px 4px 4px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- line-height: 21px;
- text-align: center;
- margin-right: 10px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- .c-bottom {
- height: 20px;
- line-height: 20px;
- display: flex;
- justify-content: space-between;
- font-size: 13px;
- font-weight: 400;
- .left {
- color: #222324;
- }
- .right {
- color: #191919;
- display: flex;
- align-items: center;
- justify-items: center;
- .value {
- margin-right: 4px;
- }
- .jump {
- img {
- height: 11px;
- width: 7px;
- margin-top: 2px;
- }
- }
- }
- }
- }
- }
- .card:first-child {
- margin: 0px 12px 12px 12px;
- }
- :deep(.van-dialog) {
- min-height: 70px;
- width: 234px;
- border-radius: 8px 8px 8px 8px;
- .van-dialog__header {
- padding-top: 4px;
- }
- .custom-header {
- display: flex;
- justify-items: center;
- justify-content: space-between;
- height: 24px;
- line-height: 24px;
- padding: 0 10px 0 11px;
- .close-icon {
- width: 11px;
- height: 11px;
- }
- .ts {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: bolder;
- font-size: 14px;
- color: #222222;
- }
- }
- .dialog-content {
- position: relative;
- font-size: 14px;
- height: 100%;
- p {
- //margin: 6px auto;
- padding: 6px 17px 11px 17px;
- width: 100%;
- min-height: 30px;
- text-align: justify
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/achievementData.vue b/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/achievementData.vue
deleted file mode 100644
index 57a0cfd..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/achievementData.vue
+++ /dev/null
@@ -1,364 +0,0 @@
-<template>
- <div class="achievement-data">
- <van-list
- v-model:loading="loading"
- :finished="finished"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getList"
- >
- <div class="achievements">
- <div class="card" v-for="item in list" :key="item.id">
- <div class="bg-img">
- <van-checkbox v-model="item.checked" shape="square"></van-checkbox>
- <van-image v-if="item.extension.includes('jpeg')" :src="item.smallUrl" fit="cover" />
-
- <div class="video-content" v-if="item.extension.includes('mp4')" @click="showImagePreviews(item)">
- <div class="shade"></div>
-
- <div class="paly-icon"></div>
-
- <img class="videoDisplay" :src="convertVideoUrlToThumbnail(item.link)" alt="" />
- </div>
- </div>
- <div class="title">{{ item.eventName || item.nickName }}</div>
- <div class="time-sf">
- <div class="time">
- <span v-if="item.status === 0" style="background-color: #ff7411"></span>
- <span v-else-if="item.status === 2" style="background-color: #ff472f"></span>
- <span v-else-if="item.status === 3" style="background-color: #ffc300"></span>
- <span v-else-if="item.status === 4" style="background-color: #06d957"></span>
- {{ formatDate(item.createTime) }}
- </div>
- <div class="sf" @click="showImagePreviews(item)"><img :src="sfSvg" alt="" /></div>
- </div>
- </div>
- </div>
- </van-list>
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- <div class="btns" v-if="list.length > 0">
- <van-button class="btn all-checked" round block type="primary" color="#00994D" @click="AllChecked">
- {{ isAllChecked ? '取消全选' : '全选' }}
- </van-button>
- <van-button class="btn down-load" round block type="primary" color="#1D6FE9" @click="downLoad">下载</van-button>
- </div>
- <van-dialog v-model:show="showDialog" :show-confirm-button="false" :show-cancel-button="false">
- <template #title>
- <div class="custom-header">
- <van-icon name="cross" class="close-icon" @click="showDialog = false" />
- </div>
- </template>
- <div class="dialog-content">
- <video class="video-player" ref="videoRefs" controls :src="videoUrl" preload="auto"
- @play="handleVideoPlay"
- @ended="handleVideoEnded">
- <source :src="videoUrl" type="video/mp4" />
- </video>
- </div>
- </van-dialog>
- </div>
-</template>
-<script setup>
-import sfSvg from '@/appDataSource/inspectionTask/sf.svg'
-import { aiImagesPage, getDownloadStatusApi, attachDownload } from '@/api/dataCenter'
-import { getShowImg, getSmallImg, getzsSmallImg, getzsShowImg, aLinkDownloadUtil } from '@/utils/util'
-import { getJobDetails } from '@/api/home/task'
-import { showImagePreview, showNotify, showLoadingToast, closeToast } from 'vant'
-import dayjs from 'dayjs'
-import { ref } from 'vue'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-
-const props = defineProps(['wayLineJobInfoId'])
-const currentIndex = ref(null)
-const imageArr = ref([])
-const total = ref(0)
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const list = ref([])
-const videoRefs = ref(null)
-const emit = defineEmits(['returnNum'])
-// 视频播放事件处理
-const handleVideoPlay = (event) => {
- if (event.target.playbackRate !== 0.75) {
- event.target.playbackRate = 0.75
-
- }
-}
-const handleVideoEnded = index => {
- // 获取当前视频
- const video = videoRefs.value
-
- // 重置视频播放时间为 0
- video.currentTime = 0
-
- // 重新加载视频
- video.load()
-}
-const detailsObj = inject('detailsObj')
-function getList() {
- loading.value = true
- // getJobDetails({ wayLineJobInfoId: props.wayLineJobInfoId, waylineJobId: route.query.waylineJobId, batchNo: route.query.batch_no }).then(async res => {
- aiImagesPage({
- wayLineJobId: detailsObj.value.job_id,
- resultTypes: [0, 1, 2, 4, 5],
- orderByCreateTime: true,
- current: 1,
- size: 2000,
- }).then(res => {
- if (res.data.data.records.length > 0) {
- list.value = res.data.data.records.map(i => ({
- ...i,
- checked: false,
- smallUrl: i.resultType === 4 ? getzsSmallImg(i.link) : getSmallImg(i.link),
- showUrl: i.resultType === 4 ? getzsShowImg(i.link) : getShowImg(i.link),
- }))
- total.value = res.data.data.total
- imageArr.value = list.value.filter(item => item.extension.includes('jpeg')).map(item => item.showUrl)
- }
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- loading.value = false
- })
- // })
-}
-const isAllChecked = ref(false)
-function AllChecked() {
- isAllChecked.value = !isAllChecked.value
- list.value = list.value.map(i => ({
- ...i,
- checked: isAllChecked.value ? true : false,
- }))
-}
-function showImagePreviews(val) {
- console.log(val.extension)
- if (val.extension.includes('jpeg')) {
- currentIndex.value = list.value.findIndex(item => item.event_num === val.event_num)
- showImagePreview({
- images: imageArr.value,
- startPosition: currentIndex.value,
- })
- } else {
- clickVideo(val)
- }
-}
-const formatDate = dateString => {
- return dayjs(dateString).format('MM/DD HH:mm')
-}
-// 下载
-async function downLoad() {
- const checkedList = list.value.filter(i => i.checked)
- if (checkedList.length === 0) {
- return showNotify({ type: 'warning', message: '请选择要下载的图片' })
- }
- for (let i = 0; i < checkedList.length; i++) {
- const item = checkedList[i]
- const suffix = item.link.split('.').pop()
-
- await new Promise(resolve => {
- setTimeout(() => {
- aLinkDownloadUtil(item.link, item.nickName + '.' + suffix)
- resolve()
- }, 1000) // 1秒间隔
- })
- }
- // checkedList.forEach((item, index) => {
- // const suffix = item.link.split('.').pop()
- // aLinkDownloadUtil(item.link, item.nickName + '.' + suffix)
- // })
- // if (checkedList.length === 1) {
- //
- // } else {
- // // 显示加载
- // showLoadingToast({
- // duration: 0, // 持续显示,不会自动关闭
- // forbidClick: true, // 禁止背景点击
- // message: '打包中,请稍等...',
- // overlay: true, // 显示遮罩层
- // background: 'rgba(0, 0, 0, 0.5)',
- // });
- // const fileIds = checkedList.map(i => i.id)
- // const res = await getDownloadStatusApi({ type: 'dpsjzx' })
- //
- // if (!['CANCELLED', 'COMPLETED'].includes(res.data.data?.status || 'COMPLETED')) {
- // return showNotify({ type: 'warning', message: '还有正在处理的' })
- // }
- // attachDownload({ attachIds: fileIds, type: 'dplsrwxq' }).finally(() => {
- // closeToast();
- // })
- // }
-}
-const showDialog = ref(false)
-let videoUrl = ref('')
-function clickVideo(item) {
- showDialog.value = true
- videoUrl = item.link
-}
-
-function convertVideoUrlToThumbnail(videoUrl) {
- // 检查是否是有效的视频URL
- if (!videoUrl || typeof videoUrl !== 'string') {
- return videoUrl
- }
- // 替换文件扩展名
- return videoUrl.replace(/\.mp4$/, '_small.jpg')
-}
-
-watch(detailsObj, (newVal) => {
- getList()
-})
-
-onMounted(() => {
- // getList()
-})
-</script>
-
-<style lang="scss" scoped>
-.achievement-data {
- margin: 12px;
- .achievements {
- //margin: 10px 0;
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- .card {
- width: calc((100vw - 12px - 12px - 10px) / 2);
- height: 146px;
- background: #ffffff;
- border-radius: 6px 6px 6px 6px;
- .bg-img {
- width: calc((100vw - 12px - 12px - 10px) / 2);
- height: 98px;
- margin-bottom: 4px;
- position: relative;
- :deep(.van-checkbox__icon .van-icon) {
- border-radius: 4px 4px 4px 4px;
- border: 1px solid #ffffff;
- }
- .van-checkbox {
- position: absolute;
- top: 7px;
- left: 9px;
- background: rgba(86, 86, 86, 0.4);
- backdrop-filter: blur(0.4rem);
- z-index: 1;
- }
- :deep(.van-image) {
- width: 100%;
- height: 100%;
- border-radius: 6px 6px 6px 6px;
- img {
- border-radius: 6px 6px 6px 6px;
- }
- }
- .videoDisplay {
- width: 100%;
- height: 100%;
- border-radius: 6px 6px 6px 6px;
- object-fit: cover;
- }
- }
-
- .video-content {
- position: relative;
- width: 100%;
- height: 100%;
- border-radius: 6px 6px 6px 6px;
- overflow: hidden;
-
- .shade {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(26, 26, 26, 0.25);
- }
-
- .paly-icon {
- position: absolute;
- top: 50%;
- left: 50%;
- width: 42px;
- height: 42px;
- background: url('@/appDataSource/inspectionTask/video-play.png') no-repeat center / 100% 100%;
- transform: translate(-50%, -50%);
- }
-
- .videoDisplay {
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- }
-
- .title {
- padding: 0 4px;
- font-weight: 500;
- font-size: 14px;
- color: #000000;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .time-sf {
- padding: 0 4px;
- display: flex;
- justify-content: space-between;
- .time {
- font-size: 12px;
- span {
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 50%;
- margin-right: 4px;
- }
- color: #a6a6a6;
- }
- }
- }
- }
- .btns {
- position: fixed;
- bottom: 10px;
- left: 10px;
- right: 10px;
- display: flex;
- gap: 10px;
- z-index: 1000;
- .all-checked {
- width: 30%;
- }
- .down-load {
- width: 68%;
- }
- }
- :deep(.van-dialog) {
- width: 100vw;
- background-color: rgba(33, 33, 33, 0.8);
- .custom-header {
- position: absolute;
- top: 0;
- .close-icon {
- position: fixed;
- top: 6px;
- right: 10px;
- color: white;
- }
- border: 1px solid #e4e7ed;
- }
- .dialog-content {
- height: 200px;
- position: relative;
- .video-player {
- width: 100%;
- height: 100%;
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/details.vue b/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/details.vue
deleted file mode 100644
index 8deff05..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/details.vue
+++ /dev/null
@@ -1,381 +0,0 @@
-<template>
- <div class="yzx-details">
- <div class="det-title">
- <div class="title">执行机巢详情</div>
- <div class="contain">
- <div class="img-title">
- <img :src="flySvg" alt="" />
- {{ details.device_names }}
- </div>
- <div class="img-status">
- <img v-if="details.status === 5" :src="errorSvg" alt="" @click.stop="errorClick" />
- <div class="status" :style="{ background: selectedColor }">{{ selectedStatus }}</div>
- </div>
- </div>
- </div>
- <TaskContent :taskDetails="details" />
- <div class="task-line">
- <div class="title">任务航线</div>
- <div class="details-map" :class="{ 'fullscreen': isFullscreen }">
- <div class="sf-img" @click.stop="handleMapClick"><img :src="isFullscreen ? suoSvg : fangSvg" alt="" /></div>
- <div id="detailsMap"></div>
- </div>
- </div>
- <van-dialog v-model:show="showDialog" :show-confirm-button="false" :show-cancel-button="false">
- <template #title>
- <div class="custom-header">
- <div class="ts">提示</div>
- <div class="close-icon">
- <van-icon name="cross" @click="showDialog = false" />
- </div>
- </div>
- </template>
- <div class="dialog-content">
- <p class="reason">{{ details.reason || '暂无原因' }}</p>
- </div>
- </van-dialog>
- </div>
-</template>
-<script setup>
-import { getJobDetails } from '@/api/home/task'
-import { getFindAction } from '@/utils/cesium/pointWayLineUtils'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-import _ from 'lodash'
-import L from 'leaflet'
-import 'leaflet/dist/leaflet.css'
-import sl from '@/appDataSource/leafletMapIcon/sl.svg'
-import yx from '@/appDataSource/leafletMapIcon/yx.svg'
-import suoSvg from '@/appDataSource/inspectionTask/suo-bg.svg'
-import fangSvg from '@/appDataSource/inspectionTask/fang-bg.svg'
-import { analysisPointLineKmz } from '@/utils/cesium/pointWayLineUtils'
-import startImg from '@/assets/images/signMachineNest/rwqfd.png'
-import droneIconSvg from '@/appDataSource/leafletMapIcon/drone-icon.svg'
-import endPointImg from '@/assets/images/EndPointicon.png'
-import TaskContent from '@/appPages/inspectionTask/TaskInProgress/TaskContent.vue'
-import { useIdentificationAreaForApp } from '@ztzf/hooks'
-import 'leaflet-ant-path'
-import {
- basemapLayer0,
- basemapLayer1,
- basemapLayer2,
- basemapLayer3,
- polylineOptions0,
- polylineOptions1,
- polylineOptions2,
-} from '@/const/leafletConst'
-import { useAreaBoundary } from '@/hooks/useAreaBoundary'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-const basemap0 = L.layerGroup([basemapLayer0, basemapLayer1])
-const basemap1 = L.layerGroup([basemapLayer2, basemapLayer3])
-const layers = [
- {
- src: sl,
- name: '天地图电子',
- key: 1,
- map: basemap0,
- },
- {
- src: yx,
- name: '天地图影像',
- key: 2,
- map: basemap1,
- },
-]
-let map = null
-
-const props = defineProps(['wayLineJobInfoId'])
-const flightEvents = ref([])
-const details = inject('detailsObj')
-const taskWayLineDetails = inject('taskWayLineDetails')
-
-async function getDetails() {
- const params = {
- wayLineJobInfoId: props.wayLineJobInfoId,
- waylineJobId: route.query.waylineJobId,
- batchNo: route.query.batch_no
- }
-
- // getJobDetails(params).then(async res => {
- // details.value = res.data.data
- // 飞行事件
- try {
- flightEvents.value = details?.value.action_modes.flatMap(item => getFindAction(item, 'app'))
- // 状态
- selectedColor.value = listStatus.value.find(item => item.status.includes(details.value.status)).color
- selectedStatus.value = listStatus.value.find(item => item.status.includes(details.value.status)).name
- // 显示航线
-
- console.log(taskWayLineDetails, 111111111)
- const { pointList } = await analysisPointLineKmz(taskWayLineDetails.value[0].url)
- let points = pointList.map(item => {
- return [item.latitude, item.longitude]
- })
- // 连接到机巢
- points.unshift([details.value.latitude, details.value.longitude])
- let currentPolyline = L.polyline.antPath(points, polylineOptions0).addTo(map)
- // 创建起点图标
- const startIcon = L.icon({
- iconUrl: droneIconSvg, // 起点图片路径
- iconSize: [28, 28], // 图标大小
- })
-
- // 创建终点图标
- const endIcon = L.icon({
- iconUrl: endPointImg, // 终点图片路径
- iconSize: [28, 28],
- iconAnchor: [16, 28],
- popupAnchor: [0, -28],
- })
- // 添加起点标记
- L.marker(points[0], { icon: startIcon }).addTo(map)
- // 添加终点标记
- L.marker(points[points.length - 1], { icon: endIcon }).addTo(map)
- // 调整地图视图显示整个航线
- map.fitBounds(currentPolyline.getBounds().pad(0.1))
- // 自定义识别区渲染
- const {setArea,removeArea } = useIdentificationAreaForApp()
- setArea(details.value.ai_types.split(','),map)
- // })
- } catch (error) {
- // 航线不存在 解析会报错
- console.log(error,'error')
- if (map) {
- map.setView([details.value.latitude, details.value.longitude], 13);
- }
- }
-}
-const selectedColor = ref('')
-const selectedStatus = ref('')
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-let boundaryInstance = useAreaBoundary()
-let markersLayer = null
-const initMap = () => {
- if (map) return
- map = L.map('detailsMap', {
- preferCanvas: true,
- crs: L.CRS.EPSG4326,
- zoomControl: false,
- attributionControl: false,
- doubleClickZoom: false,
- editable: true, //绘制控件
- }).setView([25.992338, 114.823254], 13)
- boundaryInstance.initBoundary(map)
- markersLayer = L.layerGroup().addTo(map) // 创建一个标注层,便于管理和移除
-}
-const showDialog = ref(false)
-function errorClick() {
- showDialog.value = true
-}
-const isFullscreen = ref(false)
-async function handleMapClick() {
- if (isFullscreen.value) {
- isFullscreen.value = false
- } else {
- isFullscreen.value = true
- }
- await nextTick()
- setTimeout(() => {
- map.invalidateSize()
- }, 350)
-}
-
-let activeTab = inject('activeTab')
-
-watch(activeTab, (newValue,oldValue) => {
- isFullscreen.value = true
- handleMapClick()
-},{immediate:true})
-
-watch(details, (newVal) => {
- getDetails()
-})
-
-onMounted(async () => {
- // getDetails()
- await nextTick()
- initMap()
- map.addLayer(layers[0].map)
-})
-</script>
-
-<style lang="scss" scoped>
-.yzx-details {
- .det-title {
- height: 86px;
- background: white;
- margin: 12px;
- padding: 8px;
- border-radius: 6px 6px 6px 6px;
- .title {
- height: 30px;
- font-weight: bold;
- font-size: 16px;
- color: #222324;
- }
- .contain {
- height: 38px;
- line-height: 38px;
- background: #e6f0ff;
- box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.03);
- border-radius: 6px 6px 6px 6px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 0 12px;
-
- .img-title {
- display: flex;
- align-items: center;
- font-weight: 500;
- font-size: 14px;
- color: #282828;
- margin-right: 4px;
- }
- .img-status {
- display: flex;
- }
- .status {
- margin-left: 4px;
- padding: 0 6px;
- min-width: 54px;
- height: 22px;
- line-height: 22px;
- text-align: center;
- color: white;
- //background: #39b002;
- border-radius: 4px 4px 4px 4px;
- }
- }
- }
- .det-contain {
- background: white;
- margin: 12px;
- padding: 8px 8px 23px 8px;
- border-radius: 6px 6px 6px 6px;
- .title {
- font-weight: bold;
- font-size: 16px;
- color: #222324;
- }
- .item {
- height: 40px;
- line-height: 40px;
- padding: 0 14px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- .left {
- font-weight: 400;
- font-size: 15px;
- color: #222324;
- }
- .right {
- text-align: right;
- width: 60%;
- font-weight: 400;
- font-size: 15px;
- color: #7b7b7b;
- align-items: center;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .flightEvents {
- display: flex;
- align-items: center;
- justify-content: end;
- > img {
- width: 22px;
- height: 22px;
- margin-right: 2px;
- }
- }
- border-bottom: 1px solid #f5f5f5;
- }
- }
- .task-line {
- height: 260px;
- background: #ffffff;
- border-radius: 6px 6px 6px 6px;
- margin: 12px;
- padding: 12px;
- .title {
- font-weight: bold;
- font-size: 16px;
- color: #222324;
- margin-bottom: 7px;
- }
- .details-map {
- width: 100%;
- height: 206px;
- position: relative;
- .sf-img {
- position: absolute;
- top: 8px;
- right: 11px;
- z-index: 999;
- }
- }
- #detailsMap {
- width: 100%;
- height: 100%;
- border-radius: 6px 6px 6px 6px;
- }
- .fullscreen {
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- margin-top: 44px;
- height: calc(100vh - 44px);
- z-index: 997;
- }
- }
- :deep(.van-dialog) {
- min-height: 70px;
- width: 234px;
- border-radius: 8px 8px 8px 8px;
- .van-dialog__header {
- padding-top: 4px;
- }
- .custom-header {
- display: flex;
- justify-items: center;
- justify-content: space-between;
- height: 24px;
- line-height: 24px;
- padding: 0 10px 0 11px;
- .close-icon {
- width: 11px;
- height: 11px;
- }
- .ts {
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: bolder;
- font-size: 14px;
- color: #222222;
- }
- }
- .dialog-content {
- position: relative;
- font-size: 14px;
- height: 100%;
- p {
- //margin: 6px auto;
- padding: 6px 17px 11px 17px;
- width: 100%;
- min-height: 30px;
- text-align: justify
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/events.vue b/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/events.vue
deleted file mode 100644
index 005a70f..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/execution/compoment/events.vue
+++ /dev/null
@@ -1,164 +0,0 @@
-<template>
- <div class="yzx-events">
- <van-list v-model:loading="loading" :finished="finished" :error="error" error-text="加载失败,点击重新加载"
- @load="getList">
- <div class="events">
- <div class="eve-card" v-for="(item,index) in list" :key="item.id">
- <div class="bg-img" @click="jumpOrder(item,index+1)">
- <!-- <img :src="item.photo_url" alt="">-->
- <van-image :src="item.smallUrl" fit="cover" />
- </div>
- <div class="title">{{ item.ai_types || '暂无事件' }}</div>
- <div class="time-sf">
- <div class="time">
- <span v-if="item.status === 0" style="background-color: #ff7411"></span>
- <span v-else-if="item.status === 2" style="background-color: #ff472f"></span>
- <span v-else-if="item.status === 3" style="background-color: #ffc300"></span>
- <span v-else-if="item.status === 4" style="background-color: #06d957"></span>
- {{ formatDate(item.job_create_time) }}
- </div>
- <div class="sf" @click.stop="showImagePreviews(item)"><img :src="sfSvg" alt=""></div>
- </div>
- </div>
- </div>
- </van-list>
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- </div>
-</template>
-<script setup>
-import sfSvg from '@/appDataSource/inspectionTask/sf.svg'
-import { getDeviceEventList } from '@/api/home/machineNest'
-import { showImagePreview } from 'vant'
-import { getShowImg, getSmallImg } from '@/utils/util'
-import dayjs from 'dayjs'
-import { ref } from 'vue'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-
-const props = defineProps(['wayLineJobInfoId'])
-
-const total = ref(0)
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const list = ref([])
-const emit = defineEmits(['returnNum'])
-const currentIndex = ref(null)
-const imageArr = ref([])
-
-function getList () {
- loading.value = true
- const params = {
- way_line_job_info_id: props.wayLineJobInfoId,
- batch_no: route.query.batch_no,
- }
- getDeviceEventList(params, { current: 1, size: 1999 }).then(res => {
- const resData = res?.data?.data || {}
- if (resData.records.length > 0) {
- list.value = resData.records.map(i => ({
- ...i,
- url: i.photo_url,
- smallUrl: getSmallImg(i.photo_url),
- showUrl: getShowImg(i.photo_url)
- }))
- }
- total.value = res.data.data.total
- imageArr.value = list.value.map(item => item.showUrl)
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- loading.value = false
- })
-}
-
-function showImagePreviews (val) {
- currentIndex.value = list.value.findIndex(item => item.event_num === val.event_num)
- showImagePreview({
- images: imageArr.value,
- startPosition: currentIndex.value,
- })
-}
-
-const formatDate = dateString => {
- return dayjs(dateString).format('MM/DD HH:mm')
-}
-
-function jumpOrder (item, current) {
- const transmitData = { data: { type: 'workid', eventNum: item.event_num, wLJobInfoId: props.wayLineJobInfoId,current } }
-
- wx.miniProgram.navigateTo({ url: `/subPackages/workDetail/index?eventNum=${item.event_num}&wLJobInfoId=${props.wayLineJobInfoId}¤t=${current}` })
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-
-onMounted(() => {
- getList()
-})
-</script>
-
-<style lang="scss" scoped>
-.yzx-events {
- margin: 12px;
-
- .events {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
-
- .eve-card {
- width: calc((100vw - 12px - 12px - 10px)/2);
- height: 146px;
- background: #FFFFFF;
- border-radius: 6px 6px 6px 6px;
-
- .bg-img {
- width: calc((100vw - 12px - 12px - 10px)/2);
- height: 98px;
- margin-bottom: 4px;
-
- :deep(.van-image) {
- width: 100%;
- height: 100%;
-
- img {
- border-radius: 6px 6px 6px 6px;
- }
- }
- }
-
- .title {
- padding: 0 4px;
- font-weight: 500;
- font-size: 14px;
- color: #000000;
- white-space: nowrap;
- /* 不换行 */
- overflow: hidden;
- /* 超出隐藏 */
- text-overflow: ellipsis;
- /* 显示省略号 */
- }
-
- .time-sf {
- padding: 0 4px;
- display: flex;
- justify-content: space-between;
-
- span {
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 50%;
- //margin-right: 2px;
- }
-
- .time {
- font-size: 12px;
- color: #a6a6a6;
- }
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/execution/index.vue b/applications/mobile-web-view/src/appPages/inspectionTask/execution/index.vue
deleted file mode 100644
index fc0cc7d..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/execution/index.vue
+++ /dev/null
@@ -1,146 +0,0 @@
-<template>
- <div class="execution-container">
- <!-- 固定头部 tabs -->
- <div class="fixed-tabs">
- <van-tabs
- v-model:active="active"
- title-active-color="#1989fa"
- title-inactive-color="#646566"
- sticky
- @click-tab="tabClick"
- >
- <van-tab title="任务情况" name="任务情况"/>
- <van-tab title="关联事件" name="关联事件" :badge="eventTotal" />
- <van-tab title="成果数据" name="成果数据" :badge="resultTotal" />
- </van-tabs>
- </div>
-
- <!-- 可滚动的内容区域 -->
- <div class="scroll-content">
- <div v-show="active === '任务情况'" class="tab-content">
- <ex-details :wayLineJobInfoId="route.query.wayLineJobInfoId" />
- </div>
-
- <div v-show="active === '关联事件'" class="tab-content">
- <ex-events :wayLineJobInfoId="route.query.wayLineJobInfoId" />
- </div>
-
- <div v-show="active === '成果数据'" class="tab-content tab-content-cg">
- <achievementData :wayLineJobInfoId="route.query.wayLineJobInfoId" />
- </div>
- </div>
- </div>
-</template>
-
-<script setup>
-import { getDeviceEventList } from '@/api/home/machineNest'
-import { aiImagesPage } from '@/api/dataCenter'
-import {getJobWayLineDetails} from '@ztzf/apis'
-
-import { getJobDetails } from '@/api/home/task'
-import { useRoute } from 'vue-router'
-import exDetails from './compoment/details.vue'
-import exEvents from './compoment/events.vue'
-import achievementData from './compoment/achievementData.vue'
-import { setStore } from '@/utils/store'
-const active = ref('任务情况')
-provide('activeTab', active)
-const route = useRoute()
-
-const eventTotal = ref(0)
-function returnNumEx(value) {
- eventTotal.value = value
-}
-const resultTotal = ref(0)
-function returnNumE(value) {
- resultTotal.value = value
-}
-function tabClick(value) {
- active.value = value.name
-}
-
-const detailsObj = ref({})
-const taskWayLineDetails = ref([])
-provide('detailsObj', detailsObj)
-provide('taskWayLineDetails', taskWayLineDetails)
-
-onMounted(() => {
- console.log(route.query, '8888')
- // const item = JSON.parse(decodeURIComponent(route.query.rowItem))
- const params = {
- way_line_job_info_id: route.query.wayLineJobInfoId,
- batch_no: route.query.batch_no,
- }
- getDeviceEventList(params, { current: 1, size: 1999 }).then(res => {
- eventTotal.value = res.data.data.total;
- })
- getJobDetails({ wayLineJobInfoId: route.query.wayLineJobInfoId, waylineJobId: route.query.waylineJobId, batchNo: route.query.batch_no }).then(async resDetails => {
- detailsObj.value = resDetails.data.data
- aiImagesPage({ wayLineJobId: detailsObj.value.job_id, resultTypes: [0, 1, 2, 4, 5],orderByCreateTime:true,current: 1,size:2000 }).then(res => {
- resultTotal.value = res.data.data.total;
- })
- })
- getJobWayLineDetails({ wayLineJobInfoId: route.query.wayLineJobInfoId, waylineJobId: route.query.waylineJobId, batchNo: route.query.batch_no }).then(async res => {
- taskWayLineDetails.value = res.data.data
- })
-})
-</script>
-
-<style lang="scss" scoped>
-.execution-container {
- height: 100vh;
- display: flex;
- flex-direction: column;
- font-family: Source Han Sans CN, Source Han Sans CN;
- :deep(.van-badge) {
- position: initial;
- background-color: #1D6FE9;
- }
- :deep(){
- .van-tabs__nav{
- background: transparent;
- }
- }
- .van-tabs{
- background: transparent;
- :deep(.van-tab) {
- font-size: 15px;
- font-weight: 400;
- }
- :deep(.van-badge__wrapper) {
- display: flex;
- justify-items: center;
- align-items: center;
- }
- :deep(.van-badge--top-right) {
- transform: none;
- }
- }
- .fixed-tabs {
- flex-shrink: 0; /* 防止 tabs 被压缩 */
- z-index: 1000;
- }
-
- .scroll-content {
- flex: 1;
- overflow-y: auto;
- -webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
- }
-
- .tab-content {
- height: 100%;
- overflow-y: auto;
- }
- .tab-content-cg {
- -webkit-overflow-scrolling: touch;
- padding-bottom: 48px; /* 预留按钮高度 + 间距 */
- }
-
- /* 确保内容区域在 tabs 下面 */
- :deep(.van-tabs__wrap) {
- position: sticky;
- top: 0;
- z-index: 1000;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/index.vue b/applications/mobile-web-view/src/appPages/inspectionTask/index.vue
deleted file mode 100644
index 7bdbccf..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/index.vue
+++ /dev/null
@@ -1,276 +0,0 @@
-<template>
- <div class="inspectionTask" :style="{ paddingTop: route.query.topMargin + 'px' }">
- <van-search v-model="app_key_word" enterkeyhint="go" placeholder="请输入任务编号/名称/机巢名称/创建人" shape="round"
- @search="handleSearch" @clear="onCancel" />
-
- <van-tabs v-model:active="currentTab" @click-tab="onClickTab" line-width="26">
- <van-tab title="我的任务">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">我的任务</div>
- <div class="tab-badge">{{ tabList[0].number }}</div>
- </div>
- </template>
- <MyTask :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails"></MyTask>
- </van-tab>
- <van-tab title="计划执行">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">计划执行</div>
- <div class="tab-badge">{{ tabList[1].number }}</div>
- </div>
- </template>
- <planExecute :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails"></planExecute>
- </van-tab>
- <van-tab title="执行中">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">执行中</div>
- <div class="tab-badge">{{ tabList[2].number }}</div>
- </div>
- </template>
- <executeing :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails"></executeing>
- </van-tab>
- <van-tab title="待执行">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">待执行</div>
- <div class="tab-badge">{{ tabList[3].number }}</div>
- </div>
- </template>
- <pendingExecution :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails">
- </pendingExecution>
- </van-tab>
- <van-tab title="已执行">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">已执行</div>
- <div class="tab-badge">{{ tabList[4].number }}</div>
- </div>
- </template>
- <executioned :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails"></executioned>
- </van-tab>
- <van-tab title="执行失败">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">执行失败</div>
- <div class="tab-badge">{{ tabList[5].number }}</div>
- </div>
- </template>
- <executionError :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails">
- </executionError>
- </van-tab>
- <van-tab title="取消执行">
- <template #title>
- <div class="custom-tab-title">
- <div class="tab-text">取消执行</div>
- <div class="tab-badge">{{ tabList[6].number }}</div>
- </div>
- </template>
- <cancelExecution :indexTab="indexTab" :searchTxt="search_txt" @taskDetails="taskDetails">
- </cancelExecution>
- </van-tab>
- </van-tabs>
-
- <div class="add-task-btn" v-if="showAddBtn">
- <img :src="addBtnSvg" alt="" @click="addTask">
- </div>
- </div>
-</template>
-
-<script setup>
-import addBtnSvg from '@/appDataSource/add.png'
-import { getDeviceJobList, jobStatistics } from '@/api/home/task'
-// import { useStore } from 'vuex'
-import { showToast, showLoadingToast, closeToast } from 'vant'
-import _ from 'lodash'
-import MyTask from './compoment/myTask.vue'
-import planExecute from './compoment/planExecute.vue'
-import executeing from './compoment/executeing.vue'
-import executioned from './compoment/executioned.vue'
-import executionError from './compoment/executionError.vue'
-import cancelExecution from './compoment/cancelExecution.vue'
-import pendingExecution from './compoment/pendingExecution.vue'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-// const store = useStore()
-
-const app_key_word = ref('')
-const currentTab = ref(1)
-const showAddBtn = ref(false)
-const tabList = ref([
- { name: '我的任务', number: 0, id: 'my_planned_executions' },
- { name: '计划执行', number: 0, id: 'planned_executions' },
- { name: '执行中', number: 0, id: 'running_num' },
- { name: '待执行', number: 0, id: 'pending_executions' },
- { name: '已执行', number: 0, id: 'executed' },
- { name: '执行失败', number: 0, id: 'failed_executions' },
- { name: '取消执行', number: 0, id: 'go_home_executions' },
-])
-
-function getNumbers () {
- jobStatistics({ date_enum: '', app_key_word: app_key_word.value }).then(res => {
- // {executed:56,my_planned_executions:34,planned_executions:45 }
- tabList.value.forEach(tab => {
- if (res.data.data.hasOwnProperty(tab.id)) {
- tab.number = res.data.data[tab.id]
- }
- })
- })
-}
-function taskDetails (item) {
- const transmitData = { data: { type: 'taskDetails', rowItem: { ..._.cloneDeep(item) } } }
- if ([1, 2].includes(item.status)) {
- wx.miniProgram.navigateTo({ url: `/subPackages/taskDetail/inProgress/index?wayLineJobInfoId=${item.id}` })
- } else {
- wx.miniProgram.navigateTo({ url: `/subPackages/taskDetail/execution/index?wayLineJobInfoId=${item.id}&waylineJobId=${item.wayline_job_id}&batch_no=${item.batch_no}` })
- }
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-const search_txt = ref('')
-function handleSearch () {
- search_txt.value = app_key_word.value
- getNumbers()
-}
-function onCancel () {
- search_txt.value = app_key_word.value
- getNumbers()
-}
-let indexTab = ref(0)
-function onClickTab (index) {
- // app_key_word.value = ''
- indexTab.value = index
- search_txt.value = app_key_word.value
- getNumbers()
-}
-
-function addTask () {
- const transmitData = { data: { type: 'addTask' } }
- wx.miniProgram.navigateTo({ url: `/subPackages/taskDetail/addTask/index` })
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-
-watch(
- () => route.query,
- (newValue, oldValue) => {
- if (newValue.updateKey) {
- nextTick()
- app_key_word.value = ''
- currentTab.value = 1
- getNumbers()
- }
- },
- { deep: true })
-
-onMounted(() => {
- if ('showAddBtn' in route.query) {
- showAddBtn.value = Number(route.query.showAddBtn)
- }
-
- getNumbers()
-})
-</script>
-
-<style scoped lang="scss">
-.inspectionTask {
- position: relative;
- height: 100%;
-
- //overflow: auto;
- //background: #f6f6f6;
- :deep(.van-search) {
- background: transparent;
- }
-
- :deep(.van-tabs) {
- display: flex;
- flex-direction: column;
- height: calc(100vh - 54px);
- }
-
- :deep(.van-tabs__wrap) {
- height: 59px;
- margin-bottom: 10px;
- }
-
- :deep(.van-tabs__content) {
- flex: 1;
- overflow-y: auto;
- height: 0;
- }
-
- :deep(.van-tabs__nav--line) {
- background: transparent;
- }
-
- :deep(.van-badge) {
- background-color: #1d6fe9;
- }
-
- :deep(.van-empty) {
- //height: calc(100vh - 100px);
- margin-top: 100px;
- }
-
- :deep(.van-tab) {
- .custom-tab-title {
- padding-bottom: 8px;
- min-width: 60px;
- text-align: center;
-
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 500;
-
- .tab-text {
- height: 21px;
- line-height: 21px;
- color: #676666 !important;
- font-size: 15px;
- }
-
- .tab-badge {
- margin-top: 2px;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 18px;
- background: rgba(29, 111, 233, 0.14);
- border-radius: 4px 4px 4px 4px;
- color: #222324 !important;
- font-size: 12px;
- }
- }
- }
-
- :deep(.van-tab--active) {
- .custom-tab-title {
- .tab-text {
- color: #1d6fe9 !important;
- }
-
- .tab-badge {
- color: #0051ff !important;
- }
- }
- }
-
- :deep(.van-tabs__line) {
- background: #227bff !important;
- }
-
- .add-task-btn {
- position: absolute;
- right: 6px;
- bottom: 24px;
-
- img {
- width: 60px;
- height: 60px;
- vertical-align: middle;
- // border-radius: 50%;
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/appPages/inspectionTask/indexcopy.vue b/applications/mobile-web-view/src/appPages/inspectionTask/indexcopy.vue
deleted file mode 100644
index faae8cb..0000000
--- a/applications/mobile-web-view/src/appPages/inspectionTask/indexcopy.vue
+++ /dev/null
@@ -1,300 +0,0 @@
-<template>
- <div class="inspectionTask">
- <van-search v-model="params.key_word" placeholder="请输入搜索关键词" :shape="round" @search="getJobList" />
- <van-tabs v-model:active="currentTab" @click-tab="onClickTab">
- <van-tab
- v-for="item in tabList"
- :key="item.name"
- :title="item.name"
- :badge="item.number > 99 ? `${99}+` : item.number"
- >
- <!-- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">-->
- <van-list
- v-model:loading="loading"
- :finished="finished"
- finished-text="没有更多了"
- :error="error"
- error-text="加载失败,点击重新加载"
- @load="getJobList"
- >
- <div class="card" v-for="item in list" :key="item.id" @click="taskClick(item)">
- <div class="drone_svg">
- <img :src="droneSvg" alt="" />
- </div>
- <div class="drone-right">
- <div class="c-top">
- <div class="create-name">
- <div class="name">{{ item.name }}</div>
- <div class="creator_name">{{ item.creator_name }}</div>
- </div>
- <div class="device_status">
- <div class="device">
- <img :src="flySvg" alt="" />
- <span>{{ item.device_names }}</span>
- </div>
- <img v-if="item.status === 5" :src="errorSvg" alt="" />
- <div class="status" :style="{ background: changeColor(item.status) }">
- {{ changStatus(item.status) }}
- </div>
- </div>
- </div>
- <div class="c-bottom">
- <div class="item">{{ item.job_info_num }}</div>
- <div class="item">{{ item.cycle_time_value }}</div>
- </div>
- </div>
- </div>
- </van-list>
- <!-- </van-pull-refresh>-->
- <!-- 空状态 -->
- <van-empty v-if="!loading && list.length === 0" description="暂无数据" />
- </van-tab>
- </van-tabs>
- </div>
-</template>
-
-<script setup>
-import { getDeviceJobList, jobStatistics } from '@/api/home/task'
-import { useStore } from 'vuex'
-import { showToast, showLoadingToast, closeToast } from 'vant'
-import _ from 'lodash'
-import droneSvg from '@/appDataSource/inspectionTask/drone.svg'
-import flySvg from '@/appDataSource/inspectionTask/fly.svg'
-import errorSvg from '@/appDataSource/inspectionTask/error.svg'
-
-const store = useStore()
-
-const currentTab = ref(1)
-const tabList = ref([
- { name: '我的任务', number: 0, id: 'my_planned_executions' },
- { name: '计划执行', number: 0, id: 'planned_executions' },
- { name: '执行中', number: 0, id: 'running_num' },
- { name: '待执行', number: 0, id: 'pending_executions' },
- { name: '已执行', number: 0, id: 'executed' },
- { name: '执行失败', number: 0, id: 'failed_executions' },
- { name: '取消执行', number: 0, id: 'go_home_executions' },
-])
-
-const params = ref({
- device_sn: null,
- order_by_create_time: false,
- my_task: false,
- key_word: '',
- status_list: [],
-})
-const total = ref(0)
-const sizeParams = ref({
- current: 1,
- size: 10,
-})
-const loading = ref(false)
-const finished = ref(false)
-const error = ref(false)
-const refreshing = ref(false)
-const list = ref([])
-function getJobList(isRefresh = false) {
- // if (refreshing.value) {
- // list.value = [];
- // refreshing.value = false;
- // }
- // 如果是刷新,重置分页
- if (isRefresh) {
- sizeParams.value.current = 1
- list.value = []
- finished.value = false
- }
- getDeviceJobList(params.value, sizeParams.value).then(res => {
- // 更新数据
- if (isRefresh) {
- list.value = res.data.data.records
- } else {
- list.value.push(...res.data.data.records)
- }
-
- loading.value = false
-
- // 更新分页信息
- total.value = res.data.data.total
- sizeParams.value.current++
- // 检查是否加载完成
- if (list.value.length >= res.data.data.total) {
- finished.value = true
- }
- })
-}
-
-// function onRefresh() {
-// finished.value = false;
-// loading.value = true;
-// getJobList()
-// }
-
-function getNumbers() {
- jobStatistics({ date_enum: '' }).then(res => {
- // {executed:56,my_planned_executions:34,planned_executions:45 }
- tabList.value.forEach(tab => {
- if (res.data.data.hasOwnProperty(tab.id)) {
- tab.number = res.data.data[tab.id]
- }
- })
- })
-}
-const listStatus = ref([
- { name: '执行中', color: '#FF8B42', status: [2] },
- { name: '待执行', color: '#F3B200', status: [1] },
- { name: '已执行', color: '#39B002', status: [3] },
- { name: '执行失败', color: '#FF381D', status: [5] },
- { name: '取消执行', color: '#ADADAD', status: [7] },
-])
-// function executed() {
-// uni.navigateTo({
-// url: '/pages/inspectionTask/TaskDetails/TaskDetails'
-// })
-// }
-function changStatus(status) {
- return listStatus.value.find(item => item.status.includes(status)).name
-}
-function changeColor(status) {
- return listStatus.value.find(item => item.status.includes(status)).color
-}
-function onClickTab() {
- sizeParams.value.current = 1
- list.value = []
- params.value.my_task = false
- params.value.status_list = []
- loading.value = true
- // showLoadingToast({
- // message: '加载中...',
- // duration: 0, // 不会自动关闭
- // forbidClick: true, // 禁止背景点击
- // });
- if (currentTab.value === 0) {
- params.value.my_task = true
- } else if (currentTab.value === 1) {
- params.value.status_list = [1, 2, 3, 5, 7]
- } else if (currentTab.value === 2) {
- params.value.status_list = [2]
- } else if (currentTab.value === 3) {
- params.value.status_list = [1]
- } else if (currentTab.value === 4) {
- params.value.status_list = [3]
- } else if (currentTab.value === 5) {
- params.value.status_list = [5]
- } else if (currentTab.value === 6) {
- params.value.status_list = [7]
- }
- getJobList()
-}
-
-function taskClick(item) {
- const transmitData = { data: { type: 'taskDetails', rowItem: { ..._.cloneDeep(item) } } }
- if ([1, 2].includes(item.status)) {
- wx.miniProgram.navigateTo({ url: `/subPackages/taskDetail/inProgress/index?wayLineJobInfoId=${item.id}` })
- } else {
- wx.miniProgram.navigateTo({ url: `/subPackages/taskDetail/execution/index?wayLineJobInfoId=${item.id}&waylineJobId=${item.wayline_job_id}&batch_no=${item.batch_no}` })
- }
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-
-onMounted(() => {
- // getJobList()
- getNumbers()
-})
-</script>
-
-<style scoped lang="scss">
-.inspectionTask {
- background: #f8f8f8;
- :deep(.van-badge) {
- background-color: #1d6fe9;
- }
- .card {
- margin: 6px;
- padding: 6px;
- height: 72px;
- border-radius: 10px 10px 10px 10px;
- background: #ffffff;
- display: flex;
- align-items: center;
- .drone_svg {
- margin-right: 6px;
- margin-top: 10px;
- img {
- width: 46px;
- height: 46px;
- }
- }
- .drone-right {
- width: calc(100% - 46px - 6px);
- font-family: Source Han Sans CN, Source Han Sans CN;
- .c-top {
- height: 36px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- .create-name {
- display: flex;
- .name {
- width: 82px;
- font-weight: bold;
- font-size: 15px;
- color: #191919;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- .creator_name {
- height: 20px;
- line-height: 20px;
- padding: 0 2px;
- font-weight: 500;
- font-size: 13px;
- color: #207aff;
- background: #dae6ff;
- border-radius: 30px 30px 30px 30px;
- }
- }
- .device_status {
- display: flex;
- .device {
- display: flex;
- align-items: center;
- margin-right: 2px;
- img {
- width: 14px;
- height: 14px;
- }
- span {
- width: 60px;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- font-weight: 500;
- font-size: 14px;
- color: #282828;
- }
- .status {
- margin-left: 2px;
- font-size: 14px;
- color: white;
- border-radius: 2px 2px 2px 2px;
- padding: 0px 2px;
- }
- }
- }
- .c-bottom {
- display: flex;
- justify-content: space-between;
- .item {
- width: 46%;
- white-space: nowrap; /* 不换行 */
- overflow: hidden; /* 超出隐藏 */
- text-overflow: ellipsis; /* 显示省略号 */
- }
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleLeft.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleLeft.vue
deleted file mode 100644
index fd80449..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleLeft.vue
+++ /dev/null
@@ -1,511 +0,0 @@
-<template>
- <div class="consoleLeft">
- <img class="continueOrPause" v-if="isManualControl" @click="droneContinues" :src="jxrwSvg" alt="" />
- <img class="continueOrPause" v-else @click="switchDronePaused" :src="ztrwSvg" alt="" />
-
- <div
- class="btnFun"
- v-for="item in list1.filter(i => i.show)"
- @click="setOtherCamera(item)"
- :class="{ activeBtn: item.key === cameraParams.camera_type }"
- >
- {{ item.name }}
- </div>
- <div class="btnFun" v-if="hasIr" :class="{ activeBtn: 'ir' === cameraParams.camera_type }" @click="setIrCamera">红外</div>
-
- <img class="returnVoyage" v-if="[9, 10, 11, 12].includes(modeCode)" @click="turnBack" :src="qxfhSvg" alt="" />
- <img class="returnVoyage" v-else @click="turnBack" :src="fhSvg" alt="" />
-
- <van-slider
- v-if="cameraParams.camera_type !== 'wide'"
- v-model="cameraParams.zoom_factor"
- vertical
- active-color="#1D6FE9"
- inactive-color="#ffffff"
- @change="sliderChange"
- @update:model-value="activeSlider = true"
- :reverse="true"
- :min="2"
- :max="(cameraParams.camera_type === 'ir' ? zoomFactor.ir.max : zoomFactor.zoom.max) || 100"
- >
- <template #button>
- <div class="custom-button">{{ cameraParams.zoom_factor }}</div>
- </template>
- </van-slider>
- </div>
-</template>
-
-<script setup>
-import EventBus from '@/utils/eventBus'
-import _ from 'lodash'
-import {
- callPhotoAndVideoCmd,
- cameraParamsChangeApi,
- ptzResetModeApi,
- setWidgetSetApi,
- setThermalCurrentPaletteStyle,
- openSendWsApi,
- closeSendWsApi,
- startVoice,
- voiceMode,
-} from '@/api/payload'
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { throttle } from 'lodash'
-import getBaseConfig from '@/buildConfig/config'
-import SvgIcon from '@/components/SvgIcon.vue'
-import dayjs from 'dayjs'
-import Recorder from 'js-audio-recorder'
-import hkSvg from '@/appDataSource/inspectionTask/droneConsole/滑块.svg'
-import sjSvg from '@/appDataSource/inspectionTask/droneConsole/时间.svg'
-import ztrwSvg from '@/appDataSource/inspectionTask/droneConsole/暂停任务.svg'
-import jxrwSvg from '@/appDataSource/inspectionTask/droneConsole/继续任务.svg'
-import fhSvg from '@/appDataSource/inspectionTask/droneConsole/返航.svg'
-import qxfhSvg from '@/appDataSource/inspectionTask/droneConsole/qxfh.svg'
-import { showToast } from 'vant'
-
-const { showConsoleSearchlight, showConsoleMegaphone } = getBaseConfig()
-const wsInfo = inject('wsInfo')
-const zoomFactor = inject('zoomFactor')
-const activeSlider = inject('activeSlider')
-const isRecording = inject('isRecording')
-const recordingTime = inject('recordingTime')
-const cameraParams = inject('cameraParams')
-const isManualControl = inject('isManualControl')
-const droneSn = inject('droneSn')
-const dockSn = inject('dockSn')
-const lineQuality = inject('lineQuality')
-const usedControl = inject('usedControl')
-const irModeStyleType = inject('irModeStyleType')
-const loadDevice = inject('loadDevice')
-const workspace_id = inject('workspace_id')
-const hasPayloadControl = inject('hasPayloadControl')
-const isRouteRecord = inject('isRouteRecord')
-const showUpKeyPanel = inject('showUpKeyPanel')
-const showFunBlock = inject('showFunBlock')
-const zoomText = computed(() => cameraParams.value.zoom_factor + 'X')
-const hasAiTypeStr = inject('hasAiTypeStr')
-const delayedRecepAuto = inject('delayedRecepAuto')
-const isBackDock = inject('isBackDock')
-const droneStatus = inject('droneStatus')
-const taskDetails = inject('taskDetails')
-const modeCode = computed(() => droneStatus?.value?.mode_code)
-const cameraDisable = computed(() => {
- return (taskDetails.value.ai_type_str && !isBackDock.value) || photoAndVideoLoading.value
-})
-const editCameraDebounce = _.debounce(fn => {
- fn()
-}, 1000) //修改相机信息节流版
-const photoAndVideoLoading = ref(false) //拍照录像接口加载中
-
-const value = ref(10)
-
-function onChange(val) {
- console.log(val)
-}
-
-function droneContinues() {
- EventBus.emit('controlPanel-cancelManualControl')
-}
-
-function switchDronePaused() {
- usedControl.value = true
- EventBus.emit('controlPanel-control')
-}
-
-// 返航
-function turnBack() {
- EventBus.emit('controlPanel-returnOrCancelReturn')
-}
-
-// 延迟4秒接收相机信息
-function delayedRecepCamera(key) {
- cameraParams.value.camera_type = key
- delayedRecepAuto()
-}
-
-const popperOptions = {
- placement: 'right',
- modifiers: [
- {
- name: 'offset',
- options: {
- offset: [120, 35],
- },
- },
- ],
-}
-
-const hasIr = inject('hasIr')
-const list1 = computed(() => {
- return [
- { name: '广角', key: 'wide', show: true },
- { name: '变焦', key: 'zoom', show: true },
- ]
-})
-
-// 调色盘选项数据
-const paletteOptions = ref([
- { label: '白热', value: 0 },
- { label: '黑热', value: 1 },
- { label: '描红', value: 2 },
- { label: '医疗', value: 3 },
- { label: '彩虹1', value: 5 },
- { label: '铁红', value: 6 },
- { label: '北极', value: 8 },
- { label: '熔岩', value: 11 },
- { label: '热铁', value: 12 },
- { label: '彩虹2', value: 13 },
-])
-
-// 探照灯选项数据
-const searchlightModeList = ref([
- { label: '关闭', value: 0 },
- { label: '爆闪', value: 2 },
- { label: '常亮', value: 1 },
-])
-
-const qualityList = [
- { name: '自适应', id: 0 },
- { name: '流畅', id: 1 },
- { name: '标清', id: 2 },
- { name: '高清', id: 3 },
- { name: '超清', id: 4 },
-]
-
-const ptzResetMode = _.throttle(resetMode => {
- ptzResetModeApi({ sn: dockSn.value, resetMode })
-}, 2000)
-
-// 创建一个防抖函数,延迟 2000 毫秒执行
-const debouncedActiveSlider = _.debounce(() => (activeSlider.value = false), 4000)
-// 修改相机参数-节流版
-const cameraParamsChangeThrottle = _.throttle(cameraParamsChange, 500)
-
-// 倍率调整
-function sliderChange(val) {
- if (cameraParams.value.camera_type !== 'ir') {
- cameraParams.value.camera_type = val > zoomFactor.value.zoom.min - 1 ? 'zoom' : 'wide'
- }
- cameraParamsChangeThrottle()
- debouncedActiveSlider()
-}
-
-function setOtherCamera(item) {
- editCameraDebounce(() => setCameraType(item))
- delayedRecepCamera(item.key)
-}
-
-function setIrCamera() {
- editCameraDebounce(irSettingItemClick)
- delayedRecepCamera('ir')
-}
-
-// 修改相机参数
-async function cameraParamsChange() {
- const { camera_type, zoom_factor } = cameraParams.value
- await cameraParamsChangeApi({
- sn: dockSn.value,
- ...cameraParams.value,
- zoom_factor: camera_type === 'wide' ? undefined : zoom_factor,
- })
-}
-
-function switchDroneAction() {}
-
-// 快捷键变焦
-function quickZoomIn(val) {
- activeSlider.value = true
- const { camera_type, zoom_factor } = cameraParams.value
- const max = camera_type === 'ir' ? zoomFactor.value.ir.max : zoomFactor.value.zoom.max
- const min = camera_type === 'ir' ? 2 : 1
- let zoomVal = val > 0 ? Math.min(max, zoom_factor + val) : Math.max(min, zoom_factor + val)
- zoomVal = zoomVal >= 2 ? zoomVal : 1
- if (camera_type === 'ir') {
- const arr = [2, 4, 7, 14, 28]
- let index = arr.findIndex(item => item >= cameraParams.value.zoom_factor)
- index = val > 0 ? (arr[index + 1] ? index + 1 : arr.length - 1) : arr[index - 1] ? index - 1 : 0
- zoomVal = arr[index]
- } else {
- cameraParams.value.camera_type = zoomVal >= 2 ? 'zoom' : 'wide'
- }
- cameraParams.value.zoom_factor = _.round(zoomVal, 1)
- debouncedActiveSlider()
- cameraParamsChange()
-}
-
-//红外调色盘设置
-async function irSettingItemClick(row) {
- searchlightChange()
- const payload_index = wsInfo?.value?.device_osd?.data?.host?.cameras?.[0]?.payload_index
- if (!payload_index) return
- await setCameraType({ key: 'ir' })
- if (row?.value === undefined) return
- const params = {
- [payload_index]: { thermal_current_palette_style: row.value },
- }
- setThermalCurrentPaletteStyle(dockSn.value, workspace_id.value, params)
-}
-
-// 修改相机类型
-async function setCameraType(row) {
- cameraParams.value.camera_type = row.key
- const zoomMin = zoomFactor.value?.zoom?.min
- const irMin = zoomFactor.value?.ir?.min
- if (row.key === 'wide') {
- cameraParams.value.zoom_factor = zoomMin ? zoomMin - 1 : 0
- }
- if (row.key === 'zoom') {
- cameraParams.value.zoom_factor = zoomMin ? zoomMin : 5
- }
- if (row.key === 'ir') {
- cameraParams.value.zoom_factor = irMin || 2
- }
- await cameraParamsChange()
-}
-
-// 画质切换
-function qualityChange(row) {
- lineQuality.value = row.id
- EventBus.emit('CurrentTaskDetails-changeLineQuality')
-}
-
-const searchlightMode = inject('searchlightMode')
-
-function searchlightChange() {
- isTxtVideo.value = ''
- isBroadcast.value = false
-}
-
-// 设置探照灯模式
-async function searchlightSet(row) {
- searchlightMode.value = row.value
- delayedRecepAuto()
- // 三代灯走mqtt,一代走接口
- if (loadDevice.value?.lightIndex === 5) {
- EventBus.emit('controlPanel-setSearchlight', row.value)
- } else {
- const params = { psdk_index: 2, index: 3, value: row.value }
- await setWidgetSetApi(dockSn.value, params)
- }
- if (row.value === 0) {
- closeSendWsApi(droneSn.value, { type: 'SEARCHLIGHT' })
- } else {
- openSendWsApi(droneSn.value, { type: 'SEARCHLIGHT' }, { value: row.value })
- }
-}
-
-const recordFun = _.throttle(() => {
- if (cameraDisable.value) return
- const type = isRecording.value ? 'video_stop' : 'video_start'
- const msg = isRecording.value ? '停止录像' : '开始录像'
- return photoAndVideoFun(type, msg)
-}, 4000)
-
-const takePictures = _.throttle(async () => {
- if (cameraDisable.value) return
- if (!isRecording.value) {
- await photoAndVideoFun('photo', '拍照成功')
- return
- }
- await ElMessageBox.confirm('停止录像后才可拍照,点击确认将停止录像?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- customClass: 'ztzf-message-box-grey',
- type: 'warning',
- })
- await photoAndVideoFun('video_stop', '停止录像')
- setTimeout(() => {
- photoAndVideoFun('photo', '拍照成功')
- }, 2000)
-}, 2000)
-
-// 拍照和录像
-async function photoAndVideoFun(type, msg) {
- const camera_type = cameraParams.value.camera_type
- let params = { cameraType: '' }
- if (camera_type === 'wide' || camera_type === 'zoom') {
- params.cameraType = droneSn.value === '1581F5BMD22CK0014H2U' ? 'wide' : 'vision'
- } else {
- params.cameraType = camera_type
- }
- photoAndVideoLoading.value = true
- return callPhotoAndVideoCmd(dockSn.value, type, params)
- .then(res => {
- showToast(msg)
- })
- .finally(() => {
- setTimeout(() => {
- photoAndVideoLoading.value = false
- }, 2000)
- })
-}
-
-// 记录喊话是否开始阶段
-const isRecordShouting = ref(true)
-const percent = ref(0) // 滚动条滚动百分比
-const isBroadcast = ref(false)
-
-// 广播
-function broadcastFun() {
- // 是否需要判断有控制权限
- // 弹出框选择文件
- isTxtVideo.value = ''
- isBroadcast.value = true
- // 获取文件接口
- // getFileList()
-}
-
-// 文字和音频广播
-const isTxtVideo = ref('')
-
-function txtVideoClick(type) {
- if (type === 'soundRecord') {
- isBroadcast.value = false
- }
- isTxtVideo.value = type
-}
-
-function closeClick() {
- isTxtVideo.value = ''
- isBroadcast.value = false
-}
-
-// 滚轮变焦
-const monitorWheel = _.throttle(e => {
- if (!hasPayloadControl.value) return
- e.preventDefault()
- const delta = e.deltaY || e.detail || e.wheelDelta
- quickZoomIn(delta > 0 ? -1 : 1)
-}, 1000)
-
-// 触发M键
-let isMKey = ref(false)
-
-function shoutMKeyClick() {
- isMKey.value = !isMKey.value
- isBroadcast.value = isMKey.value ? true : closeClick()
- isTxtVideo.value = isMKey.value ? 'video' : closeClick()
-}
-
-// 触发N键
-let isNKey = ref(false)
-
-function shoutNKeyClick(value) {
- isNKey.value = !isNKey.value
- isTxtVideo.value = isNKey.value ? 'soundRecord' : closeClick()
-}
-
-// 触发B键
-let isBKey = ref(false)
-
-function txtShoutBKeyClick(value) {
- isBKey.value = !isBKey.value
- isBroadcast.value = isBKey.value ? true : closeClick()
- isTxtVideo.value = isBKey.value ? 'txt' : closeClick()
-}
-
-// let isStartShout = ref(false)
-// watch(
-// () => wsInfo.value.dock_osd,
-// async newVal => {
-// if (!newVal?.data?.host?.psdk_widget_values?.speaker) return
-// const objSpeaker = newVal?.data.host.psdk_widget_values.speaker
-// if (objSpeaker?.system_state !== 0) {
-// isStartShout.value = true
-// }
-// if (isTxtVideo.value === 'videoNKey' && objSpeaker?.system_state === 0 && isStartShout.value) {
-// isTxtVideo.value = ''
-// isStartShout.value = false
-// }
-// },
-// {
-// deep: true,
-// }
-// )
-
-onMounted(() => {
- const videoBoxDom = document.querySelector('#liveVideoBox')
- videoBoxDom.addEventListener('wheel', monitorWheel)
- EventBus.on('TaskDetailsLeft-takePictures', takePictures)
- EventBus.on('TaskDetailsLeft-recordFun', recordFun)
- EventBus.on('TaskDetailsLeft-quickZoomIn', quickZoomIn)
- EventBus.on('TaskDetailsLeft-broadcastList', shoutMKeyClick)
- EventBus.on('TaskDetailsLeft-shoutList', shoutNKeyClick)
- EventBus.on('TaskDetailsLeft-txtShoutList', txtShoutBKeyClick)
-})
-onBeforeUnmount(() => {
- const videoBoxDom = document.querySelector('#liveVideoBox')
- videoBoxDom.removeEventListener('wheel', monitorWheel)
- EventBus.off('TaskDetailsLeft-takePictures', takePictures)
- EventBus.off('TaskDetailsLeft-recordFun', recordFun)
- EventBus.off('TaskDetailsLeft-quickZoomIn', quickZoomIn)
- EventBus.off('TaskDetailsLeft-broadcastList', shoutMKeyClick)
- EventBus.off('TaskDetailsLeft-shoutList', shoutNKeyClick)
- EventBus.on('TaskDetailsLeft-txtShoutList', txtShoutBKeyClick)
-})
-</script>
-
-<style scoped lang="scss">
-
-.custom-button{
- width: half(26);
- color: #fff;
- font-size: half(10);
- line-height: half(18);
- text-align: center;
- background-color: var(--van-primary-color);
- border-radius: half(100);
-}
-.consoleLeft {
- display: flex;
- flex-direction: column;
- align-items: center;
- position: absolute;
- gap: half(12);
- top: half(50);
- left: half(40);
- z-index: 5000;
-
- .continueOrPause{
- margin-bottom: half(7);
- }
-
- .returnVoyage{
- margin-top: half(7);
- }
- //
- //.btnFun{
- // margin: half(17) 0;
- //}
- //.btnFun:nth-child(3) {
- // /* 第二个 .btnFun 的样式 */
- // color: red;
- // margin: half(10) 0 !important;
- //}
-
- > img {
- width: half(33);
- height: half(33);
- }
-
- .btnFun {
- background: #ffffff;
- width: half(57);
- height: half(32);
- text-align: center;
- line-height: half(32);
- border-radius: half(4);
- font-size: half(13);
- &.activeBtn{
- background: #1d6fe9;
- color: #ffffff;
- }
- }
-
- .van-slider {
- position: absolute;
- left: half(100);
- top: half(0);
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/AppConsoleRight.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/AppConsoleRight.vue
deleted file mode 100644
index e0d4c8e..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/AppConsoleRight.vue
+++ /dev/null
@@ -1,560 +0,0 @@
-<template>
- <div class="consoleRight">
- <img
- :src="recordMode ? xjqhSvg : lxqhSvg"
- alt=""
- @click="() => cameraDisable || (recordMode = !recordMode)"
- :class="{ cameraDisable }"
- :style="{ visibility: isRecording ? 'hidden' : 'visible' }"
- />
- <div class="circle" @click="takePicOrRecord" :class="{ cameraDisable }">
- <div :class="{ videoRecording: recordMode, pauseRecording: isRecording, pzhlx: true }"></div>
- <div class="recordingTime" v-if="recordingTime !== '00:00:00'">{{ recordingTime }}</div>
- </div>
-
- <img
- :src="hhSvg"
- alt=""
- @click="shoutDlg"
- :style="{ visibility: loadDevice.speakIndex !== -1 && !isBackDock ? 'visible' : 'hidden' }"
- />
- </div>
-
- <Teleport to=".content-container" v-if="showSelectDlg">
- <div class="selectShout">
- <van-icon name="cross" class="closeDlg" @click="showSelectDlg = false" />
- <div>请选择广播/喊话</div>
- <div class="funBtn">
- <div class="broadcast" @click="broadcastBtnFun">广播</div>
- <div class="shoutBtn" @click="shoutBtnFun">喊话</div>
- </div>
- </div>
- </Teleport>
-
- <ShoutComponent v-model:show="showShouting" v-if="showShouting" />
- <BroadcastComponent v-model:show="showBroadcast" v-if="showBroadcast" />
-</template>
-
-<script setup>
-import EventBus from '@/utils/eventBus'
-import _ from 'lodash'
-import {
- callPhotoAndVideoCmd,
- cameraParamsChangeApi,
- ptzResetModeApi,
- setWidgetSetApi,
- setThermalCurrentPaletteStyle,
- openSendWsApi,
- closeSendWsApi,
- startVoice,
- voiceMode,
-} from '@/api/payload'
-import getBaseConfig from '@/buildConfig/config'
-import xjqhSvg from '@/appDataSource/inspectionTask/droneConsole/相机切换.svg'
-import lxqhSvg from '@/appDataSource/inspectionTask/droneConsole/录像.svg'
-import hhSvg from '@/appDataSource/inspectionTask/droneConsole/喊话.svg'
-import { showToast } from 'vant'
-import ShoutComponent from '@/components/CurrentTaskDetails/AppConsoleRight/ShoutComponent.vue'
-import BroadcastComponent from '@/components/CurrentTaskDetails/AppConsoleRight/BroadcastComponent.vue'
-
-const showSelectDlg = ref(false)
-const showShouting = ref(false)
-const showBroadcast = ref(false)
-
-const wsInfo = inject('wsInfo')
-const zoomFactor = inject('zoomFactor')
-const activeSlider = inject('activeSlider')
-const isRecording = inject('isRecording')
-const recordingTime = inject('recordingTime')
-const cameraParams = inject('cameraParams')
-const isManualControl = inject('isManualControl')
-const droneSn = inject('droneSn')
-const dockSn = inject('dockSn')
-const lineQuality = inject('lineQuality')
-const usedControl = inject('usedControl')
-const irModeStyleType = inject('irModeStyleType')
-const loadDevice = inject('loadDevice')
-const workspace_id = inject('workspace_id')
-const hasPayloadControl = inject('hasPayloadControl')
-const isRouteRecord = inject('isRouteRecord')
-const showUpKeyPanel = inject('showUpKeyPanel')
-const showFunBlock = inject('showFunBlock')
-const zoomText = computed(() => cameraParams.value.zoom_factor + 'X')
-const hasAiTypeStr = inject('hasAiTypeStr')
-const delayedRecepAuto = inject('delayedRecepAuto')
-const isBackDock = inject('isBackDock')
-const droneStatus = inject('droneStatus')
-const modeCode = computed(() => droneStatus?.value?.mode_code)
-const cameraDisable = computed(() => hasAiTypeStr.value|| isBackDock.value || photoAndVideoLoading.value)
-const editCameraDebounce = _.debounce(fn => {
- fn()
-}, 1000) //修改相机信息节流版
-const photoAndVideoLoading = ref(false) //拍照录像接口加载中
-const recordMode = ref(false)
-
-function takePicOrRecord() {
- if (cameraDisable.value) return
- recordMode.value ? recordFun() : takePictures()
-}
-
-function shoutDlg() {
- showSelectDlg.value = true
-}
-
-function shoutBtnFun() {
- showSelectDlg.value = false
- showShouting.value = true
-}
-
-function broadcastBtnFun() {
- showSelectDlg.value = false
- showBroadcast.value = true
-}
-
-function droneContinues() {
- EventBus.emit('controlPanel-cancelManualControl')
-}
-
-function switchDronePaused() {
- usedControl.value = true
- EventBus.emit('controlPanel-control')
-}
-
-// 返航
-function turnBack() {
- EventBus.emit('controlPanel-returnOrCancelReturn')
-}
-
-// 延迟4秒接收相机信息
-function delayedRecepCamera(key) {
- cameraParams.value.camera_type = key
- delayedRecepAuto()
-}
-
-const popperOptions = {
- placement: 'right',
- modifiers: [
- {
- name: 'offset',
- options: {
- offset: [120, 35],
- },
- },
- ],
-}
-
-const hasIr = inject('hasIr')
-const list1 = computed(() => {
- return [
- { name: '广角', key: 'wide', show: true },
- { name: '变焦', key: 'zoom', show: true },
- ]
-})
-
-// 调色盘选项数据
-const paletteOptions = ref([
- { label: '白热', value: 0 },
- { label: '黑热', value: 1 },
- { label: '描红', value: 2 },
- { label: '医疗', value: 3 },
- { label: '彩虹1', value: 5 },
- { label: '铁红', value: 6 },
- { label: '北极', value: 8 },
- { label: '熔岩', value: 11 },
- { label: '热铁', value: 12 },
- { label: '彩虹2', value: 13 },
-])
-
-// 探照灯选项数据
-const searchlightModeList = ref([
- { label: '关闭', value: 0 },
- { label: '爆闪', value: 2 },
- { label: '常亮', value: 1 },
-])
-
-const qualityList = [
- { name: '自适应', id: 0 },
- { name: '流畅', id: 1 },
- { name: '标清', id: 2 },
- { name: '高清', id: 3 },
- { name: '超清', id: 4 },
-]
-
-const ptzResetMode = _.throttle(resetMode => {
- ptzResetModeApi({ sn: dockSn.value, resetMode })
-}, 2000)
-
-// 创建一个防抖函数,延迟 2000 毫秒执行
-const debouncedActiveSlider = _.debounce(() => (activeSlider.value = false), 4000)
-// 修改相机参数-节流版
-const cameraParamsChangeThrottle = _.throttle(cameraParamsChange, 500)
-
-// 倍率调整
-function sliderChange(val) {
- if (cameraParams.value.camera_type !== 'ir') {
- cameraParams.value.camera_type = val > zoomFactor.value.zoom.min - 1 ? 'zoom' : 'wide'
- }
- cameraParamsChangeThrottle()
- debouncedActiveSlider()
-}
-
-function setOtherCamera(item) {
- editCameraDebounce(() => setCameraType(item))
- delayedRecepCamera(item.key)
-}
-
-function setIrCamera() {
- editCameraDebounce(irSettingItemClick)
- delayedRecepCamera('ir')
-}
-
-// 修改相机参数
-async function cameraParamsChange() {
- const { camera_type, zoom_factor } = cameraParams.value
- await cameraParamsChangeApi({
- sn: dockSn.value,
- ...cameraParams.value,
- zoom_factor: camera_type === 'wide' ? undefined : zoom_factor,
- })
-}
-
-function switchDroneAction() {}
-
-// 快捷键变焦
-function quickZoomIn(val) {
- activeSlider.value = true
- const { camera_type, zoom_factor } = cameraParams.value
- const max = camera_type === 'ir' ? zoomFactor.value.ir.max : zoomFactor.value.zoom.max
- const min = camera_type === 'ir' ? 2 : 1
- let zoomVal = val > 0 ? Math.min(max, zoom_factor + val) : Math.max(min, zoom_factor + val)
- zoomVal = zoomVal >= 2 ? zoomVal : 1
- if (camera_type === 'ir') {
- const arr = [2, 4, 7, 14, 28]
- let index = arr.findIndex(item => item >= cameraParams.value.zoom_factor)
- index = val > 0 ? (arr[index + 1] ? index + 1 : arr.length - 1) : arr[index - 1] ? index - 1 : 0
- zoomVal = arr[index]
- } else {
- cameraParams.value.camera_type = zoomVal >= 2 ? 'zoom' : 'wide'
- }
- cameraParams.value.zoom_factor = _.round(zoomVal, 1)
- debouncedActiveSlider()
- cameraParamsChange()
-}
-
-//红外调色盘设置
-async function irSettingItemClick(row) {
- searchlightChange()
- const payload_index = wsInfo?.value?.device_osd?.data?.host?.cameras?.[0]?.payload_index
- if (!payload_index) return
- await setCameraType({ key: 'ir' })
- if (row?.value === undefined) return
- const params = {
- [payload_index]: { thermal_current_palette_style: row.value },
- }
- setThermalCurrentPaletteStyle(dockSn.value, workspace_id.value, params)
-}
-
-// 修改相机类型
-async function setCameraType(row) {
- cameraParams.value.camera_type = row.key
- const zoomMin = zoomFactor.value?.zoom?.min
- const irMin = zoomFactor.value?.ir?.min
- if (row.key === 'wide') {
- cameraParams.value.zoom_factor = zoomMin ? zoomMin - 1 : 0
- }
- if (row.key === 'zoom') {
- cameraParams.value.zoom_factor = zoomMin ? zoomMin : 5
- }
- if (row.key === 'ir') {
- cameraParams.value.zoom_factor = irMin || 2
- }
- await cameraParamsChange()
-}
-
-// 画质切换
-function qualityChange(row) {
- lineQuality.value = row.id
- EventBus.emit('CurrentTaskDetails-changeLineQuality')
-}
-
-const searchlightMode = inject('searchlightMode')
-
-function searchlightChange() {
- isTxtVideo.value = ''
- isBroadcast.value = false
-}
-
-// 设置探照灯模式
-async function searchlightSet(row) {
- searchlightMode.value = row.value
- delayedRecepAuto()
- // 三代灯走mqtt,一代走接口
- if (loadDevice.value?.lightIndex === 5) {
- EventBus.emit('controlPanel-setSearchlight', row.value)
- } else {
- const params = { psdk_index: 2, index: 3, value: row.value }
- await setWidgetSetApi(dockSn.value, params)
- }
- if (row.value === 0) {
- closeSendWsApi(droneSn.value, { type: 'SEARCHLIGHT' })
- } else {
- openSendWsApi(droneSn.value, { type: 'SEARCHLIGHT' }, { value: row.value })
- }
-}
-
-const recordFun = _.throttle(() => {
- if (cameraDisable.value) return
- const type = isRecording.value ? 'video_stop' : 'video_start'
- const msg = isRecording.value ? '停止录像' : '开始录像'
- return photoAndVideoFun(type, msg)
-}, 4000)
-
-const takePictures = _.throttle(async () => {
- if (cameraDisable.value) return
- await photoAndVideoFun('photo', '拍照成功')
-}, 2000)
-
-// 拍照和录像
-async function photoAndVideoFun(type, msg) {
- const camera_type = cameraParams.value.camera_type
- let params = { cameraType: '' }
- if (camera_type === 'wide' || camera_type === 'zoom') {
- params.cameraType = droneSn.value === '1581F5BMD22CK0014H2U' ? 'wide' : 'vision'
- } else {
- params.cameraType = camera_type
- }
- photoAndVideoLoading.value = true
- return callPhotoAndVideoCmd(dockSn.value, type, params)
- .then(res => {
- showToast(msg)
- })
- .finally(() => {
- setTimeout(() => {
- photoAndVideoLoading.value = false
- }, 2000)
- })
-}
-
-// 记录喊话是否开始阶段
-const isRecordShouting = ref(true)
-const percent = ref(0) // 滚动条滚动百分比
-const isBroadcast = ref(false)
-
-// 广播
-function broadcastFun() {
- // 是否需要判断有控制权限
- // 弹出框选择文件
- isTxtVideo.value = ''
- isBroadcast.value = true
- // 获取文件接口
- // getFileList()
-}
-
-// 文字和音频广播
-const isTxtVideo = ref('')
-
-function txtVideoClick(type) {
- if (type === 'soundRecord') {
- isBroadcast.value = false
- }
- isTxtVideo.value = type
-}
-
-function closeClick() {
- isTxtVideo.value = ''
- isBroadcast.value = false
-}
-
-// 滚轮变焦
-const monitorWheel = _.throttle(e => {
- if (!hasPayloadControl.value) return
- e.preventDefault()
- const delta = e.deltaY || e.detail || e.wheelDelta
- quickZoomIn(delta > 0 ? -1 : 1)
-}, 1000)
-
-// 触发M键
-let isMKey = ref(false)
-
-function shoutMKeyClick() {
- isMKey.value = !isMKey.value
- isBroadcast.value = isMKey.value ? true : closeClick()
- isTxtVideo.value = isMKey.value ? 'video' : closeClick()
-}
-
-// 触发N键
-let isNKey = ref(false)
-
-function shoutNKeyClick(value) {
- isNKey.value = !isNKey.value
- isTxtVideo.value = isNKey.value ? 'soundRecord' : closeClick()
-}
-
-// 触发B键
-let isBKey = ref(false)
-
-function txtShoutBKeyClick(value) {
- isBKey.value = !isBKey.value
- isBroadcast.value = isBKey.value ? true : closeClick()
- isTxtVideo.value = isBKey.value ? 'txt' : closeClick()
-}
-
-// let isStartShout = ref(false)
-// watch(
-// () => wsInfo.value.dock_osd,
-// async newVal => {
-// if (!newVal?.data?.host?.psdk_widget_values?.speaker) return
-// const objSpeaker = newVal?.data.host.psdk_widget_values.speaker
-// if (objSpeaker?.system_state !== 0) {
-// isStartShout.value = true
-// }
-// if (isTxtVideo.value === 'videoNKey' && objSpeaker?.system_state === 0 && isStartShout.value) {
-// isTxtVideo.value = ''
-// isStartShout.value = false
-// }
-// },
-// {
-// deep: true,
-// }
-// )
-
-watch(recordingTime,()=>{
- if (recordingTime.value !== '00:00:00'){
- recordMode.value = true
- }
-})
-
-onMounted(() => {
- const videoBoxDom = document.querySelector('#liveVideoBox')
- videoBoxDom.addEventListener('wheel', monitorWheel)
- EventBus.on('TaskDetailsLeft-takePictures', takePictures)
- EventBus.on('TaskDetailsLeft-recordFun', recordFun)
- EventBus.on('TaskDetailsLeft-quickZoomIn', quickZoomIn)
- EventBus.on('TaskDetailsLeft-broadcastList', shoutMKeyClick)
- EventBus.on('TaskDetailsLeft-shoutList', shoutNKeyClick)
- EventBus.on('TaskDetailsLeft-txtShoutList', txtShoutBKeyClick)
-})
-onBeforeUnmount(() => {
- const videoBoxDom = document.querySelector('#liveVideoBox')
- videoBoxDom.removeEventListener('wheel', monitorWheel)
- EventBus.off('TaskDetailsLeft-takePictures', takePictures)
- EventBus.off('TaskDetailsLeft-recordFun', recordFun)
- EventBus.off('TaskDetailsLeft-quickZoomIn', quickZoomIn)
- EventBus.off('TaskDetailsLeft-broadcastList', shoutMKeyClick)
- EventBus.off('TaskDetailsLeft-shoutList', shoutNKeyClick)
- EventBus.on('TaskDetailsLeft-txtShoutList', txtShoutBKeyClick)
-})
-</script>
-
-<style scoped lang="scss">
-.selectShout {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- background: rgba(230, 230, 230, 0.9);
- //backdrop-filter: blur(5px);
- font-size: half(13);
- text-align: center;
- padding: half(20) half(20) half(10) half(20);
- border-radius: half(10);
- z-index: 1;
-
- .closeDlg {
- position: absolute;
- right: half(5);
- top: half(5);
- }
-
- .funBtn {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 0 half(20);
- padding-top: half(15);
-
- > div {
- width: half(57);
- height: half(32);
- text-align: center;
- line-height: half(32);
- border-radius: half(4);
- }
- }
-
- .shoutBtn {
- background: #1d6fe9;
- color: #ffffff;
- }
-
- .broadcast {
- background: #ffffff;
- }
-}
-
-.consoleRight {
- position: absolute;
- width: half(101);
- height: calc(100% - 17px);
- top: half(34);
- right: half(0);
- background: rgba(22, 22, 22, 0.5);
- padding: half(30) 0;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
- z-index: 1;
-
- .cameraDisable {
- opacity: 0.3;
- }
-
- .recordingTime {
- }
-
- > img {
- width: half(50);
- height: half(50);
- }
-
- .circle {
- width: half(60);
- height: half(60);
- background: transparent;
- border-radius: 50%;
- display: flex;
- justify-content: center;
- align-items: center;
- border: 1.5px solid #ffffff;
- position: relative;
-
- > .pzhlx {
- width: half(48);
- height: half(48);
- background: #ffffff;
- border-radius: 50%;
- }
-
- .recordingTime {
- position: absolute;
- color: #ffffff;
- left: 50%;
- bottom: -15px;
- white-space: nowrap;
- transform: translate(-50%, 0);
- }
-
- .videoRecording {
- background: red;
- }
-
- .pauseRecording {
- width: half(25);
- height: half(25);
- border-radius: 10%;
- background: red;
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/BroadcastComponent.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/BroadcastComponent.vue
deleted file mode 100644
index 4897bc8..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/BroadcastComponent.vue
+++ /dev/null
@@ -1,453 +0,0 @@
-<template>
- <Teleport to=".content-container">
- <div class="shoutingMask">
- {{nowPlaying}}
- <van-icon name="cross" class="closeDlg" @click="closeDlgFun" />
- <div class="playBox">
- <div>
- <img
- :src="speakerInfo.play_mode === 0 ? bigPlayOne : bigXunHuan"
- @click="setModelPlay(speakerInfo.play_mode === 0 ? 1 : 0)"
- alt=""
- />
- <div>{{ playMode?.[speakerInfo.play_mode] }}</div>
- </div>
- <div>
- <img v-if="speakerInfo.system_state === 2" :src="videoStopImg" alt="" @click="suspendDrone" />
- <div v-else-if="speakerInfo.system_state === 1" class="intermediateState">
- <img :src="videoPlayImg" alt="" />
- <van-loading color="#0E0E0EFF" />
- </div>
-
- <img v-else :src="videoPlayImg" alt="" @click="pushToDrone(checkRow)" />
- <div>{{ systemState?.[speakerInfo?.system_state] }}</div>
- </div>
- <div>
- <img :src="bigVolume" alt="" @click="showVolumeAdjustment = !showVolumeAdjustment" />
- <div>音量</div>
- </div>
- </div>
- <VolumeAdjustment v-if="showVolumeAdjustment" />
-
- <div class="searchBox">
- <el-input
- size="small"
- v-model="searchParams.name"
- placeholder="请输入文件名称"
- :suffix-icon="null"
- v-focusDisableKeys
- />
- <div class="whiteBtn" @click="getFileList('search')">搜索</div>
- <div class="whiteBtn">
- <el-upload
- action="/upload"
- accept=".FLAC,.ALAC,.WAV,.MP3,.AAC,.AIFF"
- :show-file-list="false"
- :before-upload="handleUpload"
- >
- 上传音频
- </el-upload>
- </div>
- </div>
-
- <div class="listBoxBlock">
- <div class="listItem title">
- <div class="serialNumber">序号</div>
- <div class="fileName">文件名称</div>
- <div class="operation">操作</div>
- </div>
- <van-list
- class="listBox"
- v-model:loading="loading"
- :finished="finished"
- finished-text=" "
- @load="onLoad"
- offset="5"
- >
- <div
- class="listItem"
- v-for="(item, index) in tableList"
- :class="{ checked: item.checked }"
- :key="item.id"
- @click="pushToDrone(item)"
- >
- <div class="serialNumber">{{ index + 1 }}</div>
- <div class="fileName">{{ item.name }}</div>
- <div class="operation">
- <img @click.stop="deleteVideo(item)" :src="deleteImg" alt="" />
- <img v-if="item.isTryListren" @click.stop="stopTryListren(item)" :src="litterTryPlayImg" alt="" />
- <img v-else @click.stop="playTryListren(item)" :src="litterTryListrenImg" alt="" />
- </div>
- </div>
- </van-list>
- </div>
- </div>
- </Teleport>
-</template>
-
-<script setup>
-import videoStopImg from '@/assets/images/taskManagement/taskIntermediateContent/video-stop.svg'
-import videoPlayImg from '@/assets/images/taskManagement/taskIntermediateContent/video-play.svg'
-import { getVoiceFile, playAudio, stopVoiceApi, uploadSpeak, voiceMode } from '@/api/payload'
-import bigPlayOne from '@/assets/images/taskManagement/taskIntermediateContent/play-one-big.svg'
-import bigXunHuan from '@/assets/images/taskManagement/taskIntermediateContent/xunhuan-big.svg'
-import bigVolume from '@/assets/images/taskManagement/taskIntermediateContent/volume-big.svg'
-import VolumeAdjustment from '@/components/CurrentTaskDetails/AppConsoleRight/VolumeAdjustment.vue'
-import deleteImg from '@/assets/images/taskManagement/taskIntermediateContent/delete.svg'
-import litterTryListrenImg from '@/assets/images/taskManagement/taskIntermediateContent/little-try-listren.svg'
-import litterTryPlayImg from '@/assets/images/taskManagement/taskIntermediateContent/litter-try-play.svg'
-import { deleteSpeakVoiceByIdApi } from '@/api/routePlan'
-import { showConfirmDialog, showToast } from 'vant'
-
-const showBlock = defineModel('show')
-const dockSn = inject('dockSn')
-const searchParams = ref({
- sn: dockSn.value,
- name: '',
- page: 0,
- page_size: 999,
-})
-const loading = ref(false)
-const finished = ref(true)
-const total = ref(0)
-const speakerInfo = inject('speakerInfo')
-const showVolumeAdjustment = ref(false)
-const tableList = ref([])
-const checkRow = computed(() => {
- return tableList.value.find(item => item.checked === true)
-})
-let audioPlayer = null
-const playMode = { 0: '单次播放', 1: '循环播放' }
-const systemState = { 0: '空闲中', 1: '传输中', 2: '播放中', 3: '异常', 4: '文本转换中', 99: '下载中' }
-// 正在播放
-const nowPlaying = computed(()=>{
- return speakerInfo.value.system_state === 2 && !checkRow.value ? '正在播放上一次音频' : ''
-})
-
-// 停止播放
-function suspendDrone() {
- stopVoiceApi({ sn: dockSn.value, psdk_index: 2 }).then(res => {
- // speakerInfo.value.system_state = 0
- })
-}
-
-function closeDlgFun() {
- showBlock.value = false
-}
-
-function setModelPlay(type) {
- const data = {
- psdk_index: 2,
- play_mode: type, // 1:是循环播放,0:单次播放
- }
- voiceMode({ sn: dockSn.value }, data)
-}
-
-// 删除音频
-function deleteVideo(row) {
- showConfirmDialog({ title: '提示', message: '确定删除该条音频文件?' }).then(() => {
- deleteSpeakVoiceByIdApi(row.id).then(res => {
- if (res.data.code === 0) {
- showToast('删除成功')
- loading.value = true
- getFileList()
- }
- })
- })
-}
-
-// 上传
-function handleUpload(file) {
- let formData = new FormData()
- formData.append('file', file)
- formData.append('sn', dockSn.value)
- uploadSpeak(formData).then(res => {
- showToast('上传成功')
- // 获取文件接口
- getFileList()
- })
-}
-
-// 获取音频列表
-function getFileList() {
- getVoiceFile(searchParams.value).then(res => {
- tableList.value = res.data.data.records
- // if (!checkRow.value) {
- // if (speakerInfo.value?.play_file_md5 && speakerInfo.value?.system_state === 2){
- // const row = tableList.value.find(item => item.md5 === speakerInfo.value?.play_file_md5)
- // playTryListren(row)
- // }
- // }
- total.value = res.data.data.total
- nextTick(() => {
- loading.value = false
- })
- })
-}
-
-function onLoad() {
- searchParams.value.page = searchParams.value.page + 1
- getFileList()
-}
-
-// 本地试听
-function playTryListren(row) {
- // 先播放本地音频
- if (row.url) {
- if (!audioPlayer) {
- audioPlayer = new Audio()
- }
- tableList.value.forEach(item => {
- item.isTryListren = false
- item.checked = false
- })
- row.isTryListren = true
- row.checked = true
- audioPlayer.src = row.url
- // speakerInfo.play_mode
- audioPlayer.loop = !!speakerInfo.value.play_mode
- audioPlayer.play()
- audioPlayer.addEventListener('ended', () => {
- row.isTryListren = false
- })
- }
-}
-
-// 停止试听
-function stopTryListren(row) {
- tableList.value.forEach(item => {
- item.isTryListren = false
- })
- if (audioPlayer) {
- audioPlayer.pause()
- // audioPlayer = null
- }
-}
-
-let duration = null
-let timeout = null
-
-// 获取当前音频时长
-function getDuration(url) {
- return new Promise((resolve, reject) => {
- try {
- let audio = new Audio()
- audio.src = url
- audio.addEventListener('loadedmetadata', () => {
- resolve(audio.duration)
- audio = null
- })
- } catch (e) {
- reject(e)
- }
- })
-}
-
-// 推送到无人机
-async function pushToDrone(item) {
- const { sn, name, url, md5, voice } = item || {}
- if (!name) return showToast('请先选择音频')
- if (!url) return showToast('文件已损坏,请选择其他音频')
-
- // await stopVoiceApi({ sn: dockSn.value, psdk_index: 2 })
- playAudio({ sn, name, url, md5, voice }).then(async res => {
- tableList.value.forEach(item => (item.checked = false))
- item.checked = true
- // speakerInfo.value.system_state = 1
- // playTryListren(item)
- showToast('推送成功')
- // const duration = await getDuration(item.url)
- // if (speakerInfo.value.play_mode === 0) {
- // timeout && clearTimeout(timeout)
- // timeout = setTimeout(() => {
- // }, (duration || 0) * 1000)
- // }
- })
-}
-
-watch(
- () => speakerInfo.value,
- (newValue, oldValue) => {
- const new_system_state = newValue?.system_state
- const old_system_state = oldValue?.system_state
- if (new_system_state !== old_system_state) {
- if (new_system_state === 2) {
- const row = tableList.value.find(item => item.md5 === speakerInfo.value?.play_file_md5)
- row && playTryListren(row)
- } else {
- stopTryListren()
- }
- }
- if (audioPlayer) {
- audioPlayer.loop = !!speakerInfo.value?.play_mode
- }
- },
- { immediate: true, deep: true }
-)
-
-onMounted(() => {
- getFileList()
-})
-
-onBeforeUnmount(() => {
- if (audioPlayer) {
- audioPlayer.pause()
- audioPlayer = null
- }
-})
-</script>
-
-<style scoped lang="scss">
-.shoutingMask {
- position: absolute;
- width: half(313);
- height: 100%;
- top: half(0);
- right: half(0);
- padding-top: half(20);
- z-index: 1;
- background: rgba(0, 0, 0, 0.4);
- backdrop-filter: blur(0.5rem);
- display: flex;
- gap: half(10) 0;
- flex-direction: column;
- align-items: center;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-size: half(13);
- color: #ffffff;
-
- .van-overlay {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .playBox {
- display: flex;
- justify-content: center;
- align-items: center;
- text-align: center;
- gap: half(25);
-
- >div{
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: half(5);
- }
-
- .intermediateState {
- position: relative;
- width: half(42);
- height: half(42);
-
- > img {
- opacity: 0.5;
- }
-
- .van-loading {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: half(35);
- height: half(35);
- }
- }
-
- //>div{
- // width: half(42);
- // height: half(42);
- //}
-
- img {
- width: half(42);
- height: half(42);
- }
- }
-
- .listItem {
- flex-shrink: 0;
- width: 100%;
- height: half(45);
- display: flex;
- align-items: center;
- background: rgba(15, 15, 15, 0.9);
- color: #ffffff;
-
- &.title {
- border-radius: half(10) half(10) 0 0;
- }
-
- &.checked {
- background: rgba(255, 255, 255, 0.4);
- color: #000000;
- }
-
- > div {
- display: flex;
- justify-content: center;
- }
-
- .serialNumber {
- width: 25%;
- }
-
- .fileName {
- width: 50%;
- text-wrap: wrap;
- text-align: center;
- }
-
- .operation {
- width: 25%;
- }
- }
-
- .closeDlg {
- font-size: half(20);
- position: absolute;
- right: half(5);
- top: half(5);
- color: #ffffff;
- }
-
- .searchBox {
- display: flex;
- height: half(38);
- gap: 0 half(6);
- padding: 0 half(20);
-
- .el-input {
- height: 100%;
- font-size: half(15);
- }
- }
-
- .listBoxBlock {
- padding: 0 half(20);
- border-radius: half(10) half(10) 0 0;
- overflow: hidden;
- flex-grow: 1;
- width: 100%;
- display: flex;
- flex-direction: column;
-
- .listBox {
- flex-grow: 1;
- overflow: auto;
- width: 100%;
-
- :deep() {
- .van-list__finished-text {
- background: rgba(15, 15, 15, 0.9);
- color: #ffffff;
- font-size: half(13);
- height: half(45);
- line-height: half(45);
- }
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/ShoutComponent.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/ShoutComponent.vue
deleted file mode 100644
index d27ef72..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/ShoutComponent.vue
+++ /dev/null
@@ -1,278 +0,0 @@
-<template>
- <Teleport to=".content-container">
- <div class="shoutingMask">
- <van-icon name="cross" class="closeDlg" @click="closeDlgFun" />
- <div v-if="startState === '2'" style="text-align: center">{{nowPlaying}}</div>
- <div class="functionHead">
- <div v-if="startState === '0'">
- <img :src="startSpeakImg" alt="" @click="startRecording" />
- <div>点击录音</div>
- </div>
- <div v-if="startState === '1'">
- <img :src="videoStopImg" alt="" @click="stopRecord" />
- <div>点击完成</div>
- </div>
-
- <template v-if="startState === '2'">
- <div>
- <img :src="tryListrenImg" alt="" @click="trialListening" />
- <div>试听</div>
- </div>
- <div>
- <img v-if="speakerInfo?.system_state === 2" :src="videoStopImg" alt="" @click="suspendDrone" />
- <div v-else-if="speakerInfo?.system_state === 1" class="intermediateState" @click="suspendDrone">
- <img :src="videoPlayImg" alt="" />
- <van-loading color="#0E0E0EFF" />
- </div>
- <img v-else :src="videoPlayImg" alt="" @click="pushToDrone" />
- <div>{{ systemState?.[speakerInfo?.system_state] }}</div>
- </div>
- <div>
- <img :src="repertSpeakImg" alt="" @click="resetRecording" />
- <div>重录</div>
- </div>
- </template>
- </div>
-
- <div v-if="startState === '2'" class="saveBlock">
- <el-input
- size="small"
- v-model="soundVideoName"
- :suffix-icon="null"
- placeholder="请输入音频名称名称"
- v-focusDisableKeys
- />
- <div class="whiteBtn" @click="saveSound">保存音频</div>
- </div>
-
- <VolumeAdjustment />
- </div>
- </Teleport>
-</template>
-
-<script setup>
-import startSpeakImg from '@/assets/images/taskManagement/taskIntermediateContent/start-speak.svg'
-import videoStopImg from '@/assets/images/taskManagement/taskIntermediateContent/video-stop.svg'
-import tryListrenImg from '@/assets/images/taskManagement/taskIntermediateContent/try-listren.svg'
-import videoPlayImg from '@/assets/images/taskManagement/taskIntermediateContent/video-play.svg'
-import repertSpeakImg from '@/assets/images/taskManagement/taskIntermediateContent/repret-speak.svg'
-import Recorder from 'js-audio-recorder'
-import _ from 'lodash'
-import dayjs from 'dayjs'
-import { setVoiceVolumn, startVoice, stopVoiceApi, uploadSpeak, voiceMode } from '@/api/payload'
-import { showToast } from 'vant'
-import VolumeAdjustment from '@/components/CurrentTaskDetails/AppConsoleRight/VolumeAdjustment.vue'
-
-const showShouting = defineModel('show')
-const soundVideoName = ref(`${dayjs().format('YYYYMMDDHHmmss')}实时喊话`) // 喊话名称
-
-const fileName = ref('')
-const accept = '.FLAC,.ALAC,.WAV,.MP3,.AAC,.OGG,.wav'
-const list = ref([])
-let audioPlayer = null
-let recordingTime = ref('00:00')
-const showAdd = ref(false)
-// 0未录制 1 录制中 2 录制完成
-const startState = ref('0')
-const droneHornState = ref('0')
-const activeAudio = ref('')
-const searchText = ref('')
-const showSearch = ref(false)
-const editItem = ref({})
-let ctx = null
-let oCanvas = null
-let drawRecordId = null
-const dockSn = inject('dockSn')
-const speakerInfo = inject('speakerInfo')
-const delayedRecepAuto = inject('delayedRecepAuto')
-
-const playMode = { 0: '单次播放', 1: '循环播放' }
-const systemState = { 0: '空闲中', 1: '传输中', 2: '播放中', 3: '异常', 4: '文本转换中', 99: '下载中' }
-
-
-const pushed = ref(false)
-// 正在播放
-const nowPlaying = computed(()=>{
- return speakerInfo.value.system_state === 2 && !pushed.value ? '正在播放上一次音频' : ''
-})
-
-const wayLineJobInfoId = ref(null)
-const updateKey = ref(0)
-const uNotifyRef = ref(null)
-
-const route = useRoute()
-
-function timeConversion(secondsCount) {
- const minutes = _.padStart(Math.floor(secondsCount / 60), 2, '0')
- const secs = _.padStart(Math.floor(secondsCount % 60), 2, '0')
- return minutes + ':' + secs
-}
-
-function startRecording() {
- startState.value = '1'
- audioPlayer = new Recorder({
- sampleBits: 16, // 采样位数,支持8或16,默认16
- sampleRate: 16000, // 采样率,支持11025、16000、22050、24000、44100、48000
- numChannels: 1, // 声道,支持1或2,默认1
- })
- nextTick(() => {
- audioPlayer.start().then(() => {
- audioPlayer.onprocess = duration => {}
- })
- })
-}
-
-// 完成录音
-function stopRecord() {
- startState.value = '2'
- audioPlayer.stop()
- soundVideoName.value = `${dayjs().format('YYYYMMDDHHmmss')}实时喊话`
-}
-
-// 试听
-function trialListening() {
- audioPlayer?.play()
-}
-
-async function pushToDrone() {
- let formData = new FormData()
- const wavBlob = audioPlayer.getWAVBlob()
- const wavform = new File([wavBlob], new Date().getTime() + '.wav')
- formData.append('file', wavform)
- formData.append('sn', dockSn.value)
- formData.append('psdk_index', 2)
- formData.append('name', soundVideoName.value + '.wav')
- formData.append('volumn', 100)
- await voiceMode({ sn: dockSn.value }, { psdk_index: 2, play_mode: 0 })
- await stopVoiceApi({ sn: dockSn.value, psdk_index: 2 })
- startVoice(formData)
- .then( res => {
- pushed.value = true
- showToast('推送成功')
- })
-}
-
-function suspendDrone() {
- stopVoiceApi({ sn: dockSn.value, psdk_index: 2 }).then(res => {
- showToast('停止播放成功')
- })
-}
-
-function resetRecording() {
- startState.value = '0'
- audioPlayer?.destroy().then(() => {
- audioPlayer = null // 释放资源
- })
-}
-
-function closeDlgFun() {
- resetRecording()
- showShouting.value = false
-}
-
-function saveSound() {
- const wavFile = new File([audioPlayer.getWAVBlob()], '.wav')
- let formData = new FormData()
- formData.append('file', wavFile)
- formData.append('fileName', soundVideoName.value + '.wav')
- formData.append('sn', dockSn.value)
- uploadSpeak(formData).then(res => {
- showToast('保存成功')
- })
-}
-
-watch(
- () => speakerInfo.value,
- (newValue, oldValue) => {
- const new_system_state = newValue?.system_state
- const old_system_state = oldValue?.system_state
- if (new_system_state !== old_system_state) {
- if (new_system_state === 2) {
- trialListening()
- } else {
- audioPlayer?.pause?.()
- }
- }
- },
- { immediate: true, deep: true }
-)
-</script>
-
-<style scoped lang="scss">
-.shoutingMask {
- position: absolute;
- width: half(313);
- height: 100%;
- top: half(0);
- right: half(0);
- z-index: 1;
- background: rgba(0, 0, 0, 0.4);
- backdrop-filter: blur(5px);
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-size: half(11);
- color: #ffffff;
- display: flex;
- flex-direction: column;
- justify-content: center;
- gap: half(30) 0;
-
- .closeDlg {
- font-size: half(20);
- position: absolute;
- right: half(5);
- top: half(5);
- color: #ffffff;
- }
-
- .functionHead {
- display: flex;
- justify-content: center;
- align-items: center;
- text-align: center;
- gap: half(36);
-
- img {
- width: half(42);
- height: half(42);
- }
- >div{
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: half(5);
- }
-
-
- .intermediateState{
- position: relative;
- width: half(42);
- height: half(42);
- > img {
- width: half(42);
- height: half(42);
- opacity: 0.5;
- }
- .van-loading {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: half(35);
- height: half(35);
- }
- }
- }
-
- .saveBlock {
- display: flex;
- height: half(38);
- padding: half(0) half(30);
- gap: 0 half(6);
-
- .el-input {
- height: 100%;
- font-size: half(15);
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/VolumeAdjustment.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/VolumeAdjustment.vue
deleted file mode 100644
index 5f06978..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppConsoleRight/VolumeAdjustment.vue
+++ /dev/null
@@ -1,62 +0,0 @@
-
-<template>
- <div class="volumeBlock">
- <img
- @click="volumeChange(speakerInfo.play_volume === 0 ? 100 : 0)"
- :src="speakerInfo.play_volume !== 0 ? listVolumeImg : muteImg"
- alt=""
- />
- <van-slider
- v-model="speakerInfo.play_volume"
- @change="volumeChange(speakerInfo.play_volume)"
- @update:model-value="delayedRecepAuto"
- active-color="#1D6FE9"
- >
- <template #button>
- <div class="custom-button">{{ speakerInfo.play_volume }}</div>
- </template>
- </van-slider>
- </div>
-</template>
-
-<script setup>
-import listVolumeImg from '@/assets/images/taskManagement/taskIntermediateContent/list-volume.svg'
-import muteImg from '@/assets/images/taskManagement/taskIntermediateContent/mute.svg'
-import { setVoiceVolumn } from '@/api/payload'
-import { showToast } from 'vant'
-
-const speakerInfo = inject('speakerInfo')
-const delayedRecepAuto = inject('delayedRecepAuto')
-const dockSn = inject('dockSn')
-
-function volumeChange(volume) {
- const data = {
- play_volume: volume,
- psdk_index: 2,
- }
- setVoiceVolumn({ sn: dockSn.value }, data).then(res => {
- showToast('设置成功')
- })
-}
-
-</script>
-
-
-<style scoped lang="scss">
-.volumeBlock {
- width: 100%;
- display: flex;
- align-items: center;
- padding: half(0) half(30);
- gap: 0 half(15);
-
- .custom-button {
- width: half(24);
- color: #fff;
- font-size: half(10);
- text-align: center;
- background-color: var(--van-primary-color);
- border-radius: half(100);
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppPtzControl.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/AppPtzControl.vue
deleted file mode 100644
index c4f4197..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/AppPtzControl.vue
+++ /dev/null
@@ -1,535 +0,0 @@
-<template>
-<!-- <div class="ptzControlBtnBox">-->
- <div class="ptzControlBtnBox" v-show="isTakeOff">
- <BaseControl/>
- <div class="ptzControlBtn b-r">
- <div
- v-for="(item, index) in ptzBtns"
- :style="item.style"
- class="ptzControlItem"
- :class="{ isActiveBtn: isActiveBtn(item.key) }"
- @touchstart="onMouseDown(item.key)"
- @touchend="onMouseUp"
- ></div>
-
- <div
- class="ptzControlItemIcon"
- v-for="(item, index) in ptzBtns"
- :style="{ transform: `rotate(${index * 90}deg)` }"
- >
- <el-icon>
- <CaretRight />
- </el-icon>
- </div>
- <div class="circles2 b-r">
- <div class="circles3 b-r">
- 云台
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<script setup>
-import { KeyCode, useManualControl } from '@/hooks/controlDrone/useManualControl'
-import { droneController, exitController, postDrc, returnHome, returnHomeCancel } from '@/api/drc'
-import { ElMessage } from 'element-plus'
-import { UranusMqtt } from '@/utils/mqtt'
-import {
- ArrowDown,
- ArrowLeft,
- ArrowRight,
- ArrowUp,
- Bottom,
- CaretRight,
- Minus,
- Plus,
- RefreshLeft,
- RefreshRight,
-} from '@element-plus/icons-vue'
-import _ from 'lodash'
-import BaseControl from '@/components/CurrentTaskDetails/ControlPanel/BaseControl.vue'
-import EventBus from '@/utils/eventBus'
-import { getPayloadControlApi } from '@/api/payload'
-import { directionMap } from '@/const/drc'
-import { useRunOnce } from '@/hooks'
-import { decryptAES } from '@/utils/cryptoUtils'
-import { useMqtt } from '@/hooks/controlDrone/useMqtt'
-import { analysisPointLineKmz } from '@/utils/cesium/pointWayLineUtils'
-import { showToast } from 'vant'
-
-const wsInfo = inject('wsInfo')
-const device_osd_host = computed(() => wsInfo?.value?.device_osd?.data?.host || {})
-const dock_osd_host = computed(() => wsInfo?.value?.dock_osd?.data?.host || {})
-const taskDetails = inject('taskDetails')
-const dockSn = inject('dockSn')
-const droneSn = inject('droneSn')
-const trueAltitude = inject('trueAltitude')
-const client_id = inject('client_id')
-const isBackDock = inject('isBackDock')
-const isAutoControl = inject('isAutoControl')
-const isManualControl = inject('isManualControl')
-const showUpKeyPanel = inject('showUpKeyPanel')
-const showFunBlock = inject('showFunBlock')
-const isTakeOff = inject('isTakeOff')
-const isMaxMap = inject('isMaxMap')
-const hasPayloadControl = inject('hasPayloadControl')
-const currentWayLine = inject('currentWayLine')
-const job_id = computed(() => currentWayLine.value?.job_id)
-
-const apiDisable = inject('apiDisable')
-const zoomFactor = inject('zoomFactor')
-const cameraParams = inject('cameraParams')
-const activeSlider = inject('activeSlider')
-const droneStatus = inject('droneStatus')
-const workspace_id = inject('workspace_id')
-const activeBtnList = ref([])
-
-function isActiveBtn(key) {
- return activeBtnList.value.includes(key)
-}
-
-let mqttState = null
-const speed = ref(5)
-provide('speed', speed)
-
-const deviceTopicInfo = ref({
- pubTopic: '',
- subTopic: '',
-})
-// 控制对象
-let manualControl = null
-const activeKeyboard = ref(null)
-const compassOptions = computed(() => {
- return {
- pitchAngle: pitchAngle.value.angle,
- trueAltitude: trueAltitude.value,
- yawAngle: yawAngle.value.angle,
- }
-})
-
-const list1 = [
- { key: KeyCode.KEY_Q, text: 'Q', icon: RefreshLeft },
- { key: KeyCode.KEY_W, text: 'W', icon: ArrowUp },
- { key: KeyCode.KEY_E, text: 'E', icon: RefreshRight },
-]
-const list2 = [
- { key: KeyCode.KEY_A, text: 'A', icon: ArrowLeft },
- { key: KeyCode.KEY_S, text: 'S', icon: ArrowDown },
- { key: KeyCode.KEY_D, text: 'D', icon: ArrowRight },
-]
-
-const ptzBtns = [
- { name: '上', key: KeyCode.ARROW_UP, operate: 'up', style: { top: '-70%' } },
- { name: '右', key: KeyCode.ARROW_RIGHT, operate: 'right', style: { left: '70%' } },
- { name: '下', key: KeyCode.ARROW_DOWN, operate: 'down', style: { top: '70%' } },
- { name: '左', key: KeyCode.ARROW_LEFT, operate: 'left', style: { left: '-70%' } },
-]
-
-const baseInfoList = ref([
- [
- { name: '焦距倍数', value: 0 },
- { name: '俯仰角度', value: 0, unit: '' },
- { name: '横向角度', value: 0, unit: '' },
- ],
- [
- { name: '储存', value: 0, unit: 'G' },
- { name: '方向', value: 0 },
- { name: '方向', value: 0 },
- ],
-])
-
-const pitchAngle = computed(() => {
- const { payloads } = device_osd_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 { payloads, attitude_head } = device_osd_host?.value || {}
- 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
- }
- const roundResult = Math.round(result)
- let direction = ''
- for (const item of directionMap) {
- if (roundResult >= item.min && roundResult <= item.max) {
- direction = item.value
- break
- }
- }
- return {
- angle: _.round(result, 1),
- direction,
- }
-})
-const isRecording = inject('isRecording')
-const recordingTime = inject('recordingTime')
-
-// 设置录像时间
-function setRecordTime({ recording_state = 0, record_time = 0 }) {
- isRecording.value = !!recording_state
- if (recording_state) {
- const hours = String(Math.floor(record_time / 3600)).padStart(2, '0')
- const minutes = String(Math.floor((record_time % 3600) / 60)).padStart(2, '0')
- const secs = String(record_time % 60).padStart(2, '0')
- recordingTime.value = `${hours}:${minutes}:${secs}`
- } else {
- recordingTime.value = '00:00:00'
- }
-}
-
-// 设置变焦倍率
-function setZoomFactor(camerasInfo) {
- let zoom_factor
- const irLevel = camerasInfo?.ir_zoom_factor
- const zoomLevel = camerasInfo?.zoom_factor
- if (cameraParams.value.camera_type === 'wide') {
- zoom_factor = zoomFactor.value.zoom.min - 1
- } else if (cameraParams.value.camera_type === 'ir') {
- zoom_factor = irLevel
- } else {
- zoom_factor = zoomLevel
- }
- zoom_factor = _.round(zoom_factor, 1)
- if (!activeSlider.value) {
- cameraParams.value.zoom_factor = zoom_factor
- }
- baseInfoList.value[0][0].value = zoom_factor
-}
-
-// 基本信息赋值
-const baseInfoChange = () => {
- const newUsedStorage = dock_osd_host.value?.storage?.used
- const camerasInfo = device_osd_host.value?.cameras?.[0] || {}
- setRecordTime(camerasInfo)
- setZoomFactor(camerasInfo)
- const usedStorageGB = _.round(newUsedStorage / 1024 / 1024, 2)
- baseInfoList.value[0][1].value = pitchAngle.value.angle
- baseInfoList.value[0][2].value = yawAngle.value.angle
- if (newUsedStorage !== undefined) baseInfoList.value[1][0].value = usedStorageGB
- baseInfoList.value[1][1].value = pitchAngle.value.direction
- baseInfoList.value[1][2].value = yawAngle.value.direction
-}
-const throttleBaseInfoChange = _.throttle(baseInfoChange, 1000)
-watch(wsInfo, throttleBaseInfoChange, { immediate: true, deep: true })
-
-// 按下操作
-function onMouseDown(type) {
- manualControl?.handleKeyup(type)
-}
-
-// 弹起操作
-function onMouseUp() {
- manualControl?.resetControlState()
-}
-
-// 取消手动控制
-function cancelManualControl() {
- if ([undefined, 0, 14].includes(droneStatus.value.mode_code)) {
- return showToast('当前状态无法操作')
- }
- if (isAutoControl.value) return showToast('当前已经是自动飞行中')
- if (isBackDock.value) return showToast('当前正在返航,无法自动控制')
- apiDisable.value = true
- exitController({ client_id: client_id.value, dock_sn: dockSn.value, job_id: job_id.value })
- .then(res => {
- deviceTopicInfo.value.subTopic = ''
- deviceTopicInfo.value.pubTopic = ''
- showToast('退出飞行控制成功')
- })
- .catch(e => {})
- .finally(() => {
- apiDisable.value = false
- })
-}
-
-// 获得有效载荷控制
-function getPayloadControl() {
- if (hasPayloadControl.value || !dockSn.value) return
- getPayloadControlApi({ sn: dockSn.value }).then(res => {
- hasPayloadControl.value = true
- console.log('成功获得有效载荷控制--(云台操作等等)')
- })
-}
-
-// 手动控制
-function control(params = {}) {
- const { hasTips = true } = params
- if (!dockSn.value) return ElMessage.error('系统错误,未获取到dock_sn')
- if (droneStatus.value.mode_code === 10) return showToast('自动降落时不允许手动控制')
- if (droneStatus.value.mode_code === 9) return showToast('请先取消返航')
- if ([undefined, 0,1,2,10, 14].includes(droneStatus.value.mode_code)) return showToast('当前状态无法操作')
- apiDisable.value = true
- droneController({ client_id: client_id.value, dock_sn: dockSn.value, job_id: job_id.value })
- .then(res => {
- const { data } = res.data
- if (data.sub && data.sub?.length > 0) {
- deviceTopicInfo.value.subTopic = data.sub[0]
- }
- if (data.pub && data.pub?.length > 0) {
- deviceTopicInfo.value.pubTopic = data.pub[0]
- }
- showUpKeyPanel.value = true
- hasTips && showToast('暂停成功')
- getPayloadControl()
- isMaxMap.value = false
- })
- .finally(() => {
- apiDisable.value = false
- })
-}
-
-// 返航
-async function onBackDock() {
- if (![5, 17, 3, 16].includes(droneStatus.value.mode_code)) {
- return showToast('当前状态无法操作')
- }
- apiDisable.value = true
- try {
- await returnHome(dockSn?.value)
- showToast('返航操作成功')
- } catch (e) {
- } finally {
- apiDisable.value = false
- }
-}
-
-// 取消返航
-async function cancelBackDock() {
- if (droneStatus.value.mode_code !== 9) {
- return showToast('当前状态不允许取消返航')
- }
- apiDisable.value = true
- returnHomeCancel({ dock_sn: dockSn.value, client_id: client_id.value, job_id: job_id.value })
- .then(res => {
- const { data } = res.data
- if (data.sub && data.sub?.length > 0) {
- deviceTopicInfo.value.subTopic = data.sub[0]
- }
- if (data.pub && data.pub?.length > 0) {
- deviceTopicInfo.value.pubTopic = data.pub[0]
- }
- showToast('取消返航成功')
- // 取消返航 后 就要开始手动控制了 获取一下负载
- getPayloadControl()
- })
- .finally(() => {
- apiDisable.value = false
- })
-}
-
-// 创建mqtt连接
-const createConnect = async () => {
- const result = await postDrc({}, workspace_id.value)
- if (result?.code === 0) {
- const { address, client_id: clientId, username, password } = result.data
- mqttState = new UranusMqtt(address, { clientId, username, password: decryptAES(password) })
- mqttState?.initMqtt()
- client_id.value = clientId
- }
-}
-
-// 销毁连接
-const destroyConnect = () => {
- if (mqttState) {
- mqttState?.destroyed()
- mqttState = null
- client_id.value = ''
- }
- deviceTopicInfo.value.pubTopic = ''
- deviceTopicInfo.value.subTopic = ''
-}
-
-// 返航或取消返航
-const returnOrCancelReturn = () => {
- if ([undefined, 0, 14].includes(droneStatus.value.mode_code)) {
- return showToast('当前状态无法操作')
- }
- isBackDock.value ? cancelBackDock() : onBackDock()
-}
-
-// useManualControl里面用的参数
-const paramsRef = computed(() => ({
- droneSn: droneSn.value,
- dockSn: dockSn.value,
- speed: speed.value,
-}))
-
-let mqttHooks
-
-function setSearchlight(mode) {
- console.log(deviceTopicInfo.value.pubTopic)
- mqttHooks?.publishMqtt(
- deviceTopicInfo.value.pubTopic,
- {
- data: {
- group: 0, //{"0":"主探照灯"}
- mode: mode, //{ "0": "关闭", "1": "常量", "2": "爆闪", "3": "快速爆闪", "4": "交替爆闪" }
- psdk_index: 5, //psdk 负载设备索引
- },
- method: 'drc_light_mode_set',
- },
- { qos: 0 }
- )
-}
-
-// 编辑飞行速度
-function editSpeed(val) {
- speed.value = Math.min(15, Math.max(1, speed.value + val))
-}
-
-const modelCode = computed(() => droneStatus?.value?.mode_code)
-
-const getFileSpeedOnce = useRunOnce(async () => {
- const {auto_flight_speed} = await analysisPointLineKmz(currentWayLine?.value?.url)
- speed.value = auto_flight_speed
-})
-
-watch(
- taskDetails,
- () => {
- currentWayLine.value?.url && getFileSpeedOnce()
- },
- { immediate: true }
-)
-
-watch(workspace_id, async () => {
- if (workspace_id.value && mqttState === null && client_id.value === '') {
- await createConnect()
- mqttHooks = useMqtt(mqttState, deviceTopicInfo.value)
- manualControl = useManualControl(
- mqttHooks,
- deviceTopicInfo.value,
- paramsRef,
- isManualControl,
- modelCode,
- activeBtnList
- )
- manualControl?.openKeyMonitor()
- }
-})
-
-onMounted(async () => {
- EventBus.on('controlPanel-control', control)
- EventBus.on('controlPanel-cancelManualControl', cancelManualControl)
- EventBus.on('controlPanel-returnOrCancelReturn', returnOrCancelReturn)
- EventBus.on('controlPanel-onMouseDown', onMouseDown)
- EventBus.on('controlPanel-getPayloadControl', getPayloadControl)
- EventBus.on('controlPanel-setSearchlight', setSearchlight)
- EventBus.on('controlPanel-editSpeed', editSpeed)
-})
-
-onBeforeUnmount(() => {
- manualControl?.removeKeyMonitor()
- manualControl = null
- EventBus.off('controlPanel-control', control)
- EventBus.off('controlPanel-cancelManualControl', cancelManualControl)
- EventBus.off('controlPanel-returnOrCancelReturn', returnOrCancelReturn)
- EventBus.off('controlPanel-onMouseDown', onMouseDown)
- EventBus.off('controlPanel-getPayloadControl', getPayloadControl)
- EventBus.off('controlPanel-setSearchlight', setSearchlight)
- EventBus.off('controlPanel-editSpeed', editSpeed)
- destroyConnect()
-})
-</script>
-
-<style scoped lang="scss">
-.b-r {
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-.ptzControlBtnBox {
- z-index: 1;
- color: #ffffff;
- position: absolute;
- right: half(110);
- bottom: half(10);
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .ptzControlBtn {
- position: relative;
- overflow: hidden;
- width: half(143);
- height: half(143);
- background: rgba(22, 22, 22, 0.5); /* 半透明背景 */
-
- .ptzControlItemIcon {
- pointer-events: none;
- width: half(135);
- display: flex;
- justify-content: right;
- font-size: half(30);
- position: absolute;
- }
-
- .ptzControlItem {
- position: absolute;
- width: 100%;
- height: 100%;
- transform: rotate(45deg);
-
- &.isActiveBtn,
- &:hover {
- cursor: pointer;
- box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.3);
- }
- }
-
- .circles2 {
- width: half(79);
- height: half(79);
- //background: rgba(255,255,255,0.25);
- background: rgba(22, 22, 22, 0.5);
- border: 1px solid rgba(0, 0, 0, 0.2);
-
- .circles3 {
- width: half(42);
- height: half(42);
- background: #ffffff;
- z-index: 1;
- display: flex;
- align-items: center;
- justify-content:center;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 500;
- font-size: half(12);
- color: #242424;
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/ControlPanel/BaseControl.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/ControlPanel/BaseControl.vue
deleted file mode 100644
index 2ad681b..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/ControlPanel/BaseControl.vue
+++ /dev/null
@@ -1,311 +0,0 @@
-<template>
- <div class="manualControl" v-if="false">
- <div class="manualControlBg">
- <div class="manualControlBorder">
- <div class="manualControlCenter" @click="airAlleyOop">
- <img :src="controlCenterImg" alt="" />
- </div>
- </div>
- <div
- v-for="item in controlBtnList"
- :key="item.name"
- :style="item.style"
- :title="item.name"
- :class="{
- operateBtn: true,
- active: item.active,
- disable: item.disable || (item.name === '控制台' ? false : apiDisable),
- }"
- @click="funBtnClick(item)"
- ></div>
- <SvgIcon
- v-for="(item, index) in controlBtnList"
- :name="item.svg"
- :class="`${'btnIcon-' + index} btnIcon ${item.active ? 'active' : ''}`"
- :style="item.imgStyle"
- />
- </div>
-
- </div>
-</template>
-
-<script setup>
-import { stopRecording } from '@/api/drc'
-import { checkControllUserMeApi, closeSendWsApi, setWidgetSetApi, stopVoiceApi } from '@/api/payload'
-import controlCenterImg from '@/assets/images/taskManagement/taskIntermediateContent/controlCenter.png'
-import SvgIcon from '@/components/SvgIcon.vue'
-import EventBus from '@/utils/eventBus'
-import { ElMessage } from 'element-plus'
-import { useStore } from 'vuex'
-import _, { throttle } from 'lodash'
-import { useRunOnce } from '@/hooks'
-import { showToast } from 'vant'
-const store = useStore()
-
-const isAutoControl = inject('isAutoControl')
-const isBackDock = inject('isBackDock')
-const droneStatus = inject('droneStatus')
-const showUpKeyPanel = inject('showUpKeyPanel')
-const isManualControl = inject('isManualControl')
-const dockSn = inject('dockSn')
-const isAiLive = inject('isAiLive')
-const droneSn = inject('droneSn')
-const usedControl = inject('usedControl')
-const apiDisable = inject('apiDisable')
-const airAlleyOopShow = ref(false)
-const recordingId = inject('recordingId')
-const isRouteRecord = inject('isRouteRecord')
-const controlBtnList = ref([
- {
- name: '自动控制',
- svg: 'autoControl',
- style: { top: '-70%' },
- active: true,
- handle: autoControl,
- },
- { name: '控制台', svg: 'consoleBtn', style: { left: '70%' }, active: false, handle: showConsole },
- {
- name: '手动控制',
- svg: 'manualControl',
- style: { top: '70%' },
- active: false,
- handle: manualControl,
- },
- { name: '返航/取消返航', svg: 'turnBack', style: { left: '-70%' }, active: false, handle: turnBack },
-])
-
-// 自动控制
-function autoControl() {
- EventBus.emit('controlPanel-cancelManualControl')
-}
-
-function funBtnClick(item) {
- if (item.name !== '控制台' && apiDisable.value) {
- return
- }
- !item.disable && item.handle()
-}
-
-// 切换控制台显示
-function showConsole() {
- if (!showUpKeyPanel.value && [undefined, 0, 14].includes(droneStatus.value.mode_code)) {
- return showToast('当前状态无法操作')
- }
- showUpKeyPanel.value = !showUpKeyPanel.value
- if (showUpKeyPanel.value) {
- EventBus.emit('controlPanel-getPayloadControl')
- }
-}
-
-// 手动控制
-function manualControl() {
- usedControl.value = true
- EventBus.emit('controlPanel-control')
-}
-
-// 返航
-function turnBack() {
- EventBus.emit('controlPanel-returnOrCancelReturn')
-}
-// 设置回显状态
-function setSelectStatus() {
- const modeCode = droneStatus?.value?.mode_code
-
- if (modeCode === undefined) return
- // 自动控制
- if ([0, 1, 2, 4, 5, 14].includes(modeCode)) {
- controlBtnList.value = controlBtnList.value.map(item => ({ ...item, active: false }))
- controlBtnList.value[0].active = true
- isAutoControl.value = true
- isBackDock.value = false
- isManualControl.value = false
- }
- // 控制中
- if ([3, 16, 17].includes(modeCode)) {
- controlBtnList.value = controlBtnList.value.map(item => ({ ...item, active: false }))
- controlBtnList.value[2].active = true
- isManualControl.value = true
- isAutoControl.value = false
- isBackDock.value = false
- }
- // 降落中
- if ([9, 10, 11, 12].includes(modeCode)) {
- controlBtnList.value = controlBtnList.value.map(item => ({ ...item, active: false }))
- controlBtnList.value[3].active = true
- isAutoControl.value = false
- isManualControl.value = false
- isAiLive.value && closeAiFunOnce()
- isBackDock.value = true
- if (recordingId.value) {
- getstopRecording()
- recordingId.value = ''
- }
- if (modeCode === 10) {
- showUpKeyPanel.value = false
- }
- }
-}
-
-// 停止录制
-const getstopRecording = useRunOnce(() => {
- if (!droneSn.value) return
- isRouteRecord.value = false
- stopRecording(recordingId.value).then(res => {
- recordingId.value = ''
- showToast('航线录制结束')
- })
-})
-
-// 设置按钮禁用状态
-function setButtonDisabledStatus() {
- const modeCode = droneStatus?.value?.mode_code
- controlBtnList.value[0].disable = [undefined, 0, 14, 9, 10, 11, 12].includes(modeCode)
- controlBtnList.value[1].disable = [undefined, 0, 10, 14].includes(modeCode)
- controlBtnList.value[2].disable = [undefined, 0, 14, 9, 10].includes(modeCode)
- if ([undefined, 0, 14].includes(modeCode)) {
- controlBtnList.value[3].disable = true
- } else {
- controlBtnList.value[3].disable = false
- if ([9, 10, 11, 12].includes(modeCode)) {
- controlBtnList.value[3].disable = modeCode !== 9
- }
- }
-}
-
-// 获取控制 只触发一次
-const getControlFunOnce = useRunOnce(() => {
- usedControl.value ||
- checkControllUserMeApi(dockSn.value).then(res => {
- const isMe = res.data.data
- isMe && EventBus.emit('controlPanel-control', { hasTips: false })
- })
-})
-
-const closeAiFunOnce = throttle(()=>{
- EventBus.emit('CurrentTaskDetails-getDroneLiveUrl')
- closeSendWsApi(droneSn.value, { type: 'AI' })
-}, 4000)
-
-// 统一节流
-const statusThrottle = throttle(() => {
- setButtonDisabledStatus()
- setSelectStatus()
-}, 1000)
-
-function airAlleyOop() {
- // airAlleyOopShow.value = true
-}
-
-watch(droneStatus, statusThrottle, { deep: true, immediate: true })
-</script>
-
-<style scoped lang="scss">
-.manualControl {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 188px;
- height: 188px;
- background: rgb(0, 0, 0, 0.4); /* 半透明背景 */
- border-radius: 40px 40px 40px 40px;
-
- .manualControlBg {
- display: flex;
- align-items: center;
- justify-content: center;
- overflow: hidden;
- width: 165px;
- height: 165px;
- border-radius: 50%;
- position: relative;
- background: radial-gradient(circle, #5d5c5e 0%, #514f52 50%, #3d3b3d 100%);
-
- .operateBtn {
- position: absolute;
- width: 100%;
- height: 100%;
- transform: rotate(45deg);
-
- &.active,
- &:hover {
- cursor: pointer;
- box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.3);
- z-index: 1;
- background: rgba(255, 255, 255, 0.19);
- }
-
- &.active {
- z-index: 2;
- background: radial-gradient(circle, #5d5c5e 0%, #6d6d6d 50%, #4a454a 100%);
- }
-
- &.disable {
- cursor: not-allowed;
- }
- }
-
- .btnIcon {
- position: absolute;
- font-size: 24px;
- pointer-events: none;
- color: #8e8e8f;
- z-index: 2;
-
- &.active {
- color: #fff;
- }
-
- &-0 {
- left: 50%;
- top: 20px;
- transform: translateX(-50%);
- }
-
- &-1 {
- top: 50%;
- right: 20px;
- transform: translateY(-50%);
- }
-
- &-2 {
- bottom: 20px;
- left: 50%;
- transform: translateX(-50%);
- }
-
- &-3 {
- top: 50%;
- left: 20px;
- transform: translateY(-50%);
- }
- }
-
- .manualControlBorder {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 135px;
- height: 135px;
- border-radius: 50%;
- border: 2px solid #ffffff;
-
- .manualControlCenter {
- cursor: pointer;
- z-index: 5;
- width: 50px;
- height: 50px;
- background: #404040;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
-
- img {
- width: 18px;
- height: 18px;
- }
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/CurrentTaskDetails.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
deleted file mode 100644
index bfbeb79..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
+++ /dev/null
@@ -1,691 +0,0 @@
-<!--当前任务详情-->
-<template>
- <div
- class="content-container"
- ref="monitorRef"
- :class="{ landscapeMode, showBottomLeftCorner }"
- v-if="isShow"
- v-loading="dialogLoading"
- element-loading-text="加载中..."
- element-loading-background="rgb(33 33 33 / 80%)"
- >
- <!-- 视频直播 -->
- <div :class="`${isMaxMap ? 'minBox' : 'maxBox'} ${liveSuccess ? 'centerPoint' : ''}`" id="liveVideoBox">
- <LiveVideo
- v-if="liveSuccess"
- :videoUrl="currentLiveUrl"
- :controls="false"
- :hasRightMenu="true"
- :camera_type="cameraParams.camera_type"
- :liveFullScreen="liveFullScreen"
- @video-click="() => isMaxMap && switchMapSize()"
- />
- <div v-else class="liveErr">
- <div class="liveErrBg" />
- </div>
- </div>
- <RealTimeMap
- @click="() => !isMaxMap && switchMapSize()"
- ref="realTimeMap"
- :class="`${isMaxMap ? 'maxBox' : 'minBox'}`"
- v-if="taskWayLineDetails?.[0]?.url"
- />
- <TaskDetailsHead v-if="showHead" />
- <AppPtzControl v-if="isCurFlightTask"/>
- <AppConsoleLeft v-if="isTakeOff && !showBottomLeftCorner && isCurFlightTask" />
- <AppConsoleRight v-if="isTakeOff && isCurFlightTask" />
- <div class="smallWindowArrow">
- <img alt="" :src="xzsSvg" @click="switchShowSmallWindow" />
- </div>
- </div>
-</template>
-
-<script setup>
-import LiveVideo from '@/components/LiveVideo.vue'
-import { getDeviceDetail, liveStart } from '@/api/home/machineNest'
-import RealTimeMap from '@/components/CurrentTaskDetails/RealTimeMap.vue'
-import TaskDetailsHead from '@/components/CurrentTaskDetails/TaskDetailsHead.vue'
-import amplifyImg from '@/assets/images/taskManagement/taskIntermediateContent/amplifySvg.svg'
-import gdSvg from '@/appDataSource/inspectionTask/droneConsole/高度.svg'
-import sdSvg from '@/appDataSource/inspectionTask/droneConsole/速度.svg'
-import fsSvg from '@/appDataSource/inspectionTask/droneConsole/风速.svg'
-import dcSvg from '@/appDataSource/inspectionTask/droneConsole/电池.svg'
-import xhSvg from '@/appDataSource/inspectionTask/droneConsole/信号.svg'
-import xzsSvg from '@/appDataSource/inspectionTask/droneConsole/xzs.svg'
-import EventBus from '@/utils/eventBus'
-import { updateDroneQualityApi, viewTheRecording } from '@/api/drc'
-import {
- getCameraInfoApi,
- getDevicePsdkInfoApi,
- getLiveAiLinkApi,
- getLiveStatusApi,
- getLoadInfoApi,
- openSendWsApi,
-} from '@/api/payload'
-import { CURRENT_CONFIG } from '@/utils/http/config'
-import { useDroneWS } from '@/hooks/useDroneWS'
-import { useTaskDetails } from '@/hooks/useTaskDetails/useTaskDetails'
-import { DRONE_LIST, EModeText } from '@/const/device'
-import { useRunOnce } from '@/hooks'
-import _ from 'lodash'
-import { useStore } from 'vuex'
-import AppConsoleLeft from '@/components/CurrentTaskDetails/AppConsoleLeft.vue'
-import AppPtzControl from '@/components/CurrentTaskDetails/AppPtzControl.vue'
-import AppConsoleRight from '@/components/CurrentTaskDetails/AppConsoleRight/AppConsoleRight.vue'
-import { showToast } from 'vant'
-import {getJobWayLineDetails} from '@ztzf/apis'
-import { getJobDetails, getJobsByJobInfoIdApi } from '@/api/home/task'
-
-// 获取详情后的回调
-const getDetailsCallBack = async () => {
- const dockInfoRes = await getDeviceDetail(dockSn.value)
- const result = dockInfoRes.data.data
- const isDockLive = [undefined, 0, 14, -1].includes(result?.children?.mode_code)
- isTakeOff.value = !isDockLive
- droneModelText.value = result?.children?.device_name
- if (isDockLive) {
- await getDeviceLiveUrl()
- return
- }
- isCurFlightTask.value ? await getDroneLiveUrl(false, result.child_device_sn) : await getDeviceLiveUrl()
-}
-const landscapeMode = inject('landscapeMode')
-const store = useStore()
-// 不要随意更换顺序,有联动
-const infoList = ref([
- { index: 0, title: '实时真高', value: 0, unit: 'M', hide: true },
- { index: 1, title: '绝对高度', value: 0, unit: 'M', img: gdSvg },
- { index: 2, title: '水平速度', value: 0, unit: 'M/S', img: sdSvg },
- { index: 3, title: '风速', value: 0, unit: 'M/S', img: fsSvg },
- { index: 4, title: '4G信号', value: '-', unit: '', img: xhSvg },
- { index: 5, title: 'SDR信号', value: '-', unit: '', hide: true },
- { index: 6, title: '电池电量', value: 0, unit: '%', img: dcSvg },
-])
-const monitorRef = ref(null)
-const isShow = defineModel('show') // 是否显示当前任务详情
-// const props = defineProps(['wayLineJobInfoId', 'waylineJobId', 'selectDockSn'])
-const props = defineProps({
- wayLineJobInfoId: { type: Number, default: null },
- selectDockSn: { type: String, default: null },
- // 批次id跟周期性任务有关
- batchNo: { default: null}
-})
-const dockSn = computed(() => props?.selectDockSn) //机巢sn
-const droneSn = computed(() => wsInfo.value?.device_osd?.data?.sn) //无人机sn
-const currentMinJob = ref(null) //当前小任务信息
-const isCurFlightTask = ref(false) //是否是当前飞行任务
-const lineQuality = ref(1) //1流畅,2标清
-const taskDetailsViewer = shallowRef(null) //地图实例
-const trueAltitude = ref('') // 真实高度
-const isAiLive = ref(false) // 是ai直播
-const video_id = ref('') // 直播视频id
-const currentLiveUrl = ref('') // 当前直播地址
-const isMaxMap = ref(false) //是大地图
-const client_id = ref('') //mqtt id
-const hasIr = ref(false) //有红外能力
-const isAutoControl = ref(true) //是否自动控制
-const showUpKeyPanel = ref(false) //显示按键面板
-const isTakeOff = ref(false) // 是在飞行中
-const isBackDock = ref(false) //是返航
-const activeSlider = ref(false) //变焦滑块在活动
-const isRecording = ref(false) //是录像
-const searchlightMode = ref(0) //探照灯模式
-// const showHead = computed(() => !isMaxMap.value || showUpKeyPanel.value || !(isAutoControl.value || isBackDock.value)) //显示头部
-const showHead = ref(true) //显示头部
-const cameraParams = ref({ zoom_factor: 0, camera_type: 'wide', hasVisable: false }) //相机参数
-let taskDetails = ref({})
-const taskWayLineDetails = ref([])
-let workspace_id = ref(null)
-const currentWayLine = computed(
- () =>
- taskWayLineDetails?.value?.find(item => item.device_sn === props?.selectDockSn) ||
- taskWayLineDetails?.value?.[0]
-)
-const isRouteRecord = ref(false) //是航线录制
-const recordingId = ref('') //航线录制id
-const recordingTime = ref('00:00:00') //录像时间
-const irModeStyleType = ref(null) //红外模式样式Type
-const dialogLoading = ref(false) //转圈加载
-const aiLoading = ref(false) //ai按钮转圈加载
-const showKeyRemark = ref(false) //快捷键弹框
-const showFunBlock = ref(true) //显示功能模块
-const droneModel = ref(null) //无人机型号 67 91 100
-const hasAiTypeStr = computed(() => !!taskDetails.value?.ai_type_str)//有算法
-const loadDevice = ref({}) //负载设备信息
-const liveFullScreen = ref(true) //默认全屏
-const canReceive = ref(true) //能接收 一个辅助变量
-const droneModelText = ref('')
-const isManualControl = ref(false) //当前状态是手控
-const usedControl = ref(false) //是否使用过手动控制
-const apiDisable = ref(false) //api禁用
-const liveSuccess = ref(true) //直播正常
-const debounceCanReceive = _.debounce(() => (canReceive.value = true), 4000)
-const realTimeMap = ref(null)
-const showBottomLeftCorner = ref(false) //显示左下角
-const speakerInfo = ref({
- play_volume: 80,
- play_mode: 0, //{"0":"单次播放","1":"循环播放(单曲)"}
- work_mode: 0, //{"0":"TTS 负载模式","1":"录音喊话"}
- //{"0":"空闲中","1":"传输中(机场到飞行器)","2":"播放中","3":"异常中","4":"TTS 文本转换中","99":"下载中(机场从云端下载)"}
- system_state: 0, //这个不准
-})
-
-// 延迟接收--四秒后自动恢复
-const delayedRecepAuto = () => {
- canReceive.value = false
- debounceCanReceive()
-}
-
-let { wsInfo } = useDroneWS(workspace_id) //ws信息,是一个ref对象
-const hasPayloadControl = ref(false) // 有控制权限
-const droneStatus = ref({
- mode_code: undefined,
- text: undefined,
-})
-const zoomFactor = ref({
- ir: { max: 0, min: 0 },
- zoom: { max: 0, min: 0 },
-})
-
-provide('speakerInfo', speakerInfo)
-provide('isCurFlightTask', isCurFlightTask)
-provide('showBottomLeftCorner', showBottomLeftCorner)
-provide('currentWayLine', currentWayLine)
-provide('recordingId', recordingId)
-provide('infoList', infoList)
-provide('apiDisable', apiDisable)
-provide('usedControl', usedControl)
-provide('isTakeOff', isTakeOff)
-provide('droneModelText', droneModelText)
-provide('delayedRecepAuto', delayedRecepAuto)
-provide('canReceive', canReceive)
-provide('liveFullScreen', liveFullScreen)
-provide('loadDevice', loadDevice)
-provide('showUpKeyPanel', showUpKeyPanel)
-provide('hasAiTypeStr', hasAiTypeStr)
-provide('droneModel', droneModel)
-provide('showKeyRemark', showKeyRemark)
-provide('showFunBlock', showFunBlock)
-provide('aiLoading', aiLoading)
-provide('dialogLoading', dialogLoading)
-provide('irModeStyleType', irModeStyleType)
-provide('recordingTime', recordingTime)
-provide('isRouteRecord', isRouteRecord)
-provide('searchlightMode', searchlightMode)
-provide('isRecording', isRecording)
-provide('zoomFactor', zoomFactor)
-provide('droneStatus', droneStatus)
-provide('wsInfo', wsInfo)
-provide('hasPayloadControl', hasPayloadControl)
-provide('cameraParams', cameraParams)
-provide('isMaxMap', isMaxMap)
-provide('isBackDock', isBackDock)
-provide('workspace_id', workspace_id)
-provide('dockOsdInfo', wsInfo?.value?.dock_osd)
-provide('dockSn', dockSn)
-provide('droneSn', droneSn)
-provide('isAutoControl', isAutoControl)
-provide('isManualControl', isManualControl)
-provide('lineQuality', lineQuality)
-provide('taskDetailsViewer', taskDetailsViewer)
-provide('taskDetails', taskDetails)
-provide('taskWayLineDetails', taskWayLineDetails)
-provide('trueAltitude', trueAltitude)
-provide('isAiLive', isAiLive)
-provide('video_id', video_id)
-provide('client_id', client_id)
-provide('hasIr', hasIr)
-provide('showHead', showHead)
-provide('activeSlider', activeSlider)
-
-const userId = computed(() => store.state.user.userInfo.user_id)
-
-// 获取机巢直播
-const getDeviceLiveUrl = async () => {
- try {
- const res = await liveStart(dockSn.value, 2)
- currentLiveUrl.value = res.data.data.rtcs_url
- video_id.value = null
- liveSuccess.value = true
- } catch (e) {
- liveSuccess.value = false
- }
-}
-
-// set Ai直播url
-const getAiLiveUrl = async () => {
- if (!video_id.value) return showToast('无人机未起飞,无法开启AI识别')
- if (!isCurFlightTask.value) return
- aiLoading.value = true
- try {
- const res = await getLiveAiLinkApi({
- original_stream_url: `${CURRENT_CONFIG.rtmpURL}${video_id.value.replace(/\//g, '-')}`,
- video_id: video_id.value,
- })
- currentLiveUrl.value = res.data.data.rtcs_url
- showToast('开启成功')
- openSendWsApi(droneSn.value, { type: 'AI' }, { open: true, user_id: userId.value })
- isAiLive.value = true
- } catch (e) {}
- aiLoading.value = false
-}
-
-// 获取无人机直播url
-async function getDroneLiveUrl(reset = false, sn) {
- try {
- delayedRecepAuto()
- currentLiveUrl.value = ''
- await nextTick()
- const res = await liveStart(sn || droneSn.value, lineQuality.value)
- currentLiveUrl.value = res.data.data.rtcs_url
- video_id.value = res.data.data.video_id
- isAiLive.value = false
- reset && showToast('刷新成功')
- liveSuccess.value = true
- } catch (e) {
- liveSuccess.value = false
- }
-}
-
-// 无人机直播画质切换
-const changeLineQuality = async () => {
- await updateDroneQualityApi({ video_id: video_id.value, video_quality: lineQuality.value })
- showToast('切换画质成功')
-}
-
-// 设置当前直播地址
-const setCurrentLiveUrl = async () => {
- const deviceInfo = wsInfo.value?.device_osd?.data?.host
- if (!deviceInfo) return
- const currentIsTakeOff = ![14, 0].includes(deviceInfo?.mode_code)
- // 如果还是之前的状态,不切换
- if (isTakeOff.value === currentIsTakeOff) return
- isTakeOff.value = currentIsTakeOff
- isTakeOff.value && isCurFlightTask.value ? await getDroneLiveUrl() : await getDeviceLiveUrl()
-}
-
-// 获取相机信息,只会触发一次
-const getCameraInfo = useRunOnce(() => {
- getCameraInfoApi(droneSn.value, 1).then(res => {
- res.data?.data?.forEach(item => {
- if (item.camera_mode === 4) {
- cameraParams.value.hasVisable = !!item.is_storage
- }
- if (item.camera_mode === 3 && item.is_storage) {
- hasIr.value = true
- }
- if ([2, 3].includes(item.camera_mode)) {
- const field = item.camera_mode === 3 ? 'ir' : 'zoom'
- zoomFactor.value[field].max = _.round(item.zoom_factor_max, 0)
- zoomFactor.value[field].min = _.round(item.zoom_factor_min, 0)
- if (field === 'zoom') {
- // 设置广角默认值
- cameraParams.value.zoom_factor = _.round(item.zoom_factor_min - 1, 0)
- }
- }
- })
- })
-})
-
-// 获取当前psdk信息
-const getDevicePsdkInfo = useRunOnce(() => {
- getDevicePsdkInfoApi(droneSn.value).then(res => {
- const psdkInfo = res?.data?.data?.psdk_widget_values
- const speaker = psdkInfo?.[0]?.speaker
- if (speaker) {
- speakerInfo.value = speaker
- }
- getDevicePsdkInfoWs(psdkInfo)
- })
-})
-
-function switchMapSize() {
- isMaxMap.value = !isMaxMap.value
- nextTick(() => {
- realTimeMap?.value?.mapReset()
- })
-}
-function switchShowSmallWindow() {
- showBottomLeftCorner.value = !showBottomLeftCorner.value
- nextTick(() => {
- realTimeMap?.value?.mapReset()
- })
-}
-
-// 获取实时psdk信息
-const getDevicePsdkInfoWs = psdkInfoList => {
- if (psdkInfoList) {
- const findSpeaker = psdkInfoList?.find(item => item.psdk_index === 2)
- const findSearchlight = psdkInfoList?.find(item => item.psdk_name === 'Searchlight')
- if (findSpeaker) {
- if (!findSearchlight) {
- }
- }
- if (findSearchlight) {
- }
- }
-}
-
-// 设置相机类型和清晰度
-const setLiveStatusWs = live_status => {
- if (live_status) {
- cameraParams.value.camera_type = live_status?.video_type || 'wide'
- lineQuality.value = live_status?.video_quality || 1
- }
-}
-
-// 获取当前相机类型和视频清晰度
-const getLiveStatusRunOnce = useRunOnce(() => {
- getLiveStatusApi(dockSn.value).then(res => {
- const live_status = res.data?.data?.live_status?.[0]
- setLiveStatusWs(live_status)
- })
-})
-
-// 获取无人机负载设备信息
-const getLoadInfoRunOnce = useRunOnce(() => {
- getLoadInfoApi(dockSn.value).then(res => {
- loadDevice.value = res.data?.data || {}
- })
-})
-// 获取信息航线是否录制
-const getviewTheRecording = useRunOnce(() => {
- viewTheRecording({ sn: dockSn.value }).then(res => {
- isRouteRecord.value = res.data.data ? true : false
- recordingId.value = res.data.data.id
- // console.log('获取信息', res.data.data)
- })
-})
-// 开启ai识别
-const openAiRunOnce = useRunOnce(getAiLiveUrl)
-
-// 统一节流处理
-const wsInfoChangeThrottle = _.throttle(wsInfo => {
- const { mode_code, payloads } = wsInfo.value?.device_osd?.data?.host || {}
- const { sub_device } = wsInfo.value?.dock_osd?.data?.host || {}
- const { ai, searchlight } = wsInfo.value?.web_request_send_ws?.data || {}
- const live_status = wsInfo.value?.live_status?.data?.live_status
- const speaker = wsInfo.value?.psdk_widget_values?.data?.psdk_widget_values?.[0]?.speaker
-
- if (canReceive.value) {
- searchlightMode.value = searchlight?.value || 0
- if (ai?.open && !isAiLive.value && ai?.user_id === userId.value) {
- openAiRunOnce()
- }
- if (speaker) {
- speakerInfo.value = speaker
- }
- setLiveStatusWs(live_status?.[0])
- }
- if (mode_code !== undefined) {
- droneStatus.value = { text: EModeText?.[mode_code] || '--', mode_code }
- }
- if (sub_device?.device_model_key !== undefined) {
- droneModel.value = DRONE_LIST.find(item => sub_device?.device_model_key?.includes(item.value))?.value
- }
- irModeStyleType.value = payloads?.[0]?.thermal_current_palette_style
- getDevicePsdkInfoWs(wsInfo.value?.psdk_widget_values?.data?.psdk_widget_values)
-}, 1000)
-
-watch(
- wsInfo,
- () => {
- setCurrentLiveUrl()
- if (wsInfo.value?.device_osd) {
- getCameraInfo()
- getDevicePsdkInfo()
- // getviewTheRecording()
- }
- if (wsInfo.value?.dock_osd) {
- getLiveStatusRunOnce()
- getLoadInfoRunOnce()
- }
- wsInfoChangeThrottle(wsInfo)
- },
- { deep: true }
-)
-
-async function getTaskDetailsFun() {
- try {
- const minJobListRes = await getJobsByJobInfoIdApi({ jobInfoId: props.wayLineJobInfoId })
- let minJobList = minJobListRes.data.data || []
- if (props.batchNo !== null && props.batchNo !== undefined){
- minJobList = minJobList.filter(item => item.batch_no === Number(props.batchNo))
- }
- currentMinJob.value = minJobList.find(item => item.dock_sn === props.selectDockSn)
-
-
- console.log(currentMinJob, minJobList, props.selectDockSn, 11)
-
-
- isCurFlightTask.value = currentMinJob.value?.status === 2
-
- const params = {
- wayLineJobInfoId: props.wayLineJobInfoId,
- waylineJobId: currentMinJob.value?.id,
- batchNo: currentMinJob.value?.batch_no,
- }
-
- const res = await getJobDetails(params)
-
- const wayLineDetails = await getJobWayLineDetails({
- ...params,
- sn: props.selectDockSn
- })
-
- taskWayLineDetails.value = wayLineDetails.data.data
-
- taskDetails.value = res.data.data
- await getDetailsCallBack()
- workspace_id.value = currentWayLine.value?.workspace_id
- } catch (error) {
- console.log(error)
- }
-}
-
-watch(
- () => wsInfo.value?.flighttask_progress?.data?.bid,
- val => {
- const flightTaskId = currentMinJob.value.job_id
- isCurFlightTask.value = flightTaskId ? val === flightTaskId : true
- }
-)
-
-onMounted(() => {
- getTaskDetailsFun()
- store.commit('setConsoleShow', true)
- EventBus.on('CurrentTaskDetails-changeLineQuality', changeLineQuality)
- EventBus.on('CurrentTaskDetails-getAiLiveUrl', getAiLiveUrl)
- EventBus.on('CurrentTaskDetails-getDroneLiveUrl', getDroneLiveUrl)
-})
-
-onBeforeUnmount(() => {
- store.commit('setConsoleShow', false)
- EventBus.off('CurrentTaskDetails-changeLineQuality', changeLineQuality)
- EventBus.off('CurrentTaskDetails-getAiLiveUrl', getAiLiveUrl)
- EventBus.off('CurrentTaskDetails-getDroneLiveUrl', getDroneLiveUrl)
-})
-</script>
-
-<style lang="scss">
-.current-task-details {
- display: flex;
- justify-content: space-between;
-
- .closeOrBack {
- position: absolute;
- padding-left: 5px;
- left: 0;
- top: 14px;
- color: #fff;
- font-size: 35px;
- z-index: 5001;
-
- .el-icon {
- cursor: pointer;
- }
- }
-
- .el-dialog {
- position: relative;
- padding: 0;
-
- .el-dialog__body {
- width: 100%;
- height: 100%;
- }
-
- .el-dialog__header {
- height: 0;
- overflow: hidden;
- padding: 0;
- }
- }
-}
-</style>
-
-<style lang="scss" scoped>
-.content-container {
- //变量
- $minBoxWidth: half(184);
- $minBoxHeight: half(88);
-
- position: absolute;
- height: 210.9375px;
- width: 375px;
- //height: 100%;
- //width: 100%;
- overflow: hidden;
- font-size: 9px;
-
- &.landscapeMode {
- height: 100%;
- width: 100%;
- }
-
- :deep() {
- .whiteBtn {
- padding: 0 half(7);
- flex-shrink: 0;
- height: half(38);
- background: #ffffff;
- border-radius: half(8);
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- font-size: half(13);
- color: #171717;
- line-height: half(38);
- text-align: center;
- }
- }
-
- #liveVideoBox{
- .liveErr{
- position: relative;
- width: 100%;
- height: 100%;
- background: rgba(31, 31, 31, 0.6);
- .liveErrBg{
- position: relative;
- width: 100%;
- height: 100%;
- background: url(@/assets/images/offLine.svg) no-repeat center / 80% 80%;
- color: #ededed;
- font-size: 16px;
- }
- }
- }
-
- &.showBottomLeftCorner {
- .minBox {
- visibility: visible;
- width: $minBoxWidth;
- height: $minBoxHeight;
- }
- .smallWindowArrow {
- cursor: pointer;
- transform: translate(0, 100%);
- position: absolute;
- left: calc(#{$minBoxWidth} - half(27));
- bottom: $minBoxHeight;
- }
- }
-
- .centerPoint {
- &:before {
- z-index: 5;
- opacity: 0.5;
- border-radius: 50%;
- background-color: yellow;
- content: '';
- font-size: 30px;
- position: absolute;
- width: half(10);
- height: half(10);
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- pointer-events: none;
- font-weight: bold;
- text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black; /* 四方向描边 */
- }
- }
-
- .maxBox {
- width: 100%;
- height: 100%;
- }
-
- .minBox {
- position: absolute;
- visibility: hidden;
- width: $minBoxWidth;
- height: $minBoxHeight;
- left: 0;
- bottom: 0;
- z-index: 999;
- }
-
- .amplify {
- cursor: pointer;
- position: absolute;
- background: rgba(0, 0, 0, 0.3);
- transform: translate(0, 100%);
- left: 0;
- bottom: $minBoxHeight;
- width: half(27);
- height: half(27);
- z-index: 999;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 10%;
- > img {
- width: half(20);
- height: half(20);
- }
- }
-
- .smallWindowArrow {
- cursor: pointer;
- position: absolute;
- transform: translate(0, 50%) rotate(180deg);
- background: rgba(0, 0, 0, 0.3);
- left: 0;
- bottom: calc($minBoxHeight / 2);
- z-index: 999;
- color: white;
- width: half(27);
- height: half(27);
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 10%;
-
- > img {
- width: half(18);
- height: half(18);
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/DroneSlider.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/DroneSlider.vue
deleted file mode 100644
index 4e6d087..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/DroneSlider.vue
+++ /dev/null
@@ -1,123 +0,0 @@
-<template>
- <el-slider
- :marks="marks"
- :format-tooltip="convertValue"
- size="large"
- v-model="zoom_factor"
- vertical
- ref="sliderRef"
- :min="0"
- :max="1000"
- @input="inputChange"
- @change="sliderChange"
- />
-</template>
-<script setup>
-import _ from 'lodash'
-
-const modelValue = defineModel()
-const props = defineProps(['zoomModel'])
-const emit = defineEmits(['change', 'input'])
-const zoomModel = computed(() => props.zoomModel.toString())
-const sliderRef = ref(null)
-
-const marksObj = {
- '56': { 0: '1X', 250: '2X', 500: '7X', 750: '14X', 1000: '56X' },
- '200': { 0: '1X', 250: '2X', 500: '10X', 750: '20X', 1000: '200X' },
- '112': { 0: '1X', 250: '2X', 500: '14X', 750: '56X', 1000: '112X' },
- '28': { 0: '2X', 250: '4X', 500: '7X', 750: '14X', 1000: '28' },
-}
-const rulesObj = {
- // 56倍变焦规则
- '56': [
- [0, 250, 1, 2],
- [250, 500, 2, 7],
- [500, 750, 7, 14],
- [750, 1000, 14, 56],
- ],
- // 200倍变焦规则
- '200': [
- [0, 250, 1, 2],
- [250, 500, 2, 10],
- [500, 750, 10, 20],
- [750, 1000, 20, 200],
- ],
- // 112倍变焦规则
- '112': [
- [0, 250, 1, 2],
- [250, 500, 2, 14],
- [500, 750, 14, 56],
- [750, 1000, 56, 112],
- ],
- // 28倍红外变焦规则
- '28': [
- [0, 250, 2, 4],
- [250, 500, 4, 7],
- [500, 750, 7, 14],
- [750, 1000, 14, 28],
- ],
-}
-
-const rules = computed(() => rulesObj?.[zoomModel.value] || [])
-const marks = computed(() => marksObj?.[zoomModel.value]|| {})
-
-// val1 -> val2
-function val1ToVal2(value, rules) {
- for (const [min1, max1, min2, max2] of rules) {
- if (value >= min1 && value <= max1) {
- const ratio = (value - min1) / (max1 - min1)
- return _.round(min2 + ratio * (max2 - min2), 1)
- }
- }
- return 0
-}
-
-// val2 -> val1
-function val2ToVal1(value, rules) {
- for (const [min2, max2, min1, max1] of rules.map(([a, b, c, d]) => [c, d, a, b])) {
- if (value >= min2 && value <= max2) {
- const ratio = (value - min2) / (max2 - min2)
- return _.round(min1 + ratio * (max1 - min1), 1)
- }
- }
- return 0
-}
-
-const zoom_factor = computed({
- get: () => val2ToVal1(modelValue.value, rules.value),
- set: val => (modelValue.value = val1ToVal2(val, rules.value)),
-})
-
-// 提示值
-function convertValue(val) {
- return val1ToVal2(val, rules.value) // 保留一位小数
-}
-
-function inputChange(val) {
- if (zoomModel.value !== '28') {
- if (val < 125) {
- zoom_factor.value = 0
- } else if (val >= 125 && val < 250) {
- zoom_factor.value = 250
- }
- }
- if (zoomModel.value === '28'){
- rulesObj['28'].forEach(item => {
- if (val >= item[0] && val <= item[1]){
- const takeValue = _.round((val-item[0]) / 250)
- zoom_factor.value = item[takeValue]
- }
- })
- }
- const valProvides = val1ToVal2(val, rules.value)
- emit('input', valProvides)
-}
-
-function sliderChange(val) {
- sliderRef.value?.$el?.querySelectorAll('*')?.forEach(el => el.blur())
- const valProvides = val1ToVal2(val, rules.value)
- emit('change', valProvides)
-}
-</script>
-<style scoped lang="scss">
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/RealTimeMap.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/RealTimeMap.vue
deleted file mode 100644
index 262960f..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/RealTimeMap.vue
+++ /dev/null
@@ -1,164 +0,0 @@
-<template>
- <div class="realTimeMap">
- <div id="currentTaskMap"></div>
- </div>
-</template>
-<script setup>
-import L from 'leaflet'
-import 'leaflet/dist/leaflet.css'
-import {
- basemapLayer0,
- basemapLayer1,
- basemapLayer2,
- basemapLayer3,
- polylineOptions0,
- polylineOptions1, polylineOptions2,
-} from '@/const/leafletConst'
-import 'leaflet-ant-path'
-import droneIcon from '@/appDataSource/leafletMapIcon/drone-icon3.svg'
-import sl from '@/appDataSource/leafletMapIcon/sl.svg'
-import yx from '@/appDataSource/leafletMapIcon/yx.svg'
-import { analysisPointLineKmz } from '@/utils/cesium/pointWayLineUtils'
-import startImg from '@/assets/images/signMachineNest/start.png'
-import endPointImg from '@/assets/images/signMachineNest/end.png'
-import { useAreaBoundary } from '@/hooks/useAreaBoundary'
-import { useIdentificationAreaForApp } from '@ztzf/hooks'
-
-const taskDetailsViewer = inject('taskDetailsViewer')
-const showUpKeyPanel = inject('showUpKeyPanel')
-const isMaxMap = inject('isMaxMap')
-const taskDetails = inject('taskDetails')
-const taskWayLineDetails = inject('taskWayLineDetails')
-const currentWayLine = inject('currentWayLine')
-const wsInfo = inject('wsInfo')
-const isCurFlightTask = inject('isCurFlightTask')
-let map = null
-let markersLayer = null
-let boundsGroup = []
-const basemap0 = L.layerGroup([basemapLayer0, basemapLayer1])
-const basemap1 = L.layerGroup([basemapLayer2, basemapLayer3])
-const layers = [
- { src: sl, name: '天地图电子', key: 1, map: basemap0 },
- { src: yx, name: '天地图影像', key: 2, map: basemap1 },
-]
-let boundaryInstance = useAreaBoundary()
-
-const {setArea,removeArea } = useIdentificationAreaForApp()
-const initMap = async () => {
- map = L.map('currentTaskMap', {
- preferCanvas: true,
- crs: L.CRS.EPSG4326,
- zoomControl: false,
- attributionControl: false,
- doubleClickZoom: false,
- editable: true, //绘制控件
- }).setView([25.992338, 114.823254], 13)
- await boundaryInstance.initBoundary(map)
- markersLayer = L.layerGroup().addTo(map) // 创建一个标注层,便于管理和移除
- map.addLayer(layers[0].map)
- setArea(taskDetails.value.ai_types.split(','),map)
- // 渲染航线并且收集所有航线的边界
- boundsGroup = []
- const wayLines = taskWayLineDetails.value || []
- console.log(taskDetails?.value,'taskDetails?.value')
- if (taskDetails?.value?.rep_rule_type){
- const bounds = await renderRoutes(wayLines[0], 0)
- if (bounds) boundsGroup.push(bounds)
- }else{
- for (let i = 0; i < wayLines.length; i++) {
- const bounds = await renderRoutes(wayLines[i], i)
- if (bounds) boundsGroup.push(bounds)
- }
- }
- flyBounds()
-}
-
-// 合理显示范围
-function flyBounds() {
-// 统一调整视图
- if (boundsGroup.length > 0) {
- const combinedBounds = boundsGroup.reduce((acc, bounds) => acc.extend(bounds), L.latLngBounds(boundsGroup[0]))
- map.fitBounds(combinedBounds.pad(0.1))
- }
-}
-
-
-// 渲染航线
-async function renderRoutes(row,index) {
- let { pointList } = await analysisPointLineKmz(row.url)
- const { latitude, longitude } = row || {}
- pointList[0] = { latitude, longitude }
- let points = pointList.map(item => [item.latitude, item.longitude])
- const colors = [polylineOptions0,polylineOptions1,polylineOptions2]
- let currentPolyline = L.polyline.antPath(points, colors[index]).addTo(markersLayer)
- const startIcon = L.icon({ iconUrl: startImg, iconSize: [30, 30] })
- const endIcon = L.icon({ iconUrl: endPointImg, iconSize: [30, 30] })
- L.marker(points[0], { icon: startIcon }).addTo(markersLayer)
- L.marker(points[points.length - 1], { icon: endIcon }).addTo(markersLayer)
- // map.fitBounds(currentPolyline.getBounds().pad(0.1))
-
- // 返回边界而不是直接调整地图视图
- return currentPolyline.getBounds()
-}
-
-
-
-const droneEntity = L.icon({ iconUrl: droneIcon, iconSize: [30, 30] })
-let currentDronePosition = null
-
-function updateDronePosition(deviceOsdInfo) {
- const { longitude, latitude } = deviceOsdInfo || {}
- if (!longitude) return
- if (!currentDronePosition) {
- currentDronePosition = L.marker([latitude, longitude], { icon: droneEntity }).addTo(markersLayer)
- }
- currentDronePosition.setLatLng([latitude, longitude])
-}
-
-watch(
- wsInfo,
- () => {
- isCurFlightTask.value && updateDronePosition(wsInfo.value?.device_osd?.data?.host)
- },
- { deep: true, immediate: true }
-)
-
-watch(isCurFlightTask,()=>{
- if (!isCurFlightTask.value){
- currentDronePosition.remove(); // 从地图上移除标记
- currentDronePosition = null; // 清空引用,避免内存泄漏或误操作
- }
-})
-
-const removeMap = () => {}
-
-function mapReset() {
- map.invalidateSize()
- flyBounds()
-}
-
-defineExpose({ mapReset })
-
-onBeforeUnmount(() => {
- removeMap()
-})
-
-onMounted(() => {
- nextTick(() => {
- initMap()
- })
-})
-</script>
-<style scoped lang="scss">
-.realTimeMap {
- position: relative;
- z-index: 1;
- width: 100%;
- height: 100%;
-
- #currentTaskMap {
- width: 100%;
- height: 100%;
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/CurrentTaskDetails/TaskDetailsHead.vue b/applications/mobile-web-view/src/components/CurrentTaskDetails/TaskDetailsHead.vue
deleted file mode 100644
index 569c71a..0000000
--- a/applications/mobile-web-view/src/components/CurrentTaskDetails/TaskDetailsHead.vue
+++ /dev/null
@@ -1,470 +0,0 @@
-<template>
- <div class="detailsHead">
- <div class="leftArrow" @click="goBack">
- <img :src="leftArrowSvg" alt="" />
- </div>
- <div class="droneNameBox">
- <div class="droneName">{{ currentWayLine?.name }}</div>
- <div class="stateBox" v-if="isCurFlightTask" :style="getColorStyle(droneStatus.text ? droneStatus.mode_code : 0)">
- {{ droneStatusText }}
- </div>
- </div>
- <div class="infoListBox">
- <template v-if="isCurFlightTask">
- <div>
- <div class="infoValue">
- <img :src="sjSvg" alt="" />
- {{ time }}
- </div>
- </div>
- <div v-for="item in infoList.filter(i => !i.hide)">
- <div class="infoValue" :title="item.tips || item.value" @click="titleClick(item)">
- <img :src="item.img" alt="" />
- {{ item.value }}{{ item.unit }}
- </div>
- </div>
- </template>
- </div>
-
- <div
- class="aiRecognition"
- :class="{ disable: aiTypeDisable }"
- v-if="taskDetails?.ai_type_str && !aiTypeDisable && isCurFlightTask"
- >
- <!-- <div class="aiRecognition" :class="{ disable: aiTypeDisable }">-->
- <div>AI识别</div>
- <div class="switchBtn" @click="switchAiBtn">
- <div :class="{ open: !isAiLive }">OFF</div>
- <div :class="{ open: isAiLive }" style="position: relative">
- <el-icon class="loadingOn" v-if="aiLoading">
- <Loading />
- </el-icon>
- <template v-else>ON</template>
- </div>
- </div>
- </div>
-
- <img class="proportionalSwitch" v-if="liveFullScreen" :src="originalImg" alt="" @click="original" />
- <img class="proportionalSwitch" v-else :src="fillFullImg" alt="" @click="fillFull" />
- <img
- v-if="uniPlatform === 'h5'"
- class="proportionalSwitch"
- :src="isFullscreen ? qpsxImg : qpfdImg"
- alt=""
- @click="toggleFullscreen"
- />
- <img class="shuaxing" v-if="isTakeOff && isCurFlightTask" :src="sxSvg" alt="" @click="refreshLive" />
- </div>
-</template>
-
-<script setup>
-import { getFlightStatistics } from '@/api/home/machineNest'
-import _, { throttle } from 'lodash'
-import fillFullImg from '@/assets/images/taskManagement/currentTaskDetails/fillFull.svg'
-import originalImg from '@/assets/images/taskManagement/currentTaskDetails/original.svg'
-import qpsxImg from '@/assets/images/taskManagement/currentTaskDetails/qpsx.svg'
-import qpfdImg from '@/assets/images/taskManagement/currentTaskDetails/qpfd.svg'
-import { fourGQuality, SDRQuality } from '@/const/drc'
-import EventBus from '@/utils/eventBus'
-import { routeRecordStartApi, routeRecordStatusApi, routeRecordStopApi, startRecording, stopRecording } from '@/api/drc'
-import { useRunOnce } from '@/hooks'
-import getBaseConfig from '@/buildConfig/config'
-import { droneMode } from '@/const/device'
-import { closeSendWsApi, openSendWsApi } from '@/api/payload'
-import sxSvg from '@/appDataSource/inspectionTask/droneConsole/刷新.svg'
-import sjSvg from '@/appDataSource/inspectionTask/droneConsole/时间.svg'
-import leftArrowSvg from '@/appDataSource/inspectionTask/droneConsole/leftArrow.svg'
-import { showToast } from 'vant'
-import dayjs from 'dayjs'
-import { exitFullScreen, reqFullScreen } from '@/utils/util'
-import { Loading } from '@element-plus/icons-vue'
-
-const { hideRouteRecord } = getBaseConfig()
-
-const taskDetailsViewer = inject('taskDetailsViewer')
-const wsInfo = inject('wsInfo')
-const dockSn = inject('dockSn')
-const droneSn = inject('droneSn')
-const taskDetails = inject('taskDetails')
-const isAiLive = inject('isAiLive')
-const singleTotal = ref({})
-const trueAltitude = inject('trueAltitude')
-const isRouteRecord = inject('isRouteRecord')
-const droneStatus = inject('droneStatus')
-const aiLoading = inject('aiLoading')
-const showKeyRemark = inject('showKeyRemark')
-const hasAiTypeStr = inject('hasAiTypeStr')
-const showFunBlock = inject('showFunBlock')
-const liveFullScreen = inject('liveFullScreen')
-const delayedRecepAuto = inject('delayedRecepAuto')
-const isTakeOff = inject('isTakeOff')
-const infoList = inject('infoList')
-const recordingId = inject('recordingId')
-const currentWayLine = inject('currentWayLine')
-const isCurFlightTask = inject('isCurFlightTask')
-
-// ai识别按钮禁用
-const aiTypeDisable = computed(() => {
- return [0, 1, 2, 9, 10, 11, 12, undefined].includes(droneStatus.value?.mode_code)
-})
-const store = useStore()
-const uniPlatform = computed(() => store.state.common.uniPlatform)
-const droneStatusText = computed(() => {
- const val = droneStatus.value.text || '舱内关机'
- if (val === '手动飞行') {
- return '暂停'
- }
- return val
-})
-
-const time = ref('')
-const updateTime = () => {
- time.value = dayjs().format('HH:mm')
-}
-
-function original() {
- liveFullScreen.value = false
-}
-
-function fillFull() {
- liveFullScreen.value = true
-}
-
-// 控制台显示切换
-function consoleSwitch() {
- showFunBlock.value = !showFunBlock?.value
-}
-
-const isFullscreen = ref(false)
-// 切换全屏状态
-const toggleFullscreen = () => {
- try {
- isFullscreen.value ? exitFullScreen() : reqFullScreen()
- isFullscreen.value = !isFullscreen.value
- } catch (e) {
- showToast('您的浏览器不支持全屏')
- }
-}
-
-// ai识别开关
-const switchAiBtn = () => {
- delayedRecepAuto()
- if (aiTypeDisable.value) return
- if (isAiLive.value) {
- EventBus.emit('CurrentTaskDetails-getDroneLiveUrl')
- closeSendWsApi(droneSn.value, { type: 'AI' })
- } else {
- EventBus.emit('CurrentTaskDetails-getAiLiveUrl')
- }
-}
-
-// 经纬度复制
-function titleClick(data) {
- data.tips &&
- navigator.clipboard.writeText(data.tips).then(() => {
- showToast('复制成功')
- })
-}
-
-function goBack() {
- const transmitData = { data: { type: 'back', taskDetails: JSON.parse(JSON.stringify(taskDetails.value)) } }
- wx.miniProgram.navigateBack({
- delta: 1 // 返回的页面数,默认1(返回上一页)
- })
- wx.miniProgram.postMessage(transmitData)
- uni.postMessage(transmitData)
-}
-
-// 航线录制
-async function routeRecordFun() {
- if (!droneSn.value) return showToast('无人机未起飞,请起飞后再录制')
- if ([9, 10, 0, 1, 2].includes(droneStatus.value.mode_code)) return showToast('当前状态不允许录制')
-
- startRecording({
- sn: dockSn.value,
- waylineJobId: taskDetails.value.wayline_job_id,
- name: taskDetails.value?.name,
- }).then(res => {
- isRouteRecord.value = true
- recordingId.value = res.data.data.id
- showToast('开始航线录制成功')
- })
- // ElMessageBox.confirm('是否暂停航线?', '提示', {
- // confirmButtonText: '确定',
- // cancelButtonText: '取消',
- // customClass: 'ztzf-message-box-grey',
- // type: 'warning',
- // })
- // .then(() => {})
- // .catch(() => {})
-}
-
-function getColorStyle(code) {
- if (code === null || code === undefined) return
- const row = droneMode?.[code]
- return {
- color: row?.color,
- borderColor: row?.color,
- // backgroundColor: row?.color?.replace(/\)/, ', 0.2)'),
- }
-}
-
-// 停止航线录制
-function routeRecordStopFun() {
- if (!droneSn.value) return
- isRouteRecord.value = false
- stopRecording(recordingId.value).then(res => {
- isRouteRecord.value = false
- recordingId.value = ''
- showToast('航线录制结束')
- })
-}
-
-function refreshLive() {
- EventBus.emit('CurrentTaskDetails-getDroneLiveUrl', true)
-}
-
-function shortcutKeys() {
- showKeyRemark.value = true
-}
-
-function getFlightStatisticsFun() {
- if (!dockSn.value) return
- getFlightStatistics(dockSn.value).then(res => {
- singleTotal.value = res.data.data
- })
-}
-
-const getRouteRecordStatus = useRunOnce(() => {
- routeRecordStatusApi(droneSn.value).then(res => {
- isRouteRecord.value = res.data.data === 'START_OF_RECORD'
- })
-})
-
-let chargeBatteryVal
-let beforeRemainTime = 1000 * 60
-
-function getHeadInfo() {
- const device_osd_host = wsInfo?.value?.device_osd?.data?.host || {}
- const dock_osd_host = wsInfo?.value?.dock_osd?.data?.host || {}
- const chargeBattery = dock_osd_host?.drone_battery_maintenance_info?.batteries[0]?.capacity_percent
- if (chargeBattery) {
- chargeBatteryVal = chargeBattery
- }
- const { longitude, latitude, height, horizontal_speed, vertical_speed, wind_speed, battery } = device_osd_host
- const { longitude: dockLon, latitude: dockLat, wireless_link } = dock_osd_host
-
- const newGPSNum = dock_osd_host?.position_state?.gps_number
- const newRTKNum = dock_osd_host?.position_state?.rtk_number
- let newRemainTime = battery?.remain_flight_time
- 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((wind_speed || 0) / 10, 0)
- if (newFourG !== undefined) infoList.value[4].value = fourGQuality[newFourG]
- if (newSdr !== undefined) infoList.value[5].value = SDRQuality[newSdr]
- if (newRemainTime && newRemainTime < beforeRemainTime) {
- beforeRemainTime = newRemainTime
- }
- infoList.value[6].value = battery?.capacity_percent || chargeBatteryVal || '--'
- if (infoList.value[6].value > 100) infoList.value[6].value = 100
-}
-
-const getHeadInfoThrottle = throttle(getHeadInfo, 1000, { leading: true, trailing: true })
-
-watch(
- wsInfo,
- () => {
- getHeadInfoThrottle()
- if (wsInfo.value?.device_osd) {
- getRouteRecordStatus()
- }
- },
- { immediate: true, deep: true }
-)
-
-watch(dockSn, getFlightStatisticsFun, { immediate: true })
-
-let intervalTime
-onMounted(() => {
- intervalTime = setInterval(updateTime, 1000)
-})
-onUnmounted(() => {
- if (intervalTime) {
- clearInterval(intervalTime)
- intervalTime = null
- }
-})
-</script>
-<style lang="scss">
-.more-popper {
- border: none !important;
- border-radius: 10px;
- background: rgba(0, 0, 0, 0.4) !important;
- backdrop-filter: blur(5px);
-
- .el-popper__arrow {
- display: none;
- }
-}
-</style>
-
-<style scoped lang="scss">
-.detailsHead {
- position: absolute;
- z-index: 1;
- top: 0;
- width: 100%;
- height: half(34);
- padding-right: half(15);
- background: rgba(22, 22, 22, 0.5);
- backdrop-filter: blur(5px);
- display: flex;
- align-items: center;
- font-size: half(13);
- color: #ffffff;
-
- .leftArrow {
- width: half(30);
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
-
- > img {
- width: half(19);
- height: half(19);
- }
- }
-
- .shuaxing,
- .proportionalSwitch {
- width: half(22);
- height: half(22);
- margin-left: half(15);
- }
-
- .droneNameBox {
- color: #ffffff;
- height: 100%;
- padding: 0 2px;
- align-items: center;
- text-align: center;
-
- display: flex;
-
- .droneName {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .stateBox {
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 0 half(6);
- }
- }
-
- .infoListBox {
- width: 0;
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: space-evenly;
- font-family: Segoe UI, Segoe UI;
- font-weight: 400;
-
- > div {
- &.isDegree {
- width: 115px;
- }
-
- .infoValue {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- color: #ffffff;
- display: flex;
- align-items: center;
-
- img {
- width: half(16);
- height: half(16);
- }
- }
-
- .infoTitle {
- color: #d2e8fa;
- line-height: 15px;
- }
- }
- }
-
- .aiRecognition {
- display: flex;
- align-items: center;
- font-family: Segoe UI, Segoe UI;
- font-weight: 400;
- color: #ffffff;
- gap: 0 half(4);
-
- &.disable {
- cursor: not-allowed;
-
- * {
- cursor: not-allowed !important;
- }
- }
- }
-
- .switchBtn {
- width: half(70);
- height: half(20);
- line-height: half(20);
- border-radius: half(4);
- border: 1px solid #ffffff;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-family: Segoe UI, Segoe UI;
- text-align: center;
- color: #ffffff;
- overflow: hidden;
-
- /* 定义旋转动画 */
- @keyframes rotateAnimation {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
- }
-
- .loadingOn {
- width: 100%;
- height: 100%;
- position: absolute;
- left: 0;
- top: 0;
-
- > svg {
- animation: rotateAnimation 2s linear infinite; /* 添加旋转动画 */
- }
- }
-
- > div {
- width: 50%;
- }
-
- .open {
- background: #ffffff;
- color: #242424;
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/components/LiveVideo.vue b/applications/mobile-web-view/src/components/LiveVideo.vue
deleted file mode 100644
index d99442c..0000000
--- a/applications/mobile-web-view/src/components/LiveVideo.vue
+++ /dev/null
@@ -1,535 +0,0 @@
-<!--视频直播-->
-<template>
- <div
- class="live-video"
- v-loading="loading"
- element-loading-background="rgb(33 33 33 / 80%)"
- >
- <video
- :currentLiveUrl="videoUrl"
- ref="liveVideoRef"
- class="video-player"
- :style="{objectFit: liveFullScreen ? 'cover' : 'contain' }"
- :class="{ 'is-border-radius': isBorderRadius }"
- :controls="props.controls"
- autoplay
- muted
- playsinline
- @click="videoClick"
- >
- 您的浏览器太旧,不支持HTML5视频,请升级浏览器。
- </video>
-<!-- <canvas
- v-if="hasRightMenu"
- @dblclick="moveToPoint"
- :class="{ 'draw-canvas': true, 'crosshair': openBoxSelection }"
- :width="canvasWidth"
- :height="canvasHeight"
- @click.right.prevent="rightClick"
- ref="myCanvas"
- />-->
- </div>
- <teleport defer to="body">
- <div v-if="visible" :style="{ top: `${position.y}px`, left: `${position.x}px` }" class="rightMenu">
- <div @click="switchCanvas" v-if="hasFrameZoom">{{ openBoxSelection ? '关闭框选' : '开启框选' }}</div>
- <template v-if="!hideFlyToHere">
- <div @click="flyToHereFun" v-if="hasFlyToHereBtn">飞向此处</div>
- </template>
- <div @click="consoleSwitch">{{ showFunBlock ? '隐藏控制台' : '显示控制台' }}</div>
- </div>
- </teleport>
-
- <div class="flyToHere" v-if="showInputHeightBox">
- <div>目标点真高</div>
- <div class="heightInputBox">
- <el-input-number v-focusDisableKeys :controls="false" v-model="flyToHereHeight" />
- <div>m</div>
- </div>
- <div class="btnList">
- <div class="btnItem" @click="flyToHereClose">取消</div>
- <div class="btnItem" @click="flyToHereExecution">开始执行</div>
- </div>
- </div>
-</template>
-
-<script setup>
-import { flyToHereApi, frameSelectionZoomApi, postPayloadAIM } from '@/api/payload'
-import { ElMessage } from 'element-plus'
-import getBaseConfig from '@/buildConfig/config'
-import { useStore } from 'vuex'
-
-const { hideFlyToHere } = getBaseConfig()
-
-const props = defineProps({
- // 播放url
- videoUrl: {
- type: String,
- default: '',
- },
- // 显示控制台
- controls: {
- type: Boolean,
- default: true,
- },
- isBorderRadius: {
- type: Boolean,
- default: false,
- },
- hasRightMenu: {
- type: Boolean,
- default: false,
- },
- liveFullScreen:{
- type: Boolean,
- default: true,
- }
-})
-let webrtcPlayer = null
-let liveVideoRef = ref(null)
-let tryTimer = null
-const visible = ref(false)
-const position = ref({ x: 0, y: 0 })
-const openBoxSelection = ref(false) //框选变焦
-const canvasWidth = ref(0)
-const canvasHeight = ref(0)
-const myCanvas = ref(null)
-const loading = ref(true)
-const showInputHeightBox = ref(false)
-let curElement = null
-let flyToHereHeight = ref(0)
-let lastTime = 0
-let stallTimer = null
-
-const store = useStore()
-const emit = defineEmits(['videoClick'])
-const droneSn = inject('droneSn')
-const droneStatus = inject('droneStatus')
-const showFunBlock = inject('showFunBlock')
-const droneModel = inject('droneModel')
-const hasPayloadControl = inject('hasPayloadControl')
-const dockSn = inject('dockSn')
-const cameraParams = inject('cameraParams')
-const isAutoControl = inject('isAutoControl')
-const camera_type = computed(() => cameraParams?.value?.camera_type)
-const modeCode = computed(() => droneStatus?.value?.mode_code)
-
-const hasFlyToHereBtn = computed(
- () => [3, 16].includes(modeCode?.value) && hasPayloadControl?.value && droneModel?.value !== '91'
-)
-// 有框选变焦功能
-const hasFrameZoom = computed(
- () =>
- droneSn?.value !== '1581F5BMD22CK0014H2U'
- && hasPayloadControl?.value
- && ![10, 11, 0, 1, 2].includes(modeCode.value)
- && !isAutoControl?.value
-)
-
-// 开启框选变焦
-function switchCanvas() {
- if (!hasFrameZoom.value){
- closeDrawBox()
- return ElMessage.warning('当前状态无法操作')
- }
- openBoxSelection.value = !openBoxSelection.value
- nextTick(openBoxSelection.value ? drawBox : closeDrawBox)
-}
-
-// 控制台显示切换
-function consoleSwitch() {
- showFunBlock.value = !showFunBlock?.value
-}
-
-// 飞向此处弹框
-function flyToHereFun() {
- showInputHeightBox.value = true
- flyToHereHeight.value = 30
-}
-
-// 飞向此处执行
-function flyToHereExecution() {
- const e = curElement
- flyToHereApi({
- sn: dockSn.value,
- x: e.offsetX / e.target.offsetWidth,
- y: e.offsetY / e.target.offsetHeight,
- camera_type: camera_type?.value,
- height: flyToHereHeight.value,
- })
- .then(res => {
- showInputHeightBox.value = false
- })
- .finally(() => {})
-}
-
-// 飞到此处关闭
-function flyToHereClose() {
- showInputHeightBox.value = false
-}
-
-// 视频单机
-function videoClick(e) {
- e.preventDefault()
- e.stopPropagation()
- emit('videoClick')
-}
-
-// 双击画面到双击点
-function moveToPoint(e) {
- if (!hasPayloadControl?.value) return
- if ([9, 10, 11, 0, 1, 2].includes(modeCode.value)) {
- return
- }
- postPayloadAIM({
- sn: dockSn.value,
- x: e.offsetX / e.target.offsetWidth,
- y: e.offsetY / e.target.offsetHeight,
- camera_type: camera_type?.value,
- })
-}
-
-// 右键菜单
-function rightClick(e) {
- console.log('负载控制' + hasPayloadControl?.value)
- curElement = e
- visible.value = true
- position.value = { x: e.clientX, y: e.clientY }
-}
-
-// 绘制框选变焦
-function drawBox() {
- const cav = myCanvas.value
- const ctx = cav.getContext('2d') //返回一个对象,该对象提供了用于在画布上绘图的方法和属性
- let sX = 0 // 起点X坐标
- let sY = 0 // 起点Y坐标
- let eX = 0 // 终点X坐标
- let eY = 0 // 终点Y坐标
- cav.onmousedown = function (e) {
- if (!hasFrameZoom.value || !openBoxSelection.value) {
- closeDrawBox()
- return ElMessage.warning('当前状态无法操作')
- }
- sX = e.offsetX
- sY = e.offsetY
- cav.onmousemove = function (e) {
- ctx.clearRect(0, 0, cav.width, cav.height)
- ctx.fillStyle = 'rgba(81,168,255,0.2)' // 填充颜色,透明度为0.2
- ctx.strokeStyle = 'rgba(81,168,255,1)' // 边框颜色,不透明
- ctx.beginPath() // 新的绘制路径
- ctx.fillRect(sX, sY, e.offsetX - sX, e.offsetY - sY) // 填充矩形
- ctx.strokeRect(sX, sY, e.offsetX - sX, e.offsetY - sY) // 绘制边框
- }
- cav.onmouseup = function (e) {
- cav.onmousemove = null
- cav.onmouseup = null
- eX = e.offsetX // 终点X坐标
- eY = e.offsetY // 终点Y坐标
- ctx.clearRect(0, 0, cav.width, cav.height)
- if (!hasFrameZoom.value || !openBoxSelection.value) {
- closeDrawBox()
- return ElMessage.warning('当前状态无法操作')
- }
- let refuse = Math.abs(eX - sX) < 8 && Math.abs(eY - sY) < 8 //绘制路径小于8不做任何动作
- if (refuse) return
- frameSelectionZoomApi({
- x: Math.min(sX, eX) / canvasWidth.value,
- y: Math.min(sY, eY) / canvasHeight.value,
- sn: dockSn.value,
- camera_type: camera_type?.value,
- width: Math.abs(sX - eX) / canvasWidth.value,
- height: Math.abs(sY - eY) / canvasHeight.value,
- })
- }
- }
-}
-
-// 关闭绘制
-function closeDrawBox() {
- const cav = myCanvas.value
- openBoxSelection.value = false
- cav.onmousedown = null
- cav.onmousemove = null
- cav.onmouseup = null
-}
-
-// 点击其他地方关闭菜单
-function closeMenu() {
- visible.value = false
-}
-
-// 监听卡顿
-function monitorLag() {
- if (stallTimer) clearInterval(stallTimer)
- stallTimer = setInterval(() => {
- const video = liveVideoRef.value
- if (!video) return
- // currentTime 长时间不变,说明画面卡住了
- if (video.currentTime === lastTime) {
- console.log('检测到视频卡顿尝试刷新')
- playVideo()
- }
- lastTime = video.currentTime
- }, 5000)
-}
-
-// 移除监听卡顿
-function stopMonitorLog() {
- if (stallTimer) clearInterval(stallTimer)
-}
-
-// webrtc播放
-const playVideo = () => {
- loading.value = true
- pause()
- // https://gitee.com/xiongguangjie/zlmrtcclient.js/blob/dev/demo/index.html
-
- const RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
- if (!RTCPeerConnection) {
- alert('您的浏览器不支持WebRTC,请使用Chrome/Firefox/Edge等现代浏览器')
- }
-
- webrtcPlayer = new window.ZLMRTCClient.Endpoint({
- element: liveVideoRef.value, // video 标签
- debug: true, // 是否打印日志
- zlmsdpUrl: props.videoUrl, //流地址
- simulecast: false,
- useCamera: false,
- audioEnable: true,
- videoEnable: true,
- recvOnly: true,
- usedatachannel: false,
- })
- webrtcPlayer.on(window.ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS, e => {
- liveVideoRef.value.onplaying = () => {
- getVideoSize()
- loading.value = false
- monitorLag()
- }
- })
- webrtcPlayer.on(window.ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, e => {
- console.error('offer anwser 交换失败', e)
- if (e.code === -400) {
- console.log('流不存在,即将重试')
- tryTimer = setTimeout(() => {
- playVideo()
- }, 100)
- }
- })
- webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,event => {
- // ICE 协商出错
- console.log('ICE 协商出错');
- });
- webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_MSG,event => {
- console.log('rtc datachannel 消息 :',event.data);
- });
- webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_ERR,event => {
- console.log('rtc datachannel 错误 :',event);
- });
-}
-
-
-const handleMetadata = () => {
- const video = document.querySelector('video')
- console.log(`原始视频分辨率: ${video.videoWidth}x${video.videoHeight}`)
- store.commit('setLiveResolution', {width: video.videoWidth, height: video.videoHeight})
- if (props.liveFullScreen){
- canvasWidth.value = liveVideoRef.value.offsetWidth
- canvasHeight.value = (canvasWidth.value / video.videoWidth) * video.videoHeight
- }else{
- canvasHeight.value = liveVideoRef.value.offsetHeight
- canvasWidth.value = (canvasHeight.value / video.videoHeight) * video.videoWidth
- }
-}
-
-
-
-// 获取视频分辨率
-function getVideoSize() {
- const video = document.querySelector('video')
- video.removeEventListener('resize', handleMetadata)
- video.addEventListener('resize', handleMetadata)
- // 初始调用一次(如果视频元数据已加载)
- if (video.readyState >= HTMLMediaElement.HAVE_METADATA) {
- handleMetadata()
- }
-}
-
-// 销毁webrtc
-const pause = () => {
- if (webrtcPlayer) {
- webrtcPlayer.close()
- webrtcPlayer = null
- }
-}
-
-// 监听画面变化重置cavas画布
-let resizeObserver = new ResizeObserver(getVideoSize)
-
-watch(()=> props.liveFullScreen,getVideoSize)
-
-watch(
- () => props.videoUrl,
- newValue => {
- if (!newValue) return
- nextTick(() => {
- playVideo()
- })
- },
- {
- immediate: true,
- }
-)
-
-onMounted(() => {
- document.addEventListener('click', closeMenu)
- resizeObserver.observe(liveVideoRef.value)
-})
-
-onBeforeUnmount(() => {
- pause()
- stopMonitorLog()
- clearTimeout(tryTimer)
- document.removeEventListener('click', closeMenu)
- resizeObserver.unobserve(liveVideoRef.value) // 停止监听某个元素
- resizeObserver = null
-})
-</script>
-
-<style lang="scss" scoped>
-.live-video {
- position: relative;
- width: 100%;
- height: 100%;
- color: #fff;
- background: rgba(0, 0, 0, 0.5);
- z-index: 1;
-
- .video-player {
- width: 100%;
- height: 100%;
-
- &.is-border-radius {
- // 保持16:9比例
- aspect-ratio: 16/9;
- object-fit: contain;
- margin: auto;
- display: block;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
- }
-
- .draw-canvas {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
-
- &.crosshair {
- cursor: crosshair;
- }
- }
-
- :deep() {
- .el-loading-mask {
- .el-loading-spinner {
- transform: translateY(-50%);
- }
- }
- }
-}
-
-.rightMenu {
- z-index: 9999;
- position: fixed;
- width: 94px;
- background: rgba(0, 0, 0, 0.4);
- border-radius: 8px;
- cursor: pointer;
- font-weight: 500;
- font-size: 14px;
- font-family: Source Han Sans CN, Source Han Sans CN, serif;
- backdrop-filter: blur(5px);
-
- > div {
- height: 32px;
- color: #ffffff;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 8px;
-
- &:hover {
- background: rgba(255, 255, 255, 0.78) !important;
- color: #3d3b3b;
- border: 1px solid rgba(255, 255, 255, 0.99);
- }
- }
-}
-
-.flyToHere {
- position: fixed;
- z-index: 5;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 164px;
- background: rgba(29, 29, 29, 0.25);
- border-radius: 8px 8px 8px 8px;
- backdrop-filter: blur(5px);
- padding: 16px;
- color: #ffffff;
- display: flex;
- flex-direction: column;
- gap: 8px;
-
- .heightInputBox {
- display: flex;
- align-items: center;
- gap: 6px;
-
- .el-input-number {
- height: 25px;
- border-radius: 4px 4px 4px 4px;
-
- :deep() {
- .el-input__inner {
- color: #ffffff;
- }
-
- .el-input__wrapper {
- --el-input-focus-border-color: #ffffff;
- background: rgba(36, 36, 36, 0.54) !important;
- }
- }
- }
- }
-
- .btnList {
- display: flex;
- align-items: center;
- gap: 0 6px;
- font-size: 13px;
-
- .btnItem {
- height: 32px;
- line-height: 32px;
- padding: 0 9px;
- background: rgba(58, 58, 58, 0.75);
- box-shadow: 0px 4px 72px 0px rgba(0, 0, 0, 0.25);
- border-radius: 8px 8px 8px 8px;
- border: 1px solid transparent;
- cursor: pointer;
-
- &:hover {
- background: #3a3a3a;
- box-shadow: 0px 4px 72px 0px rgba(0, 0, 0, 0.25);
- border-radius: 8px 8px 8px 8px;
- border: 1px solid rgba(255, 255, 255, 0.99);
- }
- }
- }
-}
-</style>
diff --git a/applications/mobile-web-view/src/main.js b/applications/mobile-web-view/src/main.js
index 9d143bd..fd7dc3b 100644
--- a/applications/mobile-web-view/src/main.js
+++ b/applications/mobile-web-view/src/main.js
@@ -39,9 +39,9 @@
// 系统组件
import debug from './debug'
import VueClipboard from 'vue3-clipboard'
-import SvgIcon from './components/SvgIcon.vue'
+import SvgIcon from './appComponents/SvgIcon.vue'
// 全局组件
-import globalComponents from '@/components'
+import globalComponents from '@/appComponents'
import globalDirections from '@/directive'
import { onResize, pxToRem } from '@/utils/rem'
diff --git a/applications/mobile-web-view/src/router/page/index.js b/applications/mobile-web-view/src/router/page/index.js
index b1390b8..6a27fcb 100644
--- a/applications/mobile-web-view/src/router/page/index.js
+++ b/applications/mobile-web-view/src/router/page/index.js
@@ -20,18 +20,6 @@
children: [
{
- path: 'DroneConsole',
- name: 'DroneConsole',
- component: () => import('@/appPages/inspectionTask/DroneConsole/DroneConsole.vue'),
- meta: { title: '任务详情'},
- },
- {
- path: 'TaskInProgress',
- name: 'TaskInProgress',
- component: () => import('@/appPages/inspectionTask/TaskInProgress/TaskInProgress.vue'),
- meta: { title: '任务详情'},
- },
- {
path: 'defaultMap',
name: 'app地图',
component: () => import('@/appPages/Map/index.vue'),
@@ -73,25 +61,6 @@
meta: { title: '地图'},
},
-
- {
- path: 'inspectionTask',
- name: '巡检列表',
- component: () => import('@/appPages/inspectionTask/index.vue'),
- meta: { title: '任务详情'},
- },
- {
- path: 'addTask',
- name: '新建任务',
- component: () => import('@/appPages/inspectionTask/addTask/index.vue'),
- meta: { title: '新建任务'},
- },
- {
- path: 'execution',
- name: '任务详情',
- component: () => import('@/appPages/inspectionTask/execution/index.vue'),
- meta: { title: '任务详情'},
- },
{
path: 'voiceCallDetail',
name: '语音通话',
@@ -128,7 +97,7 @@
},
{
path: '/404',
- component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/404.vue'),
+ component: () => import(/* webpackChunkName: "page" */ '@/appComponents/error-page/404.vue'),
name: '404',
meta: {
keepAlive: true,
@@ -138,7 +107,7 @@
},
{
path: '/403',
- component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/403.vue'),
+ component: () => import(/* webpackChunkName: "page" */ '@/appComponents/error-page/403.vue'),
name: '403',
meta: {
keepAlive: true,
@@ -148,7 +117,7 @@
},
{
path: '/500',
- component: () => import(/* webpackChunkName: "page" */ '@/components/error-page/500.vue'),
+ component: () => import(/* webpackChunkName: "page" */ '@/appComponents/error-page/500.vue'),
name: '500',
meta: {
keepAlive: true,
diff --git a/applications/mobile-web-view/src/router/views/index.js b/applications/mobile-web-view/src/router/views/index.js
new file mode 100644
index 0000000..dca28a3
--- /dev/null
+++ b/applications/mobile-web-view/src/router/views/index.js
@@ -0,0 +1,3 @@
+
+export default [
+]
--
Gitblit v1.9.3