无人机管理后台前端(已迁走)
8 files modified
1277 ■■■■ changed files
src/page/index/useGlobalWS.js 2 ●●● patch | view | raw | blame | history
src/views/dataCenter/dataCenter.vue 21 ●●●●● patch | view | raw | blame | history
src/views/job/components/DeviceJobDetails.vue 1052 ●●●● patch | view | raw | blame | history
src/views/layerManagement/index.vue 95 ●●●● patch | view | raw | blame | history
src/views/tickets/component/AddEditDetails.vue 10 ●●●●● patch | view | raw | blame | history
src/views/tickets/component/SearchBox.vue 10 ●●●● patch | view | raw | blame | history
src/views/tickets/orderLog.vue 23 ●●●● 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/dataCenter/dataCenter.vue
@@ -308,7 +308,9 @@
            class="videoBox"
            ref="videoRefs"
            controls
           preload="auto"
              @play="handleVideoPlay"
              @ended="handleVideoEnded(index)"
            :src="currentVideoUrl"
          ></video>
        </div>
@@ -364,6 +366,23 @@
const currentAreaPosition = ref({ height: 1987280, latitude: 27.636112, longitude: 115.732975 });
let handler = null;
const switchFolders = ref(false)
// 视频播放事件处理
const handleVideoPlay = (event) => {
  if (event.target.playbackRate !== 0.75) {
    event.target.playbackRate = 0.75
  }
}
const handleVideoEnded = index => {
  // 获取当前视频
  const video = videoRefs.value[index]
  // 重置视频播放时间为 0
  video.currentTime = 0
  // 重新加载视频
  video.load()
}
function bytesToMB(bytes, decimalPlaces = 2) {
  if (typeof bytes !== 'number' || bytes < 0) return '0';
  return (bytes / 1048576).toFixed(decimalPlaces) + ' MB';
src/views/job/components/DeviceJobDetails.vue
@@ -1,148 +1,150 @@
<!-- 历史任务详情 -->
<template>
    <el-dialog class="ztzf-dialog" append-to-body modal-class="detailsOfHistoricalTasks" v-model="isShow" title="历史任务详情"
        :width="pxToRem(1800)" :close-on-click-modal="false" :destroy-on-close="true">
        <div class="content">
            <div class="contentLeft">
                <div class="machineTableDetailsTitle"><img src="/src/assets/images/task/sign.svg" alt=""><span>详情</span></div>
                <div class="infoBox">
                    <div class="itemBoxLeft">
                        <div v-for="(item, index) in infoList" :key="index" class="itemCon">
                            <div class="itemBox">
                                <div class="itemTitle">{{ item.name }}:</div>
                                <div truncated class="itemValue" v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'">{{
                                        item.value ? item.value : '--' }}</div>
                                <div class="itemValue" v-if="item.name === '任务执行次数'">{{ item.value ? item.value : '0'
                                    }}次</div>
                                <!-- 飞行事件 -->
                                <div class="flightEvents" v-if="item.name === '飞行事件'">
                                    <template v-if="flightEvents.length">
                                        <img v-for="(item, index) in flightEvents" alt="" :src="item.img"
                                            :title="item.name" :key="index"></img>
                                    </template>
                                    <div class="itemValue" v-else>--</div>
                                </div>
                            </div>
                        </div>
                    </div>
  <el-dialog class="ztzf-dialog" append-to-body modal-class="detailsOfHistoricalTasks" v-model="isShow" title="历史任务详情"
             :width="pxToRem(1800)" :close-on-click-modal="false" :destroy-on-close="true">
    <div class="content">
      <div class="contentLeft">
        <div class="machineTableDetailsTitle"><img src="/src/assets/images/task/sign.svg" alt=""><span>详情</span></div>
        <div class="infoBox">
          <div class="itemBoxLeft">
            <div v-for="(item, index) in infoList" :key="index" class="itemCon">
              <div class="itemBox">
                <div class="itemTitle">{{ item.name }}:</div>
                <div truncated class="itemValue" v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'">{{
                    item.value ? item.value : '--' }}</div>
                <div class="itemValue" v-if="item.name === '任务执行次数'">{{ item.value ? item.value : '0'
                  }}次</div>
                <!-- 飞行事件 -->
                <div class="flightEvents" v-if="item.name === '飞行事件'">
                  <template v-if="flightEvents.length">
                    <img v-for="(item, index) in flightEvents" alt="" :src="item.img"
                         :title="item.name" :key="index"></img>
                  </template>
                  <div class="itemValue" v-else>--</div>
                </div>
              </div>
            </div>
          </div>
                </div>
                <JobRelatedEvents :jobTimes="jobTimes" :batchNo="batchNo" />
                <div class="devicetitle" v-if="isShow">
                <div>
                        <img src="/src/assets/images/task/sign.svg" alt="">
                    <p>
                        成果数据
                        <span>{{ total }}</span>
                        个
                    </p>
                </div>
                    <div class="rightBox" v-if="total">
                        <div class="downloadBtn" @click="htlsrwxq === 100 && downloadFun()">
                            <el-progress v-if="htlsrwxq !== 100" :percentage="htlsrwxq" :show-text="false" striped striped-flow :duration="1" />
                            <div class="downloadBtnText">
                                <span v-if="htlsrwxq === 100">下载</span>
                                <template v-else>
                                    处理中<el-icon @click="cancelDownload"><CircleClose /></el-icon>
                                </template>
                            </div>
                        </div>
                        <div class="downloadBtn" @click="showAll = !showAll" v-if="total > 5">
                            {{ showAll ? '收起' : '更多' }}
                        </div>
                    </div>
                </div>
                <div class="imgListBox">
                    <!-- 图片显示 -->
                    <template v-for="(item, index) in achievementList.slice(0, visibleCount)" :key="index">
                    <div class="result-item">
                        <el-checkbox v-model="item.checked" />
                        <div class="itemName">{{ item.createTime }}</div>
                        <!-- 正射 -->
                            <el-image
                                v-if="item.resultType === 4"
                                :src="item.smallUrl"
                                :preview-src-list="[item.showUrl]"
                                fit="cover"
                                preview-teleported
                            />
                            <!-- 全景 -->
                            <img
                                v-else-if="item.resultType === 5"
                                class="quanjing"
                                @click="clickpanorama(item)"
                                :src="item?.smallUrl"
                                alt=""
                            />
                        <!-- 视频 -->
                            <div v-else-if="item.resultType === 1" class="videotime">
                                <img
                                    class="videoDisplay"
                                    :src="convertVideoUrlToThumbnail(item.link)"
                                    alt=""
                                    @click="enterFullScreen(index)"
                                />
                                <img
                                    @click="enterFullScreen(index)"
                                    class="videobutton"
                                    src="@/assets/images/task/videoshow.png"
                                    alt=""
                                />
                            </div>
                                <!-- 图片 -->
                            <el-image
                                v-else
                                :src="item.smallUrl"
                                :preview-src-list="[item.showUrl]"
                                preview-teleported
                                :initial-index="index"
                                fit="cover"
                            />
        </div>
        <JobRelatedEvents :jobTimes="jobTimes" :batchNo="batchNo" />
        <div class="devicetitle" v-if="isShow">
          <div>
            <img src="/src/assets/images/task/sign.svg" alt="">
            <p>
              成果数据
              <span>{{ total }}</span>
              个
            </p>
          </div>
          <div class="rightBox" v-if="total">
            <div class="downloadBtn" @click="htlsrwxq === 100 && downloadFun()">
              <el-progress v-if="htlsrwxq !== 100" :percentage="htlsrwxq" :show-text="false" striped striped-flow :duration="1" />
              <div class="downloadBtnText">
                <span v-if="htlsrwxq === 100">下载</span>
                <template v-else>
                  处理中<el-icon @click="cancelDownload"><CircleClose /></el-icon>
                </template>
              </div>
            </div>
            <div class="downloadBtn" @click="showAll = !showAll" v-if="total > 5">
              {{ showAll ? '收起' : '更多' }}
            </div>
          </div>
        </div>
        <div class="imgListBox">
          <!-- 图片显示 -->
          <template v-for="(item, index) in achievementList.slice(0, visibleCount)" :key="index">
            <div class="result-item">
              <el-checkbox v-model="item.checked" />
              <div class="itemName">{{ item.createTime }}</div>
              <!-- 正射 -->
              <el-image
                v-if="item.resultType === 4"
                :src="item.smallUrl"
                :preview-src-list="[item.showUrl]"
                fit="cover"
                preview-teleported
              />
              <!-- 全景 -->
              <img
                v-else-if="item.resultType === 5"
                class="quanjing"
                @click="clickpanorama(item)"
                :src="item?.smallUrl"
                alt=""
              />
              <!-- 视频 -->
              <div v-else-if="item.resultType === 1" class="videotime">
                <img
                  class="videoDisplay"
                  :src="convertVideoUrlToThumbnail(item.link)"
                  alt=""
                  @click="enterFullScreen(index)"
                />
                <img
                  @click="enterFullScreen(index)"
                  class="videobutton"
                  src="@/assets/images/task/videoshow.png"
                  alt=""
                />
              </div>
              <!-- 图片 -->
              <el-image
                v-else
                :src="item.smallUrl"
                :preview-src-list="[item.showUrl]"
                preview-teleported
                :initial-index="index"
                fit="cover"
              />
                        <el-dialog
              class="ztzf-dialog"
              append-to-body
              modal-class="detailsOfHistoricalTasks"
              v-model="VideoShow"
              :width="pxToRem(1600)"
              :close-on-click-modal="false"
              :destroy-on-close="true"
            >
                <div class="fullscreen">
                    <video
                        ref="fullscreenVideo"
                        class="fullscreen-video"
                        :src="currentVideoUrl"
                        :style="{ width: pxToRem(1567), height: '80vh' }"
                        controls
              <el-dialog
                class="ztzf-dialog"
                append-to-body
                modal-class="detailsOfHistoricalTasks"
                v-model="VideoShow"
                :width="pxToRem(1600)"
                :close-on-click-modal="false"
                :destroy-on-close="true"
              >
                <div class="fullscreen">
                  <video
                    ref="fullscreenVideo"
                    class="fullscreen-video"
                    :src="currentVideoUrl"
                    :style="{ width: pxToRem(1567), height: '80vh' }"
                    controls
                    preload="auto"
                    @play="handleVideoPlay"
                    @ended="handleVideoEnded"
                  ></video>
                </div>
              </el-dialog>
            </div>
                    ></video>
                </div>
            </el-dialog>
                        </div>
          </template>
                    </template>
        </div>
        <el-image-viewer
          v-if="showViewer"
          :url-list="previewUrls"
          :initial-index="activeIndex"
          @close="showViewer = false"
        />
      </div>
                </div>
                <el-image-viewer
                    v-if="showViewer"
                    :url-list="previewUrls"
                    :initial-index="activeIndex"
                    @close="showViewer = false"
                />
            </div>
            <div class="content-right" v-if="isShow">
                <DeviceJobDetailsMap
                    :detailsData="detailsData"
                    :yuanImages="yuanImages"
                    @showImageeclick="showImageeclick"
                    :jobId="props.jobId"
                />
                <div class="content-map-popups"></div>
            </div>
        </div>
    </el-dialog>
      <div class="content-right" v-if="isShow">
        <DeviceJobDetailsMap
          :detailsData="detailsData"
          :yuanImages="yuanImages"
          @showImageeclick="showImageeclick"
          :jobId="props.jobId"
        />
        <div class="content-map-popups"></div>
      </div>
    </div>
  </el-dialog>
  <!-- 全景360 -->
  <PanoramaPopup
    v-if="'全景'"
