栖息地本地接口对接,加BasicTable组件增加超出隐藏和文字提示,如果有空数据就显示-,添加排序功能。

This commit is contained in:
王兴凯 2026-06-04 11:43:16 +08:00
commit a8456cea47
5 changed files with 161 additions and 64 deletions

View File

@ -2,7 +2,7 @@ import request from '@/utils/request';
//栖息地保护工作开展情况 //栖息地保护工作开展情况
export function fhGetKendoListCust(data: any) { export function fhGetKendoListCust(data: any) {
return request({ return request({
url: '/api/wmp-env-server/env/fh/GetKendoListCust', url: '/fh/GetKendoListCust',
method: 'post', method: 'post',
data data
}); });
@ -10,7 +10,7 @@ export function fhGetKendoListCust(data: any) {
//获取所属栖息地 //获取所属栖息地
export function msstbprptGetKendoList(data: any) { export function msstbprptGetKendoList(data: any) {
return request({ return request({
url: '/api/dec-lygk-base-server/base/msstbprpt/GetKendoList', url: '/fh/msstbprpt/GetKendoList',
method: 'post', method: 'post',
data data
}); });
@ -18,7 +18,7 @@ export function msstbprptGetKendoList(data: any) {
//水温监测数据 //水温监测数据
export function sdrvwtsGetKendoList(data: any) { export function sdrvwtsGetKendoList(data: any) {
return request({ return request({
url: '/api/wmp-env-server/base/sdrvwts/GetKendoList', url: '/fh/sdrvwts/GetKendoList',
method: 'post', method: 'post',
data data
}); });
@ -26,7 +26,7 @@ export function sdrvwtsGetKendoList(data: any) {
//水文监测 //水文监测
export function sdriverdaysGetKendoList(data: any) { export function sdriverdaysGetKendoList(data: any) {
return request({ return request({
url: '/api/wmp-swqx-server/zq/sdriverdays/GetKendoList', url: '/fh/zq/sdriverdays/GetKendoList',
method: 'post', method: 'post',
data data
}); });
@ -34,7 +34,7 @@ export function sdriverdaysGetKendoList(data: any) {
//主要栖息地基本信息 //主要栖息地基本信息
export function fhGetKendoListCustom(data: any) { export function fhGetKendoListCustom(data: any) {
return request({ return request({
url: '/api/wmp-env-server/env/fh/GetKendoListCustom', url: '/fh/GetKendoListCustom',
method: 'post', method: 'post',
data data
}); });

View File

@ -1,16 +1,8 @@
<template> <template>
<div class="table-container" ref="tableContainerRef"> <div class="table-container" ref="tableContainerRef">
<a-table <a-table size="small" :loading="loading" :row-selection="enableRowSelection ? rowSelection : undefined"
size="small" :data-source="tableData" :columns="enhancedColumns" :pagination="paginationConfig" :scroll="scrollConfig"
:loading="loading" :row-key="rowKey" @change="handleTableChange">
:row-selection="enableRowSelection ? rowSelection : undefined"
:data-source="tableData"
:columns="columns"
:pagination="paginationConfig"
:scroll="scrollConfig"
:row-key="rowKey"
@change="handleTableChange"
>
<!-- 透传插槽支持自定义列内容 --> <!-- 透传插槽支持自定义列内容 -->
<template v-for="slot in Object.keys($slots)" #[slot]="scope" :key="slot"> <template v-for="slot in Object.keys($slots)" #[slot]="scope" :key="slot">
<slot :name="slot" v-bind="scope"></slot> <slot :name="slot" v-bind="scope"></slot>
@ -20,7 +12,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted, watch, nextTick } from "vue"; import { ref, computed, onMounted, watch, nextTick, h } from "vue";
import { Tooltip } from "ant-design-vue";
import { calcTableScrollY } from "@/utils/index"; import { calcTableScrollY } from "@/utils/index";
// --- Types --- // --- Types ---
@ -36,6 +29,10 @@ interface Props {
isPage?: boolean; isPage?: boolean;
getCheckboxProps?: (record: any) => any; getCheckboxProps?: (record: any) => any;
transformData?: (res: any) => { records: any[]; total: number }; transformData?: (res: any) => { records: any[]; total: number };
emptyPlaceholder?: string; //
processEmptyValues?: boolean; //
enableEllipsis?: boolean; //
enableSort?: boolean; //
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
@ -48,11 +45,16 @@ const props = withDefaults(defineProps<Props>(), {
getCheckboxProps: undefined, getCheckboxProps: undefined,
transformData: undefined, transformData: undefined,
scrollY: undefined, scrollY: undefined,
emptyPlaceholder: "-",
processEmptyValues: true, //
enableEllipsis: true, //
enableSort: false, //
}); });
const emit = defineEmits<{ const emit = defineEmits<{
(e: "data-loaded", params: any, data: any): void; (e: "data-loaded", params: any, data: any): void;
(e: "selection-change", selectedRowKeys: string[], selectedRows: any[]): void; (e: "selection-change", selectedRowKeys: string[], selectedRows: any[]): void;
(e: "sort-change", sortInfo: { field: string; order: 'ascend' | 'descend' | null }): void;
}>(); }>();
// --- State --- // --- State ---
@ -147,7 +149,7 @@ const getList = async (filter?: Record<string, any>) => {
finalTotal = res.data?.data?.total || res?.data?.total || res?.total || 0; finalTotal = res.data?.data?.total || res?.data?.total || res?.total || 0;
} }
tableData.value = finalRecords; tableData.value = processData(finalRecords);
total.value = finalTotal; total.value = finalTotal;
emit("data-loaded", params, { records: finalRecords, total: finalTotal }); emit("data-loaded", params, { records: finalRecords, total: finalTotal });
} catch (error) { } catch (error) {
@ -159,10 +161,19 @@ const getList = async (filter?: Record<string, any>) => {
} }
}; };
const handleTableChange = (pag: any) => { const handleTableChange = (pag: any, filters: any, sorter: any) => {
page.value = pag.current; page.value = pag.current;
size.value = pag.pageSize; size.value = pag.pageSize;
if (props.enableSort) {
if (sorter && sorter.field) {
emit("sort-change", { field: sorter.field, order: sorter.order });
} else {
emit("sort-change", { field: '', order: null });
}
}else {
getList(); getList();
}
}; };
const reset = () => { const reset = () => {
@ -197,6 +208,52 @@ defineExpose({
const observer = new ResizeObserver(() => { const observer = new ResizeObserver(() => {
tableScrollY.value = calcTableScrollY(tableContainerRef.value); tableScrollY.value = calcTableScrollY(tableContainerRef.value);
}); });
// --- ---
const processData = (records: any[]) => {
if (!props.processEmptyValues || !Array.isArray(records)) return records;
return records.map(record => {
const processedRecord: any = { ...record };
for (const key in processedRecord) {
if (Object.prototype.hasOwnProperty.call(processedRecord, key)) {
const val = processedRecord[key];
if (val === null || val === undefined || val === "") {
processedRecord[key] = props.emptyPlaceholder;
}
}
}
return processedRecord;
});
};
// --- + Tooltip---
const enhancedColumns = computed(() => {
if (!props.enableEllipsis) return props.columns;
return props.columns.map(col => {
if (col.customRender) {
return col; //
}
return {
...col,
ellipsis: true, // Ant Design Vue ellipsis
customRender: ({ text }: any) => {
const content = String(text ?? props.emptyPlaceholder);
return h(
Tooltip,
{ title: content },
() => h('div', {
class: 'table-cell-ellipsis',
style: { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }
}, content)
);
},
};
});
});
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
tableScrollY.value = calcTableScrollY(tableContainerRef.value); tableScrollY.value = calcTableScrollY(tableContainerRef.value);
@ -205,7 +262,7 @@ onMounted(() => {
} }
}); });
if (props.data && props.data.length > 0) { if (props.data && props.data.length > 0) {
tableData.value = props.data || []; tableData.value = processData(props.data);
} }
}); });
</script> </script>

View File

@ -11,7 +11,7 @@
<a-select v-model:value="searchData.baseId" placeholder="请选择所属基地" style="width: 200px" show-search <a-select v-model:value="searchData.baseId" placeholder="请选择所属基地" style="width: 200px" show-search
:filter-option="filterOption" :options="jiDiList" @change="handleHydropowerStationChange" /> :filter-option="filterOption" :options="jiDiList" @change="handleHydropowerStationChange" />
<div>所属栖息地:</div> <div>所属栖息地:</div>
<a-select v-model:value="searchData.fhstcd" placeholder=" " style="width: 200px" allow-clear show-search <a-select v-model:value="searchData.fhstcd" placeholder=" " style="width: 200px" show-search
:filter-option="filterOption" :options="stationOptions" /> :filter-option="filterOption" :options="stationOptions" />
<a-input v-model:value="searchData.stnm" placeholder="请输入电站或设施名称" style="width: 200px" allow-clear /> <a-input v-model:value="searchData.stnm" placeholder="请输入电站或设施名称" style="width: 200px" allow-clear />
@ -22,8 +22,8 @@
</a-space> </a-space>
</div> </div>
<!-- 列表 --> <!-- 列表 -->
<BasicTable ref="tableRef" :scrollY="360" :columns="columns" :list-url="fhGetKendoListCust" <BasicTable ref="tableRef" :scrollY="360" :columns="columns" :list-url="fhGetKendoListCust" :enable-sort="true" @sort-change="handleSortChange"
:search-params="{ sort: sortConfig }" :transform-data="customTransform"> :search-params="searchParams" :transform-data="customTransform">
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'ennm'"> <template v-if="column.key === 'ennm'">
<a @click="handleViewDetail(record, 'dz')" class="text-link"> <a @click="handleViewDetail(record, 'dz')" class="text-link">
@ -44,7 +44,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, watch, onMounted } from 'vue' import { ref, computed, watch, onMounted,nextTick } from 'vue'
import { msstbprptGetKendoList, fhGetKendoListCust } from '@/api/qxd' import { msstbprptGetKendoList, fhGetKendoListCust } from '@/api/qxd'
import BasicTable from '@/components/BasicTable/index.vue' import BasicTable from '@/components/BasicTable/index.vue'
import { useModelStore } from "@/store/modules/model"; import { useModelStore } from "@/store/modules/model";
@ -67,6 +67,7 @@ const searchData = ref<any>({
const modelStore = useModelStore(); const modelStore = useModelStore();
const tableRef = ref() const tableRef = ref()
const stationOptions: any = ref([]) const stationOptions: any = ref([])
// ==================== () ==================== // ==================== () ====================
const jiDiList: any = ref([ const jiDiList: any = ref([
{ {
@ -151,67 +152,78 @@ const columns = [
key: 'stnm', key: 'stnm',
title: '设施名称', title: '设施名称',
dataIndex: 'stnm', dataIndex: 'stnm',
width: '176px' width: '176px',
sorter: true,
}, },
{ {
key: 'baseName', key: 'baseName',
title: '所在基地', title: '所在基地',
dataIndex: 'baseName', dataIndex: 'baseName',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'ennm', key: 'ennm',
title: '所属电站', title: '所属电站',
dataIndex: 'ennm', dataIndex: 'ennm',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'fhstnm', key: 'fhstnm',
title: '所属栖息地', title: '所属栖息地',
dataIndex: 'fhstnm', dataIndex: 'fhstnm',
width: '176px' width: '176px',
sorter: true,
}, },
{ {
key: 'ststdt', key: 'ststdt',
title: '开工日期', title: '开工日期',
dataIndex: 'ststdt', dataIndex: 'ststdt',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'esstdt', key: 'esstdt',
title: '建成日期', title: '建成日期',
dataIndex: 'esstdt', dataIndex: 'esstdt',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'mway', key: 'mway',
title: '监测方式', title: '监测方式',
dataIndex: 'mway', dataIndex: 'mway',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'vlsr', key: 'vlsr',
title: '数据接入来源', title: '数据接入来源',
dataIndex: 'vlsr', dataIndex: 'vlsr',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'hydrodtin_type', key: 'hydrodtin_type',
title: '数据接入类型', title: '数据接入类型',
dataIndex: 'hydrodtinType', dataIndex: 'hydrodtinType',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'enable', key: 'enable',
title: '是否启用', title: '是否启用',
dataIndex: 'enable', dataIndex: 'enable',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
key: 'dtin', key: 'dtin',
title: '是否接入', title: '是否接入',
dataIndex: 'dtin', dataIndex: 'dtin',
width: '150px' width: '150px',
sorter: true,
}, },
{ {
title: '操作', title: '操作',
@ -221,9 +233,29 @@ const columns = [
fixed: 'right' as const fixed: 'right' as const
} }
]; ];
// // 1.
const sortConfig = computed(() => [ const sortState = ref<{ field: string; order: string } | null>(null);
{ // 2.
const handleSortChange = (info: { field: string; order: string | null }) => {
if (info.field) {
sortState.value = info;
} else {
sortState.value = null; //
}
nextTick(() => {
handleSearch()
});
}
const searchParams = computed(() => {
const params: any = { group: [],groupResultFlat: false,select:[] };
if (sortState.value) {
// [{ field: 'name', dir: 'asc' }]
params.sort = [{
field: sortState.value.field,
dir: sortState.value.order === 'ascend' ? 'asc' : 'desc'
}];
}else{
params.sort = [{
"field": "baseStepSort", "field": "baseStepSort",
"dir": "asc" "dir": "asc"
}, },
@ -234,8 +266,11 @@ const sortConfig = computed(() => [
{ {
"field": "rstcdStepSort", "field": "rstcdStepSort",
"dir": "asc" "dir": "asc"
}]
} }
])
return params;
});
const handleTabChange = (key: string) => { const handleTabChange = (key: string) => {
console.log('【Tab切换】', key) console.log('【Tab切换】', key)
tabIndex.value = key tabIndex.value = key
@ -299,7 +334,7 @@ const handleSearch = () => {
searchData.value.baseId != 'all' ? { searchData.value.baseId != 'all' ? {
"field": "baseId", "field": "baseId",
"operator": "eq", "operator": "eq",
"value": "01" "value": searchData.value.baseId
} : null, } : null,
searchData.value.fhstcd != 'all' ? { searchData.value.fhstcd != 'all' ? {
"field": "fhstcd", "field": "fhstcd",
@ -353,8 +388,6 @@ const customTransform = (res: any) => {
} }
// //
const handleViewDetail = (record: any, type: any) => { const handleViewDetail = (record: any, type: any) => {
console.log(tabIndex.value)
debugger
if (type == 'dz') { if (type == 'dz') {
modelStore.modalVisible = true; modelStore.modalVisible = true;
modelStore.params.sttp = "ENG"; modelStore.params.sttp = "ENG";
@ -379,10 +412,11 @@ const handleViewDetail = (record: any, type: any) => {
modelStore.title = record.stnm + " 详情信息"; modelStore.title = record.stnm + " 详情信息";
modelStore.params.stcd = record.stcd; modelStore.params.stcd = record.stcd;
} else if (tabIndex.value == 'VD') { } else if (tabIndex.value == 'VD') {
// modelStore.modalVisible = true; modelStore.modalVisible = true;
// modelStore.params.sttp = "fh_zq_point"; modelStore.params.sttp = "stinfo_ai_video_point";
// modelStore.title = record.stnm + " "; modelStore.title = "视频监控站详情信息";
// modelStore.params.stcd = record.stcd; modelStore.isBasicEdit = true;
modelStore.params.stcd = record.stcd;
} }
} }

View File

@ -572,8 +572,7 @@ const getselsectData = async () => {
} }
let res = await msstbprptGetKendoList(params) let res = await msstbprptGetKendoList(params)
console.log(res) console.log(res)
if (!res?.data?.data) { if (!res?.data?.data || res.data.data.length == 0) {
select.value.value = '' select.value.value = ''
select.value.options = [] select.value.options = []
return return

View File

@ -384,17 +384,24 @@ const getChartData = async (startDate: string, endDate: string, stcd: string) =>
"value": endDate // : "2026-06-30 23:59:59" "value": endDate // : "2026-06-30 23:59:59"
}, },
{ {
"field": "STCD", "field": "stcd",
"operator": "eq", "operator": "eq",
"dataType": "string", "dataType": "string",
"value": stcd "value": stcd
} }
] ]
},
"sort": [
{
"field": "dt",
"dir": "asc"
} }
]
}; };
// API // API
const res = await sdrvwtsGetKendoList(params); const res = await sdrvwtsGetKendoList(params);
debugger
console.log('API返回结果:', res); console.log('API返回结果:', res);
let data = res?.data?.data || []; let data = res?.data?.data || [];
@ -577,12 +584,12 @@ const getselsectData = async () => {
} }
let res = await msstbprptGetKendoList(params) let res = await msstbprptGetKendoList(params)
console.log(res) console.log(res)
if (!res?.data?.data) { if (!res?.data?.data || res.data.data.length == 0) {
select.value.value = '' select.value.value = ''
select.value.options = [] select.value.options = []
return return
} }
select.value.value = res.data.data[0].stcd select.value.value = res.data.data[0].stcd
select.value.options = res.data.data.map((item: any) => { select.value.options = res.data.data.map((item: any) => {
return { return {