456 lines
13 KiB
Vue
Raw Normal View History

2025-06-25 17:29:57 +08:00
<script setup lang="ts">
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { computed, nextTick, onMounted, ref, watch } from 'vue';
2025-06-25 17:29:57 +08:00
import { useRoute } from 'vue-router';
import { Page } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
2025-07-28 14:38:00 +08:00
import { postDeviceInfoPage } from '#/api-client';
import { postTreeModelDeviceDataInfoPage } from '#/api-client';
2025-07-14 08:57:04 +08:00
import { $t } from '#/locales';
2025-06-25 17:29:57 +08:00
2025-07-10 10:28:06 +08:00
import { generateDynamicColumns } from './dynamicColumns';
2025-07-11 13:51:31 +08:00
import { querySchema } from './schema';
2025-06-25 17:29:57 +08:00
2025-07-14 08:57:04 +08:00
defineOptions({
name: 'DeviceData',
});
2025-07-11 17:41:23 +08:00
// 存储设备信息选项的完整数据
const deviceOptions = ref<any[]>([]);
// 当前选中的设备信息
const selectedDeviceInfo = ref<any>(null);
2025-07-11 17:41:23 +08:00
// 获取设备信息的完整数据用于根据设备ID获取设备信息
2025-07-11 17:41:23 +08:00
const fetchDeviceOptions = async () => {
try {
2025-07-28 14:38:00 +08:00
const { data } = await postDeviceInfoPage({
2025-07-11 17:41:23 +08:00
body: {
pageIndex: 1,
pageSize: 1000,
},
});
2025-07-14 08:57:04 +08:00
2025-07-11 17:41:23 +08:00
if (data?.items) {
deviceOptions.value = data.items;
}
} catch (error) {
console.error('获取设备信息失败:', error);
}
};
2025-07-31 17:34:07 +08:00
// 根据设备地址获取设备信息对象
const getDeviceInfoByAddress = (deviceAddress: string) => {
if (!deviceAddress || !deviceOptions.value || deviceOptions.value.length === 0) {
2025-07-16 16:48:20 +08:00
return null;
}
2025-07-31 17:34:07 +08:00
return deviceOptions.value.find((device) => device.deviceAddress === deviceAddress);
2025-07-11 17:41:23 +08:00
};
2025-07-17 09:26:50 +08:00
// 格式化日期为 yyyy-MM-dd HH:mm:ss 格式
const formatDate = (date: Date | string) => {
if (!date) return undefined;
2025-07-17 09:26:50 +08:00
const d = new Date(date);
if (isNaN(d.getTime())) return undefined;
2025-07-17 09:26:50 +08:00
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
2025-07-17 09:26:50 +08:00
const day = String(d.getDate()).padStart(2, '0');
const hours = String(d.getHours()).padStart(2, '0');
const minutes = String(d.getMinutes()).padStart(2, '0');
const seconds = String(d.getSeconds()).padStart(2, '0');
2025-07-17 09:26:50 +08:00
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
2025-06-25 17:29:57 +08:00
const route = useRoute();
2025-07-31 17:34:07 +08:00
const { DeviceType, DeviceId } = route.query;
2025-07-10 10:28:06 +08:00
// 动态列定义
const dynamicColumns = ref<any[]>([]);
2025-07-10 13:50:05 +08:00
// 固定列定义(始终显示)- 基于 IoTDBTreeModelDeviceDataDto 类型
2025-07-10 10:52:19 +08:00
const fixedColumns = [
2025-07-16 17:05:52 +08:00
{ title: '序号', type: 'seq', width: 50, field: 'seq', slots: {} },
{
field: 'Timestamps',
title: $t('abp.IoTDBBase.Timestamps'),
minWidth: 150,
showOverflow: true,
slots: {},
},
{
field: 'FormattedTimestamps',
title: $t('abp.IoTDBBase.FormattedTimestamps'),
minWidth: 150,
showOverflow: true,
slots: {},
},
{
field: 'DeviceType',
title: $t('abp.IoTDBBase.DeviceType'),
minWidth: 150,
showOverflow: true,
slots: {},
},
2025-07-14 08:57:04 +08:00
{
field: 'IoTDataType',
title: $t('abp.IoTDBBase.IoTDataType'),
minWidth: 150,
2025-07-16 16:53:43 +08:00
showOverflow: true,
2025-07-16 17:05:52 +08:00
slots: {},
2025-07-14 08:57:04 +08:00
},
2025-07-17 17:12:06 +08:00
{
field: 'DeviceAddress',
title: $t('abp.IoTDBBase.DeviceAddress'),
minWidth: 150,
showOverflow: true,
slots: {},
},
2025-07-10 10:52:19 +08:00
];
2025-07-10 10:28:06 +08:00
2025-07-10 11:47:50 +08:00
// 合并固定列和动态列 - 使用计算属性确保响应式
2025-07-16 16:53:43 +08:00
const allColumns = computed(() => {
2025-07-16 17:08:11 +08:00
// 如果表格未初始化,只返回固定列
if (!isGridInitialized.value) {
return [...fixedColumns];
}
2025-07-16 16:53:43 +08:00
const columns = [...fixedColumns];
2025-07-16 16:53:43 +08:00
// 安全地添加动态列
if (dynamicColumns.value && Array.isArray(dynamicColumns.value)) {
const validDynamicColumns = dynamicColumns.value
.filter((col) => col && typeof col === 'object' && col.field && col.title)
.map((col) => ({
...col,
slots: col.slots || {}, // 确保每个列都有slots属性
}));
2025-07-16 16:53:43 +08:00
columns.push(...validDynamicColumns);
}
2025-07-16 16:53:43 +08:00
return columns;
});
2025-07-10 10:36:02 +08:00
// 初始化默认列(防止表格空白)
const initDefaultColumns = () => {
2025-07-16 16:53:43 +08:00
// 确保dynamicColumns是一个有效的数组
if (!Array.isArray(dynamicColumns.value)) {
2025-07-10 13:50:05 +08:00
dynamicColumns.value = [];
2025-07-10 10:36:02 +08:00
}
};
2025-07-16 17:08:11 +08:00
// 表格是否已初始化
const isGridInitialized = ref(false);
2025-07-10 10:36:02 +08:00
// 初始化默认列
initDefaultColumns();
2025-07-10 10:28:06 +08:00
2025-06-25 17:29:57 +08:00
const formOptions: VbenFormProps = {
schema: querySchema.value,
initialValues: {
2025-07-11 17:41:23 +08:00
DeviceType: DeviceType ? Number(DeviceType) : undefined,
2025-07-31 17:34:07 +08:00
DeviceAddress: DeviceId as string, // 使用DeviceId作为DeviceAddress的初始值
},
2025-07-10 10:28:06 +08:00
// 禁用表单值变化时自动提交,使用自定义处理函数
submitOnChange: false,
// 添加表单值变化的处理函数
handleValuesChange: async (values, changedFields) => {
2025-07-11 17:41:23 +08:00
// 当任何相关字段发生变化时,刷新表格数据
2025-07-14 08:57:04 +08:00
const relevantFields = new Set([
2025-07-31 17:34:07 +08:00
'DeviceAddress',
2025-07-14 08:57:04 +08:00
'DeviceType',
'EndCreationTime',
2025-07-14 08:57:04 +08:00
'IoTDataType',
2025-07-17 09:21:58 +08:00
'StartCreationTime',
2025-07-14 08:57:04 +08:00
]);
const hasRelevantChange = changedFields.some((field) =>
relevantFields.has(field),
);
2025-07-31 17:34:07 +08:00
// 新增DeviceAddress变化时同步selectedDeviceInfo
if (changedFields.includes('DeviceAddress')) {
const deviceAddress = values.DeviceAddress;
2025-07-31 17:34:07 +08:00
if (deviceAddress) {
// 先尝试从 deviceOptions 中查找(备用方案)
let device =
deviceOptions.value.length > 0
2025-07-31 17:34:07 +08:00
? deviceOptions.value.find((d) => d.deviceAddress === deviceAddress)
: null;
// 如果没找到,尝试从 DeviceSelect 组件中获取
if (!device && gridApi?.formApi) {
try {
// 获取 DeviceSelect 组件的实例
const deviceSelectRef =
2025-07-31 17:34:07 +08:00
gridApi.formApi.getFieldComponentRef('DeviceAddress');
if (deviceSelectRef && deviceSelectRef.getSelectedDevice) {
device = deviceSelectRef.getSelectedDevice();
}
} catch {
2025-07-16 16:31:01 +08:00
// 静默处理错误
}
}
if (device) {
selectedDeviceInfo.value = device;
} else {
// 如果还是没找到,尝试延迟获取(组件可能还没完全更新)
setTimeout(() => {
try {
const deviceSelectRef =
2025-07-31 17:34:07 +08:00
gridApi.formApi.getFieldComponentRef('DeviceAddress');
if (deviceSelectRef && deviceSelectRef.getSelectedDevice) {
const delayedDevice = deviceSelectRef.getSelectedDevice();
if (delayedDevice) {
selectedDeviceInfo.value = delayedDevice;
}
}
} catch {
2025-07-16 16:31:01 +08:00
// 静默处理错误
}
}, 100);
}
} else {
selectedDeviceInfo.value = null;
}
}
2025-07-11 17:41:23 +08:00
if (hasRelevantChange) {
2025-07-10 10:28:06 +08:00
// 使用 setTimeout 确保表单值已经完全更新
setTimeout(async () => {
const latestValues = await gridApi.formApi.getValues();
gridApi.reload(latestValues);
}, 0);
}
},
2025-06-25 17:29:57 +08:00
};
2025-07-10 11:47:50 +08:00
2025-06-25 17:29:57 +08:00
const gridOptions: VxeGridProps<any> = {
checkboxConfig: {
highlight: true,
labelField: 'name',
},
2025-07-16 17:08:11 +08:00
columns: fixedColumns, // 初始化时只使用固定列
2025-06-25 17:29:57 +08:00
height: 'auto',
keepSource: true,
2025-07-16 17:34:58 +08:00
// 确保分页功能正常工作
pager: true,
2025-07-10 10:36:02 +08:00
pagerConfig: {
currentPage: 1,
pageSize: 20,
},
2025-06-25 17:29:57 +08:00
toolbarConfig: {
custom: true,
},
customConfig: {
storage: true,
},
2025-07-10 10:52:19 +08:00
// 添加调试配置
showOverflow: true,
showHeaderOverflow: true,
2025-06-25 17:29:57 +08:00
proxyConfig: {
ajax: {
2025-07-17 08:35:36 +08:00
query: async ({ page, sorts, filters }, formValues) => {
// 确保page参数存在
if (!page) {
return { items: [], totalCount: 0 };
}
2025-07-17 08:48:10 +08:00
// 获取当前表单值如果formValues为空则从表单API获取
const currentFormValues =
formValues ||
(gridApi?.formApi ? await gridApi.formApi.getValues() : {}) ||
{};
2025-07-11 17:41:23 +08:00
// 处理DeviceType和IoTDataType确保传递数字类型
2025-07-31 17:34:07 +08:00
const deviceTypeValue = currentFormValues.DeviceType;
2025-07-14 08:57:04 +08:00
const deviceTypeNumber = deviceTypeValue
? Number(deviceTypeValue)
: undefined;
2025-07-17 08:48:10 +08:00
const ioTDataTypeValue = currentFormValues.IoTDataType;
2025-07-14 08:57:04 +08:00
2025-07-17 09:21:58 +08:00
// 处理日期范围参数
const startCreationTime = currentFormValues.StartCreationTime
? formatDate(currentFormValues.StartCreationTime)
: undefined;
const endCreationTime = currentFormValues.EndCreationTime
? formatDate(currentFormValues.EndCreationTime)
: undefined;
2025-07-17 09:21:58 +08:00
2025-07-31 17:34:07 +08:00
// 获取选中的设备信息
let deviceAddress = currentFormValues.DeviceAddress || '';
// 优先使用选中的设备信息
const deviceInfo =
selectedDeviceInfo.value ||
2025-07-31 17:34:07 +08:00
(currentFormValues.DeviceAddress && deviceOptions.value.length > 0
? getDeviceInfoByAddress(currentFormValues.DeviceAddress)
: null);
if (deviceInfo) {
2025-07-31 17:34:07 +08:00
deviceAddress = deviceInfo.deviceAddress || deviceAddress;
}
2025-07-10 10:52:19 +08:00
try {
const { data } = await postTreeModelDeviceDataInfoPage({
body: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
2025-07-31 17:34:07 +08:00
// 使用设备地址作为DeviceAddress
DeviceAddress: deviceAddress,
2025-07-16 16:48:20 +08:00
DeviceType: deviceTypeNumber || undefined,
IoTDataType: ioTDataTypeValue || undefined,
2025-07-17 09:21:58 +08:00
// 添加日期范围参数
StartCreationTime: startCreationTime || undefined,
EndCreationTime: endCreationTime || undefined,
2025-07-10 10:52:19 +08:00
},
});
2025-07-11 13:51:31 +08:00
// 简化处理逻辑,直接使用接口返回的数据
2025-07-10 10:52:19 +08:00
if (data?.items && data.items.length > 0) {
2025-07-16 16:53:43 +08:00
try {
// 动态生成列定义
const generatedColumns = generateDynamicColumns(data.items);
// 更新动态列
dynamicColumns.value = generatedColumns;
// 使用setState更新整个gridOptions确保列定义能够正确更新
await nextTick();
if (gridApi && gridApi.setState) {
gridApi.setState({
gridOptions: {
...gridOptions,
columns: allColumns.value,
2025-07-16 17:34:58 +08:00
// 保持分页配置
pager: true,
pagerConfig: gridOptions.pagerConfig,
2025-07-16 16:53:43 +08:00
},
});
}
} catch (error) {
console.error('更新列定义时出错:', error);
// 如果列更新失败,使用空数组
dynamicColumns.value = [];
}
2025-07-11 13:51:31 +08:00
// 直接使用接口返回的totalCount
2025-07-11 13:51:31 +08:00
const result = {
items: data.items || [],
totalCount: data.totalCount || 0,
2025-07-11 13:51:31 +08:00
};
2025-07-14 08:57:04 +08:00
2025-07-11 13:51:31 +08:00
return result;
2025-07-10 15:33:21 +08:00
}
2025-07-10 11:47:50 +08:00
return {
items: [],
totalCount: 0,
};
2025-07-10 10:52:19 +08:00
} catch (error) {
console.error('API调用出错:', error);
throw error;
2025-07-10 10:28:06 +08:00
}
2025-06-25 17:29:57 +08:00
},
},
},
};
2025-07-10 10:28:06 +08:00
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
2025-07-10 15:33:21 +08:00
// 监听分页器状态变化
2025-07-11 13:51:31 +08:00
watch(
() => gridApi?.pagerApi?.pageSize,
(newSize, oldSize) => {
if (newSize !== oldSize && oldSize) {
// 重置到第一页
gridApi.pagerApi.currentPage = 1;
2025-07-16 17:34:58 +08:00
// 触发数据重新加载
gridApi.reload();
}
},
);
// 监听当前页变化
watch(
() => gridApi?.pagerApi?.currentPage,
(newPage, oldPage) => {
if (newPage !== oldPage && oldPage) {
// 触发数据重新加载
gridApi.reload();
2025-07-10 15:33:21 +08:00
}
2025-07-11 13:51:31 +08:00
},
);
2025-07-16 17:08:11 +08:00
// 初始化函数
const initializeGrid = async () => {
try {
// 获取设备信息数据
await fetchDeviceOptions();
2025-07-16 17:08:11 +08:00
// 标记表格已初始化
isGridInitialized.value = true;
2025-07-16 17:08:11 +08:00
// 更新表格列定义
if (gridApi && gridApi.setState) {
await nextTick();
gridApi.setState({
gridOptions: {
...gridOptions,
columns: allColumns.value,
2025-07-16 17:34:58 +08:00
// 保持分页配置
pager: true,
pagerConfig: gridOptions.pagerConfig,
2025-07-16 17:08:11 +08:00
},
});
}
2025-07-16 17:08:11 +08:00
// 如果有路由参数,自动触发查询
2025-07-31 17:34:07 +08:00
if (DeviceType || DeviceId) {
2025-07-16 17:08:11 +08:00
// 延迟一下确保表格已完全初始化
setTimeout(() => {
if (gridApi) {
gridApi.reload();
}
}, 300);
}
} catch (error) {
console.error('初始化表格失败:', error);
}
};
// 监听路由参数变化,当有路由参数时自动触发查询
watch(
2025-07-31 17:34:07 +08:00
() => [DeviceType, DeviceId],
async (newValues, oldValues) => {
// 如果有路由参数,等待设备信息加载完成后自动触发查询
if (newValues.some(Boolean) && gridApi && isGridInitialized.value) {
// 延迟一下确保表单值已经设置
setTimeout(() => {
gridApi.reload();
}, 100);
}
},
{ immediate: false }, // 改为false避免立即触发
);
2025-08-01 14:58:48 +08:00
2025-07-16 17:08:11 +08:00
// 页面初始化时,延迟初始化表格
onMounted(async () => {
2025-07-16 17:08:11 +08:00
// 延迟初始化确保VXE表格组件已完全挂载
setTimeout(async () => {
await initializeGrid();
}, 100);
});
2025-06-25 17:29:57 +08:00
</script>
<template>
<Page auto-content-height>
<Grid />
</Page>
</template>