<template>
|
<div style="width: 100%; height: 100%">
|
<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">
|
<el-form-item label="方案名称:">
|
<el-input
|
v-model="forms.name"
|
style="max-width: 600px"
|
placeholder="Please input"
|
>
|
</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-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-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-select>
|
</el-form-item>
|
|
<el-form-item label="降雨量:">
|
<el-input
|
v-model="forms.rainfall"
|
style="max-width: 600px"
|
placeholder="Please input"
|
>
|
<template #append>mm</template>
|
</el-input>
|
</el-form-item>
|
|
<el-form-item label="降雨时长:">
|
<el-input
|
v-model="forms.duration"
|
style="max-width: 600px"
|
placeholder="Please input"
|
>
|
<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"
|
>
|
<template #append>mm/h</template>
|
</el-input>
|
</el-form-item>
|
|
<!-- <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>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { reactive, ref, watch, inject, computed } from "vue";
|
import * as XLSX from "xlsx";
|
import Papa from "papaparse";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import { initeWaterPrimitiveView } from "@/utils/water";
|
import { SimAPIStore } from "@/store/simAPI";
|
|
const simStore = SimAPIStore();
|
|
// 注入父组件提供的方法
|
const { startSimulate, endSimulate } = inject("simulateActions");
|
// 表单数据
|
const forms = reactive({
|
name: "",
|
eare: "北京市",
|
eares: "孙胡沟",
|
rainfall: "",
|
duration: "",
|
intensity: "",
|
fileList: [],
|
});
|
|
// 城市和重点区域选项
|
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 dialogTitle = computed(() => {
|
return simStore.selectTab === "行政区划仿真"
|
? "行政区划仿真"
|
: "重点区域仿真";
|
});
|
|
// 计算属性:获取上传文件的名称列表
|
const uploadedFilesText = computed(() => {
|
return forms.fileList.map((file) => file.name).join(", ") || "无";
|
});
|
|
//////////////////////////////////接口版本启用//////////////////////////////////
|
const openSaveDialog = async () => {
|
await simStore.openSaveDialog(forms);
|
};
|
|
// 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("正在保存,请稍候...");
|
// 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) => {
|
const reader = new FileReader();
|
reader.onload = (e) => {
|
const data = e.target.result;
|
if (file.name.endsWith(".csv")) {
|
parseCSV(data);
|
} else {
|
parseExcel(data);
|
}
|
};
|
reader.readAsArrayBuffer(file.raw);
|
};
|
|
// 解析CSV文件
|
const parseCSV = (data) => {
|
Papa.parse(new TextDecoder("utf-8").decode(data), {
|
complete: (results) => {
|
if (results.data.length > 0) {
|
processData(results.data);
|
}
|
},
|
header: true,
|
skipEmptyLines: true,
|
});
|
};
|
|
// 解析Excel文件
|
const parseExcel = (data) => {
|
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);
|
processData(jsonData);
|
};
|
|
// 处理数据
|
const processData = (data) => {
|
if (data.length === 0) return;
|
|
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; // 更新降雨量
|
};
|
|
// 解析日期时间
|
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();
|
}
|
}
|
|
const parsedDate = new Date(dateString);
|
if (!isNaN(parsedDate.getTime())) {
|
return parsedDate.getTime();
|
}
|
|
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 date = new Date(year, month, day, hour, minute, second);
|
if (!isNaN(date.getTime())) {
|
return date.getTime();
|
}
|
}
|
|
console.warn(`无法解析日期: ${dateString}`);
|
return NaN;
|
};
|
|
const handleExceed = () => {
|
ElMessage.warning("每次只能上传一个文件");
|
};
|
|
const beforeUpload = (file) => {
|
const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
|
const isCSV = file.name.endsWith(".csv");
|
if (!isExcel && !isCSV) {
|
ElMessage.error("只能上传Excel或CSV文件");
|
return false;
|
}
|
return true;
|
};
|
|
// 开始模拟
|
function startPlay() {
|
initeWaterPrimitiveView();
|
startSimulate();
|
}
|
</script>
|
|
<style lang="less" scoped>
|
.forms {
|
background: url("@/assets/img/screen/leftbg.png");
|
margin-top: 10px;
|
width: 100%;
|
height: 100%;
|
padding: 10px 10px 0px 0px;
|
box-sizing: border-box;
|
}
|
/deep/ .el-input-group__append,
|
.el-input-group__prepend {
|
background-color: #084b42;
|
color: #fff;
|
}
|
/deep/ .el-form-item__label {
|
color: #61f7d4 !important;
|
}
|
</style>
|