1
wangjuncheng
2025-06-30 e084592304b0499d05eaa31d59c463a8649352c2
src/components/monifangzhen/schemeInfo.vue
@@ -1,46 +1,27 @@
<template>
  <div class="listCard">
    <div class="left-top">
      <span>方案详情</span>
      <el-button class="clickable-text" @click="handleBack">结束模拟</el-button>
    </div>
    <div class="top"><span>方案详情</span></div>
    <div class="details">
      <div v-if="selectedScheme">
        <div class="input-group">
          <div class="input-item">
            <label>方案名称:</label>
            <span>{{ selectedScheme.name }}</span>
          </div>
          <div class="input-item">
            <label>创建时间:</label>
            <span>{{ formatTime(selectedScheme.createTime) }}</span>
          </div>
          <div class="input-item">
            <label>方案状态:</label>
            <span>{{ statusText[selectedScheme.taskStatus] || "未知" }}</span>
          </div>
          <div class="input-item">
            <label>开始时间:</label>
            <span>{{ selectedScheme.startTime }}</span>
          </div>
          <div class="input-item">
            <label>结束时间:</label>
            <span>{{ selectedScheme.endTime }}</span>
          </div>
          <div class="input-item">
            <label>文件数量:</label>
            <span>{{ selectedScheme.fileCount }}</span>
          </div>
          <div class="input-item">
            <label>输出周期:</label>
            <span>{{ selectedScheme.outputPeriod }} 秒</span>
          </div>
      <div v-if="formattedData.length" class="input-group">
        <div
          v-for="(item, index) in formattedData"
          :key="index"
          class="input-item"
        >
          <label>{{ item.name }}</label>
          <span
            :class="{ clickable: item.isClickable }"
            @click="item.isClickable ? openGaugeDialog(item.gauges) : null"
          >
            {{ item.value }}
          </span>
        </div>
      </div>
      <div v-else>
        <p style="text-align: center;">暂无方案信息</p>
        <p style="text-align: center">暂无方案信息</p>
      </div>
    </div>
    <div></div>
  </div>
  <Message
    @close="close"
@@ -48,46 +29,244 @@
    v-show="messageShow"
    :mesData="mesData"
  />
  <!-- 添加雨量计弹窗 -->
  <div class="dialoog">
    <el-dialog
      v-model="dialogVisible"
      title="雨量计详情"
      width="50%"
      :before-close="handleClose"
    >
      <div class="table-container">
        <el-table :data="gaugesData" border stripe height="100%">
          <el-table-column prop="name" label="名称"></el-table-column>
          <el-table-column prop="x" label="经度(X)"></el-table-column>
          <el-table-column prop="y" label="纬度(Y)"></el-table-column>
          <el-table-column prop="r" label="半径(r)"></el-table-column>
        </el-table>
      </div>
      <!-- <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">关闭</el-button>
        </span>
      </template> -->
    </el-dialog>
  </div>
