修改水温垂向右侧点击,添加录像视频和建设状态,bug修改

This commit is contained in:
扈兆增 2026-06-16 11:36:17 +08:00
parent f1b8ffebf1
commit ce8855d3c2
27 changed files with 5926 additions and 4181 deletions

View File

@ -91,6 +91,24 @@ export function getVideoList(data: any) {
data
});
}
// 录像视频 - 时间查询 没接
export function getNoLiveVideoYear(data: any) {
return request({
url: '/wmp-env-server/env/vd/GetKendoListCust',
method: 'post',
data
});
}
// 录像视频
export function getNoLiveVideoList(data: any) {
return request({
url: '/wmp-env-server/env/vd/runData/GetKendoListCust',
method: 'post',
data
});
}
// 实时视频单个查询
export function getVideoDetail(data: any) {
return request({

View File

@ -74,11 +74,6 @@ const baseColumns = [
dataIndex: 'rowId',
width: 60
},
{
title: '告警设施',
dataIndex: 'stnm',
width: 220
},
{
title: '告警时间',
dataIndex: 'tms',
@ -91,12 +86,7 @@ const baseColumns = [
width: 120
},
{
title: '监测要素',
dataIndex: 'ysName',
width: 120
},
{
title: '判断标准',
title: '限值(m³/s)',
dataIndex: 'bzz',
width: 120
},

View File

@ -21,6 +21,11 @@
</div>
</div>
<div class="filter-row">
<a-select
v-model:value="timeType"
style="margin-right: 12px"
:options="timeTypeOptions"
/>
<a-range-picker
v-model:value="dateRange"
:format="dateFormat"

View File

@ -158,12 +158,12 @@ const columnsMap: Record<string, any[]> = {
},
{
title: '性腺发育期',
dataIndex: 'fwgh',
dataIndex: 'st',
width: 140
},
{
title: '早期资源量和种类',
dataIndex: 'fwgh',
dataIndex: 'ps',
width: 220
},
{
@ -203,7 +203,7 @@ const columnsMap: Record<string, any[]> = {
},
{
title: '电导率(μS/cm)',
dataIndex: 'tm',
dataIndex: 'cond',
width: 180
}
],

View File

@ -0,0 +1,355 @@
<template>
<div class="fish-facility-build-state">
<a-spin :spinning="loading">
<!-- 步骤条 -->
<div class="steps-container">
<div class="steps-wrapper">
<div
v-for="(item, index) in bltList"
:key="item.code"
class="step-item"
:class="{
'step-active': currentStep > item.code,
'step-current': currentStep === item.code,
'step-last': index === bltList.length - 1
}"
>
<span class="step-label">{{ item.name }}</span>
<i
v-if="currentStep > item.code"
class="step-icon icon iconfont icon-check"
></i>
<div v-if="currentStep == 0" class="step-line"></div>
</div>
</div>
</div>
<!-- 建设进度 -->
<div class="progress-container">
<span class="progress-label">建设进度</span>
<div class="progress-bar-wrapper">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: progressPercent + '%' }"
></div>
</div>
<span class="progress-text">{{ progressText }}</span>
</div>
</div>
<!-- 日期信息表格 -->
<div class="info-table">
<table>
<tbody>
<tr>
<td class="label-cell">计划开工日期</td>
<td class="value-cell">{{ planStartDate || '-' }}</td>
<td class="label-cell">计划完工日期</td>
<td class="value-cell">{{ planEndDate || '-' }}</td>
</tr>
<tr>
<td class="label-cell">实际开工日期</td>
<td class="value-cell">{{ startDate || '-' }}</td>
<td class="label-cell">建成日期</td>
<td class="value-cell">{{ endDate || '-' }}</td>
</tr>
</tbody>
</table>
</div>
</a-spin>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useModelStore } from '@/store/modules/model';
import dayjs from 'dayjs';
import { queryPostUrlList } from '@/api/mapModal';
const modelStore = useModelStore();
const loading = ref(false);
const hasLoaded = ref(false);
const props = defineProps({
url: {
type: String,
default: ''
},
isActive: {
type: Boolean,
default: false
}
});
const bltList = ref<any[]>([]);
const currentStep = ref(0);
const progressPercent = ref(0);
const progressText = ref('0%');
const planStartDate = ref('');
const planEndDate = ref('');
const startDate = ref('');
const endDate = ref('');
const formatDate = (date: any) => {
if (!date) return '';
return dayjs(date).format('YYYY-MM-DD');
};
const getData = async () => {
if (hasLoaded.value || !props.url || !modelStore.params.stcd) return;
loading.value = true;
try {
const params = {
filter: {
logic: 'and',
filters: [
{
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: modelStore.params.stcd
}
]
}
};
const res: any = await queryPostUrlList(props.url, params);
if (res && res.data) {
const data = Array.isArray(res.data.data)
? res.data.data[0]
: res.data.data;
if (data) {
bltList.value = data.bltList || [];
currentStep.value = data.blprd || 0;
//
const progress = data.progress || '0%';
progressText.value = progress;
progressPercent.value = parseInt(progress) || 0;
planStartDate.value = formatDate(data.planStartDate);
planEndDate.value = formatDate(data.planEndDate);
startDate.value = formatDate(data.startDate);
endDate.value = formatDate(data.endDate);
}
}
} catch (error) {
console.error('获取建设状态数据失败:', error);
} finally {
loading.value = false;
hasLoaded.value = true;
}
};
watch(
() => props.isActive,
active => {
if (active && !hasLoaded.value) {
getData();
}
},
{ immediate: true }
);
watch(
() => modelStore.params.stcd,
(newStcd, oldStcd) => {
if (newStcd && newStcd !== oldStcd && props.url) {
hasLoaded.value = false;
getData();
}
}
);
</script>
<style scoped lang="scss">
.fish-facility-build-state {
width: 880px;
margin: 0 auto;
margin-top: 24px;
border: 1px solid #dfe6ec;
//
.steps-container {
background: #e4ecf2;
padding: 0;
margin-bottom: 24px;
.step-line {
&::after {
content: '';
position: absolute;
right: 0;
right: -6px; /* 负值让第二条线更靠右 */
top: 50%;
transform: translateY(-50%) rotate(45deg);
width: 26px;
height: 26px;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
}
}
.steps-wrapper {
display: flex;
align-items: stretch;
.step-item {
display: flex;
align-items: center;
justify-content: center;
position: relative;
flex: 1;
min-height: 40px;
gap: 6px;
.step-label {
font-size: 14px;
color: #999;
white-space: nowrap;
}
.step-icon {
font-size: 16px;
color: #2f6b98;
}
// -
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
height: 0;
width: 0;
}
//
&.step-active {
background: #f0f4f8;
.step-label {
color: #00000080;
}
&::after {
border-top: 20px solid transparent;
border-left: 15px solid #f0f4f8;
border-bottom: 20px solid transparent;
}
}
// div -
&.step-active:has(+ .step-current)::after {
border-top-color: #2f6b98;
border-bottom-color: #2f6b98;
}
// - +
&.step-current {
background: #2f6b98;
.step-label {
color: #fff;
}
//
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
height: 0;
width: 0;
border-top: 20px solid #e4ecf2;
border-left: 15px solid #2f6b98;
border-bottom: 20px solid #e4ecf2;
}
}
//
&.step-last::after {
display: none;
}
}
}
}
//
.progress-container {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 24px;
.progress-label {
font-size: 14px;
color: #333;
margin-right: 16px;
white-space: nowrap;
}
.progress-bar-wrapper {
display: flex;
align-items: center;
flex: 1;
max-width: 500px;
.progress-bar {
flex: 1;
height: 12px;
background: #e8e8e8;
border-radius: 6px;
overflow: hidden;
margin-right: 12px;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #2a7aaf 0%, #5cb85c 100%);
border-radius: 6px;
transition: width 0.3s ease;
}
}
.progress-text {
font-size: 14px;
color: #2a7aaf;
font-weight: 500;
white-space: nowrap;
}
}
}
//
.info-table {
padding: 16px;
table {
width: 100%;
border-collapse: collapse;
tr {
td {
padding: 12px 16px;
border: 1px solid #a8d8f0;
font-size: 14px;
&.label-cell {
background: #f4f7f9;
color: #333;
width: 18%;
text-align: right;
white-space: nowrap;
}
&.value-cell {
color: #333;
width: 32%;
}
}
}
}
}
}
</style>

View File

