Compare commits

...

10 Commits

Author SHA1 Message Date
ChenYi
113f24cc9d onenet日志查询 2025-07-17 11:47:00 +08:00
ChenYi
17be5382bf 默认查询的设备已经可以查询 2025-07-17 11:27:42 +08:00
ChenYi
b706f70e06 onenetlog 2025-07-17 10:50:47 +08:00
ChenYi
8609e3198a 修改代码 2025-07-17 10:27:56 +08:00
ChenYi
6019490b00 ctwinglog 2025-07-17 10:23:38 +08:00
ChenYi
3669aadcb0 新增格式化时间 2025-07-17 09:54:45 +08:00
ChenYi
27a71e1d5f 修复日期格式异常的问题 2025-07-17 09:26:50 +08:00
ChenYi
dafeaf3075 新增日期查询 2025-07-17 09:21:58 +08:00
ChenYi
d55e939e84 修改分页失效的问题 2025-07-17 08:48:10 +08:00
ChenYi
edc6241d7d 修改分页 2025-07-17 08:35:36 +08:00
8 changed files with 705 additions and 144 deletions

View File

@ -233,6 +233,7 @@
"DeviceType": "DeviceType", "DeviceType": "DeviceType",
"DeviceId": "DeviceId", "DeviceId": "DeviceId",
"Timestamps": "Timestamps", "Timestamps": "Timestamps",
"FormattedTimestamps": "Formatted Timestamps",
"DevicePath": "DevicePath" "DevicePath": "DevicePath"
}, },
"CTWingLog": { "CTWingLog": {

View File

@ -233,6 +233,7 @@
"DeviceType": "设备类型", "DeviceType": "设备类型",
"DeviceId": "设备ID", "DeviceId": "设备ID",
"Timestamps": "时标(纳秒)", "Timestamps": "时标(纳秒)",
"FormattedTimestamps": "时标",
"DevicePath": "设备路径" "DevicePath": "设备路径"
}, },
"CTWingLog": { "CTWingLog": {

View File

@ -2,6 +2,7 @@
import type { VbenFormProps } from '#/adapter/form'; import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import { ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
@ -9,6 +10,7 @@ import { Page } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { postCTWingLogInfoPage } from '#/api-client'; import { postCTWingLogInfoPage } from '#/api-client';
import DeviceSelect from '../deviceData/DeviceSelect.vue';
import { querySchema, tableSchema } from './schema'; import { querySchema, tableSchema } from './schema';
defineOptions({ defineOptions({
@ -17,9 +19,24 @@ defineOptions({
const route = useRoute(); const route = useRoute();
const { DeviceType, DeviceId, FocusAddress } = route.query; const { DeviceType, DeviceId, FocusAddress } = route.query;
//
const deviceSelectRef = ref();
//
const selectedDeviceInfo = ref<any>(null);
//
const formatDate = (date: any) => {
if (!date) return '';
if (typeof date === 'string') return date;
if (date.toISOString) return date.format('YYYY-MM-DD HH:mm:ss');
return '';
};
const formOptions: VbenFormProps = { const formOptions: VbenFormProps = {
schema: querySchema.value, schema: querySchema.value,
}; };
const gridOptions: VxeGridProps<any> = { const gridOptions: VxeGridProps<any> = {
checkboxConfig: { checkboxConfig: {
highlight: true, highlight: true,
@ -28,7 +45,19 @@ const gridOptions: VxeGridProps<any> = {
columns: tableSchema.value, columns: tableSchema.value,
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
pagerConfig: {}, pagerConfig: {
currentPage: 1,
pageSize: 10,
pageSizes: [10, 20, 100],
layouts: [
'PrevPage',
'JumpNumber',
'NextPage',
'FullJump',
'Sizes',
'Total',
],
},
toolbarConfig: { toolbarConfig: {
custom: true, custom: true,
}, },
@ -38,27 +67,41 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ page }, formValues) => { query: async ({ page }, formValues) => {
//
let deviceId = '';
let systemName = '';
const deviceType = formValues?.DeviceType || '';
const finalFocusAddress = formValues.FocusAddress || '';
if (deviceSelectRef.value) {
const deviceInfo = deviceSelectRef.value.getSelectedDeviceInfo();
if (deviceInfo) {
finalFocusAddress = deviceInfo.focusAddress || '';
systemName = deviceInfo.systemName || '';
// 10focusIdmeterId
deviceId =
Number(deviceType) === 10
? deviceInfo.focusId || ''
: deviceInfo.meterId || '';
}
}
// //
const queryParams: any = { const queryParams: any = {
pageIndex: page.currentPage, pageIndex: page.currentPage,
pageSize: page.pageSize, pageSize: page.pageSize,
SearchKeyword: formValues?.SearchKeyword || '',
DeviceType: deviceType,
IoTDataType: formValues?.IoTDataType || '',
DeviceId: deviceId,
SystemName: systemName || formValues?.SystemName || '',
StartCreationTime: formatDate(formValues?.StartCreationTime),
EndCreationTime: formatDate(formValues?.EndCreationTime),
FocusAddress: finalFocusAddress,
}; };
//
if (formValues) {
Object.assign(queryParams, formValues);
}
//
if (DeviceType) queryParams.DeviceType = DeviceType; if (DeviceType) queryParams.DeviceType = DeviceType;
if (DeviceId) queryParams.DeviceId = DeviceId; if (DeviceId) queryParams.DeviceId = DeviceId;
if (FocusAddress) queryParams.FocusAddress = FocusAddress;
const { data } = await postCTWingLogInfoPage({ const { data } = await postCTWingLogInfoPage({
body: queryParams, body: queryParams,
}); });
// totalCount
const result = { const result = {
items: data.items || [], items: data.items || [],
totalCount: data.totalCount || (data.items ? data.items.length : 0), totalCount: data.totalCount || (data.items ? data.items.length : 0),
@ -69,11 +112,50 @@ const gridOptions: VxeGridProps<any> = {
}, },
}; };
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions }); const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
//
watch(
() => gridApi?.pagerApi?.pageSize,
(newSize, oldSize) => {
if (newSize !== oldSize && oldSize) {
//
gridApi.pagerApi.currentPage = 1;
//
gridApi.reload();
}
},
);
//
watch(
() => gridApi?.pagerApi?.currentPage,
(newPage, oldPage) => {
if (newPage !== oldPage && oldPage) {
//
gridApi.reload();
}
},
);
// DeviceId
watch(
() => gridApi?.getFormModel?.()?.DeviceId,
(newVal, oldVal) => {
if (newVal !== oldVal) {
gridApi.reload();
}
},
);
</script> </script>
<template> <template>
<Page auto-content-height> <Page auto-content-height>
<Grid /> <Grid>
<template #DeviceId="{ model, field }">
<DeviceSelect ref="deviceSelectRef" v-model:value="model[field]"
:placeholder="$t('common.pleaseSelect') + $t('abp.log.deviceInfo')" allow-clear />
</template>
</Grid>
</Page> </Page>
</template> </template>

View File

@ -4,118 +4,212 @@ import { computed } from 'vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { getSelectResultList, postMetersPage } from '#/api-client';
import { $t } from '#/locales'; import { $t } from '#/locales';
export const querySchema = computed(() => [ export const querySchema = computed(() => [
{ {
component: 'Input', component: 'ApiSelect',
fieldName: 'FocusAddress',
label: $t('abp.CTWingLog.FocusAddress'),
},
{
component: 'Input',
fieldName: 'DeviceId',
label: $t('abp.IoTDBBase.DeviceId'),
},
{
component: 'Input',
fieldName: 'DeviceType',
label: $t('abp.IoTDBBase.DeviceType'),
},
{
component: 'Input',
fieldName: 'SystemName', fieldName: 'SystemName',
label: $t('abp.IoTDBBase.SystemName'), label: $t('abp.IoTDBBase.SystemName'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'BusinessSystemEnum',
},
},
labelField: 'secondValue',
valueField: 'value',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
}, },
{ {
component: 'Input', component: 'ApiSelect',
fieldName: 'ProjectId', fieldName: 'DeviceType',
label: $t('abp.IoTDBBase.ProjectId'), label: $t('abp.IoTDBBase.DeviceType'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'MeterTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
},
{
component: 'ApiSelect',
fieldName: 'IoTDataType',
label: $t('abp.IoTDBBase.IoTDataType'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'IoTDBDataTypeConst',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
},
{
component: 'DeviceSelect',
fieldName: 'DeviceId',
label: $t('abp.log.deviceInfo'),
componentProps: {
placeholder: $t('common.pleaseSelect') + $t('abp.log.deviceInfo'),
allowClear: true,
},
},
// 新增开始时间选择器
{
component: 'DatePicker',
fieldName: 'StartCreationTime',
label: '开始时间',
componentProps: {
placeholder: '开始时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
},
// 新增结束时间选择器
{
component: 'DatePicker',
fieldName: 'EndCreationTime',
label: '结束时间',
componentProps: {
placeholder: '结束时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
}, },
]); ]);
export const tableSchema: any = computed((): VxeGridProps['columns'] => [ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
{ title: $t('common.seq'), type: 'seq', width: 50 }, { title: $t('common.seq'), type: 'seq', width: 50, slots: {} },
{ {
field: 'timestamps', field: 'timestamps',
title: $t('abp.IoTDBBase.Timestamps'), title: $t('abp.IoTDBBase.Timestamps'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
{ field: 'systemName', title: $t('abp.IoTDBBase.SystemName'), minWidth: 150 }, { field: 'systemName', title: $t('abp.IoTDBBase.SystemName'), minWidth: 150, slots: {} },
{
field: 'projectId',
title: $t('abp.IoTDBBase.ProjectId'),
minWidth: 150,
},
{ {
field: 'deviceType', field: 'deviceType',
title: $t('abp.IoTDBBase.DeviceType'), title: $t('abp.IoTDBBase.DeviceType'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
{ {
field: 'ioTDataType', field: 'ioTDataType',
title: $t('abp.IoTDBBase.IoTDataType'), title: $t('abp.IoTDBBase.IoTDataType'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
{ {
field: 'deviceId', field: 'deviceId',
title: $t('abp.IoTDBBase.DeviceId'), title: $t('abp.IoTDBBase.DeviceId'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
{ {
field: 'platformTenantId', field: 'platformTenantId',
title: $t('abp.CTWingLog.PlatformTenantId'), title: $t('abp.CTWingLog.PlatformTenantId'),
minWidth: 150, minWidth: 150,
}, slots: {},
{
field: 'productId',
title: $t('abp.CTWingLog.ProductId'),
minWidth: 150,
}, },
{ {
field: 'serviceId', field: 'serviceId',
title: $t('abp.CTWingLog.ServiceId'), title: $t('abp.CTWingLog.ServiceId'),
minWidth: 150, minWidth: 150,
}, slots: {},
{
field: 'platformDeviceId',
title: $t('abp.CTWingLog.PlatformDeviceId'),
minWidth: 150,
}, },
{ {
field: 'messageType', field: 'messageType',
title: $t('abp.CTWingLog.MessageType'), title: $t('abp.CTWingLog.MessageType'),
minWidth: 180, minWidth: 180,
slots: {},
}, },
{ {
field: 'protocol', field: 'protocol',
title: $t('abp.CTWingLog.Protocol'), title: $t('abp.CTWingLog.Protocol'),
minWidth: 100, minWidth: 100,
}, slots: {},
{
field: 'focusAddress',
title: $t('abp.CTWingLog.FocusAddress'),
minWidth: 150,
},
{
field: 'meterAddress',
title: $t('abp.CTWingLog.MeterAddress'),
minWidth: 150,
}, },
{ {
field: 'rawMessage', field: 'rawMessage',
title: $t('abp.CTWingLog.RawMessage'), title: $t('abp.CTWingLog.RawMessage'),
minWidth: 200, minWidth: 200,
slots: {},
}, },
{ {
field: 'receivedPayload', field: 'receivedPayload',
title: $t('abp.CTWingLog.ReceivedPayload'), title: $t('abp.CTWingLog.ReceivedPayload'),
minWidth: 200, minWidth: 200,
slots: {},
}, },
{ {
field: 'receivedTime', field: 'receivedTime',
title: $t('abp.CTWingLog.ReceivedTime'), title: $t('abp.CTWingLog.ReceivedTime'),
minWidth: 150, minWidth: 150,
slots: {},
formatter: ({ cellValue }) => { formatter: ({ cellValue }) => {
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''; return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : '';
}, },
@ -124,10 +218,12 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
field: 'imsi', field: 'imsi',
title: $t('abp.CTWingLog.IMSI'), title: $t('abp.CTWingLog.IMSI'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
{ {
field: 'imei', field: 'imei',
title: $t('abp.CTWingLog.IMEI'), title: $t('abp.CTWingLog.IMEI'),
minWidth: 150, minWidth: 150,
slots: {},
}, },
]); ]);

View File

@ -49,6 +49,22 @@ const getDeviceInfoById = (deviceId: string) => {
return deviceOptions.value.find((device) => device.id === deviceId); return deviceOptions.value.find((device) => device.id === deviceId);
}; };
// yyyy-MM-dd HH:mm:ss
const formatDate = (date: Date | string) => {
if (!date) return undefined;
const d = new Date(date);
if (isNaN(d.getTime())) return undefined;
const year = d.getFullYear();
const month = String(d.getMonth() +1).padStart(2, '0');
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');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const route = useRoute(); const route = useRoute();
@ -61,6 +77,7 @@ const dynamicColumns = ref<any[]>([]);
const fixedColumns = [ const fixedColumns = [
{ title: '序号', type: 'seq', width: 50, field: 'seq', slots: {} }, { title: '序号', type: 'seq', width: 50, field: 'seq', slots: {} },
{ field: 'Timestamps', title: $t('abp.IoTDBBase.Timestamps'), minWidth: 150, showOverflow: true, 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: 'SystemName', title: $t('abp.IoTDBBase.SystemName'), minWidth: 150, showOverflow: true, slots: {} }, { field: 'SystemName', title: $t('abp.IoTDBBase.SystemName'), minWidth: 150, showOverflow: true, slots: {} },
{ field: 'ProjectId', title: $t('abp.IoTDBBase.ProjectId'), minWidth: 150, showOverflow: true, slots: {} }, { field: 'ProjectId', title: $t('abp.IoTDBBase.ProjectId'), minWidth: 150, showOverflow: true, slots: {} },
{ field: 'DeviceType', title: $t('abp.IoTDBBase.DeviceType'), minWidth: 150, showOverflow: true, slots: {} }, { field: 'DeviceType', title: $t('abp.IoTDBBase.DeviceType'), minWidth: 150, showOverflow: true, slots: {} },
@ -130,6 +147,8 @@ const formOptions: VbenFormProps = {
'FocusAddress', 'FocusAddress',
'IoTDataType', 'IoTDataType',
'SystemName', 'SystemName',
'StartCreationTime',
'EndCreationTime',
]); ]);
const hasRelevantChange = changedFields.some((field) => const hasRelevantChange = changedFields.some((field) =>
relevantFields.has(field), relevantFields.has(field),
@ -202,21 +221,6 @@ const gridOptions: VxeGridProps<any> = {
pagerConfig: { pagerConfig: {
currentPage: 1, currentPage: 1,
pageSize: 20, pageSize: 20,
//
onChange: (currentPage: number, pageSize: number) => {
console.log('分页变化:', { currentPage, pageSize });
// pageSize
if (pageSize !== gridOptions.pagerConfig.pageSize) {
// pageSize
gridOptions.pagerConfig.pageSize = pageSize;
gridOptions.pagerConfig.currentPage = 1;
}
//
if (gridApi) {
console.log('触发数据重新加载');
gridApi.reload();
}
},
}, },
toolbarConfig: { toolbarConfig: {
custom: true, custom: true,
@ -229,21 +233,31 @@ const gridOptions: VxeGridProps<any> = {
showHeaderOverflow: true, showHeaderOverflow: true,
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ page }, formValues) => { query: async ({ page, sorts, filters }, formValues) => {
// page
if (!page) {
return { items: [], totalCount: 0 };
}
// formValuesAPI
const currentFormValues = formValues || (gridApi?.formApi ? await gridApi.formApi.getValues() : {}) || {};
// DeviceTypeIoTDataType // DeviceTypeIoTDataType
const deviceTypeValue = formValues.DeviceType || DeviceType; const deviceTypeValue = currentFormValues.DeviceType || DeviceType;
const deviceTypeNumber = deviceTypeValue const deviceTypeNumber = deviceTypeValue
? Number(deviceTypeValue) ? Number(deviceTypeValue)
: undefined; : undefined;
const ioTDataTypeValue = formValues.IoTDataType; const ioTDataTypeValue = currentFormValues.IoTDataType;
//
const startCreationTime = currentFormValues.StartCreationTime ? formatDate(currentFormValues.StartCreationTime) : undefined;
const endCreationTime = currentFormValues.EndCreationTime ? formatDate(currentFormValues.EndCreationTime) : undefined;
// DeviceId(10)使focusId // DeviceId(10)使focusId
let finalDeviceId = formValues.DeviceId || DeviceId || ''; let finalDeviceId = currentFormValues.DeviceId || DeviceId || '';
let finalFocusAddress = formValues.FocusAddress || ''; let finalFocusAddress = currentFormValues.FocusAddress || '';
// 使 // 使
const deviceInfo = selectedDeviceInfo.value || (formValues.DeviceId && deviceOptions.value.length > 0 ? getDeviceInfoById(formValues.DeviceId) : null); const deviceInfo = selectedDeviceInfo.value || (currentFormValues.DeviceId && deviceOptions.value.length > 0 ? getDeviceInfoById(currentFormValues.DeviceId) : null);
if (deviceInfo) { if (deviceInfo) {
finalFocusAddress = deviceInfo.focusAddress || ''; finalFocusAddress = deviceInfo.focusAddress || '';
@ -261,16 +275,6 @@ const gridOptions: VxeGridProps<any> = {
} }
} }
try { try {
console.log('API调用参数:', {
pageIndex: page.currentPage,
pageSize: page.pageSize,
DeviceType: deviceTypeNumber,
DeviceId: finalDeviceId,
FocusAddress: finalFocusAddress,
SystemName: formValues.SystemName || SystemName,
IoTDataType: ioTDataTypeValue,
});
const { data } = await postTreeModelDeviceDataInfoPage({ const { data } = await postTreeModelDeviceDataInfoPage({
body: { body: {
pageIndex: page.currentPage, pageIndex: page.currentPage,
@ -280,8 +284,11 @@ const gridOptions: VxeGridProps<any> = {
DeviceId: finalDeviceId ? finalDeviceId.toString() : '', DeviceId: finalDeviceId ? finalDeviceId.toString() : '',
FocusAddress: finalFocusAddress || FocusAddress || '', FocusAddress: finalFocusAddress || FocusAddress || '',
// //
SystemName: formValues.SystemName || SystemName || '', SystemName: currentFormValues.SystemName || SystemName,
IoTDataType: ioTDataTypeValue || undefined, IoTDataType: ioTDataTypeValue || undefined,
//
StartCreationTime: startCreationTime || undefined,
EndCreationTime: endCreationTime || undefined,
}, },
}); });
@ -342,12 +349,10 @@ const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
watch( watch(
() => gridApi?.pagerApi?.pageSize, () => gridApi?.pagerApi?.pageSize,
(newSize, oldSize) => { (newSize, oldSize) => {
console.log('页面大小变化:', { newSize, oldSize });
if (newSize !== oldSize && oldSize) { if (newSize !== oldSize && oldSize) {
// //
gridApi.pagerApi.currentPage = 1; gridApi.pagerApi.currentPage = 1;
// //
console.log('页面大小变化,触发重新加载');
gridApi.reload(); gridApi.reload();
} }
}, },
@ -357,10 +362,8 @@ watch(
watch( watch(
() => gridApi?.pagerApi?.currentPage, () => gridApi?.pagerApi?.currentPage,
(newPage, oldPage) => { (newPage, oldPage) => {
console.log('当前页变化:', { newPage, oldPage });
if (newPage !== oldPage && oldPage) { if (newPage !== oldPage && oldPage) {
// //
console.log('当前页变化,触发重新加载');
gridApi.reload(); gridApi.reload();
} }
}, },

View File

@ -2,7 +2,7 @@ import type { VxeGridProps } from '#/adapter/vxe-table';
import { computed } from 'vue'; import { computed } from 'vue';
import { getSelectResultList, postMetersPage } from '#/api-client'; import { getSelectResultList } from '#/api-client';
import { $t } from '#/locales'; import { $t } from '#/locales';
export const querySchema = computed(() => [ export const querySchema = computed(() => [
@ -114,6 +114,30 @@ export const querySchema = computed(() => [
allowClear: true, allowClear: true,
}, },
}, },
// 新增开始时间选择器
{
component: 'DatePicker',
fieldName: 'StartCreationTime',
label: '开始时间',
componentProps: {
placeholder: '开始时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
},
// 新增结束时间选择器
{
component: 'DatePicker',
fieldName: 'EndCreationTime',
label: '结束时间',
componentProps: {
placeholder: '结束时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
},
]); ]);
export const tableSchema: any = computed((): VxeGridProps['columns'] => [ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
{ title: $t('common.seq'), type: 'seq', width: 50 }, { title: $t('common.seq'), type: 'seq', width: 50 },
@ -122,6 +146,11 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
title: $t('abp.IoTDBBase.Timestamps'), title: $t('abp.IoTDBBase.Timestamps'),
minWidth: '150', minWidth: '150',
}, },
{
field: 'FormattedTimestamps',
title: $t('abp.IoTDBBase.FormattedTimestamps'),
minWidth: '150',
},
{ {
field: 'SystemName', field: 'SystemName',
title: $t('abp.IoTDBBase.SystemName'), title: $t('abp.IoTDBBase.SystemName'),

View File

@ -2,13 +2,15 @@
import type { VbenFormProps } from '#/adapter/form'; import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import { onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { postOneNETLogInfoPage } from '#/api-client'; import { postMetersPage, postOneNETLogInfoPage } from '#/api-client';
import DeviceSelect from '../deviceData/DeviceSelect.vue';
import { querySchema, tableSchema } from './schema'; import { querySchema, tableSchema } from './schema';
defineOptions({ defineOptions({
@ -17,9 +19,161 @@ defineOptions({
const route = useRoute(); const route = useRoute();
const { DeviceType, DeviceId, FocusAddress } = route.query; const { DeviceType, DeviceId, FocusAddress } = route.query;
//
const deviceSelectRef = ref();
//
const selectedDeviceInfo = ref<any>(null);
//
const deviceOptions = ref<any[]>();
//
const fetchDeviceOptions = async () => {
try {
const { data } = await postMetersPage({
body: {
pageIndex: 1,
pageSize: 1000,
},
});
if (data?.items) {
deviceOptions.value = data.items;
}
} catch (error) {
console.error('获取设备信息失败:', error);
}
};
// ID
const getDeviceInfoById = (deviceId: string) => {
console.log('getDeviceInfoById 调用:', { deviceId, deviceOptionsLength: deviceOptions.value?.length });
if (!deviceId || !deviceOptions.value || deviceOptions.value.length === 0) {
console.log('getDeviceInfoById 返回 null - 条件不满足');
return null;
}
//
console.log('前3构:', deviceOptions.value.slice(0, 3).map(device => ({
id: device.id,
meterName: device.meterName,
meterId: device.meterId,
focusId: device.focusId,
systemName: device.systemName,
keys: Object.keys(device),
fullDevice: JSON.parse(JSON.stringify(device)) //
})));
const device = deviceOptions.value.find((device) => device.id === deviceId);
console.log('查找结果:', device);
return device;
};
//
const formatDate = (date: any) => {
if (!date) return '';
if (typeof date === 'string') return date;
if (date.toISOString) return date.format('YYYY-MM-DD HH:mm:ss');
return '';
};
// DeviceSelect
const getDeviceInfoFromRef = async () => {
if (
deviceSelectRef.value &&
typeof deviceSelectRef.value.getSelectedDevice === 'function'
) {
const deviceInfo = deviceSelectRef.value.getSelectedDevice();
console.log('从 ref 获取设备信息:', deviceInfo);
return deviceInfo;
}
return null;
};
const formOptions: VbenFormProps = { const formOptions: VbenFormProps = {
schema: querySchema.value, schema: querySchema.value,
// 使
submitOnChange: false,
//
handleValuesChange: async (values, changedFields) => {
console.log('handleValuesChange 被触发:', { values, changedFields });
console.log('当前所有表单值:', values);
console.log('DeviceType:', values.DeviceType);
console.log('IoTDataType:', values.IoTDataType);
// DeviceId selectedDeviceInfo
if (changedFields.includes('DeviceId')) {
const deviceId = values.DeviceId;
console.log('DeviceId 变化:', deviceId);
if (deviceId) {
// deviceOptions
let device = deviceOptions.value.length > 0 ? deviceOptions.value.find(d => d.id === deviceId) : null;
// DeviceSelect
if (!device && gridApi?.formApi) {
try {
// DeviceSelect
const deviceSelectRef = gridApi.formApi.getFieldComponentRef('DeviceId');
if (deviceSelectRef && deviceSelectRef.getSelectedDevice) {
device = deviceSelectRef.getSelectedDevice();
}
} catch (error) {
console.log('获取组件实例失败:', error);
}
}
if (device) {
selectedDeviceInfo.value = device;
console.log('handleValuesChange 更新设备信息:', device);
} else {
//
setTimeout(() => {
try {
const deviceSelectRef = gridApi.formApi.getFieldComponentRef('DeviceId');
if (deviceSelectRef && deviceSelectRef.getSelectedDevice) {
const delayedDevice = deviceSelectRef.getSelectedDevice();
if (delayedDevice) {
selectedDeviceInfo.value = delayedDevice;
console.log('延迟获取设备信息成功:', delayedDevice);
}
}
} catch (error) {
console.log('延迟获取组件实例失败:', error);
}
}, 100);
}
} else {
selectedDeviceInfo.value = null;
}
}
//
const relevantFields = new Set([
'DeviceId',
'DeviceType',
'IoTDataType',
'SystemName',
'StartCreationTime',
'EndCreationTime',
]);
const hasRelevantChange = changedFields.some((field) =>
relevantFields.has(field),
);
if (hasRelevantChange) {
// 使 setTimeout
setTimeout(async () => {
const latestValues = await gridApi.formApi.getValues();
gridApi.reload(latestValues);
}, 0);
}
},
}; };
const gridOptions: VxeGridProps<any> = { const gridOptions: VxeGridProps<any> = {
checkboxConfig: { checkboxConfig: {
highlight: true, highlight: true,
@ -28,7 +182,19 @@ const gridOptions: VxeGridProps<any> = {
columns: tableSchema.value, columns: tableSchema.value,
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
pagerConfig: {}, pagerConfig: {
currentPage: 1,
pageSize: 10,
pageSizes: [10, 20, 100],
layouts: [
'PrevPage',
'JumpNumber',
'NextPage',
'FullJump',
'Sizes',
'Total',
],
},
toolbarConfig: { toolbarConfig: {
custom: true, custom: true,
}, },
@ -38,27 +204,60 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ page }, formValues) => { query: async ({ page }, formValues) => {
// // formValuesAPI
const queryParams: any = { const currentFormValues = formValues || (gridApi?.formApi ? await gridApi.formApi.getValues() : {}) || {};
pageIndex: page.currentPage,
pageSize: page.pageSize,
};
// console.log('查询时的 formValues:', formValues);
if (formValues) { console.log('查询时的 currentFormValues:', currentFormValues);
Object.assign(queryParams, formValues);
//
let deviceId = currentFormValues.DeviceId || '';
let systemName = '';
const deviceType = currentFormValues.DeviceType || '';
console.log('查询参数:', { deviceId, deviceType, currentFormValues });
console.log('currentFormValues.DeviceId:', currentFormValues.DeviceId);
console.log('currentFormValues.DeviceType:', currentFormValues.DeviceType);
console.log('currentFormValues.IoTDataType:', currentFormValues.IoTDataType);
// 使
const deviceInfo = selectedDeviceInfo.value || (currentFormValues.DeviceId && deviceOptions.value.length > 0 ? getDeviceInfoById(currentFormValues.DeviceId) : null);
if (deviceInfo) {
console.log('使用设备信息:', deviceInfo);
systemName = deviceInfo.systemName || '';
// id
if (Number(deviceType) === 10) {
// 使 focusId
deviceId = deviceInfo.focusId || deviceId;
} else {
// 使 meterId
deviceId = deviceInfo.meterId || deviceId;
}
} else {
console.log('没有找到设备信息,使用原始 deviceId:', deviceId);
} }
// //
const queryParams = {
pageIndex: page.currentPage,
pageSize: page.pageSize,
SearchKeyword: currentFormValues.SearchKeyword || '',
DeviceType: deviceType,
IoTDataType: currentFormValues.IoTDataType || '',
DeviceId: deviceId,
SystemName: systemName || currentFormValues.SystemName || '',
StartCreationTime: formatDate(currentFormValues.StartCreationTime),
EndCreationTime: formatDate(currentFormValues.EndCreationTime),
};
console.log('最终查询参数:', queryParams);
if (DeviceType) queryParams.DeviceType = DeviceType; if (DeviceType) queryParams.DeviceType = DeviceType;
if (DeviceId) queryParams.DeviceId = DeviceId; if (DeviceId) queryParams.DeviceId = DeviceId;
if (FocusAddress) queryParams.FocusAddress = FocusAddress;
const { data } = await postOneNETLogInfoPage({ const { data } = await postOneNETLogInfoPage({
body: queryParams, body: queryParams,
}); });
// totalCount
const result = { const result = {
items: data.items || [], items: data.items || [],
totalCount: data.totalCount || (data.items ? data.items.length : 0), totalCount: data.totalCount || (data.items ? data.items.length : 0),
@ -69,11 +268,50 @@ const gridOptions: VxeGridProps<any> = {
}, },
}; };
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions }); const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
//
watch(
() => gridApi?.pagerApi?.pageSize,
(newSize, oldSize) => {
if (newSize !== oldSize && oldSize) {
gridApi.pagerApi.currentPage = 1;
gridApi.reload();
}
},
);
//
watch(
() => gridApi?.pagerApi?.currentPage,
(newPage, oldPage) => {
if (newPage !== oldPage && oldPage) {
gridApi.reload();
}
},
);
// DeviceId
watch(
() => gridApi?.getFormModel?.()?.DeviceId,
(newVal, oldVal) => {
if (newVal !== oldVal) {
gridApi.reload();
}
},
);
//
onMounted(async () => {
await fetchDeviceOptions();
});
</script> </script>
<template> <template>
<Page auto-content-height> <Page auto-content-height>
<Grid /> <Grid>
<template #DeviceId="{ model, field }">
<DeviceSelect ref="deviceSelectRef" v-model:value="model[field]"
:placeholder="$t('common.pleaseSelect') + $t('abp.log.deviceInfo')" allow-clear />
</template>
</Grid>
</Page> </Page>
</template> </template>

View File

@ -4,86 +4,193 @@ import { computed } from 'vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { getSelectResultList } from '#/api-client';
import { $t } from '#/locales'; import { $t } from '#/locales';
export const querySchema = computed(() => [ export const querySchema = computed(() => [
{ {
component: 'Input', component: 'ApiSelect',
fieldName: 'FocusAddress', fieldName: 'SystemName',
label: $t('abp.OneNETLog.FocusAddress'), label: $t('abp.IoTDBBase.SystemName'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'BusinessSystemEnum',
},
},
labelField: 'secondValue',
valueField: 'value',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
}, },
{ {
component: 'Input', component: 'ApiSelect',
fieldName: 'DeviceId',
label: $t('abp.IoTDBBase.DeviceId'),
},
{
component: 'Input',
fieldName: 'DeviceType', fieldName: 'DeviceType',
label: $t('abp.IoTDBBase.DeviceType'), label: $t('abp.IoTDBBase.DeviceType'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'MeterTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
}, },
{ {
component: 'Input', component: 'ApiSelect',
fieldName: 'ProductId', fieldName: 'IoTDataType',
label: $t('abp.OneNETLog.ProductId'), label: $t('abp.IoTDBBase.IoTDataType'),
componentProps: {
api: getSelectResultList,
params: {
query: {
TypeName: 'IoTDBDataTypeConst',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
// 如果是包装在 items 中的,提取出来
if (res && Array.isArray(res.items)) {
return res.items;
}
// 如果是包装在 data 中的,提取出来
if (res && Array.isArray(res.data)) {
return res.data;
}
// 如果都不是,返回空数组
return [];
},
},
}, },
{ {
component: 'Input', component: 'DeviceSelect',
fieldName: 'PlatformDeviceId', fieldName: 'DeviceId',
label: $t('abp.OneNETLog.PlatformDeviceId'), label: $t('abp.log.deviceInfo'),
componentProps: {
placeholder: $t('common.pleaseSelect') + $t('abp.log.deviceInfo'),
allowClear: true,
},
},
// 新增开始时间选择器
{
component: 'DatePicker',
fieldName: 'StartCreationTime',
label: '开始时间',
componentProps: {
placeholder: '开始时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
},
// 新增结束时间选择器
{
component: 'DatePicker',
fieldName: 'EndCreationTime',
label: '结束时间',
componentProps: {
placeholder: '结束时间',
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
allowClear: true,
},
}, },
]); ]);
export const tableSchema: any = computed((): VxeGridProps['columns'] => [ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
{ title: $t('common.seq'), type: 'seq', width: 50 }, { title: $t('common.seq'), type: 'seq', width: 50, slots: {} },
{ {
field: 'timestamps', field: 'timestamps',
title: $t('abp.IoTDBBase.Timestamps'), title: $t('abp.IoTDBBase.Timestamps'),
minWidth: '150', minWidth: '150',
slots: {},
}, },
{ {
field: 'systemName', field: 'systemName',
title: $t('abp.IoTDBBase.SystemName'), title: $t('abp.IoTDBBase.SystemName'),
minWidth: '120', minWidth: '120',
slots: {},
}, },
{ field: 'projectId', title: $t('abp.IoTDBBase.ProjectId'), minWidth: '120' },
{ {
field: 'deviceType', field: 'deviceType',
title: $t('abp.IoTDBBase.DeviceType'), title: $t('abp.IoTDBBase.DeviceType'),
minWidth: '120', minWidth: '120',
slots: {},
}, },
{ {
field: 'ioTDataType', field: 'ioTDataType',
title: $t('abp.IoTDBBase.IoTDataType'), title: $t('abp.IoTDBBase.IoTDataType'),
minWidth: '120', minWidth: '120',
slots: {},
}, },
{ field: 'deviceId', title: $t('abp.IoTDBBase.DeviceId'), minWidth: '120' },
{ field: 'productId', title: $t('abp.OneNETLog.ProductId'), minWidth: '120' },
{ {
field: 'platformDeviceId', field: 'deviceId',
title: $t('abp.OneNETLog.PlatformDeviceId'), title: $t('abp.IoTDBBase.DeviceId'),
minWidth: '150', minWidth: '120',
slots: {},
}, },
{ {
field: 'messageType', field: 'messageType',
title: $t('abp.OneNETLog.MessageType'), title: $t('abp.OneNETLog.MessageType'),
minWidth: '120', minWidth: '120',
}, slots: {},
{ field: 'protocol', title: $t('abp.OneNETLog.Protocol'), minWidth: '100' },
{
field: 'focusAddress',
title: $t('abp.OneNETLog.FocusAddress'),
minWidth: '120',
}, },
{ {
field: 'meterAddress', field: 'protocol',
title: $t('abp.OneNETLog.MeterAddress'), title: $t('abp.OneNETLog.Protocol'),
minWidth: '120', minWidth: '100',
slots: {},
}, },
{ {
field: 'receivedTime', field: 'receivedTime',
title: $t('abp.OneNETLog.ReceivedTime'), title: $t('abp.OneNETLog.ReceivedTime'),
minWidth: '150', minWidth: '150',
slots: {},
formatter: ({ cellValue }) => { formatter: ({ cellValue }) => {
return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''; return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : '';
}, },
@ -92,20 +199,24 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
field: 'isEncrypted', field: 'isEncrypted',
title: $t('abp.OneNETLog.IsEncrypted'), title: $t('abp.OneNETLog.IsEncrypted'),
minWidth: '200', minWidth: '200',
slots: {},
}, },
{ {
field: 'plaintextMessage', field: 'plaintextMessage',
title: $t('abp.OneNETLog.PlaintextMessage'), title: $t('abp.OneNETLog.PlaintextMessage'),
minWidth: '200', minWidth: '200',
slots: {},
}, },
{ {
field: 'rawMessage', field: 'rawMessage',
title: $t('abp.OneNETLog.RawMessage'), title: $t('abp.OneNETLog.RawMessage'),
minWidth: '200', minWidth: '200',
slots: {},
}, },
{ {
field: 'receivedPayload', field: 'receivedPayload',
title: $t('abp.OneNETLog.ReceivedPayload'), title: $t('abp.OneNETLog.ReceivedPayload'),
minWidth: '200', minWidth: '200',
slots: {},
}, },
]); ]);