</template>
<script setup>
import { defineProps, defineEmits, inject } from "vue";
import { defineProps, defineEmits, inject, ref, watch } from "vue";
import {
  ElDialog,
  ElTable,
  ElTableColumn,
  ElButton,
  ElMessage,
} from "element-plus";
import dayjs from "dayjs";
import { ElMessage } from 'element-plus'
// 定义 emit 方法
// 公共依赖
const props = defineProps({ selectedScheme: { type: Object, default: null } });
const emit = defineEmits(["back"]);
const { startSimulate, endSimulate } = inject("simulateActions");
const { endSimulate } = inject("simulateActions");
// 返回按钮点击事件
function handleBack() {
  ElMessage({
    message: '模拟进程正在关闭中...',
    type: 'success',
  })
  emit("back", false); // 向父组件传递 false 值
  endSimulate();
}
// 状态管理
const formattedData = ref([]);
// 接收父组件传递的 props
const props = defineProps({
  selectedScheme: {
    type: Object,
    default: null,
  },
});
// 格式化时间
function formatTime(time) {
  return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
}
// 定义任务状态的文本映射
const statusText = {
  0: "未开始",
  1: "进行中",
  2: "已完成",
// 映射表
const areaTypeMap = {
  0: "自定义区域仿真",
  1: "行政区划仿真",
  2: "重点区域仿真",
  3: "重点沟仿真",
};
const statusMap = {
  0: "创建仿真",
  1: "预处理",
  2: "分析中",
  10: "完成",
  20: "出错",
};
const typeMap = {
  1: "预测模拟",
  2: "实时模拟",
  3: "历史模拟",
};
// 跳过字段列表
const skipKeys = [
  "geom",
  "id",
  "serviceName",
  "updateTime",
  "updateUser",
  "createUser",
  "bak",
];
// 处理 data 字段解析
function parseDataField(dataStr) {
  if (typeof dataStr !== "string") return [];
  // console.log(dataStr, '方案详情内的降雨数据');
  try {
    const parsed = JSON.parse(dataStr);
    const fields = {
      total: "降雨总量(mm):",
      duration: "降雨时长(小时):",
      intensity: "降雨强度(mm/小时):", // 统一为 mm/h
      prediction: "降雨场次:",
      model: "降雨模式:",
      history: "历史降雨:",
    };
    let { total, duration, intensity, intensityUnit } = parsed;
    // 根据 intensityUnit 确定转换系数
    let factor = 1;
    switch (intensityUnit) {
      case "mm/min":
        factor = 60;
        break;
      case "mm/5min":
        factor = 12;
        break;
      case "mm/h":
        factor = 1;
        break;
      default:
        factor = 1;
    }
    // 转换单位:将 intensity 和 total 统一为按小时计算的值
    intensity = intensity != null ? (intensity * factor).toFixed(2) : "无";
    total = total != null ? (total * factor).toFixed(2) : "无";
    // 控制台输出你需要的关键字段
    // console.log('转换后的降雨强度(mm/h):', intensity);
    // console.log('转换后的降雨总量(mm):', total);
    // 处理 duration,如果非数字则设为默认值
    duration = duration != null ? parseInt(duration) : "无";
    const result = Object.entries(parsed)
      .filter(([k]) => fields[k])
      .map(([k, v]) => {
        let displayValue = v || "无";
        if (k === "total") displayValue = total;
        if (k === "duration") displayValue = duration;
        if (k === "intensity") displayValue = intensity;
        return {
          name: fields[k],
          value: displayValue,
        };
      });
    // 处理雨量计数据
    if (parsed.type == 2 && parsed.gauges && Array.isArray(parsed.gauges)) {
      const gaugeNames = parsed.gauges.map((g) => g.name).join(", ") || "无";
      result.push({
        name: "雨量计列表:",
        value: "查看雨量计列表",
        isClickable: true,
        gauges: parsed.gauges,
      });
    }
    return result;
  } catch (e) {
    console.error("解析 dataStr 出错:", e);
    return [{ name: "数据:", value: dataStr || "无" }];
  }
}
// 格式化时间戳
function formatDate(timestamp) {
  return dayjs(timestamp).format("YYYY-MM-DD HH:mm:ss");
}
// 格式化 selectedScheme 数据
watch(
  () => props.selectedScheme,
  (newScheme) => {
    if (!newScheme || typeof newScheme !== "object") {
      formattedData.value = [];
      return;
    }
    const entries = Object.entries(newScheme);
    const areaType = newScheme.areaType;
    // console.log(newScheme, "news");
    const result = entries.reduce((acc, [key, value]) => {
      if (skipKeys.includes(key)) return acc;
      switch (key) {
        case "createTime":
          acc.push({ name: "创建时间:", value: formatDate(value) });
          break;
        case "areaType":
          acc.push({ name: "区域类别:", value: areaTypeMap[value] || "未知" });
          break;
        case "status":
          acc.push({ name: "仿真状态:", value: statusMap[value] || "未知" });
          break;
        case "type":
          if (![1, 2].includes(areaType)) {
            acc.push({ name: "模拟类别:", value: typeMap[value] || "未知" });
          }
          break;
        case "areaName":
          acc.push({ name: "区域名称:", value: value || "无" });
          break;
        case "result":
          acc.push({ name: "仿真结果:", value: value || "无" });
          break;
        case "name":
          acc.push({ name: "仿真方案:", value: value || "无" });
          break;
        case "data":
          acc.push(...parseDataField(value));
          break;
        default:
          acc.push({ name: `${key}:`, value: value || "无" });
      }
      return acc;
    }, []);
    formattedData.value = result;
  },
  { immediate: true }
);
const dialogVisible = ref(false);
const gaugesData = ref([]);
// 打开雨量计弹窗
function openGaugeDialog(gauges) {
  if (Array.isArray(gauges) && gauges.length > 0) {
    gaugesData.value = gauges.map((g) => ({
      name: g.name || "未知",
      x: g.x != null ? g.x.toFixed(2) : "-",
      y: g.y != null ? g.y.toFixed(2) : "-",
      r: g.r || "-",
    }));
    dialogVisible.value = true;
  } else {
    ElMessage({
      message: "雨量计数据出错,请重新新建模拟方案!",
      type: "warning",
    });
  }
}
// 关闭弹窗
function handleClose(done) {
  done();
}
</script>
<style lang="less" scoped>
@@ -95,7 +274,6 @@
  margin-bottom: 20px;
  border-radius: 8px;
  color: white;
  .left-top {
    display: flex;
    justify-content: space-between;
@@ -123,7 +301,7 @@
  }
  .details {
  padding: 8px;
    padding-left: 8px;
    .input-group {
      display: flex;
@@ -149,10 +327,52 @@
    }
  }
}
.mess {
  position: absolute;
  top: 10%;
  left: 100%;
  z-index: 5000;
}
</style>
.top {
  display: flex;
  width: 100%;
  height: 41px;
  color: white;
  line-height: 41px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  text-indent: 7px;
  letter-spacing: 2px;
  font-weight: bolder;
}
.clickable {
  color: #5bc0de;
  cursor: pointer;
  text-decoration: underline;
}
.dialoog {
  ::v-deep .el-dialog__title {
    color: #fff !important;
  }
  ::v-deep .el-dialog {
    background-color: rgb(5, 75, 69) !important;
  }
  .el-dialog__body {
    padding-top: 10px;
    padding-bottom: 10px;
  }
  .table-container .el-table {
    font-size: 14px;
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  }
}
</style>