无人机管理后台前端(已迁走)
张含笑
2025-09-26 8625fe88fc9928083fc492a417f26f4abf6d7d35
Merge remote-tracking branch 'origin/feature/v6.0/6.0.3' into feature/v6.0/6.0.3
7 files modified
1 files renamed
1 files added
172 ■■■■■ changed files
src/App.vue 2 ●●●●● patch | view | raw | blame | history
src/page/index/GlobalWS.vue 11 ●●●●● patch | view | raw | blame | history
src/page/index/index.vue 4 ●●●● patch | view | raw | blame | history
src/page/index/useGlobalWS.js 45 ●●●● patch | view | raw | blame | history
src/store/modules/common.js 10 ●●●●● patch | view | raw | blame | history
src/views/dataCenter/components/searchData.vue 14 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskIntermediateContent/TaskIntermediateContent.vue 18 ●●●● patch | view | raw | blame | history
src/views/tickets/orderLog.vue 41 ●●●●● patch | view | raw | blame | history
src/views/tickets/ticket.vue 27 ●●●●● patch | view | raw | blame | history
src/App.vue
@@ -4,8 +4,6 @@
<script setup>
import { useDownloadWs } from '@/page/index/useDownloadWs';
useDownloadWs()
</script>
<style>
src/page/index/GlobalWS.vue
New file
@@ -0,0 +1,11 @@
<template>
</template>
<script setup>
import { useGlobalWS } from '@/page/index/useGlobalWS';
useGlobalWS()
</script>
<style scoped lang="scss">
</style>
src/page/index/index.vue
@@ -24,6 +24,8 @@
        </div>
      </div>
    </div>
    <GlobalWS/>
    <!-- <wechat></wechat> -->
  </div>
