From 66032f62b4a3b6a649fc02b392ae41278399b58b Mon Sep 17 00:00:00 2001
From: wangjuncheng <1>
Date: 星期二, 08 七月 2025 15:23:19 +0800
Subject: [PATCH] 添加打印加坝数据代码, 但调用被注释

---
 src/views/left/CitySim.vue |  856 ++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 571 insertions(+), 285 deletions(-)

diff --git a/src/views/left/CitySim.vue b/src/views/left/CitySim.vue
index 5fdc7bf..a4de983 100644
--- a/src/views/left/CitySim.vue
+++ b/src/views/left/CitySim.vue
@@ -1,102 +1,66 @@
 <template>
   <div style="width: 100%; height: 100%">
-    <div
-      class="left-top"
-      v-if="simStore.selectTab == '琛屾斂鍖哄垝浠跨湡'"
-      style="margin-top: 0px"
-    >
+    <div class="left-top" v-if="simStore.selectTab == '琛屾斂鍖哄垝浠跨湡'" style="margin-top: 0px">
       琛屾斂鍖哄垝浠跨湡锛�30m绮惧害锛�
     </div>
     <div class="left-top" v-if="simStore.selectTab == '閲嶇偣鍖哄煙浠跨湡'">
       閲嶇偣鍖哄煙浠跨湡锛�10m绮惧害锛�
     </div>
-    <div class="forms">
-      <el-form :model="forms" label-width="auto" style="max-width: 600px">
+    <div class="left-top" v-if="simStore.selectTab == '閲嶇偣娌熶豢鐪�'">
+      鍘嗗彶妯℃嫙
+    </div>
+
+    <div class="forms" :class="{ 'no-background': !showBackground }">
+      <el-form :rules="rules" :model="forms" label-width="auto" style="max-width: 600px">
         <el-form-item label="鏂规鍚嶇О:">
-          <el-input
-            v-model="forms.name"
-            style="max-width: 600px"
-            placeholder="Please input"
-          >
+          <el-input v-model="forms.name" style="max-width: 600px" placeholder="璇疯緭鍏ユ柟妗堝悕绉�">
           </el-input>
         </el-form-item>
         <el-form-item label="涓婁紶鍙傛暟">
-          <el-upload
-            v-model:file-list="forms.fileList"
-            class="upload-demo"
-            :auto-upload="false"
-            :multiple="false"
-            :on-change="handleFileChange"
-            :limit="1"
-            :on-exceed="handleExceed"
-            :before-upload="beforeUpload"
-            accept=".xlsx,.xls,.csv"
-          >
+          <el-upload :on-remove="handleRemove" v-model:file-list="forms.fileList" class="upload-demo"
+            :auto-upload="false" :multiple="false" :on-change="handleFileChange" :limit="1" :on-exceed="handleExceed"
+            :before-upload="beforeUpload" accept=".xlsx,.xls,.csv">
             <el-button type="primary">鐐瑰嚮涓婁紶闄嶉洦鏁版嵁</el-button>
             <template #append>mm/h</template>
           </el-upload>
         </el-form-item>
-        <el-form-item
-          label="琛屾斂鍖哄煙:"
-          v-if="simStore.selectTab == '琛屾斂鍖哄垝浠跨湡'"
-        >
-          <el-select
-            v-model="forms.eare"
-            placeholder="Select"
-            style="max-width: 600px"
-          >
-            <el-option
-              v-for="item in cityOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
+        <el-form-item label="闆ㄥ己鍗曚綅" v-if="forms.fileList.length !== 0">
+          <el-select v-model="forms.intensityUnit" placeholder="璇烽�夋嫨闆ㄥ己鍗曚綅" style="max-width: 600px"
+            :disabled="!!forms.intensityUnit">
+            <el-option v-for="item in intensityOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
-        <el-form-item
-          label="閲嶇偣鍖哄煙:"
-          v-if="simStore.selectTab == '閲嶇偣鍖哄煙浠跨湡'"
-        >
-          <el-select
-            v-model="forms.eares"
-            placeholder="Select"
-            style="max-width: 600px"
-          >
-            <el-option
-              v-for="item in earesOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
+        <el-form-item label="琛屾斂鍖哄煙:" v-if="simStore.selectTab == '琛屾斂鍖哄垝浠跨湡'">
+          <el-select @change="changeGeom" v-model="forms.geom" placeholder="璇烽�夋嫨妯℃嫙鍖哄煙" style="max-width: 600px">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="閲嶇偣鍖哄煙:" v-if="simStore.selectTab == '閲嶇偣鍖哄煙浠跨湡'">
+          <el-select @change="changeGeom" v-model="forms.geom" placeholder="璇烽�夋嫨妯℃嫙鍖哄煙" style="max-width: 600px">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item" />
           </el-select>
         </el-form-item>
 
         <el-form-item label="闄嶉洦閲�:">
-          <el-input
-            v-model="forms.rainfall"
-            style="max-width: 600px"
-            placeholder="Please input"
-          >
+          <el-input v-model="forms.rainfall" style="max-width: 600px" placeholder="璇疯緭鍏ラ檷闆ㄩ噺">
             <template #append>mm</template>
           </el-input>
         </el-form-item>