@@ -153,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'
@@ -169,46 +171,66 @@
const VideoShow = ref(false)
const showAll = ref(false) // 是否展示全部
let loadingData
const fullscreenVideo = ref(null)
// 视频播放事件处理
const handleVideoPlay = (event) => {
  if (event.target.playbackRate !== 0.75) {
    event.target.playbackRate = 0.75
  }
}
const handleVideoEnded = index => {
  // 获取当前视频
  const video = fullscreenVideo.value
  // 重置视频播放时间为 0
  video.currentTime = 0
  // 重新加载视频
  video.load()
}
// 原图
const yuanImages = ref([])
function convertVideoUrlToThumbnail(videoUrl) {
    // 检查是否是有效的视频URL
    if (!videoUrl || typeof videoUrl !== 'string') {
        return videoUrl
    }
    // 替换文件扩展名
    return videoUrl.replace(/\.mp4$/, '_small.jpg')
  // 检查是否是有效的视频URL
  if (!videoUrl || typeof videoUrl !== 'string') {
    return videoUrl
  }
  // 替换文件扩展名
  return videoUrl.replace(/\.mp4$/, '_small.jpg')
}
const infoList = ref([
    { name: '任务编号', value: '', field: 'job_info_num' },
    { name: '任务名称', value: '', field: 'name' },
    { name: '任务类型', value: '', field: 'industry_type_str' },
    { name: '飞行事件', value: '', field: 'event_number' },
    { name: '所属机巢', value: '', field: 'device_names' },
    { name: '所属部门', value: '', field: 'dept_name' },
    { name: '任务时间', value: '', field: 'cycle_time_value' },
    { name: '关联算法', value: '', field: 'ai_type_str' },
    { name: '任务描述', value: '', field: 'remark' },
  { name: '任务编号', value: '', field: 'job_info_num' },
  { name: '任务名称', value: '', field: 'name' },
  { name: '任务类型', value: '', field: 'industry_type_str' },
  { name: '飞行事件', value: '', field: 'event_number' },
  { name: '所属机巢', value: '', field: 'device_names' },
  { name: '所属部门', value: '', field: 'dept_name' },
  { name: '任务时间', value: '', field: 'cycle_time_value' },
  { name: '关联算法', value: '', field: 'ai_type_str' },
  { name: '自定义识别区', value: '', field: 'enable_custom_area' },
    // { name: '任务执行次数', value: '', field: 'job_num' },
  { name: '创建人', value: '', field: 'creator_name' },
  { name: '任务描述', value: '', field: 'remark' },
  // { name: '任务执行次数', value: '', field: 'job_num' },
])
// 机巢状态
const flystatus = ref('')
const detailsData = ref({
    id: null,
    remark: null,
    is_monitoring: null,
    industry_type_str: null,
    area_code: null,
    ai_type_str: null,
    begin_time: null,
    end_time: null,
    device_names: null,
    create_time: null,
    name: null,
    event_number: null,
    creator_name: null,
    way_lines: [],
  id: null,
  remark: null,
  is_monitoring: null,
  industry_type_str: null,
  area_code: null,
  ai_type_str: null,
  enable_custom_area:null,
  begin_time: null,
  end_time: null,
  device_names: null,
  create_time: null,
  name: null,
  event_number: null,
  creator_name: null,
  way_lines: [],
})
// 任务成果
const total = ref(0)
@@ -218,10 +240,10 @@
provide('wayLineJodInfoId', wayLineJodInfoId)
// 可见数量
const visibleCount = computed(() =>
    showAll.value ? achievementList.value.length : Math.min(5, achievementList.value.length)
  showAll.value ? achievementList.value.length : Math.min(5, achievementList.value.length)
)
const getAchievement = () => {
    if (!props.jobId) return
  if (!props.jobId) return
  const attachmentsParams = {
    'wayLineJobId': props.jobId,
@@ -230,83 +252,83 @@
    current: 1,
    size: 2000,
  }
    const pageParams = {
        current: 1,
        size: 2000,
    }
  const pageParams = {
    current: 1,
    size: 2000,
  }
  aiImagesPage(attachmentsParams ).then(res => {
        achievementList.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
        // console.log('成果数据', res.data.data)
    })
    achievementList.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
    // console.log('成果数据', res.data.data)
  })
}
const jumpMore = () => {
    ElMessage.warning('正在加急开发中...')
  ElMessage.warning('正在加急开发中...')
}
const flightEvents = ref([])
const jobTimes = ref([])
const getDetails = () => {
    const params = {
        wayLineJobInfoId: props.wayLineJodInfoId,
        waylineJobId: props.waylineJobId,
        batchNo: props.batchNo
    }
    getJobDetails(params).then(res => {
        detailsData.value = res.data.data
        jobTimes.value = res.data.data.job_times
        infoList.value.forEach(item => {
            if (item.name === '任务频次') {
                const { rep_rule_type = '', rep_rule_val = '' } = detailsData?.value || {}
                item.value = rep_rule_type + ' -- ' + rep_rule_val
            } else {
                item.value = detailsData.value?.[item.field] || '--'
            }
            if (item.name === '飞行事件') {
                const { action_modes = [] } = detailsData?.value || {}
                flightEvents.value = action_modes.flatMap(({ actionActuatorFunc }) =>
                    droneEventList.filter(({ value }) => actionActuatorFunc === value)
                )
            }
  const params = {
    wayLineJobInfoId: props.wayLineJodInfoId,
    waylineJobId: props.waylineJobId,
    batchNo: props.batchNo
  }
  getJobDetails(params).then(res => {
    detailsData.value = res.data.data
    jobTimes.value = res.data.data.job_times
    infoList.value.forEach(item => {
      if (item.name === '任务频次') {
        const { rep_rule_type = '', rep_rule_val = '' } = detailsData?.value || {}
        item.value = rep_rule_type + ' -- ' + rep_rule_val
      } else {
        item.value = detailsData.value?.[item.field] || '--'
      }
      if (item.name === '飞行事件') {
        const { action_modes = [] } = detailsData?.value || {}
        flightEvents.value = action_modes.flatMap(({ actionActuatorFunc }) =>
          droneEventList.filter(({ value }) => actionActuatorFunc === value)
        )
      }
      if (item.name === '自定义识别区') {
        item.value = res.data.data.enable_custom_area ? '是': '否'
      }
                getJobsAllFiles({
            wayLineJobId: detailsData.value.way_lines.map(item => item.job_id).join(','),
            resultTypes: [0, 2, 4, 5],
        }).then(result => {
            if (result.data.code !== 200) return
            yuanImages.value = result.data.data.records
      getJobsAllFiles({
        wayLineJobId: detailsData.value.way_lines.map(item => item.job_id).join(','),
        resultTypes: [0, 2, 4, 5],
      }).then(result => {
        if (result.data.code !== 200) return
        yuanImages.value = result.data.data.records
        })
        })
        // flystatus.value = res.data.data.ai_type_str
    })
      })
    })
    // flystatus.value = res.data.data.ai_type_str
  })
}
// 播放
const videoRef = ref(null);
const currentVideoIndex = ref(-1)
const fullscreenVideo = ref(null)
const enterFullScreen = (index) => {
    currentVideoIndex.value = index
    VideoShow.value = true
  currentVideoIndex.value = index
  VideoShow.value = true
}
// 计算当前视频URL
const currentVideoUrl = computed(() => {
    return achievementList.value[currentVideoIndex.value]?.link || ''
  return achievementList.value[currentVideoIndex.value]?.link || ''
})
// 关闭弹窗处理
const handleClose = () => {
    if (fullscreenVideo.value) {
        fullscreenVideo.value.pause()
        fullscreenVideo.value.currentTime = 0
    }
  if (fullscreenVideo.value) {
    fullscreenVideo.value.pause()
    fullscreenVideo.value.currentTime = 0
  }
}
// 下载
const downloadFun = async () => {
@@ -315,8 +337,8 @@
    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)
            const suffix = item.link.split('.').pop()
            aLinkDownloadUtil(item.link, item.nickName + '.' + suffix)
        })
    } else {
        loadingData = ElLoading.service({ background: 'rgba(0, 0, 0, 0.5)', text: '打包中,请稍等...' })
@@ -334,353 +356,353 @@
const panoramaParamsShow = ref(false)
const panoramaParamsUrl = ref(null)
const clickpanorama = val => {
    panoramaParamsShow.value = true
    panoramaParamsUrl.value = val.link
  panoramaParamsShow.value = true
  panoramaParamsUrl.value = val.link
}
// 从地图点击图片预览
const showViewer = ref(false)
const activeIndex = ref(0)
const previewUrls = ref([])
const showImageeclick = (list, index, categoriestype) => {
    if (categoriestype === 5) {
        panoramaParamsShow.value = true
        panoramaParamsUrl.value = list[0]
    } else {
        previewUrls.value = list
        activeIndex.value = 0
        showViewer.value = true
    }
  if (categoriestype === 5) {
    panoramaParamsShow.value = true
    panoramaParamsUrl.value = list[0]
  } else {
    previewUrls.value = list
    activeIndex.value = 0
    showViewer.value = true
  }
}
// 取消下载
function cancelDownload() {
    cancelDownloadApi({ type:'htlsrwxq' }).then(res =>{
        ElMessage.success('取消成功')
    }).catch(e =>{
  cancelDownloadApi({ type:'htlsrwxq' }).then(res =>{
    ElMessage.success('取消成功')
  }).catch(e =>{
    EventBus.emit('useGlobalWS-messageHandler', {biz_code: 'DOWNLOAD_PROGRESS',data:{status: 'CANCELLED',type:'htlsrwxq'}})
  })
}
onMounted(() => {
    getDetails()
    getAchievement()
  getDetails()
  getAchievement()
})
</script>
<style lang="scss">
.detailsOfHistoricalTasks {
    .el-dialog {
        --el-dialog-margin-top: 5vh;
    }
  .el-dialog {
    --el-dialog-margin-top: 5vh;
  }
    .el-pagination {
        justify-content: center;
        padding: 20px;
    }
  .el-pagination {
    justify-content: center;
    padding: 20px;
  }
    .el-dialog__body {
        height: 80vh;
    }
  .el-dialog__body {
    height: 80vh;
  }
}
</style>
<style lang="scss" scoped>
.content {
    display: flex;
    height: 100%;
.contentLeft {
        margin-left: 35px;
        margin-right: 24px;
        width: 1150px;
        overflow: auto;
  display: flex;
  height: 100%;
  .contentLeft {
    margin-left: 35px;
    margin-right: 24px;
    width: 1150px;
    overflow: auto;
        .machineTableDetailsTitle {
            margin-bottom: 10px;
            // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
            border-bottom: 2px solid #e4e7ed;
            background-size: 100% 100%;
            img{
            width: 15px;
            height: 15px;}
            span {
                display: inline-block;
                margin-left: 10px;
                font-size: 16px;
                // color: #0282ff;
                color: #303133;
                line-height: 20px;
                text-align: left;
                margin-bottom: 8px;
            }
        }
    .machineTableDetailsTitle {
      margin-bottom: 10px;
      // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
      border-bottom: 2px solid #e4e7ed;
      background-size: 100% 100%;
      img{
        width: 15px;
        height: 15px;}
      span {
        display: inline-block;
        margin-left: 10px;
        font-size: 16px;
        // color: #0282ff;
        color: #303133;
        line-height: 20px;
        text-align: left;
        margin-bottom: 8px;
      }
    }
        .devicetitle {
            margin-bottom: 16px;
            // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
            border-bottom: 2px solid #e4e7ed;
            background-size: 100% 100%;
            display: flex;
            justify-content: space-between;
            align-content: center;
            .rightBox{
                display: flex;
                align-items: center;
                padding-right: 10px;
                gap: 0 10px;
    .devicetitle {
      margin-bottom: 16px;
      // background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
      border-bottom: 2px solid #e4e7ed;
      background-size: 100% 100%;
      display: flex;
      justify-content: space-between;
      align-content: center;
      .rightBox{
        display: flex;
        align-items: center;
        padding-right: 10px;
        gap: 0 10px;
                .downloadBtn{
                    position: relative;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    height: 28px;
                    padding: 0 15px;
                    background: rgba(28, 92, 255, 0.14);
                    border-radius: 4px 4px 4px 4px;
                    border: 1px solid #1c5cff;
                    cursor: pointer;
                        color: #1C5CFF;
        .downloadBtn{
          position: relative;
          display: flex;
          align-items: center;
          justify-content: center;
          height: 28px;
          padding: 0 15px;
          background: rgba(28, 92, 255, 0.14);
          border-radius: 4px 4px 4px 4px;
          border: 1px solid #1c5cff;
          cursor: pointer;
          color: #1C5CFF;
                    .downloadBtnText{
                        display: flex;
                        align-items: center;
                        gap: 5px;
                        z-index: 5;
                    }
                    .el-progress{
                        position: absolute;
                        left: 0;
                        top: 0;
                        width: 100%;
          .downloadBtnText{
            display: flex;
            align-items: center;
            gap: 5px;
            z-index: 5;
          }
          .el-progress{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
                        :deep(){
                            .el-progress-bar__outer{
                                height: 28px !important;
                                border-radius: 0 !important;
                                background: transparent !important;
            :deep(){
              .el-progress-bar__outer{
                height: 28px !important;
                border-radius: 0 !important;
                background: transparent !important;
                                .el-progress-bar__inner{
                                    border-radius: 0 !important;
                                }
                            }
                        }
                    }
                .el-progress-bar__inner{
                  border-radius: 0 !important;
                }
              }
            }
          }
                }
            }
            img{
            width: 15px;
            height: 15px;}
            p {
                display: inline-block;
                margin-left: 10px;
                font-size: 16px;
                color: #363636;
                line-height: 20px;
                text-align: left;
                margin-bottom: 8px;
        }
      }
      img{
        width: 15px;
        height: 15px;}
      p {
        display: inline-block;
        margin-left: 10px;
        font-size: 16px;
        color: #363636;
        line-height: 20px;
        text-align: left;
        margin-bottom: 8px;
                span {
                    font-size: 26px;
                    color: #0282ff;
                    font-weight: bold;
                }
            }
        span {
          font-size: 26px;
          color: #0282ff;
          font-weight: bold;
        }
      }
            .more {
                color: #2f9dff;
                font-size: 14px;
                padding-top: 5px;
                cursor: pointer;
            }
        }
      .more {
        color: #2f9dff;
        font-size: 14px;
        padding-top: 5px;
        cursor: pointer;
      }
    }
        .infoBox {
            display: flex;
            justify-content: space-between;
    .infoBox {
      display: flex;
      justify-content: space-between;
            .itemBoxLeft {
                flex: 1;
                display: grid;
                grid-template-columns: repeat(2, 1fr);
                column-gap: 10px;
                /* 只设置列间距 */
                row-gap: 0;
                /* 取消行间距 */
                padding: 10px;
                font-size: 14px;
      .itemBoxLeft {
        flex: 1;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        column-gap: 10px;
        /* 只设置列间距 */
        row-gap: 0;
        /* 取消行间距 */
        padding: 10px;
        font-size: 14px;
                .itemBox {
                    display: flex;
                    align-items: center;
                    background: #fff;
                    height: 43px;
                    border-top: 2px solid #EFEFEF;
        .itemBox {
          display: flex;
          align-items: center;
          background: #fff;
          height: 43px;
          border-top: 2px solid #EFEFEF;
                }
        }
            }
      }
            .itemCon:nth-last-child(-n+2) {
                border-bottom: 2px solid #EFEFEF;
            }
      .itemCon:nth-last-child(-n+2) {
        border-bottom: 2px solid #EFEFEF;
      }
            .itemBox:nth-last-child(-n+2) .itemTitle {
                border-bottom: 1px solid #EFEFEF;
            }
      .itemBox:nth-last-child(-n+2) .itemTitle {
        border-bottom: 1px solid #EFEFEF;
      }
            .itemTitle {
                color: #0B1D38;
                width: 26%;
                text-align: right;
                background: #F3F6FF;
                height: 43px;
                line-height: 43px;
                padding-right: 10px;
                border-top: 1px solid #EFEFEF;
            }
      .itemTitle {
        color: #0B1D38;
        width: 26%;
        text-align: right;
        background: #F3F6FF;
        height: 43px;
        line-height: 43px;
        padding-right: 10px;
        border-top: 1px solid #EFEFEF;
      }
            .itemValue {
                font-size: 14px;
                color: #747e91;
                text-align: center;
                width: 74%;
      .itemValue {
        font-size: 14px;
        color: #747e91;
        text-align: center;
        width: 74%;
            }
      }
            .flightEvents {
                display: flex;
                flex-wrap: wrap;
                gap: 10px 10px;
                width: 74%;
                justify-content: center;
      .flightEvents {
        display: flex;
        flex-wrap: wrap;
        gap: 10px 10px;
        width: 74%;
        justify-content: center;
                img {
                    width: 30px;
                    height: 30px;
                }
            }
        img {
          width: 30px;
          height: 30px;
        }
      }
        }
    }
        .imgListBox {
            display: grid;
            grid-template-columns: repeat(5, 1fr);
            gap: 10px;
            margin-bottom: 49px;
    .imgListBox {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 10px;
      margin-bottom: 49px;
            > * {
                width: 100%;
                height: 200px;
                position: relative;
                border-radius: 0px 0px 4px 4px;
                overflow: hidden;
            }
            :deep(.el-checkbox__inner) {
                width: 17px !important;
                height: 17px !important;
                background: rgba(37, 36, 36, 0.63) !important;
                border-radius: 4px 4px 4px 4px;
                border: 1px solid #ffffff !important;
            }
            .el-checkbox {
                position: absolute;
                top: 0;
                left: 6px;
            }
            :deep(.el-checkbox__inner:after) {
                position: absolute;
                left: 50% !important;
                top: 40% !important;
                transform: translate(-50%, -50%) rotate(45deg) !important;
            }
            :deep(.el-checkbox.is-checked .el-checkbox__inner) {
                background-color: #09297b !important;
                border-color: #1c5cff !important;
            }
            .el-image {
                width: 100%;
                height: 100%;
                cursor: pointer;
                position: relative;
            }
      > * {
        width: 100%;
        height: 200px;
        position: relative;
        border-radius: 0px 0px 4px 4px;
        overflow: hidden;
      }
      :deep(.el-checkbox__inner) {
        width: 17px !important;
        height: 17px !important;
        background: rgba(37, 36, 36, 0.63) !important;
        border-radius: 4px 4px 4px 4px;
        border: 1px solid #ffffff !important;
      }
      .el-checkbox {
        position: absolute;
        top: 0;
        left: 6px;
      }
      :deep(.el-checkbox__inner:after) {
        position: absolute;
        left: 50% !important;
        top: 40% !important;
        transform: translate(-50%, -50%) rotate(45deg) !important;
      }
      :deep(.el-checkbox.is-checked .el-checkbox__inner) {
        background-color: #09297b !important;
        border-color: #1c5cff !important;
      }
      .el-image {
        width: 100%;
        height: 100%;
        cursor: pointer;
        position: relative;
      }
            .quanjing {
                width: 100%;
                height: 100%;
                object-fit: cover;
                cursor: pointer;
                position: relative;
            }
      .quanjing {
        width: 100%;
        height: 100%;
        object-fit: cover;
        cursor: pointer;
        position: relative;
      }
            .videotime {
                width: 100%;
                height: 100%;
                position: relative;
      .videotime {
        width: 100%;
        height: 100%;
        position: relative;
                .videoDisplay {
                    width: 100%;
                    height: 100%;
                    object-fit: cover;
                }
            }
            .itemName {
                position: absolute;
                bottom: 0;
                left: 0;
                height: 23px;
                width: 100%;
                background: rgba(22, 22, 22, 0.68);
                border-radius: 0px 0px 4px 4px;
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: 400;
                font-size: 14px;
                color: #ffffff;
                line-height: 23px;
                z-index: 9;
                padding: 0 6px;
            }
        }
        .videoDisplay {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
      }
      .itemName {
        position: absolute;
        bottom: 0;
        left: 0;
        height: 23px;
        width: 100%;
        background: rgba(22, 22, 22, 0.68);
        border-radius: 0px 0px 4px 4px;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 14px;
        color: #ffffff;
        line-height: 23px;
        z-index: 9;
        padding: 0 6px;
      }
    }
.videobutton {
            position: absolute;
            top: 40%;
            left: 50%;
            transform: translate(-50%);
            cursor: pointer;
            width: 40px;
            height: 40px;
            display: inline-block;
            background: #999;
            border-radius: 50%;
        }
        .videoDisplay {
            display: flex;
            flex-wrap: wrap;
            width: 200px;
            height: 200px;
    .videobutton {
      position: absolute;
      top: 40%;
      left: 50%;
      transform: translate(-50%);
      cursor: pointer;
      width: 40px;
      height: 40px;
      display: inline-block;
      background: #999;
      border-radius: 50%;
    }
    .videoDisplay {
      display: flex;
      flex-wrap: wrap;
      width: 200px;
      height: 200px;
        }
    }
        .videotime {
            position: relative;
        }
    .videotime {
      position: relative;
    }
    }
  }
        .content-right {
        position: relative;
        width: 0;
        flex-grow: 1;
        background: #19ad8d;
        margin-right: 17px;
        overflow: hidden;
  .content-right {
    position: relative;
    width: 0;
    flex-grow: 1;
    background: #19ad8d;
    margin-right: 17px;
    overflow: hidden;
        .content-map-popups {
            pointer-events: none;
    .content-map-popups {
      pointer-events: none;
            > * {
                pointer-events: auto !important;
            }
        }
    }
      > * {
        pointer-events: auto !important;
      }
    }
  }
}
</style>
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,9 +64,10 @@
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'
const store = useStore();
const userInfo = computed(() => store.getters.userInfo);
const areaCode = userInfo.value?.detail?.areaCode || '';
@@ -79,20 +80,28 @@
const selectDataList = ref([]);
// 当前面位置信息
let curPolygonPosition = [];
const tabData = ref([
  {
    name: '自定义识别区',
    type: '0',
  },
  {
    name: '自定义禁飞区',
    type: '1',
  },
  {
    name: '国土空间规划',
    type: '2',
  },
]);
const tabData = computed(() => {
  const allTabs = [
    {
      name: '自定义识别区',
      type: '0',
    },
    {
      name: '自定义禁飞区',
      type: '1',
    },
    {
      name: '国土空间规划',
      type: '2',
    },
  ];
  // 如果是生产环境,只返回自定义识别区
  if (isProd) {
    return allTabs.filter(tab => tab.type === '0');
  }
  return allTabs;
});
const layerParams = ref({
  addNest: false,
  editNest: false,
@@ -128,7 +137,7 @@
     layerParams.value.addFolder = false
    layerParams.value.editFolder = false
    resetCheck.value = !resetCheck.value;
};
const refreshMethod = () => {
  getdataFolderApi();
@@ -157,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();
@@ -212,7 +221,7 @@
      console.warn(`数据 ${item.name} 坐标点不足,无法绘制`);
      return;
    }
    tbJwdList.push(...positions);
    let degreesArray = [];
    positions.forEach(pos => {
@@ -227,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}`,
@@ -263,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) {
    // 筛选当前文件夹下的所有子节点坐标
@@ -283,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,
@@ -317,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 => {
@@ -394,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),
@@ -411,7 +420,7 @@
  }else {
    showToolTipText.value = '点击地图生成测绘区域'
  }
 if(polygon.length > 0){
      polygon.push([curPolygonPosition[0]?.lng, curPolygonPosition[0]?.lat])
 }
@@ -467,7 +476,7 @@
// 添加loading
const isPageLoading = ref(false);
const handleLoadingChange = (status) => {
  isPageLoading.value = status;
  isPageLoading.value = status;
};
provide('layerParams', layerParams);
onMounted(() => {
src/views/tickets/component/AddEditDetails.vue
@@ -364,12 +364,14 @@
      positions.unshift({latitude: maxItem.latitude, longitude: maxItem.longitude, height:maxItem.drone_height })
      positions.push({latitude: maxItem.latitude, longitude: maxItem.longitude, height:maxItem.drone_height})
      let resultHeight = 0
      let valueHeight = 0
      await getWaylineMaxTerrainHeight(positions).then(res => {
        resultHeight = safeHeight.value > (res.data.data + 30) ? safeHeight.value : (res.data.data + 30)
        resultHeight = (safeHeight.value + maxItem.drone_height) > (res.data.data + 30) ? (safeHeight.value + maxItem.drone_height) : (res.data.data + 30)
        console.log(resultHeight,maxItem.drone_height, '999')
        valueHeight = (resultHeight - maxItem.drone_height) > backHeight ? _.round(resultHeight - maxItem.drone_height) : 0
      })
      let valueHeight = _.round(backHeight - resultHeight, 2)
      if (valueHeight < 0) {
        await ElMessageBox.confirm(`当前返航高度存在安全隐患,建议调整为${resultHeight}米以上后进行发布`, '提示', {
      if (valueHeight > 0) {
        await ElMessageBox.confirm(`当前返航高度存在安全隐患,建议调整为${valueHeight}米以上后进行发布`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
src/views/tickets/component/SearchBox.vue
@@ -115,6 +115,9 @@
const aiTypeList = inject('aiTypeList')
watch(activeTab, (newTab, oldTab) => {
  if (newTab === 'all') {
    searchForm.status = ''
  }
  if(newTab === 'WAIT_AUDIT') {
    searchForm.status = '1'
  }
@@ -124,7 +127,8 @@
  if(newTab === 'PASS') {
    searchForm.status = '3'
  }
}, { immediate: true })
  emit('search', searchForm);
})
// 周期
const cycles = ref(['每天', '周一', '周二', '周三', '周四', '周五', '周六', '周末', '周天', '工作日'])
@@ -172,7 +176,9 @@
  searchForm.deal_time = ""
  searchForm.file_id = ""
  searchForm.key_word = ""
  searchForm.status = ''
  if (activeTab.value === 'all') {
    searchForm.status = ''
  }
  searchForm.rep_fre_type = ''
  dateRange.value = ''
  searchForm.create_start_date = null
src/views/tickets/orderLog.vue
@@ -173,17 +173,17 @@
// tab切换
function handleTabChange (tab) {
  activeTab.value = tab.paneName
  orderListParams.status = ''
  if (tab.paneName === 'WAIT_AUDIT') {
    orderListParams.status = '1'
  } else if (tab.paneName === 'REJECTED') {
    orderListParams.status = '2'
  } else if (tab.paneName === 'PASS') {
    orderListParams.status = '3'
  } else if (tab.paneName === 'DRAFT') {
    orderListParams.status = '0'
  }
  refreshGetOrderList()
  // orderListParams.status = ''
  // if (tab.paneName === 'WAIT_AUDIT') {
  //   orderListParams.status = '1'
  // } else if (tab.paneName === 'REJECTED') {
  //   orderListParams.status = '2'
  // } else if (tab.paneName === 'PASS') {
  //   orderListParams.status = '3'
  // } else if (tab.paneName === 'DRAFT') {
  //   orderListParams.status = '0'
  // }
  // refreshGetOrderList()
}
// 更新统计数
@@ -260,7 +260,6 @@
const searchClick = params => {
  orderListParams.current = 1
  orderListParams.size = 10
  console.log('333', params)
  orderListParams.searchParams = params
  getTableList()
}
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;
  }