无人机管理后台前端(已迁走)
罗广辉
2025-11-27 39a43e1d810bac6f1aab2b3f9b8d93397dd2a06a
Merge branch 'feature/v8.0/8.0.2' into feature/v8.0/8.0.3

# Conflicts:
# src/views/job/components/DeviceJobDetails.vue
# src/views/layerManagement/index.vue
# src/views/tickets/orderLog.vue
# src/views/tickets/ticket.vue
4 files modified
164 ■■■■ changed files
src/page/index/useGlobalWS.js 2 ●●● patch | view | raw | blame | history
src/views/job/components/DeviceJobDetails.vue 40 ●●●● patch | view | raw | blame | history
src/views/layerManagement/index.vue 58 ●●●● patch | view | raw | blame | history
src/views/tickets/ticket.vue 64 ●●●● patch | view | raw | blame | history
src/page/index/useGlobalWS.js
@@ -30,7 +30,7 @@
            ...downloadProgress.value,
            [type]: setProgress,
        })
        if (status === 'COMPLETED' && ['dpsjzx','dplsrwxq'].includes(type)) {
        if (status === 'COMPLETED' && ['htsjzx','htlsrwxq'].includes(type)) {
            const name = `数据中心-${dayjs().format('YYYYMMDDHHmmss')}.zip`
            const currentUrl = getStore({name: 'downloadUrl'})
            if (currentUrl === download_url && download_url!== undefined) return
src/views/job/components/DeviceJobDetails.vue
@@ -155,7 +155,7 @@
<script setup>
import PanoramaPopup from '@/components/PanoramaPopup/PanoramaPopup.vue';
import { getShowImg, getSmallImg, getzsSmallImg,getzsShowImg } from '@/utils/util';
import { getShowImg, getSmallImg, getzsSmallImg, getzsShowImg, aLinkDownloadUtil } from '@/utils/util';
import { getaiImagesPageAPI,cancelDownloadApi,getDownloadStatusApi,attachDownload,aiImagesPage} from '@/api/dataCenter/dataCenter';
import { pxToRem } from '@/utils/rem'
import JobRelatedEvents from './JobRelatedEvents.vue'
@@ -332,25 +332,25 @@
}
// 下载
const downloadFun = async () => {
  const list = achievementList.value.filter(i => i.checked)
  console.log('list',list);
  if (!list?.length) return ElMessage.warning('请选择文件')
  if (list.length === 1) {
    list.forEach((item, index) => {
      const suffix = item.url.split('.').pop()
      aLinkDownloadUtil(item.url, item.nickName + '.' + suffix)
    })
  } else {
    loadingData = ElLoading.service({ background: 'rgba(0, 0, 0, 0.5)', text: '打包中,请稍等...' })
    const fileIds = list.map(i => i.id)
    const res = await getDownloadStatusApi({type: 'htlsrwxq'})
    if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){
      return ElMessage.warning('还有正在处理的')
    }
    attachDownload({ attachIds: fileIds,type:'htlsrwxq' }).finally(()=>{
      loadingData.close()
    })
  }
    const list = achievementList.value.filter(i => i.checked)
    console.log('list',list);
    if (!list?.length) return ElMessage.warning('请选择文件')
    if (list.length === 1) {
        list.forEach((item, index) => {
            const suffix = item.link.split('.').pop()
            aLinkDownloadUtil(item.link, item.nickName + '.' + suffix)
        })
    } else {
        loadingData = ElLoading.service({ background: 'rgba(0, 0, 0, 0.5)', text: '打包中,请稍等...' })
        const fileIds = list.map(i => i.id)
        const res = await getDownloadStatusApi({type: 'htlsrwxq'})
        if (!['CANCELLED','COMPLETED'].includes(res.data.data?.status || 'COMPLETED')){
            return ElMessage.warning('还有正在处理的')
        }
        attachDownload({ attachIds: fileIds,type:'htlsrwxq' }).finally(()=>{
            loadingData.close()
        })
    }
}
// 全景预览
const panoramaParamsShow = ref(false)
src/views/layerManagement/index.vue
@@ -33,7 +33,7 @@
          @update:editFolder="handleFolder"
          :activeName="activeName"
          @newFencesMethods="newFencesMethods"
          :reset-check="resetCheck"
          :reset-check="resetCheck"
        ></leftList>
        <rightEdit
          v-if="layerParams.addNest || layerParams.editNest"
