forked from drone/command-center-dashboard

罗广辉
2025-03-31 46f05dd23583a4a4b58f136a4b6f2d32eb91be5a
Merge remote-tracking branch 'origin/master'
6 files modified
212 ■■■■ changed files
src/api/home/index.js 16 ●●●●● patch | view | raw | blame | history
src/api/home/machineNest.js 19 ●●●● patch | view | raw | blame | history
src/views/Home/components/HomeLeft/OverviewNext.vue 134 ●●●● patch | view | raw | blame | history
src/views/Home/components/HomeRight/Synergy.vue 14 ●●●●● patch | view | raw | blame | history
src/views/Home/components/HomeRight/TaskAchievements.vue 25 ●●●●● patch | view | raw | blame | history
src/views/SignMachineNest/components/MachineRight/InspectionRaskList.vue 4 ●●●● patch | view | raw | blame | history
src/api/home/index.js
@@ -45,3 +45,19 @@
    data
  });
};
// 任务成果
export const getMediaFileCountBy = () => {
  return request({
    url: 'blade-resource/media/api/v1/workspaces/files/getMediaFileCountBy',
    method: 'get',
  });
};
// 降本增效
export const optimizeCostEfficiency = () => {
  return request({
    url: 'drone-device-core/manage/api/v1/devices/optimizeCostEfficiency',
    method: 'get',
  });
};
src/api/home/machineNest.js
@@ -1,10 +1,21 @@
import request from '@/axios';
// 机巢列表
// 机巢统计
export const getDeviceInfoNum = () => {
  return request({
    url: '/manage/api/v1/devices/getDeviceInfoNum',
    method: 'post',
    url: 'drone-device-core/manage/api/v1/devices/getDeviceInfoNum',
    method: 'get',
    params: {},
  });
};
};
// 机巢列表
export const selectDevicePage = (params) => {
  return request({
    url: `drone-device-core/manage/api/v1/devices/selectDevicePage?type=${params.type}&current=${params.current}&size=${params.size}`,
    method: 'post',
    data: {
      nickname: params.nickname,
      is_execute: params.is_execute,
    },
  });
};
src/views/Home/components/HomeLeft/OverviewNext.vue
@@ -4,20 +4,20 @@
  <div class="overview-next">
    <div class="next-num">
      <div class="total">
        <div class="value">88</div>
        <div class="value">{{ total }}</div>
        <div class="name">机巢总数</div>
      </div>
      <div class="status">
        <div v-for="item in list">
        <div v-for="item in listNum">
          <div :style="{ color: item.color }" class="value">{{ item.value }}</div>
          <div class="name">{{ item.name }}</div>
        </div>
      </div>
    </div>
    <div class="search-box">
      <el-input v-model="searchText" placeholder="请输入搜索内容" class="input-with-select">
      <el-input v-model="searchText" placeholder="请输入机巢名称" class="input-with-select">
        <template #append>
          <el-button :icon="Search" />
          <el-button :icon="Search" @click="searchNickName"/>
        </template>
      </el-input>
    </div>
@@ -26,44 +26,104 @@
        <div class="name">机巢名称</div>
        <div class="status">机巢状态</div>
      </div>
      <div class="table-item" v-for="item in tableList">
        <div class="name">
          <img class="yjzx-img" width="10" height="10" src="@/assets/images/home/homeLeft/table-zx.png" alt="" />
          <img width="13" height="15" src="@/assets/images/home/homeLeft/table-icon.png" alt="" />
          {{ item.name }}
      <div class="table-body" v-if="tableList.length > 0"
        infinite-scroll-distance="6"
        v-infinite-scroll="loadMore"
        :infinite-scroll-disabled="busy"
        infinite-scroll-immediate="true">
        <div class="table-item" v-for="item in tableList">
          <div class="name">
            <!-- <img class="yjzx-img" width="10" height="10" src="@/assets/images/home/homeLeft/table-zx.png" alt="" /> -->
            <img width="13" height="15" src="@/assets/images/home/homeLeft/table-icon.png" alt="" />
            {{ item.nickname }}
          </div>
          <div class="status" :class="item.status==='WORKING'?'atcive':''" @click="signMachineNestClick">
            {{ item.status==='OFFLINE'?'离线中':(item.status==='WORKING'?'作业中':'空闲中') }}
          </div>
        </div>
        <div class="status" @click="signMachineNestClick">{{ item.status }}</div>
      </div>
      <el-empty class="custom-empty" v-else>
        <template #description>
          <span class="custom-text">暂无数据</span>
        </template>
      </el-empty>
    </div>
  </div>
