forked from drone/command-center-dashboard

张含笑
2025-04-19 cf95f7829bc0026b931f233f32358f156cde4313
src/views/SignMachineNest/MachineRight/InspectionRaskList.vue
@@ -1,355 +1,492 @@
<!-- 巡检任务列表 -->
<template>
  <CommonTitle title="巡检任务列表" />
  <div :style="{ marginLeft: pxToRem(14) }">
    <div class="inspection-rask-list">
      <div class="tab-search">
        <div class="tab-btn">
          <div :class="tabIndex===1?'active':''" @click="tabClick(1)">当前任务</div>
          <div :class="tabIndex===2?'active':''" @click="tabClick(2)">历史任务</div>
        </div>
        <div class="search-box">
          <el-input v-model="searchText" placeholder="请输入搜索内容" class="input-with-select">
            <template #append>
              <el-button :icon="Search" @click="searchNickName"/>
            </template>
          </el-input>
        </div>
      </div>
      <div class="table-list" v-if="tableList.length > 0"
        infinite-scroll-distance="6"
        v-infinite-scroll="loadMore"
        :infinite-scroll-disabled="busy"
        infinite-scroll-immediate="true">>
        <div class="item" v-for="(item,index) in tableList">
          <div class="left" @click="taskClick(item)">
            <div class="left-t">
              <span>{{ index+1 }}.</span>{{ item.name }}
              <span class="status" :class="item.status===2?'active':''">
                {{ getStatusText(item.status) }}
              </span>
            </div>
            <div class="left-b">
              <img src="../../../assets/images/signMachineNest/machineRight/date.png" alt="" />{{ item.begin_time }}
              <img src="../../../assets/images/signMachineNest/machineRight/name.png" alt="" />{{ item.creator_name || '' }}
            </div>
          </div>
          <div class="right" v-if="tabIndex===1" @click="reExecute(item.dock_sn)">
            <span>立即返航</span>
            <img src="../../../assets/images/signMachineNest/machineRight/return-fly.png" alt="">
          </div>
          <div class="right" v-else @click="returnImmediately(item.job_id)">
            <span>再次执行</span>
            <img src="../../../assets/images/signMachineNest/machineRight/return-fly.png" alt="">
          </div>
        </div>
      </div>
      <el-empty class="custom-empty" v-else>
        <template #description>
          <span class="custom-text">暂无数据</span>
        </template>
      </el-empty>
    </div>
  </div>
  <!-- 当前任务详情 -->
  <CurrentTaskDetails
      v-if="isShowCurrentTaskDetails"
      v-model:show="isShowCurrentTaskDetails"
      :id="currentInfoId"/>
   <CommonTitle title="巡检任务列表" />
   <div :style="{ marginLeft: pxToRem(14) }">
      <div class="inspection-rask-list">
         <div class="tab-search">
            <div class="tab-btn">
               <div :class="tabIndex === 1 ? 'active' : ''" @click="tabClick(1)">当前任务</div>
               <div :class="tabIndex === 2 ? 'active' : ''" @click="tabClick(2)">历史任务</div>
            </div>
            <div class="search-box">
               <el-input v-model="searchText" placeholder="请输入搜索内容" class="input-with-select">
                  <template #append>
                     <el-button :icon="Search" @click="searchNickName" />
                  </template>
               </el-input>
            </div>
         </div>
         <div
            class="table-list"
            v-if="tableList.length > 0"
            infinite-scroll-distance="6"
            v-infinite-scroll="loadMore"
            :infinite-scroll-disabled="busy"
            infinite-scroll-immediate="true"
         >
            >
            <div class="item" v-for="(item, index) in tableList">
               <div class="left" @click="taskClick(item)">
                  <div class="left-t">
                     <span>{{ index + 1 }}.</span>
                     {{ item.name }}
                     <span class="status" :class="item.status === 2 ? 'active' : ''">
                        {{ getStatusText(item.status) }}
                     </span>
                  </div>
                  <div class="left-b">
                     <img src="../../../assets/images/signMachineNest/machineRight/date.png" alt="" />
                     {{ item.begin_time }}
                     <img src="../../../assets/images/signMachineNest/machineRight/name.png" alt="" />
                     {{ item.creator_name || '' }}
                  </div>
               </div>
               <div class="right" v-if="tabIndex === 1" @click="reExecute(item.dock_sn)">
                  <span>立即返航</span>
                  <img src="../../../assets/images/signMachineNest/machineRight/return-fly.png" alt="" />
               </div>
               <div class="right" v-else @click="returnImmediately(item.job_id)">
                  <span>再次执行</span>
                  <img src="../../../assets/images/signMachineNest/machineRight/return-fly.png" alt="" />
               </div>
            </div>
         </div>
         <el-empty class="custom-empty" v-else>
            <template #description>
               <span class="custom-text">暂无数据</span>
            </template>
         </el-empty>
      </div>
   </div>
   <!-- 当前任务详情 -->
   <CurrentTaskDetails v-if="isShowCurrentTaskDetails" v-model:show="isShowCurrentTaskDetails" :id="currentInfoId" />
   <!-- 历史任务详情 -->
  <DeviceJobDetails
   <DeviceJobDetails
      v-if="isShowDeviceJobDetails"
      v-model:show="isShowDeviceJobDetails"
      :wayLineJodInfoId="wayLineJodInfoId"/>
      :wayLineJodInfoId="wayLineJodInfoId"
   />
