兰宝车间质量管理系统-前端
baoshiwei
2025-05-20 e181f04c642204e79749af93fa921875ff6c21ba
src/views/qms/trend/quality.vue
@@ -299,6 +299,12 @@
    return;
  }
  // 检查测试项目是否选择
  if (!selectedTestItems.value.length) {
    proxy?.$modal.msgWarning("请选择测试项目!");
    return;
  }
  getList();
}
@@ -387,15 +393,43 @@
    '#ff6f61', '#ffd700', '#00ced1', '#da70d6', '#adff2f'
  ];
  // 使用Map替代Object更高效
  const seriesMap = new Map<string, [string, number][]>();
  testResultList.value.forEach(item => {
    const key = item.testItem;
    if (!seriesMap.has(key)) {
      seriesMap.set(key, []);
 // 使用Map替代Object更高效
const seriesMap = new Map<string, [string, number][]>();
testResultList.value.forEach((item) => {
  const key = item.testItem;
  const xValue = `${item.batchCode}-${item.testNum}`;
  if (!seriesMap.has(key)) {
    seriesMap.set(key, []);
  }
  const seriesArray = seriesMap.get(key)!;
  // 移除已有相同 xValue 的条目
  const filtered = seriesArray.filter(entry => entry[0] !== xValue);
  filtered.push([xValue, item.testValue]);
  seriesMap.set(key, filtered);
});
// 对每个 testItem 下的数据进行统一排序:先按 batchCode 再按 testNum
seriesMap.forEach((value, key) => {
  value.sort((a, b) => {
    const [batchA, testNumA] = a[0].split('-');
    const [batchB, testNumB] = b[0].split('-');
    // 先比较 batchCode(字符串比较)
    if (batchA !== batchB) {
      return batchA.localeCompare(batchB);
    }
    seriesMap.get(key)?.push([item.createTime, item.testValue]);
    // 再比较 testNum(转换为数字比较)
    return Number(testNumA) - Number(testNumB);
  });
  seriesMap.set(key, value);
});
  // 解析最后一条数据的判断条件字段
  let upperLimit: number | null = null;
@@ -426,101 +460,116 @@
  const option = {
    grid: {
      top: '15%',
      left: '5%',
      right: '5%',
      containLabel: true
  tooltip: {
    trigger: 'axis', // 按坐标轴触发,适用于折线图/柱状图等
    formatter: (items: any[]) => {
      const result: string[] = [];
      items.forEach(item => {
        result.push(`${item.marker} ${item.seriesName}<br/>`);
        result.push(`序号:${item.name}<br/>`);
        result.push(`测试数据:${item.value[1]}<br/>`);
      });
      return result.join('');
    },
    xAxis: {
      type: 'time',
      name: '时间'
    backgroundColor: 'rgba(255, 255, 255, 0.9)',
    borderColor: '#ccc',
    textStyle: {
      color: '#333'
    }
  },
  grid: {
    top: '15%',
    left: '5%',
    right: '5%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    name: '序号',
    data: Array.from(seriesMap.values())[0]?.map(item => item[0]) || [] // 使用排序后的 x 值
  },
  yAxis: {
    type: 'value',
    name: '测试数据',
    min: newLowerLimit,
    max: newUpperLimit,
    axisLabel: {
      formatter: function (value: number) {
        return value;
      }
    }
  },
  legend: {
    data: Array.from(seriesMap.keys())
  },
  series: Array.from(seriesMap).map(([name, data], index) => ({
    name: name,
    data: data,
    type: 'line',
    animationDuration: 1000,
    lineStyle: {
      color: colorPool[index % colorPool.length],
      width: 2
    },
    yAxis: {
      type: 'value',
      name: '测试数据',
      min: newLowerLimit, // 使用新的下限值
      max: newUpperLimit, // 使用新的上限值
      axisLabel: {
        formatter: function (value: number) {
          return value;
    itemStyle: {
      color: colorPool[index % colorPool.length],
      opacity: 0.8
    },
    markLine: {
      symbol: ['none', 'none'],
      label: {
        position: 'end',
        align: 'center',
        formatter: function (params: any) {
          const name = params.name || '';
          const value = params.value || '';
          return `${name}\n${value}`;
        }
      }
    },
    legend: {
      data: Array.from(seriesMap.keys())
    },
    series: Array.from(seriesMap).map(([name, data], index) => ({
      name: name,
      data: data,
      type: 'line',
      animationDuration: 1000,
      },
      lineStyle: {
        color: colorPool[index % colorPool.length],
        width: 2 // 增加线条宽度
        color: 'red',
        type: 'dashed'
      },
      itemStyle: {
        color: colorPool[index % colorPool.length],
        opacity: 0.8 // 添加透明度
      },
      markLine: {
        symbol: ['none', 'none'],
        label: {
          position: 'end',
          align: 'center', // 添加 align 属性以实现居中对齐
          formatter: function (params: any) {
            const name = params.name || ''; // 上限或下限标识
            const value = params.value || ''; // 对应的数值
            return `${name}\n${value}`; // 换行显示,确保上下行内容清晰
          }
      data: [
        {
          name: '下限',
          yAxis: lowerLimit !== null ? lowerLimit : undefined
        },
        lineStyle: {
          color: 'red',
          type: 'dashed'
        },
        data: [
          {
            name: '下限',
            yAxis: lowerLimit !== null ? lowerLimit : undefined
          },
          {
            name: '上限',
            yAxis: upperLimit !== null ? upperLimit : undefined
          }
        ]
      },
      // markLine: {
      //   data: [{ type: 'average', name: 'Avg' }]
      // }
    })),
    // 新增 dataZoom 配置
    dataZoom: [
      {
        type: 'slider', // X轴滑动条
        xAxisIndex: 0,
        start: 0, // 初始范围起点百分比
        end: 100 // 初始范围终点百分比
      },
      {
        type: 'slider', // Y轴滑动条
        yAxisIndex: 0,
        start: 0, // 初始范围起点百分比
        end: 100 // 初始范围终点百分比
      },
      {
        type: 'inside', // X轴内置拖动和框选
        xAxisIndex: 0,
        start: 0,
        end: 100
      },
      {
        type: 'inside', // Y轴内置拖动和框选
        yAxisIndex: 0,
        start: 0,
        end: 100
      }
    ]
  };
        {
          name: '上限',
          yAxis: upperLimit !== null ? upperLimit : undefined
        }
      ]
    }
  })),
  dataZoom: [
    {
      type: 'slider',
      xAxisIndex: 0,
      start: 0,
      end: 100
    },
    {
      type: 'slider',
      yAxisIndex: 0,
      start: 0,
      end: 100
    },
    {
      type: 'inside',
      xAxisIndex: 0,
      start: 0,
      end: 100
    },
    {
      type: 'inside',
      yAxisIndex: 0,
      start: 0,
      end: 100
    }
  ]
};
  chart.setOption(option, true);
  window.addEventListener('resize', () => {