无人机管理后台前端(已迁走)
张含笑
2025-08-05 c832bf2e80ac465e71b7a1c1f7a59d4252030989
src/views/wel/components/flyratio.vue
@@ -2,24 +2,23 @@
  <div class="machineNest">
    <div class="nestTop">
      <div class="card-title">
        <img :src="jc1" alt="" />
        <div class="cardtotal">
          <p>机巢工单数量排名</p>
          <!-- <div class="total-number">111</div>
          <span>个</span> -->
           <img @click="refresh" src="/src/assets/images/workbench/st1.svg" alt="" />
        </div>
         <div class="time-card">
        <div
          class="card-item"
          :class="item === checked ? 'active' : ''"
          v-for="(item, index) in timeListEnum"
          :key="index"
          @click="timeClick(item, index)"
        >
          {{ timeListStr[index] }}
        </div>
      </div>
      <!-- <div class="status-grid">
        <div v-for="(item, index) in jcOrder" :key="index" class="status-item">
          <img :src="jc2" alt="" />
          <div>
            <div class="status-label">{{ item.name }}</div>
            <div :style="{ color: '#387FC8' }" class="status-value">
              {{ item.value }}
            </div>
          </div>
        </div>
      </div> -->
      </div>
    </div>
    <div class="nestCenter">
      <div class="chart" ref="echartsRef"></div>
