2025-07-11 17:41:23 +08:00

321 lines
10 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.

<script setup lang="ts">
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { computed, nextTick, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Page } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { postTreeModelDeviceDataInfoPage, postMetersPage } from '#/api-client';
import { generateDynamicColumns } from './dynamicColumns';
import { querySchema } from './schema';
// 存储设备信息选项的完整数据
const deviceOptions = ref<any[]>([]);
// 获取设备信息的完整数据
const fetchDeviceOptions = async () => {
try {
const { data } = await postMetersPage({
body: {
pageIndex: 1,
pageSize: 1000,
},
});
if (data?.items) {
deviceOptions.value = data.items;
console.log('设备信息选项:', deviceOptions.value);
}
} catch (error) {
console.error('获取设备信息失败:', error);
}
};
// 根据设备ID获取设备信息对象
const getDeviceInfoById = (deviceId: string) => {
return deviceOptions.value.find(device => device.id === deviceId);
};
defineOptions({
name: 'DeviceData',
});
const route = useRoute();
const { DeviceType, DeviceId, FocusAddress } = route.query;
// 动态列定义
const dynamicColumns = ref<any[]>([]);
// 固定列定义(始终显示)- 基于 IoTDBTreeModelDeviceDataDto 类型
const fixedColumns = [
{ title: '序号', type: 'seq', width: 50 },
{ field: 'Timestamps', title: '时间戳', minWidth: 150 },
{ field: 'SystemName', title: '系统名称', minWidth: 150 },
{ field: 'ProjectId', title: '项目ID', minWidth: 150 },
{ field: 'DeviceType', title: '设备类型', minWidth: 150 },
{ field: 'IoTDataType', title: 'IoT数据类型', minWidth: 150 },
{ field: 'DeviceId', title: '设备ID', minWidth: 150 },
];
// 合并固定列和动态列 - 使用计算属性确保响应式
const allColumns = computed(() => [...fixedColumns, ...dynamicColumns.value]);
// 初始化默认列(防止表格空白)
const initDefaultColumns = () => {
if (dynamicColumns.value.length === 0) {
// 不再需要在这里设置默认列,因为固定列已经包含了基本字段
dynamicColumns.value = [];
}
};
// 初始化默认列
initDefaultColumns();
// 获取设备信息数据
fetchDeviceOptions();
const formOptions: VbenFormProps = {
schema: querySchema.value,
initialValues: {
FocusAddress: FocusAddress as string,
DeviceType: DeviceType ? Number(DeviceType) : undefined,
DeviceId: DeviceId as string,
},
// 禁用表单值变化时自动提交,使用自定义处理函数
submitOnChange: false,
// 添加表单值变化的处理函数
handleValuesChange: async (values, changedFields) => {
// 当任何相关字段发生变化时,刷新表格数据
const relevantFields = ['SystemName', 'DeviceType', 'IoTDataType', 'DeviceId', 'FocusAddress'];
const hasRelevantChange = changedFields.some(field => relevantFields.includes(field));
if (hasRelevantChange) {
console.log('表单字段变化:', { values, changedFields });
console.log('相关字段变化:', changedFields.filter(field => relevantFields.includes(field)));
// 使用 setTimeout 确保表单值已经完全更新
setTimeout(async () => {
const latestValues = await gridApi.formApi.getValues();
console.log('最新表单值:', latestValues);
gridApi.reload(latestValues);
}, 0);
}
},
};
const gridOptions: VxeGridProps<any> = {
checkboxConfig: {
highlight: true,
labelField: 'name',
},
columns: allColumns, // 使用计算属性
height: 'auto',
keepSource: true,
pagerConfig: {
currentPage: 1,
pageSize: 20,
// 添加分页事件处理
onChange: (currentPage: number, pageSize: number) => {
console.log('分页变化:', { currentPage, pageSize });
// 当pageSize变化时重置到第一页
if (pageSize !== gridOptions.pagerConfig.pageSize) {
console.log('页面大小变化,重置到第一页');
// 更新配置中的pageSize
gridOptions.pagerConfig.pageSize = pageSize;
gridOptions.pagerConfig.currentPage = 1;
}
},
},
toolbarConfig: {
custom: true,
},
customConfig: {
storage: true,
},
// 添加调试配置
showOverflow: true,
showHeaderOverflow: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
console.log('=== API调用开始 ===');
// 处理DeviceType和IoTDataType确保传递数字类型
const deviceTypeValue = formValues.DeviceType || DeviceType;
const deviceTypeNumber = deviceTypeValue ? Number(deviceTypeValue) : undefined;
const ioTDataTypeValue = formValues.IoTDataType;
const ioTDataTypeNumber = ioTDataTypeValue ? Number(ioTDataTypeValue) : undefined;
// 处理DeviceId当设备类型为集中器(10)时使用focusId
let finalDeviceId = formValues.DeviceId || DeviceId;
if (deviceTypeNumber === 10 && formValues.DeviceId) {
const deviceInfo = getDeviceInfoById(formValues.DeviceId);
if (deviceInfo && deviceInfo.focusId) {
finalDeviceId = deviceInfo.focusId;
console.log('设备类型为集中器使用focusId:', {
originalDeviceId: formValues.DeviceId,
focusId: deviceInfo.focusId,
deviceInfo: deviceInfo,
});
}
}
console.log('请求参数:', {
page,
formValues,
routeParams: { DeviceType, DeviceId, FocusAddress },
typeConversions: {
deviceType: {
originalValue: deviceTypeValue,
convertedValue: deviceTypeNumber,
type: typeof deviceTypeNumber,
},
ioTDataType: {
originalValue: ioTDataTypeValue,
convertedValue: ioTDataTypeNumber,
type: typeof ioTDataTypeNumber,
},
deviceId: {
originalValue: formValues.DeviceId || DeviceId,
finalValue: finalDeviceId,
isFocusId: deviceTypeNumber === 10 && formValues.DeviceId && getDeviceInfoById(formValues.DeviceId)?.focusId,
},
},
finalParams: {
...formValues,
pageIndex: page.currentPage,
pageSize: page.pageSize,
DeviceType: deviceTypeNumber,
DeviceId: finalDeviceId,
FocusAddress: formValues.FocusAddress || FocusAddress,
SystemName: formValues.SystemName,
IoTDataType: ioTDataTypeNumber,
},
});
try {
const { data } = await postTreeModelDeviceDataInfoPage({
body: {
...formValues,
pageIndex: page.currentPage,
pageSize: page.pageSize,
// 优先使用表单中的值,如果没有则使用路由参数
DeviceType: deviceTypeNumber,
DeviceId: finalDeviceId,
FocusAddress: formValues.FocusAddress || FocusAddress,
// 添加其他表单参数
SystemName: formValues.SystemName,
IoTDataType: ioTDataTypeNumber,
},
});
console.log('API返回的原始数据:', data);
console.log('数据类型:', typeof data);
console.log(
'data是否为null/undefined:',
data === null || data === undefined,
);
if (data) {
console.log('data.items存在:', !!data.items);
console.log(
'data.items类型:',
Array.isArray(data.items) ? 'Array' : typeof data.items,
);
if (data.items) {
console.log('data.items长度:', data.items.length);
if (data.items.length > 0) {
console.log('第一条数据:', data.items[0]);
console.log(
'第一条数据的所有字段:',
Object.keys(data.items[0]),
);
}
}
}
// 简化处理逻辑,直接使用接口返回的数据
if (data?.items && data.items.length > 0) {
console.log('原始items数据:', data.items);
// 动态生成列定义
const generatedColumns = generateDynamicColumns(data.items);
console.log('生成的列定义:', generatedColumns);
// 更新动态列
dynamicColumns.value = generatedColumns;
// 使用setState更新整个gridOptions确保列定义能够正确更新
await nextTick();
gridApi.setState({
gridOptions: {
...gridOptions,
columns: allColumns.value,
},
});
// 直接使用接口返回的totalCount
const result = {
items: data.items || [],
totalCount: data.totalCount || 0,
};
console.log('返回给表格的数据:', result);
console.log('总数:', result.totalCount, '当前页数据量:', result.items.length);
console.log('分页信息:', {
currentPage: page.currentPage,
pageSize: page.pageSize,
});
return result;
}
console.log('没有数据或数据为空');
return {
items: [],
totalCount: 0,
};
} catch (error) {
console.error('API调用出错:', error);
throw error;
}
},
},
},
};
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
// 监听分页器状态变化
watch(
() => gridApi?.pagerApi?.currentPage,
(newPage, oldPage) => {
console.log('当前页变化:', { newPage, oldPage });
},
);
watch(
() => gridApi?.pagerApi?.pageSize,
(newSize, oldSize) => {
console.log('页面大小变化:', { newSize, oldSize });
if (newSize !== oldSize && oldSize) {
console.log('页面大小从', oldSize, '变为', newSize, ',重置到第一页');
// 重置到第一页
gridApi.pagerApi.currentPage = 1;
}
},
);
</script>
<template>
<Page auto-content-height>
<Grid />
</Page>
</template>