@@ -64,7 +64,7 @@
import * as Cesium from 'cesium';
import { PublicCesium } from '@/utils/cesium/publicCesium';
import _, { cloneDeep, throttle } from 'lodash';
const isProd = import.meta.env.VITE_APP_ENV === 'production'
import { provide } from 'vue';
import { useStore } from 'vuex';
const isProd = import.meta.env.VITE_APP_ENV === 'production'
@@ -137,7 +137,7 @@
     layerParams.value.addFolder = false
    layerParams.value.editFolder = false
    resetCheck.value = !resetCheck.value;
};
const refreshMethod = () => {
  getdataFolderApi();
@@ -166,7 +166,7 @@
  viewer.entities.removeAll();
  layerParams.value.editDetailData = val;
  drawPolygonExample.editThePatch(true);
  drawPolygonExample.drawTheArea(true);
  drawPolygonExample.drawTheArea(true);
  let geoDataArr = JSON.parse(val.geo_data);
  if (geoDataArr.length > 0) {
    geoDataArr.pop();
@@ -221,7 +221,7 @@
      console.warn(`数据 ${item.name} 坐标点不足,无法绘制`);
      return;
    }
    tbJwdList.push(...positions);
    let degreesArray = [];
    positions.forEach(pos => {
@@ -236,20 +236,20 @@
    border2: Cesium.Color.fromCssColorString('#ff0000'),
    border3: Cesium.Color.fromCssColorString('#00ffea'),
  };
   const fillColor = item.category_id === 1
      ? colorMap[1]
      : item.category_id === 2
        ? colorMap[2]
        : item.category_id === 3
          ? colorMap[3]
   const fillColor = item.category_id === 1
      ? colorMap[1]
      : item.category_id === 2
        ? colorMap[2]
        : item.category_id === 3
          ? colorMap[3]
          : Cesium.Color.YELLOW.withAlpha(0.5);
    const borderColor = item.category_id === 1
      ? colorMap.border1
      : item.category_id === 2
        ? colorMap.border2
        : item.category_id === 3
          ? colorMap.border3
    const borderColor = item.category_id === 1
      ? colorMap.border1
      : item.category_id === 2
        ? colorMap.border2
        : item.category_id === 3
          ? colorMap.border3
          : Cesium.Color.YELLOW;
      viewer.entities.add({
      id: `polygon_${item.id}`,
@@ -272,17 +272,17 @@
        material:borderColor,
        clampToGround: true,
      },
      zIndex: 99,
      zIndex: 99,
    });
  });
  });
 if (!layerParams.value.isSingleLocating) {
    focusOnAllFeatures();
    focusOnAllFeatures();
  }
  viewInstance.value?.addLeftClickEvent(null, handleFenceClick);
};
const focusOnAllFeatures = () => {
  if (tbJwdList.length === 0 || !viewer) return;
  // 判断是否有指定定位的文件夹
  if (layerParams.value.currentLocationFolderId) {
    // 筛选当前文件夹下的所有子节点坐标
@@ -292,7 +292,7 @@
        const positions = parseGeoDataToPositions(item.geo_data, item.altitude);
        return positions.length >= 3 ? positions : [];
      });
    if (targetFolderPositions.length > 0) {
      const positionsData = targetFolderPositions.map(pos => [
        pos.lng,
@@ -326,16 +326,16 @@
const handleFenceClick = movement => {
  if (!viewer) return;
  layerParams.value.editDetailData = null;
if(activeName.value !== '国土空间规划') {
    const pickedObjects = viewer.scene.drillPick(movement.position, 10);
    const pickedObjects = viewer.scene.drillPick(movement.position, 10);
  // 遍历所有被点击的实体,找到围栏类型(customType: 'fence_polygon')
  let selectedEntity = null;
  for (let i = 0; i < pickedObjects.length; i++) {
    const pick = pickedObjects[i];
    if (Cesium.defined(pick.id) && pick.id?.customType === 'fence_polygon') {
      selectedEntity = pick.id;
      break;
      break;
    }
  }
    // viewer.entities.values.forEach(entity => {
@@ -403,7 +403,7 @@
      let cartographic = Cesium.Cartographic.fromCartesian(item);
      let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
      let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
      let height = Cesium.Math.toDegrees(cartographic.height); //高度
      let height = Cesium.Math.toDegrees(cartographic.height); //高度
      return {
        lng: _.round(lng, 6),
        lat: _.round(lat, 6),
@@ -420,7 +420,7 @@
  }else {
    showToolTipText.value = '点击地图生成测绘区域'
  }
 if(polygon.length > 0){
      polygon.push([curPolygonPosition[0]?.lng, curPolygonPosition[0]?.lat])
 }
@@ -476,7 +476,7 @@
// 添加loading
const isPageLoading = ref(false);
const handleLoadingChange = (status) => {
  isPageLoading.value = status;
  isPageLoading.value = status;
};
provide('layerParams', layerParams);
onMounted(() => {
src/views/tickets/ticket.vue
@@ -131,7 +131,7 @@
              >
                批量审核
              </el-button>
              <el-button
                v-if="permissionList.exportBtn"
                type="success"
@@ -149,7 +149,7 @@
           class="ztzf-public-general-el-table custom-header"
          ref="elTable"
          :data="tableData"
          v-loading="loading"
          v-loading="loading"
          @selection-change="handleSelectionChange"
          border
          style="width: 100%"
@@ -171,40 +171,40 @@
              </el-tooltip-copy>
            </template>
          </el-table-column>
          <el-table-column prop="department" label="所属部门" show-overflow-tooltip />
          <el-table-column prop="startTime" label="发起任务时间" width="160" show-overflow-tooltip />
          <el-table-column prop="aiType" label="关联算法" show-overflow-tooltip />
          <el-table-column prop="type" label="工单类型" width="110" show-overflow-tooltip>
            <template #default="{ row }">
              {{ getTypeLabel(row.type) }}
            </template>
          </el-table-column>
          <el-table-column prop="content" label="工单内容" width="132" show-overflow-tooltip>
            <template #default="{ row }">
              {{ row.address || row.content }}
            </template>
          </el-table-column>
          <el-table-column prop="creator" label="创建人" width="120" show-overflow-tooltip />
          <el-table-column prop="handler" label="处理人" width="120" show-overflow-tooltip />
          <el-table-column
            v-if="['all', 'completed', 'myTickets'].includes(activeTab)"
            label="复核状态"
            prop="isReview"
          <el-table-column
            v-if="['all', 'completed', 'myTickets'].includes(activeTab)"
            label="复核状态"
            prop="isReview"
            width="90"
          >
            <template #default="{ row }">
              <span>{{ showIsReviewText(row) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="工单状态" prop="status" width="90">
            <template #default="{ row }">
              <span :style="getStatusTagType(row.status) ? 'color:' + getStatusTagType(row.status) : ''">
@@ -212,7 +212,7 @@
              </span>
            </template>
          </el-table-column>
          <!-- 操作列 -->
          <el-table-column label="操作" width="200" align="center">
            <template #default="{ row }">
@@ -222,15 +222,15 @@
                  删除
                </el-button>
              </template>
              <template v-else>
                <el-button type="text" icon="el-icon-view" @click="handleViewDetail(row)">详情</el-button>
              </template>
              <template v-if="row.status === 4 && !isProd">
                <el-button type="text" icon="el-icon-download" @click="exportTheTick(row)">导出</el-button>
              </template>
              <template v-if="permission.tickets_repeat_review">
                <el-button
                  v-if="row.status === 4 && row.isReview !== 1"
@@ -510,7 +510,7 @@
const checkedKeys = ref([])
const inputMapShowDefaultCenter = ref(null)
const userInfo = computed(() => store.state.user.userInfo)
const permission = computed(() => store.state.user.permission);
const permission = computed(() => store.state.user.permission);
// 计算属性
const firstRowData = computed(() => {
@@ -521,7 +521,7 @@
  const tabPending = permission.value?.tickets_tab_pending === true//待审核
  const tabMyTickets = permission.value?.tickets_tab_mytickets === true  //我的工单
  const tabALL = permission.value?.tickets_allWorkOrders === true //全部工单
  const tabInProgress= permission.value?.tickets_inProgress === true //处理中
  const tabInProgress= permission.value?.tickets_inProgress === true //处理中
  const tabProcessing= permission.value?.tickets_pending === true //待处理
  const tabCompleted= permission.value?.tickets_wasDone === true //已完成
  return tabs.value
@@ -558,7 +558,7 @@
const defaultActiveTab = computed(() => {
  const hasAllTab = filteredTabs.value.some(tab => tab.name === 'all')
  const hasPendingTab = filteredTabs.value.some(tab => tab.name === 'pending')
  // 如果没有全部工单权限,但有待审核权限,则默认显示待审核
  if (!hasAllTab && hasPendingTab) {
    return 'pending'
@@ -710,7 +710,7 @@
        }
      })
      dataList.value = filteredData
    }
  })
}
@@ -825,7 +825,7 @@
    })) || []
    algorithms2.value = _.cloneDeep(algorithms.value)
    userNameToIdMap.value = {}
    dept_data.forEach(dept => {
      (dept.user_data || []).forEach(user => {
@@ -864,7 +864,7 @@
function mapStatus(status) {
  const statusTextMap = {
    2: '待审核',
    0: '待处理',
    3: '处理中',
@@ -890,8 +890,8 @@
  }
  try {
    const response = await getstatusCount(params)
    const statusCount = response.data.data || {}
    const totalCount = Object.values(statusCount).reduce((sum, count) => sum + (count || 0), 0)
    const statusCount = response.data.data || {}
    const totalCount = Object.values(statusCount).reduce((sum, count) => sum + (count || 0), 0)
    tabs.value.forEach(tab => {
      if (tab.name === 'all') {
        tab.count = totalCount
@@ -1000,7 +1000,7 @@
  await getStepInfoData(row.orderNumber)
  currentDetail.value.status = row.status
  currentDetail.value = {
    ...detailData,
    showQR: false,
@@ -1436,7 +1436,7 @@
        }
      })
    }
    if (tab) {
      const isTabValid = filteredTabs.value.some(t => t.name === tab)
      if (isTabValid) {
@@ -1483,7 +1483,7 @@
  right: 0;
  padding: 0 30px;
  z-index: 1000;
  z-index: 1000;
}
:deep(.custom-header th.el-table__cell) {
  color: rgba(0, 0, 0, 0.85);
@@ -1518,13 +1518,13 @@
  :deep(.el-table__header-wrapper) {
    background-color: #f5f7fa;
  }
  :deep(.el-table th) {
    background-color: #f5f7fa;
    color: #606266;
    font-weight: 600;
  }
  :deep(.el-table--border) {
    border: 1px solid #ebeef5;
  }