</template>
<script setup>
import { Search } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import CommonTitle from '@/components/CommonTitle.vue';
import CurrentTaskDetails from '@/components/CurrentTaskDetails/CurrentTaskDetails.vue';
import { Search } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import CommonTitle from '@/components/CommonTitle.vue'
import CurrentTaskDetails from '@/components/CurrentTaskDetails/CurrentTaskDetails.vue'
import DeviceJobDetails from '@/components/DeviceJobDetails/DeviceJobDetails.vue'
import { getBeforeJob, getTodayJob, flyByJobId, returnHome } from '@/api/home';
import { useStore } from 'vuex';
import { getBeforeJob, getTodayJob, flyByJobId, returnHome } from '@/api/home'
import { useStore } from 'vuex'
import { useTaskWayline } from '@/hooks/useTaskWayline/useTaskWayline'
import { useTaskDetails } from '@/hooks/useTaskDetails/useTaskDetails'
let { taskDetails, workspace_id, getTaskDetails } = useTaskDetails()
const store = useStore();
const store = useStore()
// 设备任务详情
let currentInfoId = ref('');
let isShowCurrentTaskDetails = ref(false);
let wayLineJodInfoId = ref('');
let isShowDeviceJobDetails = ref(false);
let currentInfoId = ref('')
let isShowCurrentTaskDetails = ref(false)
let wayLineJodInfoId = ref('')
let isShowDeviceJobDetails = ref(false)
// 单个机巢信息
const singleUavHome = computed(() => store.state.home.singleUavHome);
const singleUavHome = computed(() => store.state.home.singleUavHome)
const isMore = ref(true);
const isMore = ref(true)
// 控制加载状态
const busy = ref(false);
const busy = ref(false)
let searchText = ref('')
const tableList = ref([]);
const tableList = ref([])
// 分页
const pageParams = ref({
  current: 1,
  size: 5,
  total: 0
});
   current: 1,
   size: 5,
   total: 0,
})
// 当前任务和历史任务切换
let tabIndex = ref(1);
const tabClick = (value) => {
  tabIndex.value = value;
  clearData();
};
let tabIndex = ref(1)
const tabClick = value => {
   tabIndex.value = value
   clearData()
}
// 状态文字判断
const getStatusText = (status) => {
  switch (status) {
    case 1:
      return '待执行';
    case 2:
      return '执行中';
    case 3:
      return '完成';
    case 4:
      return '取消';
    case 5:
      return '失败';
    default:
      return '未知';
  }
};
const getStatusText = status => {
   switch (status) {
      case 1:
         return '待执行'
      case 2:
         return '执行中'
      case 3:
         return '完成'
      case 4:
         return '取消'
      case 5:
         return '失败'
      default:
         return '未知'
   }
}
// 获取历史巡检任务列表
const getJobList = async () => {
  const params = {
    area_code: '',
    device_sn: singleUavHome.value.device_sn,
    job_name: searchText.value,
    current: pageParams.value.current,
    size: pageParams.value.size,
  }
  let result = null;
  if (tabIndex.value === 1) {
    result = await getTodayJob(params)
  } else {
    result = await getBeforeJob(params)
  }
  if (result.data.code !== 0) return;
  if (result.data.data.records.length === 0) return (isMore.value = false);
  pageParams.value.current += 1;
  tableList.value = [...tableList.value, ...result.data.data.records];
  busy.value = false;
   const params = {
      area_code: '',
      device_sn: singleUavHome.value.device_sn,
      job_name: searchText.value,
      current: pageParams.value.current,
      size: pageParams.value.size,
   }
   let result = null
   if (tabIndex.value === 1) {
      result = await getTodayJob(params)
   } else {
      result = await getBeforeJob(params)
   }
   if (result.data.code !== 0) return
   if (result.data.data.records.length === 0) return (isMore.value = false)
   pageParams.value.current += 1
   tableList.value = [...tableList.value, ...result.data.data.records]
   busy.value = false
}
// 清除数据
const clearData = () => {
  tableList.value = [];
  pageParams.value.current = 1;
  isMore.value = true;
  getJobList();
};
   tableList.value = []
   pageParams.value.current = 1
   isMore.value = true
   getJobList()
}
// 加载更多数据
const loadMore = async () => {
    busy.value = true;
    if (!isMore.value) return;
    getJobList();
};
   busy.value = true
   if (!isMore.value) return
   getJobList()
}
// 搜索数据
const searchNickName = () => {
  clearData();
};
   clearData()
}
// 立即返航
const returnImmediately = (id) => {
  flyByJobId(id).then(result => {
    if (result.data.code === 0) {
      ElMessage.success('执行成功');
    } else {
      ElMessage.error(result.data.message);
    }
  });
};
const returnImmediately = id => {
   flyByJobId(id).then(result => {
      if (result.data.code === 0) {
         ElMessage.success('执行成功')
      } else {
         ElMessage.error(result.data.message)
      }
   })
}
// 重新执行
const reExecute = (dock_sn) => {
  returnHome(dock_sn).then(result => {
    if (result.data.code === 0) {
      ElMessage.success('返航成功');
    } else {
      ElMessage.error(result.data.message);
    }
  });
};
const reExecute = dock_sn => {
   returnHome(dock_sn).then(result => {
      if (result.data.code === 0) {
         ElMessage.success('返航成功')
      } else {
         ElMessage.error(result.data.message)
      }
   })
}
// 点击当前任务显示当前任务详情
const taskClick = (item) => {
  if (tabIndex.value === 1) {
    // 展示当前任务详情
    currentInfoId.value = item.wayline_job_info_id;
    isShowCurrentTaskDetails.value = true;
  } else {
    // 展示历史任务详情
    wayLineJodInfoId.value = item.wayline_job_info_id;
    isShowDeviceJobDetails.value = true;
  }
};
const taskClick = item => {
   if (tabIndex.value === 1) {
      // 展示当前任务详情
      currentInfoId.value = item.wayline_job_info_id
      isShowCurrentTaskDetails.value = true
   } else {
      // 展示历史任务详情
      wayLineJodInfoId.value = item.wayline_job_info_id
      isShowDeviceJobDetails.value = true
   }
}
onMounted(() => {
  getJobList();
});
onMounted(async () => {
   await getJobList()
   // tableList.value = [
   //    {
   //       id: 11563,
   //       status: 5,
   //       begin_time: '2025/04/19 05:46:25',
   //       end_time: '2025/04/19 05:46:25',
   //       create_time: '2025-04-19T05:46:36.032+00:00',
   //       name: '智引即飞202504191252',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 340,
   //       job_id: '484a7846-60e0-4ec3-b9fb-272a055c6938',
   //    },
   //    {
   //       id: 11559,
   //       status: 5,
   //       begin_time: '2025/04/19 05:39:42',
   //       end_time: '2025/04/19 05:39:42',
   //       create_time: '2025-04-19T05:39:52.022+00:00',
   //       name: '智引即飞202504191252',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 340,
   //       job_id: 'b8c58bfb-4352-47c5-ba33-242eec8df188',
   //    },
   //    {
   //       id: 11558,
   //       status: 3,
   //       begin_time: '2025/04/19 05:39:17',
   //       end_time: '2025/04/19 05:39:17',
   //       create_time: '2025-04-19T05:39:27.407+00:00',
   //       name: '智引即飞202504191252',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 340,
   //       job_id: '839773ce-bd46-4947-a2ef-d859eaea82f6',
   //    },
   //    {
   //       id: 11557,
   //       status: 5,
   //       begin_time: '2025/04/19 04:52:04',
   //       end_time: '2025/04/19 04:52:04',
   //       create_time: '2025-04-19T04:52:14.503+00:00',
   //       name: '智引即飞202504191252',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 340,
   //       job_id: '58366fd4-8361-456f-8ad9-3b881f933620',
   //    },
   //    {
   //       id: 11556,
   //       status: 5,
   //       begin_time: '2025/04/19 03:45:06',
   //       end_time: '2025/04/19 03:45:06',
   //       create_time: '2025-04-19T03:45:16.522+00:00',
   //       name: '智引即飞202504191145',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 338,
   //       job_id: '39c60fb8-e5c4-4474-912a-c3af3f1b9054',
   //    },
   //    {
   //       id: 11555,
   //       status: 5,
   //       begin_time: '2025/04/19 03:27:55',
   //       end_time: '2025/04/19 03:27:55',
   //       create_time: '2025-04-19T03:28:05.196+00:00',
   //       name: '智引即飞202504191127',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 336,
   //       job_id: '78c42532-45e4-4a01-b698-69bca19286ff',
   //    },
   //    {
   //       id: 11554,
   //       status: 5,
   //       begin_time: '2025/04/19 02:58:53',
   //       end_time: '2025/04/19 02:58:53',
   //       create_time: '2025-04-19T02:59:03.602+00:00',
   //       name: '智引即飞202504191058',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 335,
   //       job_id: 'd3b25edc-ec23-4ad6-800a-0f659a72bff3',
   //    },
   //    {
   //       id: 11553,
   //       status: 5,
   //       begin_time: '2025/04/19 02:52:21',
   //       end_time: '2025/04/19 02:52:21',
   //       create_time: '2025-04-19T02:52:31.415+00:00',
   //       name: '智引即飞202504191052',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 334,
   //       job_id: 'e27090f1-e740-4ae4-8d4d-301354eb0bbc',
   //    },
   //    {
   //       id: 11548,
   //       status: 5,
   //       begin_time: '2025/04/19 02:23:06',
   //       end_time: '2025/04/19 02:23:06',
   //       create_time: '2025-04-19T02:23:16.151+00:00',
   //       name: '智引即飞202504191023',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 332,
   //       job_id: '9e1f7283-fe34-4cfd-b468-cd2b34a96d34',
   //    },
   //    {
   //       id: 11547,
   //       status: 3,
   //       begin_time: '2025/04/19 02:18:24',
   //       end_time: '2025/04/19 02:18:24',
   //       create_time: '2025-04-19T02:18:34.590+00:00',
   //       name: '智引即飞202504191018',
   //       event_number: 0,
   //       dock_sn: '7CTDLCR00BQBM2',
   //       wayline_job_info_id: 331,
   //       job_id: '7aa5222c-2f8b-401e-b6ba-d6a550398829',
   //    },
   // ]
   if (tableList.value.length > 0) {
      await getTaskDetails(tableList.value[0].wayline_job_info_id)
   }
})
useTaskWayline(window.$viewer, taskDetails)
</script>
<style lang="scss" scoped>
  .inspection-rask-list {
    width: 390px;
    height: 325px;
    background: linear-gradient(
      270deg,
      #1f3e7a 0%,
      rgba(31, 62, 122, 0.35) 79%,
      rgba(31, 62, 122, 0) 100%
    );
    opacity: 0.85;
    margin: 2px 0 13 0;
    padding: 11px 27px 0;
    .tab-search {
      width: 358px;
      height: 76px;
      margin-bottom: 12px;
      .tab-btn {
        display: flex;
        justify-content: center;
        margin-bottom: 16px;
        div {
          width: 104px;
          height: 32px;
          background: #0E2042;
          border: 1px solid #8EA3D1;
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 400;
          font-size: 16px;
          color: #8EA3D1;
          line-height: 32px;
          text-align: center;
          cursor: pointer;
        }
        .active {
          width: 104px;
          height: 32px;
          background: linear-gradient( 180deg, rgba(0,82,248,0.58) 0%, rgba(103,209,251,0.8) 100%);
          color: #fff;
          border: 1px solid rgba(103,209,251,0.8);
        }
      }
      .search-box {
        :deep(.el-input__wrapper) {
          background-color: rgba(0, 112, 255, 0.1);
          background: rgba(0, 15, 34, 0.5);
          box-shadow: 0 0 0 1px #0070ff inset;
        }
.inspection-rask-list {
   width: 390px;
   height: 325px;
   background: linear-gradient(270deg, #1f3e7a 0%, rgba(31, 62, 122, 0.35) 79%, rgba(31, 62, 122, 0) 100%);
   opacity: 0.85;
   margin: 2px 0 13 0;
   padding: 11px 27px 0;
   .tab-search {
      width: 358px;
      height: 76px;
      margin-bottom: 12px;
      .tab-btn {
         display: flex;
         justify-content: center;
         margin-bottom: 16px;
         div {
            width: 104px;
            height: 32px;
            background: #0e2042;
            border: 1px solid #8ea3d1;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 16px;
            color: #8ea3d1;
            line-height: 32px;
            text-align: center;
            cursor: pointer;
         }
         .active {
            width: 104px;
            height: 32px;
            background: linear-gradient(180deg, rgba(0, 82, 248, 0.58) 0%, rgba(103, 209, 251, 0.8) 100%);
            color: #fff;
            border: 1px solid rgba(103, 209, 251, 0.8);
         }
      }
      .search-box {
         :deep(.el-input__wrapper) {
            background-color: rgba(0, 112, 255, 0.1);
            background: rgba(0, 15, 34, 0.5);
            box-shadow: 0 0 0 1px #0070ff inset;
         }
        :deep(.el-input-group__append) {
          background: rgba(0, 112, 255, 0.38);
          .el-button {
            background-color: transparent;
            border: 1px solid #0070ff;
            border-left: none;
            color: #fff;
          }
        }
      }
    }
    .table-list {
      width: 358px;
      height: 202px;
      overflow: auto;
      &::-webkit-scrollbar {
        width: 0;
        display: none;
      }
      -ms-overflow-style: none;  /* IE and Edge */
      scrollbar-width: none;  /* Firefox */
      .item {
        width: 100%;
        height: 72px;
        padding: 12px 16px;
        margin-bottom: 8px;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 500;
        font-size: 14px;
        color: #fff;
        display: flex;
        justify-content: space-between;
        background: linear-gradient( 90deg, rgba(71,157,255,0) 0%, rgba(71, 157, 255, 0.12) 50%, rgba(71,157,255,0) 100%);
        .left {
          cursor: pointer;
          .left-t {
            height: 24px;
            font-size: 16px;
            margin-bottom: 4px;
            .status {
              text-align: center;
              font-size: 12px;
              display: inline-block;
              width: 48px;
              height: 20px;
              background: rgba(76,166,255,0.08);
              border-radius: 4px 4px 4px 4px;
              border: 1px solid #4CA6FF;
              color: #4CA6FF;
              margin-left: 10px;
            }
            .active {
              border: 1px solid #04F0D1;
              color: #04F0D1;
            }
          }
          .left-b {
            height: 21px;
            line-height: 21px;
            img {
              width: 16px;
              height: 16px;
              margin-right: 2px;
              &:last-child {
                margin-left: 42px;
              }
            }
          }
        }
        .right {
          cursor: pointer;
          position: relative;
          span {
            position: absolute;
            display: inline-block;
            top: 12px;
            left: 12px;
            width: 26px;
            line-height: 12px;
            font-size: 12px;
            font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
            color: rgb(4,18,44)
          }
          img {
            width: 46px;
            height: 46px
          }
        }
      }
    }
    .custom-empty {
      color: #fff;
      margin: 16px 0;
      padding: 0;
      :deep(.el-empty__image) {
        width: 100px;
        height: 100px;
      }
    }
 }
         :deep(.el-input-group__append) {
            background: rgba(0, 112, 255, 0.38);
            .el-button {
               background-color: transparent;
               border: 1px solid #0070ff;
               border-left: none;
               color: #fff;
            }
         }
      }
   }
   .table-list {
      width: 358px;
      height: 202px;
      overflow: auto;
      &::-webkit-scrollbar {
         width: 0;
         display: none;
      }
      -ms-overflow-style: none; /* IE and Edge */
      scrollbar-width: none; /* Firefox */
      .item {
         width: 100%;
         height: 72px;
         padding: 12px 16px;
         margin-bottom: 8px;
         font-family: Source Han Sans CN, Source Han Sans CN;
         font-weight: 500;
         font-size: 14px;
         color: #fff;
         display: flex;
         justify-content: space-between;
         background: linear-gradient(
            90deg,
            rgba(71, 157, 255, 0) 0%,
            rgba(71, 157, 255, 0.12) 50%,
            rgba(71, 157, 255, 0) 100%
         );
         .left {
            cursor: pointer;
            .left-t {
               height: 24px;
               font-size: 16px;
               margin-bottom: 4px;
               .status {
                  text-align: center;
                  font-size: 12px;
                  display: inline-block;
                  width: 48px;
                  height: 20px;
                  background: rgba(76, 166, 255, 0.08);
                  border-radius: 4px 4px 4px 4px;
                  border: 1px solid #4ca6ff;
                  color: #4ca6ff;
                  margin-left: 10px;
               }
               .active {
                  border: 1px solid #04f0d1;
                  color: #04f0d1;
               }
            }
            .left-b {
               height: 21px;
               line-height: 21px;
               img {
                  width: 16px;
                  height: 16px;
                  margin-right: 2px;
                  &:last-child {
                     margin-left: 42px;
                  }
               }
            }
         }
         .right {
            cursor: pointer;
            position: relative;
            span {
               position: absolute;
               display: inline-block;
               top: 12px;
               left: 12px;
               width: 26px;
               line-height: 12px;
               font-size: 12px;
               font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
               color: rgb(4, 18, 44);
            }
            img {
               width: 46px;
               height: 46px;
            }
         }
      }
   }
   .custom-empty {
      color: #fff;
      margin: 16px 0;
      padding: 0;
      :deep(.el-empty__image) {
         width: 100px;
         height: 100px;
      }
   }
}
</style>