</template>
<script setup>
import { Search } from '@element-plus/icons-vue';
import CommonTitle from '@/components/CommonTitle.vue';
import { getDeviceInfoNum } from '@/api/home/machineNest.js'
import { getDeviceInfoNum, selectDevicePage } from '@/api/home/machineNest.js'
import { useStore } from 'vuex';
const searchText = ref('')
const list = ref([
const store = useStore();
// 统计机巢总数
let total = ref(0);
// 机巢统计
let listNum = ref([
  { name: '执行中', value: 89, color: '#FFA768' },
  { name: '在线', value: 100, color: '#8EFFAC' },
  { name: '离线', value: 66, color: '#FFFFFF' },
  { name: '异常', value: 10, color: '#FF8E8E' },
  // { name: '异常', value: 10, color: '#FF8E8E' },
]);
const tableList = ref([
  { name: '小兰工业园3号', status: '预计执行' },
  { name: '小兰工业园3号', status: '正在执行' },
  { name: '小兰工业园3号', status: '预计执行' },
  { name: '小兰工业园3号', status: '预计执行' },
]);
// 获取机巢列表
const getList = () => {
  getDeviceInfoNum().then((res) => {
    console.log(res);
    if (res.data.code !== 0) return;
    let result = res.data.data;
    listNum.value[0].value = result.ex_num;
    listNum.value[1].value = result.leisure_num;
    listNum.value[2].value = result.offline_num;
    total.value = result.device_num;
  });
}
const store = useStore();
const isMore = ref(true);
// 控制加载状态
const busy = ref(false);
// 机巢搜索名称
const searchText = ref('')
// 分页参数
const pageParams = ref({
  current: 1,
  size: 5,
  total: 0
});
// 机巢列表
const tableList = ref([]);
// 机巢列表数据
const getTableList = () => {
  const params = {
    nickname: searchText.value,
    is_execute: false,
    type: 1,
    current: pageParams.value.current,
    size: pageParams.value.size
  };
  selectDevicePage(params).then((res) => {
    // if (res.data.code !== 0) return;
    if (res.data.data.records.length === 0) return (isMore.value = false);
    pageParams.value.current += 1;
    tableList.value = [...tableList.value, ...res.data.data.records];
    busy.value = false;
  });
}
// 加载更多数据
const loadMore = async () => {
    busy.value = true;
    if (!isMore.value) return;
    getTableList();
};
// 搜索数据
const searchNickName = () => {
  pageParams.value.current = 1;
  tableList.value = [];
  isMore.value = true
  getTableList();
}
// 单个机巢详情
const signMachineNestClick = () => {
@@ -78,6 +138,7 @@
onMounted(() => {
  getList();
  getTableList();
});
</script>
<style scoped lang="scss">
@@ -167,6 +228,7 @@
    margin: 16px;
    font-weight: 500;
    font-size: 16px;
    height: 220px;
    .table-header,
    .table-item {
      display: flex;
@@ -174,6 +236,21 @@
      height: 36px;
      line-height: 36px;
      padding: 0 20px;
    }
    .table-header {
      background: linear-gradient( 90deg, rgba(12,45,92,1) 0%, #0C3B78 50%, rgba(12,45,92,1) 100%), linear-gradient( 90deg, rgba(12,45,92,1) 0%, rgba(12,45,92,1) 50%, rgba(12,45,92,1) 100%);
      border-radius: 0px 0px 0px 0px;
      // border: 1px solid;
    }
    .table-body {
      height: 190px;
      overflow: auto;
      &::-webkit-scrollbar {
        width: 0;
        display: none;
      }
      -ms-overflow-style: none;  /* IE and Edge */
      scrollbar-width: none;  /* Firefox */
    }
    .table-item {
      position: relative;
@@ -188,6 +265,15 @@
      }
      .atcive {
        color: #04f020;
        background: linear-gradient( 90deg, rgba(12,45,92,1) 0%, #154671 50%, rgba(12,45,92,1) 100%), linear-gradient( 90deg, rgba(12,45,92,1) 0%, rgba(12,45,92,1) 50%, rgba(12,45,92,1) 100%);
      }
    }
    .custom-empty {
      margin: 16px 0;
      padding: 0;
      :deep(.el-empty__image) {
        width: 100px;
        height: 100px;
      }
    }
  }
src/views/Home/components/HomeRight/Synergy.vue
@@ -1,12 +1,26 @@
<script setup>
import CommonTitle from '@/components/CommonTitle.vue';
import { pxToRem } from '@/utils/rem';
import {  optimizeCostEfficiency } from '@/api/home/index.js'
const list = ref([
  { name: '替代人工(人次)', value: 1174, color: '#FFFFFF' },
  { name: '替代车辆(公里)', value: 2345, color: '#FFA768' },
  { name: '节约成本(万元)', value: 12.07, color: '#68FFC8' },
]);
const getStatisticalData = () => {
  optimizeCostEfficiency().then((res) => {
    if (res.data.code !== 200) return;
    let result = res.data.data
    list.value[0].value = result.replaced_manual_times;
    list.value[1].value = result.saved_vehicle_kilometers;
    list.value[2].value = result.total_cost_saved;
  });
};
onMounted(() => {
  getStatisticalData();
});
</script>
<template>
  <CommonTitle title="降本增效" />
src/views/Home/components/HomeRight/TaskAchievements.vue
@@ -5,10 +5,16 @@
import data2 from '@/assets/images/home/homeRight/data2.png';
import data3 from '@/assets/images/home/homeRight/data3.png';
import data4 from '@/assets/images/home/homeRight/data4.png';
import {  getMediaFileCountBy } from '@/api/home/index.js'
const detailsFun = () => {
  console.log('details');
};
// 照片总数
let photoNum = ref(0);
// 视频总数
let videoNum = ref(0);
const list = ref([
  { name: 'AI识别', value: '14656', color: '#6DD7FF', img: data1 },
@@ -16,6 +22,21 @@
  { name: '三维', value: '897', color: '#8EFFAC', img: data3 },
  { name: '正射', value: '1185', color: '#61FFFC', img: data4 },
]);
const getStatisticalData = () => {
  getMediaFileCountBy().then((res) => {
    if (res.data.code !== 0) return;
    let result = res.data.data
    list.value[0].value = result.aiNum;
    list.value[1].value = result.fullNum;
    list.value[2].value = result.gisNum;
    list.value[3].value = result.tifNum;
    photoNum.value = result.phoneNum;
    videoNum.value = result.videoNum;
  });
};
onMounted(() => {
  getStatisticalData();
});
</script>
<template>
  <CommonTitle title="任务成果" @details="detailsFun" />
@@ -28,11 +49,11 @@
          <div class="rawDataContent">
            <div>
              <div class="title">照片总数(张)</div>
              <div class="value">6582</div>
              <div class="value">{{ photoNum }}</div>
            </div>
            <div>
              <div class="title">视频总数(个)</div>
              <div class="value">4785</div>
              <div class="value">{{ videoNum }}</div>
            </div>
          </div>
        </div>
src/views/SignMachineNest/components/MachineRight/InspectionRaskList.vue
@@ -5,8 +5,8 @@
    <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 :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">