无人机管理后台前端(已迁走)
罗广辉
2025-09-27 d46953fb97893833d027ee1aabf783d20e3207a1
Merge branch 'feature/v6.0/6.0.3' into prod
21 files modified
1 files renamed
2 files added
1069 ■■■■ changed files
.env.development 1 ●●●● patch | view | raw | blame | history
src/App.vue 2 ●●●●● patch | view | raw | blame | history
src/api/logs.js 52 ●●●●● patch | view | raw | blame | history
src/api/resource/wayline.js 8 ●●●● patch | view | raw | blame | history
src/option/job/jobserver.js 4 ●●● 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/types/device-cmd.js 2 ●●● patch | view | raw | blame | history
src/views/dataCenter/components/searchData.vue 14 ●●●● patch | view | raw | blame | history
src/views/dataCenter/dataCenter.vue 3 ●●●● patch | view | raw | blame | history
src/views/device/addDevice.vue 4 ●●●● patch | view | raw | blame | history
src/views/device/airport.vue 97 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskIntermediateContent/TaskIntermediateContent.vue 18 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskTop/TaskIndustry.vue 8 ●●●● patch | view | raw | blame | history
src/views/monitor/log/flightLog.vue 393 ●●●●● patch | view | raw | blame | history
src/views/resource/components/DrawPolygon.vue 5 ●●●●● patch | view | raw | blame | history
src/views/resource/components/spotDetails.vue 263 ●●●● patch | view | raw | blame | history
src/views/system/dept.vue 27 ●●●●● patch | view | raw | blame | history
src/views/system/userinfo.vue 18 ●●●● patch | view | raw | blame | history
src/views/tickets/orderLog.vue 45 ●●●● patch | view | raw | blame | history
src/views/tickets/ticket.vue 32 ●●●●● patch | view | raw | blame | history
src/views/wel/components/backlog.vue 3 ●●●● patch | view | raw | blame | history
.env.development
@@ -23,6 +23,7 @@
VITE_APP_URL = https://wrj.shuixiongit.com/api
#VITE_APP_URL= http://192.168.1.168
#VITE_APP_URL= http://192.168.1.33
#VITE_APP_URL= http://192.168.1.204
#新大屏地址
VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/'
src/App.vue
@@ -4,8 +4,6 @@
<script setup>
import { useDownloadWs } from '@/page/index/useDownloadWs';
useDownloadWs()
</script>
<style>
src/api/logs.js
@@ -62,3 +62,55 @@
    },
  });
};
// 历史轨迹记录
export const getHistoryTrack = (params) => {
  return request({
    url: '/drone-device-core/log/droneFlightLog/page',
    method: 'get',
    params
  })
}
// 导出飞行日志
export const exportFlyLog = data => {
  return request({
    url: '/drone-device-core/log/droneFlightLogInfo/export',
    method: 'post',
    data
  })
}
// 收藏
export const addStar = data => {
  return request({
    url: '/drone-device-core/log/favorite/add',
    method: 'post',
    data
  })
}
// 收藏列表
export const starPage = (params) => {
  return request({
    url: '/drone-device-core/log/favorite/page',
    method: 'post',
    params
  })
}
export const updateDroneFlight = (data) => {
  return request({
    url: '/drone-device-core/log/droneFlightLog/updateDroneFlight',
    method: 'post',
    data
  })
}
export const cancelStar = data => {
  return request({
    url: '/drone-device-core/log/favorite/cancel/'+data,
    method: 'get',
  })
}
export const droneFlightLogInfoPage = params => {
  return request({
    url: '/drone-device-core/log/droneFlightLogInfo/page',
    method: 'get',
    params
  })
}
src/api/resource/wayline.js
@@ -17,7 +17,13 @@
  });
};
export const newGetWorkspacesPage = params => {
  return request({
    url: `/drone-device-core/wayline/api/v1/wayline-groups/page`,
    method: 'get',
    params,
  })
}
export const getWaylineFileListByArea = (areaCode) => {
  return request({
src/option/job/jobserver.js
@@ -11,7 +11,9 @@
export default {
  tip: false,
  searchShow: true,
  searchMenuSpan: 6,
  // searchGutter: 10,
  searchMenuPosition: 'right',
  searchMenuSpan: 12,
  border: true,
  index: true,
  viewBtn: true,
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/types/device-cmd.js
@@ -146,7 +146,7 @@
    disabled: true,
  },
  {
    label: '4g 增强',
    label: '4G 增强',
    status: '--',
    operateText: '开启',
    cmdKey: DeviceCmd.SdrWorkModeSwitch,
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/dataCenter/dataCenter.vue
@@ -35,7 +35,7 @@
              }}
            </template>
          </el-table-column>
          <el-table-column property="recordName" label="任务名称" show-overflow-tooltip />
          <el-table-column property="name" label="任务名称" show-overflow-tooltip />
           <el-table-column property="regionName" label="所属区域">
             <template #default="scope">
              <span>{{scope.row.city_name ? scope.row.city_name :'--'}},{{scope.row.area_name ? scope.row.area_name :'--'}}</span>
@@ -500,6 +500,7 @@
        .then(res => {
    folderList.value = res.data.data.records.map(i => ({ ...i, checked: false }))
    total.value = res.data.data.total
        })
        .finally(() => {
          loadings.value = false;
src/views/device/addDevice.vue
@@ -74,8 +74,8 @@
                searchGutter: 30,
                tip: false,
                searchShow: true,
                searchMenuSpan: 6,
                searchGutter: 30,
                searchMenuPosition: 'right',
                searchMenuSpan: 10,
                border: true,
                index: true,
                indexLabel: '序号',
src/views/device/airport.vue
@@ -306,7 +306,9 @@
        searchGutter: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        // searchMenuSpan: 16,
        searchMenuPosition: 'right',
        searchMenuSpan: 8,
        border: true,
        index: true,
        indexLabel: '序号',
@@ -363,13 +365,6 @@
            searchSpan: 4,
            labelWidth: 145,
            width: 120,
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入设备型号',
            //     trigger: 'blur',
            //   },
            // ],
          },
          {
            label: '设备SN',
@@ -380,27 +375,8 @@
            searchSpan: 4,
            // editDisabled: true,
            editDisplay: false, //编辑显示
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入设备SN',
            //     trigger: 'blur',
            //   },
            // ],
          },
          // {
          //   label: '机巢编号',
          //   prop: 'machine_nest_sn',
          //   labelWidth: 145,
          //   editDisabled: true,
          //   rules: [
          //     {
          //       required: false,
          //       message: '请输入机巢编号',
          //       trigger: 'blur',
          //     },
          //   ],
          // },
          {
            label: '设备位置',// '行政区划',
            prop: 'area_name',
@@ -490,21 +466,23 @@
              },
            ],
          },
          // {
          //   label: '设备位置',
          //   prop: 'address',
          //   labelWidth: 145,
          //   width: 100,
          //   overHidden: true,
          //   rules: [
          //     {
          //       required: true,
          //       message: '请输入设备位置',
          //       trigger: 'blur',
          //     },
          //   ],
          // },
          {
            label: '4G增强',
            prop: 'link_workmode',
            labelWidth: 145,
            width: 160,
            overHidden: true,
            editDisplay: false, //编辑显示
            viewDisplay: false,
            align: 'center',
            formatter: (row, column, cellValue) => {
              const statusMap = {
                0: '关',
                1: '开',
              };
              return statusMap[cellValue] || '/';
            }
          },
          {
            label: '负载设备',
@@ -513,14 +491,7 @@
            width: 160,
            overHidden: true,
            editDisplay: false, //编辑显示
            // editDisabled: true,
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入负载设备',
            //     trigger: 'blur',
            //   },
            // ],
          },
          {
            // hide: true,
@@ -581,14 +552,6 @@
            type: 'date',
            format: 'YYYY-MM-DD',
            editDisplay: false, //编辑显示
            // editDisabled: true,
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入流量到期时间',
            //     trigger: 'blur',
            //   },
            // ],
          },
          {
            label: '固件版本',
@@ -596,14 +559,6 @@
            labelWidth: 145,
            width: 110,
            editDisplay: false, //编辑显示
            // editDisabled: true,
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入固件版本',
            //     trigger: 'blur',
            //   },
            // ],
          },
          {
            label: '固件升级',
@@ -614,16 +569,8 @@
            viewDisabled: true,
            addDisabled: true,
            editDisplay: false, //编辑显示
            // editDisabled: true,
            addDisplay: false,
            viewDisplay: false,
            // rules: [
            //   {
            //     required: true,
            //     message: '请输入固件升级',
            //     trigger: 'blur',
            //   },
            // ],
          },
          {
            label: '所属单位',
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/job/components/TaskTop/TaskIndustry.vue
@@ -29,8 +29,8 @@
            color: '#363636',
            fontSize: 12,
        },
        itemWidth: 2, // 减小图例标记的宽度
        itemHeight: 6, // 减小图例标记的高度
        itemWidth: 8, // 减小图例标记的宽度
        itemHeight: 8, // 减小图例标记的高度
        itemGap: 8, // 减小图例项之间的间距
        formatter: '{name}', // 简化图例文本
    },