-
+        <el-form-item label="閫夋嫨鏃堕棿:">
+          <el-date-picker v-if="forms.fileList.length !== 0" v-model="forms.hours" type="datetime"
+            placeholder="璇烽�夋嫨寮�濮嬫椂闂�" />
+          <el-date-picker v-if="forms.fileList.length == 0" v-model="forms.hours" type="datetimerange"
+            start-placeholder="寮�濮嬫椂闂�" end-placeholder="缁撴潫鏃堕棿" format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd"
+            time-format="A hh:mm:ss" @change="change" />
+        </el-form-item>
         <el-form-item label="闄嶉洦鏃堕暱:">
-          <el-input
-            v-model="forms.duration"
-            style="max-width: 600px"
-            placeholder="Please input"
-          >
+          <el-input disabled v-model="forms.duration" style="max-width: 600px" placeholder="璇疯緭鍏ラ檷闆ㄦ椂闀�">
             <template #append>h</template>
           </el-input>
         </el-form-item>
 
         <el-form-item label="闄嶉洦寮哄害:">
-          <el-input
-            v-model="forms.intensity"
-            style="max-width: 600px"
-            placeholder="Please input"
-          >
+          <el-input v-model="forms.intensity" style="max-width: 600px" placeholder="璇疯緭鍏ラ檷闆ㄥ己搴�">
             <template #append>mm/h</template>
           </el-input>
         </el-form-item>
@@ -104,196 +68,157 @@
         <!-- <el-form-item label="浠跨湡鍙傛暟:"></el-form-item> -->
       </el-form>
       <div style="display: flex; justify-content: flex-end">
-        <el-button type="primary" @click="openSaveDialog">淇濆瓨鏂规</el-button>
-        <el-button type="success" @click="startPlay">寮�濮嬫ā鎷�</el-button>
+        <el-button type="primary" @click="addSimCheme">淇濆瓨鏂规</el-button>
+        <el-button type="success" @click="startPlay">淇濆瓨骞跺紑濮嬫ā鎷�</el-button>
       </div>
-      <!---------------------------- 淇濆瓨鏂规瀵硅瘽妗嗭紙鎺ュ彛鐗堟湰闇�鍒犻櫎锛� -------------------------------->
-      <!-- <el-dialog
-        v-model="saveDialogVisible"
-        :title="dialogTitle"
-        width="50%"
-        :before-close="handleClose"
-        custom-class="custom-dialog"
-      >
-        <div class="dialog-content">
-          <p><strong>妯℃嫙绫诲瀷锛�</strong>{{ dialogTitle }}</p>
-          <p v-if="disForm === '琛屾斂鍖哄垝浠跨湡'">
-            <strong>琛屾斂鍖哄煙锛�</strong>{{ forms.eare }}
-          </p>
-          <p v-if="disForm === '閲嶇偣鍖哄煙浠跨湡'">
-            <strong>閲嶇偣鍖哄煙锛�</strong>{{ forms.eares }}
-          </p>
-          <p><strong>闄嶉洦閲忥細</strong>{{ forms.rainfall }} mm</p>
-          <p><strong>闄嶉洦鏃堕暱锛�</strong>{{ forms.duration }} h</p>
-          <p><strong>闄嶉洦寮哄害锛�</strong>{{ forms.intensity }} mm/h</p>
-          <p><strong>涓婁紶鏂囦欢锛�</strong>{{ uploadedFilesText }}</p>
-        </div>
-        <template #footer>
-          <span class="dialog-footer">
-            <el-button @click="saveDialogVisible = false">鍙栨秷</el-button>
-            <el-button type="primary" @click="confirmSave">纭畾淇濆瓨</el-button>
-          </span>
-        </template>
-      </el-dialog> -->
     </div>
   </div>
 </template>
 
 <script setup>
-import { reactive, ref, watch, inject, computed } from "vue";
+import { reactive, ref, watch, inject, computed, onMounted } from "vue";
 import * as XLSX from "xlsx";
 import Papa from "papaparse";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { initeWaterPrimitiveView } from "@/utils/water";
-import { useSimStore } from "@/store/simulation";
+import { SimAPIStore } from "@/store/simAPI";
+import { getRegionData, getSimStart, getSimDataById } from "@/api/trApi";
 
-const simStore = useSimStore();
+import { storeToRefs } from "pinia";
+import dayjs from "dayjs";
+import { EventBus } from "@/eventBus"; // 寮曞叆浜嬩欢鎬荤嚎
+
+const simStore = SimAPIStore();
+const { selectTab } = storeToRefs(simStore);
+
+const options = reactive([]);
+
+// 鍘嗗彶妯℃嫙閫変腑鍖哄煙
+const props = defineProps({
+  selectedArea: {
+    type: Object,
+    required: true,
+  },
+});
+
+const intensityOptions = ref([
+  { value: "mm/h", label: "mm/h" },
+  { value: "mm/5min", label: "mm/5min" },
+  { value: "mm/min", label: "mm/min" },
+]);
+
+// 瀹氫箟涓�涓柟娉曪紝鐢ㄤ簬鏍规嵁 type 鑾峰彇鍖哄煙鏁版嵁
+const fetchRegionData = (type) => {
+  getRegionData({ type: type }).then((res) => {
+    // 浣跨敤鍝嶅簲寮忔暟缁勭殑鏂规硶鏇存柊鍐呭
+    options.splice(
+      0,
+      options.length,
+      ...res.data.map((item) => ({
+        value: item.geom,
+        label: item.name,
+      }))
+    );
+  });
+};
+
+onMounted(() => {
+  fetchRegionData(1);
+});
+
+const showBackground = ref(true); // 榛樿鏄剧ず鑳屾櫙鍥�
+
+// 鐩戝惉 selectTab 鐨勫彉鍖�
+watch(selectTab, (newVal) => {
+  let type;
+  switch (newVal) {
+    case "琛屾斂鍖哄垝浠跨湡":
+      type = 1;
+      break;
+    case "閲嶇偣鍖哄煙浠跨湡":
+      type = 2;
+      break;
+    case "閲嶇偣娌熶豢鐪�":
+      type = 3;
+      break;
+    default:
+      type = 1; // 榛樿鍊�
+  }
+  // 鏍规嵁 type 璁剧疆鏄惁鏄剧ず鑳屾櫙鍥撅紙鍥犱负鍘嗗彶妯℃嫙涓〃鍗曞甫浜嗚儗鏅浘锛�
+  if (type == 3) {
+    showBackground.value = false;
+  } else {
+    showBackground.value = true;
+  }
+  fetchRegionData(type);
+  // Tab鍒囨崲鐨勬椂鍊欐竻绌鸿〃鍗�
+  resetForm();
+});
 
 // 娉ㄥ叆鐖剁粍浠舵彁渚涚殑鏂规硶
 const { startSimulate, endSimulate } = inject("simulateActions");
