637 lines
18 KiB
Vue
637 lines
18 KiB
Vue
<template>
|
||
<div class="shuiwenjiancegongzwo-ej-container">
|
||
<!-- Tab切换 -->
|
||
<a-tabs v-model:activeKey="tabIndex" @change="handleTabChange">
|
||
<a-tab-pane v-for="tab in tabs" :key="tab.key" :tab="tab.name" />
|
||
</a-tabs>
|
||
|
||
<!-- 搜索表单 -->
|
||
<div class="search-form">
|
||
<a-space size="middle">
|
||
<div>选择水电站:</div>
|
||
<a-select
|
||
v-model:value="searchData.stcd.dataDimensionData"
|
||
placeholder="请选择水电站"
|
||
style="width: 200px"
|
||
show-search
|
||
:filter-option="filterOption"
|
||
:options="hydropowerStationOptions"
|
||
@change="handleHydropowerStationChange"
|
||
/>
|
||
<a-select
|
||
v-model:value="searchData.stnm"
|
||
placeholder=" "
|
||
style="width: 200px"
|
||
allow-clear
|
||
show-search
|
||
:filter-option="filterOption"
|
||
:options="stationOptions"
|
||
@change="handleStationChange"
|
||
/>
|
||
<!-- <a-input v-model:value="searchData.stnm" placeholder="请输入测站名称" style="width: 200px" allow-clear /> -->
|
||
|
||
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||
<a-tooltip title="重置">
|
||
<a-button @click="handleReset">重置</a-button>
|
||
</a-tooltip>
|
||
</a-space>
|
||
</div>
|
||
|
||
<!-- 数据表格 -->
|
||
<a-table :columns="columns" :data-source="tableData" :loading="loading" :pagination="pagination"
|
||
:scroll="{ y: tableHeight }" row-key="stcd" @change="handleTableChange">
|
||
<template #bodyCell="{ column, record }">
|
||
<!-- 监测状态 -->
|
||
<template v-if="column.key === 'coenvwState'">
|
||
<a-tooltip placement="top">
|
||
<template #title>
|
||
<ol>
|
||
<li>最近1天有监测数据为在线,否则为离线。</li>
|
||
</ol>
|
||
</template>
|
||
<a-tag :color="record.coenvwState > 0 ? 'green' : '#999'">
|
||
{{ record.coenvwState > 0 ? '在线' : '离线' }}
|
||
</a-tag>
|
||
</a-tooltip>
|
||
</template>
|
||
|
||
<!-- 操作 -->
|
||
<template v-else-if="column.key === 'action'">
|
||
<a @click="handleViewDetail(record)" class="text_hocer">查看详情</a>
|
||
</template>
|
||
</template>
|
||
</a-table>
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { ref, computed, watch, onMounted } from 'vue'
|
||
import { wbsbGetKendoList, getVmsstbprpt } from '@/api/sw'
|
||
import { vmsstbprptGetKendoList } from '@/api/sz'
|
||
import { useModelStore } from "@/store/modules/model";
|
||
|
||
const modelStore = useModelStore();
|
||
// ==================== Props 定义 ====================
|
||
const props = defineProps<{
|
||
baseId?: string
|
||
tabs?: any[]
|
||
activeKey?: string
|
||
}>()
|
||
|
||
// ==================== 状态管理 ====================
|
||
const tabIndex = ref(props.activeKey || '0')
|
||
const loading = ref(false)
|
||
const tableData = ref<any[]>([])
|
||
const pagination = ref({
|
||
current: 1,
|
||
pageSize: 20,
|
||
total: 0,
|
||
size: 'small',
|
||
showSizeChanger: true,
|
||
showQuickJumper: true,
|
||
showTotal: (total: number) => `共 ${total} 条`,
|
||
pageSizeOptions: ['10', '20', '50', '100']
|
||
})
|
||
const tableHeight = 'calc(48vh)'
|
||
|
||
// 水电站列表数据
|
||
const hydropowerStationList = ref<any[]>([])
|
||
const stationDataList: any = ref([])
|
||
|
||
// 转换为 a-select options 格式
|
||
const hydropowerStationOptions = computed(() => {
|
||
return hydropowerStationList.value.map(station => ({
|
||
label: station.wbsName,
|
||
value: station.wbsCode
|
||
}))
|
||
})
|
||
|
||
const stationOptions = computed(() => {
|
||
return stationDataList.value.map(station => ({
|
||
label: station.stnm,
|
||
value: station.stcd
|
||
}))
|
||
})
|
||
|
||
const searchData = ref<any>({
|
||
stcd: {
|
||
dataDimensionType: 'hyBase',
|
||
stcdId: '',
|
||
dataDimensionData: props.baseId || 'all'
|
||
},
|
||
stnm: null
|
||
})
|
||
|
||
// ==================== 计算合并信息 ====================
|
||
const getRowSpanInfo = (dataIndex: string) => {
|
||
const spanMap = new Map()
|
||
|
||
if (!tableData.value || tableData.value.length === 0) {
|
||
return spanMap
|
||
}
|
||
|
||
let currentGroupStart = 0
|
||
let currentValue = tableData.value[0][dataIndex]
|
||
|
||
for (let i = 0; i < tableData.value.length; i++) {
|
||
const value = tableData.value[i][dataIndex]
|
||
|
||
if (value !== currentValue) {
|
||
// 记录当前组的起始位置和行数
|
||
spanMap.set(currentGroupStart, i - currentGroupStart)
|
||
currentGroupStart = i
|
||
currentValue = value
|
||
}
|
||
}
|
||
|
||
// 处理最后一组
|
||
spanMap.set(currentGroupStart, tableData.value.length - currentGroupStart)
|
||
|
||
return spanMap
|
||
}
|
||
|
||
// ==================== 监听 Props 变化 ====================
|
||
// const baseId = ref('')
|
||
watch(
|
||
() => props.baseId,
|
||
(newVal) => {
|
||
if (newVal && newVal !== searchData.value.stcd.dataDimensionData) {
|
||
searchData.value.stcd.dataDimensionData = newVal
|
||
fetchData()
|
||
}
|
||
}
|
||
)
|
||
|
||
watch(
|
||
() => props.activeKey,
|
||
(newVal) => {
|
||
if (newVal && newVal !== tabIndex.value) {
|
||
tabIndex.value = newVal
|
||
fetchData()
|
||
}
|
||
}
|
||
)
|
||
|
||
|
||
// ==================== 列配置 ====================
|
||
const columns = computed(() => {
|
||
const baseColumns = [
|
||
{
|
||
title: '所属基地',
|
||
dataIndex: 'baseName',
|
||
key: 'baseName',
|
||
width: 150,
|
||
customCell: (record: any, index: number) => {
|
||
const spanMap = getRowSpanInfo('baseName')
|
||
const rowSpan = spanMap.get(index)
|
||
|
||
if (rowSpan === undefined) {
|
||
// 被合并的行,不显示
|
||
return { rowSpan: 0 }
|
||
}
|
||
|
||
// 第一行,设置合并行数
|
||
return { rowSpan }
|
||
}
|
||
},
|
||
{
|
||
title: '测站名称',
|
||
dataIndex: 'stnm',
|
||
key: 'stnm',
|
||
width: 150
|
||
},
|
||
{
|
||
title: '电站',
|
||
dataIndex: 'ennm',
|
||
key: 'ennm',
|
||
width: 150
|
||
},
|
||
// {
|
||
// title: '建成时间',
|
||
// dataIndex: 'jcdt',
|
||
// key: 'jcdt',
|
||
// width: 120
|
||
// },
|
||
{
|
||
title: '监测指标',
|
||
dataIndex: 'stindx',
|
||
key: 'stindx',
|
||
width: 150
|
||
},
|
||
// {
|
||
// title: '监测状态',
|
||
// key: 'coenvwState',
|
||
// dataIndex: 'coenvwState',
|
||
// width: 100,
|
||
// align: 'center' as const
|
||
// },
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
width: 100,
|
||
align: 'center' as const,
|
||
fixed: 'right' as const
|
||
}
|
||
]
|
||
|
||
return baseColumns.filter(Boolean)
|
||
})
|
||
|
||
// ==================== 过滤条件构建 ====================
|
||
const buildSearchFilter = () => {
|
||
const filters: any[] = []
|
||
|
||
// 基地ID过滤
|
||
if (searchData.value?.stcd?.dataDimensionData && searchData.value.stcd.dataDimensionData !== 'all') {
|
||
filters.push({
|
||
field: 'baseId',
|
||
operator: 'eq',
|
||
value: searchData.value.stcd.dataDimensionData
|
||
})
|
||
}
|
||
|
||
// 测站ID过滤
|
||
if (searchData.value?.stcd?.stcdId) {
|
||
filters.push({
|
||
field: 'rstcd',
|
||
operator: 'eq',
|
||
value: searchData.value.stcd.stcdId
|
||
})
|
||
}
|
||
|
||
// 测站名称模糊搜索
|
||
if (searchData.value?.stnm) {
|
||
filters.push({
|
||
field: 'rstcd',
|
||
operator: 'eq',
|
||
value: searchData.value.stnm
|
||
})
|
||
}
|
||
|
||
// 根据 tabIndex 设置站点类型(水质监测)
|
||
if (tabIndex.value === '3') {
|
||
filters.push({
|
||
field: 'sttpCode',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 'WQFB'
|
||
})
|
||
} else {
|
||
filters.push({
|
||
field: 'sttpCode',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 'WQ'
|
||
})
|
||
}
|
||
|
||
// Tab特定过滤 - 对齐 React 版本的水质监测逻辑
|
||
switch (tabIndex.value) {
|
||
case '0': // 自动监测-实时
|
||
filters.push(
|
||
{
|
||
field: 'mway',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 2
|
||
},
|
||
{
|
||
field: 'dtinType',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 0
|
||
}
|
||
)
|
||
break
|
||
case '1': // 自动监测-历史
|
||
filters.push(
|
||
{
|
||
field: 'mway',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 2
|
||
},
|
||
{
|
||
field: 'dtinType',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 1
|
||
}
|
||
)
|
||
break
|
||
case '2': // 人工监测
|
||
filters.push(
|
||
{
|
||
field: 'mway',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 1
|
||
},
|
||
{
|
||
field: 'dtinType',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 2
|
||
}
|
||
)
|
||
break
|
||
case '3': // 特殊类型
|
||
filters.push(
|
||
{
|
||
field: 'mway',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 2
|
||
},
|
||
{
|
||
field: 'dtinType',
|
||
operator: 'eq',
|
||
dataType: 'string',
|
||
value: 0
|
||
}
|
||
)
|
||
break
|
||
}
|
||
|
||
return {
|
||
logic: 'and',
|
||
filters: filters.filter((f) => f.value !== undefined && f.value !== null && f.value !== '')
|
||
}
|
||
}
|
||
|
||
// ==================== API调用 ====================
|
||
const fetchData = async () => {
|
||
loading.value = true
|
||
try {
|
||
const filter = buildSearchFilter()
|
||
const params = {
|
||
take: pagination.value.pageSize,
|
||
skip: pagination.value.current,
|
||
filter: filter,
|
||
select: [
|
||
'baseName',
|
||
'stnm',
|
||
'ennm',
|
||
'jcdt',
|
||
'stindx',
|
||
'coenvwState',
|
||
'sttpCode',
|
||
'stcd',
|
||
'rstcd',
|
||
'stCode',
|
||
'stName',
|
||
'dvtp'
|
||
],
|
||
sort: [
|
||
{ field: 'baseStepSort', dir: 'asc' },
|
||
{ field: 'hbrvcd', dir: 'asc' },
|
||
{ field: 'rstcdStepSort', dir: 'asc' },
|
||
{ field: 'siteStepSort', dir: 'asc' }
|
||
],
|
||
groupResultFlat:false
|
||
}
|
||
|
||
console.log('【请求参数】', params)
|
||
const res = await vmsstbprptGetKendoList(params)
|
||
console.log('【响应数据】', res)
|
||
|
||
// 数据处理
|
||
let total = res.data.total
|
||
let records = res?.data?.data || res?.data
|
||
// if (Array.isArray(res?.data?.data)) {
|
||
// records = res.data.data
|
||
// total = res.data.data.length
|
||
// }
|
||
|
||
tableData.value = records || []
|
||
pagination.value.total = total
|
||
loading.value = false
|
||
} catch (error) {
|
||
console.error('获取水文监测数据失败:', error)
|
||
tableData.value = []
|
||
pagination.value.total = 0
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const getselect = async () => {
|
||
try {
|
||
const params = {
|
||
"filter": {
|
||
"logic": "and",
|
||
"filters": [
|
||
{
|
||
"field": "wbsType",
|
||
"operator": "eq",
|
||
"dataType": "string",
|
||
"value": "PSB"
|
||
},
|
||
{
|
||
"field": "treeLevel",
|
||
"operator": "eq",
|
||
"dataType": "string",
|
||
"value": "1"
|
||
}
|
||
]
|
||
},
|
||
"sort": [
|
||
{
|
||
"field": "orderIndex",
|
||
"dir": "asc"
|
||
}
|
||
]
|
||
}
|
||
|
||
const res = await wbsbGetKendoList(params)
|
||
console.log('【水电站列表】', res)
|
||
|
||
// 数据处理:提取水电站列表
|
||
if (res?.data?.data && Array.isArray(res.data.data)) {
|
||
hydropowerStationList.value = res.data.data
|
||
console.log('站点数据列表', stationDataList.value)
|
||
getselectTwo(searchData.value.stcd.dataDimensionData)
|
||
console.log('【水电站数量】', hydropowerStationList.value.length)
|
||
} else {
|
||
console.warn('【警告】未获取到有效的水电站数据')
|
||
hydropowerStationList.value = []
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('【错误】获取水电站列表失败:', error)
|
||
hydropowerStationList.value = []
|
||
}
|
||
}
|
||
const getselectTwo = async (code: any) => {
|
||
console.log('站点数据列表')
|
||
// 根据当前 Tab 确定站点类型
|
||
// const sttpCodeValue = tabIndex.value === '3' ? 'WQFB' : 'WQ'
|
||
|
||
const params = {
|
||
"filter": {
|
||
"logic": "and",
|
||
"filters": [
|
||
code != 'all' ? {
|
||
"field": "baseId",
|
||
"operator": "contains",
|
||
"dataType": "string",
|
||
"value": code
|
||
} : null,
|
||
{
|
||
"field": "sttpCode",
|
||
"operator": "eq",
|
||
"dataType": "string",
|
||
"value": "ENG"
|
||
}
|
||
].filter(Boolean)
|
||
},
|
||
"sort": code !== 'all'
|
||
? [
|
||
{
|
||
"field": "baseId",
|
||
"dir": "asc"
|
||
},
|
||
{
|
||
"field": "rvcdStepSort",
|
||
"dir": "asc"
|
||
},
|
||
{
|
||
"field": "rstcdStepSort",
|
||
"dir": "asc"
|
||
},
|
||
{
|
||
"field": "siteStepSort",
|
||
"dir": "asc"
|
||
}
|
||
]
|
||
: [
|
||
{
|
||
"field": "ttpwr",
|
||
"dir": "desc"
|
||
}
|
||
],
|
||
"select": [
|
||
"stcd",
|
||
"stnm"
|
||
]
|
||
}
|
||
const res = await getVmsstbprpt(params)
|
||
// console.log('结果', res)
|
||
console.log('站点数据列表', res?.data?.data)
|
||
stationDataList.value = res?.data?.data || res?.data
|
||
|
||
}
|
||
|
||
// ==================== 事件处理 ====================
|
||
const filterOption = (input: string, option: any) => {
|
||
// 使用 options 属性时,option 是标准对象 { label, value }
|
||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||
}
|
||
|
||
const handleHydropowerStationChange = (value: string) => {
|
||
console.log('【水电站选择变化】', value)
|
||
// 清空测站选择
|
||
searchData.value.stnm = null
|
||
searchData.value.stcd.stcdId = ''
|
||
// 获取该水电站下的测站列表
|
||
getselectTwo(value)
|
||
// 重新查询数据
|
||
// pagination.value.current = 1
|
||
// fetchData()
|
||
}
|
||
|
||
const handleStationChange = (value: string | undefined) => {
|
||
console.log('【测站选择变化】', value)
|
||
// 更新测站ID
|
||
if (value) {
|
||
searchData.value.stcd.stcdId = value
|
||
} else {
|
||
searchData.value.stcd.stcdId = ''
|
||
}
|
||
}
|
||
|
||
const handleSearch = () => {
|
||
console.log('【搜索】', searchData.value)
|
||
pagination.value.current = 1
|
||
fetchData()
|
||
}
|
||
|
||
const handleReset = () => {
|
||
console.log('【重置】')
|
||
searchData.value = {
|
||
stcd: {
|
||
dataDimensionType: 'hyBase',
|
||
stcdId: '',
|
||
dataDimensionData: props.baseId || 'all'
|
||
},
|
||
stnm: null
|
||
}
|
||
pagination.value.current = 1
|
||
fetchData()
|
||
}
|
||
|
||
const handleTabChange = (key: string) => {
|
||
console.log('【Tab切换】', key)
|
||
tabIndex.value = key
|
||
pagination.value.current = 1
|
||
fetchData()
|
||
}
|
||
|
||
const handleTableChange = (pag: any) => {
|
||
pagination.value.current = pag.current
|
||
pagination.value.pageSize = pag.pageSize
|
||
fetchData()
|
||
}
|
||
|
||
const handleViewDetail = (record: any) => {
|
||
if (record) {
|
||
modelStore.modalVisible = true;
|
||
modelStore.params.sttp = "WQFB";
|
||
modelStore.title = record.stnm + "详情信息";
|
||
// modelStore.isBasicEdit = true;
|
||
modelStore.params.stcd = record.stcd;
|
||
modelStore.modalVisible = true;
|
||
|
||
|
||
}
|
||
|
||
// TODO: 后续实现详情查看功能
|
||
}
|
||
|
||
// ==================== 生命周期 ====================
|
||
onMounted(() => {
|
||
console.log('【组件挂载】水文监测工作二级页面已加载')
|
||
fetchData()
|
||
getselect()
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.shuiwenjiancegongzwo-ej-container {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background-color: #ffffff;
|
||
box-sizing: border-box;
|
||
|
||
.search-form {
|
||
margin-bottom: 16px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
:deep(.ant-table-wrapper) {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
|
||
.text_hocer {
|
||
color: #2f6b98;
|
||
}
|
||
|
||
.text_hocer:hover {
|
||
color: #40a9ff;
|
||
}
|
||
</style>
|