Browse Source

feat: 补充水闸、堤防的弹框内容

feature-v1.0.0
Befend 1 month ago
parent
commit
bd2dc5d37b
  1. 180
      src/hooks/web/useProject.tsx
  2. 0
      src/views/Main/Dike/components/BaseInfo.vue
  3. 0
      src/views/Main/Dike/components/DataStatistics.vue
  4. 0
      src/views/Main/Dike/components/MonitorWarning.vue
  5. 0
      src/views/Main/Dike/components/VideoAnalysis.vue
  6. 2
      src/views/Main/Dike/index.vue
  7. 769
      src/views/Main/Reservoir/components/BaseInfo.vue
  8. 446
      src/views/Main/Reservoir/components/DataStatistics.vue
  9. 198
      src/views/Main/Reservoir/components/MonitorWarning.vue
  10. 94
      src/views/Main/Reservoir/components/VideoAnalysis.vue
  11. 142
      src/views/Main/Reservoir/index.vue
  12. 769
      src/views/Main/Sluice/components/BaseInfo.vue
  13. 446
      src/views/Main/Sluice/components/DataStatistics.vue
  14. 198
      src/views/Main/Sluice/components/MonitorWarning.vue
  15. 94
      src/views/Main/Sluice/components/VideoAnalysis.vue
  16. 142
      src/views/Main/Sluice/index.vue
  17. 21
      src/views/Main/index.vue

180
src/hooks/web/useProject.tsx

