refactor: 优化设备和产品详情页组件加载

- 引入 defineAsyncComponent 实现异步组件加载
- 在产品详情页添加 Metadata 组件预取
- 优化标签页 active-key绑定方式
This commit is contained in:
fhysy 2025-09-18 09:35:51 +08:00
parent ac343f006a
commit 78c7cff383
2 changed files with 71 additions and 12 deletions

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted } from 'vue';
import { computed, defineAsyncComponent, onMounted, onUnmounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page } from '@vben/common-ui';
@ -12,10 +12,18 @@ import { deviceStateOptions } from '#/constants/dicts';
import { useDeviceStore } from '#/store/device';
import { getWebSocket } from '#/utils/websocket';
import BasicInfo from './components/BasicInfo.vue';
import DeviceSimulation from './components/DeviceSimulation.vue';
import LogManagement from './components/LogManagement.vue';
import RunningStatus from './components/RunningStatus.vue';
const BasicInfo = defineAsyncComponent(
() => import('./components/BasicInfo.vue'),
);
const DeviceSimulation = defineAsyncComponent(
() => import('./components/DeviceSimulation.vue'),
);
const LogManagement = defineAsyncComponent(
() => import('./components/LogManagement.vue'),
);
const RunningStatus = defineAsyncComponent(
() => import('./components/RunningStatus.vue'),
);
const route = useRoute();
const router = useRouter();
@ -207,7 +215,7 @@ onUnmounted(() => {
<!-- 标签页内容 -->
<Tabs
v-model:active-key="activeTab"
:active-key="activeTab"
class="detail-tabs"
@change="handleTabChange"
:destroy-inactive-tab-pane="true"

View File

@ -1,11 +1,26 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted } from 'vue';
import {
computed,
defineAsyncComponent,
defineComponent,
h,
onMounted,
onUnmounted,
} from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page } from '@vben/common-ui';
import { ArrowLeftOutlined } from '@ant-design/icons-vue';
import { Image, message, Modal, Switch, TabPane, Tabs } from 'ant-design-vue';
import {
Image,
message,
Modal,
Spin,
Switch,
TabPane,
Tabs,
} from 'ant-design-vue';
import {
productPushMetadataById,
@ -13,9 +28,35 @@ import {
} from '#/api/device/product';
import { useProductStore } from '#/store/product';
import BasicInfo from './components/BasicInfo.vue';
import DeviceAccess from './components/DeviceAccess.vue';
import Metadata from './components/Metadata.vue';
const BasicInfo = defineAsyncComponent(
() => import('./components/BasicInfo.vue'),
);
const DeviceAccess = defineAsyncComponent(
() => import('./components/DeviceAccess.vue'),
);
// Metadata loading +
const MetadataLoading = defineComponent({
name: 'MetadataLoading',
setup() {
return () =>
h(
'div',
{
style:
'display:flex;align-items:center;justify-content:center;padding:24px;',
},
[h(Spin, { tip: '正在加载物模型...' })],
);
},
});
const loadMetadataAsync = () =>
import(/* webpackPrefetch: true */ './components/Metadata.vue');
const Metadata = defineAsyncComponent({
loader: loadMetadataAsync,
loadingComponent: MetadataLoading,
delay: 200,
});
const route = useRoute();
const router = useRouter();
@ -32,6 +73,16 @@ const loadProductInfo = async () => {
// TODO:
// 0
productStore.setDeviceCount(0);
// Metadata
if (activeTab.value !== 'Metadata') {
const idle = (cb: () => void) =>
(window as any).requestIdleCallback
? (window as any).requestIdleCallback(cb)
: setTimeout(cb, 200);
idle(() => {
loadMetadataAsync().catch(() => undefined);
});
}
} catch {
message.error('加载产品信息失败');
}
@ -154,7 +205,7 @@ onUnmounted(() => {
<!-- 标签页内容 -->
<Tabs
v-model:active-key="activeTab"
:active-key="activeTab"
class="detail-tabs"
@change="handleTabChange"
>