@@ -43,14 +43,14 @@
      center: ['30%', '50%'],
            data: [],
            label: {
                show: true,
                show: false,
                position: 'outside',
                formatter: '{c}',
                fontSize: 12,
                color: '#000',
            },
            labelLine: {
                show: true,
                show: false,
                length: 10,
                length2: 10,
                lineStyle: {
src/views/monitor/log/flightLog.vue
New file
@@ -0,0 +1,393 @@
<!-- 飞行日志 -->
<template>
  <div class="flight">
    <div class="ztzf-search-mange">
      <el-form :model="params" inline>
        <div class="search-contain">
          <div>
            <el-form-item label="任务名称:">
              <el-input v-model="params.jobName" placeholder="请输入任务名称" clearable />
            </el-form-item>
            <el-form-item label="任务编号:">
              <el-input v-model="params.jobInfoNum" placeholder="请输入任务编号" clearable />
            </el-form-item>
            <el-form-item label="日期:">
              <el-date-picker
                v-model="rangTime"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                clearable
                @change="changeselect"
              />
            </el-form-item>
          </div>
          <div class="btns">
            <el-button type="primary" @click="getList" :icon="Search">搜索</el-button>
            <el-button @click="cancelSearch" :icon="Delete">清空</el-button>
          </div>
        </div>
      </el-form>
    </div>
    <div class="mange-table">
<!--      <el-tabs v-model="tabType" class="demo-tabs" @tab-click="handleTabClick">-->
<!--        <el-tab-pane label="全部" name="全部"></el-tab-pane>-->
<!--        <el-tab-pane label="我的收藏" name="收藏"></el-tab-pane>-->
<!--        -->
<!--      </el-tabs>-->
      <el-table border :data="tableList" class="custom-header">
        <el-table-column label="序号" type="index" width="60"></el-table-column>
        <el-table-column prop="job_name" label="任务名称" align="center" show-overflow-tooltip></el-table-column>
        <el-table-column prop="job_info_num" label="任务编号" align="center" show-overflow-tooltip></el-table-column>
        <el-table-column prop="title" label="飞行类型" align="center" show-overflow-tooltip></el-table-column>
        <el-table-column prop="device_name" label="无人机" align="center"></el-table-column>
        <el-table-column prop="start_time" label="开始时间" align="center">
          <template #default="scope">
            {{ timeFormatConvert(scope.row.start_time) }}
          </template>
        </el-table-column>
        <el-table-column prop="end_time" label="结束时间" align="center">
          <template #default="scope">
            {{ timeFormatConvert(scope.row.end_time) }}
          </template>
        </el-table-column>
<!--        <el-table-column prop="end_time" label="标签" align="center">-->
<!--          <template #default="scope">-->
<!--            <el-select v-model="scope.row.label_id" @change="handleUpdateLabel(scope.row)" clearable>-->
<!--              <el-option-->
<!--                v-for="item in tagList"-->
<!--                :key="item.id"-->
<!--                :label="item.label_name"-->
<!--                :value="item.id"-->
<!--              ></el-option>-->
<!--            </el-select>-->
<!--          </template>-->
<!--        </el-table-column>-->
        <el-table-column label="操作" width="300" align="center">
          <template #default="scope">
            <el-button icon="el-icon-view" type="text" @click="handleDetail(scope.row)">查看</el-button>
            <el-button icon="el-icon-delete" type="text" @click="handleDelete(scope.row)">删除</el-button>
<!--            <el-button type="text" @click="handleStar(scope.row)">-->
<!--              <el-icon><Star /></el-icon>-->
<!--              {{ scope.row.is_favorite ? '取消收藏':'收藏' }}</el-button>-->
            <el-button type="text" @click="handleExport(scope.row)"><el-icon><Download /></el-icon>导出</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="pagination">
      <el-pagination class="ztzf-pagination" popper-class="custom-pagination-dropdown" background
                     :page-sizes="[10, 20, 30, 40, 50, 100]" :size="size" v-model:current-page="params.page"
                     v-model:page-size="params.page_size" layout="total, sizes, prev, pager, next, jumper" :total="total"
                     @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </div>
  </div>
  <el-dialog class="ztzf-dialog" append-to-body v-model="isShowView" title="查看"
             :width="pxToRem(1000)" :close-on-click-modal="false" :destroy-on-close="true">
    <!-- <div class="content"> -->
    <el-table border :data="tableDataDetails" height="466">
      <el-table-column label="序号" type="index" width="60"></el-table-column>
      <el-table-column prop="flight_type" label="飞行类型" align="center" show-overflow-tooltip></el-table-column>
      <el-table-column prop="latitude" label="经度" align="center"></el-table-column>
      <el-table-column prop="longitude" label="纬度" align="center"></el-table-column>
      <el-table-column prop="height" label="高度" align="center"></el-table-column>
      <el-table-column prop="elevation" label="海拔高度" align="center"></el-table-column>
    </el-table>
    <div class="pagination" style="display: flex;justify-content: end;margin-top: 10px;">
      <el-pagination class="ztzf-pagination" popper-class="custom-pagination-dropdown" background
                     :page-sizes="[10, 20, 30, 40, 50, 100]" :size="size" v-model:current-page="detailParams.current"
                     v-model:page-size="detailParams.size" layout="total, sizes, prev, pager, next, jumper" :total="detailTotal"
                     @size-change="handleSizeChangeDetails" @current-change="handleCurrentChangeDetails" />
      <!-- </div> -->
    </div>
  </el-dialog>
</template>
<script setup>
import { getHistoryTrack, cancelStar, addStar, updateDroneFlight, droneFlightLogInfoPage } from '@/api/logs';
// import { flightLogPage } from '@/api/airspace/airspace';
import { downloadXls } from '@/utils/util';
import { exportBlob } from '@/api/common'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
import { Delete, Search } from '@element-plus/icons-vue';
const total = ref(0)
let rangTime = ref([])
const params = ref({
  isFavorite: false,
  page: 1,
  page_size: 10,
  startTime: '',
  endTime: '',
  jobName: '',
  jobInfoNum: '',
});
let tableList = ref([])
let isShowView = ref(false)
let tabType = ref('全部')
function timeFormatConvert(time) {
  if (!time) return '/'
  const date = new Date(time);
  return date.toLocaleString();
}
function cancelSearch() {
  rangTime.value = []
  params.value = {
    startTime: '',
    endTime: '',
    isFavorite: tabType.value === '收藏' ? true : false,
    page: '1',
    page_size: '10',
    jobName: '',
    jobInfoNum: '',
  }
  getList()
}
function getList() {
  params.value.startTime = rangTime.value?.length ? rangTime.value[0].getTime() : ''
  params.value.endTime = rangTime.value?.length? new Date(
    rangTime.value[1].getFullYear(),
    rangTime.value[1].getMonth(),
    rangTime.value[1].getDate(),
    23, 59, 59
  ).getTime() : ''
  getHistoryTrack(params.value).then(res => {
    tableList.value = res.data.data.list || []
    total.value = res.data.data.pagination.total || 0
  })
}
function handleAll() {
  params.value.isFavorite = false
  params.value.page = 1
  tabType.value = '全部'
  getList()
}
// 查看
let tableDataDetails = ref([])
let detailTotal = ref(0)
let detailParams = ref({
  current: 1,
  size: 10,
  flightId: ''
})
function handleDetail(row) {
  isShowView.value = true
  detailParams.value.current = 1
  detailParams.value.flightId = row.id
  detailTotal.value = 0
  droneFlightLogInfoPage(detailParams.value).then(res => {
    tableDataDetails.value = res.data.data.records
    detailTotal.value = res.data.data.total
  })
}
// 分页
function handleSizeChangeDetails(val) {
  detailParams.value.size = val
  detailParams.value.current = 1
  droneFlightLogInfoPage(detailParams.value).then(res => {
    tableDataDetails.value = res.data.data.records
    detailTotal.value = res.data.data.total
  })
}
function handleCurrentChangeDetails(val) {
  detailParams.value.current = val
  droneFlightLogInfoPage(detailParams.value).then(res => {
    tableDataDetails.value = res.data.data.records
    detailTotal.value = res.data.data.total
  })
}
function handleStartList() {
  params.value.isFavorite = true
  tabType.value = '收藏'
  params.value.page = 1
  getList()
}
// function handleTabClick() {
//   if (tabType.value === '全部') {
//     handleAll()
//   } else if (tabType.value === '收藏') {
//     handleStartList()
//   }
// }
// 收藏
function handleStar(row) {
  if (row.is_favorite) {
    cancelStar(row.id).then(res => {
      ElMessage.success('取消收藏成功')
      getList()
    })
  } else {
    addStar({ flight_log_id: row.id }).then(res => {
      ElMessage.success('收藏成功')
      getList()
    })
  }
}
// 打标签
function handleUpdateLabel(row) {
  updateDroneFlight({ id: row.id, label_id: row.label_id }).then(res => {
    // getList()
    ElMessage.success('设置标签成功')
  })
}
// 删除
function handleDelete(row) {
  ElMessageBox.confirm('确定删除该条数据?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    updateDroneFlight({ is_deleted: 1, id: row.id }).then(res => {
      ElMessage.success('删除成功')
      getList()
    })
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除'
    })
  })
}
// 导出
function handleExport(row) {
  exportBlob(
    `/drone-device-core/log/droneFlightLogInfo/export/${row.id}`
  ).then(res => {
    downloadXls(res.data, `${row.job_name}.xlsx`)
  })
}
// 日期选择
// const changeselect = () => {
//   params.value.startTime = rangTime.value[0] ? rangTime.value[0].getTime() : ''
//   params.value.endTime = rangTime.value[1]? rangTime.value[1].getTime() : ''
//   getList()
// };
function handleSizeChange(val) {
  params.value.page_size = val
  getList()
}
function handleCurrentChange(val) {
  params.value.page = val
  getList()
}
let tagList = ref([])
function tagManageList() {
  flightLogPage({ current:1, size: 99 }).then(res => {
    tagList.value = res.data.data.records || []
  })
}
onMounted(() => {
  // tagManageList()
  getList()
})
</script>
<style lang="scss" scoped>
.flight {
  height: 0;
  flex: 1;
  margin: 0 10px 10px 10px;
  background-color: #ffffff;
  padding: 10px 20px;
  border-radius: 5px;
  display: flex;
  flex-direction: column;
  //.search-box {
  //  height: 30px;
  //}
  :deep(.el-input) {
    .el-input__wrapper {
      width: 200px;
    }
  }
  // 表格
  .mange-table {
    height: 0;
    flex: 1;
    margin-top: 18px;
    overflow: auto;
  }
  :deep(.el-pagination) {
    display: flex;
    justify-content: right;
  }
  :deep(.el-pagination button) {
    background: center center no-repeat none !important;
    color: #8eb8ea !important;
  }
  :deep(.ztzf-select){
    .el-select__selection {
      width: 200px;
    }
  }
}
.content {
  padding: 20px;
  .view-table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid #EBEEF5;
    tr {
      &:not(:last-child) {
        border-bottom: 1px solid #EBEEF5;
      }
      td {
        padding: 12px 10px;
        &.label {
          width: 140px;
          text-align: right;
          // color: #909399;
          // background-color: #F5F7FA;
          border-right: 1px solid #EBEEF5;
        }
        &.value {
          width: 180px;
          // color: #303133;
        }
      }
    }
  }
}
.content-edit {
  .el-form {
    .el-form-item {
      width: 300px;
      :deep(.el-form-item__label) {
        width: 120px;
      }
    }
    .btns {
      display: flex;
      justify-content: center
    }
  }
}
</style>
src/views/resource/components/DrawPolygon.vue
@@ -214,7 +214,7 @@
  viewInstance.value.removeMouseHandler('drawCustomPolygon');
}
const emit = defineEmits(['upDateDrawState']);
const emit = defineEmits(['upDateDrawState',]);
function updatePolygon() {
  let polygon = savePolygonPosition.reduce((pre, cur) => {
@@ -222,7 +222,7 @@
    return pre;
  }, []);
  polygon.push(polygon[0]);
  console.log('绘制', `POLYGON((${polygon.join(',')}))`);
  // 接口
  sdfwUpdate({
      ids: selectionIds.value,
@@ -244,6 +244,7 @@
      })
}
function cancel() {
  remove();
  removeMenuPanel();
src/views/resource/components/spotDetails.vue
@@ -66,14 +66,12 @@
              :row-class-name="tableRowClassName"
              :data="tableData"
              @row-click="handleLocationPolygon"
              @current-change="handleTableRowChange"
            >
              <el-table-column type="index" align="center" :width="pxToRemNum(30)" label="序号">
                <template #default="{ $index }">
                  {{
                    ($index + 1 + (params.page - 1) * params.pageSize).toString().padStart(2, '0')
                  }}
                </template>
               <template #default="{ $index }">
                {{ ($index + 1).toString().padStart(2, '0') }}
              </template>
              </el-table-column>
              <el-table-column prop="dkbh" align="center"  label="图斑名称" show-overflow-tooltip />
              <el-table-column prop="is_exception" :width="pxToRemNum(50)" align="center" label="图斑状态">
@@ -94,20 +92,7 @@
                </template>
              </el-table-column>
            </el-table>
            <div class="pagination-container">
              <el-pagination
                :current-page="params.page"
                :page-size="params.pageSize"
                background
                layout="prev, pager, next, ..."
                :pager-count="3"
                prev-text="上一页"
                next-text="下一页"
                :total="total"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </div>
          </div>
        </div>
        <!--绘制按钮-->
@@ -116,6 +101,7 @@
          ref="drawPolygonRef"
          v-if="isEditing"
          @upDateDrawState="handleUpDateDrawState"
        />
        <!-- 完成/取消 -->
        <div class="btnGroups" v-if="props.title === '图斑编辑'">
@@ -130,6 +116,7 @@
</template>
<script setup>
import { flyVisual } from '@/utils/cesium/mapUtil'
import { pxToRem, pxToRemNum } from '@/utils/rem'
import DrawPolygon from '@/views/resource/components/DrawPolygon.vue';
import { ElMessage, ElMessageBox } from 'element-plus';
@@ -252,59 +239,30 @@
  page: 1,
  pageSize: 10,
});
const isInit = ref(true);
// 图斑管理表格
const getTableList = () => {
  const requestParams = {
    patchesInfoId: props.detailid,
    page: params.value.page,
    pageSize: params.value.pageSize,
  };
  tableMapListApi(requestParams).then(res => {
    tableData.value = res.data.data.records?.map(item => ({
  AlltableMapListApi(requestParams).then(res => {
    tableData.value = res.data.data?.map(item => ({
      ...item,
      dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw,
    }));
    total.value = res.data.data.total || res.data.data.length;
    tbJwdList = [];
    viewer?.entities.removeAll();
    if (!AlltableData.value) {
    if (!tableData.value) {
      viewInstance.value?.flyToContour();
    } else {
      entitiesAddSpot();
    }
  });
};
// 所有图斑数据
const getAlltableMapListApi = () => {
  loading.value = true;
  const requestParams = {
    patchesInfoId: props.detailid,
  };
  AlltableMapListApi(requestParams).then(res => {
    AlltableData.value = res.data.data?.map(item => ({
      ...item,
      dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw,
    }));
    tbJwdList = [];
    viewer?.entities.removeAll();
    if (AlltableData.value.length < 1) {
      viewInstance.value?.flyToContour();
    } else {
      entitiesAddSpot();
    }
    loading.value = false;
  });
};
const handleSizeChange = val => {
  params.value.pageSize = val;
  params.value.page = 1;
  getTableList();
};
const handleCurrentChange = val => {
  params.value.page = val;
  getTableList();
};
// 地图
const initMap = () => {
@@ -324,35 +282,52 @@
  viewer.scene.globe.depthTestAgainstTerrain = true;
  viewInstance.value.switchContour(true);
};
// 仅弹框初始化时执行的定位逻辑
const initMapLocation = () => {
  if (tbJwdList.length === 0 || !homeViewer.value) return;
  // 计算所有图斑的包围球(用于初始化定位)
  const allPositions = tbJwdList.flatMap(item =>
    Cesium.Cartesian3.fromDegreesArray(item.grouped)
  );
  const boundingSphere = Cesium.BoundingSphere.fromPoints(allPositions);
  // 初始化定位(仅执行一次)
  homeViewer.value.camera.flyToBoundingSphere(boundingSphere, {
    duration: 0,
    offset: new Cesium.HeadingPitchRange(
      Cesium.Math.toRadians(0),
      Cesium.Math.toRadians(-90)
    ),
  });
};
// 初始化所有图斑
const entitiesAddSpot = () => {
  viewer?.entities.removeAll();
  AlltableData.value.forEach(item => {
    // 取出当中经纬度
  tbJwdList = []; // 重置经纬度列表
  tableData.value.forEach(item => {
    const numbersWithCommas = item.dkfw.match(/\d+(\.\d+)?/g);
    if (!numbersWithCommas) return;
    // 绘制图斑
    const grouped = numbersWithCommas.map(item => Number(item));
    // 为框选存储对比值
    tbJwdList.push({
      ...item,
      grouped: grouped,
    });
    viewInstance.value.removeById('polygon_dk' + item.id);
    // 根据 is_exception 设置颜色
    const color =
      item.is_exception == 2 ? Cesium.Color.RED.withAlpha(0.5) : Cesium.Color.YELLOW.withAlpha(0.5);
    const outlineColor = item.is_exception == 2 ? Cesium.Color.RED : Cesium.Color.YELLOW;
    const grouped = numbersWithCommas.map(Number);
    tbJwdList.push({ ...item, grouped }); // 存储经纬度用于后续操作
    // 绘制图斑(保留原有逻辑,仅移除定位相关代码)
    const fillColor = item.is_exception === 2
      ? Cesium.Color.RED.withAlpha(0.5)
      : Cesium.Color.YELLOW.withAlpha(0.5);
    const outlineColor = item.is_exception === 2
      ? Cesium.Color.RED
      : Cesium.Color.YELLOW;
    homeViewer.value?.entities?.add({
      id: 'polygon_dk' + item.id,
      id: `polygon_dk${item.id}`,
      customType: 'pattern_spot_polygon',
      customInfo: {
        ...item,
      },
      customInfo: item,
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(grouped)),
        material: color,
        material: fillColor,
        outline: true,
        outlineColor: outlineColor,
        outlineWidth: 2,
@@ -362,23 +337,22 @@
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray(grouped),
        width: 2,
        material: color,
        material: outlineColor,
        clampToGround: true,
      },
      zIndex: 99,
    });
    if (tbJwdList.length > 0) {
      const positions = tbJwdList.flatMap(item => Cesium.Cartesian3.fromDegreesArray(item.grouped));
      const boundingSphere = Cesium.BoundingSphere.fromPoints(positions);
      homeViewer.value?.camera.flyToBoundingSphere(boundingSphere, {
        duration: 0,
        offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(-90)),
      });
    }
    viewInstance.value?.removeLeftClickEvent('spotHighlighting');
    viewInstance.value?.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting');
  });
  // 仅在初始化阶段执行定位(关键:通过isInit控制)
  if (isInit.value) {
    initMapLocation();
    isInit.value = false; // 初始化完成,后续不再执行定位
  }
  // 保留图斑点击高亮事件(原有逻辑不变)
  viewInstance.value?.removeLeftClickEvent('spotHighlighting');
  viewInstance.value?.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting');
};
// 高亮当前选中图斑,并定位
@@ -441,16 +415,12 @@
  updateMapSpotInfo(nowEntity);
}
// 更新上一个和这一个信息
function updateMapSpotInfo(nowEntity) {
  const nowData = nowEntity.customInfo;
  if (!nowEntity) return;
  if (nowEntity.customInfo.id === lastEntity?.customInfo.id) return;
  // 设置新的
  nowEntity.polygon.material = Cesium.Color.RED.withAlpha(0);
  nowEntity.polyline.material = Cesium.Color.RED;
  // 重置上一个
  if (lastEntity) {
    const lastData = lastEntity.customInfo;
    const originalFillColor =
@@ -459,7 +429,6 @@
        : Cesium.Color.YELLOW.withAlpha(0.5);
    const originalOutlineColor =
      lastData.is_exception == 2 ? Cesium.Color.RED : Cesium.Color.YELLOW;
    lastEntity.polygon.material = originalFillColor;
    lastEntity.polygon.outlineColor = originalOutlineColor;
    lastEntity.polyline.material = originalOutlineColor;
@@ -467,23 +436,20 @@
  lastEntity = nowEntity;
  const numbersWithCommas = nowData.dkfw.match(/\d+(\.\d+)?/g);
  if (numbersWithCommas) {
    // 解析经纬度数组
    const groupedArr = numbersWithCommas.reduce((acc, val, index, src) => {
      if (index % 2 === 0) acc.push(src.slice(index, index + 2));
      return acc;
    }, []);
    const polygonCenter = getCenterPoint(groupedArr);
    // 相机定位
    homeViewer.value.scene.camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(
        Number(polygonCenter.lng),
        Number(polygonCenter.lat),
        1500
      ),
      zIndex: 100,
    const positionsData = [];
    for (let i = 0; i < numbersWithCommas.length; i += 2) {
      const lon = Number(numbersWithCommas[i]);
      const lat = Number(numbersWithCommas[i + 1]);
      positionsData.push([lon, lat, 10]);
    }
    flyVisual({
      positionsData: positionsData,
      viewer: homeViewer.value,
      multiple: 15,
    });
  }
  // flyMapSpot(nowEntity?.customInfo)
}
// 清空选中的数据
const clearSelect = () => {
@@ -492,26 +458,31 @@
  viewer?.entities.removeAll();
};
// 编辑
const handleSelectionChange = row => {
  let curRowIsSelect = row;
  curRowIsSelect && handleLocationPolygon(row);
  // 如果是同一个图斑且正在编辑,则取消编辑
  if (selectionIds.value === row.id && isEditing.value) {
    isEditing.value = false;
    handleUpDateDrawState(false);
    selectionIds.value = null;
    selectionList.value = [];
    return;
  }
  // 定位到选中的图斑
  handleLocationPolygon(row);
  // 仅异常图斑可编辑
  if (row.is_exception !== 2) {
    ElMessage.warning('仅异常图斑支持编辑绘制');
    return;
  }
  // 设置编辑状态
  selectionIds.value = row.id;
  selectionList.value = row;
  if (isEditing.value) {
    //当前已编辑 → 取消编辑(关闭绘制、重置状态)
    isEditing.value = false;
    handleUpDateDrawState(false); // 通知DrawPolygon取消绘制
  } else {
    // 当前未编辑 → 开启编辑(仅异常图斑可编辑)
    if (row.is_exception === 2 && curRowIsSelect) {
      isEditing.value = true;
      handleUpDateDrawState(true); // 通知DrawPolygon开启绘制
    } else {
      ElMessage.warning('仅异常图斑支持编辑绘制');
      isEditing.value = false;
    }
  }
  isEditing.value = true;
  handleUpDateDrawState(true);
};
const handleUpDateDrawState = show => {
  isEditing.value = show; // 同步编辑状态
@@ -522,7 +493,7 @@
  }
};
// 删除
const handleDelete = row => {
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除当前行图斑?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
@@ -531,9 +502,27 @@
    deletePatches({ ids: row.id }).then(res => {
      if (res.data.code !== 0) return ElMessage.warning('删除失败');
      ElMessage.success('删除成功');
      getTableList();
      getspotManagementTableApi();
      getAlltableMapListApi();
      tableData.value = tableData.value.filter(item => item.id !== row.id);
      //从地图上移除对应的图斑实体
      const entityId = `polygon_dk${row.id}`;
      viewer?.entities.removeById(entityId);
      const exceptionCountItem = infoList.value.find(item => item.name === '异常图斑数量');
      if (exceptionCountItem && row.is_exception === 2) {
        exceptionCountItem.value = Math.max(0, parseInt(exceptionCountItem.value) - 1);
      }
      const totalCountItem = infoList.value.find(item => item.name === '图斑数量');
      if (totalCountItem) {
        totalCountItem.value = Math.max(0, parseInt(totalCountItem.value) - 1);
      }
      // 清除选中状态
      if (selectionIds.value === row.id) {
        selectionIds.value = null;
        selectionList.value = [];
        isEditing.value = false;
        handleUpDateDrawState(false);
      }
    });
  });
};
@@ -602,18 +591,23 @@
  publicCesiumInstance = null;
};
watch(uploadPatchDialog, newVal => {
  if (newVal) {
    isInit.value = true;
    setTimeout(() => {
      initMap();
      getTableList();
      getAlltableMapListApi();
      initMap();
      getTableList();
      getspotManagementTableApi();
    }, 0);
  } else {
 tableData.value = [];
    isEditing.value = false;
    handleUpDateDrawState(false);
    destroyMap();
    isInit.value = false;
    clearSelect();
  }
  refreshonload();
});
@@ -634,6 +628,10 @@
  font-size: 16px !important;
  color: #363636 !important;
}
:global(.spotDialog .el-dialog__body) {
    padding: 2rem 2rem 0 !important;
  }