@ -472,6 +472,13 @@ const handleSearch = () => fetchData();
const initData = () => {
if (hasLoaded.value) return;
console.log(modelStore.filter.rangeTm);
if (modelStore.filter.rangeTm.length > 0) {
dateRange.value = [
dayjs(modelStore.filter.rangeTm[0]),
dayjs(modelStore.filter.rangeTm[1])
];
}
nextTick(() => initChart());
fetchData();
hasLoaded.value = true;

View File

@ -0,0 +1,396 @@
<template>
<div class="no-live-video">
<!-- 视频模式 -->
<div class="video-mode">
<div class="video-main" v-loading="videoLoading">
<!-- 视频显示 -->
<div v-if="activeMedia.src" class="media-display">
<LiveVideoBox
ref="liveVideoRef"
:videoData="{ url: activeMedia.src }"
height="100%"
:showTitle="false"
/>
</div>
<div v-else class="media-empty">
<a-empty description="请选择右侧数据" />
</div>
</div>
<div class="video-sidebar" v-loading="videoLoading">
<!-- 时间范围查询 -->
<div class="sidebar-search">
<a-range-picker
v-model:value="dateRange"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%"
@change="handleDateChange"
/>
<a-button type="primary" class="ml-2" @click="handleSearch">
查询
</a-button>
</div>
<!-- 列表 -->
<div class="sidebar-list" v-if="videoList.length > 0">
<div
v-for="item in videoList"
:key="item.flpth"
class="sidebar-item"
:class="{ active: activeFlpth === item.flpth }"
@click="handleSelectMedia(item)"
>
<div class="item-thumb">
<img
v-if="item.imgPath"
:src="item.imgPath"
@error="handleImageError"
/>
<div v-else class="thumb-placeholder">
<img :src="videoCover" />
</div>
</div>
<div class="item-time">
<div>{{ item.titleName || item.stnm || '-' }}</div>
{{ item.tm }}
</div>
</div>
</div>
<a-empty
v-else
description="暂无数据"
class="empty-wrapper h-full flex items-center justify-center flex-col"
/>
<!-- 分页 -->
<div class="sidebar-pagination">
<a-pagination
v-model:current="videoPage"
v-model:pageSize="videoTake"
:page-size-options="videoPageSizeOptions"
:total="videoTotal"
show-size-changer
size="small"
@change="handleVideoPageChange"
/>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import dayjs from 'dayjs';
import LiveVideoBox from '@/views/shiPinJianKong/components/LiveVideoBox.vue';
import { getNoLiveVideoYear, getNoLiveVideoList } from '@/api/mapModal';
import { useModelStore } from '@/store/modules/model';
import videoCover from '@/assets/images/videFm.jpg';
const modelStore = useModelStore();
const props = defineProps({
isActive: { type: Boolean, default: false }
});
const hasLoaded = ref(false);
//
const dateRange = ref<[string, string] | null>(null);
//
const videoPage = ref(1);
const videoTake = ref(10);
const videoPageSizeOptions = ['10', '20', '50'];
const videoTotal = ref(0);
const videoLoading = ref(false);
const videoList = ref<any[]>([]);
const activeFlpth = ref('');
const activeMedia = ref<{ src: string }>({ src: '' });
const liveVideoRef = ref();
// getNoLiveVideoYear
const initDefaultDateRange = async () => {
try {
const res: any = await getNoLiveVideoYear({
filter: {
logic: 'and',
filters: [
{
field: 'stcd',
operator: 'in',
value: [modelStore.params.stcd]
}
]
},
sort: [{ field: 'tm', dir: 'desc' }]
});
const data = res?.data?.data || res?.data || [];
if (data.length > 0) {
//
const latestTm = data[0].tm;
const endDate = dayjs(latestTm);
const startDate = endDate.subtract(7, 'day');
dateRange.value = [
startDate.format('YYYY-MM-DD'),
endDate.format('YYYY-MM-DD')
];
} else {
// 7
const endDate = dayjs();
const startDate = endDate.subtract(7, 'day');
dateRange.value = [
startDate.format('YYYY-MM-DD'),
endDate.format('YYYY-MM-DD')
];
}
} catch (error) {
console.error('获取时间范围失败:', error);
// 7
const endDate = dayjs();
const startDate = endDate.subtract(7, 'day');
dateRange.value = [
startDate.format('YYYY-MM-DD'),
endDate.format('YYYY-MM-DD')
];
}
};
//
const initData = async () => {
await initDefaultDateRange();
fetchVideoList();
};
//
const handleDateChange = () => {
videoPage.value = 1;
fetchVideoList();
};
//
const handleSearch = () => {
videoPage.value = 1;
fetchVideoList();
};
//
const fetchVideoList = async () => {
videoLoading.value = true;
try {
const skip = (videoPage.value - 1) * videoTake.value;
const timeFilters: any[] = [];
if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
timeFilters.push({
field: 'tm',
operator: 'gte',
dataType: 'date',
value: `${dateRange.value[0]} 00:00:00`
});
timeFilters.push({
field: 'tm',
operator: 'lte',
dataType: 'date',
value: `${dateRange.value[1]} 23:59:59`
});
}
const res: any = await getNoLiveVideoList({
take: videoTake.value,
skip,
filter: {
logic: 'and',
filters: [
{
field: 'stcd',
operator: 'in',
value: [modelStore.params.stcd]
},
...timeFilters
]
},
sort: [{ field: 'tm', dir: 'desc' }]
});
res?.data?.data.forEach(item => {
item.tm = dayjs(item.tm).format('YYYY-MM-DD HH') || '-';
});
videoList.value = res?.data?.data || [];
videoTotal.value = res?.data?.total || 0;
if (videoList.value.length > 0 && !activeFlpth.value) {
handleSelectMedia(videoList.value[0]);
}
} catch (error) {
console.error('获取视频列表失败:', error);
videoList.value = [];
} finally {
videoLoading.value = false;
}
};
//
const handleSelectMedia = (item: any) => {
activeFlpth.value = item.flpth;
activeMedia.value = { src: item.flpth || '' };
};
//
const handleVideoPageChange = (page: number) => {
videoPage.value = page;
activeFlpth.value = '';
activeMedia.value = { src: '' };
fetchVideoList();
};
//
const handleImageError = (e: Event) => {
const target = e.target as HTMLImageElement;
target.style.display = 'none';
};
// isActive
watch(
() => props.isActive,
active => {
if (active && !hasLoaded.value) {
initData();
}
},
{ immediate: true }
);
// stcd
watch(
() => modelStore.params.stcd,
async (newStcd, oldStcd) => {
if (newStcd && newStcd !== oldStcd) {
videoList.value = [];
activeFlpth.value = '';
activeMedia.value = { src: '' };
await initDefaultDateRange();
fetchVideoList();
}
}
);
</script>
<style lang="scss" scoped>
.no-live-video {
width: 100%;
.video-mode {
display: flex;
height: 600px;
gap: 12px;
.video-main {
flex: 0 0 60%;
background: #000;
border-radius: 4px;
overflow: hidden;
.media-display {
width: 100%;
height: 100%;
}
.media-empty {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
}
.video-sidebar {
flex: 0 0 40%;
display: flex;
flex-direction: column;
border: 1px solid #e8e8e8;
border-radius: 4px;
.sidebar-search {
padding: 8px;
display: flex;
align-items: center;
border-bottom: 1px solid #e8e8e8;
}
.sidebar-list {
height: 600px;
overflow-y: auto;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: min-content;
gap: 8px;
padding: 8px;
.sidebar-item {
cursor: pointer;
border: 1px solid #f0f0f0;
border-radius: 4px;
overflow: hidden;
transition: all 0.2s;
&:hover {
border-color: #1890ff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
&.active {
border-color: #1890ff;
background: #e6f7ff;
}
.item-thumb {
width: 100%;
height: 105px;
background: #1a1a1a;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.thumb-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
.item-time {
padding: 4px;
font-size: 11px;
color: #666;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.sidebar-pagination {
padding: 8px;
text-align: center;
border-top: 1px solid #e8e8e8;
}
}
}
}
</style>

View File

@ -103,13 +103,13 @@ const tableColumns = ref([
String(record.tecnt).trim() !== ''
? record.tecnt
: '-';
const transplant =
record?.transplant !== undefined &&
record?.transplant !== null &&
String(record.transplant).trim() !== ''
? record.transplant
const plantask =
record?.plantask !== undefined &&
record?.plantask !== null &&
String(record.plplantask).trim() !== ''
? record.plplantask
: '-';
return `${tecnt}/${transplant}`;
return `${tecnt}/${plantask}`;
}
},
{
@ -123,13 +123,13 @@ const tableColumns = ref([
String(record.surnum).trim() !== ''
? record.surnum
: '-';
const plantask =
record?.plantask !== undefined &&
record?.plantask !== null &&
String(record.plantask).trim() !== ''
? record.plantask
const transplant =
record?.transplant !== undefined &&
record?.transplant !== null &&
String(record.transplant).trim() !== ''
? record.transplant
: '-';
return `${surnum}/${plantask}`;
return `${surnum}/${transplant}`;
}
},
{

View File

@ -479,6 +479,12 @@ const handleSearch = () => fetchData();
const initData = () => {
if (hasLoaded.value) return;
nextTick(() => {
if (modelStore.filter.rangeTm.length > 0) {
dateRange.value = [
dayjs(modelStore.filter.rangeTm[0]),
dayjs(modelStore.filter.rangeTm[1])
];
}
if (chartRef.value && !chartInstance)
chartInstance = echarts.init(chartRef.value);
});

View File

@ -903,7 +903,15 @@ const handleExport = () => {
const initData = () => {
if (hasLoaded.value) return;
console.log('modelStore.filter.rangeTm:', modelStore.filter.rangeTm);
nextTick(() => {
if (modelStore.filter.rangeTm.length > 0) {
dateRange.value = [
dayjs(modelStore.filter.rangeTm[0]),
dayjs(modelStore.filter.rangeTm[1])
];
}
if (chartRef.value && !chartInstance)
chartInstance = echarts.init(chartRef.value);
});

View File

@ -37,7 +37,12 @@
<!-- 同期对比列的自定义渲染 -->
<template #contrast="{ record }">
<span
v-if="record.wt && record.beforeWt && !isNaN(Number(record.wt)) && !isNaN(Number(record.beforeWt))"
v-if="
record.wt &&
record.beforeWt &&
!isNaN(Number(record.wt)) &&
!isNaN(Number(record.beforeWt))
"
:style="{
color:
Number(record.wt) - Number(record.beforeWt) > 0
@ -664,6 +669,12 @@ const initData = () => {
setTimeout(() => {
initChart();
}, 200);
if (modelStore.filter.rangeTm.length > 0) {
rangePicker.value = [
dayjs(modelStore.filter.rangeTm[0]),
dayjs(modelStore.filter.rangeTm[1])
];
}
hasLoaded.value = true; //
};

View File

@ -10,8 +10,8 @@
class="map-modal"
>
<!-- 问题
1.基础信息图片展示是什么逻辑
2. 电站专题展示逻辑
1.基础信息图片展示是什么逻辑
2. 电站专题展示逻辑
3. 实时视频回放 少接口
4. 预警提示 少接口
5. 生态流量 达标率查询不对()
@ -20,13 +20,13 @@
8. 栖息地-流量监测 没有水位视频和流量视频 字段没数据
9. 栖息地 水温水质流量没有数据没法测
10.鱼类增殖站 - 运行数据 要添加字典
11.珍惜植物园 - 种植要求字段不知道
12.水生调查断面 - 监测数据 不知道电导率 性腺发育期早期资源量和种类
13.水电告警情况 生态流量 不知道字段 接口传参有问题
11.珍惜植物园 - 种植要求字段不知道
12.水生调查断面 - 监测数据 不知道电导率 性腺发育期早期资源量和种类
13.水电告警情况 生态流量 不知道字段 接口传参有问题
14. 地图抽吸 碰撞检测 放大到具体层级锚点抽吸了但是popup弹框还在显示;
15.运行情况 计划开始运行时间 接口没接
没弄 环保设施
-->
<div v-if="modelStore.showStcdSelector" class="stcd-selector-wrapper">
<a-select
@ -88,18 +88,23 @@
v-show="currentActiveKey === 'videoInfo'"
:is-active="currentActiveKey === 'videoInfo'"
/>
<!-- 录像视频 -->
<NoLiveVideo
v-show="currentActiveKey === 'noLiveVideo'"
:is-active="currentActiveKey === 'noLiveVideo'"
/>
<!-- 全景影像 -->
<PanoramaInfo
v-show="currentActiveKey === 'panoramaInfo'"
:url="getTabUrl('panoramaInfo')"
:is-active="currentActiveKey === 'panoramaInfo'"
/>
<!-- 监测数据 - 电站运行过程线 -->
<!-- 监测数据 - 电站运行过程线 -->
<MonitorInfo
v-show="currentActiveKey === 'monitorInfo'"
:is-active="currentActiveKey === 'monitorInfo'"
/>
<!-- 监测数据 - 水温 -->
<!-- 监测数据 - 水温 -->
<WaterTemperature
v-show="currentActiveKey === 'WaterTemperature'"
:is-active="currentActiveKey === 'WaterTemperature'"
@ -111,7 +116,7 @@
"
:wt-config="modelStore.wtConfig"
/>
<!-- 监测数据 - 垂向水温 -->
<!-- 监测数据 - 垂向水温 -->
<VerticalWaterTemperature
v-show="currentActiveKey === 'VerticalWaterTemperature'"
:is-active="currentActiveKey === 'VerticalWaterTemperature'"
@ -167,6 +172,12 @@
v-show="currentActiveKey === 'FishZHFX'"
:is-active="currentActiveKey === 'FishZHFX'"
/>
<!-- 建设情况 -->
<FishFacilityBuildState
v-show="currentActiveKey === 'FishFacilityBuildState'"
:is-active="currentActiveKey === 'FishFacilityBuildState'"
:url="getTabUrl('FishFacilityBuildState')"
/>
<!-- AI运行识别 -->
<AIYXSB
v-show="currentActiveKey === 'AIYXSB'"
@ -178,12 +189,12 @@
: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'"
@ -259,6 +270,7 @@ import { ref, watch, reactive, computed } from 'vue';
// Tab
import BasicInfo from './components/BasicInfo.vue'; //
import VideoInfo from './components/videoInfo.vue'; //
import NoLiveVideo from './components/NoLiveVideo.vue'; //
import PanoramaInfo from './components/PanoramaInfo.vue'; //
import MonitorInfo from './components/MonitorInfo.vue'; // 线
import WaterTemperature from './components/WaterTemperature.vue'; //
@ -270,6 +282,7 @@ import FlowMeasure from './components/FlowMeasure.vue'; // 流量监测
import FishFacilityMonitorData from './components/FishFacilityMonitorData.vue'; // 线
import FishFacilityRunState from './components/FishFacilityRunState.vue'; //
import FlowDischarge from './components/FlowDischarge.vue'; // -
import FishFacilityBuildState from './components/FishFacilityBuildState.vue'; //
//
import NormalOperationData from './components/NormalOperationData/index.vue'; //
import ProcessDiagram from './components/ProcessDiagram.vue'; //
@ -999,6 +1012,12 @@ const handleClose = () => {
modelStore.verticalWaterStcd = '';
modelStore.aiSites = [];
modelStore.wtConfig = {};
modelStore.filter = {
stllgzlx: '', // -
stllTmType: '', // -
tm: '',
rangeTm: []
};
modelStore.wqShow = false;
modelStore.fishTabInfo = null;
};

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,7 @@ export class MapClass implements MapClassInterface {
this.service = new MapOl();
}
static getInstance(): MapClass {
console.log('getInstance');
if (!this.instance) {
this.instance = new MapClass();
}

View File

@ -72,6 +72,7 @@ export class MapOl implements MapInterface {
private hoveredFeatureId: string | number | null = null;
private popupManager: PopupManager;
private regionMaskManager: RegionMaskManager;
private isBatchPopupMode = false;
constructor() {
this.pointLayerManager = new PointLayerManager({
map: null,
@ -142,7 +143,11 @@ export class MapOl implements MapInterface {
this.popupManager.setMap(this.map);
this.regionMaskManager.setContext(this.map, this.view);
this.view.on('change:resolution', () => {});
this.view.on('change:resolution', () => {
this.handleZoomChange();
const zoom = this.view.getZoom();
console.log('mouse zoom:', zoom);
});
this.map.on('click', evt => {
this.popupManager.showPopup(undefined, undefined);
this.popupManager.handleMapClick(evt.pixel, detectedFeature => {
@ -169,9 +174,24 @@ export class MapOl implements MapInterface {
targetElement.style.cursor = payload.hoveredId ? 'pointer' : '';
}
this.showPopup(payload.detectedFeature, payload.coordinate);
// 批量 popup 模式下(>= 14 级)不触发 hover popup
if (!this.isBatchPopupMode) {
this.showPopup(payload.detectedFeature, payload.coordinate);
}
});
});
this.map.on('pointerdrag', () => {
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
});
this.map.on('moveend', () => {
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
});
return Promise.resolve(this.map);
} catch (e) {
console.error('OL Init Error', e);
@ -220,6 +240,52 @@ export class MapOl implements MapInterface {
showPopup(feature: Feature | undefined, coordinate: number[] | undefined) {
this.popupManager.showPopup(feature, coordinate);
}
/**
* >= 15 popup
*/
private handleZoomChange() {
if (!this.view) return;
const zoom = this.view.getZoom();
if (zoom === undefined) return;
if (zoom >= 15) {
this.enableBatchPopupMode();
} else {
this.disableBatchPopupMode();
}
}
/**
* popup popup
*/
private enableBatchPopupMode() {
this.isBatchPopupMode = true;
this.popupManager.clearBatchPopups();
this.updateBatchPopups();
}
/**
* popup popup
*/
private disableBatchPopupMode() {
this.isBatchPopupMode = false;
this.popupManager.clearBatchPopups();
this.popupManager.showPopup(undefined, undefined);
}
/**
* popups
*/
private updateBatchPopups() {
const features = this.pointLayerManager.getFeaturesInViewport();
// 传入样式检查器,过滤掉 declutter/距离过滤等隐藏的锚点
this.popupManager.showPopupsForFeatures(features, feature => {
const style = this.createPointStyle(feature);
return style !== null;
});
}
/**
* ( Leaflet DivIcon )
*/
@ -660,6 +726,10 @@ export class MapOl implements MapInterface {
const layerInstance = this.layerRegistry.get(registryKey as string);
if (layerInstance) {
layerInstance.setVisible(checked);
// 图层显隐变化时刷新 batch popup
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
} else {
console.warn(
`未找到标识为 [${registryKey}] 的图层实例,当前注册表 keys:`,
@ -669,6 +739,10 @@ export class MapOl implements MapInterface {
}
mdLayerTreeShowOrHidden(layerType: string, checked?: boolean): void {
this.pointLayerManager.setLayerVisible(layerType, checked);
// 图层显隐变化时刷新 batch popup
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
}
hasLayer(layerType: string): void {
@ -1212,7 +1286,6 @@ export class MapOl implements MapInterface {
// 使用 Object.assign 批量设置样式,代码更整洁
Object.assign(container.style, {
position: 'absolute',
backgroundColor: 'rgba(255, 255, 255, 0.9)',
border: '1px solid #000',
padding: '4px 8px',
borderRadius: '4px',
@ -1223,7 +1296,6 @@ export class MapOl implements MapInterface {
display: 'flex',
alignItems: 'center',
zIndex: '1001',
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
pointerEvents: 'auto' // 确保可以点击
});
@ -1309,6 +1381,10 @@ export class MapOl implements MapInterface {
key || '',
!!checked
);
// 图例变化时刷新 batch popup
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
}
/**
@ -1327,6 +1403,10 @@ export class MapOl implements MapInterface {
anchoPointState,
checked
);
// 图例变化时刷新 batch popup
if (this.isBatchPopupMode) {
this.updateBatchPopups();
}
}
switchView(_type): void {}

View File

@ -32,6 +32,34 @@ export class PointLayerManager {
this.map = map;
}
// 备注:获取当前屏幕可视区域内的所有点要素(仅包含图层可见且图例可见的要素)。
getFeaturesInViewport(): Feature[] {
if (!this.map) return [];
const extent = this.map.getView().calculateExtent(this.map.getSize());
if (!extent) return [];
const [minX, minY, maxX, maxY] = extent;
const result: Feature[] = [];
this.forEachFeature((feature, layer) => {
// 跳过图层本身不可见的要素
if (!layer.getVisible()) return;
const geom = feature.getGeometry();
if (!geom || geom.getType() !== 'Point') return;
const coords = (geom as Point).getCoordinates();
const [x, y] = coords;
if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
result.push(feature);
}
});
return result;
}
// 备注:统一返回当前点图层注册表,供外层做遍历或清理。
getRegistry() {
return this.layerRegistry;
@ -128,6 +156,7 @@ export class PointLayerManager {
const vectorLayer = this.layerRegistry.get(layerKey);
if (vectorLayer && vectorLayer.getVisible() !== visible) {
vectorLayer.setVisible(visible);
vectorLayer.changed();
}
}

View File

@ -204,6 +204,213 @@ export class PopupManager {
this.popupElement.style.display = 'none';
}
// 备注:批量显示多个要素的 Popup使用绝对定位的 div 而非 Overlay。
showPopupsForFeatures(
features: Feature[],
styleChecker?: (feature: Feature) => boolean
) {
if (!this.map || !this.popupElement) return;
// 清除之前批量显示的 popups
this.clearBatchPopups();
// 过滤:只显示图例可见的要素
const visibleFeatures = features.filter(
f => f.get('_legendVisible') !== false
);
if (visibleFeatures.length === 0) return;
const mapElement = this.map.getTargetElement();
const batchContainer = document.createElement('div');
batchContainer.className = 'batch-popup-container';
batchContainer.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1000;
`;
batchContainer.id = 'batch-popup-container';
// 先添加容器到 DOM以便后续元素能正确测量尺寸
mapElement.appendChild(batchContainer);
// 用于碰撞检测的已放置 popup 列表
const placedPopups: Array<{
left: number;
right: number;
top: number;
bottom: number;
}> = [];
let styleHiddenCount = 0;
let blockedCount = 0;
let renderedCount = 0;
const renderedIds: Array<string | number | null> = [];
const blockedIds: Array<string | number | null> = [];
// 用于 declutter 模拟检测的已放置要素边界框列表
const placedAnchors: Array<{
bbLeft: number;
bbRight: number;
bbTop: number;
bbBottom: number;
}> = [];
visibleFeatures.forEach(feature => {
const geom = feature.getGeometry();
if (!geom || geom.getType() !== 'Point') return;
const coords = (geom as Point).getCoordinates();
const pixel = this.map?.getPixelFromCoordinate(coords);
if (!pixel) return;
// 检查样式是否隐藏declutter、距离过滤等
if (styleChecker && !styleChecker(feature)) {
styleHiddenCount += 1;
return;
}
// 模拟 OpenLayers declutter基于图标+文字的边界框碰撞检测
const zoom = this.map.getView().getZoom() ?? 14;
let dynamicScale = 0.7 + (zoom - 4.5) * 0.08;
dynamicScale = Math.max(0.5, Math.min(3.0, dynamicScale));
// 计算要素的碰撞边界框
const labelText = (feature.get('_labelText') as string) || '';
const labelLineCount = labelText.split('\n').length;
const labelWidth = Math.min(
labelText
.split('\n')
.reduce((max, line) => Math.max(max, line.length), 0) *
7 *
dynamicScale,
200
);
const labelHeight = 12 * dynamicScale * labelLineCount;
const labelOffsetY =
labelLineCount > 1 ? -30 * dynamicScale : -22 * dynamicScale;
const iconSize = 32 * dynamicScale; // 假设图标原始大小 32x32
// 碰撞框 = 图标框 文字框
const bbLeft = pixel[0] - Math.max(iconSize / 2, labelWidth / 2);
const bbRight = pixel[0] + Math.max(iconSize / 2, labelWidth / 2);
const bbTop = pixel[1] + labelOffsetY - labelHeight;
const bbBottom = pixel[1] + iconSize / 2;
// 检查是否和已放置的要素碰撞
let blocked = false;
for (const placed of placedAnchors) {
if (
bbRight > placed.bbLeft &&
bbLeft < placed.bbRight &&
bbBottom > placed.bbTop &&
bbTop < placed.bbBottom
) {
blocked = true;
break;
}
}
if (blocked) {
blockedCount += 1;
blockedIds.push((feature.getId?.() as string | number | null) ?? null);
return;
}
const props = feature.getProperties();
const popupHtml = props.popupHtml || generatePopupHtml(props);
if (!popupHtml) return;
// 记录边界框用于 declutter 检测
placedAnchors.push({ bbLeft, bbRight, bbTop, bbBottom });
// 创建与原始 popupElement 完全相同的样式
const popupEl = document.createElement('div');
popupEl.className = this.popupElement.className;
popupEl.innerHTML = popupHtml;
// 不设置自定义 cssText只设置定位对应原始 popup 的 positioning: 'bottom-center', offset: [0, -10]
popupEl.style.position = 'absolute';
popupEl.style.display = 'block';
popupEl.style.transform = 'translate(-50%, -100%)'; // bottom-center 对齐
popupEl.style.pointerEvents = 'none';
// 临时设置 visibility: hidden 来测量尺寸
popupEl.style.visibility = 'hidden';
popupEl.style.left = `${pixel[0]}px`;
popupEl.style.top = `${pixel[1] - 10}px`;
batchContainer.appendChild(popupEl);
// 获取 popup 尺寸
const rect = popupEl.getBoundingClientRect();
const popupWidth = rect.width;
const popupHeight = rect.height;
// 计算 popup 的位置(对应原始 positioning: 'bottom-center', offset: [0, -10]
const popupX = pixel[0];
const popupY = pixel[1] - 10; // bottom-center 对齐 + 10px 偏移
const popupRect = {
left: popupX - popupWidth / 2,
right: popupX + popupWidth / 2,
top: popupY - popupHeight,
bottom: popupY
};
// 碰撞检测
let hasCollision = false;
for (const placed of placedPopups) {
if (this.checkCollision(popupRect, placed)) {
hasCollision = true;
break;
}
}
if (!hasCollision) {
// 无碰撞,显示 popup
popupEl.style.visibility = 'visible';
popupEl.style.left = `${popupX}px`;
popupEl.style.top = `${popupY}px`;
renderedCount += 1;
renderedIds.push((feature.getId?.() as string | number | null) ?? null);
placedPopups.push({
left: popupRect.left,
right: popupRect.right,
top: popupRect.top,
bottom: popupRect.bottom
});
} else {
// 有碰撞,移除该 popup
blockedCount += 1;
blockedIds.push((feature.getId?.() as string | number | null) ?? null);
batchContainer.removeChild(popupEl);
}
});
}
// 备注:清除批量显示的 popups。
clearBatchPopups() {
const existing = document.getElementById('batch-popup-container');
if (existing) {
existing.remove();
}
}
// 备注:检测两个 popup 矩形是否碰撞。
private checkCollision(
rect1: { left: number; right: number; top: number; bottom: number },
rect2: { left: number; right: number; top: number; bottom: number }
): boolean {
const padding = 4;
return !(
rect1.right + padding < rect2.left ||
rect1.left - padding > rect2.right ||
rect1.bottom + padding < rect2.top ||
rect1.top - padding > rect2.bottom
);
}
// 备注:统一重置 hover 和 Popup 状态,供地图销毁和切换时复用。
reset() {
if (this.animationFrameId) {
@ -264,6 +471,7 @@ export class PopupManager {
// 备注:销毁 Popup 管理器内部状态和 Overlay 引用。
destroy() {
this.clearBatchPopups();
this.reset();
if (this.popupElement && this.popupMouseEnterHandler) {
this.popupElement.removeEventListener(

View File

@ -1,11 +1,19 @@
<!-- 垂向水温变化图 -->
<template>
<SidePanelItem title="垂向水温变化" :moreSelect="select" :datetimePicker="datetimePicker"
@update-values="handlePanelChange1">
<SidePanelItem
title="垂向水温变化"
:moreSelect="select"
:datetimePicker="datetimePicker"
@update-values="handlePanelChange1"
>
<div class="chart-wrapper">
<!-- 图表容器 -->
<a-spin :spinning="loading" tip="加载中...">
<div v-show="showemit && !loading" ref="chartRef" class="chart-container"></div>
<div
v-show="showemit && !loading"
ref="chartRef"
class="chart-container"
></div>
<div v-show="!showemit && !loading" class="chart-container">
<a-empty />
</div>
@ -15,18 +23,29 @@
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
import {
ref,
computed,
onMounted,
onBeforeUnmount,
watch,
nextTick
} from 'vue';
import * as echarts from 'echarts';
import type { ECharts } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
import { getChuiXiangShuiWenTreeStcd, getCxswList } from "@/api/sw";
import { useModelStore } from "@/store/modules/model";
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { getChuiXiangShuiWenTreeStcd, getCxswList } from '@/api/sw';
import { useModelStore } from '@/store/modules/model';
import { useMapModalStore } from '@/store/modules/mapModal';
import { MapClass } from '@/components/gis/map.class';
const modelStore = useModelStore();
const JidiSelectEventStore = useJidiSelectEventStore();
const baseid = ref('');
//
const year = ref('');
//
defineOptions({
name: 'chuixiangshuiwenChangeMod'
@ -140,7 +159,7 @@ function transformAggregatesToChartData(
if (!monthData || monthData.length === 0) {
result.push({
name: `${month}`,
dataXy: [] // ECharts
dataXy: [] // ECharts
});
continue;
}
@ -152,11 +171,11 @@ function transformAggregatesToChartData(
stnm: string;
}> = monthData.map((item: any) => ({
value: [
parseFloat(item.vwt), //
parseInt(item.wthg) // /
] as [number, number], //
stcd: stcd, //
stnm: stnm //
parseFloat(item.vwt), //
parseInt(item.wthg) // /
] as [number, number], //
stcd: stcd, //
stnm: stnm //
}));
result.push({
@ -172,16 +191,25 @@ function transformAggregatesToChartData(
* 根据当前年月生成颜色和图例显隐状态
*/
function generateColorsAndVisibility(
dataLength: number, // 12
dataLength: number, // 12
sDate: string | number
): {
colors: string[];
selected: Record<string, boolean>;
} {
const baseColors = [
'#6ca4f7', '#78c300', '#9556a4', '#df91ab',
'#7399c6', '#dbb629', '#56c2e3', '#f56a06',
'#cdba75', '#76523b', '#df75b6', '#00a050'
'#6ca4f7',
'#78c300',
'#9556a4',
'#df91ab',
'#7399c6',
'#dbb629',
'#56c2e3',
'#f56a06',
'#cdba75',
'#76523b',
'#df75b6',
'#00a050'
];
const currentYear = new Date().getFullYear();
@ -233,7 +261,7 @@ const getCurrentHourTimeTwo = () => {
const startTime = new Date(endTime);
startTime.setMonth(startTime.getMonth() - 1);
const formatDateTime = (date) => {
const formatDateTime = date => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
@ -253,15 +281,15 @@ const select = ref({
value: '',
options: [],
picker: undefined,
format: undefined,
format: undefined
});
const datetimePicker = ref({
show: true,
value: computed(() => getCurrentHourTime()),
format: "YYYY",
picker: "year" as const,
options: [],
format: 'YYYY',
picker: 'year' as const,
options: []
});
/**
@ -273,58 +301,61 @@ const selectOptions = async () => {
try {
let filters = [
{
"field": "mway",
"operator": "eq",
"dataType": "string",
"value": 2
field: 'mway',
operator: 'eq',
dataType: 'string',
value: 2
},
{
"field": "tm",
"operator": "gte",
"dataType": "date",
"value": getCurrentHourTimeTwo()[0]
field: 'tm',
operator: 'gte',
dataType: 'date',
value: getCurrentHourTimeTwo()[0]
},
{
"field": "tm",
"operator": "lte",
"dataType": "date",
"value": getCurrentHourTimeTwo()[1]
field: 'tm',
operator: 'lte',
dataType: 'date',
value: getCurrentHourTimeTwo()[1]
}
];
if (baseid.value && baseid.value !== 'all') {
filters.push({
"field": "baseId",
"operator": "eq",
"dataType": "string",
"value": baseid.value
field: 'baseId',
operator: 'eq',
dataType: 'string',
value: baseid.value
});
}
let filter = {
"logic": "and",
"filters": filters
logic: 'and',
filters: filters
};
let sort = baseid.value && baseid.value !== 'all' ? [
{
"field": "rstcdStepSort",
"dir": "asc"
}
] : [
{
"field": "baseId",
"dir": "asc"
},
{
"field": "rstcdStepSort",
"dir": "asc"
}
];
let sort =
baseid.value && baseid.value !== 'all'
? [
{
field: 'rstcdStepSort',
dir: 'asc'
}
]
: [
{
field: 'baseId',
dir: 'asc'
},
{
field: 'rstcdStepSort',
dir: 'asc'
}
];
const data = { filter, sort };
const res = await getChuiXiangShuiWenTreeStcd(data);
let dataOne = res?.data?.data || res.data
let dataOne = res?.data?.data || res.data;
if (dataOne.length > 0) {
const treeData = dataOne.map(item => {
@ -334,27 +365,29 @@ const selectOptions = async () => {
selectable: false,
children: (item.stcdVo || []).map(child => ({
title: child.stnm,
value: child.stcd
value: child.stcd,
lgtd: child.lgtd,
lttd: child.lttd
}))
};
});
if (baseid.value == 'all') {
select.value.value = '008640203800001014'
select.value.value = '008640203800001014';
select.value.options = treeData;
} else {
select.value.value = treeData[0].children[0].value
select.value.value = treeData[0].children[0].value;
select.value.options = treeData;
}
} else {
select.value.options = []
select.value.value = ''
select.value.options = [];
select.value.value = '';
}
} catch (error) {
console.error('获取站点数据失败:', error);
} finally {
loading.value = false; // loading
}
}
};
// ==================== ====================
@ -362,14 +395,16 @@ const chartRef = ref<HTMLElement | null>(null);
let chartInstance: ECharts | null = null;
//
const chartData = ref<Array<{
name: string;
dataXy: Array<{
value: [number, number];
stcd: string;
stnm: string;
}>;
}>>([]);
const chartData = ref<
Array<{
name: string;
dataXy: Array<{
value: [number, number];
stcd: string;
stnm: string;
}>;
}>
>([]);
// Y1=2=
const type = ref(1);
@ -390,26 +425,26 @@ const fetchChartData = async (stcd: string, year: string | number) => {
try {
const params = {
filter: {
logic: "and",
logic: 'and',
filters: [
{
field: "year",
operator: "eq",
dataType: "string",
field: 'year',
operator: 'eq',
dataType: 'string',
value: String(year)
},
{
field: "stcd",
operator: "eq",
dataType: "string",
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: stcd
}
]
},
sort: [
{
field: "depth",
dir: "asc"
field: 'depth',
dir: 'asc'
}
]
};
@ -429,18 +464,26 @@ const fetchChartData = async (stcd: string, year: string | number) => {
});
// stcd stnm
chartData.value = transformAggregatesToChartData(aggregates, stcd, currentStnm);
chartData.value = transformAggregatesToChartData(
aggregates,
stcd,
currentStnm
);
// 12 chartData.value.length
const { colors: newColors, selected: newSelected } = generateColorsAndVisibility(
12, // 12
year
);
const { colors: newColors, selected: newSelected } =
generateColorsAndVisibility(
12, // 12
year
);
colors.value = newColors;
selected.value = newSelected;
// showemit
if (chartData.value.length > 0 && chartData.value.some(item => item.dataXy.length > 0)) {
if (
chartData.value.length > 0 &&
chartData.value.some(item => item.dataXy.length > 0)
) {
showemit.value = true; //
} else {
showemit.value = false; //
@ -490,12 +533,26 @@ const initChart = () => {
console.log('站点名称:', stnm);
console.log('水温:', temperature);
console.log('深度:', depth);
const matchMonth = params.seriesName.match(/\d+/);
const monthNum = matchMonth ? parseInt(matchMonth[0]) : 1;
const startTime = `${year.value}-${String(monthNum).padStart(
2,
'0'
)}-01 00:00:00`;
const lastDay = new Date(year.value, monthNum, 0).getDate();
const endTime = `${year.value}-${String(monthNum).padStart(
2,
'0'
)}-${lastDay} 23:59:59`;
console.log(endTime);
modelStore.modalVisible = true;
modelStore.params.sttp = "WT";
modelStore.params.sttp = 'WT';
modelStore.params.enfc = '1';
modelStore.title = stnm ;
modelStore.title = stnm;
// modelStore.isBasicEdit = true;
modelStore.params.stcd = stcd;
modelStore.filter.rangeTm = [startTime, endTime];
// TODO:
});
@ -511,7 +568,7 @@ const updateChart = () => {
const yData: any[] = [];
const legend: string[] = [];
chartData.value.forEach((item) => {
chartData.value.forEach(item => {
if (item.dataXy.length > 0) {
// value[0]
xData.push(item.dataXy[0].value[0]);
@ -521,7 +578,7 @@ const updateChart = () => {
yData.push({
name: item.name,
data: item.dataXy, // 使
data: item.dataXy, // 使
type: 'line',
smooth: true,
connectNulls: true,
@ -593,7 +650,7 @@ const updateChart = () => {
type: 'value' as const,
name: type.value === 2 ? '高程(m)' : '水深(m)',
min: 0,
scale: false, // Y 0
scale: false, // Y 0
nameGap: type.value === 2 ? 22 : 10,
inverse: type.value !== 2
},
@ -612,13 +669,17 @@ const handleChartClick = (params: any) => {
const matchMonth = params.seriesName.match(/\d+/);
const monthNum = matchMonth ? parseInt(matchMonth[0]) : 1;
const year = typeof datetimePicker.value.value === 'string'
? parseInt(datetimePicker.value.value)
: datetimePicker.value.value;
const year =
typeof datetimePicker.value.value === 'string'
? parseInt(datetimePicker.value.value)
: datetimePicker.value.value;
const startTime = `${year}-${String(monthNum).padStart(2, '0')}-01 00:00:00`;
const lastDay = new Date(year, monthNum, 0).getDate();
const endTime = `${year}-${String(monthNum).padStart(2, '0')}-${lastDay} 23:59:59`;
const endTime = `${year}-${String(monthNum).padStart(
2,
'0'
)}-${lastDay} 23:59:59`;
const currentStcd = select.value.value;
let currentStnm = '';
@ -669,7 +730,7 @@ onBeforeUnmount(() => {
watch(
() => JidiSelectEventStore.selectedItem,
async (newVal) => {
async newVal => {
if (!newVal || !newVal.wbsCode) {
return;
}
@ -689,20 +750,28 @@ watch(
// },
// { deep: true }
// );
const handlePanelChange1 = (data: any) => {
const handlePanelChange1 = (data: any, type: string) => {
console.log('当前所有控件状态:', data);
if (data.moreSelect && data.datetime) {
fetchChartData(data.moreSelect, data.datetime)
if (type == 'click') {
const mapClass = MapClass.getInstance();
mapClass.flyTopanto(
[
Number(data.selectedNodeExtra.lgtd),
Number(data.selectedNodeExtra.lttd)
],
15
);
}
year.value = data.datetime;
fetchChartData(data.moreSelect, data.datetime);
} else {
showemit.value = true
showemit.value = true;
chartData.value = [];
colors.value = [];
selected.value = {};
showemit.value = false;
}
};
</script>

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,8 @@ export const useMapOrchestrator = () => {
mapDataStore.setLoading(true);
try {
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
const previousCheckedKeys = mapViewStore.getCheckedLayerKeys();
const { layerConfig, legendOriginal, pageLegend } =
await mapConfigStore.loadPageMapConfig({
systemId: SYSTEM_ID,
@ -122,11 +124,26 @@ export const useMapOrchestrator = () => {
if (layerConfig.length > 0) {
mapStore.setLayerData(layerConfig);
ensureBaseLayersInitialized(layerConfig);
const checkedKeys = mapViewStore.getCheckedLayerKeys();
let checkedKeys = mapViewStore.getCheckedLayerKeys();
if (previousPageKey === pageKey && previousCheckedKeys.length > 0) {
const currentLayerKeys = new Set(
layerConfig
.flatMap((item: any) => layerConfig2Flat([item]))
.map((item: any) => item?.key)
.filter(Boolean)
);
const runtimeCheckedKeys = previousCheckedKeys.filter(key =>
currentLayerKeys.has(key)
);
if (runtimeCheckedKeys.length > 0) {
mapViewStore.setCheckedLayerKeys(runtimeCheckedKeys);
checkedKeys = runtimeCheckedKeys;
}
}
await mapStore.loadAllLayerData(layerConfig, checkedKeys);
}
} finally {
mapDataStore.setLoading(false);
// mapDataStore.setLoading(false);
}
};
@ -380,7 +397,7 @@ export const useMapOrchestrator = () => {
};
// 备注:统一处理搜索定位,按点位编码从缓存数据中查找并飞行到目标位置。
const focusPoint = (pointId: string, zoom: number = 14) => {
const focusPoint = (pointId: string, zoom: number = 15) => {
if (!pointId) return;
const targetPoint = mapDataStore.pointData.find((item: any) => {
return item.stcd === pointId || item._id === pointId;

View File

@ -1,36 +1,73 @@
<template>
<div class="monthly-average-container">
<!-- 搜索表单 -->
<a-form ref="formRef" :model="formValue" layout="inline" class="search-form">
<a-form
ref="formRef"
:model="formValue"
layout="inline"
class="search-form"
>
<a-form-item label="基地名称" name="dataDimensionVal">
<a-select v-model:value="formValue.dataDimensionVal" placeholder="请选择" style="width: 200px"
@change="handleBaseChange">
<a-select-option v-for="item in jdList" :key="item.wbsCode" :value="item.wbsCode">
<a-select
v-model:value="formValue.dataDimensionVal"
placeholder="请选择"
style="width: 200px"
@change="handleBaseChange"
>
<a-select-option
v-for="item in jdList"
:key="item.wbsCode"
:value="item.wbsCode"
>
{{ item.wbsName }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="所在流域" name="rvcd">
<a-select v-model:value="formValue.rvcd" placeholder="请选择" style="width: 200px"
:disabled="!formValue.dataDimensionVal" @change="handleRvcdChange">
<a-select-option v-for="item in lyList" :key="item.value" :value="item.value">
<a-select
v-model:value="formValue.rvcd"
placeholder="请选择"
style="width: 200px"
:disabled="!formValue.dataDimensionVal"
@change="handleRvcdChange"
>
<a-select-option
v-for="item in lyList"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="断面名称" name="stcd">
<a-select v-model:value="formValue.stcd" placeholder="请选择" style="width: 200px" :disabled="!formValue.rvcd">
<a-select-option v-for="item in dmList" :key="item.value" :value="item.value">
<a-select
v-model:value="formValue.stcd"
placeholder="请选择"
style="width: 200px"
:disabled="!formValue.rvcd"
>
<a-select-option
v-for="item in dmList"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="月份" name="tm">
<a-date-picker v-model:value="formValue.tm" picker="month" :disabled-date="disabledDate" format="YYYY-MM"
value-format="YYYY-MM-DD HH:mm:ss" :allow-clear="false" />
<a-date-picker
v-model:value="formValue.tm"
picker="month"
:disabled-date="disabledDate"
format="YYYY-MM"
value-format="YYYY-MM-DD HH:mm:ss"
:allow-clear="false"
/>
</a-form-item>
<a-form-item>
@ -45,8 +82,14 @@
<div style="width: 100%; display: flex">
<!-- 图表容器始终存在不再使用 v-if -->
<div class="chart-wrapper" ref="chartRef"></div>
<BasicTable ref="tableRef" :scrollY="460" :columns="columns" :list-url="DetGetKendoListCust"
:search-params="{ sort: sort }" :transform-data="customTransform">
<BasicTable
ref="tableRef"
:scrollY="460"
:columns="columns"
:list-url="DetGetKendoListCust"
:search-params="{ sort: sort }"
:transform-data="customTransform"
>
<template #action="{ record }">
<a @click="handleViewDetail(record)" class="text_hocer">查看详情</a>
</template>
@ -254,10 +297,10 @@ const fetchLyData = async () => {
},
formValue.dataDimensionVal != 'all'
? {
field: 'fullPath',
operator: 'startswith',
value: formValue.dataDimensionVal
}
field: 'fullPath',
operator: 'startswith',
value: formValue.dataDimensionVal
}
: null
].filter(Boolean)
},
@ -311,15 +354,15 @@ const fetchDmData = async () => {
{ field: 'mway', operator: 'eq', value: 2 },
formValue.dataDimensionVal == 'all'
? {
field: 'rvcd',
operator: 'contains',
value: formValue.rvcd
}
field: 'rvcd',
operator: 'contains',
value: formValue.rvcd
}
: {
field: 'baseId',
operator: 'contains',
value: formValue.dataDimensionVal
}
field: 'baseId',
operator: 'contains',
value: formValue.dataDimensionVal
}
]
},
select: ['stcd', 'stnm', 'lgtd', 'lttd', 'rstcdStepSort'],
@ -816,8 +859,12 @@ const handleViewDetail = (record: any) => {
});
modelStore.modalVisible = true;
modelStore.params.sttp = 'WT';
modelStore.title = stnm ;
modelStore.title = stnm;
modelStore.params.stcd = formValue.stcd;
modelStore.filter.rangeTm = [
dayjs(formValue.value.tm).startOf('month').format('YYYY-MM-DD HH:mm:ss'),
dayjs(formValue.value.tm).endOf('month').format('YYYY-MM-DD HH:mm:ss')
];
};
defineExpose({

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -298,8 +298,12 @@ const handleExport = async () => {};
const handleViewDetail = (record: any) => {
modelStore.modalVisible = true;
modelStore.params.sttp = 'WT';
modelStore.title = record.stnm ;
modelStore.title = record.stnm;
modelStore.params.stcd = record.stcd;
modelStore.filter.rangeTm = [
dayjs(record.dt).startOf('month').format('YYYY-MM-DD HH:mm:ss'),
dayjs(record.dt).endOf('month').format('YYYY-MM-DD HH:mm:ss')
];
};
//

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,42 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="沿程水温变化" :prompt="prompts" :moreSelect="select" :datetimePicker="datetimePicker"
@update-values="handlePanelChange1">
<SidePanelItem
title="沿程水温变化"
:prompt="prompts"
:moreSelect="select"
:datetimePicker="datetimePicker"
@update-values="handlePanelChange1"
>
<a-spin :spinning="loading" tip="加载中...">
<div v-show="showemit && !loading" ref="chartRef" class="chart-container"></div>
<div v-show="!showemit && !loading" class="chart-container"> <a-empty /></div>
<div
v-show="showemit && !loading"
ref="chartRef"
class="chart-container"
></div>
<div v-show="!showemit && !loading" class="chart-container">
<a-empty />
</div>
</a-spin>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, watch, computed } from "vue";
import * as echarts from "echarts";
import type { ECharts } from "echarts";
import SidePanelItem from "@/components/SidePanelItem/index.vue";
import { getKendoListCust, wbsbGetKendoList } from "@/api/sw";
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue';
import * as echarts from 'echarts';
import type { ECharts } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import { getKendoListCust, wbsbGetKendoList } from '@/api/sw';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import { da } from "element-plus/es/locale/index.mjs";
import { f } from "vue-router/dist/router-CWoNjPRp.mjs";
import { useModelStore } from "@/store/modules/model";
import { da } from 'element-plus/es/locale/index.mjs';
import { f } from 'vue-router/dist/router-CWoNjPRp.mjs';
import { useModelStore } from '@/store/modules/model';
const modelStore = useModelStore();
// 便
defineOptions({
name: "yanchengshuiwenChangeMod",
name: 'yanchengshuiwenChangeMod'
});
//
const getCurrentHourTime = () => {
@ -46,21 +54,21 @@ const baseid: any = ref(null);
const paramsOne = {
rvcd: '',
tm: []
}
const dataOne = ref('')
};
const dataOne = ref('');
// 使 computed 使 prompts dataOne.value
const prompts = computed(() => ({
show: true,
value: `注:最新数据时间为${dataOne.value || getCurrentHourTime()}`,
value: `注:最新数据时间为${dataOne.value || getCurrentHourTime()}`
}));
const showemit = ref(false)
const loading = ref(false)
const showemit = ref(false);
const loading = ref(false);
// const selectOptions: any = ref([])
const optionsFmt = (options: any) =>
options.map((item: any) => ({
label: item.wbsName,
value: item.wbsCode
}))
}));
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: ECharts | null = null;
@ -69,7 +77,9 @@ let chartInstance: ECharts | null = null;
const stationNames = ref([]);
// - (°C) null使stcd
const waterTemperatures = ref<{ value: number | null; stcd: string; stnm: string }[]>([]);
const waterTemperatures = ref<
{ value: number | null; stcd: string; stnm: string }[]
>([]);
// 使 computed 使 currentTime dataOne.value
const currentTime = computed(() => dataOne.value || getCurrentHourTime());
@ -79,16 +89,16 @@ const select = ref({
value: '',
options: [],
picker: undefined,
format: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: computed(() => getCurrentHourTime()),
format: "YYYY-MM-DD HH",
picker: "date" as const,
options: [],
format: 'YYYY-MM-DD HH',
picker: 'date' as const,
options: []
});
//
const initChart = () => {
@ -98,14 +108,14 @@ const initChart = () => {
const option = {
title: {
text: "水温(°C)",
text: '水温(°C)',
left: 5,
top: 0,
textStyle: {
color: "#000000",
color: '#000000',
fontSize: 12,
fontWeight: "normal",
},
fontWeight: 'normal'
}
},
dataZoom: [
{
@ -118,7 +128,7 @@ const initChart = () => {
}
],
tooltip: {
trigger: "axis",
trigger: 'axis',
formatter: (params: any) => {
if (params && params.length > 0) {
const data = params[0];
@ -129,31 +139,31 @@ const initChart = () => {
return `${currentTime.value}<br/>${data.name}-`;
}
}
return "";
},
return '';
}
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
top: "15%",
containLabel: true,
left: '3%',
right: '4%',
bottom: '3%',
top: '15%',
containLabel: true
},
xAxis: {
type: "category",
type: 'category',
data: stationNames.value,
boundaryGap: true,
axisLine: {
show: true,
lineStyle: {
color: "#8f8f8f",
},
color: '#8f8f8f'
}
},
axisTick: {
show: false,
show: false
},
axisLabel: {
color: "#333",
color: '#333',
fontSize: 12,
margin: 8,
interval: 0,
@ -166,76 +176,76 @@ const initChart = () => {
} else {
return ` \n${value}`; // + +
}
},
}
},
splitLine: {
show: true,
lineStyle: {
color: "#e0e0e0",
type: "solid",
},
},
color: '#e0e0e0',
type: 'solid'
}
}
},
yAxis: {
type: "value",
type: 'value',
min: 0,
// max: 10,
interval: 2,
axisLine: {
show: true,
lineStyle: {
color: "#8f8f8f",
},
color: '#8f8f8f'
}
},
axisTick: {
show: true,
length: 3,
lineStyle: {
color: "#8f8f8f",
},
color: '#8f8f8f'
}
},
axisLabel: {
color: "#333",
fontSize: 12,
color: '#333',
fontSize: 12
},
splitLine: {
show: true,
lineStyle: {
color: "#e0e0e0",
type: "solid",
},
},
color: '#e0e0e0',
type: 'solid'
}
}
},
series: [
{
name: "水温",
type: "line",
name: '水温',
type: 'line',
smooth: true,
symbol: "circle",
symbol: 'circle',
symbolSize: 6,
connectNulls: true, // 线线
connectNulls: true, // 线线
lineStyle: {
color: "#6ca4f7",
width: 2,
color: '#6ca4f7',
width: 2
},
itemStyle: {
color: "#6ca4f7",
color: '#6ca4f7'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(108, 164, 247, 0.3)",
color: 'rgba(108, 164, 247, 0.3)'
},
{
offset: 1,
color: "rgba(108, 164, 247, 0.05)",
},
]),
color: 'rgba(108, 164, 247, 0.05)'
}
])
},
data: waterTemperatures.value,
},
],
data: waterTemperatures.value
}
]
};
chartInstance.setOption(option);
@ -247,11 +257,12 @@ const initChart = () => {
console.log('stcd:', params.data.stcd);
console.log('stnm:', params.data.stnm);
console.log('temperature:', params.data.value);
console.log('temperature:', paramsOne.tm);
modelStore.modalVisible = true;
modelStore.params.sttp = "WT";
modelStore.params.sttp = 'WT';
modelStore.title = params.data.stnm;
modelStore.params.stcd = params.data.stcd;
modelStore.params.date = paramsOne.tm;
modelStore.filter.rangeTm = [paramsOne.tm[1], paramsOne.tm[0]];
}
});
};
@ -269,33 +280,48 @@ const init = async () => {
try {
const params = {
filter: {
logic: "and",
logic: 'and',
filters: [
{ field: "rvcd", operator: "eq", dataType: "string", value: paramsOne.rvcd },
{ field: "tm", operator: "gte", dataType: "date", value: paramsOne.tm[1] },
{ field: "tm", operator: "lte", dataType: "date", value: paramsOne.tm[0] },
],
{
field: 'rvcd',
operator: 'eq',
dataType: 'string',
value: paramsOne.rvcd
},
{
field: 'tm',
operator: 'gte',
dataType: 'date',
value: paramsOne.tm[1]
},
{
field: 'tm',
operator: 'lte',
dataType: 'date',
value: paramsOne.tm[0]
}
]
},
sort: [{ field: "sort", dir: "asc" }],
sort: [{ field: 'sort', dir: 'asc' }]
};
let res = await getKendoListCust(params);
let data = res.data.data || res.data
let data = res.data.data || res.data;
if (data.length > 0) {
showemit.value = true
showemit.value = true;
} else {
showemit.value = false
showemit.value = false;
}
stationNames.value = data
.filter((item: any) => item.sttp == "1")
.filter((item: any) => item.sttp == '1')
.map((item: any) => item.stnm);
console.log(stationNames.value);
// stcdstnm
waterTemperatures.value = data
.filter((item: any) => item.sttp == "2")
.filter((item: any) => item.sttp == '2')
.map((item: any) => ({
value: item.temperature,
stcd: item.stcd,
@ -311,13 +337,13 @@ const init = async () => {
//
chartInstance.setOption({
xAxis: {
data: stationNames.value,
data: stationNames.value
},
series: [
{
data: waterTemperatures.value,
},
],
data: waterTemperatures.value
}
]
});
}
//
@ -336,11 +362,11 @@ const init = async () => {
const getSelectConfig = async () => {
loading.value = true;
try {
let obj: any = {}
let obj: any = {};
if (baseid.value === 'all') {
obj = { rstcdStepSort: 'asc', siteStepSort: 'asc' }
obj = { rstcdStepSort: 'asc', siteStepSort: 'asc' };
} else {
obj = { siteStepSort: 'asc' }
obj = { siteStepSort: 'asc' };
}
const filters = [
{
@ -348,13 +374,13 @@ const getSelectConfig = async () => {
operator: 'eq',
value: 'PSB_RVCD'
}
]
];
if (baseid.value && baseid.value !== 'all') {
filters.push({
field: 'objId',
operator: 'eq', // contains
value: baseid.value
})
});
}
let data: any = {
filter: {
@ -362,10 +388,10 @@ const getSelectConfig = async () => {
filters
}
// select: ['WBS_CODE', 'WBS_NAME']
}
};
if (obj) {
data.sort = [obj]
data.sort = [obj];
} else {
data = {
...data,
@ -373,31 +399,42 @@ const getSelectConfig = async () => {
{ dir: 'asc', field: 'orderIndex' },
{ dir: 'asc', field: 'wbsCode' },
{ dir: 'asc', field: 'wbsName' },
{ dir: 'asc', field: 'objid' },
{ dir: 'asc', field: 'objid' }
],
groupResultFlat: true
}
};
}
let res = await wbsbGetKendoList(data)
let dataOne = res?.data?.data || res?.data
let res = await wbsbGetKendoList(data);
let dataOne = res?.data?.data || res?.data;
if (dataOne.length > 0) {
let dataMapNameMap: any = {}
let jiDiListMap: any = {}
let dataMapNameMap: any = {};
let jiDiListMap: any = {};
JidiSelectEventStore.jidiData.forEach((item: any) => {
jiDiListMap[item.wbsCode] = item.wbsName
})
jiDiListMap[item.wbsCode] = item.wbsName;
});
dataOne.map((item: any, index: number) => {
const { stcd, stnm, objId } = item
const { stcd, stnm, objId } = item;
if (dataMapNameMap[objId]) {
dataMapNameMap[objId].push({ ...item, baseName: jiDiListMap[objId], baseId: objId })
dataMapNameMap[objId].push({
...item,
baseName: jiDiListMap[objId],
baseId: objId
});
} else {
dataMapNameMap[objId] = [{ ...item, baseName: jiDiListMap[objId], baseId: objId }]
dataMapNameMap[objId] = [
{ ...item, baseName: jiDiListMap[objId], baseId: objId }
];
}
return { label: item.wbsName, value: item.wbsCode, baseId: objId, baseName: jiDiListMap[objId] }
})
let dataMapNameArr: any = []
return {
label: item.wbsName,
value: item.wbsCode,
baseId: objId,
baseName: jiDiListMap[objId]
};
});
let dataMapNameArr: any = [];
Object.keys(dataMapNameMap).forEach((item: any) => {
dataMapNameArr.push({
@ -409,24 +446,29 @@ const getSelectConfig = async () => {
return {
title: item2.wbsName,
value: item2.wbsCode
}
};
})
})
})
});
});
dataMapNameArr = dataMapNameArr.sort((a: any, b: any) => {
const indexA = JidiSelectEventStore.jidiData.findIndex(item => item.wbsCode === a.value);
const indexB = JidiSelectEventStore.jidiData.findIndex(item => item.wbsCode === b.value);
const indexA = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === a.value
);
const indexB = JidiSelectEventStore.jidiData.findIndex(
item => item.wbsCode === b.value
);
return indexA - indexB;
})
select.value.options = filterSelectOptions(dataMapNameArr)
});
select.value.options = filterSelectOptions(dataMapNameArr);
if (baseid.value === 'all') {
select.value.value = 'SJLY1U'
select.value.value = 'SJLY1U';
} else if (filterSelectOptions(dataMapNameArr)[0]?.children) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value
select.value.value =
filterSelectOptions(dataMapNameArr)[0]?.children[0]?.value;
} else if (filterSelectOptions(dataMapNameArr)[0]?.value) {
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.value
select.value.value = filterSelectOptions(dataMapNameArr)[0]?.value;
} else {
select.value.value = ''
select.value.value = '';
}
}
} catch (error) {
@ -434,31 +476,39 @@ const getSelectConfig = async () => {
} finally {
loading.value = false;
}
}
};
const filterSelectOptions = (selectOptions: any) => {
if (selectOptions?.length === 1 && selectOptions?.[0]?.children?.length === 1) {
return [{ ...selectOptions?.[0]?.children?.[0], isLeaf: true }]
if (
selectOptions?.length === 1 &&
selectOptions?.[0]?.children?.length === 1
) {
return [{ ...selectOptions?.[0]?.children?.[0], isLeaf: true }];
} else if (selectOptions.length) {
return selectOptions.map((e) => {
return selectOptions.map(e => {
if (e?.children?.length > 1) {
return { ...e, isLeaf: false, selectable: true, children: e.children.map((item) => ({ ...item, isLeaf: true })) }
return {
...e,
isLeaf: false,
selectable: true,
children: e.children.map(item => ({ ...item, isLeaf: true }))
};
} else {
return { ...e.children[0], isLeaf: true }
return { ...e.children[0], isLeaf: true };
}
})
});
}
return []
}
return [];
};
//
const handlePanelChange1 = (data) => {
const handlePanelChange1 = data => {
console.log('当前所有控件状态:', data);
if (data.moreSelect) {
paramsOne.rvcd = data.moreSelect
paramsOne.rvcd = data.moreSelect;
}
if (data.datetime) {
dataOne.value = data.datetime
dataOne.value = data.datetime;
const datetime = data.datetime;
//
@ -466,7 +516,14 @@ const handlePanelChange1 = (data) => {
const [year, month, day] = datePart.split('-').map(Number);
// Date
const currentDate = new Date(year, month - 1, day, parseInt(hourPart), 0, 0);
const currentDate = new Date(
year,
month - 1,
day,
parseInt(hourPart),
0,
0
);
// Date
const previousDate = new Date(year, month - 2, day, 0, 0, 0);
@ -484,23 +541,22 @@ const handlePanelChange1 = (data) => {
//
const result = [
formatDate(currentDate), // "2026-05-15 15:00:00"
formatDate(previousDate) // "2026-04-15 00:00:00"
formatDate(currentDate), // "2026-05-15 15:00:00"
formatDate(previousDate) // "2026-04-15 00:00:00"
];
paramsOne.tm = result
console.log(paramsOne.tm, 'paramsOne.tm')
paramsOne.tm = result;
console.log(paramsOne.tm, 'paramsOne.tm');
}
if (paramsOne.rvcd || paramsOne.tm.length > 0) {
init();
}
}
};
watch(
() => JidiSelectEventStore.selectedItem,
(newVal) => {
newVal => {
baseid.value = newVal.wbsCode;
getSelectConfig()
getSelectConfig();
},
{ deep: true, immediate: true }
);
@ -508,12 +564,12 @@ watch(
onMounted(() => {
// DOM
init();
window.addEventListener("resize", handleResize);
window.addEventListener('resize', handleResize);
});
//
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
</script>