From fd16dd684cde186443c03eabc343db0e3fbb18f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=88=E5=85=86=E5=A2=9E?= <你的邮箱@example.com> Date: Tue, 9 Jun 2026 11:44:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9E=82=E5=90=91=E6=B0=B4?= =?UTF-8?q?=E6=B8=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/mapModal/index.ts | 27 + frontend/src/components/BasicTable/index.vue | 42 +- .../MapModal/components/MonitorInfo.vue | 720 +++++++----- .../components/VerticalWaterTemperature.vue | 628 ++++++++++ .../MapModal/components/WaterTemperature.vue | 1020 +++++++++++++++++ .../components/charts/PowerStationChart.vue | 315 ----- .../components/charts/WaterTempChart.vue | 505 -------- .../composables/useWaterTempTable.ts | 399 ------- frontend/src/components/MapModal/index.vue | 18 +- .../src/components/MapModal/setting.config.ts | 4 +- 10 files changed, 2178 insertions(+), 1500 deletions(-) create mode 100644 frontend/src/components/MapModal/components/VerticalWaterTemperature.vue create mode 100644 frontend/src/components/MapModal/components/WaterTemperature.vue delete mode 100644 frontend/src/components/MapModal/components/charts/PowerStationChart.vue delete mode 100644 frontend/src/components/MapModal/components/charts/WaterTempChart.vue delete mode 100644 frontend/src/components/MapModal/components/composables/useWaterTempTable.ts diff --git a/frontend/src/api/mapModal/index.ts b/frontend/src/api/mapModal/index.ts index 9afcc47c..d7aa32a9 100644 --- a/frontend/src/api/mapModal/index.ts +++ b/frontend/src/api/mapModal/index.ts @@ -78,6 +78,33 @@ export function getMonitorDataWaterTempPowerStation(params: any) { params }); } +// 监测数据 - 水温 - 、综合分析导出数据 +export function exportMonitorDataWaterTempPowerStation(params: any) { + return request({ + url: '/api/wmp-env-server/sw/alongDetail/qgc/GetKendoListCust', + method: 'post', + params, + responseType: 'blob' + }); +} + +// 监测数据 - 水温 - 查询是否显示 等温水深 +export function getMonitorDataWaterTempPowerStation2(params: any) { + return request({ + url: '/api/wmp-env-server/sw/alongDetail/qgc/stcdCheck2', + method: 'get', + params + }); +} +// 监测数据 - 垂向水温 + +export function getMonitorDataWaterTempVertical(data: any) { + return request({ + url: '/api/wmp-env-server/sw/cxDetail/GetKendoListCust', + method: 'post', + data + }); +} // 生态流量 - 限制范围查询 - 日 export function getEngLimitDay(data: any) { return request({ diff --git a/frontend/src/components/BasicTable/index.vue b/frontend/src/components/BasicTable/index.vue index 823b91c6..561d4247 100644 --- a/frontend/src/components/BasicTable/index.vue +++ b/frontend/src/components/BasicTable/index.vue @@ -51,7 +51,9 @@ interface Props { searchParams?: Record; defaultPageSize?: number; isPage?: boolean; + defaultSelectedRowKeys?: string[]; getCheckboxProps?: (record: any) => any; + minSelectionCount?: number; // 最小选中数量,0表示无限制 transformData?: (res: any) => { records: any[]; total: number }; emptyPlaceholder?: string; // 新增:空值占位符 processEmptyValues?: boolean; // 新增:是否开启空值处理 @@ -66,7 +68,9 @@ const props = withDefaults(defineProps(), { data: () => [], searchParams: () => ({}), defaultPageSize: 20, + defaultSelectedRowKeys: () => [], getCheckboxProps: undefined, + minSelectionCount: 0, transformData: undefined, scrollY: undefined, emptyPlaceholder: '-', @@ -90,7 +94,7 @@ const tableData = ref([]); const total = ref(0); const page = ref(1); const size = ref(props.defaultPageSize); -const selectedRowKeys = ref([]); +const selectedRowKeys = ref([...props.defaultSelectedRowKeys]); const selectedRows = ref([]); const lastFilter = ref | undefined>(undefined); const tableContainerRef = ref(null); @@ -124,6 +128,16 @@ const scrollConfig = computed(() => { const rowSelection = computed(() => ({ selectedRowKeys: selectedRowKeys.value, onChange: (keys: string[], rows: any[]) => { + // 至少保留 minSelectionCount 条勾选,如果取消后低于最小值则恢复默认第一条 + if ( + props.minSelectionCount > 0 && + keys.length < props.minSelectionCount && + props.data.length > 0 + ) { + const firstKey = props.data[0][props.rowKey]; + keys = [firstKey]; + rows = [props.data[0]]; + } selectedRowKeys.value = keys; selectedRows.value = rows; emit('selection-change', keys, rows); @@ -248,6 +262,32 @@ const observer = new ResizeObserver(() => { tableScrollY.value = calcTableScrollY(tableContainerRef.value); }); +watch( + () => props.data, + newData => { + if (newData && newData.length > 0) { + // If defaultSelectedRowKeys is provided, reset selection + if ( + props.defaultSelectedRowKeys && + props.defaultSelectedRowKeys.length > 0 + ) { + selectedRowKeys.value = [...props.defaultSelectedRowKeys]; + selectedRows.value = newData.filter(row => + props.defaultSelectedRowKeys.includes(row[props.rowKey]) + ); + } else { + // Otherwise clear selection when data changes + selectedRowKeys.value = []; + selectedRows.value = []; + } + } else { + selectedRowKeys.value = []; + selectedRows.value = []; + } + }, + { deep: true } +); + // --- 空值处理工具函数 --- const processData = (records: any[]) => { if (!props.processEmptyValues || !Array.isArray(records)) return records; diff --git a/frontend/src/components/MapModal/components/MonitorInfo.vue b/frontend/src/components/MapModal/components/MonitorInfo.vue index ccd7b7cf..7738e8e8 100644 --- a/frontend/src/components/MapModal/components/MonitorInfo.vue +++ b/frontend/src/components/MapModal/components/MonitorInfo.vue @@ -1,98 +1,42 @@ diff --git a/frontend/src/components/MapModal/components/VerticalWaterTemperature.vue b/frontend/src/components/MapModal/components/VerticalWaterTemperature.vue new file mode 100644 index 00000000..b97ef4b3 --- /dev/null +++ b/frontend/src/components/MapModal/components/VerticalWaterTemperature.vue @@ -0,0 +1,628 @@ + + + + + diff --git a/frontend/src/components/MapModal/components/WaterTemperature.vue b/frontend/src/components/MapModal/components/WaterTemperature.vue new file mode 100644 index 00000000..d6ee354c --- /dev/null +++ b/frontend/src/components/MapModal/components/WaterTemperature.vue @@ -0,0 +1,1020 @@ + + + + + diff --git a/frontend/src/components/MapModal/components/charts/PowerStationChart.vue b/frontend/src/components/MapModal/components/charts/PowerStationChart.vue deleted file mode 100644 index e9c7067e..00000000 --- a/frontend/src/components/MapModal/components/charts/PowerStationChart.vue +++ /dev/null @@ -1,315 +0,0 @@ - - - - - diff --git a/frontend/src/components/MapModal/components/charts/WaterTempChart.vue b/frontend/src/components/MapModal/components/charts/WaterTempChart.vue deleted file mode 100644 index 7a031031..00000000 --- a/frontend/src/components/MapModal/components/charts/WaterTempChart.vue +++ /dev/null @@ -1,505 +0,0 @@ - - - - - diff --git a/frontend/src/components/MapModal/components/composables/useWaterTempTable.ts b/frontend/src/components/MapModal/components/composables/useWaterTempTable.ts deleted file mode 100644 index e9334696..00000000 --- a/frontend/src/components/MapModal/components/composables/useWaterTempTable.ts +++ /dev/null @@ -1,399 +0,0 @@ -import { ref, computed } from 'vue'; -import dayjs from 'dayjs'; - -/** - * 水温表格相关逻辑(Checkbox、表格列、合计行) - */ -export function useWaterTempTable(chartData: any[], activeTabKey: any) { - const selectedColumns = ref([]); - - // ==================== Checkbox 配置 ==================== - const checkBoxOptions = [ - { label: '综合分析', value: 'summary' }, - { label: '等深水温', value: 'deep' } - ]; - - const showSummaryCheckbox = ref(false); // ioWtrv - const showDeepCheckbox = ref(false); // hasRstcdWtvt - const isDataEmpty = computed( - () => !Array.isArray(chartData.value) || chartData.value.length === 0 - ); - - // 根据 powerStationRes 数据 + 互斥逻辑 动态过滤 checkbox 选项 - const filteredCheckBoxOptions = computed(() => { - if (activeTabKey.value !== 'swjc.tabs.jcsj') return []; - if (isDataEmpty.value) return []; - - const selected = selectedColumns.value; - const hasSelected = selected.length > 0; - const selectedValue = selected[0]; - - return checkBoxOptions.filter(opt => { - if (opt.value === 'summary' && !showSummaryCheckbox.value) return false; - if (opt.value === 'deep' && !showDeepCheckbox.value) return false; - if (hasSelected) { - return opt.value === selectedValue; - } - return true; - }); - }); - - const isDeepMode = computed(() => selectedColumns.value.includes('deep')); - const isSummaryMode = computed(() => - selectedColumns.value.includes('summary') - ); - - const currentChartMode = computed(() => { - if (isSummaryMode.value) return 'summary'; - if (isDeepMode.value) return 'deep'; - return 'base'; - }); - - // Checkbox 变化处理 - const handleCheckboxChange = (values: any[], fetchData: () => void) => { - const hasSummary = values.includes('summary'); - const hasDeep = values.includes('deep'); - - if (hasSummary && hasDeep) { - selectedColumns.value = [values[values.length - 1]]; - } else { - selectedColumns.value = values; - } - - fetchData(); - }; - - // ==================== 表格列配置 ==================== - const baseWaterTempColumns = [ - { - title: '时间', - dataIndex: 'tm', - fixed: 'left', - customRender: ({ text }: any) => - text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '-' - }, - { - title: '水温(°C)', - dataIndex: 'wt', - summary: true, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(1) : '-' - } - ]; - - const deepModeExtraColumns = [ - { - title: '等温水深(m)', - dataIndex: 'deep_wt', - summary: true, - customRender: ({ record }: any) => { - const val = record?.wtvtDataVo?.wthg; - return val !== undefined && val !== null ? Number(val).toFixed(2) : '-'; - } - }, - { - title: '垂向水温(℃)', - dataIndex: 'vert_wt', - summary: true, - customRender: ({ record }: any) => { - const val = record?.wtvtDataVo?.vwt; - return val !== undefined && val !== null ? Number(val).toFixed(1) : '-'; - } - } - ]; - - const summaryModeColumns = [ - { - title: '时间', - dataIndex: 'tm', - width: 130, - fixed: 'left', - customRender: ({ text }: any) => - text ? dayjs(text).format('YYYY-MM-DD HH:mm') : '-' - }, - { - title: '出库水温(℃)', - dataIndex: 'wt', - summary: true, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(1) : '-' - }, - { - title: '入库水温(℃)', - dataIndex: 'iwt_wt', - summary: true, - customRender: ({ record }: any) => - record?.iwtDataVo?.wt !== undefined && record?.iwtDataVo?.wt !== null - ? Number(record.iwtDataVo.wt).toFixed(1) - : '-' - }, - { - title: '天然水温(°C)', - dataIndex: 'natureTmp', - summary: true, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(1) : '-' - }, - { - title: '气温(℃)', - dataIndex: 'tmp_at', - summary: true, - width: 80, - customRender: ({ record }: any) => - record?.tmpDataVo?.at !== undefined && record?.tmpDataVo?.at !== null - ? Number(record.tmpDataVo.at).toFixed(1) - : '-' - }, - { - title: '出库流量(m³/s)', - dataIndex: 'hydropw_qo', - summary: true, - width: 120, - customRender: ({ record }: any) => - record?.hydropwDataVo?.qo !== undefined && - record?.hydropwDataVo?.qo !== null - ? Number(record.hydropwDataVo.qo).toFixed(3) - : '-' - }, - { - title: '入库流量(m³/s)', - dataIndex: 'hydropw_qi', - summary: true, - width: 120, - customRender: ({ record }: any) => - record?.hydropwDataVo?.qi !== undefined && - record?.hydropwDataVo?.qi !== null - ? Number(record.hydropwDataVo.qi).toFixed(3) - : '-' - } - ]; - - const tableColumnsConfig: Record = { - 'dzxq.tabs.jcsj': [ - { - title: '时间', - dataIndex: 'tm', - width: 180, - fixed: 'left', - customRender: ({ text }: any) => - text ? dayjs(text).format('YYYY-MM-DD HH:mm:ss') : '-' - }, - { - title: '坝上水位(m)', - dataIndex: 'rz', - width: 130, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(2) : '-' - }, - { - title: '坝下水位(m)', - dataIndex: 'dz', - width: 130, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(2) : '-' - }, - { - title: '入库流量(m³/s)', - dataIndex: 'qi', - width: 130, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Math.round(Number(text)) : '-' - }, - { - title: '出库流量(m³/s)', - dataIndex: 'qo', - width: 130, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text) : '-' - }, - { - title: '生态流量(m³/s)', - dataIndex: 'qec', - width: 130, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(1) : '-' - }, - { - title: '生态流量限值(m³/s)', - dataIndex: 'qecLimit', - width: 150, - customRender: ({ text }: any) => - text !== undefined && text !== null ? Number(text).toFixed(1) : '-' - } - ], - 'swjc.tabs.jcsj': [] - }; - - const swjcColumns = computed(() => { - if (isSummaryMode.value) { - return summaryModeColumns; - } - if (isDeepMode.value) { - return [...baseWaterTempColumns, ...deepModeExtraColumns]; - } - return baseWaterTempColumns; - }); - - const currentColumns = computed(() => { - if (activeTabKey.value === 'swjc.tabs.jcsj') { - return swjcColumns.value; - } - return ( - tableColumnsConfig[activeTabKey.value] || - tableColumnsConfig['dzxq.tabs.jcsj'] - ); - }); - - const tableScrollX = computed(() => { - const columns = currentColumns.value; - const totalWidth = columns.reduce( - (sum: number, col: any) => sum + (col.width || 100), - 0 - ); - return totalWidth > 600 ? totalWidth : undefined; - }); - - // ==================== 合计行配置 ==================== - const dataPathMap: Record = { - wt: 'wt', - iwt_wt: 'iwtDataVo.wt', - natureTmp: 'natureTmp', - tmp_at: 'tmpDataVo.at', - hydropw_qo: 'hydropwDataVo.qo', - hydropw_qi: 'hydropwDataVo.qi', - deep_wt: 'wtvtDataVo.wthg', - vert_wt: 'wtvtDataVo.vwt' - }; - - const summaryColumns = computed(() => { - if (activeTabKey.value !== 'swjc.tabs.jcsj') return []; - const cols = currentColumns.value - .filter((col: any) => col.summary === true) - .map((col: any, idx: number) => ({ - ...col, - summaryIndex: idx + 1 - })); - return cols; - }); - - const getNestedValue = (obj: any, path: string) => { - if (!path || !obj) return undefined; - return path.split('.').reduce((acc, key) => acc?.[key], obj); - }; - - const calcSummary = (dataIndex: string, type: 'max' | 'min' | 'avg') => { - const data = Array.isArray(chartData.value) ? chartData.value : []; - if (!data || data.length === 0) return null; - - const dataPath = dataPathMap[dataIndex] || dataIndex; - const values = data - .map((r: any) => { - const val = getNestedValue(r, dataPath); - return val !== null && val !== undefined && val !== '-' - ? Number(val) - : NaN; - }) - .filter((v: number) => !isNaN(v)); - - if (values.length === 0) return null; - - if (type === 'max') return Math.max(...values); - if (type === 'min') return Math.min(...values); - return values.reduce((s, v) => s + v, 0) / values.length; - }; - - const getSummaryTime = (dataIndex: string, type: 'max' | 'min') => { - const data = Array.isArray(chartData.value) ? chartData.value : []; - if (!data || data.length === 0) return ''; - - const dataPath = dataPathMap[dataIndex] || dataIndex; - const records = data.filter((r: any) => { - const val = getNestedValue(r, dataPath); - return val !== null && val !== undefined && val !== '-'; - }); - if (records.length === 0) return ''; - - const target = Math[type]( - ...records.map((r: any) => Number(getNestedValue(r, dataPath))) - ); - const record = records.find( - (r: any) => Number(getNestedValue(r, dataPath)) === target - ); - return record?.tm ? dayjs(record.tm).format('YYYY-MM-DD HH:mm:ss') : ''; - }; - - const formatSummaryValue = (dataIndex: string, value: number | null) => { - if (value === null) return '-'; - if (dataIndex.includes('qo') || dataIndex.includes('qi')) { - return Number(value).toFixed(3); - } - if (dataIndex === 'deep_wt') { - return Number(value).toFixed(2); - } - return Number(value).toFixed(1); - }; - - const summaryRows = computed(() => { - if (activeTabKey.value !== 'swjc.tabs.jcsj') return []; - if (isDataEmpty.value) return []; - - const rows = [ - { - label: '最大值', - showTime: true, - cells: {} as Record - }, - { - label: '最小值', - showTime: true, - cells: {} as Record - }, - { - label: '平均值', - showTime: false, - cells: {} as Record - } - ]; - - summaryColumns.value.forEach((col: any) => { - const dataIndex = col.dataIndex; - const maxVal = calcSummary(dataIndex, 'max'); - const minVal = calcSummary(dataIndex, 'min'); - const avgVal = calcSummary(dataIndex, 'avg'); - - rows[0].cells[dataIndex] = { - value: formatSummaryValue(dataIndex, maxVal), - time: maxVal !== null ? getSummaryTime(dataIndex, 'max') : '' - }; - rows[1].cells[dataIndex] = { - value: formatSummaryValue(dataIndex, minVal), - time: minVal !== null ? getSummaryTime(dataIndex, 'min') : '' - }; - rows[2].cells[dataIndex] = { - value: formatSummaryValue(dataIndex, avgVal), - time: '' - }; - }); - - return rows; - }); - - return { - // state - selectedColumns, - showSummaryCheckbox, - showDeepCheckbox, - isDataEmpty, - // computed - filteredCheckBoxOptions, - isDeepMode, - isSummaryMode, - currentChartMode, - currentColumns, - tableScrollX, - summaryColumns, - summaryRows, - // methods - handleCheckboxChange - }; -} diff --git a/frontend/src/components/MapModal/index.vue b/frontend/src/components/MapModal/index.vue index 25931267..d81a9c8e 100644 --- a/frontend/src/components/MapModal/index.vue +++ b/frontend/src/components/MapModal/index.vue @@ -16,6 +16,7 @@ 4. 预警提示 少接口 5. 生态流量 达标率查询不对 6. 鱼类适应性繁殖同期对比NAN (王) + 7. 出库水温 综合分析 导出没做 -->
- + + + + + = [ name: '监测数据', key: 'WaterTemperature', type: 'WaterTemperature', + code: 'swjc.tabs.jcsj', default: true // 默认显示 }, // { @@ -770,7 +771,8 @@ const WTTabs1: Array = [ name: '监测数据', key: 'VerticalWaterTemperature', type: 'VerticalWaterTemperature', - default: true // 默认显示 + code: 'cxsw.tabs.jcsj', + default: true // 默认显示 } ];