riku
2025-09-11 307b17ef15c73a071912a262834f2a5f68e1fa87
完成走航季度报告自动生成
已修改3个文件
已添加1个文件
214 ■■■■■ 文件已修改
public/underway_season_report - 副本.docx 补丁 | 查看 | 原始文档 | blame | 历史
public/underway_season_report.docx 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/chart/chart-map.js 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/historymode/component/MissionReport.vue 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/underway_season_report - ¸±±¾.docx
Binary files differ
public/underway_season_report.docx
Binary files differ
src/utils/chart/chart-map.js
@@ -115,16 +115,6 @@
  chart.setOption(option);
  // å°†åƒç´ åæ ‡è½¬æ¢ä¸ºç»çº¬åº¦
  // const convert = (x, y) => {
  //   return chart.convertFromPixel(
  //     {
  //       geoIndex: 0
  //     },
  //     [x, y]
  //   );
  // };
  // å°†ç»çº¬åº¦è½¬æ¢ä¸ºåƒç´ åæ ‡
  const convert = (lng, lat) => {
    return chart.convertToPixel(
@@ -162,88 +152,12 @@
        pixelRatio: 2,
        backgroundColor: '#fff'
      });
      // é”€æ¯å®žä¾‹å¹¶ç§»é™¤ä¸´æ—¶DOM
      chart.dispose();
      document.body.removeChild(div);
      resolve(url);
    }, 1000);
  });
  // return captureMapByBounds({
  //   chart: chart,
  //   bounds: bounds
  // }).catch((err) => {
  //   console.error('截图失败:', err);
  // });
}
/**
 * æ ¹æ®ç»çº¬åº¦èŒƒå›´æˆªå–地图区域
 * @param {Object} params - æˆªå–参数
 * @param {Array} params.bounds - ç»çº¬åº¦èŒƒå›´ [minLng, minLat, maxLng, maxLat]
 * @param {Object} params.chart - ECharts实例
 * @returns {Promise<string>} æˆªå–区域的base64图片
 */
// function captureMapByBounds(params) {
//   const { bounds, chart } = params;
//   const [minLng, minLat, maxLng, maxLat] = bounds;
//   // èŽ·å–åœ°å›¾åæ ‡ç³»
//   // const geo = chart.getModel().getComponent('geo');
//   // if (!geo) return Promise.reject('未找到地图组件');
//   // å°†ç»çº¬åº¦è½¬æ¢ä¸ºåƒç´ åæ ‡
//   const convert = (lng, lat) => {
//     return chart.convertToPixel(
//       {
//         geoIndex: 0
//       },
//       [lng, lat]
//     );
//   };
//   // è®¡ç®—四个角的像素坐标
//   const topLeft = convert(minLng, maxLat);
//   const bottomRight = convert(maxLng, minLat);
//   // åˆ›å»ºä¸´æ—¶Canvas
//   const canvas = document.createElement('canvas');
//   const ctx = canvas.getContext('2d');
//   // èŽ·å–åŽŸå§‹å›¾è¡¨Canvas
//   const originalCanvas = chart.getDom().querySelector('canvas');
//   // è®¾ç½®Canvas尺寸为截取区域大小
//   topLeft[0] -= 10;
//   topLeft[1] -= 10;
//   bottomRight[0] += 10;
//   bottomRight[1] += 10;
//   topLeft[0] = Math.max(topLeft[0], 0);
//   topLeft[1] = Math.max(topLeft[1], 0);
//   bottomRight[0] = Math.min(bottomRight[0], originalCanvas.width);
//   bottomRight[1] = Math.min(bottomRight[1], originalCanvas.height);
//   const width = bottomRight[0] - topLeft[0];
//   const height = bottomRight[1] - topLeft[1];
//   canvas.width = width;
//   canvas.height = height;
//   // è£å‰ªæŒ‡å®šåŒºåŸŸ
//   ctx.drawImage(
//     originalCanvas,
//     topLeft[0],
//     topLeft[1], // æºå›¾åƒè£å‰ªèµ·ç‚¹
//     width,
//     height, // æºå›¾åƒè£å‰ªå°ºå¯¸
//     0,
//     0, // ç›®æ ‡å›¾åƒç»˜åˆ¶èµ·ç‚¹
//     width,
//     height // ç›®æ ‡å›¾åƒç»˜åˆ¶å°ºå¯¸
//   );
//   // è½¬æ¢ä¸ºbase64图片
//   return new Promise((resolve) => {
//     // å»¶è¿Ÿæ‰§è¡Œç¡®ä¿ç»˜åˆ¶å®Œæˆ
//     setTimeout(() => {
//       const base64 = canvas.toDataURL('image/png', 1.0);
//       resolve(base64);
//     }, 100);
//   });
// }
export default { generateGridMap };
src/views/historymode/component/MissionReport.vue
@@ -123,6 +123,7 @@
  srySceneCount: 5,
  sryProbByFactor:
    '颗粒物(PM)相关X处,占比 %,主要涉及工地扬尘污染问题、道路扬尘污染问题等;VOC相关X处,占比 %,主要涉及加油站油气泄露、餐饮油烟污染等',
  sryFocusRegion: '聚焦区域',
  missionInfoList: [
    {
      missionCode: '',
@@ -131,7 +132,8 @@
      _airQulity: 'AQI:30(优)',
      mainFactor: '',
      _abnormalFactors: '',
      sceneCount: 0
      sceneCount: 0,
      _kilometres: '1000'
    }
  ],
  missionDetailList: [
@@ -149,6 +151,7 @@
          avgValue: 38
        }
      ],
      _airQulity: 'AQI:30(优)',
      aqi: 30,
      pollutionDegree: '优'
    }