-const saveDialogVisible = ref(false); // 鎺у埗淇濆瓨鏂规瀵硅瘽妗嗙殑鏄剧ず鐘舵�侊紙鎺ュ彛鐗堟湰鍒犻櫎锛�
 // 琛ㄥ崟鏁版嵁
 const forms = reactive({
   name: "",
-  eare: "鍖椾含甯�",
-  eares: "瀛欒儭娌�",
-  rainfall: "",
-  duration: "",
-  intensity: "",
+  geom: "",
+  rainfall: null,
+  duration: null,
+  intensity: null,
   fileList: [],
+  type: 3,
+  rainFallList: [],
+  hours: null,
+  intensityUnit: "",
 });
 
-// 鍩庡競鍜岄噸鐐瑰尯鍩熼�夐」
-const cityOptions = [
-  { value: "鍖椾含甯�", label: "鍖椾含甯�" },
-  { value: "涓滃煄鍖�", label: "涓滃煄鍖�" },
-  { value: "瑗垮煄鍖�", label: "瑗垮煄鍖�" },
-  { value: "鏈濋槼鍖�", label: "鏈濋槼鍖�" },
-  { value: "娴锋穩鍖�", label: "娴锋穩鍖�" },
-  { value: "涓板彴鍖�", label: "涓板彴鍖�" },
-  { value: "鐭虫櫙灞卞尯", label: "鐭虫櫙灞卞尯" },
-  { value: "闂ㄥご娌熷尯", label: "闂ㄥご娌熷尯" },
-  { value: "鎴垮北鍖�", label: "鎴垮北鍖�" },
-  { value: "閫氬窞鍖�", label: "閫氬窞鍖�" },
-  { value: "椤轰箟鍖�", label: "椤轰箟鍖�" },
-  { value: "鏄屽钩鍖�", label: "鏄屽钩鍖�" },
-  { value: "澶у叴鍖�", label: "澶у叴鍖�" },
-  { value: "鎬�鏌斿尯", label: "鎬�鏌斿尯" },
-  { value: "骞宠胺鍖�", label: "骞宠胺鍖�" },
-  { value: "瀵嗕簯鍖�", label: "瀵嗕簯鍖�" },
-  { value: "寤跺簡鍖�", label: "寤跺簡鍖�" },
-];
-const earesOptions = [
-  { value: "瀛欒儭娌�", label: "瀛欒儭娌�" },
-  { value: "楸兼按娲炲悗娌�", label: "楸兼按娲炲悗娌�" },
-  { value: "浜庡瑗挎矡", label: "浜庡瑗挎矡" },
-  { value: "鍖楁渤娌�", label: "鍖楁渤娌�" },
-  { value: "榫欐硥宄潙", label: "榫欐硥宄潙" },
-];
+const flyHeight = ref(100000);
 
-// 璁$畻灞炴�э細鑾峰彇瀵硅瘽妗嗘爣棰�
-const dialogTitle = computed(() => {
-  return simStore.selectTab === "琛屾斂鍖哄垝浠跨湡"
-    ? "琛屾斂鍖哄垝浠跨湡"
-    : "閲嶇偣鍖哄煙浠跨湡";
-});
+// 灏嗛�変腑鍖哄煙浼犻�掔粰gisView鏂囦欢锛屽仛鏍囩孩flyTo鏄剧ず
+const changeGeom = (val) => {
+  if (selectTab.value == "琛屾斂鍖哄垝浠跨湡") {
+    flyHeight.value = 100000;
+  } else {
+    flyHeight.value = 5000;
+  }
+  EventBus.emit("select-geom", { geom: val.value, flyHeight: flyHeight.value });
+};
+
+const { calculateHoursDifference } = inject("calculateHours");
+
+const change = (val) => {
+  forms.duration = calculateHoursDifference(val);
+};
+
+const addSimCheme = async () => {
+  try {
+    if (selectTab.value == "閲嶇偣娌熶豢鐪�") {
+      forms.geom = props.selectedArea;
+    }
+    await simStore.addSimCheme(forms);
+    // 鎵撳嵃鎷︽尅鍧濇墍闇�瑕佺殑鏁版嵁
+    // printDamEntities();
+    resetForm(); // 鍙湁鍦ㄤ繚瀛樻垚鍔熷悗鎵嶉噸缃〃鍗�
+    EventBus.emit("close-selectArea");
+  } catch (error) { }
+};
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  forms.name = "";
+  forms.geom = "";
+  forms.rainfall = null;
+  forms.duration = null;
+  forms.intensity = null;
+  forms.fileList = [];
+  forms.rainFallList = [];
+  forms.hours = null;
+  forms.intensityUnit = "";
+};
 
 // 璁$畻灞炴�э細鑾峰彇涓婁紶鏂囦欢鐨勫悕绉板垪琛�
 const uploadedFilesText = computed(() => {
   return forms.fileList.map((file) => file.name).join(", ") || "鏃�";
 });
