wangjuncheng
2025-06-24 4cd8a5eb7d58e711e37e43bb332e332159687324
Merge branch 'master' of http://103.135.160.14:9034/r/NslWeb
已修改2个文件
240 ■■■■ 文件已修改
src/store/simAPI.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/CitySim.vue 238 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simAPI.js
@@ -40,7 +40,7 @@
                return false
            }
            if (!forms.rainfall || !forms.intensity || !forms.duration) {
            if (!forms.rainfall || !forms.intensity || !forms.duration || !forms.intensityUnit) {
                ElMessage.warning('请确保表单均已填写')
                return false
            }
src/views/left/CitySim.vue
@@ -31,6 +31,7 @@
        </el-form-item>
        <el-form-item label="上传参数">
          <el-upload
            :on-remove="handleRemove"
            v-model:file-list="forms.fileList"
            class="upload-demo"
            :auto-upload="false"
@@ -48,8 +49,9 @@
        <el-form-item label="雨强单位" v-if="forms.fileList.length !== 0">
          <el-select
            v-model="forms.intensityUnit"
            placeholder="Select"
            placeholder="请选择雨强单位"
            style="max-width: 600px"
            :disabled="!!forms.intensityUnit"
          >
            <el-option
              v-for="item in intensityOptions"
@@ -328,7 +330,6 @@
// 解析Excel文件
const parseExcel = (data) => {
  const workbook = XLSX.read(data, { type: "array" });
  console.log(workbook, "wokr");
  const firstSheetName = workbook.SheetNames[0];
  const worksheet = workbook.Sheets[firstSheetName];
  const jsonData = XLSX.utils.sheet_to_json(worksheet, {
@@ -337,14 +338,6 @@
  });
  processData(jsonData);
};
const transformKeys = (data) => {
  return data.map((item) => ({
    time: item["时间"], // "时间" → "time"
    intensity: parseFloat(item["小时雨强mm/h"]), // 转为浮点数
    total: parseFloat(item["累计雨量"]), // 转为浮点数
  }));
};
/**
@@ -379,58 +372,204 @@
  if (!header) return "";
  // 直接匹配 "mm/h"、"m/s" 等常见单位
  const unitRegex = /(mm\/h|m\/s|mm|℃|%|hPa|km\/h)/; // 根据需要扩展
  const unitRegex = /(mm\/h|mm\/1min|mm\/5min|mm\/15min)/; // 根据需要扩展
  const match = header.match(unitRegex);
  return match ? match[0] : "";
};
// 处理数据
const transformKeys = (data) => {
  return data.map((item) => ({
    time: item["时间"], // "时间" → "time"
    intensity: parseFloat(item["小时雨强"]), // 转为浮点数
    total: parseFloat(item["累计雨量"]), // 转为浮点数
  }));
};
// 可配置的字段名匹配规则
const COLUMN_MATCH_RULES = {
  time: ["时间", "time", "datetime", "date"],
  intensity: [
    "雨强",
    "小时雨强",
    "rain_intensity",
    "rain_rate",
    "hour_rain",
    "降雨强度",
  ],
  totalRainfall: [
    "累计雨量",
    "总雨量",
    "total_rain",
    "cumulative_rainfall",
    "降雨总量",
  ],
};
/**
 * 自动匹配字段名
 * @param {Object} headers - 表头对象(第一行)
 * @returns {{time: string, intensity: string, totalRainfall: string}}
 */
function matchColumns(headers) {
  const matched = {
    time: null,
    intensity: null,
    totalRainfall: null,
  };
  for (const header of Object.keys(headers)) {
    const cleanHeader = header.trim();
    if (
      !matched.time &&
      COLUMN_MATCH_RULES.time.some((k) => cleanHeader.includes(k))
    ) {
      matched.time = header;
    }
    if (
      !matched.intensity &&
      COLUMN_MATCH_RULES.intensity.some((k) => cleanHeader.includes(k))
    ) {
      matched.intensity = header;
    }
    if (
      !matched.totalRainfall &&
      COLUMN_MATCH_RULES.totalRainfall.some((k) => cleanHeader.includes(k))
    ) {
      matched.totalRainfall = header;
    }
  }
  return matched;
}
/**
 * 数据处理主函数
 */
const processData = (data) => {
  // 1. 检查数据是否为空
  // 检查空数据
  if (data.length === 0) {
    ElMessage.warning("文件内容为空!");
    return;
  }
  // 2. 获取表头(第一列是时间列)
  const tableColumns = Object.keys(data[0]);
  const timeColumn = tableColumns[0]; // 假设第一列是时间
  // 匹配字段名
  const columns = matchColumns(data[0]);
  // 3. 校验时间列是否按升序排列
  if (!isTimeColumnSorted(data, timeColumn)) {
    ElMessage.error("时间列必须按升序排列!");
  // 校验必要字段是否存在
  if (!columns.time) {
    ElMessage.error(
      "未找到有效的时间列,请检查列名是否为“时间”或其他支持的格式"
    );
    forms.fileList = [];
    return; // 终止处理
    return;
  }
  const intensityColumn = tableColumns[1]; // 雨强列(如 "小时雨强(mm/h)")
  console.log(intensityColumn, "intensityColumnintensityColumnintensityColumn");
  // 3. 提取第二列的单位(如 "(mm/h)" → "mm/h")
  const intensityUnit = extractUnitFromHeader(intensityColumn);
  forms.intensityUnit = intensityUnit; // 存储单位(可选)
  if (!columns.intensity) {
    ElMessage.error(
      "未找到有效的雨强列,请检查列名是否为“小时雨强”或其他支持的格式"
    );
    forms.fileList = [];
    return;
  }
  // 4. 如果校验通过,继续处理数据
  forms.rainFallList = transformKeys(data);
  console.log(forms.rainFallList, "data");
  // 时间列校验是否升序
  if (!isTimeColumnSorted(data, columns.time)) {
    ElMessage.error("时间列必须按升序排列!");
    forms.fileList = [];
    return;
  }
  // 5. 计算降雨时长、最大雨强、累计雨量(原逻辑)
  const firstTime = parseDateTime(data[0][timeColumn]);
  const lastTime = parseDateTime(data[data.length - 1][timeColumn]);
  const timeDuration = Math.floor((lastTime - firstTime) / 1000);
  console.log(firstTime,lastTime,timeDuration,'aaaaaaaaaaaaaaaaaaaaaaaaaaaa')
  forms.duration = (timeDuration / 3600).toFixed(2);
  // 提取单位
  forms.intensityUnit = extractUnitFromHeader(columns.intensity);
  const maxValue = Math.max(
    ...data.map((row) => {
      const value = parseFloat(row[tableColumns[1]]);
      return isNaN(value) ? -Infinity : value;
    })
  if (!forms.intensityUnit) {
    forms.intensityUnit = "";
  }
  // 转换 key 名并转换数值类型
  forms.rainFallList = data.map((row) => ({
    time: row[columns.time],
    intensity: parseFloat(row[columns.intensity]),
    total: columns.totalRainfall
      ? parseFloat(row[columns.totalRainfall])
      : undefined,
  }));
  console.log(forms.rainFallList, "解析后的降雨数据");
  // 计算统计信息
  const firstTime = parseDateTime(data[0][columns.time]);
  const lastTime = parseDateTime(data[data.length - 1][columns.time]);
  const durationSeconds = Math.floor((lastTime - firstTime) / 1000);
  forms.duration = (durationSeconds / 3600).toFixed(2); // 小时
  const maxIntensity = Math.max(
    ...data
      .map((row) => parseFloat(row[columns.intensity]))
      .filter((v) => !isNaN(v))
  ).toFixed(2);
  forms.intensity = maxValue;
  forms.intensity = maxIntensity;
  const lastValue = data[data.length - 1][tableColumns[2]];
  forms.rainfall = lastValue;
  if (columns.totalRainfall) {
    const lastTotal = parseFloat(data[data.length - 1][columns.totalRainfall]);
    forms.rainfall = isNaN(lastTotal) ? 0 : lastTotal.toFixed(2);
  } else {
    forms.rainfall = 0;
  }
};
// // 处理数据
// const processData = (data) => {
//   // 1. 检查数据是否为空
//   if (data.length === 0) {
//     ElMessage.warning("文件内容为空!");
//     return;
//   }
//   // 2. 获取表头(第一列是时间列)
//   const tableColumns = Object.keys(data[0]);
//   const timeColumn = tableColumns[0]; // 假设第一列是时间
//   // 3. 校验时间列是否按升序排列
//   if (!isTimeColumnSorted(data, timeColumn)) {
//     ElMessage.error("时间列必须按升序排列!");
//     forms.fileList = [];
//     return; // 终止处理
//   }
//   const intensityColumn = tableColumns[1]; // 雨强列(如 "小时雨强(mm/h)")
//   // console.log(intensityColumn, "intensityColumnintensityColumnintensityColumn");
//   // 3. 提取第二列的单位(如 "(mm/h)" → "mm/h")
//   const intensityUnit = extractUnitFromHeader(intensityColumn);
//   forms.intensityUnit = intensityUnit; // 存储单位(可选)
//   console.log(forms.intensityUnit,'aaaaaaaaaaaaaaaaaaaaa')
//   // 4. 如果校验通过,继续处理数据
//   forms.rainFallList = transformKeys(data);
//   console.log(forms.rainFallList, "data");
//   // 5. 计算降雨时长、雨强、累计雨量(原逻辑)
//   const firstTime = parseDateTime(data[0][timeColumn]);
//   const lastTime = parseDateTime(data[data.length - 1][timeColumn]);
//   const timeDuration = Math.floor((lastTime - firstTime) / 1000);
//   // 降雨时长
//   forms.duration = (timeDuration / 3600).toFixed(2);
//   // 降雨强度
//   const maxValue = Math.max(
//     ...data.map((row) => {
//       const value = parseFloat(row[tableColumns[1]]);
//       return isNaN(value) ? -Infinity : value;
//     })
//   ).toFixed(2);
//   forms.intensity = maxValue;
//   const lastValue = data[data.length - 1][tableColumns[2]];
//   forms.rainfall = lastValue;
// };
/**
 * 解析日期时间字符串或Excel数字日期,返回时间戳(毫秒数)
@@ -487,6 +626,16 @@
  ElMessage.warning("每次只能上传一个文件");
};
const handleRemove = () => {
  forms.rainfall = null;
  forms.duration = null;
  forms.intensity = null;
  forms.fileList = [];
  forms.rainFallList = [];
  forms.hours = null;
  forms.intensityUnit = "";
};
const beforeUpload = (file) => {
  const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
  const isCSV = file.name.endsWith(".csv");
@@ -518,7 +667,7 @@
    // 关闭选择区域窗口、初始化视图并开始模拟
    EventBus.emit("close-selectArea");
    simStore.shouldPoll = true;
    // 暂时不在此处开始模拟,模拟都在方案列表中进行模拟
    // initeWaterPrimitiveView();
    // startSimulate();
@@ -557,4 +706,7 @@
/deep/ .el-form-item__label {
  color: #61f7d4 !important;
}
/deep/ .el-upload-list__item-file-name {
  white-space: normal;
}
</style>