@@ -246,6 +249,7 @@
        return `${item.first}相关${item.second}处,占比 ${Math.round(item.third * 1000) / 10}%,主要涉及${getPollutingProblemTypes(item.first)}等`;
      })
      .join(';');
    templateParam.sryFocusRegion = res.data.focusRegion.join('、');
  });
}
@@ -257,18 +261,6 @@
      item._abnormalFactors = item.abnormalFactors
        .map((factor) => factor)
        .join('、');
      return item;
    });
  });
}
function generateMissionDetail(param) {
  return dataAnalysisApi.fetchMissionDetail(param).then((res) => {
    templateParam.missionDetailList = res.data.map((item, index) => {
      const t = formatDateTimeRange(item.startTime, item.endTime).split(' ');
      item._index = index + 1;
      item._startTime = t[0];
      item._time = t[1];
      item._kilometres = Math.round(item.kilometres / 1000);
      const keySceneMap = new Map();
@@ -285,16 +277,35 @@
            `${info.count}个${type}(${info.scenes.map((s) => s.name).join('、')})`
        )
        .join('、');
      item._dataStat = item.dataStatistics
        .map(
          (e) =>
            `${e.factor.des}(范围${e.minValue}–${e.maxValue}μg/m³,均值${e.avgValue}μg/m³)`
        )
        .join('、');
      item._focusScene =
        item.scenes.length > 0
          ? item.scenes.map((s) => s.name).join('、')
          : '道路交通密集区和部分施工周边';
      return item;
    });
  });
}
function generateMissionDetail(param) {
  return dataAnalysisApi.fetchMissionDetail(param).then((res) => {
    templateParam.missionDetailList = res.data.map((item, index) => {
      const t = formatDateTimeRange(item.startTime, item.endTime).split(' ');
      item._index = index + 1;
      item._startTime = t[0];
      item._time = t[1];
      item._kilometres = Math.round(item.kilometres / 1000);
      item._airQulity = `AQI:${item.aqi}(${item.pollutionDegree})`;
      const factorNames = radioOptions(TYPE0).map((e) => e.name);
      item._dataStatistics = item.dataStatistics.filter((e) => {
        return factorNames.indexOf(e.factor) != -1;
      });
      radioOptions(TYPE0).forEach((f) => {
        const _factor = item.dataStatistics.find((e) => e.factor == f.name);
        item[`avgValue_${f.name}`] = _factor?.avgValue ?? '-';
        item[`maxValue_${f.name}`] = _factor?.maxValue ?? '-';
        item[`minValue_${f.name}`] = _factor?.minValue ?? '-';
      });
      return item;
@@ -307,7 +318,7 @@
    templateParam.clueByAreaList = res.data.map((item, index) => {
      return {
        _index: index + 1,
        _area: item.sceneInfo.name + '周边',
        _area: `${item.sceneInfo.type}${item.sceneInfo.name}周边`,
        clueByFactorList: item.clueByFactorList.map((cbf) => {
          return {
            factor: cbf.factor,
@@ -395,10 +406,12 @@
        pollutionDegree: item.pollutionDegree,
        _areaDes: `走航区域经过${scenes.join('、')}`,
        _gridDes: `${item.gridLen}米正方形网格`,
        _missionDes: `${item.missionList.map((m) => m.missioncode).join('、')}${item.missionList.length}次`
        _missionDes: `${item.missionList.map((m) => m.missionCode).join('、')}共${item.missionList.length}次`
      };
      const _highRiskGridList = [];
      item.highRiskGridList.forEach((g, i) => {
        // const g = item.highRiskGridList[0];
        // const i = 0;
        const p = generateGridFusionImg(g.factorType, item.gridFusionList).then(
          (url) => {
            const { url1, url2 } = url;
@@ -414,7 +427,10 @@
              _boundsDes: `经度${g.bounds[0]}至${g.bounds[1]},纬度${g.bounds[2]}至${g.bounds[3]}`,
              // æ¶‰åŠè¡—镇
              town: g.town,
              _scenesDes: g.highRiskScenes.map((s) => s.name).join('、')
              _scenesDes:
                g.highRiskScenes.length > 0
                  ? `涉及的污染场景包括${g.highRiskScenes.map((s) => s.name).join('、')}`
                  : '网格内可能存在隐藏风险源'
            });
          }
        );
@@ -466,14 +482,16 @@
}
async function generateGridFusionImg(factorName, dataList) {
  var min = 1000000;
  var max = 0;
  let min = 1000000;
  let max = 0;
  dataList.forEach((v) => {
    min = Math.min(min, getGridDataDetailFactorValue(v.data, factorName));
    max = Math.max(max, getGridDataDetailFactorValue(v.data, factorName));
  });
  const gridData = dataList.map((v) => {
  const gridDataStand = [];
  const gridDataCustom = [];
  dataList.forEach((v) => {
    const data = getGridDataDetailFactorValue(v.data, factorName);
    const grid = v.cell;
@@ -503,36 +521,32 @@
      nextColor.map((v) => v * 255),
      ratio
    );
    return [
      {
        centerLng: grid.longitude,
        centerLat: grid.latitude,
        value: _color1,
        coordinates: [
          [grid.point1Lon, grid.point1Lat],
          [grid.point2Lon, grid.point2Lat],
          [grid.point3Lon, grid.point3Lat],
          [grid.point4Lon, grid.point4Lat]
        ]
      },
      {
        centerLng: grid.longitude,
        centerLat: grid.latitude,
        value: _color,
        coordinates: [
          [grid.point1Lon, grid.point1Lat],
          [grid.point2Lon, grid.point2Lat],
          [grid.point3Lon, grid.point3Lat],
          [grid.point4Lon, grid.point4Lat]
        ]
      }
    ];
    gridDataStand.push({
      centerLng: grid.longitude,
      centerLat: grid.latitude,
      value: _color1,
      coordinates: [
        [grid.point1Lon, grid.point1Lat],
        [grid.point2Lon, grid.point2Lat],
        [grid.point3Lon, grid.point3Lat],
        [grid.point4Lon, grid.point4Lat]
      ]
    });
    gridDataCustom.push({
      centerLng: grid.longitude,
      centerLat: grid.latitude,
      value: _color,
      coordinates: [
        [grid.point1Lon, grid.point1Lat],
        [grid.point2Lon, grid.point2Lat],
        [grid.point3Lon, grid.point3Lat],
        [grid.point4Lon, grid.point4Lat]
      ]
    });
  });
  if (gridData[0] == undefined || gridData[1] == undefined) {
    console.log(gridData);
  }
  const url1 = await chartMap.generateGridMap(gridData[0]);
  const url2 = await chartMap.generateGridMap(gridData[1]);
  const url1 = await chartMap.generateGridMap(gridDataStand);
  const url2 = await chartMap.generateGridMap(gridDataCustom);
  if (gridBase64Url.value == null) {
    gridBase64Url.value = url1;
  }