</template>
@@ -37,10 +39,12 @@
import logo from './logo.vue'
import top from './top/index.vue'
import sidebar from './sidebar/index.vue'
import GlobalWS from '@/page/index/GlobalWS.vue';
export default {
  mixins: [index],
  components: {
    GlobalWS,
    top,
    logo,
    tags,
src/page/index/useGlobalWS.js
File was renamed from src/page/index/useDownloadWs.js
@@ -1,20 +1,21 @@
import { computed, onBeforeUnmount, onMounted } from 'vue';
import { getWebsocketUrl } from '@/utils/websocket/config'
import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'
import { useStore } from 'vuex'
import dayjs from 'dayjs'
import { aLinkDownloadUtil } from '@/utils/util'
import EventBus from '@/utils/eventBus'
import { computed, onBeforeUnmount, onMounted } from 'vue';
import { setStore,getStore } from '@/utils/store';
import { getDownloadStatusApi } from '@/api/dataCenter/dataCenter';
import { getStore, setStore } from '@/utils/store'
export const useDownloadWs = () => {
export const useGlobalWS = () => {
    const store = useStore()
    const loginUserInfo = computed(() => store.state.user.userInfo)
    const downloadProgress = computed(() => store.state.common.downloadProgress)
    let currentWebSocket = null
    function messageHandler(payload) {
        const {type,status,progress,download_url} = payload
    // 下载进度处理
    function downloadProcessing(payload) {
        const {type,status,progress,download_url} = payload?.data || {}
        let setProgress = 0
        if (status === 'PENDING'){
            setProgress = 1
@@ -29,7 +30,7 @@
            ...downloadProgress.value,
            [type]: setProgress,
        })
        if (status === 'COMPLETED' && ['htsjzx','htlsrwxq'].includes(type)) {
        if (status === 'COMPLETED' && ['dpsjzx','dplsrwxq'].includes(type)) {
            const name = `数据中心-${dayjs().format('YYYYMMDDHHmmss')}.zip`
            const currentUrl = getStore({name: 'downloadUrl'})
            if (currentUrl === download_url && download_url!== undefined) return
@@ -38,18 +39,42 @@
        }
    }
    const logOut = () => {
        store.commit('SET_THEME_NAME', '')
        store.dispatch('LogOut').then(() => {
            router.push({ path: '/login' })
            setTimeout(() => location.reload())
        })
    }
    function messageHandler(payload) {
        switch (payload.biz_code) {
            case 'JOB_ISREFRESH':
                store.commit('jobUpdateKeyAdd')
                break
            case 'DEVICE_ISREFRESH':
                store.commit('deviceUpdateKeyAdd')
                break
            case 'DOWNLOAD_PROGRESS':
                downloadProcessing(payload)
                break
            case 'LOGOUT_USER':
                logOut()
                break
        }
    }
    onMounted(() => {
        let webSocketUrl = getWebsocketUrl() + `&model_type=3&workspace-id=${loginUserInfo.value.user_id}`
        currentWebSocket = useConnectWebSocket((result)=>{
            const payload = JSON.parse(result)
            messageHandler(payload.data)
            messageHandler(payload)
        }, webSocketUrl)
        EventBus.on('useDownloadWs-messageHandler',messageHandler)
        EventBus.on('useGlobalWS-messageHandler',messageHandler)
    })
    onBeforeUnmount(() => {
        currentWebSocket?.close()
        EventBus.off('useDownloadWs-messageHandler',messageHandler)
        EventBus.off('useGlobalWS-messageHandler',messageHandler)
    })
    return {}
}
src/store/modules/common.js
@@ -18,9 +18,17 @@
    downloadProgress:{
      htsjzx: 100, //数据中心
      htlsrwxq: 100, //历史任务详情
    }
    },
    deviceUpdateKey: 0, //设备刷新key
    jobUpdateKey: 0, //任务刷新key
  },
  mutations: {
    deviceUpdateKeyAdd(state, data) {
      state.deviceUpdateKey = state.deviceUpdateKey + 1
    },
    jobUpdateKeyAdd(state, data) {
      state.jobUpdateKey = state.jobUpdateKey + 1
    },
    setDownloadProgress(state, data) {
      state.downloadProgress = data
    },
src/views/dataCenter/components/searchData.vue
@@ -3,7 +3,7 @@
    <el-form :model="searchForm" inline>
      <div class="search-first">
        <el-form-item label="行政区划:" >
          <el-tree-select
          <el-tree-select
          :disabled="viewDetailsDisabled"
            popper-class="custom-tree-select"
            v-model="searchForm.areaCode"
@@ -80,7 +80,7 @@
        </el-form-item>
        <el-form-item label="文件类别:">
          <el-select
            :disabled="disabled || foldersDisabled || viewDetailsDisabled"
            :teleported="false"
            v-model="searchForm.photoType"
@@ -283,7 +283,7 @@
  machineData.value = '';
  const droneList = await getDeviceRegion({ areaCode: data.id });
  machineData.value = droneList?.data?.data;
  // 默认选中值
  if (signDevice_sn.value) {
    searchForm.deviceSn = signDevice_sn.value;
@@ -292,7 +292,7 @@
  deptData.value = [];
  getDeptsByAreaCode();
  handleSearch();
};
// 所属部门信息
const getDeptsByAreaCode = () => {
@@ -351,17 +351,17 @@
}
// 切换文件夹
const handleswitchFolders =()=>{
  emit('handleswitchFolders');
  emit('handleswitchFolders');
}
// 返回按钮
const handleBack = ()=>{
  emit('handleBack');
  emit('handleBack');
}
onMounted(() => {
  requestDockInfo();
  getDownloadStatusApi({type: 'htsjzx'}).then(res =>{
    if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){
      EventBus.emit('useDownloadWs-messageHandler',res.data.data)
      EventBus.emit('useGlobalWS-messageHandler',res.data.data)
    }
  })
});
src/views/job/components/TaskIntermediateContent/TaskIntermediateContent.vue
@@ -119,7 +119,7 @@
import CancelTaskDialog from '../CancelTaskDialog.vue'
import { useStore } from 'vuex'
import { cloneDeep } from 'lodash'
import { inject, onBeforeUnmount } from 'vue';
import { inject, onBeforeUnmount, watch } from 'vue';
import ElTooltipCopy from '@/components/ElTooltipCopy.vue';
const store = useStore()
const singleUavHome = computed(() => store.state.home.singleUavHome)
@@ -264,14 +264,14 @@
const changeKey = inject('changeKey')
// 轮询查询是否刷新
const polling = setInterval(async () => {
  const res = await statusChangedApi()
  if (res.data.data.DEVICE_REFRESH || res.data.data.JOB_REFRESH) {
    getJobList()
    changeKey.value++
  }
}, 4000)
const jobUpdateKey = computed(() => store.state.common.jobUpdateKey)
const deviceUpdateKey = computed(() => store.state.common.deviceUpdateKey)
watch([jobUpdateKey,deviceUpdateKey],()=>{
  getJobList()
  changeKey.value++
})
onBeforeUnmount(() => {
  clearInterval(polling)
src/views/tickets/orderLog.vue
@@ -281,7 +281,7 @@
              ></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="7">
          <el-col :span="12">
            <el-form-item label="关联航线" prop="file_id">
              <el-select
                v-model="form.file_id"
@@ -298,15 +298,15 @@
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="5">
            <el-form-item label="安全返航真高" prop="rth_altitude">
              <el-input-number
                v-model="form.rth_altitude"
                :min="30"
                :max="300"
              ></el-input-number>
            </el-form-item>
          </el-col>
<!--          <el-col :span="6">-->
<!--            <el-form-item label="安全返航真高" prop="rth_altitude">-->
<!--              <el-input-number-->
<!--                v-model="form.rth_altitude"-->
<!--                :min="30"-->
<!--                :max="300"-->
<!--              ></el-input-number>-->
<!--            </el-form-item>-->
<!--          </el-col>-->
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
@@ -404,9 +404,9 @@
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="danger" @click="submitForm(1)">发起</el-button>
          <el-button type="primary" @click="submitForm(0)">存草稿</el-button>
          <el-button @click="dialogVisible = false" :icon="CircleClose">取消</el-button>
          <el-button type="danger" @click="submitForm(1)" icon="el-icon-position">发起</el-button>
          <el-button type="primary" @click="submitForm(0)" icon="el-icon-document-add">存草稿</el-button>
          <el-button @click="dialogVisible = false" icon="el-icon-circle-close">取消</el-button>
        </div>
      </template>
    </el-dialog>
@@ -598,12 +598,14 @@
            type="danger"
            v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)"
            @click="submitForm(1)"
            icon="el-icon-position"
          >发布</el-button
          >
          <el-button
            type="primary"
            v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)"
            @click="submitForm(0)"
            icon="el-icon-plus"
          >保存</el-button
          >
          <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user"
@@ -803,6 +805,7 @@
          type="danger"
          v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)"
          @click="submitForm(1)"
          icon="el-icon-position"
        >发布</el-button
        >
        <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user"
@@ -812,15 +815,17 @@
          type="primary"
          v-if="form.status == 1 && hasPaddingBtnPermission()"
          @click="orderLogPass(form.id)"
          icon="el-icon-check"
        >通过</el-button
        >
        <el-button
          type="danger"
          v-if="form.status == 1 && hasRejectionBtnPermission()"
          @click="orderLogReject(form.id)"
          icon="el-icon-close"
        >驳回</el-button
        >
        <el-button @click="detailVisibleCopy = false">取消</el-button>
        <el-button @click="detailVisibleCopy = false" icon="el-icon-circle-close">取消</el-button>
      </div>
        </template>
    </el-dialog>
@@ -855,7 +860,7 @@
import 'dayjs/locale/zh-cn'; // 导入中文语言包
import weekday from 'dayjs/plugin/weekday';
import elTooltipCopy from '@/components/ElTooltipCopy.vue';
import { CircleClose } from '@element-plus/icons-vue';
import { CircleClose, Promotion, Select } from '@element-plus/icons-vue';
dayjs.extend(weekday);
dayjs.locale('zh-cn');
@@ -1678,6 +1683,12 @@
</script>
<style lang="scss" scoped>
:deep(.el-input-number) {
  width: 200px;
}
:deep(.el-form-item__label) {
  width: 100px !important;
}
::v-deep(.el-tabs) {
  height: 100%;
  display: flex;
src/views/tickets/ticket.vue
@@ -415,12 +415,12 @@
      </el-form>
      <template #footer>
        <div class="dialog-footer-new">
          <el-button type="danger" :loading="submitLoading" @click="submitForm">发布</el-button>
          <el-button type="infoprimary" plain :loading="draftLoading" @click="saveDraft"
          <el-button type="danger" :loading="submitLoading" @click="submitForm" icon="el-icon-position">发布</el-button>
          <el-button type="infoprimary" plain :loading="draftLoading" @click="saveDraft"  icon="el-icon-document-add"
            >存草稿</el-button
          >
          <el-button @click="handleCancel" :icon="CircleClose">取 消</el-button>
          <el-button @click="handleCancel" icon="el-icon-circle-close">取 消</el-button>
        </div>
      </template>
    </el-dialog>
@@ -736,6 +736,7 @@
                type="primary"
                :loading="approveLoading"
                @click="approveTicket"
                icon="el-icon-check"
                >通过</el-button
              >
              <el-button
@@ -743,9 +744,10 @@
                type="danger"
                :loading="rejectLoading"
                @click="rejectTicket"
                icon="el-icon-close"
                >不通过</el-button
              >
              <el-button @click="detailVisible = false":icon="CircleClose">取消</el-button>
              <el-button @click="detailVisible = false" icon="el-icon-circle-close">取消</el-button>
            </template>
            <template v-else-if="currentDetail.status === 0">
              <el-button
@@ -753,6 +755,7 @@
                type="primary"
                :loading="dispatchLoading"
                @click="approveAndDispatch"
                icon="el-icon-check"
                >受理</el-button
              >
              <el-button
@@ -760,9 +763,10 @@
                type="danger"
                :loading="rejectLoading"
                @click="rejectTicket"
                icon="el-icon-close"
                >不受理</el-button
              >
              <el-button @click="detailVisible = false">取消</el-button>
              <el-button @click="detailVisible = false" icon="el-icon-circle-close">取消</el-button>
            </template>
            <template v-if="currentDetail.status === 3">
              <!-- 处理中 -->
@@ -771,15 +775,16 @@
                type="primary"
                :loading="completeLoading"
                @click="completeTicket"
                icon="el-icon-circle-check"
                >完成工单</el-button
              >
              <el-button @click="detailVisible = false">取消</el-button>
              <el-button @click="detailVisible = false" icon="el-icon-circle-close">取消</el-button>
            </template>
            <template v-else-if="currentDetail.status === 4">
              <!-- 已完成 -->
              <!-- <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" :loading="finalizeLoading"
              @click="finalizeTicket">完结工单</el-button> -->
              <el-button @click="detailVisible = false">取消</el-button>
              <el-button @click="detailVisible = false" icon="el-icon-circle-close">取消</el-button>
            </template>
          </div>
          <div
@@ -832,7 +837,7 @@
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dispatchDialogVisible = false">取消</el-button>
        <el-button @click="dispatchDialogVisible = false" icon="el-icon-circle-close">取消</el-button>
        <el-button type="primary" :loading="dispatchLoading" @click="submitDispatch"
          >确认派发</el-button
        >
@@ -909,9 +914,9 @@
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleBatchApprove">通过</el-button>
          <el-button type="danger" @click="handleBatchReject">不通过</el-button>
          <el-button @click="cancleBatchReject">取消</el-button>
          <el-button type="primary" @click="handleBatchApprove" icon="el-icon-check">通过</el-button>
          <el-button type="danger" @click="handleBatchReject" icon="el-icon-close">不通过</el-button>
          <el-button @click="cancleBatchReject" icon="el-icon-circle-close">取消</el-button>
        </div>
      </template>
    </el-dialog>