WholeProcessPlatform/frontend/src/components/MapModal/index.vue

458 lines
14 KiB
Vue
Raw Normal View History

<template>
<a-modal
:open="visible"
:title="title"
width="80vw"
:footer="null"
:closable="true"
@cancel="handleClose"
:destroyOnClose="true"
class="map-modal"
>
<!-- 问题
1.基础信息图片展示是什么逻辑
2. 电站专题展示逻辑
3. 实时视频回放 少接口
4. 预警提示 少接口
5. 生态流量 达标率查询不对()
6. 鱼类适应性繁殖同期对比NAN ()
2026-06-09 11:44:29 +08:00
7. 出库水温 综合分析 导出没做
8. 栖息地-流量监测 没有水位视频和流量视频 字段没数据
9. 栖息地 水温水质流量没有数据没法测
-->
<div v-if="modelStore.showStcdSelector" class="stcd-selector-wrapper">
<a-select
v-model:value="modelStore.params.stcd"
placeholder="请选择测站"
style="width: 240px; margin-bottom: 12px"
:options="modelStore.stcdOptions"
show-search
:filter-option="filterOption"
@change="handleStcdChange"
>
</a-select>
</div>
<a-tabs :active-key="currentActiveKey" @change="onTabChange">
<a-tab-pane v-for="tab in tabsConfig" :key="tab.key" :tab="tab.name">
</a-tab-pane>
<template #rightExtra v-if="anchor.sttp == 'ENG' || anchor.sttp == 'eng'">
<a-tooltip :title="!isEngConfig ? '' : '该电站无专题配置'">
<a-button type="primary" :disabled="isEngConfig">
<i class="icon iconfont icon-topic mr-[5px]"></i>
电站专题
</a-button></a-tooltip
>
</template>
</a-tabs>
<!-- 内容区域 - 使用动态组件 + keep-alive 实现按需加载和缓存 -->
<keep-alive>
<div class="content">
<div class="content-wrapper" v-show="isQxdMode(currentActiveKey)">
测站
<a-select
v-model:value="currentQxdSelectedStcd"
:options="qxdStationOptions"
style="width: 200px; margin-bottom: 12px"
placeholder="请选择站点"
@change="handleQxdStationChange"
/>
</div>
<!-- 基本信息 -->
<BasicInfo
v-show="currentActiveKey === 'basicInfo'"
:url="getTabUrl('basicInfo')"
:is-active="currentActiveKey === 'basicInfo'"
/>
<!-- 实时视频 -->
<VideoInfo
v-show="currentActiveKey === 'videoInfo'"
:is-active="currentActiveKey === 'videoInfo'"
/>
<!-- 全景影像 -->
<PanoramaInfo
v-show="currentActiveKey === 'panoramaInfo'"
:url="getTabUrl('panoramaInfo')"
:is-active="currentActiveKey === 'panoramaInfo'"
/>
2026-06-09 11:44:29 +08:00
<!-- 监测数据 - 电站运行过程线 -->
<MonitorInfo
v-show="currentActiveKey === 'monitorInfo'"
:is-active="currentActiveKey === 'monitorInfo'"
2026-06-09 11:44:29 +08:00
/>
<!-- 监测数据 - 水温 -->
<WaterTemperature
v-show="currentActiveKey === 'WaterTemperature'"
:is-active="currentActiveKey === 'WaterTemperature'"
:code="getTabCode('WaterTemperature')"
:stcd="
getTabCode('WaterTemperature') == 'qxd.tabs.jcsj'
? qxdSelectedStcd
: ''
"
2026-06-09 11:44:29 +08:00
/>
<!-- 监测数据 - 垂向水温 -->
<VerticalWaterTemperature
v-show="currentActiveKey === 'VerticalWaterTemperature'"
:is-active="currentActiveKey === 'VerticalWaterTemperature'"
/>
<!-- 监测数据 - 水质 -->
<WaterQuality
v-show="currentActiveKey === 'WaterQuality'"
:is-active="currentActiveKey === 'WaterQuality'"
:code="getTabCode('WaterQuality')"
:stcd="
getTabCode('WaterQuality') == 'qxd.tabs.szjc'
? qxdSelectedStcdWq
: ''
"
/>
<!-- 流量监测 -->
<FlowMeasure
v-show="currentActiveKey === 'FlowMeasure'"
:is-active="currentActiveKey === 'FlowMeasure'"
:url="getTabUrl('FlowMeasure')"
:code="getTabCode('FlowMeasure')"
:stcd="
getTabCode('FlowMeasure') == 'qxd.tabs.lcjs'
? qxdSelectedStcdZq
: ''
"
/>
<!-- 预警提示 -->
<EarlyWarningAlert
v-show="currentActiveKey === 'tableTabs'"
:tabs-items="getTabChildren('tableTabs')"
:is-active="currentActiveKey === 'tableTabs'"
/>
<!-- 生态流量 -->
<EcologicalFlow
v-show="currentActiveKey === 'EcologicalFlow'"
:is-active="currentActiveKey === 'EcologicalFlow'"
/>
<!-- 鱼类繁殖适宜性分析 -->
<WaterTemperatureRep
v-show="currentActiveKey === 'WaterTemperatureRep'"
:is-active="currentActiveKey === 'WaterTemperatureRep'"
/>
<!-- 查看报告 -->
<Attachment
v-show="currentActiveKey === 'attachment'"
:is-active="currentActiveKey === 'attachment'"
tabKey="attachment"
:show-download="false"
:url="getTabUrl('attachment')"
/>
<!-- 批复文件 -->
<Attachment
v-show="currentActiveKey === 'approval'"
:is-active="currentActiveKey === 'approval'"
tabKey="approval"
:show-download="true"
:url="getTabUrl('approval')"
/>
</div>
</keep-alive>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, watch, reactive, computed } from 'vue';
// 导入预定义的 Tab 内容组件
import BasicInfo from './components/BasicInfo.vue'; // 基本信息
import VideoInfo from './components/videoInfo.vue'; // 实时视频
import PanoramaInfo from './components/PanoramaInfo.vue'; // 全景影像
2026-06-09 11:44:29 +08:00
import MonitorInfo from './components/MonitorInfo.vue'; // 电站运行过程线
import WaterTemperature from './components/WaterTemperature.vue'; // 水温
import VerticalWaterTemperature from './components/VerticalWaterTemperature.vue'; // 垂向水温
import WaterQuality from './components/WaterQuality.vue'; // 水质
import EarlyWarningAlert from './components/EarlyWarningAlert.vue'; // 预警提示
import FlowMeasure from './components/FlowMeasure.vue'; // 流量监测
import EcologicalFlow from './components/EcologicalFlow.vue'; // 生态流量
import Attachment from './components/Attachment.vue'; // 查看报告/批复文件
import WaterTemperatureRep from './components/WaterTemperatureRep.vue'; // 水温对比数据
import { useModelStore } from '@/store/modules/model';
import { handleTabs } from './setting.config';
import {
getMonitorDataWt,
getMonitorDataWq,
getMonitorDataZq
} from '@/api/mapModal';
const modelStore = useModelStore();
const tabsConfig = ref([]);
// 判断是否显示电站专题配置
const isEngConfig = ref(true);
// ==================== qxd 栖息地模式相关 ====================
// qxd模式配置映射
const qxdConfigMap: Record<
string,
{
sttpCode: string;
apiFn: (data: any) => Promise<any>;
selectProp: string;
}
> = {
'qxd.tabs.jcsj': {
// 水温
sttpCode: 'WTRV',
apiFn: getMonitorDataWt,
selectProp: 'qxdSelectedStcd'
},
'qxd.tabs.szjc': {
// 水质
sttpCode: 'WQ',
apiFn: getMonitorDataWq,
selectProp: 'qxdSelectedStcdWq'
},
'qxd.tabs.lcjs': {
// 流量监测
sttpCode: 'ZQ',
apiFn: getMonitorDataZq,
selectProp: 'qxdSelectedStcdZq'
}
};
// 各模式的站点选项和选中值
const qxdStationOptions = ref<{ label: string; value: string }[]>([]);
const qxdSelectedStcd = ref<string>('');
const qxdSelectedStcdWq = ref<string>('');
const qxdSelectedStcdZq = ref<string>('');
const qxdLoadedCodes = ref<Set<string>>(new Set());
// 获取当前tab对应的qxd配置
const getCurrentQxdConfig = (tabKey: string) => {
const code = getTabCode(tabKey);
return code && qxdConfigMap[code] ? qxdConfigMap[code] : null;
};
// 获取选中的stcd
const getQxdSelectedStcd = (tabKey: string) => {
const config = getCurrentQxdConfig(tabKey);
if (!config) return '';
switch (config.selectProp) {
case 'qxdSelectedStcd':
return qxdSelectedStcd.value;
case 'qxdSelectedStcdWq':
return qxdSelectedStcdWq.value;
case 'qxdSelectedStcdZq':
return qxdSelectedStcdZq.value;
default:
return '';
}
};
// 设置选中的stcd
const setQxdSelectedStcd = (tabKey: string, value: string) => {
const config = getCurrentQxdConfig(tabKey);
if (!config) return;
switch (config.selectProp) {
case 'qxdSelectedStcd':
qxdSelectedStcd.value = value;
break;
case 'qxdSelectedStcdWq':
qxdSelectedStcdWq.value = value;
break;
case 'qxdSelectedStcdZq':
qxdSelectedStcdZq.value = value;
break;
}
};
// 加载栖息地站点列表
const loadQxdStationList = async (tabKey: string) => {
const code = getTabCode(tabKey);
if (!code || !qxdConfigMap[code]) return;
if (qxdLoadedCodes.value.has(code)) return;
const config = qxdConfigMap[code];
try {
const params = {
filter: {
logic: 'and',
filters: [
{
field: 'fhstcd',
operator: 'eq',
dataType: 'string',
value: modelStore.params.stcd
},
{
field: 'sttpCode',
operator: 'eq',
dataType: 'string',
value: config.sttpCode
}
]
},
select: ['stcd', 'stnm']
};
const res = await config.apiFn(params);
const stations = res?.data?.data || res?.data?.records || [];
if (stations.length > 0) {
qxdStationOptions.value = stations.map((item: any) => ({
label: item.stnm,
value: item.stcd
}));
setQxdSelectedStcd(tabKey, stations[0].stcd);
}
qxdLoadedCodes.value.add(code);
} catch (error) {
console.error(`获取站点列表失败(${code}):`, error);
}
};
// 获取当前激活tab对应的选中stcd (支持v-model双向绑定)
const currentQxdSelectedStcd = computed({
get: () => getQxdSelectedStcd(currentActiveKey.value),
set: (val: string) => setQxdSelectedStcd(currentActiveKey.value, val)
});
// 判断是否是qxd模式
const isQxdMode = (tabKey: string) => {
const code = getTabCode(tabKey);
return code && qxdConfigMap[code] ? true : false;
};
// 处理栖息地站点切换
const handleQxdStationChange = () => {
// 站点切换后,子组件会通过 watch stcd 自动刷新
};
// import MapView from './components/MapView.vue';
// import SurroundingInfo from './components/SurroundingInfo.vue';
// 定义 Tab 配置项接口
interface TabItem {
key: string;
title: string;
url: string;
}
// 获取 Tab 配置项的 URL
const getTabUrl = (key: string) => {
const tab = tabsConfig.value.find((item: any) => item.key === key);
return tab?.url || '';
};
// 获取 Tab 配置项的子 Tab
const getTabChildren = (key: string) => {
console.log(tabsConfig.value);
const tab = tabsConfig.value.find((item: any) => item.key === key);
return tab?.tabs || [];
};
// 获取 Tab 配置项的 code
const getTabCode = (key: string) => {
const tab = tabsConfig.value.find((item: any) => item.key === key);
return tab?.code || '';
};
// 定义 Props
const props = defineProps<{
visible: boolean;
title?: string;
activeKey?: string; // 外部控制的当前激活 tab
data?: any; // 可选:传递给内部组件的数据
}>();
// 定义 Emits
// 添加 'update:activeKey' 以支持 v-model:active-key
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
(e: 'change', key: string): void;
}>();
// 内部维护的 activeKey
const currentActiveKey = ref<string>('');
const anchor = ref<string>('');
// 监听外部传入的 activeKey 变化,同步到内部状态
watch(
() => props.activeKey,
newVal => {
if (newVal && newVal !== currentActiveKey.value) {
currentActiveKey.value = newVal;
}
},
{ immediate: true }
);
watch(
() => modelStore.params,
newVal => {
if (!newVal || Object.keys(newVal).length === 0) return;
2026-05-13 08:45:15 +08:00
console.log(newVal);
anchor.value = newVal;
let params = newVal;
if (['VD', 'WTRV', 'ZQ', 'WQ'].includes(params?.sttpCode)) {
params.sttp = params.sttpCode;
2026-06-10 18:54:40 +08:00
}else
if (['ENG_ALARM'].includes(params?.sttpMap)) {
params.sttp = params.sttpMap;
}
tabsConfig.value = handleTabs({ ...params });
let value = tabsConfig.value.find((item: any) => item.default);
currentActiveKey.value = value?.key;
},
{ deep: true, immediate: true }
);
// 监听 tab 切换,如果是 qxd 模式,加载站点列表
watch(
() => currentActiveKey.value,
activeKey => {
const code = getTabCode(activeKey);
if (code && qxdConfigMap[code]) {
loadQxdStationList(activeKey);
}
},
{ immediate: true }
);
// 监听内部 tab 切换
const onTabChange = (key: string) => {
currentActiveKey.value = key;
// 通知父组件更新 activeKey (支持 v-model)
// 通知父组件发生了切换事件 (用于业务逻辑,如加载数据)
emit('change', key);
};
// 关闭弹窗
const handleClose = () => {
emit('update:visible', false);
modelStore.params = {};
// 清理状态,避免影响下次打开
modelStore.showStcdSelector = false;
modelStore.stcdOptions = [];
// 清理qxd模式状态
qxdStationOptions.value = [];
qxdSelectedStcd.value = '';
qxdSelectedStcdWq.value = '';
qxdSelectedStcdZq.value = '';
qxdLoadedCodes.value = new Set();
};
// 为了方便模板中使用,将 props.data 暴露给模板
const modalData = ref(props.data);
watch(
() => props.data,
newVal => {
modalData.value = newVal;
}
);
// 搜索过滤函数
const filterOption = (input: string, option: any) => {
return option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
// 处理测站切换
const handleStcdChange = (newStcd: string) => {
console.log('【测站切换】', newStcd);
// 由于 BasicInfo.vue 监听了 stcd 变化,这里只需更新 store
// 如果需要刷新所有 tab 的数据,可以在这里触发事件
};
</script>
<style lang="scss" scoped>
.map-modal {
.content {
min-height: 600px;
}
}
</style>