-
-////////////////////////////////////// 鎺ュ彛鐗堟湰闇�鍒犻櫎//////////////////////////////////////
-// // 鎵撳紑淇濆瓨鏂规瀵硅瘽妗�
-// const openSaveDialog = () => {
-//   if (
-//     !forms.rainfall ||
-//     !forms.duration ||
-//     !forms.intensity ||
-//     (simStore.selectTab === "琛屾斂鍖哄垝浠跨湡" && !forms.eare) ||
-//     (simStore.selectTab === "閲嶇偣鍖哄煙浠跨湡" && !forms.eares)
-//   ) {
-//     ElMessage.warning("璇峰厛濉啓鎵�鏈夊繀濉」");
-//     return;
-//   }
-//   saveDialogVisible.value = true;
-// }
-// const handleClose = () => {
-//   saveDialogVisible.value = false;
-// };
-
-// // 纭淇濆瓨
-// const confirmSave = () => {
-//   console.log("淇濆瓨鏂规鎴愬姛", {
-//     妯℃嫙绫诲瀷: dialogTitle.value,
-//     琛屾斂鍖哄煙: simStore.selectTab === "琛屾斂鍖哄垝浠跨湡" ? forms.eare : null,
-//     閲嶇偣鍖哄煙: simStore.selectTab === "閲嶇偣鍖哄煙浠跨湡" ? forms.eares : null,
-//     闄嶉洦閲�: `${forms.rainfall} mm`,
-//     闄嶉洦鏃堕暱: `${forms.duration} h`,
-//     闄嶉洦寮哄害: `${forms.intensity} mm/h`,
-//     涓婁紶鏂囦欢: forms.fileList.map((file) => file.name),
-//   });
-//   ElMessage.success("鏂规宸蹭繚瀛�");
-//   saveDialogVisible.value = false;
-//   resetForm();
-// };
-////////////////////////////////////// 缁撴潫鍒犻櫎//////////////////////////////////////
-
-//////////////////////////////////鎺ュ彛鐗堟湰鍚敤//////////////////////////////////
-const isLoading = ref(false);
-// 淇濆瓨鏂规
-const openSaveDialog = () => {
-  if (
-    !forms.rainfall ||
-    !forms.duration ||
-    !forms.intensity ||
-    (simStore.selectTab === "琛屾斂鍖哄垝浠跨湡" && !forms.eare) ||
-    (simStore.selectTab === "閲嶇偣鍖哄煙浠跨湡" && !forms.eares)
-  ) {
-    ElMessage.warning("璇峰厛濉啓鎵�鏈夊繀濉」");
-    return;
-  }
-  ElMessageBox.confirm("纭畾瑕佷繚瀛樺綋鍓嶆柟妗堝悧?", dialogTitle.value, {
-    confirmButtonText: "纭畾",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(confirmSave)
-    .catch(() => {
-      ElMessage({
-        type: "info",
-        message: "宸插彇娑堜繚瀛�",
-      });
-    });
-};
-const confirmSave = async () => {
-  if (isLoading.value) {
-    ElMessage.warning("姝e湪淇濆瓨锛岃绋嶅��...");
-    return; // 闃叉閲嶅鎻愪氦
-  }
-  isLoading.value = true; // 寮�濮嬪姞杞界姸鎬�
-  try {
-    await simStore.createSimulation(forms); // 璋冪敤 Store 涓殑淇濆瓨鏂规硶
-    ElMessage.success("淇濆瓨鎴愬姛");
-    saveDialogVisible.value = true; // 鏄剧ず淇濆瓨瀵硅瘽妗嗭紙濡傛灉闇�瑕侊級
-  } catch (error) {
-    console.error("淇濆瓨澶辫触:", error);
-    ElMessage.error("淇濆瓨澶辫触锛岃绋嶅悗閲嶈瘯");
-  } finally {
-    isLoading.value = false; // 缁撴潫鍔犺浇鐘舵��
-  }
-};
-//////////////////////////////////鎺ュ彛鐗堟湰鍚敤//////////////////////////////////
-
-// 閲嶇疆琛ㄥ崟
-const resetForm = () => {
-  forms.eare = "鍖椾含甯�";
-  forms.eares = "瀛欒儭娌�";
-  forms.rainfall = "";
-  forms.duration = "";
-  forms.intensity = "";
-  forms.fileList = [];
-};
 
 // 鏂囦欢鍙樺寲鏃惰Е鍙戣В鏋�
 const handleFileChange = (file) => {
@@ -327,78 +252,352 @@
   const workbook = XLSX.read(data, { type: "array" });
   const firstSheetName = workbook.SheetNames[0];
   const worksheet = workbook.Sheets[firstSheetName];
-  const jsonData = XLSX.utils.sheet_to_json(worksheet);
+  const jsonData = XLSX.utils.sheet_to_json(worksheet, {
+    raw: false, // 浣跨敤鏍煎紡鍖栧瓧绗︿覆鑰屼笉鏄師濮嬪��
+    dateNF: "yyyy-mm-dd hh:mm:ss", // 鎸囧畾鏃ユ湡鏍煎紡
+  });
+
   processData(jsonData);
 };
 
-// 澶勭悊鏁版嵁
-const processData = (data) => {
-  if (data.length === 0) return;
+/**
+ * 妫�鏌ユ椂闂村垪鏄惁鎸夊崌搴忔帓鍒�
+ * @param {Array} data - 琛ㄦ牸鏁版嵁
+ * @param {string} timeColumn - 鏃堕棿鍒楃殑瀛楁鍚�
+ * @returns {boolean} - 鏄惁鎸夊崌搴忔帓鍒�
+ */
+const isTimeColumnSorted = (data, timeColumn) => {
+  for (let i = 1; i < data.length; i++) {
+    const prevTime = parseDateTime(data[i - 1][timeColumn]);
+    const currentTime = parseDateTime(data[i][timeColumn]);
 
-  const tableColumns = Object.keys(data[0]);
-
-  // 绗竴鍒楋細鏃堕棿
-  const firstTime = parseDateTime(data[0][tableColumns[0]]);
-  const lastTime = parseDateTime(data[data.length - 1][tableColumns[0]]);
-  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; // 鏇存柊闄嶉洦閲�
+    // 濡傛灉鍓嶄竴涓椂闂� > 褰撳墠鏃堕棿锛岃鏄庝笉鏄崌搴�
+    if (prevTime > currentTime) {
+      console.error(`鏃堕棿涔卞簭锛氱 ${i} 琛宍, {
+        prevTime: new Date(prevTime),
+        currentTime: new Date(currentTime),
+      });
+      return false;
+    }
+  }
+  return true; // 鎵�鏈夋椂闂撮兘鎸夊崌搴忔帓鍒�
 };
 
-// 瑙f瀽鏃ユ湡鏃堕棿
-const parseDateTime = (dateString) => {
-  if (typeof dateString === "number") {
-    const parsedDate = XLSX.SSF.parse_date_code(dateString);
-    if (parsedDate) {
-      return new Date(
-        parsedDate.y,
-        parsedDate.m - 1,
-        parsedDate.d,
-        parsedDate.H || 0,
-        parsedDate.M || 0,
-        parsedDate.S || 0
-      ).getTime();
+/**
+ * 浠庤〃澶存彁鍙栧崟浣嶏紙濡� "灏忔椂闆ㄥ己mm/h" 鈫� "mm/h"锛�
+ * @param {string} header - 琛ㄥご瀛楃涓�
+ * @returns {string} - 鎻愬彇鐨勫崟浣嶏紙濡� "mm/h"锛夛紝榛樿杩斿洖绌哄瓧绗︿覆
+ */
+const extractUnitFromHeader = (header) => {
+  if (!header) return "";
+
+  // 鐩存帴鍖归厤 "mm/h"銆�"m/s" 绛夊父瑙佸崟浣�
+  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;
     }
   }
 
-  const parsedDate = new Date(dateString);
-  if (!isNaN(parsedDate.getTime())) {
-    return parsedDate.getTime();
+  return matched;
+}
+
+/**
+ * 鏁版嵁澶勭悊涓诲嚱鏁�
+ * @param {Array} data - 瑙f瀽鍚庣殑鍘熷鏁版嵁鏁扮粍锛屾瘡涓厓绱犳槸涓�涓璞�
+ */
+const processData = (data) => {
+  // 妫�鏌ユ槸鍚︿负绌烘暟鎹�
+  if (data.length === 0) {
+    ElMessage.warning("鏂囦欢鍐呭涓虹┖锛�");
+    return;
   }
 
-  const parts = dateString.split(/[/\s:]/);
-  if (parts.length >= 6) {
-    const year = parseInt(parts[0], 10);
-    const month = parseInt(parts[1], 10) - 1;
-    const day = parseInt(parts[2], 10);
-    const hour = parseInt(parts[3], 10) || 0;
-    const minute = parseInt(parts[4], 10) || 0;
-    const second = parseInt(parts[5], 10) || 0;
+  // 鍖归厤鍒楀悕锛堜緥濡傗�滄椂闂粹�濄�佲�滃皬鏃堕洦寮衡�濓級
+  const columns = matchColumns(data[0]);
 
+  // 鏍¢獙蹇呰瀛楁鏄惁瀛樺湪
+  if (!columns.time) {
+    ElMessage.error(
+      "鏈壘鍒版湁鏁堢殑鏃堕棿鍒楋紝璇锋鏌ュ垪鍚嶆槸鍚︿负鈥滄椂闂粹�濇垨鍏朵粬鏀寔鐨勬牸寮�"
+    );
+    forms.fileList = [];
+    return;
+  }
+
+  if (!columns.intensity) {
+    ElMessage.error(
+      "鏈壘鍒版湁鏁堢殑闆ㄥ己鍒楋紝璇锋鏌ュ垪鍚嶆槸鍚︿负鈥滃皬鏃堕洦寮衡�濇垨鍏朵粬鏀寔鐨勬牸寮�"
+    );
+    forms.fileList = [];
+    return;
+  }
+
+  // 鏍¢獙鏃堕棿鍒楁槸鍚﹀崌搴忔帓鍒�
+  if (!isTimeColumnSorted(data, columns.time)) {
+    ElMessage.error("鏃堕棿鍒楀繀椤绘寜鍗囧簭鎺掑垪锛�");
+    forms.fileList = [];
+    return;
+  }
+
+  // 鎻愬彇鍗曚綅锛堝 mm/h锛夛紝鑻ユ病鏈夊垯璁句负绌哄瓧绗︿覆
+  forms.intensityUnit = extractUnitFromHeader(columns.intensity) || "";
+
+  // 灏嗗師濮嬫暟鎹浆鎹负缁熶竴缁撴瀯鐨勫璞℃暟缁�
+  const rawRainFallList = data.map((row) => ({
+    time: row[columns.time],
+    intensity: parseFloat(row[columns.intensity]),
+    total: columns.totalRainfall
+      ? parseFloat(row[columns.totalRainfall])
+      : undefined,
+  }));
+
+  // 鏇存柊 forms.rainFallList锛屽彲鐢ㄤ簬鍥捐〃鏄剧ず绛夌敤閫�
+  forms.rainFallList = rawRainFallList;
+
+
+  // 鍒ゆ柇鏄惁涓烘暣灏忔椂鏁版嵁锛堝嵆鐩搁偦鏃堕棿闂撮殧鏄惁涓烘暣灏忔椂锛�
+  const isHourlyData = checkIfHourlyData(rawRainFallList);
+
+  let hourlyRainfallList = [];
+
+  if (!isHourlyData) {
+    // 濡傛灉涓嶆槸鏁村皬鏃舵暟鎹紝鎸夊皬鏃惰繘琛岃仛鍚堝鐞�
+    hourlyRainfallList = aggregateToHourlyRainfall(rawRainFallList);
+    console.log(hourlyRainfallList, "淇鍚庣殑灏忔椂闆ㄥ己");
+  } else {
+    // 濡傛灉鏄暣灏忔椂鏁版嵁锛岀洿鎺ヤ娇鐢ㄥ師濮嬮洦寮哄��
+    hourlyRainfallList = rawRainFallList.map((item) => ({
+      time: item.time,
+      intensity: item.intensity,
+    }));
+  }
+
+  // 璁$畻璧峰鏃堕棿鍜岀粨鏉熸椂闂达紙姣鏁帮級
+  const firstTime = parseDateTime(hourlyRainfallList[0]?.time);
+  const lastTime = parseDateTime(
+    hourlyRainfallList[hourlyRainfallList.length - 1]?.time
+  );
+
+  // 璁$畻鎸佺画鏃堕棿锛堝崟浣嶏細灏忔椂锛�
+  const durationSeconds = Math.floor((lastTime - firstTime) / 1000);
+  forms.duration = (durationSeconds / 3600).toFixed(2); // 鍗曚綅锛氬皬鏃�
+
+  // 鎵惧嚭鏈�澶у皬鏃堕洦寮�
+  const maxIntensity = Math.max(
+    ...hourlyRainfallList.map((item) => item.intensity).filter((v) => !isNaN(v))
+  ).toFixed(2);
+  forms.intensity = maxIntensity;
+
+  // 鑻ユ湁鎬婚檷闆ㄩ噺鍒楋紝鍙栧嚭鏈�鍚庝竴涓�间綔涓烘�婚檷闆ㄩ噺
+  if (columns.totalRainfall) {
+    const lastTotal = parseFloat(data[data.length - 1][columns.totalRainfall]);
+    forms.rainfall = isNaN(lastTotal) ? 0 : lastTotal.toFixed(2);
+  } else {
+    forms.rainfall = 0;
+  }
+};
+
+/**
+ * 妫�鏌ユ暟鎹槸鍚︿负鏁村皬鏃惰褰�
+ * @param {Array} rainList - 鍘熷闄嶉洦鏁版嵁鍒楄〃锛屾瘡涓厓绱犲寘鍚� time 鍜� intensity
+ * @returns {boolean} - 鏄惁涓烘暣灏忔椂鏁版嵁
+ */
+function checkIfHourlyData(rainList) {
+  if (rainList.length < 2) return true; // 鍙湁涓�涓偣锛岄粯璁よ涓烘暣灏忔椂鏁版嵁
+
+  for (let i = 1; i < rainList.length; i++) {
+    // 瑙f瀽涓や釜鐩搁偦鏃堕棿鐐�
+    const time1 = parseDateTime(rainList[i - 1].time);
+    const time2 = parseDateTime(rainList[i].time);
+
+    // 璁$畻鏃堕棿宸紙鍒嗛挓锛�
+    const diffMinutes = Math.abs(time2 - time1) / (1000 * 60);
+
+    // 濡傛灉鏃堕棿宸笉鏄暣灏忔椂锛堜笉鑳借60鏁撮櫎锛夛紝鍒欎笉鏄暣灏忔椂鏁版嵁
+    if (diffMinutes % 60 !== 0) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/**
+ * 灏嗕换鎰忔椂闂寸矑搴︾殑闆ㄥ己鏁版嵁锛屾寜灏忔椂鑱氬悎涓衡�滃皬鏃堕洦寮衡��
+ * @param {Array} rainList - 鍘熷鏁版嵁鍒楄〃锛屾瘡涓厓绱犲寘鍚� time 鍜� intensity
+ * @returns {Array} - 鎸夊皬鏃跺垎缁勭殑鑱氬悎缁撴灉
+ */
+function aggregateToHourlyRainfall(rainList) {
+  const grouped = {}; // 鐢ㄤ簬涓存椂瀛樺偍姣忎釜灏忔椂鐨勬暟鎹�
+
+  for (const item of rainList) {
+    // 瑙f瀽鏃堕棿瀛楃涓蹭负鏃堕棿鎴�
+    const timestamp = parseDateTime(item.time);
+
+    // 濡傛灉瑙f瀽澶辫触锛岃烦杩囧綋鍓嶉」
+    if (isNaN(timestamp)) {
+      console.warn("鏃犳晥鐨勬椂闂存牸寮忥紝宸茶烦杩�", item.time);
+      continue;
+    }
+
+    // 灏嗘椂闂存埑杞负 Date 瀵硅薄浠ヤ究鎿嶄綔鏃ユ湡
+    const dt = new Date(timestamp);
+
+    // 鏋勯�犲勾鏈堟棩+灏忔椂閿紙濡傦細"2024-08-25 14"锛�
+    const year = String(dt.getFullYear()).padStart(4, "0");
+    const month = String(dt.getMonth() + 1).padStart(2, "0"); // 娉ㄦ剰鏈堜唤浠�0寮�濮�
+    const date = String(dt.getDate()).padStart(2, "0");
+    const hour = String(dt.getHours()).padStart(2, "0");
+
+    const hourKey = `${year}-${month}-${date} ${hour}`;
+
+    // 鍒濆鍖栬灏忔椂鐨勮仛鍚堝璞�
+    if (!grouped[hourKey]) {
+      grouped[hourKey] = {
+        time: `${hourKey}:00:00`, // 鏍囧噯鍖栦负鏁寸偣鏃堕棿
+        intensity: 0,
+      };
+    }
+
+    // 绱姞璇ュ皬鏃跺唴鎵�鏈夐洦寮哄��
+    grouped[hourKey].intensity += item.intensity;
+  }
+
+  // 灏嗚仛鍚堢粨鏋滆浆涓烘暟缁勫苟淇濈暀涓や綅灏忔暟
+  const result = Object.values(grouped).map((item) => ({
+    time: item.time,
+    intensity: Number(item.intensity.toFixed(2)),
+  }));
+
+  return result;
+}
+/**
+ * 瑙f瀽鏃ユ湡鏃堕棿瀛楃涓叉垨Excel鏁板瓧鏃ユ湡锛岃繑鍥炴椂闂存埑锛堟绉掓暟锛�
+ * @param {string|number} dateString - 鏃ユ湡瀛楃涓叉垨Excel鏁板瓧鏃ユ湡
+ * @returns {number} 鏃堕棿鎴筹紙姣鏁帮級锛岃В鏋愬け璐ヨ繑鍥� NaN
+ */
+const parseDateTime = (dateString) => {
+  // 1. 澶勭悊 Excel 鏁板瓧鏃ユ湡锛堝 45136.91666666666锛夛紝浣嗘槸姝ゅ鎴戝湪Excel瑙f瀽鏃堕棿鐨勬椂鍊欏凡缁忚浆鎹簡锛屾墍浠ヨ繖涓殏鏃舵棤鐢�
+  if (typeof dateString === "number") {
+    // 浣跨敤 XLSX 宸ュ叿瑙f瀽 Excel 鏃ユ湡缂栫爜
+    const parsedDate = XLSX.SSF.parse_date_code(dateString);
+    if (parsedDate) {
+      // 杞崲涓� JavaScript Date 瀵硅薄骞惰繑鍥炴椂闂存埑
+      return new Date(
+        parsedDate.y, // 骞�
+        parsedDate.m - 1, // 鏈堬紙Excel 涓� 1-12锛孞S 涓� 0-11锛�
+        parsedDate.d, // 鏃�
+        parsedDate.H || 0, // 鏃讹紙鍙兘涓嶅瓨鍦紝榛樿涓� 0锛�
+        parsedDate.M || 0, // 鍒嗭紙鍙兘涓嶅瓨鍦紝榛樿涓� 0锛�
+        parsedDate.S || 0 // 绉掞紙鍙兘涓嶅瓨鍦紝榛樿涓� 0锛�
+      ).getTime(); // 杩斿洖鏃堕棿鎴�
+    }
+  }
+
+  // 2. 灏濊瘯鐩存帴瑙f瀽鏃ユ湡瀛楃涓诧紙濡� "2023-07-30T16:00:00"锛夛紝鐜板湪浣跨敤鐨勬槸杩欎釜
+  const parsedDate = new Date(dateString);
+  if (!isNaN(parsedDate.getTime())) {
+    return parsedDate.getTime(); // 杩斿洖鏈夋晥鏃堕棿鎴�
+  }
+
+  // 3. 澶勭悊鑷畾涔夋牸寮忕殑鏃ユ湡瀛楃涓诧紙濡� "2023/07/30 16:00:00"锛�
+  const parts = dateString.split(/[/\s:]/); // 鎸� `/`銆佺┖鏍笺�乣:` 鍒嗗壊
+  if (parts.length >= 6) {
+    const year = parseInt(parts[0], 10); // 骞�
+    const month = parseInt(parts[1], 10) - 1; // 鏈堬紙杞崲涓� JS 鐨� 0-11锛�
+    const day = parseInt(parts[2], 10); // 鏃�
+    const hour = parseInt(parts[3], 10) || 0; // 鏃讹紙榛樿 0锛�
+    const minute = parseInt(parts[4], 10) || 0; // 鍒嗭紙榛樿 0锛�
+    const second = parseInt(parts[5], 10) || 0; // 绉掞紙榛樿 0锛�
+
+    // 鏋勯�� Date 瀵硅薄骞惰繑鍥炴椂闂存埑
     const date = new Date(year, month, day, hour, minute, second);
     if (!isNaN(date.getTime())) {
       return date.getTime();
     }
   }
 
+  // 4. 瑙f瀽澶辫触鏃惰鍛婂苟杩斿洖 NaN
   console.warn(`鏃犳硶瑙f瀽鏃ユ湡: ${dateString}`);
   return NaN;
 };
 
 const handleExceed = () => {
   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) => {
@@ -411,11 +610,86 @@
   return true;
 };
 
-
 // 寮�濮嬫ā鎷�
-function startPlay() {
-  initeWaterPrimitiveView();
-  startSimulate();
+async function startPlay() {
+  try {
+    // 淇濆瓨鏂规
+    if (selectTab.value == "閲嶇偣娌熶豢鐪�") {
+      forms.geom = props.selectedArea;
+    }
+    const res = await simStore.addSimCheme(forms);
+    const schemeId = res.data?.data?.id;
+
+    if (!schemeId) {
+      ElMessage.error("鏂规淇濆瓨澶辫触锛屾湭鑾峰彇鍒版湁鏁� ID");
+      return;
+    }
+
+    // 璋冪敤姹傝В鍣�
+    const simStartRes = await getSimStart(schemeId);
+
+    // 鍏抽棴閫夋嫨鍖哄煙绐楀彛銆佸垵濮嬪寲瑙嗗浘骞跺紑濮嬫ā鎷�
+    EventBus.emit("close-selectArea");
+    simStore.shouldPoll = true;
+
+    // 鏆傛椂涓嶅湪姝ゅ寮�濮嬫ā鎷燂紝妯℃嫙閮藉湪鏂规鍒楄〃涓繘琛屾ā鎷�
+    // initeWaterPrimitiveView();
+    // startSimulate();
+
+    ElMessage.warning({
+      message: "璇疯繑鍥炴柟妗堝垪琛ㄧ瓑寰呮ā鎷熺粨鏋滐紒",
+      duration: 10000, // 鎻愮ず妗嗘樉绀烘椂闀匡紝鍗曚綅涓烘绉掞紝榛樿鏄�3000姣
+    });
+  } catch (error) {
+    console.error("鍚姩妯℃嫙杩囩▼涓彂鐢熼敊璇細", error);
+    // ElMessage.error("鍚姩妯℃嫙澶辫触锛岃绋嶅悗鍐嶈瘯");
+  }
+}
+// ========================================鎷︽尅鍧�===============================================================
+// 鑾峰彇鎷︽尅鍧濇暟鎹�
+function printDamEntities() {
+  const entities = viewer.entities.values;
+  const damDataList = [];
+
+  for (let i = 0; i < entities.length; i++) {
+    const entity = entities[i];
+
+    if (entity.name && (entity.name === '鏍忔。鍧�1' || entity.name === '鏍忔。鍧�2')) {
+      damDataList.push({
+        name: entity.name,
+        position: entity.position?._value,
+        heading: entity.heading?._value ?? entity.heading,
+        pitch: entity.pitch?._value ?? entity.pitch,
+        roll: entity.roll?._value ?? entity.roll,
+        modelScale: entity.model?.scale?._value ?? entity.model?.scale
+      });
+    }
+  }
+  if (damDataList.length > 0) {
+    console.log("銆愭爮妗e潩瀹炰綋鏁版嵁鍒楄〃銆戯細", damDataList);
+    deleteDamEntitiesAfterDelay();
+  } else {
+    console.log("鏈壘鍒颁换浣曞悕涓� '鏍忔。鍧�1' 鎴� '鏍忔。鍧�2' 鐨勫疄浣�");
+  }
+}
+// 淇濆瓨鏂规鍚庡畾鏃舵竻闄ゆ柊寤虹殑鎷︽尅鍧濇暟鎹�
+function deleteDamEntitiesAfterDelay() {
+  setTimeout(() => {
+    const entities = Array.from(viewer.entities.values);
+    const damsToDelete = entities.filter(
+      entity => entity.name === '鏍忔。鍧�1' || entity.name === '鏍忔。鍧�2'
+    );
+
+    damsToDelete.forEach(entity => {
+      viewer.entities.remove(entity);
+    });
+
+    if (damsToDelete.length > 0) {
+      console.log(`銆愬凡鍒犻櫎銆戝叡 ${damsToDelete.length} 涓爮妗e潩瀹炰綋`);
+    } else {
+      console.log("鏈壘鍒颁换浣曞彲鍒犻櫎鐨勬爮妗e潩瀹炰綋");
+    }
+  }, 5000);
 }
 </script>
 
@@ -427,13 +701,25 @@
   height: 100%;
   padding: 10px 10px 0px 0px;
   box-sizing: border-box;
+  transition: background 0.3s ease; // 鍙�夎繃娓℃晥鏋�
 }
+
+.forms.no-background {
+  margin-top: 0px;
+  background-image: none;
+}
+
 /deep/ .el-input-group__append,
 .el-input-group__prepend {
   background-color: #084b42;
   color: #fff;
 }
+
 /deep/ .el-form-item__label {
   color: #61f7d4 !important;
 }
+
+/deep/ .el-upload-list__item-file-name {
+  white-space: normal;
+}
 </style>

--
Gitblit v1.9.3