吉安感知网项目-前端
罗广辉
2026-01-20 bcbcc546577c7c6643e7f0d4ac366f8a013bd306
Merge remote-tracking branch 'origin/master'
33 files modified
2 files added
975 ■■■■■ changed files
applications/drone-command/public/fonts/DinAB.TTF patch | view | raw | blame | history
applications/drone-command/public/fonts/font.css 7 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/device-map-container.vue 30 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/mac/index.vue 7 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/page/index/top/top-full.vue 13 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/page/lock/index.vue 10 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/page/login/index.vue 10 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/common/cockpit.scss 32 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/cesium/DrawPolygon.js 1 ●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/util.js 25 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue 3 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue 3 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue 3 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue 1 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/job/jobinfo.vue 12 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/layerManagement/components/utils.js 1 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/layerManagement/index.vue 8 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue 3 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/recordManage/historyTracks/index.vue 33 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue 607 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue 6 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue 16 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue 91 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js 9 ●●●●● patch | view | raw | blame | history
applications/drone-command/public/fonts/DinAB.TTF
Binary files differ
applications/drone-command/public/fonts/font.css
@@ -52,3 +52,10 @@
  font-display: swap;
}
@font-face {
  font-family: "DinAB";
  src: url("DinAB.TTF") format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -22,7 +22,15 @@
        <div v-if="popupVisible" class="device-popup" :style="popupStyle" @click.stop>
            <div class="device-popup__header">
                <span class="device-popup__title">{{ popupTitle }}</span>
                <el-tooltip
                    class="device-popup__title-tooltip"
                    :content="popupTitle"
                    placement="top"
                    effect="dark"
                    :show-after="200"
                >
                    <span class="device-popup__title">{{ popupTitleDisplay }}</span>
                </el-tooltip>
                <img class="device-popup__close" :src="popupClose" alt="" @click.stop="closePopup">
            </div>
@@ -579,7 +587,13 @@
    top: `${popupPosition.value.y}px`,
}))
const POPUP_TITLE_MAX = 12
const popupTitle = computed(() => selectedDevice.value?.deviceName || selectedDevice.value?.deviceModel || '-')
const popupTitleOverflow = computed(() => popupTitle.value.length > POPUP_TITLE_MAX)
const popupTitleDisplay = computed(() => {
    if (!popupTitleOverflow.value) return popupTitle.value
    return `${popupTitle.value.slice(0, POPUP_TITLE_MAX)}……`
})
const popupStatusText = computed(() => {
    const status = selectedDevice.value?.status
    if (status === 0) return '在线'
@@ -828,6 +842,20 @@
            border-radius: 0px 0px 5px 5px;
        }
        .device-popup__title-tooltip {
            flex: 1;
            min-width: 0;
            display: block;
        }
        .device-popup__title {
            display: inline-block;
            max-width: 100%;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .device-popup__close {
            cursor: pointer;
        }
applications/drone-command/src/mac/index.vue
@@ -69,6 +69,7 @@
    return {
      app: false,
      timeString: '',
      timeTimer: null,
    }
  },
  computed: {
@@ -116,6 +117,12 @@
    this.startTimer()
    this.$store.dispatch('GetMenu')
  },
  beforeDestroy () {
    if (this.timeTimer) {
      clearInterval(this.timeTimer)
      this.timeTimer = null
    }
  },
  methods: {
    switchTheme () {
      this.$store.commit('SET_THEME_NAME', '')
applications/drone-command/src/page/index/top/top-full.vue
@@ -6,11 +6,22 @@
import { fullscreenToggel, listenfullscreen } from 'utils/util';
export default {
  data() {
    return {
      fullscreenCleanup: null,
    };
  },
  computed: {
    ...mapGetters(['isFullScren']),
  },
  mounted() {
    listenfullscreen(this.setScreen);
    this.fullscreenCleanup = listenfullscreen(this.setScreen);
  },
  beforeDestroy() {
    if (this.fullscreenCleanup) {
      this.fullscreenCleanup();
      this.fullscreenCleanup = null;
    }
  },
  methods: {
    setScreen() {
applications/drone-command/src/page/lock/index.vue
@@ -45,6 +45,7 @@
  data() {
    return {
      time: '',
      timeTimer: null,
      passwd: '',
      passwdError: false,
      pass: false,
@@ -52,10 +53,17 @@
  },
  created() {
    this.getTime();
    setInterval(() => {
    if (this.timeTimer) clearInterval(this.timeTimer);
    this.timeTimer = setInterval(() => {
      this.getTime();
    }, 1000);
  },
  beforeDestroy() {
    if (this.timeTimer) {
      clearInterval(this.timeTimer);
      this.timeTimer = null;
    }
  },
  mounted() {},
  computed: {
    ...mapGetters(['userInfo', 'tag', 'lockPasswd']),
applications/drone-command/src/page/login/index.vue
@@ -56,6 +56,7 @@
      },
      website: website,
      time: '',
      timeTimer: null,
      activeName: 'user',
      socialForm: {
        tenantId: '000000',
@@ -82,6 +83,12 @@
  computed: {
    ...mapGetters(['tagWel']),
  },
  beforeDestroy() {
    if (this.timeTimer) {
      clearInterval(this.timeTimer);
      this.timeTimer = null;
    }
  },
  props: [],
  methods: {
    // 动态获取系统名称
@@ -93,7 +100,8 @@
      })
    },
    getTime() {
      setInterval(() => {
      if (this.timeTimer) clearInterval(this.timeTimer);
      this.timeTimer = setInterval(() => {
        this.time = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
      }, 1000);
    },
applications/drone-command/src/styles/common/cockpit.scss
@@ -1065,24 +1065,37 @@
}
.command-page-view-dialog {
    padding: 30px;
    margin: 0;
    padding: 20px;
    display: flex;
    flex-direction: column;
    width: 770px;
    background: #1A1A2A;
    border-radius: 6px 6px 6px 6px;
    border: 1px solid #2E2E46;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    .el-dialog__header {
        position: relative;
        span {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: bold;
            font-size: 18px;
            color: #FFFFFF;
            line-height: 40px;
            text-align: left;
            font-style: normal;
            text-transform: none;
        }
        .el-button {
            width: auto;
            height: auto;
            display: flex;
            align-items: center;
        }
        .el-icon {
@@ -1145,6 +1158,7 @@
                height: 360px;
                .command-table-pagination {
                    padding-bottom: 20px;
                    justify-content: center;
                }
            }
@@ -1165,6 +1179,10 @@
            .el-row {
                .el-col {
                    margin-bottom: 0;
                    .el-form-item {
                        margin-bottom: 20px;
                    }
                }
            }
@@ -1288,6 +1306,7 @@
    }
    .el-dialog__footer {
        padding-top: 0;
        display: flex;
        justify-content: center;
@@ -1353,7 +1372,9 @@
}
.command-page-map-view-dialog {
    padding: 30px;
    margin: 0;
    padding: 20px;
    display: flex;
    flex-direction: column;
    width: 80%;
@@ -1362,6 +1383,11 @@
    border-radius: 6px 6px 6px 6px;
    border: 1px solid #2E2E46;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    .el-dialog__header,
    .el-dialog__footer {
        margin: 0;
applications/drone-command/src/utils/cesium/DrawPolygon.js
@@ -785,6 +785,7 @@
                this.handler.removeInputAction(type)
            })
            this.handler.destroy()
            this.handler = null
        }
    }
applications/drone-command/src/utils/util.js
@@ -102,22 +102,21 @@
 * esc监听全屏
 */
export const listenfullscreen = callback => {
  function listen () {
  const handler = () => {
    callback()
  }
  document.addEventListener('fullscreenchange', function () {
    listen()
  })
  document.addEventListener('mozfullscreenchange', function () {
    listen()
  })
  document.addEventListener('webkitfullscreenchange', function () {
    listen()
  })
  document.addEventListener('msfullscreenchange', function () {
    listen()
  })
  document.addEventListener('fullscreenchange', handler)
  document.addEventListener('mozfullscreenchange', handler)
  document.addEventListener('webkitfullscreenchange', handler)
  document.addEventListener('msfullscreenchange', handler)
  return () => {
    document.removeEventListener('fullscreenchange', handler)
    document.removeEventListener('mozfullscreenchange', handler)
    document.removeEventListener('webkitfullscreenchange', handler)
    document.removeEventListener('msfullscreenchange', handler)
  }
}
/**
 * 获取缩略图路径
applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]">
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]"
        :close-on-click-modal="false">
        <div class="detail-container" v-if="readonly">
            <div class="detail-title">派出所详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">派出所名称</div>
applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
@@ -1,6 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed"
        destroy-on-close>
        destroy-on-close :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <el-row>
                <el-col :span="12">
applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
@@ -1,5 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
        :close-on-click-modal="false">
        <el-form class="dialog-form" ref="formRef" :model="formData" :rules="rules" label-width="100px">
            <el-row>
                <el-col :span="24">
applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
@@ -1,5 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
        :close-on-click-modal="false">
        <el-form class="dialog-form" ref="formRef" :model="formData" :rules="rules" label-width="100px">
            <el-row>
                <el-col :span="12">
applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
@@ -1,6 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed"
        destroy-on-close>
        destroy-on-close :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">设备详情</div>
            <el-row>
applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
@@ -1,6 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed"
        destroy-on-close>
        destroy-on-close :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">设备详情</div>
            <el-row>
applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
@@ -5,9 +5,9 @@
        :title="titleEnum[dialogMode]"
        @closed="handleClosed"
        destroy-on-close
        :close-on-click-modal="false"
    >
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">设备详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">设备名称</div>
applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue
@@ -72,8 +72,11 @@
const removeDom = () => {
  const dom = document.querySelector('#mapPopUpBox');
  if (dom && dom.parentNode) {
    dom.parentNode.removeChild(dom);
  if (dom) {
    render(null, dom);
    if (dom.parentNode) {
      dom.parentNode.removeChild(dom);
    }
  }
};
// 移除弹框标签
@@ -290,6 +293,7 @@
onMounted(() => {});
onBeforeUnmount(() => {
  removeLabel();
  if (viewer) {
    viewer.destroy();
  }
applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue
@@ -25,7 +25,7 @@
            <div class="list">
                <div class="item" v-for="(item, ind) in equipmentList" :key="ind">
                    <div class="val" :class="{highlight: item.isHighlight}" @click="equipmentClick(item.isHighlight)">
                    <div class="val" :class="{ highlight: item.isHighlight }" @click="equipmentClick(item.isHighlight)">
                        {{ item.value }}
                    </div>
@@ -158,7 +158,7 @@
        display: flex;
        align-items: center;
        height: 100px;
        background: rgba(0,0,0,0.3);
        background: rgba(0, 0, 0, 0.3);
        box-sizing: border-box;
        border-radius: 16px 16px 16px 16px;
        pointer-events: auto;
@@ -172,7 +172,7 @@
            height: 100%;
            z-index: -1;
            background: rgba(17, 23, 34, 0.56);
              backdrop-filter: blur(2px);
            backdrop-filter: blur(2px);
            border-radius: 16px 16px 16px 16px;
        }
@@ -208,7 +208,7 @@
                }
                .val {
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-family: DinAB;
                    font-weight: bold;
                    font-size: 30px;
                    text-align: left;
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2026-01-07 15:17:54
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-19 14:05:35
 * @LastEditTime : 2026-01-20 09:19:16
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RightContainer.vue
 * @Description  : 
 * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -233,7 +233,7 @@
            .val {
                margin-top: 10px;
                font-family: DIN, DIN;
                font-family: DinAB;
                font-weight: bold;
                font-size: 22px;
                color: #FFFFFF;
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
@@ -65,8 +65,8 @@
        </div>
        <div class="footer">
            <el-button v-if="showSignalBtn(data)" class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
            <el-button v-if="showCounterBtn(data)" color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
            <el-button class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
            <el-button color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
        </div>
    </div>
</template>
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
@@ -8,7 +8,6 @@
        destroy-on-close
    >
        <div v-if="readonly" class="detail-container">
            <div class="detail-title">配置详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">起始扇区</div>
@@ -94,7 +93,7 @@
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="24"><h3 style="color: #ffffff">工作模式</h3></el-col>
                <el-col :span="24"><h3 style="color: #ffffff">设备参数</h3></el-col>
                <el-col :span="12">
                    <el-form-item label="伺服模式" prop="servoMode">
                        <el-select
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
@@ -8,7 +8,6 @@
        @closed="handleClosed"
    >
        <div v-if="readonly" class="detail-container">
            <div class="detail-title">调度详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">设备名称</div>
applications/drone-command/src/views/job/jobinfo.vue
@@ -45,13 +45,21 @@
      selectionList: [],
      option: option,
      data: [],
      searchChangeHandler: null,
    }
  },
  created() {
       this.$bus?.on('triggerSearchChange', (params) => {
       this.searchChangeHandler = (params) => {
         this.searchChange(params, () => {});
       });
       };
       this.$bus?.on('triggerSearchChange', this.searchChangeHandler);
     },
  beforeDestroy() {
    if (this.searchChangeHandler) {
      this.$bus?.off('triggerSearchChange', this.searchChangeHandler);
      this.searchChangeHandler = null;
    }
  },
  computed: {
    ...mapGetters(['permission']),
    permissionList () {
applications/drone-command/src/views/layerManagement/components/utils.js
@@ -600,6 +600,7 @@
                this.handler.removeInputAction(type)
            })
            this.handler.destroy()
            this.handler = null
        }
    }
applications/drone-command/src/views/layerManagement/index.vue
@@ -488,14 +488,15 @@
  isPageLoading.value = status;
};
provide('layerParams', layerParams);
const focusOnNodeHandler = nodeData => {
  focusOnNode(nodeData);
};
onMounted(() => {
  initMap();
  cesiumContextMenu();
  getdataFolderApi();
  // 监听定位事件
  EventBus.on('focusOnNode', (nodeData) => {
    focusOnNode(nodeData);
  });
  EventBus.on('focusOnNode', focusOnNodeHandler);
  EventBus.on('deleteMapEntityById', deleteMapEntityById);
  EventBus.on('deleteMapEntitiesByFolderId', deleteMapEntitiesByFolderId);
});
@@ -523,6 +524,7 @@
onBeforeUnmount(() => {
  destroyMap();
  cesiumContextMenu(false);
  EventBus.off('focusOnNode', focusOnNodeHandler);
  EventBus.off('deleteMapEntityById', deleteMapEntityById);
  EventBus.off('deleteMapEntitiesByFolderId', deleteMapEntitiesByFolderId);
});
applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
        :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">机构详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">部门名称</div>
applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
        :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">角色详情</div>
            <el-row>
                <el-col :span="12">
                    <div class="label">角色名称</div>
applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
@@ -1,5 +1,6 @@
<template>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
    <el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
        :close-on-click-modal="false">
        <div class="detail-container" v-if="dialogReadonly">
            <div class="detail-title">用户详情</div>
            <el-row>
applications/drone-command/src/views/recordManage/historyTracks/index.vue
@@ -39,12 +39,22 @@
        </el-form>
        <div class="command-table-toolbar">
            <el-button :icon="Download" color="#1A2652" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button>
            <el-button
                :icon="Download"
                color="#1A2652"
                type="primary"
                @click="exportFile"
                :loading="exportLoading"
                :disabled="!selectionList.length"
            >
                导出
            </el-button>
        </div>
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-table" :data="list">
                <el-table class="command-table" :data="list" ref="tableRef" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="48" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" />
                    <el-table-column prop="serialNo" show-overflow-tooltip label="无人机序列号" />
@@ -82,7 +92,7 @@
<script setup>
import { Search, RefreshRight, Download } from '@element-plus/icons-vue'
import { onMounted, ref } from 'vue'
import { onMounted, ref, nextTick } from 'vue'
import { exportFwDroneFlightRecordApi, fwDroneFlightRecordPageApi } from './fwDroneFlightRecord'
import { blobDownload, dateRangeFormat } from '@ztzf/utils'
import TrajectoryDiaLog from '@/views/recordManage/historyTracks/TrajectoryDiaLog.vue'
@@ -97,6 +107,8 @@
const total = ref(0) // 总条数
const loading = ref(true) // 列表加载中
const list = ref([]) // 列表数据
const tableRef = ref(null)
const selectionList = ref([])
const queryParamsRef = ref(null) // 查询表单实例
const dateRange = ref([])
const exportLoading = ref(false)
@@ -111,6 +123,9 @@
        const res = await fwDroneFlightRecordPageApi(params)
        list.value = res?.data?.data?.records ?? []
        total.value = res?.data?.data?.total ?? 0
        selectionList.value = []
        await nextTick()
        tableRef.value?.clearSelection()
    } finally {
        loading.value = false
    }
@@ -141,8 +156,14 @@
function exportFile() {
    const range = dateRangeFormat(dateRange.value)
    const ids = selectionList.value.map(item => item.id).filter(Boolean)
    exportLoading.value = true
    exportFwDroneFlightRecordApi({ ...searchParams.value, start_time: range[0], end_time: range[1] })
    exportFwDroneFlightRecordApi({
        ...searchParams.value,
        start_time: range?.[0],
        end_time: range?.[1],
        id: ids.join(','),
    })
        .then(res => {
            blobDownload(res)
        })
@@ -151,6 +172,10 @@
        })
}
function handleSelectionChange(selection) {
    selectionList.value = selection || []
}
function handleView(row) {
    dialogRef.value?.open({ mode: 'view', row: { ...row } })
}
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue
@@ -1,164 +1,154 @@
<template>
    <el-dialog
        class="gd-dialog"
        v-model="visible"
        :title="'查看申请'"
        @closed="visible = false"
        destroy-on-close
    >
    <div class="detail-container">
        <!-- 左侧步骤条 -->
        <div class="detail-left">
            <el-steps :active="activeStep" direction="vertical" align-center>
                <el-step v-for="(step, index) in steps" :key="index" :title="step.title">
                    <template #description>
                        <div class="step-person">{{ step.person }}</div>
                        <div class="step-time">{{ step.time }}</div>
                    </template>
                </el-step>
            </el-steps>
        </div>
        <!-- 右侧表单数据 -->
        <div class="detail-right">
        <div>
            <div class="label">需求详情</div>
            <div class="requirementsDetailsBox">
                <div class="detail-table">
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">需求名称</span>
                            <span class="cell-value">{{ formData.demandName }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">需求类型</span>
                            <span class="cell-value">{{ getDictLabel(formData.demandType, dictObj.requirementType) }}</span>
    <el-dialog class="gd-dialog" v-model="visible" :title="'查看申请'" @closed="visible = false" destroy-on-close>
        <div class="detail-container">
            <!-- 左侧审批记录 -->
            <div class="detail-left">
                <div class="label">审批记录</div>
                <el-steps :active="activeStep" direction="vertical" align-center>
                    <el-step v-for="(step, index) in steps" :key="index" :title="step.title">
                        <template #description>
                            <div class="step-person">{{ step.person }}</div>
                            <div class="step-time">{{ step.time }}</div>
                        </template>
                    </el-step>
                </el-steps>
            </div>
            <!-- 右侧表单数据 -->
            <div class="detail-right">
                <div>
                    <div class="label">需求详情</div>
                    <div class="requirementsDetailsBox">
                        <div class="detail-table">
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">需求名称</span>
                                    <span class="cell-value">{{ formData.demandName }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">需求类型</span>
                                    <span class="cell-value">{{ getDictLabel(formData.demandType, dictObj.requirementType) }}</span>
                                </div>
                            </div>
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">需求联系人</span>
                                    <span class="cell-value">{{ formData.contactPerson }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">需求联系人电话</span>
                                    <span class="cell-value">{{ formData.contactPhone }}</span>
                                </div>
                            </div>
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">需求邮箱</span>
                                    <span class="cell-value">{{ formData.contactEmail }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">更新周期</span>
                                    <span class="cell-value">{{ formData.updateCycle }}</span>
                                </div>
                            </div>
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">申请依据</span>
                                    <span class="cell-value">{{ formData.applyBasis }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">共享类型</span>
                                    <span class="cell-value">{{ getDictLabel(formData.shareType, dictObj.sharedType) }}</span>
                                </div>
                            </div>
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">应用场景类型</span>
                                    <span class="cell-value">{{ getDictLabel(formData.applicationScene, dictObj.appSceneType) }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">责任部门</span>
                                    <span class="cell-value">{{ formData.responsibleDeptName }}</span>
                                </div>
                            </div>
                            <div class="detail-row">
                                <div class="detail-cell">
                                    <span class="cell-label">数据来源依据</span>
                                    <span class="cell-value">{{ formData.dataSource }}</span>
                                </div>
                                <div class="detail-cell">
                                    <span class="cell-label">需求信息项</span>
                                    <span class="cell-value">{{ formData.demandInfo }}</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">需求联系人</span>
                            <span class="cell-value">{{ formData.contactPerson }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">需求联系人电话</span>
                            <span class="cell-value">{{ formData.contactPhone }}</span>
                        </div>
                    </div>
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">需求邮箱</span>
                            <span class="cell-value">{{ formData.contactEmail }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">更新周期</span>
                            <span class="cell-value">{{ formData.updateCycle }}</span>
                        </div>
                    </div>
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">申请依据</span>
                            <span class="cell-value">{{ formData.applyBasis }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">共享类型</span>
                            <span class="cell-value">{{ getDictLabel(formData.shareType, dictObj.sharedType) }}</span>
                        </div>
                    </div>
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">应用场景类型</span>
                            <span class="cell-value">{{ getDictLabel(formData.applicationScene, dictObj.appSceneType) }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">责任部门</span>
                            <span class="cell-value">{{ formData.responsibleDeptName }}</span>
                        </div>
                    </div>
                    <div class="detail-row">
                        <div class="detail-cell">
                            <span class="cell-label">数据来源依据</span>
                            <span class="cell-value">{{ formData.dataSource }}</span>
                        </div>
                        <div class="detail-cell">
                            <span class="cell-label">需求信息项</span>
                            <span class="cell-value">{{ formData.demandInfo }}</span>
                </div>
                <div>
                    <div class="label">数据上传</div>
                    <div class="upload-container">
                        <el-upload
                            ref="uploadRef"
                            :auto-upload="false"
                            :limit="1"
                            :on-change="handleFileChange"
                            :on-remove="handleFileRemove"
                            :before-upload="beforeFileUpload"
                            :file-list="fileList"
                            accept=".zip,.rar,.7z,.tar,.gz"
                            class="upload-demo"
                        >
                            <template #trigger>
                                <el-button type="primary">选择文件</el-button>
                            </template>
                            <template #tip>
                                <div class="el-upload__tip">请上传压缩文件 (.zip/.rar/.7z/.tar/.gz)</div>
                            </template>
                        </el-upload>
                        <el-button type="success" :disabled="!selectedFile" @click="handleUpload" style="margin-top: 10px">
                            上传文件
                        </el-button>
                        <!-- 已上传文件列表 -->
                        <div v-if="uploadedFiles.length > 0" class="uploaded-files">
                            <h4>已上传文件:</h4>
                            <div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
                                <span>{{ file.originalName }}</span>
                                <el-button type="text" @click="viewFile(file)" style="margin-left: 10px">查看</el-button>
                                <el-button type="text" @click="downloadFile(file)" style="margin-left: 5px">下载</el-button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
            <div>
                <div class="label">数据上传</div>
                <div class="upload-container">
                   <el-upload
                    ref="uploadRef"
                    :auto-upload="false"
                    :limit="1"
                    :on-change="handleFileChange"
                    :on-remove="handleFileRemove"
                    :before-upload="beforeFileUpload"
                    :file-list="fileList"
                    accept=".zip,.rar,.7z,.tar,.gz"
                    class="upload-demo"
                  >
                    <template #trigger>
                      <el-button type="primary">选择文件</el-button>
                    </template>
                    <template #tip>
                      <div class="el-upload__tip">
                        请上传压缩文件 (.zip/.rar/.7z/.tar/.gz)
                      </div>
                    </template>
                  </el-upload>
                  <el-button
                    type="success"
                    :disabled="!selectedFile"
                    @click="handleUpload"
                    style="margin-top: 10px;"
                  >
                    上传文件
                  </el-button>
                  <!-- 已上传文件列表 -->
                  <div v-if="uploadedFiles.length > 0" class="uploaded-files">
                    <h4>已上传文件:</h4>
                    <div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
                      <span>{{ file.originalName }}</span>
                      <el-button type="text" @click="viewFile(file)" style="margin-left: 10px;">查看</el-button>
                      <el-button type="text" @click="downloadFile(file)" style="margin-left: 5px;">下载</el-button>
                    </div>
                  </div>
                </div>
            </div>
        </div>
    </div>
        <template #footer>
            <el-button
                class="save-btn"
                color="#4C34FF"
                @click="rejectTheApplication"
            >
                拒绝申请
            </el-button>
            <el-button color="#F2F3F5"  @click="approvedByTheReview">审核通过</el-button>
            <el-button class="save-btn" color="#4C34FF" @click="rejectTheApplication">拒绝申请</el-button>
            <el-button color="#F2F3F5" @click="approvedByTheReview">审核通过</el-button>
        </template>
    </el-dialog>
    <!-- 拒绝申请弹框 -->
    <reasonForRejectionDialog
        v-if="rejectionDialogVisible"
        v-model="rejectionDialogVisible"
        @confirm="handleRejectionConfirm"
    />
</template>
<script setup>
import { ref, inject } from 'vue'
import { getDictLabel } from '@ztzf/utils'
import { gdSupplyDemandDetailApi, putFileAttachApi,gdSupplyDemandAuditPassApi,gdSupplyDemandAuditRejectApi } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
    gdSupplyDemandDetailApi,
    putFileAttachApi,
    gdSupplyDemandAuditPassApi,
    gdSupplyDemandAuditRejectApi,
    gdSupplyDemandAuditListApi
} from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi'
import { ElMessage } from 'element-plus'
import reasonForRejectionDialog from './reasonForRejectionDialog.vue'
const emit = defineEmits(['success'])
const dictObj = inject('dictObj')
const deptTree = inject('deptTree')
const demandId = ref('')
const visible = defineModel() // 弹框显隐
const formData = ref({}) // 表单数据
const uploadRef = ref() // 上传组件引用
@@ -167,131 +157,132 @@
const uploadedFiles = ref([]) // 已上传文件列表
const uploadLoading = ref(false) // 上传加载状态
const responseData = ref([])
// 拒绝申请弹框控制
const rejectionDialogVisible = ref(false) // 拒绝申请弹框显隐
// 步骤条数据
const steps = ref([
    { title: '需求申请', person: '张三', time: '2025-03-31 12:23:30' },
    { title: '审核通过', person: '', time: '' },
    { title: '需求申请', person: '', time: '' },
    { title: '审核通过', person: '', time: '' }
])
// 当前激活步骤
const activeStep = ref(0)
const activeStep = ref(0)
// 文件选择变化
const handleFileChange = (file, fileList) => {
  if (fileList.length > 0) {
    selectedFile.value = file.raw
  } else {
    selectedFile.value = null
  }
    if (fileList.length > 0) {
        selectedFile.value = file.raw
    } else {
        selectedFile.value = null
    }
}
// 文件移除
const handleFileRemove = () => {
  selectedFile.value = null
    selectedFile.value = null
}
// 上传前验证
const beforeFileUpload = (file) => {
  const allowedExtensions = ['.zip', '.rar', '.7z', '.tar', '.gz']
  const fileExtension = '.' + file.name.split('.').pop().toLowerCase()
  if (!allowedExtensions.includes(fileExtension)) {
    ElMessage.error('只能上传压缩文件格式:.zip/.rar/.7z/.tar/.gz')
    return false
  }
  // 文件大小限制,这里限制为100MB
  const maxSize = 100 * 1024 * 1024 // 100MB
  if (file.size > maxSize) {
    ElMessage.error('文件大小不能超过100MB')
    return false
  }
  return true
const beforeFileUpload = file => {
    const allowedExtensions = ['.zip', '.rar', '.7z', '.tar', '.gz']
    const fileExtension = '.' + file.name.split('.').pop().toLowerCase()
    if (!allowedExtensions.includes(fileExtension)) {
        ElMessage.error('只能上传压缩文件格式:.zip/.rar/.7z/.tar/.gz')
        return false
    }
    // 文件大小限制,这里限制为100MB
    const maxSize = 100 * 1024 * 1024 // 100MB
    if (file.size > maxSize) {
        ElMessage.error('文件大小不能超过100MB')
        return false
    }
    return true
}
// 处理文件上传
const handleUpload = async () => {
  if (!selectedFile.value) {
    ElMessage.warning('请先选择文件')
    return
  }
    if (!selectedFile.value) {
        ElMessage.warning('请先选择文件')
        return
    }
  // 再次验证文件类型
  if (!beforeFileUpload(selectedFile.value)) {
    return
  }
    // 再次验证文件类型
    if (!beforeFileUpload(selectedFile.value)) {
        return
    }
  try {
    uploadLoading.value = true
    // 创建FormData对象
    const formData = new FormData()
    formData.append('file', selectedFile.value)
    // 调用上传接口
    const response = await putFileAttachApi(formData)
    if (response.data && response.data.success) {
      const fileData = response.data.data
      console.log('成功数据',fileData);
      responseData.value = fileData
      // 添加到已上传文件列表
      uploadedFiles.value.push({
        name: fileData.name,
        originalName: fileData.originalName,
        link: fileData.link,
        attachId: fileData.attachId
      })
      ElMessage.success('文件上传成功!')
      // 清空上传列表
      uploadRef.value.clearFiles()
      selectedFile.value = null
      // 这里可以将附件ID保存到表单数据中,供后续提交使用
      // formData.value.attachmentId = fileData.attachId
    } else {
      ElMessage.error(response.data?.msg || '文件上传失败')
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    ElMessage.error('文件上传失败,请重试')
  } finally {
    uploadLoading.value = false
  }
    try {
        uploadLoading.value = true
        // 创建FormData对象
        const formData = new FormData()
        formData.append('file', selectedFile.value)
        // 调用上传接口
        const response = await putFileAttachApi(formData)
        if (response.data && response.data.success) {
            const fileData = response.data.data
            console.log('成功数据', fileData)
            responseData.value = fileData
            // 添加到已上传文件列表
            uploadedFiles.value.push({
                name: fileData.name,
                originalName: fileData.originalName,
                link: fileData.link,
                attachId: fileData.attachId,
            })
            ElMessage.success('文件上传成功!')
            // 清空上传列表
            uploadRef.value.clearFiles()
            selectedFile.value = null
            // 这里可以将附件ID保存到表单数据中,供后续提交使用
            // formData.value.attachmentId = fileData.attachId
        } else {
            ElMessage.error(response.data?.msg || '文件上传失败')
        }
    } catch (error) {
        console.error('文件上传失败:', error)
        ElMessage.error('文件上传失败,请重试')
    } finally {
        uploadLoading.value = false
    }
}
// 查看文件
const viewFile = (file) => {
  if (file.link) {
    window.open(file.link, '_blank')
  } else {
    ElMessage.warning('文件链接无效')
  }
const viewFile = file => {
    if (file.link) {
        window.open(file.link, '_blank')
    } else {
        ElMessage.warning('文件链接无效')
    }
}
// 下载文件
const downloadFile = (file) => {
  if (file.link) {
    // 创建一个隐藏的a标签来触发下载
    const a = document.createElement('a')
    a.href = file.link
    a.download = file.originalName || file.name
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
  } else {
    ElMessage.warning('文件链接无效')
  }
const downloadFile = file => {
    if (file.link) {
        // 创建一个隐藏的a标签来触发下载
        const a = document.createElement('a')
        a.href = file.link
        a.download = file.originalName || file.name
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
    } else {
        ElMessage.warning('文件链接无效')
    }
}
// 根据部门ID获取部门名称
function getDeptNameById(deptId, deptList) {
    // 处理类型转换,确保比较的是相同类型
    const targetId = String(deptId)
    // 递归遍历部门树
    function findDept(deptList) {
        for (const dept of deptList) {
@@ -305,11 +296,11 @@
        }
        return ''
    }
    if (!targetId || !Array.isArray(deptList) || deptList.length === 0) {
        return ''
    }
    return findDept(deptList)
}
@@ -317,8 +308,8 @@
async function open({ row }) {
    if (row?.id) {
        await loadDetail(row.id)
        // 可以在这里加载已上传的文件列表
        // loadUploadedFiles(row.id)
        demandId.value = row.id
        console.log('row.id', demandId.value)
    }
    visible.value = true
}
@@ -332,36 +323,132 @@
        data.responsibleDeptName = getDeptNameById(data.responsibleDeptId, deptTree.value)
    }
    formData.value = data
    // 加载审核记录
    await loadAuditRecords(id)
}
// 如果需要加载已上传的文件列表
const loadUploadedFiles = async (id) => {
  try {
    // 这里根据实际情况调用接口获取已上传的文件列表
    // const response = await getFileListApi({ id })
    // if (response.data?.success) {
    //   uploadedFiles.value = response.data.data || []
    // }
  } catch (error) {
    console.error('加载已上传文件失败:', error)
  }
// 加载审核记录
async function loadAuditRecords(demandId) {
    try {
        const res = await gdSupplyDemandAuditListApi({ demandId })
        const auditRecords = res?.data?.data ?? []
        // 处理审核记录为步骤格式
        processAuditRecords(auditRecords)
    } catch (error) {
        console.error('加载审核记录失败:', error)
        ElMessage.error('加载审核记录失败,请重试')
        // 保持默认步骤,不做清空
        activeStep.value = 0
    }
}
// 处理审核记录为步骤格式
function processAuditRecords(records) {
    // 重置为默认步骤结构
    steps.value = [
        { title: '需求申请', person: '', time: '' },
        { title: '审核通过', person: '', time: '' }
    ]
    if (!records || records.length === 0) {
        // 没有审核记录,保持默认步骤
        activeStep.value = 0
        return
    }
    // 按创建时间排序(最新的在最后)
    const sortedRecords = [...records].sort((a, b) => new Date(a.createTime) - new Date(b.createTime))
    // 处理需求申请步骤(第一个步骤)
    const demandRecord = sortedRecords.find(record => record.auditStatus === '0') || sortedRecords[0]
    if (demandRecord) {
        steps.value[0] = {
            title: '需求申请',
            person: demandRecord.createUser ? `${demandRecord.createUser}` : '',
            time: demandRecord.createTime ? demandRecord.createTime : ''
        }
    }
    // 处理审核步骤(第二个步骤)
    const latestRecord = sortedRecords[sortedRecords.length - 1]
    if (latestRecord) {
        // 根据最新审核结果设置标题
        let auditTitle = '审核通过'
        if (latestRecord.auditStatus === '2') {
            auditTitle = '审核驳回'
            // 更新第二个步骤的标题为审核驳回
            steps.value[1].title = auditTitle
        }
        // 添加审核意见(如果有)
        if (latestRecord.auditOpinion) {
            steps.value[1].title += ` - ${latestRecord.auditOpinion}`
        }
        // 更新审核步骤的信息
        steps.value[1].person = latestRecord.createUser ? `${latestRecord.createUser}` : ''
        steps.value[1].time = latestRecord.createTime ? latestRecord.createTime : ''
        // 根据最新审核结果设置activeStep
        switch (latestRecord.auditStatus) {
            case '0':
                // 审核中,高亮第一个步骤
                activeStep.value = 0
                break
            case '1':
                // 审核通过,高亮第二个步骤
                activeStep.value = 1
                break
            case '2':
                // 审核驳回,高亮第二个步骤
                activeStep.value = 1
                break
            default:
                // 默认高亮第一个步骤
                activeStep.value = 0
        }
    }
}
// 拒绝申请
const rejectTheApplication = () => {
    // const id = ['2013182736046530562']
    if (responseData.value.length === 0) {
        return ElMessage.warning('请上传数据')
    }
    // 打开拒绝申请弹框
    rejectionDialogVisible.value = true
}
// 处理拒绝申请确认
const handleRejectionConfirm = reason => {
    const id = [responseData.value.attachId]
    console.log('responseData.value',responseData.value)
    gdSupplyDemandAuditRejectApi({ attachIds:id }).then(() => {
        ElMessage.success('拒绝申请成功')
        visible.value = false
    })
    console.log('demandId.value', demandId.value)
    gdSupplyDemandAuditRejectApi({ attachIds: id, auditOpinion: reason, demandId: demandId.value })
        .then(() => {
            ElMessage.success('拒绝申请成功')
            visible.value = false
            emit('success')
        })
        .catch(error => {
            console.error('拒绝申请失败:', error)
            ElMessage.error('拒绝申请失败,请重试')
            emit('success')
        })
}
// 审核通过
const approvedByTheReview = () => {
    if (responseData.value.length === 0) {
        return ElMessage.warning('请上传数据')
    }
    const id = [responseData.value.attachId]
    gdSupplyDemandAuditPassApi({ id }).then(() => {
    gdSupplyDemandAuditPassApi({ attachIds: id, demandId: demandId.value }).then(() => {
        ElMessage.success('审核通过成功')
        visible.value = false
        emit('success')
    })
}
@@ -436,7 +523,7 @@
}
:deep(.el-step) {
    margin-bottom: 20px;
    margin-bottom: 90px;
}
:deep(.el-step__title) {
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue
@@ -66,7 +66,7 @@
            :model="formData"
            :rules="rules"
            :disabled="dialogReadonly"
            label-width="120px"
            label-width="130px"
        >
            <el-row>
                <el-col :span="12">
@@ -172,13 +172,11 @@
                        <el-input class="gd-input" v-model="formData.dataSource" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="24">
                <el-col :span="12">
                    <el-form-item label="需求信息项" prop="demandInfo">
                        <el-input
                            class="gd-input"
                            v-model="formData.demandInfo"
                            type="textarea"
                            :rows="4"
                            placeholder="请输入"
                            clearable
                        />
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue
@@ -75,10 +75,11 @@
                    <el-table-column prop="demandInfo" show-overflow-tooltip label="需求信息项" />
                    <el-table-column label="操作" class-name="operation-btns">
                        <template v-slot="{ row }">
                            <el-link @click="openForm('view', row)">查看</el-link>
                            <el-link @click="openForm('edit', row)" v-if="row.demandStatus !== '1'">编辑</el-link>
                            <el-link @click="handleDelete(row)" v-if="row.demandStatus !== '1'">删除</el-link>
                        </template>
                    <el-link @click="openForm('view', row)">查看</el-link>
                    <!-- 只对非审批状态显示编辑和删除按钮 -->
                    <el-link @click="openForm('edit', row)" v-if="!['1', '2', '3'].includes(row.demandStatus)">编辑</el-link>
                    <el-link @click="handleDelete(row)" v-if="!['1', '2', '3'].includes(row.demandStatus)">删除</el-link>
                </template>
                    </el-table-column>
                </el-table>
            </div>
@@ -96,7 +97,7 @@
        </div>
        <FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" />
        <ApplyViewDialog ref="applyDialogRef" v-if="applyDialogVisible" v-model="applyDialogVisible" />
        <ApplyViewDialog ref="applyDialogRef" @success="getList" v-if="applyDialogVisible" v-model="applyDialogVisible" />
    </basic-container>
</template>
<script setup>
@@ -192,8 +193,9 @@
// 新增/编辑/查看 弹框
function openForm(mode, row) {
    if (mode === 'view' && row?.demandStatus === '1') {
        // 如果是查看申请中的记录,使用申请详情弹框
    // 对于所有审批相关状态(申请中、审核通过、审核拒绝)都使用申请详情弹框
    if (mode === 'view' && ['1', '2', '3'].includes(row?.demandStatus)) {
        // 使用申请详情弹框
        openApplyViewDialog(row)
    } else {
        // 其他情况使用原有弹框
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue
New file
@@ -0,0 +1,91 @@
<template>
    <el-dialog
        class="gd-dialog"
        v-model="visible"
        :title="'拒绝申请'"
        @closed="visible = false"
        destroy-on-close
        width="550px"
        align-center
    >
        <div class="detail-container">
            <div class="detail-cell">
                <span class="cell-label">拒绝原因:</span>
                <el-input v-model="reasonForRejection" style="width: 380px" type="textarea" placeholder="请输入" />
            </div>
        </div>
        <template #footer>
            <!-- <el-button @click="handleCancel">取消</el-button> -->
            <el-button class="save-btn" color="#4C34FF" @click="handleConfirm">确认</el-button>
        </template>
    </el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
const props = defineProps({
    modelValue: {
        type: Boolean,
        default: false,
    },
})
const emit = defineEmits(['update:modelValue', 'confirm'])
const visible = ref(props.modelValue)
const reasonForRejection = ref('')
// 监听visible变化,同步到父组件
watch(
    () => visible.value,
    newVal => {
        emit('update:modelValue', newVal)
    }
)
// 监听父组件modelValue变化
watch(
    () => props.modelValue,
    newVal => {
        visible.value = newVal
    }
)
// 取消按钮点击事件
const handleCancel = () => {
    visible.value = false
    reasonForRejection.value = ''
}
// 确认按钮点击事件
const handleConfirm = () => {
    if (!reasonForRejection.value.trim()) {
        return ElMessage.warning('请输入拒绝原因')
    }
    emit('confirm', reasonForRejection.value)
    visible.value = false
    reasonForRejection.value = ''
}
</script>
<style scoped lang="scss">
.detail-container {
    padding: 20px;
    display: flex;
    align-items: flex-start;
    gap: 30px;
    .detail-cell {
        display: flex;
        justify-content: center;
        .cell-label {
            min-width: 80px;
            flex-shrink: 0;
        }
        :deep(.el-textarea__inner) {
            height: 100px !important;
        }
    }
}
</style>
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js
@@ -63,3 +63,12 @@
    
    })
}
// 获取供需需求审核记录
export const gdSupplyDemandAuditListApi = params => {
    return request({
        url: `/drone-gd/orderdata/gdSupplyDemandAudit/list`,
        method: 'get',
        params,
    })
}