WholeProcessPlatform/frontend-sjgl/src/views/monitorData/FlowData/index.vue
2026-08-20 09:23:32 +08:00

623 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="w-full h-full flex flex-col pt-[20px] pl-[20px] body_one">
<!-- 搜索组件 -->
<FlowDataSearch
@export-btn="exportBtn"
@search-finish="onSearchFinish"
@reset="onReset"
@seeEdit="handleSeeEdit"
@batch-delete="handleBatchDelete"
:show-batch-delete="currentSearchParams.timeScale === 'tm'"
:selected-count="selectedRowKeys.length"
:exportLoading="exportLoading"
ref="searchRef"
/>
<!-- 表格组件 -->
<BasicTable
ref="tableRef"
:enable-row-selection="currentSearchParams.timeScale === 'tm'"
:scrollX="tableScrollX"
:scrollY="tableScrollY"
:columns="displayColumns"
:list-url="currentListUrl"
:searchParams="{
sort: sort
}"
@selection-change="handleSelectionChange"
>
<template #action="{ record }">
<template v-if="currentSearchParams.timeScale === 'tm'">
<a-button
type="link"
class="text-[#2f6b98]"
size="small"
@click="handleEdit(record)"
>编辑</a-button
>
<a-button
type="link"
danger
size="small"
@click="handleDelete(record)"
>删除</a-button
>
</template>
</template>
</BasicTable>
<!-- 编辑生态流量数据 Modal -->
<EditFlowDataModal
v-model:open="editVisible"
:record="editRecord"
@success="handleEditSuccess"
/>
<!-- 删除确认 Modal -->
<DeleteConfirmModal
ref="deleteModalRef"
:delete-fn="handleDeleteFn"
:label="deleteLabel"
:title="'删除' + deleteLabel"
@success="handleEditSuccess"
/>
<!-- 操作日志弹框 -->
<OperationLogModal
v-model:open="operationLogVisible"
:table-name="operationTableName"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, nextTick, h } from 'vue';
import dayjs from 'dayjs';
import FlowDataSearch from './FlowDataSearch.vue';
import EditFlowDataModal from './EditFlowDataModal.vue';
import DeleteConfirmModal from '@/views/conventionalHydropower/BasicData/DeleteConfirmModal.vue';
import OperationLogModal from '@/components/OperationLogModal/index.vue';
import { Tooltip, message } from 'ant-design-vue';
import BasicTable from '@/components/BasicTable/index.vue';
import {
getFlowDataList,
getFlowDataDayList,
getFlowDataMonthList,
deleteFlowDataInfo
} from '@/api/DataQueryMenuModule';
import { calcTableScrollY } from '@/utils/index';
import { buildTimeFilters } from '@/utils/buildTimeFilters';
const currentSearchParams = ref<any>({});
const sort = computed(() => {
return [
{ field: 'baseStepSort', dir: 'asc' },
{ field: 'rvcdStepSort', dir: 'asc' },
{ field: 'siteStepSort', dir: 'asc' },
currentSearchParams.value.timeScale == 'tm'
? { field: 'tm', dir: 'desc' }
: null,
currentSearchParams.value.timeScale == 'dt'
? { field: 'dt', dir: 'desc' }
: null,
currentSearchParams.value.timeScale == 'month'
? { field: 'year', dir: 'desc' }
: null,
currentSearchParams.value.timeScale == 'month'
? { field: 'month', dir: 'desc' }
: null
].filter(Boolean);
});
const tableRef = ref();
const searchRef = ref();
const tableScrollY = ref<string | number>(0);
const exportLoading = ref(false);
// 编辑/删除相关
const editVisible = ref(false);
const editRecord = ref<any>(null);
const deleteModalRef = ref();
const operationLogVisible = ref(false);
const deleteLabel = '生态流量数据';
// TODO: 操作日志表名待确认
const operationTableName = 'SD_QEC_R';
// 多选相关
const selectedRowKeys = ref<string[]>([]);
const selectedRows = ref<any[]>([]);
const handleSelectionChange = (keys: string[], rows: any[]) => {
selectedRowKeys.value = keys;
selectedRows.value = rows;
};
// 根据 timeScale 动态切换 API
const currentListUrl = computed(() => {
const timeScale = currentSearchParams.value.timeScale;
if (timeScale === 'dt') return getFlowDataDayList;
if (timeScale === 'month') return getFlowDataMonthList;
return getFlowDataList; // 默认 tm小时
});
const tableScrollX = computed(() =>
Math.max(
displayColumns.value.reduce(
(sum: number, col: any) => sum + (col.width || 180),
0
),
600
)
);
// 基础列(始终显示)
const baseColumns: any = [
{
key: 'stnm',
title: '电站名称',
dataIndex: 'stnm',
visible: true,
width: 150,
sort: true,
fixed: 'left',
ellipsis: true
},
{
key: 'baseName',
title: '基地',
dataIndex: 'baseName',
visible: true,
width: 150,
sort: true,
fixed: 'left',
ellipsis: true
},
{
key: 'tm',
title: '时间',
dataIndex: 'tm',
visible: true,
width: 150,
sort: true,
fixed: 'left',
ellipsis: true
},
{
key: 'qi',
title: '入库流量(m³/s)',
dataIndex: 'qi',
visible: true,
width: 150,
sort: true,
ellipsis: true,
customRender: ({ text }) => {
return text ? Number(text).toFixed(1) : '-';
}
},
{
key: 'qec',
title: '生态流量值(m³/s)',
dataIndex: 'qec',
visible: true,
sort: true,
width: 150,
ellipsis: true,
customRender: ({ text }) => {
return text ? Number(text).toFixed(1) : '-';
}
}
];
// 可控制显示的列
const ruleColumnsMap: any = {
'': [
// 全部 - 显示所有
{
key: 'qecLimit',
title: '生态环境部限值要求(m³/s)',
dataIndex: 'qecLimit',
visible: true,
sort: true,
width: 200,
ellipsis: true
},
{
key: 'sfdb',
// title: '生态流量是否达标',
dataIndex: 'sfdbName',
visible: true,
sort: true,
width: 170,
title: () =>
h('span', { style: 'display:flex;align-items:center;gap:4px' }, [
'生态流量是否达标',
h(
Tooltip,
{
title: h('ol', {}, [
h('li', {}, '达标判定规则:'),
h(
'li',
{},
'a)环评中对生态流量限值有明确要求的,按环评要求评判,'
),
h(
'li',
{},
'b)环评中未对生态流量限值有明确要求的,按水利部要求评判,'
),
h(
'li',
{},
'c)无环评要求、无水利部要求的按多年平均流量的10%作为评判依据,'
),
h('li', {}, 'd)当来水不足时,生态流量不小于入库流量判定达标,')
])
},
{
default: () =>
h('i', {
class: 'iconfont icon-iconQuestion'
})
}
)
])
},
{
key: 'mwrLimit',
title: '水利部限值要求(m³/s)',
dataIndex: 'mwrLimit',
visible: true,
width: 180,
sort: true,
ellipsis: true
},
{
key: 'mwrSfdb',
dataIndex: 'mwrSfdbName',
visible: true,
sort: true,
width: 180,
title: () =>
h('span', { style: 'display:flex;align-items:center;gap:4px' }, [
'水利部要求是否达标',
h(
Tooltip,
{
title: h('ol', {}, [
h('li', {}, '达标判定规则:'),
h(
'li',
{},
'a)环评中对生态流量限值有明确要求的,按环评要求评判,'
),
h(
'li',
{},
'b)环评中未对生态流量限值有明确要求的,按水利部要求评判,'
),
h(
'li',
{},
'c)无环评要求、无水利部要求的按多年平均流量的10%作为评判依据,'
),
h('li', {}, 'd)当来水不足时,生态流量不小于入库流量判定达标,')
])
},
{
default: () =>
h('i', {
class: 'iconfont icon-iconQuestion'
})
}
)
])
},
{
key: 'avqLimit',
title: '多年平均流量(m³/s)',
dataIndex: 'avqLimit',
visible: true,
sort: true,
width: 160
},
{
key: 'avqSfdb',
dataIndex: 'avqSfdbName',
visible: true,
sort: true,
width: 230,
title: () =>
h('span', { style: 'display:flex;align-items:center;gap:4px' }, [
'多年平均流量*10%是否达标',
h(
Tooltip,
{
title: h('ol', {}, [
h('li', {}, '达标判定规则:'),
h(
'li',
{},
'a)环评中对生态流量限值有明确要求的,按环评要求评判,'
),
h(
'li',
{},
'b)环评中未对生态流量限值有明确要求的,按水利部要求评判,'
),
h(
'li',
{},
'c)无环评要求、无水利部要求的按多年平均流量的10%作为评判依据,'
),
h('li', {}, 'd)当来水不足时,生态流量不小于入库流量判定达标,')
])
},
{
default: () =>
h('i', {
class: 'iconfont icon-iconQuestion'
})
}
)
])
}
],
sfdb: [
// 环评要求
{
key: 'qecLimit',
title: '生态环境部限值要求(m³/s)',
dataIndex: 'qecLimit',
visible: true,
sort: true,
width: 200,
ellipsis: true
},
{
key: 'sfdb',
title: '生态流量是否达标',
dataIndex: 'sfdbName',
visible: true,
sort: true,
width: 150
}
],
mwrSfdb: [
// 水利部要求
{
key: 'mwrLimit',
title: '水利部限值要求(m³/s)',
dataIndex: 'mwrLimit',
visible: true,
width: 180,
sort: true,
ellipsis: true
},
{
key: 'mwrSfdb',
title: '水利部要求是否达标',
dataIndex: 'mwrSfdbName',
visible: true,
sort: true,
width: 150
}
],
avqSfdb: [
// 多年平均流量10%
{
key: 'avqLimit',
title: '多年平均流量(m³/s)',
dataIndex: 'avqLimit',
visible: true,
sort: true,
width: 150
},
{
key: 'avqSfdb',
title: '多年平均流量*10%是否达标',
dataIndex: 'avqSfdbName',
visible: true,
sort: true,
width: 200
}
],
wstllyq: [] // 无生态流量要求 - 不显示
};
// 根据 ruleType 动态计算列
const displayColumns = computed(() => {
const ruleType = currentSearchParams.value.ruleType ?? '';
const ruleColumns = ruleColumnsMap[ruleType] || ruleColumnsMap[''];
const columns: any[] = [...baseColumns, ...ruleColumns];
// 仅 timeScale === 'tm' 时显示操作列
if (currentSearchParams.value.timeScale === 'tm') {
columns.push({
key: 'action',
title: '操作',
dataIndex: 'action',
fixed: 'right',
width: 120
});
}
return columns;
});
const onSearchFinish = async (values: any) => {
currentSearchParams.value = values;
// 切换查询条件时清空选中
selectedRowKeys.value = [];
selectedRows.value = [];
tableRef.value?.clearSelection();
await nextTick();
initTable(values);
};
const onReset = async (values: any) => {
currentSearchParams.value = values;
// 切换查询条件时清空选中
selectedRowKeys.value = [];
selectedRows.value = [];
tableRef.value?.clearSelection();
await nextTick();
initTable(values);
};
const exportBtn = () => {
if (exportLoading.value) return;
exportLoading.value = true;
searchRef.value.btnLoading = true;
tableRef.value
.exportTable({
fileName: `生态流量运行数据_${dayjs().format('YYYY-MM-DD HH-mm-ss')}`
})
.finally(() => {
exportLoading.value = false;
searchRef.value.btnLoading = false;
});
};
// 构建 ruleType 过滤条件
const buildRuleTypeFilters = (ruleType: string) => {
// 全部:不传
if (ruleType === '' || ruleType === undefined) return [];
// 环评要求
if (ruleType === 'sfdb') {
return [{ field: 'sfdb', operator: 'neq', dataType: 'string', value: '3' }];
}
// 水利部要求
if (ruleType === 'mwrSfdb') {
return [
{ field: 'mwrSfdb', operator: 'neq', dataType: 'string', value: '3' }
];
}
// 多年平均流量10%
if (ruleType === 'avqSfdb') {
return [
{ field: 'avqSfdb', operator: 'neq', dataType: 'string', value: '3' }
];
}
// 无生态流量要求:三个都不达标
if (ruleType === 'wstllyq') {
return [
{ field: 'sfdb', operator: 'eq', dataType: 'string', value: '3' },
{ field: 'mwrSfdb', operator: 'eq', dataType: 'string', value: '3' },
{ field: 'avqSfdb', operator: 'eq', dataType: 'string', value: '3' }
];
}
return [];
};
const initTable = (values: any) => {
const filters = [
values.rvcd && values.rvcd !== 'all'
? {
field: 'rvcd',
operator: 'contains',
dataType: 'string',
value: values.rvcd
}
: null,
values.rstcd
? {
field: 'stcd',
operator: 'eq',
dataType: 'string',
value: values.rstcd
}
: null,
...buildRuleTypeFilters(values.ruleType),
...buildTimeFilters(values)
].filter(Boolean);
const params = {
logic: 'and',
filters
};
tableRef.value.getList(params);
};
// 编辑
const handleEdit = (record: any) => {
editRecord.value = { ...record };
editVisible.value = true;
};
// 编辑成功回调
const handleEditSuccess = () => {
initTable(currentSearchParams.value);
};
// 删除兼容单条record 本身批量record.records 数组),仅小时(tm)数据支持删除
const handleDeleteFn = async (record: any, reason: string) => {
const list = Array.isArray(record.records) ? record.records : [record];
const dataList = list.map((r: any) => ({
id: r.stcd,
tm: r.tm
}));
return deleteFlowDataInfo({
dataList,
dataType: 'TIME',
source: reason
});
};
// 删除后刷新:清空选中(让批量删除按钮回到禁用状态)并重新加载列表
const refreshAfterDelete = () => {
selectedRowKeys.value = [];
selectedRows.value = [];
tableRef.value?.clearSelection();
initTable(currentSearchParams.value);
};
const handleDelete = (record: any) => {
deleteModalRef.value?.open(record, () => {
refreshAfterDelete();
});
};
// 批量删除
const handleBatchDelete = () => {
if (currentSearchParams.value.timeScale !== 'tm') {
message.info('仅小时数据支持删除');
return;
}
if (selectedRowKeys.value.length === 0) {
message.info('请先勾选要删除的数据');
return;
}
deleteModalRef.value?.open(
{
records: [...selectedRows.value],
stnm: `选中的 ${selectedRowKeys.value.length} 条数据`
},
() => {
refreshAfterDelete();
}
);
};
// 查看修改(操作日志)
const handleSeeEdit = () => {
operationLogVisible.value = true;
};
onMounted(() => {
nextTick(() => {
tableScrollY.value = calcTableScrollY();
});
});
</script>
<style scoped lang="scss">
.body_one {
position: relative;
z-index: 900;
pointer-events: all;
}
</style>