WholeProcessPlatform/frontend/src/modules/EnvironmentalQuality/TwoLayers/HJMZDTwoLays.vue

541 lines
17 KiB
Vue
Raw Normal View History

2026-06-02 14:52:44 +08:00
<template>
<div>
<!-- 搜索表单 - 使用 Ant Design Vue 原生组件 -->
<a-form ref="formRef" :model="formState" layout="inline" @finish="onFinish" style="margin-bottom: 16px">
<a-form-item label="达标状态" name="sfdb">
<a-select v-model:value="formState.sfdb" placeholder="请选择" allow-clear style="width: 150px">
<a-select-option value="">全部</a-select-option>
<a-select-option :value="'0'">不达标</a-select-option>
<a-select-option :value="'1'">达标</a-select-option>
<a-select-option :value="'2'">无目标等级/无数据</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" html-type="submit">查询</a-button>
<Tooltip title="重置">
<a-button @click="handleReset">重置</a-button>
</Tooltip>
</a-space>
</a-form-item>
</a-form>
<!-- 数据表格 -->
<BasicTable ref="tableRef" :columns="columns"
:list-url="props.calculateFlag?.calculateFlag == 1 ? dataGetKendoListCust : NodataGetKendoListCust"
:scrollY="500" :search-params="{ sort: [{ field: 'tm', dir: 'desc' }] }"
:transform-data="customTransform" />
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted, h, nextTick } from 'vue'
import { omit } from 'lodash-es'
import { Button, Tooltip, Popover } from 'ant-design-vue'
import BasicTable from '@/components/BasicTable/index.vue'
import { ruleGetKendoListCust, noAuthGetKendoListCust, stbprpGetStbprpYsByStcd, dataGetKendoListCust, NodataGetKendoListCust } from '@/api/sz'
// ==================== Props 定义 ====================
interface Props {
tc: {
stcd: string
startTime: string
endTime: string
sfdb: string
}
calculateFlag?: {
calculateFlag: number
}
}
const props = defineProps<Props>()
// ==================== 响应式状态 ====================
const formRef = ref()
const tableRef = ref()
const col = ref<any[]>([])
// ✅ 表单状态(替代之前的 sfdb ref
const formState = reactive({
sfdb: '1'
})
// ==================== 固定列配置 ====================
const columnList = [
{
dataIndexRaw: '',
key: 'tm',
title: '时间',
dataIndex: 'tm',
children: [],
visible: true,
fixed: '',
ellipsis: true,
wrap: false,
dictType: '',
dictCode: '',
dictDatas: {},
fromType: '',
dataType: 'date',
dataFormat: '',
selectMode: '',
unit: '',
remark: '',
rules: '',
ruleTips: '',
setting: {},
chartColor: '',
elementCode: '',
disabledDate: true,
sorter: true,
multiLink: false
},
{
dataIndexRaw: '',
key: 'wwqtg',
title: '水质要求',
dataIndex: 'wwqtgName',
children: [],
visible: true,
fixed: '',
ellipsis: true,
wrap: false,
dictType: '',
dictCode: '',
dictDatas: {},
fromType: '',
dataFormat: '',
selectMode: '',
unit: '',
remark: '',
rules: '',
ruleTips: '',
setting: {},
chartColor: '',
elementCode: '',
sorter: true,
disabledDate: true,
multiLink: false,
width: 100
},
{
dataIndexRaw: '',
key: 'wqGrd',
title: '水质等级',
dataIndex: 'wqgrdName',
children: [],
visible: true,
fixed: '',
ellipsis: true,
wrap: false,
dictType: '',
dictCode: '',
dictDatas: {},
fromType: '',
dataFormat: '',
selectMode: '',
unit: '',
remark: '',
rules: '',
ruleTips: '',
setting: {},
chartColor: '',
elementCode: '',
sorter: true,
disabledDate: true,
multiLink: false,
width: 100
},
{
dataIndexRaw: 'sfdb',
key: 'sfdb',
title: '是否达标',
dataIndex: 'sfdbName',
children: [],
visible: true,
fixed: '',
ellipsis: true,
wrap: false,
// TODO: 【您需要实现】字典转换逻辑 - BasicTable 不支持 dictType/dictCode
// 需要在 customRender 中手动处理
dictType: 'dataDict',
dictCode: 'sd_wq_r.sfdb',
dictDatas: {},
fromType: 'select',
dataFormat: '',
selectMode: '',
unit: '',
remark: '',
rules: '',
ruleTips: '',
setting: {},
chartColor: '',
elementCode: '',
sorter: true,
disabledDate: true,
multiLink: false,
width: 100,
// ✅ Vue3 版本需要添加 customRender
customRender: ({ record }: any) => {
// TODO: 【您需要实现】字典转换逻辑
// 示例return getDictLabel('sd_wq_r.sfdb', record.sfdbName)
return record.sfdbName // 暂时直接显示原始值
}
}
]
// ==================== 动态列计算 ====================
const columns = computed(() => {
if (!col.value.length) return columnList
return [...columnList, ...col.value]
})
// ==================== 筛选条件计算 ====================
const tableFilter = computed(() => {
let res: any = {
stcd: props.tc.stcd,
sfdb: formState.sfdb === '2' ? '' : formState.sfdb,
startTime: props.tc.startTime,
endTime: props.tc.endTime
}
if (res.sfdb === '') res = omit(res, 'sfdb')
return res
})
// ==================== 方法定义 ====================
// 搜索表单提交
const onFinish = () => {
const filters: any[] = [
{
"field": "stcd",
"operator": "eq",
"dataType": "string",
"value": tableFilter.value.stcd
},
formState.sfdb ? {
"field": "sfdb",
"operator": "eq",
"dataType": "string",
"value": formState.sfdb
} : null,
{
"field": "tm",
"operator": "gte",
"dataType": "date",
"value": tableFilter.value.startTime
},
{
"field": "tm",
"operator": "lte",
"dataType": "date",
"value": tableFilter.value.endTime
}
].filter(Boolean)
const filter = {
logic: 'and',
filters
}
// 触发表格刷新
tableRef.value?.getList(filter)
}
// 重置表单
const handleReset = () => {
formState.sfdb = '1'
onFinish()
}
// TODO: 【预留】获取动态列配置 - 您需要实现的API调用逻辑
const getCol = async (params: any) => {
try {
const lo = await columYaoshu(params)
col.value = lo || []
} catch (error) {
console.error('获取列配置失败:', error)
}
}
// TODO: 【预留】处理列配置的核心逻辑 - 您需要实现
const columYaoshu = async (params: any) => {
// API 1: 获取预警规则限值
let params3 = {
"filter": {
"logic": "and",
"filters": [
{
"field": "stcd",
"operator": "eq",
"dataType": "string",
"value": params?.stcd
}
]
}
}
const MaxData = await ruleGetKendoListCust(params3)
// API 2: 获取数据范围
let params2 = {
"filter": {
"logic": "and",
"filters": [
{
"field": "stcd",
"operator": "eq",
"dataType": "string",
"value": params?.stcd
},
{
"field": "tm",
"operator": "lte",
"dataType": "date",
"value": params?.endTime
},
{
"field": "tm",
"operator": "gte",
"dataType": "date",
"value": params?.startTime
}
]
}
}
const noAuthRes = await noAuthGetKendoListCust(params2)
const noAuthResData = noAuthRes?.data?.data || []
// API 3: 获取要素配置
let params1 = {
stcd: params?.stcd,
tbCode: 'WQ_R',
endTime: params.endTime,
startTime: params.startTime
}
const res = await stbprpGetStbprpYsByStcd(params1)
if (res?.data?.data) {
const processedColumns = res.data.data
.filter((item: any) => item.enable === '1')
.map((item: any) => {
const _t = item.ysShowName
const reg = /[(][^()]+[)]/
// TODO: 【您需要实现】单位转换工具函数
const _u = getUnitConfigByCode('WQ_R', item.ys)?.unit
if (_u) {
item.ysShowName = reg.test(_t)
? _t.replace(reg, `(${_u})`)
: `${_t}(${_u})`
}
let showValue = ''
if (noAuthResData.length) {
const { max, min } = noAuthResData[0]
const ys = item.ys
const maxValue = max.filter((e: any) => e[ys])
const minValue = min.filter((e: any) => e[ys])
if (maxValue.length && minValue.length) {
showValue = `(${minValue[0]?.[ys]}-${maxValue[0]?.[ys]})`
} else {
if (minValue.length) {
showValue = `>${minValue[0]?.[ys]}`
}
if (maxValue.length) {
showValue = `<${maxValue[0]?.[ys]}`
}
}
}
return {
dataIndexRaw: '',
key: item.ys.toLowerCase(),
// ✅ Vue3 版本title 支持函数返回 VNode
title: () => h('div', [
h('p', {
style: {
overflow: 'hidden',
textOverflow: 'ellipsis',
wordBreak: 'keep-all'
}
}, item.ysShowName),
h('p', showValue)
]),
dataIndex: item.ys.toLowerCase(),
children: [],
visible: true,
fixed: '',
sorter: true,
ellipsis: true,
wrap: false,
dictType: '',
dictCode: '',
dictDatas: {},
// ✅ Vue3 版本:使用 customRender 替代 render
customRender: ({ record }: any) => {
// TODO: 【您需要传入】MaxData 数据
const datalist = MaxData?.data?.data
const dynamicDataIndex = item.ys
const dynamicDataName = item.ysShowName
const matchedItem = datalist.find((m: any) => m.ys === dynamicDataIndex)
// 判断是否超标
if (
matchedItem &&
(matchedItem.isAsc == 1 ? matchedItem?.maxVal : matchedItem.minVal) &&
record[dynamicDataIndex?.toLowerCase()] &&
((matchedItem.isAsc == 1 && record[dynamicDataIndex?.toLowerCase()] > matchedItem?.maxVal) ||
(matchedItem.isAsc != 1 && record[dynamicDataIndex?.toLowerCase()] < matchedItem.minVal))
) {
// ✅ Vue3 版本:使用 h() 函数创建 VNode
return h(Popover, {
content: h('div', `预警标准: ${matchedItem.isAsc === 1 ? `>${matchedItem.maxVal}` : `<${matchedItem.minVal}`}`),
trigger: 'hover'
}, () =>
h('span', {
style: { color: 'red', cursor: 'pointer' },
// TODO: 【您需要实现】单位转换渲染
}, transUnitRender(record[dynamicDataIndex?.toLowerCase()], 'WQ_R', dynamicDataIndex))
)
}
// 正常显示
// TODO: 【您需要实现】单位转换渲染
return transUnitRender(record[dynamicDataIndex?.toLowerCase()], 'WQ_R', dynamicDataIndex)
},
fromType: '',
dataType: '',
dataFormat: '',
selectMode: '',
unit: '',
remark: '',
rules: '',
ruleTips: '',
setting: {},
chartColor: '',
elementCode: '',
disabledDate: true,
multiLink: false
}
})
console.log(processedColumns)
onFinish()
return processedColumns || []
}
}
// TODO: 【预留】单位转换工具函数 - 您需要实现
// ==================== 单位转换工具函数区域 ====================
/**
* 根据表代码和要素代码获取单位配置
* @param tbCode 表代码 ( 'WQ_R')
* @param ys 要素代码 ( 'DOX', 'CODCR')
* @returns 单位配置对象 { unit: string }
*/
const getUnitConfigByCode = (tbCode: string, ys: string) => {
// TODO: 【您需要实现】单位配置映射
const unitConfig: Record<string, Record<string, { unit: string }>> = {
'WQ_R': {
'PH': { unit: '' },
'DOX': { unit: 'mg/L' },
'CODMN': { unit: 'mg/L' },
'CODCR': { unit: 'mg/L' },
'NH3N': { unit: 'mg/L' },
'TP': { unit: 'mg/L' },
'TN': { unit: 'mg/L' },
'WTMP': { unit: '℃' },
'COND': { unit: 'μS/cm' },
'CLARITY': { unit: 'm' }
}
}
return unitConfig[tbCode]?.[ys] || { unit: '' }
}
/**
* 带单位的值渲染根据要素类型设置不同小数位数不带单位
* @param value 数值
* @param tbCode 表代码
* @param ys 要素代码
* @returns 格式化后的字符串不带单位
*/
const transUnitRender = (value: any, tbCode: string, ys: string) => {
if (value === null || value === undefined || value === '') return '-'
const numValue = Number(value)
if (isNaN(numValue)) return String(value)
// 根据不同要素类型设置小数位数
let formattedValue: string
if (ys === 'WTMP' || ys === 'PH') {
// 水温和PH保留一位小数
formattedValue = numValue.toFixed(1)
} else if (ys === 'COND') {
// 电导率不要小数
formattedValue = Math.round(numValue).toString()
} else {
// 其他要素保留两位小数
formattedValue = numValue.toFixed(2)
}
return formattedValue
}
/**
* 纯单位转换不带渲染
* @param value 数值
* @param tbCode 表代码
* @param ys 要素代码
* @returns 转换后的数值
*/
const transUnit = (value: any, tbCode: string, ys: string) => {
if (value === null || value === undefined) return null
return Number(value)
}
// ==================== 监听器 ====================
// 监听 tc 和 formState.sfdb 变化,重新获取列配置
watch(
() => [props.tc.stcd, props.tc.startTime, props.tc.endTime, formState.sfdb],
([stcd, startTime, endTime]) => {
if(!stcd){
return
}
// debugger
tableRef.value.tableData = []
getCol({ stcd, startTime, endTime })
},
{ immediate: false } // 不在初始化时立即执行,由 onMounted 处理
)
// 初始化
onMounted(() => {
nextTick(() => {
})
getCol({
stcd: props.tc.stcd,
startTime: props.tc.startTime,
endTime: props.tc.endTime
})
})
// 自定义数据转换
const customTransform = (res: any) => {
return {
records: res?.data?.data || [],
total: res?.data?.total || 0
}
}
</script>
<style scoped>
/* 如需添加样式,请在此处编写 */
</style>