From 180718974d3ee06465ff11d873024f510980efe2 Mon Sep 17 00:00:00 2001 From: ChenYi <296215406@outlook.com> Date: Thu, 17 Jul 2025 15:26:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AE=BE=E5=A4=87=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=B1=95=E7=A4=BA=EF=BC=8C=E7=A7=BB=E9=99=A4=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/dataManger/ctwingLog/schema.ts | 17 ++- .../dataManger/deviceData/dynamicColumns.ts | 39 +++-- .../src/views/dataManger/deviceData/index.vue | 139 ++++++++++++------ .../src/views/dataManger/deviceData/schema.ts | 5 - .../src/views/dataManger/onenetLog/schema.ts | 8 + 5 files changed, 142 insertions(+), 66 deletions(-) diff --git a/apps/web-antd/src/views/dataManger/ctwingLog/schema.ts b/apps/web-antd/src/views/dataManger/ctwingLog/schema.ts index 4a7f79a..6643439 100644 --- a/apps/web-antd/src/views/dataManger/ctwingLog/schema.ts +++ b/apps/web-antd/src/views/dataManger/ctwingLog/schema.ts @@ -4,7 +4,7 @@ import { computed } from 'vue'; import dayjs from 'dayjs'; -import { getSelectResultList, postMetersPage } from '#/api-client'; +import { getSelectResultList } from '#/api-client'; import { $t } from '#/locales'; export const querySchema = computed(() => [ @@ -150,7 +150,20 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [ minWidth: 150, slots: {}, }, - { field: 'systemName', title: $t('abp.IoTDBBase.SystemName'), minWidth: 150, slots: {} }, + { + field: 'formattedTimestamps', + title: $t('abp.IoTDBBase.FormattedTimestamps'), + minWidth: '150', + formatter: ({ cellValue }) => { + return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''; + }, + }, + { + field: 'systemName', + title: $t('abp.IoTDBBase.SystemName'), + minWidth: 150, + slots: {}, + }, { field: 'deviceType', title: $t('abp.IoTDBBase.DeviceType'), diff --git a/apps/web-antd/src/views/dataManger/deviceData/dynamicColumns.ts b/apps/web-antd/src/views/dataManger/deviceData/dynamicColumns.ts index 49b4612..9b382f4 100644 --- a/apps/web-antd/src/views/dataManger/deviceData/dynamicColumns.ts +++ b/apps/web-antd/src/views/dataManger/deviceData/dynamicColumns.ts @@ -1,4 +1,9 @@ -import type { FieldMapping, FieldTypeConfig, ColumnConfig, DynamicDeviceData } from './types'; +import type { + ColumnConfig, + DynamicDeviceData, + FieldMapping, + FieldTypeConfig, +} from './types'; // 字段名映射配置 export const fieldNameMapping: FieldMapping = { @@ -30,32 +35,35 @@ export const fieldTypeConfig: FieldTypeConfig = { // 固定字段列表 - 这些字段已经在固定列中定义,不需要在动态列中重复生成 const FIXED_FIELDS = [ 'SystemName', - 'ProjectId', + 'ProjectId', 'DeviceType', 'IoTDataType', 'DeviceId', - 'Timestamps' + 'Timestamps', + 'FormattedTimestamps', ]; // 动态生成表格列 -export const generateDynamicColumns = (data: DynamicDeviceData[]): ColumnConfig[] => { +export const generateDynamicColumns = ( + data: DynamicDeviceData[], +): ColumnConfig[] => { if (!data || data.length === 0) return []; - + // 获取第一条数据的所有字段 const firstRow = data[0]; if (!firstRow) return []; const fields = Object.keys(firstRow); - + // 过滤掉不需要显示的字段和固定字段 - const excludeFields = ['id', 'key', '__typename', ...FIXED_FIELDS]; - + const excludeFields = new Set(['__typename', 'id', 'key', ...FIXED_FIELDS]); + return fields - .filter(field => !excludeFields.includes(field)) - .map(field => { + .filter((field) => !excludeFields.has(field)) + .map((field) => { // 确保字段名是有效的字符串 const safeField = String(field || '').trim(); if (!safeField) return null; - + const columnConfig: ColumnConfig = { field: safeField, title: fieldNameMapping[safeField] || safeField, @@ -67,7 +75,10 @@ export const generateDynamicColumns = (data: DynamicDeviceData[]): ColumnConfig[ // 应用字段类型配置,确保配置是安全的 if (fieldTypeConfig[safeField]) { const typeConfig = fieldTypeConfig[safeField]; - if (typeConfig.formatter && typeof typeConfig.formatter === 'function') { + if ( + typeConfig.formatter && + typeof typeConfig.formatter === 'function' + ) { columnConfig.formatter = typeConfig.formatter; } if (typeConfig.width !== undefined) { @@ -94,11 +105,11 @@ export const getAllPossibleFields = () => { // 预定义列配置(可选) export const getPredefinedColumns = () => { - return getAllPossibleFields().map(field => ({ + return getAllPossibleFields().map((field) => ({ field, title: fieldNameMapping[field] || field, minWidth: 150, showOverflow: true, ...fieldTypeConfig[field], })); -}; +}; diff --git a/apps/web-antd/src/views/dataManger/deviceData/index.vue b/apps/web-antd/src/views/dataManger/deviceData/index.vue index 2c34576..41e6129 100644 --- a/apps/web-antd/src/views/dataManger/deviceData/index.vue +++ b/apps/web-antd/src/views/dataManger/deviceData/index.vue @@ -2,7 +2,7 @@ import type { VbenFormProps } from '#/adapter/form'; import type { VxeGridProps } from '#/adapter/vxe-table'; -import { computed, nextTick, ref, watch, onMounted } from 'vue'; +import { computed, nextTick, onMounted, ref, watch } from 'vue'; import { useRoute } from 'vue-router'; import { Page } from '@vben/common-ui'; @@ -52,21 +52,20 @@ const getDeviceInfoById = (deviceId: string) => { // 格式化日期为 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 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 { DeviceType, DeviceId, FocusAddress, SystemName } = route.query; @@ -76,11 +75,41 @@ const dynamicColumns = ref([]); // 固定列定义(始终显示)- 基于 IoTDBTreeModelDeviceDataDto 类型 const fixedColumns = [ { 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: 'SystemName', title: $t('abp.IoTDBBase.SystemName'), 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: '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: 'ProjectId', + title: $t('abp.IoTDBBase.ProjectId'), + minWidth: 150, + showOverflow: true, + slots: {}, + }, + { + field: 'DeviceType', + title: $t('abp.IoTDBBase.DeviceType'), + minWidth: 150, + showOverflow: true, + slots: {}, + }, { field: 'IoTDataType', title: $t('abp.IoTDBBase.IoTDataType'), @@ -88,7 +117,13 @@ const fixedColumns = [ showOverflow: true, slots: {}, }, - { field: 'DeviceId', title: $t('abp.IoTDBBase.DeviceId'), minWidth: 150, showOverflow: true, slots: {} }, + { + field: 'DeviceId', + title: $t('abp.IoTDBBase.DeviceId'), + minWidth: 150, + showOverflow: true, + slots: {}, + }, ]; // 合并固定列和动态列 - 使用计算属性确保响应式 @@ -97,20 +132,20 @@ const allColumns = computed(() => { if (!isGridInitialized.value) { return [...fixedColumns]; } - + const columns = [...fixedColumns]; - + // 安全地添加动态列 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属性 - })); + const validDynamicColumns = dynamicColumns.value + .filter((col) => col && typeof col === 'object' && col.field && col.title) + .map((col) => ({ + ...col, + slots: col.slots || {}, // 确保每个列都有slots属性 + })); columns.push(...validDynamicColumns); } - + return columns; }); @@ -144,11 +179,11 @@ const formOptions: VbenFormProps = { const relevantFields = new Set([ 'DeviceId', 'DeviceType', + 'EndCreationTime', 'FocusAddress', 'IoTDataType', - 'SystemName', 'StartCreationTime', - 'EndCreationTime', + 'SystemName', ]); const hasRelevantChange = changedFields.some((field) => relevantFields.has(field), @@ -157,38 +192,43 @@ const formOptions: VbenFormProps = { // 新增:DeviceId变化时同步selectedDeviceInfo if (changedFields.includes('DeviceId')) { const deviceId = values.DeviceId; - + if (deviceId) { // 先尝试从 deviceOptions 中查找(备用方案) - let device = deviceOptions.value.length > 0 ? deviceOptions.value.find(d => d.id === deviceId) : null; - + 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'); + const deviceSelectRef = + gridApi.formApi.getFieldComponentRef('DeviceId'); if (deviceSelectRef && deviceSelectRef.getSelectedDevice) { device = deviceSelectRef.getSelectedDevice(); } - } catch (error) { + } catch { // 静默处理错误 } } - + if (device) { selectedDeviceInfo.value = device; } else { // 如果还是没找到,尝试延迟获取(组件可能还没完全更新) setTimeout(() => { try { - const deviceSelectRef = gridApi.formApi.getFieldComponentRef('DeviceId'); + const deviceSelectRef = + gridApi.formApi.getFieldComponentRef('DeviceId'); if (deviceSelectRef && deviceSelectRef.getSelectedDevice) { const delayedDevice = deviceSelectRef.getSelectedDevice(); if (delayedDevice) { selectedDeviceInfo.value = delayedDevice; } } - } catch (error) { + } catch { // 静默处理错误 } }, 100); @@ -239,7 +279,10 @@ const gridOptions: VxeGridProps = { return { items: [], totalCount: 0 }; } // 获取当前表单值,如果formValues为空则从表单API获取 - const currentFormValues = formValues || (gridApi?.formApi ? await gridApi.formApi.getValues() : {}) || {}; + const currentFormValues = + formValues || + (gridApi?.formApi ? await gridApi.formApi.getValues() : {}) || + {}; // 处理DeviceType和IoTDataType,确保传递数字类型 const deviceTypeValue = currentFormValues.DeviceType || DeviceType; const deviceTypeNumber = deviceTypeValue @@ -249,19 +292,27 @@ const gridOptions: VxeGridProps = { const ioTDataTypeValue = currentFormValues.IoTDataType; // 处理日期范围参数 - const startCreationTime = currentFormValues.StartCreationTime ? formatDate(currentFormValues.StartCreationTime) : undefined; - const endCreationTime = currentFormValues.EndCreationTime ? formatDate(currentFormValues.EndCreationTime) : undefined; + const startCreationTime = currentFormValues.StartCreationTime + ? formatDate(currentFormValues.StartCreationTime) + : undefined; + const endCreationTime = currentFormValues.EndCreationTime + ? formatDate(currentFormValues.EndCreationTime) + : undefined; // 处理DeviceId,当设备类型为集中器(10)时,使用focusId let finalDeviceId = currentFormValues.DeviceId || DeviceId || ''; let finalFocusAddress = currentFormValues.FocusAddress || ''; - + // 优先使用选中的设备信息 - const deviceInfo = selectedDeviceInfo.value || (currentFormValues.DeviceId && deviceOptions.value.length > 0 ? getDeviceInfoById(currentFormValues.DeviceId) : null); - + const deviceInfo = + selectedDeviceInfo.value || + (currentFormValues.DeviceId && deviceOptions.value.length > 0 + ? getDeviceInfoById(currentFormValues.DeviceId) + : null); + if (deviceInfo) { finalFocusAddress = deviceInfo.focusAddress || ''; - + if (deviceTypeNumber === 10) { // 集中器类型使用focusId if (deviceInfo.focusId) { @@ -292,8 +343,6 @@ const gridOptions: VxeGridProps = { }, }); - - // 简化处理逻辑,直接使用接口返回的数据 if (data?.items && data.items.length > 0) { try { @@ -374,10 +423,10 @@ const initializeGrid = async () => { try { // 获取设备信息数据 await fetchDeviceOptions(); - + // 标记表格已初始化 isGridInitialized.value = true; - + // 更新表格列定义 if (gridApi && gridApi.setState) { await nextTick(); @@ -391,7 +440,7 @@ const initializeGrid = async () => { }, }); } - + // 如果有路由参数,自动触发查询 if (DeviceType || DeviceId || FocusAddress || SystemName) { // 延迟一下确保表格已完全初始化 @@ -411,14 +460,14 @@ watch( () => [DeviceType, DeviceId, FocusAddress, SystemName], async (newValues, oldValues) => { // 如果有路由参数,等待设备信息加载完成后自动触发查询 - if (newValues.some(val => val) && gridApi && isGridInitialized.value) { + if (newValues.some(Boolean) && gridApi && isGridInitialized.value) { // 延迟一下确保表单值已经设置 setTimeout(() => { gridApi.reload(); }, 100); } }, - { immediate: false } // 改为false,避免立即触发 + { immediate: false }, // 改为false,避免立即触发 ); // 页面初始化时,延迟初始化表格 diff --git a/apps/web-antd/src/views/dataManger/deviceData/schema.ts b/apps/web-antd/src/views/dataManger/deviceData/schema.ts index 6f3d938..1daf1c7 100644 --- a/apps/web-antd/src/views/dataManger/deviceData/schema.ts +++ b/apps/web-antd/src/views/dataManger/deviceData/schema.ts @@ -146,11 +146,6 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [ title: $t('abp.IoTDBBase.Timestamps'), minWidth: '150', }, - { - field: 'FormattedTimestamps', - title: $t('abp.IoTDBBase.FormattedTimestamps'), - minWidth: '150', - }, { field: 'SystemName', title: $t('abp.IoTDBBase.SystemName'), diff --git a/apps/web-antd/src/views/dataManger/onenetLog/schema.ts b/apps/web-antd/src/views/dataManger/onenetLog/schema.ts index 5928c61..35e39b1 100644 --- a/apps/web-antd/src/views/dataManger/onenetLog/schema.ts +++ b/apps/web-antd/src/views/dataManger/onenetLog/schema.ts @@ -150,6 +150,14 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [ minWidth: '150', slots: {}, }, + { + field: 'formattedTimestamps', + title: $t('abp.IoTDBBase.FormattedTimestamps'), + minWidth: '150', + formatter: ({ cellValue }) => { + return cellValue ? dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss') : ''; + }, + }, { field: 'systemName', title: $t('abp.IoTDBBase.SystemName'),