diff --git a/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-point-form.vue b/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-point-form.vue index cce6c75f1..6f91a6973 100644 --- a/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-point-form.vue +++ b/apps/web-antd/src/views/iot/device/device/detail/modules/modbus-point-form.vue @@ -246,10 +246,20 @@ const [Form, formApi] = useVbenForm({ if (option && option.registerCount > 0) { await formApi.setFieldValue('registerCount', option.registerCount); } - // 重置字节序为第一个选项 + // 字节序:仅在当前值为空或不属于新 rawDataType 时才重置为第一个选项; + // 编辑回填时 setValues 会触发本回调,无条件重置会覆盖已保存字节序 const byteOrderOptions = getByteOrderOptions(rawDataType); if (byteOrderOptions.length > 0) { - await formApi.setFieldValue('byteOrder', byteOrderOptions[0]!.value); + const currentByteOrder = values.byteOrder; + const isCurrentValid = + !!currentByteOrder && + byteOrderOptions.some((opt) => opt.value === currentByteOrder); + if (!isCurrentValid) { + await formApi.setFieldValue( + 'byteOrder', + byteOrderOptions[0]!.value, + ); + } } } } diff --git a/apps/web-antd/src/views/iot/device/device/index.vue b/apps/web-antd/src/views/iot/device/device/index.vue index 4d21ca3bf..682fcac25 100644 --- a/apps/web-antd/src/views/iot/device/device/index.vue +++ b/apps/web-antd/src/views/iot/device/device/index.vue @@ -9,7 +9,7 @@ import type { IotProductApi } from '#/api/iot/product/product'; import { nextTick, onMounted, ref } from 'vue'; import { useRoute, useRouter } from 'vue-router'; -import { Page, useVbenModal } from '@vben/common-ui'; +import { confirm, Page, useVbenModal } from '@vben/common-ui'; import { DICT_TYPE } from '@vben/constants'; import { getDictOptions } from '@vben/hooks'; import { IconifyIcon } from '@vben/icons'; @@ -169,6 +169,7 @@ async function handleDeleteBatch() { message.warning('请选择要删除的设备'); return; } + await confirm($t('ui.actionMessage.deleteBatchConfirm')); const hideLoading = message.loading({ content: $t('ui.actionMessage.deletingBatch'), duration: 0, diff --git a/apps/web-antd/src/views/iot/home/modules/message-trend-card.vue b/apps/web-antd/src/views/iot/home/modules/message-trend-card.vue index 0a8a30e3c..334f14ff0 100644 --- a/apps/web-antd/src/views/iot/home/modules/message-trend-card.vue +++ b/apps/web-antd/src/views/iot/home/modules/message-trend-card.vue @@ -3,7 +3,7 @@ import type { Dayjs } from 'dayjs'; import type { IotStatisticsApi } from '#/api/iot/statistics'; -import { computed, nextTick, reactive, ref } from 'vue'; +import { computed, nextTick, onMounted, reactive, ref } from 'vue'; import { DICT_TYPE } from '@vben/constants'; import { getDictOptions } from '@vben/hooks'; @@ -26,6 +26,7 @@ const loading = ref(false); // 加载状态 const messageData = ref( [], ); // 消息趋势数据 +const isFirstMount = ref(true); // 首次挂载标记,用于跳过子组件 mount 时的默认 emit /** 时间范围(仅日期,不包含时分秒) */ const dateRange = ref<[string, string]>([ @@ -74,6 +75,11 @@ function handleDateRangeChange(times?: [Dayjs, Dayjs]) { ]; // 将选择的日期转换为带时分秒的格式(开始日期 00:00:00,结束日期 23:59:59) queryParams.times = formatDateRangeWithTime(dateRange.value); + if (isFirstMount.value) { + // 子组件 ShortcutDateRangePicker mount 时会 emit 一次默认日期范围,跳过 fetch; + // 首次请求统一由父组件 onMounted 发起,避免双请求 + return; + } handleQuery(); } @@ -123,6 +129,13 @@ async function renderChartWhenReady() { initChart(); } +// 父组件挂载后统一发起首次请求; +// 原因:子组件 ShortcutDateRangePicker 早期 emit 触发的请求落在 useEcharts isActiveRef = false 阶段,会被 renderEcharts 静默丢弃; +// 通过 handleDateRangeChange 在 isFirstMount=true 时跳过 fetch,由这里统一发起一次,避免双请求 +onMounted(() => { + fetchMessageData(); + isFirstMount.value = false; +});