@@ -33,6 +32,17 @@
import jc1 from '@/assets/images/workbench/jc1.png';
import jc2 from '@/assets/images/workbench/jc2.png';
import { industryJobNumPieChart } from '@/api/home/index';
import { nextTick } from 'vue';
let checked = ref('CURRENT_YEAR');
let timeListStr = ['本周', '本月', '本年'];
let timeListEnum = ['CURRENT_WEEK', 'CURRENT_MONTH', 'CURRENT_YEAR'];
const params = ref({
  date_enum: 'CURRENT_YEAR',
  device_sn: '',
  end_date: undefined,
  start_date: undefined,
});
const dateSelect = ref('CURRENT_YEAR');
const echartsRef = ref(null);
let { chart: jcchart } = useEchartsResize(echartsRef);
const jcOrder = ref([]);
@@ -41,15 +51,38 @@
    type: String,
  },
});
const params = reactive({
  date_enum: props.dateSelect,
});
const refresh = () => {
  // params.value.date_enum = 'CURRENT_YEAR';
  // checked.value = 'CURRENT_YEAR';
  // dateSelect.value = 'CURRENT_YEAR';
getIndustryJobNumPieChart();
};
let timeClick = (item, index) => {
  checked.value = item;
  params.value.date_enum = item;
  dateSelect.value = item;
getIndustryJobNumPieChart();
};
// 空数据计算
const isEmptyData = computed(() => {
  return jcOrder.value.length === 0 ||
         jcOrder.value.every(item => !item.name || item.value === 0)
})
// 图表初始化
const initChart = () => {
  if (echartsRef.value && !jcchart.value) {
    jcchart.value = echarts.init(echartsRef.value)
  }
}
// 获取机巢事件数据
const getIndustryJobNumPieChart = () => {
  industryJobNumPieChart(params).then(res => {
  industryJobNumPieChart(params.value).then(res => {
    const resList = res?.data?.data || [];
    jcOrder.value = resList;
    pieInit(resList);
     nextTick(() => {
        initChart()
        pieInit(resList)
      })
  });
};
watch(
@@ -61,111 +94,162 @@
  { immediate: true }
);
const pieInit = resList => {
  // 处理数据,过滤掉没有name的项
  const validData = resList.filter(item => item.name);
// if (!jcchart.value || !resList?.length) return
  const validData = resList?.filter(item => item.name).sort((a, b) => b.value - a.value); // 从大到小排序
  const colors = [
  '#F87E04',
  '#FFC400',
  '#08BC44',
  '#07B5FF',
  '#A98DFF',
  '#9ABFFF'
];
    '#F87E04', // 橙色
    '#FFC400', // 黄色
    '#08BC44', // 绿色
    '#07B5FF', // 蓝色
    '#A98DFF', // 紫色
    '#9ABFFF', // 浅蓝
  ];
  const optionData = {
    yAxisData: validData.map(item => item.name),
    seriesData: validData.map(item => item.value),
  };
  const option = {
    title: {
      text: resList.length  ? '' :'暂无数据',
      left: 'center',
      top: 'center',
      textStyle: {
        color: '#999',
        fontSize: '1.6rem',
        fontWeight: 'normal'
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow',
      },
      axisPointer: { type: 'shadow' },
      formatter: '{b}: {c}',
    },
    grid: {
      left: '3%',
      right: '4%',
      right: '3%',
      bottom: '3%',
         top: '-3%', // 添加顶部间距
      containLabel: true,
    },
    xAxis: {
      type: 'value',
      splitLine: {
        lineStyle: {
          color: '#E5E5E5',
        },
      },
      axisLabel: {
        color: '#35455aa6',
      },
      splitLine: { lineStyle: { color: '#E5E5E5' },show:false },
      axisLabel: { color: '#7C8091',fontSize:'1.2rem',show:false },
      boundaryGap: [0, 0.01],
    },
    yAxis: {
      type: 'category',
      data: optionData.yAxisData, // 使用处理后的分类数据
      axisLabel: {
        color: '#35455aa6',
      },
      axisLine: {
        lineStyle: {
          color: '#D1D1D1',
        },
      },
      axisTick: {
        show: false,
      },
      data: optionData.yAxisData,
      axisLabel: { color: '#7C8091' ,fontSize:'1.2rem',},
      axisLine: { lineStyle: { color: '#D1D1D1' } ,show:false},
      axisTick: { show: false },
      // 确保排序后的数据从上到下显示(最大值在顶部)
      inverse: true,
      show:optionData.seriesData?.length  ? true : false
    },
    series: [
      {
        type: 'bar',
        data: optionData.seriesData, // 使用处理后的数值数据
        data: optionData.seriesData,
        itemStyle: {
          // 修改为根据索引返回不同颜色
        color: (params) => {
          if (params.dataIndex < 5) {
            // 前5条使用固定颜色
            return colors[params.dataIndex % colors.length];
          }
          // 第6条及之后保持原渐变
          return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
            { offset: 0, color: '#93BAFF' },
            { offset: 1, color: '#C5DEFF' }
          ]);
        }
        barBorderRadius: [0, 20, 20, 0],
          color: params => {
            // 前6项使用固定颜色循环,之后使用渐变
            return params.dataIndex < colors.length
              ? colors[params.dataIndex]
              : new echarts.graphic.LinearGradient(0, 0, 1, 0, [
                  { offset: 0, color: '#93BAFF' },
                  { offset: 1, color: '#C5DEFF' },
                ]);
          },
        },
        barWidth: '30%',
        label: {
          show: true,
          position: 'right',
          formatter: '{c}',
          itemStyle:{
             fontSize: '1.4rem',
             color: '#414243',
          }
        },
      },
    ],
  };
  jcchart.value.setOption(option);
  jcchart.value.setOption(option, true);
};
onMounted(() => {
  getIndustryJobNumPieChart();
});
onBeforeUnmount(() => {
  if (jcchart.value) {
    jcchart.value.dispose()
    jcchart.value = null
  }
})
</script>
<style scoped lang="scss">
.machineNest {
width: 100%;
  width: 93%;
  margin-left: 10px;
  height: pxToVh(282);
    border-radius: 8px 8px 8px 8px;
  padding: 4px 14px 0 15px;
  background: #ffffff !important;
  .custom-text {
    font-size: 14px;
    color: #7c8091;
  }
  .nestTop {
    .card-title {
   .card-title {
    display: flex;
    margin-bottom: 10px;
    align-items: center;
    justify-content: space-between;
    .cardtotal {
      display: flex;
      margin-left: 57px;
      margin-bottom: 15px;
      align-items: center;
      img {
        width: 36px;
        height: 40px;
        width: 17px;
        height: 17px;
        margin-left: 6px;
        cursor: pointer;
      }
      p {
        font-weight: bold;
        font-size: 14px;
        color: #363636;
      }
      span {
        font-weight: 400;
        font-size: 14px;
        color: #7c8091;
      }
      .total-number {
        font-family: 'Source Han Sans CN';
        font-weight: bold;
        font-size: 32px;
        color: #2a54ff;
      }
    }
    img {
      width: 36px;
      height: 40px;
    }
  }
    .cardtotal {
      display: flex;
      align-items: center;
@@ -181,7 +265,7 @@
        color: #7c8091;
      }
      .total-number {
        font-family: 'YouSheBiaoTiHei';
        font-family: 'Source Han Sans CN';
        font-weight: bold;
        font-size: 32px;
        color: #2a54ff;
@@ -210,7 +294,7 @@
          color: #383838;
        }
        .status-value {
          font-family: 'YouSheBiaoTiHei';
          font-family: 'Source Han Sans CN';
          font-weight: bold;
          font-size: 20px;
        }
@@ -219,11 +303,51 @@
  }
  .nestCenter {
    width: 100%;
    height: 600px;
    height: pxToVh(226);
    .chart {
      width: 100%;
      height: 100%;
    }
  }
}
.time-card {
  text-align: center;
  // height: 30px;
  height: pxToVh(30);
  background: #ffffff;
  border: 1px solid #e5e5e5;
  font-weight: 400;
  font-size: 14px;
  color: #7c8091;
  display: flex;
  width: 282px;
  margin-left: 15px;
  border-radius: 4px;
  .card-item {
    width: 94px;
    height: 100%;
    line-height: 28px;
    cursor: pointer;
    font-family: 'Source Han Sans CN';
    font-weight: 400;
    font-size: 14px;
    color: #7c8091;
  }
  .card-item:first-child {
    border-right: 1px solid #e5e5e5;
  }
  .card-item:nth-child(2) {
    border-right: 1px solid #e5e5e5;
  }
  .card-item.active {
    color: #1441ff;
    border: 1px solid #1c5cff;
  }
}
</style>