@ -277,12 +277,12 @@ export function useLayer() {
const viewerClickEvent = throttle((e: any) => { const viewerClickEvent = throttle((e: any) => {
if (!e.wgs84SurfacePosition) return; if (!e.wgs84SurfacePosition) return;
const projectStore = useProjectStore(); const projectStore = useProjectStore();
const selectLayers: any = projectStore.selectedLayers; const selectLayers: any = projectStore.selectedLayers.filter((item: any) => item.isNeedCluster === "1");
// .filter((item: any) => item.isNeedCluster === "1");
queryLayersByPos(e.wgs84SurfacePosition, selectLayers, (res: any) => { queryLayersByPos(e.wgs84SurfacePosition, selectLayers, (res: any) => {
if (res?.attributes?.showCode) { if (res?.attributes?.showCode) {
const { showCode, showName, scale } = res?.attributes; const { showCode, showName, scale } = res?.attributes;
window.$bus.$emit("open-water-dialog", { // TODO: 待处理区分
window.$bus.$emit("open-reservoir-dialog", {
code: showCode, code: showCode,
name: showName, name: showName,
scale scale
@ -321,93 +321,93 @@ export function useLayer() {
} }
if (!layerType || !(action = layerActions[layerType as string])) return; if (!layerType || !(action = layerActions[layerType as string])) return;
let layer: any = await action(layerData); let layer: any = await action(layerData);
// if (isNeedCluster === "1") { if (isNeedCluster === "1") {
// let baseUrl = import.meta.env.VITE_BASE_URL; let baseUrl = import.meta.env.VITE_BASE_URL;
// const data = await getFeatures(layerData); const data = await getFeatures(layerData);
// if (data?.features?.[0]?.geometry?.type === 'Point') { if (data?.features?.[0]?.geometry?.type === 'Point') {
// let layerConfig = {}; let layerConfig = {};
// switch (layerData.nameCn) { switch (layerData.nameCn) {
// case "水库点": case "水库点":
// layerConfig = { layerConfig = {
// isUniqueRender: true, isUniqueRender: true,
// field: "ENG_SCAL", field: "ENG_SCAL",
// fieldOptions: [ fieldOptions: [
// { name: "1.0", attr: "image", value: "reservoir_big.png" }, { name: "1.0", attr: "image", value: "reservoir_big.png" },
// { name: "2.0", attr: "image", value: "reservoir_big.png" }, { name: "2.0", attr: "image", value: "reservoir_big.png" },
// { name: "3.0", attr: "image", value: "reservoir_normal.png" }, { name: "3.0", attr: "image", value: "reservoir_normal.png" },
// { name: "4.0", attr: "image", value: "reservoir_small.png" }, { name: "4.0", attr: "image", value: "reservoir_small.png" },
// { name: "5.0", attr: "image", value: "reservoir_small.png" }, { name: "5.0", attr: "image", value: "reservoir_small.png" },
// ], ],
// width: 24, width: 24,
// height: 24, height: 24,
// image: "reservoir_big.png", image: "reservoir_big.png",
// }; };
// break; break;
// case "水闸": case "水闸":
// layerConfig = { layerConfig = {
// isUniqueRender: true, isUniqueRender: true,
// field: "ENG_SCAL", field: "ENG_SCAL",
// fieldOptions: [ fieldOptions: [
// { name: "1.0", attr: "image", value: "sluice_big.png" }, { name: "1.0", attr: "image", value: "sluice_big.png" },
// { name: "2.0", attr: "image", value: "sluice_big.png" }, { name: "2.0", attr: "image", value: "sluice_big.png" },
// { name: "3.0", attr: "image", value: "sluice_middle.png" }, { name: "3.0", attr: "image", value: "sluice_middle.png" },
// { name: "4.0", attr: "image", value: "sluice_small.png" }, { name: "4.0", attr: "image", value: "sluice_small.png" },
// { name: "5.0", attr: "image", value: "sluice_small.png" }, { name: "5.0", attr: "image", value: "sluice_small.png" },
// ], ],
// image: "sluice_middle.png", image: "sluice_middle.png",
// }; };
// break; break;
// } }
// layer = new SyCim.ClusterWfsLayer(layerData.id, { layer = new SyCim.ClusterWfsLayer(layerData.id, {
// data, data,
// symbol: { symbol: {
// type: "billboardP", type: "billboardP",
// imageProxy: `${baseUrl}/img/map/`, // 图片代理 imageProxy: `${baseUrl}/img/map/`, // 图片代理
// style: { style: {
// clampToGround: true, clampToGround: true,
// image: "reservoir_small.png", image: "reservoir_small.png",
// ...layerConfig, ...layerConfig,
// }, },
// clustering: { clustering: {
// enabled: clustering.enabled, enabled: clustering.enabled,
// pixelRange: clustering.pixelRange, pixelRange: clustering.pixelRange,
// minimumClusterSize: clustering.minimumClusterSize, minimumClusterSize: clustering.minimumClusterSize,
// clusterEvent: undefined, clusterEvent: undefined,
// clusterColors: undefined, // 聚合点颜色 clusterColors: undefined, // 聚合点颜色
// getImage: undefined, // 获取聚合图片的函数 getImage: undefined, // 获取聚合图片的函数
// }, },
// }, },
// }); });
// layer.bindPopup( layer.bindPopup(
// (e: any) => { (e: any) => {
// const graphic = e.graphic; const graphic = e.graphic;
// if (graphic) { if (graphic) {
// const attr = graphic?.attr; const attr = graphic?.attr;
// const code = attr?.RES_CODE ?? attr?.WAGA_CODE; const code = attr?.RES_CODE ?? attr?.WAGA_CODE;
// const name = attr?.RES_NAME ?? attr?.WAGA_NAME; const name = attr?.RES_NAME ?? attr?.WAGA_NAME;
// const scale = attr?.ENG_SCAL ?? attr?.WAGA_TYPE; const scale = attr?.ENG_SCAL ?? attr?.WAGA_TYPE;
// if (attr?.RES_CODE) { if (attr?.RES_CODE) {
// window.$bus.$emit("open-water-dialog", { window.$bus.$emit("open-reservoir-dialog", {
// code, code,
// name, name,
// scale scale
// }); });
// return ""; return "";
// } else { } else {
// return `<div class="box"> return `<div class="box">
// <div class="detail-item"><span>水闸名称</span>:${name}</div> <div class="detail-item"><span></span>${name}</div>
// <div class="detail-item"><span>水闸编码</span>:${code}</div> <div class="detail-item"><span></span>${code}</div>
// <div class="detail-item"><span>水闸位置</span>:${attr.WAGA_LOC}</div> <div class="detail-item"><span></span>${attr.WAGA_LOC}</div>
// </div>`; </div>`;
// } }
// } }
// }, },
// { {
// closeButton: true, closeButton: true,
// }, },
// ); );
// } }
// } }
layer && window.viewer.addLayer(layer); layer && window.viewer.addLayer(layer);
if (["013000"].includes(layerType)) { if (["013000"].includes(layerType)) {
// 3d tiles // 3d tiles

0
src/views/Main/ProjectOperation/components/BaseInfo.vue → src/views/Main/Dike/components/BaseInfo.vue

0
src/views/Main/ProjectOperation/components/DataStatistics.vue → src/views/Main/Dike/components/DataStatistics.vue

0
src/views/Main/ProjectOperation/components/MonitorWarning.vue → src/views/Main/Dike/components/MonitorWarning.vue

0
src/views/Main/ProjectOperation/components/VideoAnalysis.vue → src/views/Main/Dike/components/VideoAnalysis.vue

2
src/views/Main/ProjectOperation/index.vue → src/views/Main/Dike/index.vue

@ -77,7 +77,7 @@ function handleGetResInfo(data: any) {
} }
function handleClose() { function handleClose() {
window.$bus.$emit("close-water-dialog"); window.$bus.$emit("close-reservoir-dialog");
} }
watch( watch(
() => props.data, () => props.data,

769
src/views/Main/Reservoir/components/BaseInfo.vue

@ -0,0 +1,769 @@
<template>
<div class="baseInfo-page">
<el-tabs v-model="activeName" class="sub-tabs" @tab-click="handleChangeTab">
<el-tab-pane label="水库信息" name="1">
<div class="sub-title">水库基本信息</div>
<el-descriptions class="mt-16" :column="3" border>
<el-descriptions-item>
<template #label> 水库名称 </template>
{{ form.resName }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库代码 </template>
{{ form.resCode }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库注册登记号 </template>
{{ form.registerCode }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库功能 </template>
{{ form.resAction }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库类型 </template>
{{ form.resType }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库状态 </template>
{{ form.resState }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程规模 </template>
{{ form.engScal }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程等别 </template>
{{ form.engGrad }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 曾用名 </template>
{{ form.oldName }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库中心经度 </template>
{{ form.resCenLong }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库中心纬度 </template>
{{ form.resCenLat }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 归口管理部门 </template>
{{ form.admDep }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库主管部门 </template>
{{ form.cmun }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库管理部门 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在行政区划 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在流域 </template>
{{ form.localBasin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在河流 </template>
{{ form.localRiver }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水准基面 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 是否注册 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 左下角经度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 左下角纬度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 右上角经度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 右上角纬度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库所在位置 </template>
{{ form.resLoc }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库管理单位 </template>
{{ form.mnun }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程建设情况 </template>
{{ form.engStat }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 有效年份 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 主要建筑物级别 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 控制流域面积 </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道长度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道比降 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均径流量 </template>
{{ form.avanrnam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均降水量 </template>
{{ form.avanpram }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均流沙量 </template>
{{ form.avansdam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计重现期 </template>
{{ form.dsrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪峰流量 </template>
{{ form.dspkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计1日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计3日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核重现期 </template>
{{ form.chrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪峰流量 </template>
{{ form.chpkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水历时 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水总量 </template>
{{ form.chflvl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪水位 </template>
{{ form.dsfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水位 </template>
{{ form.chfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪高水位 </template>
{{ form.uppLevFlco }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪限制水位库容 </template>
{{ form.flLowLimLevCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位 </template>
{{ form.normWatLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应水面面积 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应库容 </template>
{{ form.normPoolStagCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死水位 </template>
{{ form.deadLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 总库容 </template>
{{ form.totCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 调节库容 </template>
{{ form.storFlCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死库容 </template>
{{ form.deadCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪库容 </template>
{{ form.flcoCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 兴利库容 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 坝址控制流域面积 </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 地震基本烈度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 地震动峰值加速度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设防地震烈度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 集雨面积 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 下泄生态流量 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 数据来源 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 数据创建时间 </template>
{{ form.createTime }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 备注 </template>
{{ form.note }}
</el-descriptions-item>
</el-descriptions>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '100px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item :span="2">
<template #label> 水库概况 </template>
{{ form.resOv }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">水库建设时间</div>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '60px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 开工时间 </template>
{{ form.startDate }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 完工时间 </template>
{{ form.compDate }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">最近异常加固改造时间</div>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '60px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 更新时间 </template>
{{ form.updateTime }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="水文特征" name="2">
<div class="sub-title">水库水文特征</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 控制流域面积(km²) </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均降雨量(mm) </template>
{{ form.avanpram }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均径流量(万m³) </template>
{{ form.avanrnam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均输沙两(万t) </template>
{{ form.avansdam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均最低气温() </template>
{{ form.myavgmintp }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均蒸发量(mm) </template>
{{ form.avanev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均含沙量(kg/m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库调节性能 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应水面面积(km²) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪高水位(m) </template>
{{ form.uppLevFlco }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死水位(m) </template>
{{ form.deadLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 橙色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 红色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 黄色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期开始日期 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期结束日期 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水准基面 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 备注 </template>
{{ form.note }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">设计洪水</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 校核洪峰流量(m³/s) </template>
{{ form.chpkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪峰流量(m³/s) </template>
{{ form.dspkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪水位(m) </template>
{{ form.dsfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水位(m) </template>
{{ form.chfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计1日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计3日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水历时(d) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 洪水总量 </template>
{{ "" }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">汛期限制水位</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 设计重现期 </template>
{{ form.dsrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道比降 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道长度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期限制水位主汛期 </template>
{{ "" }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">库容</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 兴利库容 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 总库容(m³) </template>
{{ form.totCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪库容(m³) </template>
{{ form.flcoCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 调节库容(m³) </template>
{{ form.storFlCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死库容(m³) </template>
{{ form.deadCap }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="库容曲线" name="3">
<div class="chart-container" ref="lineChartRef"></div>
</el-tab-pane>
<el-tab-pane label="责任人信息" name="4">
<div class="sub-title">责任人信息</div>
<el-table class="mt-16" :data="dutyPersonList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60"> </el-table-column>
<el-table-column prop="dutyName" label="负责人" width="120"> </el-table-column>
<el-table-column prop="dutyType" label="负责人类别" width="120"> </el-table-column>
<el-table-column prop="phone" label="电话"> </el-table-column>
<el-table-column prop="manageUnit" label="单位"> </el-table-column>
<el-table-column prop="createTime" label="数据创建时间"> </el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import * as echarts from "echarts";
import { getReservoirBaseDetailData, getReservoirRsppDetailData } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
let myChart: any = null;
let code: any = null;
const activeName: any = ref("1");
let typeApi: any = {
["1"]: initBaseAndRsppInfo,
["2"]: initBaseAndRsppInfo,
["3"]: initEchart,
["4"]: null,
};
const form: any = ref({});
const dutyPersonList: any = ref([]);
const emits = defineEmits(["getResInfo"]);
function initBaseInfo() {
getReservoirBaseDetailData(props.resCode).then((res) => {
if (res?.data) {
form.value = {
...form.value,
...res.data,
};
emits("getResInfo", res.data);
}
});
}
function initRsppInfo() {
getReservoirRsppDetailData(props.resCode).then((res) => {
if (res?.data) {
Object.keys(res.data).forEach((key) => {
form.value[key] = res.data[key];
});
}
});
}
function initBaseAndRsppInfo() {
initBaseInfo();
initRsppInfo();
}
function initData() {
activeName.value = "1";
initBaseAndRsppInfo();
}
const lineChartRef = ref(null);
function initEchart() {
let chartDom = lineChartRef.value;
if (!chartDom) return;
if (myChart) {
myChart.dispose();
}
myChart = echarts.init(chartDom);
let option;
option = {
title: {
// text: "World Population",
},
color: ["#38A0FF", "#4CCA73", "#FBD437"],
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#283b56",
},
},
},
legend: {
orient: "horizontal",
bottom: "2%",
},
grid: {
left: "10%",
right: "10%",
top: "10%",
bottom: "18%",
containLabel: true,
},
xAxis: [
{
type: "category",
name: "库容",
nameLocation: "middle",
nameGap: 20,
axisLine: {
show: true,
lineStyle: {
color: "green",
},
},
axisTick: {
alignWithLabel: true,
},
data: [],
},
{
type: "category",
name: "面积(km²)",
nameLocation: "middle",
position: "top",
nameGap: 20,
axisLine: {
onZero: false,
show: true,
lineStyle: {
// color: "red",
},
},
data: [],
},
],
yAxis: [
{
type: "value",
name: "水位(mm)",
position: "left",
nameLocation: "middle",
nameGap: 34,
axisLine: {
onZero: false,
show: true,
},
axisLabel: {
formatter: "{value}",
},
},
// {
// type: "value",
// name: "test1",
// position: "right",
// nameLocation: "middle",
// axisLine: {
// onZero: false,
// show: true,
// color: "red",
// },
// alignTicks: true,
// axisLabel: {
// formatter: "{value}?",
// },
// },
],
series: [
{
type: "line",
color: "#0000f7",
name: "库容",
data: [],
},
{
type: "line",
color: "#00f400",
name: "面积",
data: [],
},
],
};
option && myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function handleChangeTab() {
typeApi[activeName.value] && typeApi[activeName.value](code);
}
watch(
() => props.resCode,
(val) => {
initData();
},
{ immediate: true },
);
// onMounted(() => {
// initData();
// });
</script>
<style scoped lang="scss">
.baseInfo-page {
height: 100%;
padding: 0 12px;
:deep(.sub-tabs) {
color: rgba(0, 0, 0, 0.9);
height: 100%;
.sy-tabs__header {
margin-bottom: 0;
}
.sy-tabs__content {
height: calc(100% - 60px) !important;
overflow: auto;
.sub-title {
position: relative;
padding: 12px 0 12px 10px;
font-family: Source Han Sans;
font-size: 14px;
font-weight: normal;
line-height: 22px;
&::before {
content: "";
position: absolute;
left: 0;
top: calc(50% - 2px);
width: 4px;
height: 4px;
background: #36b29e;
border-radius: 100%;
}
}
.sy-descriptions {
.sy-descriptions__label {
text-align: left;
min-width: 120px;
height: 50px;
}
.sy-descriptions__content {
min-width: 180px;
}
}
}
}
.chart-container {
width: 480px;
height: 480px;
}
}
</style>

446
src/views/Main/Reservoir/components/DataStatistics.vue

@ -0,0 +1,446 @@
<!-- 数据统计 -->
<template>
<div class="data-statistics">
<div class="search-box">
<div class="options-box">
<el-cascader
size="small"
v-model="cascaderArr"
:options="cascaderOptions"
:props="cascaderProps"
@change="handleChangeCascader"
></el-cascader>
<el-date-picker
class="ml-12"
size="small"
v-model="dateArr"
type="daterange"
range-separator="至"
value-format="YYYY-MM-DD"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
<el-button type="primary" class="!ml-12" @click="handleSearch">查询</el-button>
</div>
<el-radio-group v-model="showType" @change="handleChangeShowType">
<el-radio-button label="1">指标</el-radio-button>
<el-radio-button label="2">图表</el-radio-button>
</el-radio-group>
</div>
<div class="mt-24 statistics-main">
<!-- 指标 -->
<div v-if="showType === '1'">
<div class="attributes-box" v-for="(item, index) in attributesList" :key="index">
<div class="title">{{ item.group }}</div>
<div class="list-box">
<div class="list-item" v-for="(item2, index2) in item.items" :key="index2">
<div class="item-title">{{ item2.zhName }}({{ item2.unit }})</div>
<div class="item-value">
{{ item2.value == null ? "-" : item2.value }}
</div>
</div>
</div>
</div>
<div v-if="!attributesList || !attributesList.length" class="pt-30 text-center">-暂无指标数据-</div>
</div>
<!-- 图表 -->
<div v-else-if="showType === '2'" class="echarts-box">
<div class="echarts-dom-box">
<div class="title">水库基本情况</div>
<div ref="echartsRef1" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">环境情况</div>
<div ref="echartsRef2" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">应变应力情况</div>
<div ref="echartsRef3" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">渗流压力情况</div>
<div ref="echartsRef4" class="echarts-dom"></div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import {
getReservoirCZListData,
getReservoirCDListData,
getReservoirMonitorIndexData,
getReservoirCZMonitorEchartsData,
} from "@/api/reservoir";
import * as echarts from "echarts";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const cascaderOptions: any = ref([]);
const showType: any = ref("1");
const cascaderArr: any = ref([]);
const dateArr: any = ref([]);
const cascaderProps: any = {
expandTrigger: "hover",
label: "stnm",
value: "stcd",
children: "children",
checkStrictly: true,
lazy: true,
lazyLoad(node: any, resolve: any) {
console.log("lazyLoad-node >>>>> ", node);
if (node && node.data && node.data.prjcd) {
getReservoirCDListData({
stcd: node.data.prjcd,
}).then((res) => {
resolve(res.records);
});
} else {
resolve([]);
}
},
};
const attributesList: any = ref([]);
let echart1: any = null;
let echart2: any = null;
let echart3: any = null;
let echart4: any = null;
const echartsRef1 = ref();
const echartsRef2 = ref();
const echartsRef3 = ref();
const echartsRef4 = ref();
function getData() {
switch (showType.value) {
case "1":
//
getReservoirMonitorIndexData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
group: "SK",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
mpcd: cascaderArr.value[1] || "",
}).then((res) => {
attributesList.value = res;
});
break;
case "2":
//
getEchartsData();
break;
}
}
function initChart(data: any, chartInstance: any, echartRes: any) {
// echarts
if (!echartRes) {
return;
}
if (chartInstance) {
chartInstance.dispose();
}
let options = initLineOptions(data);
chartInstance = echarts.init(echartRes);
options && chartInstance.setOption(options);
}
// 线
function initLineOptions(data: any) {
const { markLine, xaxis, yaxis } = data;
if (!xaxis || !yaxis || !yaxis.length) return {};
let yAxis = yaxis.map((v: any) => {
return {
type: "value",
name: `${v.name}(${v.unit})`,
nameLocation: "end",
};
});
let series: any = [];
yaxis.forEach((v: any, i: any) => {
if (v.series?.length) {
v.series.forEach((v2: any) => {
series.push({
type: "line",
smooth: true,
yAxisIndex: i,
name: v2.name,
data: v2.data,
});
});
}
});
if (markLine && markLine.length && series.length) {
let seriesItem = series.find((v: any) => v.yAxisIndex === 1) || series[0];
let colors = ["#f8afaf", "#bae4dd"];
let markLineData = markLine.map((v: any, i: any) => {
return {
name: v.name,
yAxis: v.value,
label: {
color: colors[i] || "red",
},
lineStyle: {
color: colors[i] || "red",
},
};
});
seriesItem.markLine = {
symbol: "none",
label: {
show: true,
position: "insideEndTop",
formatter: "{b}",
},
lineStyle: {
width: 2,
type: "solid",
color: colors[0] || "red",
},
data: markLineData,
};
}
return {
title: {
// text: "",
},
legend: {
orient: "horizontal",
top: "2%",
},
grid: {
left: "5%",
right: "10%",
bottom: "10%",
top: "20%",
containLabel: true,
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#283b56",
},
},
},
xAxis: [
{
type: "category",
name: "时间",
position: "bottom",
axisLine: {
onZero: false,
show: true,
},
axisTick: {
alignWithLabel: true,
},
data: xaxis,
},
],
yAxis: yAxis,
series: series,
};
}
function getEchartsData() {
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
mpcd: cascaderArr.value[1] || "",
elementType: "WATER_LEVEL",
}).then((res) => {
if (res.data) {
initChart(res.data, echart1, echartsRef1.value);
}
});
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
elementType: "ENV",
}).then((res) => {
if (res.data) {
initChart(res.data, echart2, echartsRef2.value);
}
});
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
mpcd: cascaderArr.value[1] || "",
elementType: "C_STRESS",
}).then((res) => {
if (res.data) {
initChart(res.data, echart3, echartsRef3.value);
}
});
// -
initChart([], echart4, echartsRef4.value);
}
function handleSearch() {
attributesList.value = [];
getData();
}
function handleChangeCascader() {}
function handleChangeShowType() {
getData();
}
onMounted(() => {
getReservoirCZListData({
data: {
page: 1,
pageSize: 1000,
prjcd: props.resCode,
},
}).then((res) => {
cascaderOptions.value = res.records;
});
getData();
});
</script>
<style scoped lang="scss">
.data-statistics {
height: 100%;
:deep(.sy-cascader) .sy-input__wrapper,
:deep(.sy-range-editor--small.sy-input__wrapper) {
height: 32px !important;
line-height: 32px !important;
}
:deep(.sy-range-editor--small) .sy-range-input {
color: rgba(0, 0, 0, 0.9) !important;
}
.search-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 12px;
.options-box {
display: flex;
align-items: center;
gap: 8px;
}
}
.attributes-box {
margin-bottom: 16px;
width: 100%;
height: 100%;
padding: 24px 12px;
.title {
padding-left: 10px;
font-size: 14px;
font-weight: 500;
position: relative;
&::before {
content: " ";
width: 4px;
height: 4px;
background: #36b29e;
position: absolute;
left: 1px;
top: 50%;
margin-top: -2px;
transform: rotate(45deg);
}
}
.list-box {
display: flex;
flex-wrap: wrap;
margin-top: 10px;
.list-item {
width: 236px;
height: 102px;
border: 1px solid #36b29e;
border-radius: 10px;
position: relative;
padding: 16px 24px;
margin-right: 16px;
margin-bottom: 12px;
background: linear-gradient(180deg, #eafffc 0%, rgba(222, 255, 250, 0) 100%), #ffffff;
overflow: hidden;
&::after {
position: absolute;
content: "";
background: url("@/assets/img/icon-attr-bg.png") no-repeat center center;
width: 64px;
height: 64px;
right: -12px;
bottom: -12px;
}
.item-title {
font-size: 14px;
}
.item-value {
margin-top: 12px;
font-size: 32px;
color: #36b29e;
font-weight: 500;
}
}
}
}
.echarts-box {
display: flex;
flex-wrap: wrap;
width: 100%;
height: 100%;
padding: 24px 12px;
.echarts-dom-box {
margin-bottom: 24px;
&:nth-child(2n) {
margin-left: 24px;
}
.title {
padding-left: 10px;
font-size: 14px;
font-weight: 500;
position: relative;
margin-bottom: 12px;
&::before {
content: " ";
width: 4px;
height: 4px;
background: #36b29e;
position: absolute;
left: 1px;
top: 50%;
margin-top: -2px;
transform: rotate(45deg);
}
}
.echarts-dom {
width: 478px;
height: 260px;
border: 1px solid #f0f0f0;
}
}
}
.statistics-main {
height: calc(100% - 64px);
overflow: auto;
}
}
.text-center {
padding-top: 30px;
text-align: center;
color: rgba(0, 0, 0, 0.9);
}
</style>

198
src/views/Main/Reservoir/components/MonitorWarning.vue

@ -0,0 +1,198 @@
<template>
<div class="monitor-warning">
<div class="search-box">
<div class="options-box">
<el-select class="w-150" size="small" v-model="dateRange" @change="handleChangeDate">
<el-option label="近1月" value="0"></el-option>
<el-option label="近1日" value="1"></el-option>
<el-option label="近7日" value="2"></el-option>
<el-option label="近3月" value="3"></el-option>
<el-option label="近1年" value="4"></el-option>
</el-select>
<span class="ml-10 mr-6">开始日期</span>
<el-date-picker
class="w-150"
popper-class="date-select-common"
v-model="startDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="选择日期"
></el-date-picker>
<span class="ml-10 mr-6">结束日期</span>
<el-date-picker
class="w-150"
type="date"
v-model="endDate"
placeholder="选择日期"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
></el-date-picker>
</div>
<div class="flex items-center">
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</div>
</div>
<div class="mt-10">
<el-table :data="tableData" border>
<el-table-column label="测站名称">
<template #default="{ row }">
<span>{{ row.stnm }}</span>
</template>
</el-table-column>
<el-table-column label="测站编码">
<template #default="{ row }">
<span>{{ row.stcd }}</span>
</template>
</el-table-column>
<el-table-column label="测站类型">
<template #default="{ row }">
<span>{{ row.sttp }}</span>
</template>
</el-table-column>
<el-table-column label="预警类型">
<template #default="{ row }">
<span>{{ row.alarmType }}</span>
</template>
</el-table-column>
<el-table-column label="监测数据">
<template #default="{ row }">
<span>{{ row.monitorData }}</span>
</template>
</el-table-column>
<el-table-column label="监测时间">
<template #default="{ row }">
<span>{{ row.monitorTime }}</span>
</template>
</el-table-column>
<el-table-column label="预警值" width="100">
<template #default="{ row }">
<span>{{ row.alarmValue }}</span>
</template>
</el-table-column>
<el-table-column label="预警时间">
<template #default="{ row }">
<span>{{ row.alarmTime }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button type="text" size="small">告警处置</el-button>
<el-button type="text" size="small">解除本次预警</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import dayjs from "dayjs";
import { getReservoirCZAlarmPageData } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const dateRange: any = ref("0");
const startDate: any = ref(dayjs().subtract(1, "month").format("YYYY-MM-DD HH:mm:ss"));
const endDate: any = ref(dayjs().format("YYYY-MM-DD HH:mm:ss"));
const tableData: any = ref([]);
const paramsData: any = ref({
pageSize: 10,
pageNum: 1,
total: 0,
});
watch(
() => props.resCode,
(val) => {
getTableData(val);
},
{ immediate: true },
);
// onMounted(() => {
// getTableData();
// });
function getTableData(code = "") {
getReservoirCZAlarmPageData({
startDate: startDate.value + " 00:00:00",
endDate: endDate.value + " 23:59:59",
pageSize: paramsData.value.pageSize,
pageNum: paramsData.value.pageNum,
}).then((res: any) => {
console.log("res >>>>> ", res);
tableData.value = res.records || [];
paramsData.value.total = res.total;
});
}
function handleChangeDate(value: any) {
switch (value) {
case "0":
startDate.value = dayjs().subtract(1, "month").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "1":
startDate.value = dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "2":
startDate.value = dayjs().subtract(7, "day").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "3":
startDate.value = dayjs().subtract(3, "month").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "4":
startDate.value = dayjs().subtract(1, "year").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
default:
break;
}
}
function handleSearch() {
tableData.value = [];
getTableData();
}
function handleReset() {
dateRange.value = null;
startDate.value = null;
endDate.value = null;
paramsData.value.pageNum = 1;
tableData.value = [];
getTableData();
}
</script>
<style scoped lang="scss">
.monitor-warning {
width: 100%;
height: 100%;
padding: 12px;
.search-box {
display: flex;
justify-content: space-between;
align-items: center;
// padding: 0 12px;
font-size: 14px;
color: #262626;
padding-bottom: 12px;
.options-box {
display: flex;
align-items: center;
gap: 8px;
}
}
:deep(.sy-select) .sy-input__wrapper,
:deep(.sy-date-editor) .sy-input__wrapper {
height: 32px !important;
line-height: 32px !important;
}
}
</style>

94
src/views/Main/Reservoir/components/VideoAnalysis.vue

@ -0,0 +1,94 @@
<template>
<div class="video-analysis">
<div class="videoSelect">
<el-select placeholder="请选择视频" v-model="activeVideo" size="small" style="width: 240px" @change="videoChange">
<el-option v-for="item in videoList" :key="item" :label="item" :value="item" />
</el-select>
</div>
<el-tabs v-model="activeName">
<el-tab-pane label="实时视频" name="realTime">
<div class="videoBox">
<video style="width: 100%; height: 100%" :src="videoUrl" v-if="videoUrl"></video>
<div v-else class="videoNull">
<div class="videoContent">
<img src="@/assets/image/videoNull.png" />
<span>暂无内容</span>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getVideoDataList, getOperationPlay } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const activeName = ref("realTime");
const videoUrl = ref("");
const activeVideo = ref("");
const videoList = ref([]);
onMounted(() => {
getVideoDataList({
pageNum: 1,
pageSize: 100,
resCode: props.resCode,
}).then((res) => {
if (res.data) {
videoList.value = res.data.cameraIds;
}
});
});
function videoChange(val: any) {
console.log("cameraId-watch >>>>> ", val);
getOperationPlay({
cameraId: val,
}).then((res) => {
if (res.data) {
videoUrl.value = res.data.urlsMap.flvPlayUrl;
}
});
}
</script>
<style scoped lang="scss">
.video-analysis {
.videoBox {
height: 558px;
video {
width: 100%;
height: 100%;
}
.videoNull {
width: 100%;
height: 100%;
background: #383838;
display: flex;
justify-content: center;
align-items: center;
.videoContent {
img {
width: 44px;
height: 35px;
margin-bottom: 8px;
}
display: flex;
flex-direction: column;
align-items: center;
color: rgba(255, 255, 255, 0.55);
}
}
}
.videoSelect {
position: absolute;
z-index: 12;
right: 0;
top: 5px;
}
}
</style>

142
src/views/Main/Reservoir/index.vue

@ -0,0 +1,142 @@
<template>
<div class="project-detail-wrapper">
<div class="header">
<div class="title">
<img :src="waterIcon" />
<span>{{ data.name }}</span>
</div>
<div class="btns">
<el-icon @click="handleClose">
<Close />
</el-icon>
</div>
</div>
<div class="content">
<el-tabs class="main-tabs" :tab-position="'left'" v-model="activeTab">
<el-tab-pane label="基础信息" name="1" lazy>
<BaseInfo ref="baseInfoRef" :resCode="resCode" @getResInfo="handleGetResInfo"></BaseInfo>
</el-tab-pane>
<el-tab-pane label="数据统计" name="2" lazy>
<DataStatistics ref="dataStatisticsRef" :resCode="resCode"></DataStatistics>
</el-tab-pane>
<el-tab-pane label="监测预警" name="5" lazy>
<MonitorWarning ref="monitorWarning" :resCode="resCode"></MonitorWarning>
</el-tab-pane>
<!-- <el-tab-pane label="视频分析" name="6" lazy>
<VideoAnalysis ref="videoAnalysis" :resCode="resCode"></VideoAnalysis>
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import BaseInfo from "./components/BaseInfo.vue";
import DataStatistics from "./components/DataStatistics.vue";
import MonitorWarning from "./components/MonitorWarning.vue";
import { Close } from "@element-plus/icons-vue";
import RB from "@/assets/map/reservoir_big.png";
import RN from "@/assets/map/reservoir_normal.png";
import RS from "@/assets/map/reservoir_small.png";
// import VideoAnalysis from "./components/VideoAnalysis.vue";
const props = defineProps({
data: {
type: Object,
default: {},
},
});
const resCode = ref("");
defineOptions({
name: "ProjectDetail",
});
const emits = defineEmits(["getResInfo"]);
const waterIcon = ref(RN);
const activeTab = ref("1");
function setWaterIcon() {
switch (props.data.scale) {
case "1.0":
case "2.0":
waterIcon.value = RB;
break;
case "3.0":
waterIcon.value = RN;
break;
case "4.0":
case "5.0":
waterIcon.value = RS;
break;
default:
waterIcon.value = RN;
break;
}
}
function handleGetResInfo(data: any) {
emits("getResInfo", data);
}
function handleClose() {
window.$bus.$emit("close-reservoir-dialog");
}
watch(
() => props.data,
(val) => {
if (val) {
resCode.value = val.code;
}
},
{ immediate: true },
);
onMounted(() => {
setWaterIcon();
});
</script>
<style scoped lang="scss">
.project-detail-wrapper {
position: fixed;
top: 50%;
left: 50%;
width: 80%;
min-height: 600px;
max-height: 800px;
transform: translate(-50%, -50%);
border-radius: 4px;
background: #fff;
.header {
display: flex;
padding: 0 20px;
height: 42px;
color: #262626;
font-family: PingFang SC;
font-size: 16px;
font-weight: 500;
flex-direction: row;
align-items: center;
justify-content: space-between;
.title {
display: flex;
align-items: center;
img {
width: 16px;
height: 16px;
margin-right: 4px;
}
}
.btns {
cursor: pointer;
}
}
.content {
height: 748px;
:deep(.main-tabs) {
height: 100%;
.sy-tabs__content,
.sy-tab-pane {
height: 100%;
}
}
}
}
</style>

769
src/views/Main/Sluice/components/BaseInfo.vue

@ -0,0 +1,769 @@
<template>
<div class="baseInfo-page">
<el-tabs v-model="activeName" class="sub-tabs" @tab-click="handleChangeTab">
<el-tab-pane label="水库信息" name="1">
<div class="sub-title">水库基本信息</div>
<el-descriptions class="mt-16" :column="3" border>
<el-descriptions-item>
<template #label> 水库名称 </template>
{{ form.resName }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库代码 </template>
{{ form.resCode }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库注册登记号 </template>
{{ form.registerCode }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库功能 </template>
{{ form.resAction }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库类型 </template>
{{ form.resType }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库状态 </template>
{{ form.resState }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程规模 </template>
{{ form.engScal }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程等别 </template>
{{ form.engGrad }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 曾用名 </template>
{{ form.oldName }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库中心经度 </template>
{{ form.resCenLong }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库中心纬度 </template>
{{ form.resCenLat }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 归口管理部门 </template>
{{ form.admDep }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库主管部门 </template>
{{ form.cmun }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库管理部门 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在行政区划 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在流域 </template>
{{ form.localBasin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 所在河流 </template>
{{ form.localRiver }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水准基面 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 是否注册 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 左下角经度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 左下角纬度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 右上角经度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 右上角纬度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库所在位置 </template>
{{ form.resLoc }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库管理单位 </template>
{{ form.mnun }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 工程建设情况 </template>
{{ form.engStat }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 有效年份 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 主要建筑物级别 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 控制流域面积 </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道长度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道比降 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均径流量 </template>
{{ form.avanrnam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均降水量 </template>
{{ form.avanpram }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均流沙量 </template>
{{ form.avansdam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计重现期 </template>
{{ form.dsrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪峰流量 </template>
{{ form.dspkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计1日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计3日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核重现期 </template>
{{ form.chrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪峰流量 </template>
{{ form.chpkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水历时 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水总量 </template>
{{ form.chflvl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪水位 </template>
{{ form.dsfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水位 </template>
{{ form.chfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪高水位 </template>
{{ form.uppLevFlco }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪限制水位库容 </template>
{{ form.flLowLimLevCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位 </template>
{{ form.normWatLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应水面面积 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应库容 </template>
{{ form.normPoolStagCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死水位 </template>
{{ form.deadLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 总库容 </template>
{{ form.totCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 调节库容 </template>
{{ form.storFlCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死库容 </template>
{{ form.deadCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪库容 </template>
{{ form.flcoCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 兴利库容 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 坝址控制流域面积 </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 地震基本烈度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 地震动峰值加速度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设防地震烈度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 集雨面积 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 下泄生态流量 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 数据来源 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 数据创建时间 </template>
{{ form.createTime }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 备注 </template>
{{ form.note }}
</el-descriptions-item>
</el-descriptions>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '100px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item :span="2">
<template #label> 水库概况 </template>
{{ form.resOv }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">水库建设时间</div>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '60px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 开工时间 </template>
{{ form.startDate }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 完工时间 </template>
{{ form.compDate }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">最近异常加固改造时间</div>
<el-descriptions
class="mt-16"
:column="2"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '60px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 更新时间 </template>
{{ form.updateTime }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="水文特征" name="2">
<div class="sub-title">水库水文特征</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 控制流域面积(km²) </template>
{{ form.watShedArea }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均降雨量(mm) </template>
{{ form.avanpram }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均径流量(万m³) </template>
{{ form.avanrnam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均输沙两(万t) </template>
{{ form.avansdam }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均最低气温() </template>
{{ form.myavgmintp }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均蒸发量(mm) </template>
{{ form.avanev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 多年平均含沙量(kg/m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水库调节性能 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 正常蓄水位相应水面面积(km²) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪高水位(m) </template>
{{ form.uppLevFlco }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死水位(m) </template>
{{ form.deadLev }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 橙色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 红色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 黄色预警水位(m) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期开始日期 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期结束日期 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 水准基面 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 备注 </template>
{{ form.note }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">设计洪水</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 校核洪峰流量(m³/s) </template>
{{ form.chpkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪峰流量(m³/s) </template>
{{ form.dspkfl }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计洪水位(m) </template>
{{ form.dsfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水位(m) </template>
{{ form.chfllv }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计1日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 设计3日洪水洪量(万m³) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 校核洪水历时(d) </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 洪水总量 </template>
{{ "" }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">汛期限制水位</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 设计重现期 </template>
{{ form.dsrcin }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道比降 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 河道长度 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 汛期限制水位主汛期 </template>
{{ "" }}
</el-descriptions-item>
</el-descriptions>
<div class="sub-title mt-16">库容</div>
<el-descriptions
class="mt-16"
:column="3"
border
:labelStyle="{
'text-align': 'left',
width: '120px',
height: '50px',
}"
:contentStyle="{ minWidth: '180px' }"
>
<el-descriptions-item>
<template #label> 兴利库容 </template>
{{ "" }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 总库容(m³) </template>
{{ form.totCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 防洪库容(m³) </template>
{{ form.flcoCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 调节库容(m³) </template>
{{ form.storFlCap }}
</el-descriptions-item>
<el-descriptions-item>
<template #label> 死库容(m³) </template>
{{ form.deadCap }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="库容曲线" name="3">
<div class="chart-container" ref="lineChartRef"></div>
</el-tab-pane>
<el-tab-pane label="责任人信息" name="4">
<div class="sub-title">责任人信息</div>
<el-table class="mt-16" :data="dutyPersonList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60"> </el-table-column>
<el-table-column prop="dutyName" label="负责人" width="120"> </el-table-column>
<el-table-column prop="dutyType" label="负责人类别" width="120"> </el-table-column>
<el-table-column prop="phone" label="电话"> </el-table-column>
<el-table-column prop="manageUnit" label="单位"> </el-table-column>
<el-table-column prop="createTime" label="数据创建时间"> </el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import * as echarts from "echarts";
import { getReservoirBaseDetailData, getReservoirRsppDetailData } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
let myChart: any = null;
let code: any = null;
const activeName: any = ref("1");
let typeApi: any = {
["1"]: initBaseAndRsppInfo,
["2"]: initBaseAndRsppInfo,
["3"]: initEchart,
["4"]: null,
};
const form: any = ref({});
const dutyPersonList: any = ref([]);
const emits = defineEmits(["getResInfo"]);
function initBaseInfo() {
getReservoirBaseDetailData(props.resCode).then((res) => {
if (res?.data) {
form.value = {
...form.value,
...res.data,
};
emits("getResInfo", res.data);
}
});
}
function initRsppInfo() {
getReservoirRsppDetailData(props.resCode).then((res) => {
if (res?.data) {
Object.keys(res.data).forEach((key) => {
form.value[key] = res.data[key];
});
}
});
}
function initBaseAndRsppInfo() {
initBaseInfo();
initRsppInfo();
}
function initData() {
activeName.value = "1";
initBaseAndRsppInfo();
}
const lineChartRef = ref(null);
function initEchart() {
let chartDom = lineChartRef.value;
if (!chartDom) return;
if (myChart) {
myChart.dispose();
}
myChart = echarts.init(chartDom);
let option;
option = {
title: {
// text: "World Population",
},
color: ["#38A0FF", "#4CCA73", "#FBD437"],
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#283b56",
},
},
},
legend: {
orient: "horizontal",
bottom: "2%",
},
grid: {
left: "10%",
right: "10%",
top: "10%",
bottom: "18%",
containLabel: true,
},
xAxis: [
{
type: "category",
name: "库容",
nameLocation: "middle",
nameGap: 20,
axisLine: {
show: true,
lineStyle: {
color: "green",
},
},
axisTick: {
alignWithLabel: true,
},
data: [],
},
{
type: "category",
name: "面积(km²)",
nameLocation: "middle",
position: "top",
nameGap: 20,
axisLine: {
onZero: false,
show: true,
lineStyle: {
// color: "red",
},
},
data: [],
},
],
yAxis: [
{
type: "value",
name: "水位(mm)",
position: "left",
nameLocation: "middle",
nameGap: 34,
axisLine: {
onZero: false,
show: true,
},
axisLabel: {
formatter: "{value}",
},
},
// {
// type: "value",
// name: "test1",
// position: "right",
// nameLocation: "middle",
// axisLine: {
// onZero: false,
// show: true,
// color: "red",
// },
// alignTicks: true,
// axisLabel: {
// formatter: "{value}?",
// },
// },
],
series: [
{
type: "line",
color: "#0000f7",
name: "库容",
data: [],
},
{
type: "line",
color: "#00f400",
name: "面积",
data: [],
},
],
};
option && myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
function handleChangeTab() {
typeApi[activeName.value] && typeApi[activeName.value](code);
}
watch(
() => props.resCode,
(val) => {
initData();
},
{ immediate: true },
);
// onMounted(() => {
// initData();
// });
</script>
<style scoped lang="scss">
.baseInfo-page {
height: 100%;
padding: 0 12px;
:deep(.sub-tabs) {
color: rgba(0, 0, 0, 0.9);
height: 100%;
.sy-tabs__header {
margin-bottom: 0;
}
.sy-tabs__content {
height: calc(100% - 60px) !important;
overflow: auto;
.sub-title {
position: relative;
padding: 12px 0 12px 10px;
font-family: Source Han Sans;
font-size: 14px;
font-weight: normal;
line-height: 22px;
&::before {
content: "";
position: absolute;
left: 0;
top: calc(50% - 2px);
width: 4px;
height: 4px;
background: #36b29e;
border-radius: 100%;
}
}
.sy-descriptions {
.sy-descriptions__label {
text-align: left;
min-width: 120px;
height: 50px;
}
.sy-descriptions__content {
min-width: 180px;
}
}
}
}
.chart-container {
width: 480px;
height: 480px;
}
}
</style>

446
src/views/Main/Sluice/components/DataStatistics.vue

@ -0,0 +1,446 @@
<!-- 数据统计 -->
<template>
<div class="data-statistics">
<div class="search-box">
<div class="options-box">
<el-cascader
size="small"
v-model="cascaderArr"
:options="cascaderOptions"
:props="cascaderProps"
@change="handleChangeCascader"
></el-cascader>
<el-date-picker
class="ml-12"
size="small"
v-model="dateArr"
type="daterange"
range-separator="至"
value-format="YYYY-MM-DD"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
<el-button type="primary" class="!ml-12" @click="handleSearch">查询</el-button>
</div>
<el-radio-group v-model="showType" @change="handleChangeShowType">
<el-radio-button label="1">指标</el-radio-button>
<el-radio-button label="2">图表</el-radio-button>
</el-radio-group>
</div>
<div class="mt-24 statistics-main">
<!-- 指标 -->
<div v-if="showType === '1'">
<div class="attributes-box" v-for="(item, index) in attributesList" :key="index">
<div class="title">{{ item.group }}</div>
<div class="list-box">
<div class="list-item" v-for="(item2, index2) in item.items" :key="index2">
<div class="item-title">{{ item2.zhName }}({{ item2.unit }})</div>
<div class="item-value">
{{ item2.value == null ? "-" : item2.value }}
</div>
</div>
</div>
</div>
<div v-if="!attributesList || !attributesList.length" class="pt-30 text-center">-暂无指标数据-</div>
</div>
<!-- 图表 -->
<div v-else-if="showType === '2'" class="echarts-box">
<div class="echarts-dom-box">
<div class="title">水库基本情况</div>
<div ref="echartsRef1" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">环境情况</div>
<div ref="echartsRef2" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">应变应力情况</div>
<div ref="echartsRef3" class="echarts-dom"></div>
</div>
<div class="echarts-dom-box">
<div class="title">渗流压力情况</div>
<div ref="echartsRef4" class="echarts-dom"></div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import {
getReservoirCZListData,
getReservoirCDListData,
getReservoirMonitorIndexData,
getReservoirCZMonitorEchartsData,
} from "@/api/reservoir";
import * as echarts from "echarts";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const cascaderOptions: any = ref([]);
const showType: any = ref("1");
const cascaderArr: any = ref([]);
const dateArr: any = ref([]);
const cascaderProps: any = {
expandTrigger: "hover",
label: "stnm",
value: "stcd",
children: "children",
checkStrictly: true,
lazy: true,
lazyLoad(node: any, resolve: any) {
console.log("lazyLoad-node >>>>> ", node);
if (node && node.data && node.data.prjcd) {
getReservoirCDListData({
stcd: node.data.prjcd,
}).then((res) => {
resolve(res.records);
});
} else {
resolve([]);
}
},
};
const attributesList: any = ref([]);
let echart1: any = null;
let echart2: any = null;
let echart3: any = null;
let echart4: any = null;
const echartsRef1 = ref();
const echartsRef2 = ref();
const echartsRef3 = ref();
const echartsRef4 = ref();
function getData() {
switch (showType.value) {
case "1":
//
getReservoirMonitorIndexData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
group: "SK",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
mpcd: cascaderArr.value[1] || "",
}).then((res) => {
attributesList.value = res;
});
break;
case "2":
//
getEchartsData();
break;
}
}
function initChart(data: any, chartInstance: any, echartRes: any) {
// echarts
if (!echartRes) {
return;
}
if (chartInstance) {
chartInstance.dispose();
}
let options = initLineOptions(data);
chartInstance = echarts.init(echartRes);
options && chartInstance.setOption(options);
}
// 线
function initLineOptions(data: any) {
const { markLine, xaxis, yaxis } = data;
if (!xaxis || !yaxis || !yaxis.length) return {};
let yAxis = yaxis.map((v: any) => {
return {
type: "value",
name: `${v.name}(${v.unit})`,
nameLocation: "end",
};
});
let series: any = [];
yaxis.forEach((v: any, i: any) => {
if (v.series?.length) {
v.series.forEach((v2: any) => {
series.push({
type: "line",
smooth: true,
yAxisIndex: i,
name: v2.name,
data: v2.data,
});
});
}
});
if (markLine && markLine.length && series.length) {
let seriesItem = series.find((v: any) => v.yAxisIndex === 1) || series[0];
let colors = ["#f8afaf", "#bae4dd"];
let markLineData = markLine.map((v: any, i: any) => {
return {
name: v.name,
yAxis: v.value,
label: {
color: colors[i] || "red",
},
lineStyle: {
color: colors[i] || "red",
},
};
});
seriesItem.markLine = {
symbol: "none",
label: {
show: true,
position: "insideEndTop",
formatter: "{b}",
},
lineStyle: {
width: 2,
type: "solid",
color: colors[0] || "red",
},
data: markLineData,
};
}
return {
title: {
// text: "",
},
legend: {
orient: "horizontal",
top: "2%",
},
grid: {
left: "5%",
right: "10%",
bottom: "10%",
top: "20%",
containLabel: true,
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#283b56",
},
},
},
xAxis: [
{
type: "category",
name: "时间",
position: "bottom",
axisLine: {
onZero: false,
show: true,
},
axisTick: {
alignWithLabel: true,
},
data: xaxis,
},
],
yAxis: yAxis,
series: series,
};
}
function getEchartsData() {
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
mpcd: cascaderArr.value[1] || "",
elementType: "WATER_LEVEL",
}).then((res) => {
if (res.data) {
initChart(res.data, echart1, echartsRef1.value);
}
});
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
stcd: cascaderArr.value[0] || "",
elementType: "ENV",
}).then((res) => {
if (res.data) {
initChart(res.data, echart2, echartsRef2.value);
}
});
//
getReservoirCZMonitorEchartsData({
startTime: dateArr.value?.length ? dateArr.value[0] + " 00:00:00" : "",
endTime: dateArr.value?.length ? dateArr.value[1] + " 23:59:59" : "",
resCode: props.resCode,
mpcd: cascaderArr.value[1] || "",
elementType: "C_STRESS",
}).then((res) => {
if (res.data) {
initChart(res.data, echart3, echartsRef3.value);
}
});
// -
initChart([], echart4, echartsRef4.value);
}
function handleSearch() {
attributesList.value = [];
getData();
}
function handleChangeCascader() {}
function handleChangeShowType() {
getData();
}
onMounted(() => {
getReservoirCZListData({
data: {
page: 1,
pageSize: 1000,
prjcd: props.resCode,
},
}).then((res) => {
cascaderOptions.value = res.records;
});
getData();
});
</script>
<style scoped lang="scss">
.data-statistics {
height: 100%;
:deep(.sy-cascader) .sy-input__wrapper,
:deep(.sy-range-editor--small.sy-input__wrapper) {
height: 32px !important;
line-height: 32px !important;
}
:deep(.sy-range-editor--small) .sy-range-input {
color: rgba(0, 0, 0, 0.9) !important;
}
.search-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 12px;
.options-box {
display: flex;
align-items: center;
gap: 8px;
}
}
.attributes-box {
margin-bottom: 16px;
width: 100%;
height: 100%;
padding: 24px 12px;
.title {
padding-left: 10px;
font-size: 14px;
font-weight: 500;
position: relative;
&::before {
content: " ";
width: 4px;
height: 4px;
background: #36b29e;
position: absolute;
left: 1px;
top: 50%;
margin-top: -2px;
transform: rotate(45deg);
}
}
.list-box {
display: flex;
flex-wrap: wrap;
margin-top: 10px;
.list-item {
width: 236px;
height: 102px;
border: 1px solid #36b29e;
border-radius: 10px;
position: relative;
padding: 16px 24px;
margin-right: 16px;
margin-bottom: 12px;
background: linear-gradient(180deg, #eafffc 0%, rgba(222, 255, 250, 0) 100%), #ffffff;
overflow: hidden;
&::after {
position: absolute;
content: "";
background: url("@/assets/img/icon-attr-bg.png") no-repeat center center;
width: 64px;
height: 64px;
right: -12px;
bottom: -12px;
}
.item-title {
font-size: 14px;
}
.item-value {
margin-top: 12px;
font-size: 32px;
color: #36b29e;
font-weight: 500;
}
}
}
}
.echarts-box {
display: flex;
flex-wrap: wrap;
width: 100%;
height: 100%;
padding: 24px 12px;
.echarts-dom-box {
margin-bottom: 24px;
&:nth-child(2n) {
margin-left: 24px;
}
.title {
padding-left: 10px;
font-size: 14px;
font-weight: 500;
position: relative;
margin-bottom: 12px;
&::before {
content: " ";
width: 4px;
height: 4px;
background: #36b29e;
position: absolute;
left: 1px;
top: 50%;
margin-top: -2px;
transform: rotate(45deg);
}
}
.echarts-dom {
width: 478px;
height: 260px;
border: 1px solid #f0f0f0;
}
}
}
.statistics-main {
height: calc(100% - 64px);
overflow: auto;
}
}
.text-center {
padding-top: 30px;
text-align: center;
color: rgba(0, 0, 0, 0.9);
}
</style>

198
src/views/Main/Sluice/components/MonitorWarning.vue

@ -0,0 +1,198 @@
<template>
<div class="monitor-warning">
<div class="search-box">
<div class="options-box">
<el-select class="w-150" size="small" v-model="dateRange" @change="handleChangeDate">
<el-option label="近1月" value="0"></el-option>
<el-option label="近1日" value="1"></el-option>
<el-option label="近7日" value="2"></el-option>
<el-option label="近3月" value="3"></el-option>
<el-option label="近1年" value="4"></el-option>
</el-select>
<span class="ml-10 mr-6">开始日期</span>
<el-date-picker
class="w-150"
popper-class="date-select-common"
v-model="startDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="选择日期"
></el-date-picker>
<span class="ml-10 mr-6">结束日期</span>
<el-date-picker
class="w-150"
type="date"
v-model="endDate"
placeholder="选择日期"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
></el-date-picker>
</div>
<div class="flex items-center">
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</div>
</div>
<div class="mt-10">
<el-table :data="tableData" border>
<el-table-column label="测站名称">
<template #default="{ row }">
<span>{{ row.stnm }}</span>
</template>
</el-table-column>
<el-table-column label="测站编码">
<template #default="{ row }">
<span>{{ row.stcd }}</span>
</template>
</el-table-column>
<el-table-column label="测站类型">
<template #default="{ row }">
<span>{{ row.sttp }}</span>
</template>
</el-table-column>
<el-table-column label="预警类型">
<template #default="{ row }">
<span>{{ row.alarmType }}</span>
</template>
</el-table-column>
<el-table-column label="监测数据">
<template #default="{ row }">
<span>{{ row.monitorData }}</span>
</template>
</el-table-column>
<el-table-column label="监测时间">
<template #default="{ row }">
<span>{{ row.monitorTime }}</span>
</template>
</el-table-column>
<el-table-column label="预警值" width="100">
<template #default="{ row }">
<span>{{ row.alarmValue }}</span>
</template>
</el-table-column>
<el-table-column label="预警时间">
<template #default="{ row }">
<span>{{ row.alarmTime }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button type="text" size="small">告警处置</el-button>
<el-button type="text" size="small">解除本次预警</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import dayjs from "dayjs";
import { getReservoirCZAlarmPageData } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const dateRange: any = ref("0");
const startDate: any = ref(dayjs().subtract(1, "month").format("YYYY-MM-DD HH:mm:ss"));
const endDate: any = ref(dayjs().format("YYYY-MM-DD HH:mm:ss"));
const tableData: any = ref([]);
const paramsData: any = ref({
pageSize: 10,
pageNum: 1,
total: 0,
});
watch(
() => props.resCode,
(val) => {
getTableData(val);
},
{ immediate: true },
);
// onMounted(() => {
// getTableData();
// });
function getTableData(code = "") {
getReservoirCZAlarmPageData({
startDate: startDate.value + " 00:00:00",
endDate: endDate.value + " 23:59:59",
pageSize: paramsData.value.pageSize,
pageNum: paramsData.value.pageNum,
}).then((res: any) => {
console.log("res >>>>> ", res);
tableData.value = res.records || [];
paramsData.value.total = res.total;
});
}
function handleChangeDate(value: any) {
switch (value) {
case "0":
startDate.value = dayjs().subtract(1, "month").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "1":
startDate.value = dayjs().subtract(1, "day").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "2":
startDate.value = dayjs().subtract(7, "day").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "3":
startDate.value = dayjs().subtract(3, "month").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
case "4":
startDate.value = dayjs().subtract(1, "year").format("YYYY-MM-DD HH:mm:ss");
endDate.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
break;
default:
break;
}
}
function handleSearch() {
tableData.value = [];
getTableData();
}
function handleReset() {
dateRange.value = null;
startDate.value = null;
endDate.value = null;
paramsData.value.pageNum = 1;
tableData.value = [];
getTableData();
}
</script>
<style scoped lang="scss">
.monitor-warning {
width: 100%;
height: 100%;
padding: 12px;
.search-box {
display: flex;
justify-content: space-between;
align-items: center;
// padding: 0 12px;
font-size: 14px;
color: #262626;
padding-bottom: 12px;
.options-box {
display: flex;
align-items: center;
gap: 8px;
}
}
:deep(.sy-select) .sy-input__wrapper,
:deep(.sy-date-editor) .sy-input__wrapper {
height: 32px !important;
line-height: 32px !important;
}
}
</style>

94
src/views/Main/Sluice/components/VideoAnalysis.vue

@ -0,0 +1,94 @@
<template>
<div class="video-analysis">
<div class="videoSelect">
<el-select placeholder="请选择视频" v-model="activeVideo" size="small" style="width: 240px" @change="videoChange">
<el-option v-for="item in videoList" :key="item" :label="item" :value="item" />
</el-select>
</div>
<el-tabs v-model="activeName">
<el-tab-pane label="实时视频" name="realTime">
<div class="videoBox">
<video style="width: 100%; height: 100%" :src="videoUrl" v-if="videoUrl"></video>
<div v-else class="videoNull">
<div class="videoContent">
<img src="@/assets/image/videoNull.png" />
<span>暂无内容</span>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getVideoDataList, getOperationPlay } from "@/api/reservoir";
const props = defineProps({
resCode: {
type: String,
default: "",
},
});
const activeName = ref("realTime");
const videoUrl = ref("");
const activeVideo = ref("");
const videoList = ref([]);
onMounted(() => {
getVideoDataList({
pageNum: 1,
pageSize: 100,
resCode: props.resCode,
}).then((res) => {
if (res.data) {
videoList.value = res.data.cameraIds;
}
});
});
function videoChange(val: any) {
console.log("cameraId-watch >>>>> ", val);
getOperationPlay({
cameraId: val,
}).then((res) => {
if (res.data) {
videoUrl.value = res.data.urlsMap.flvPlayUrl;
}
});
}
</script>
<style scoped lang="scss">
.video-analysis {
.videoBox {
height: 558px;
video {
width: 100%;
height: 100%;
}
.videoNull {
width: 100%;
height: 100%;
background: #383838;
display: flex;
justify-content: center;
align-items: center;
.videoContent {
img {
width: 44px;
height: 35px;
margin-bottom: 8px;
}
display: flex;
flex-direction: column;
align-items: center;
color: rgba(255, 255, 255, 0.55);
}
}
}
.videoSelect {
position: absolute;
z-index: 12;
right: 0;
top: 5px;
}
}
</style>

142
src/views/Main/Sluice/index.vue

@ -0,0 +1,142 @@
<template>
<div class="project-detail-wrapper">
<div class="header">
<div class="title">
<img :src="waterIcon" />
<span>{{ data.name }}</span>
</div>
<div class="btns">
<el-icon @click="handleClose">
<Close />
</el-icon>
</div>
</div>
<div class="content">
<el-tabs class="main-tabs" :tab-position="'left'" v-model="activeTab">
<el-tab-pane label="基础信息" name="1" lazy>
<BaseInfo ref="baseInfoRef" :resCode="resCode" @getResInfo="handleGetResInfo"></BaseInfo>
</el-tab-pane>
<el-tab-pane label="数据统计" name="2" lazy>
<DataStatistics ref="dataStatisticsRef" :resCode="resCode"></DataStatistics>
</el-tab-pane>
<el-tab-pane label="监测预警" name="5" lazy>
<MonitorWarning ref="monitorWarning" :resCode="resCode"></MonitorWarning>
</el-tab-pane>
<!-- <el-tab-pane label="视频分析" name="6" lazy>
<VideoAnalysis ref="videoAnalysis" :resCode="resCode"></VideoAnalysis>
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import BaseInfo from "./components/BaseInfo.vue";
import DataStatistics from "./components/DataStatistics.vue";
import MonitorWarning from "./components/MonitorWarning.vue";
import { Close } from "@element-plus/icons-vue";
import RB from "@/assets/map/reservoir_big.png";
import RN from "@/assets/map/reservoir_normal.png";
import RS from "@/assets/map/reservoir_small.png";
// import VideoAnalysis from "./components/VideoAnalysis.vue";
const props = defineProps({
data: {
type: Object,
default: {},
},
});
const resCode = ref("");
defineOptions({
name: "ProjectDetail",
});
const emits = defineEmits(["getResInfo"]);
const waterIcon = ref(RN);
const activeTab = ref("1");
function setWaterIcon() {
switch (props.data.scale) {
case "1.0":
case "2.0":
waterIcon.value = RB;
break;
case "3.0":
waterIcon.value = RN;
break;
case "4.0":
case "5.0":
waterIcon.value = RS;
break;
default:
waterIcon.value = RN;
break;
}
}
function handleGetResInfo(data: any) {
emits("getResInfo", data);
}
function handleClose() {
window.$bus.$emit("close-reservoir-dialog");
}
watch(
() => props.data,
(val) => {
if (val) {
resCode.value = val.code;
}
},
{ immediate: true },
);
onMounted(() => {
setWaterIcon();
});
</script>
<style scoped lang="scss">
.project-detail-wrapper {
position: fixed;
top: 50%;
left: 50%;
width: 80%;
min-height: 600px;
max-height: 800px;
transform: translate(-50%, -50%);
border-radius: 4px;
background: #fff;
.header {
display: flex;
padding: 0 20px;
height: 42px;
color: #262626;
font-family: PingFang SC;
font-size: 16px;
font-weight: 500;
flex-direction: row;
align-items: center;
justify-content: space-between;
.title {
display: flex;
align-items: center;
img {
width: 16px;
height: 16px;
margin-right: 4px;
}
}
.btns {
cursor: pointer;
}
}
.content {
height: 748px;
:deep(.main-tabs) {
height: 100%;
.sy-tabs__content,
.sy-tab-pane {
height: 100%;
}
}
}
}
</style>

21
src/views/Main/index.vue

@ -24,7 +24,8 @@
</RightPanel> </RightPanel>
<BottomPanel v-if="showBottomPanel"></BottomPanel> <BottomPanel v-if="showBottomPanel"></BottomPanel>
<Map></Map> <Map></Map>
<ProjectOperation v-if="showWaterDialog" :data="waterData"></ProjectOperation> //
<Reservoir v-if="showReservoir" :data="reservoirData"></Reservoir>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -42,7 +43,7 @@ import LayerTree from "./Map/components/LayerTree.vue";
import Map from "./Map/index.vue"; import Map from "./Map/index.vue";
import RegionSelect from "../RegionSelect/index.vue"; import RegionSelect from "../RegionSelect/index.vue";
import MapSearch from "./MapSearch/index.vue"; import MapSearch from "./MapSearch/index.vue";
import ProjectOperation from "./ProjectOperation/index.vue"; import Reservoir from "./Reservoir/index.vue";
import { onBeforeUnmount, onMounted, ref } from "vue"; import { onBeforeUnmount, onMounted, ref } from "vue";
defineOptions({ defineOptions({
name: "main", name: "main",
@ -51,8 +52,8 @@ const showLeftDrawer = ref(true);
const showRightDrawer = ref(true); const showRightDrawer = ref(true);
const showBottomPanel = ref(true); const showBottomPanel = ref(true);
const showLayerTree = ref(false); const showLayerTree = ref(false);
const showWaterDialog = ref(false); const showReservoir = ref(false);
const waterData = ref({}); const reservoirData = ref({});
function layerTreeChange(val: boolean) { function layerTreeChange(val: boolean) {
showLayerTree.value = val; showLayerTree.value = val;
} }
@ -76,17 +77,17 @@ onMounted(() => {
window.$bus.$on("close-bottom-panel", () => { window.$bus.$on("close-bottom-panel", () => {
showBottomPanel.value = false; showBottomPanel.value = false;
}); });
window.$bus.$on("open-water-dialog", (data: any) => { window.$bus.$on("open-reservoir-dialog", (data: any) => {
window.$bus.$emit("close-left-panel"); window.$bus.$emit("close-left-panel");
window.$bus.$emit("close-right-panel"); window.$bus.$emit("close-right-panel");
showWaterDialog.value = true; showReservoir.value = true;
waterData.value = data; reservoirData.value = data;
}); });
window.$bus.$on("close-water-dialog", () => { window.$bus.$on("close-reservoir-dialog", () => {
window.$bus.$emit("open-left-panel"); window.$bus.$emit("open-left-panel");
window.$bus.$emit("open-right-panel"); window.$bus.$emit("open-right-panel");
showWaterDialog.value = false; showReservoir.value = false;
waterData.value = {}; reservoirData.value = {};
}); });
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {

Loading…
Cancel
Save