.container {
  display: flex;
  flex-direction: column;
@@ -794,7 +792,7 @@
    // 表格主体
    .el-table__body {
      tr:hover > td {
        background-color: rgba(0, 0, 0, 0.6) !important;
        background-color: rgba(64, 158, 255,0.3) !important;
      }
      td {
@@ -804,7 +802,8 @@
    // 选中行
    .current-row td {
      background-color: rgba(0, 0, 0, 0.6) !important;
      background-color: rgba(64, 158, 255,0.3) !important;
    }
  }
  :deep(.el-table__body) {
src/views/system/dept.vue
@@ -183,6 +183,7 @@
            labelWidth: 120,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: false,
            width: 80,
            rules: [
              {
@@ -264,8 +265,34 @@
            },
          },
          {
            label: '部署模式',
            type: 'radio',
            prop: 'deploymentMode',
            labelWidth: 120,
            value: 0,
            dicData: [
              {
                label: '统一部署',
                value: 0,
              },
              {
                label: '独立部署',
                value: 1,
              },
            ],
            rules: [
              {
                required: true,
                message: '请选择部署模式',
                trigger: 'blur',
              },
            ],
          },
          {
            label: '备注',
            prop: 'remark',
            type: 'textarea',
            span: 24,
            labelWidth: 120,
            rules: [
              {
src/views/system/userinfo.vue
@@ -44,7 +44,7 @@
            <el-form-item label="姓名:">
              <el-input
                class="ztzf-input"
                :style="{ width: pxToRem(230) }"
                :style="{ width: pxToRem(350) }"
                v-model="userInfo.realName"
                disabled
              />
@@ -300,6 +300,7 @@
  margin: 16px;
  padding: 10px;
  background-color: #ffffff;
  height: 100%;
}
.titleBoxs {
  margin: 0 24px;
@@ -319,26 +320,25 @@
:deep(.el-form-item__label) {
  color: #000 !important;
}
:deep(.el-button) {
  width: 150px !important;
}
// :deep(.el-button) {
//   width: 150px !important;
// }
.info {
  display: flex;
  justify-content: space-between;
  justify-content: center;
  align-items: center;
  padding: 0 80px 0 50px;
  .section:first-child{
  margin-right: 50px;}
}
.password {
  padding: 0 120px 0 50px;
}
.butn {
  // position: absolute;
  // bottom: 20px;
  // left: 50%;
  // transform: translate(-50%);
  display: flex;
  justify-content: center;
  cursor: pointer;
  img {
    width: 96px;
    height: 32px;
src/views/tickets/orderLog.vue
@@ -298,6 +298,15 @@
              </el-select>
            </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">
@@ -395,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>
@@ -589,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"
@@ -794,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"
@@ -803,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>
@@ -834,7 +848,7 @@
} from '@/api/tickets/orderLog';
import { getTicketInfo } from '@/api/tickets/ticket';
import { getDictionaryByCode } from '@/api/system/dictbiz';
import { getWaylineFileListByArea } from '@/api/resource/wayline';
import { getWaylineFileListByArea, newGetWorkspacesPage } from '@/api/resource/wayline';
import { export_json_to_excel } from '@/utils/exportExcel';
import { getFlyingNestBy } from '@/api/device/device';
import { mapGetters } from 'vuex';
@@ -846,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');
@@ -1559,8 +1573,15 @@
    },
    //获取航线列表
    async asyncgetWaylineFileListByArea(name) {
      var wayLineListResponse = await getWaylineFileListByArea(this.userInfo.detail.areaCode);
      this.wayLineList = wayLineListResponse.data.data;
      const formData = {
        name: '',
        waylineType: undefined,
        current: 1,
        size: 99999999,
        descs: 'update_time',
      }
      var wayLineListResponse = await newGetWorkspacesPage(formData);
      this.wayLineList =  wayLineListResponse.data.data.records
      this.initMapLine();
    },
@@ -1597,7 +1618,7 @@
        //按照航线来
        const params = {
          type: [2, 4, 5].includes(currentLine.wayline_type) ? 2 : 0,
          type: ['2', '4', '5'].includes(currentLine.wayline_type) ? 2 : 0,
          wayline_id: waylineId,
          polygon,
        };
@@ -1669,6 +1690,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>
@@ -644,7 +644,7 @@
                      :src="getThumbUrl(currentDetail.mediaUrl)"
                      :preview-src-list="[getPreviewUrl(currentDetail.mediaUrl)]"
                      fit="contain"
                      style="width: 700px; height: 520px; cursor: pointer"
                      style="pxToRemNum(width: 700px); pxToRemNum(height: 520px); cursor: pointer"
                    >
                      <template #placeholder>
                        <div class="image-placeholder">
@@ -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>
@@ -935,6 +940,7 @@
</template>
<script>
import { pxToRem, pxToRemNum } from '@/utils/rem'
import { getSmallImg, getShowImg } from '@/utils/util';
import { ElMessageBox, ElLoading } from 'element-plus';
import { calculateDefaultRange } from '@/utils/util';
@@ -3574,7 +3580,7 @@
  opacity: 0.3 !important;
}
.PopUpTableScrolls {
  height: 600px;
  max-height: 600px;
  overflow-y: scroll;
  overflow-x: hidden;
}
src/views/wel/components/backlog.vue
@@ -15,7 +15,7 @@
        </div>
      </div>
      <div class="todo-items" v-if="todos.length > 0" v-loading="loading" element-loading-background="rgba(255, 255, 255, 0.5)">
      <div class="todo-items" v-if="todos.length > 0" v-loading="loading" element-loading-background="rgba(255, 255, 255, 0.8)">
        <div v-for="(item, index) in todos" :key="index" class="todo-item" :style="getStatusStyle(item.status)"
          @click="jumporder(item)">
          <div class="status-indicator"><img :src="getStatus(item.status)" alt=""></div>
@@ -83,6 +83,7 @@
])
const titleClick = async (item, index) => {
todos.value =[]
  checked.value = item.name
  await getListMatter()
}