fix(web-antdv-next): 使用 Tabs items 和 contentRender 迁移 IoT 详情页签

pull/359/head
XuZhiqiang 2026-06-06 22:22:56 +08:00
parent 4646900de1
commit 1900c051fc
5 changed files with 79 additions and 63 deletions

View File

@ -3,7 +3,7 @@ import type { IotDeviceApi } from '#/api/iot/device/device';
import type { IotProductApi } from '#/api/iot/product/product';
import type { ThingModelApi } from '#/api/iot/thingmodel';
import { onMounted, ref } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page } from '@vben/common-ui';
@ -33,6 +33,22 @@ const product = ref<IotProductApi.Product>({} as IotProductApi.Product);
const device = ref<IotDeviceApi.Device>({} as IotDeviceApi.Device);
const activeTab = ref('info');
const thingModelList = ref<ThingModelApi.ThingModel[]>([]);
const deviceTabItems = computed(() => [
{ key: 'info', label: '设备信息' },
{ key: 'model', label: '物模型数据' },
...(product.value.deviceType === DeviceTypeEnum.GATEWAY
? [{ key: 'subDevice', label: '子设备管理' }]
: []),
{ key: 'log', label: '设备消息' },
{ key: 'simulator', label: '模拟设备' },
{ key: 'config', label: '设备配置' },
...([
ProtocolTypeEnum.MODBUS_TCP_CLIENT,
ProtocolTypeEnum.MODBUS_TCP_SERVER,
].includes(product.value.protocolType as ProtocolTypeEnum)
? [{ key: 'modbus', label: 'Modbus 配置' }]
: []),
]);
/** 获取设备详情 */
async function getDeviceData(deviceId: number) {
@ -94,69 +110,52 @@ onMounted(async () => {
@refresh="() => getDeviceData(id)"
/>
<Tabs v-model:active-key="activeTab" class="mt-4">
<Tabs.TabPane key="info" tab="设备信息">
<Tabs v-model:active-key="activeTab" :items="deviceTabItems" class="mt-4">
<template #contentRender="{ item }">
<DeviceDetailsInfo
v-if="activeTab === 'info' && device.id"
v-if="item.key === 'info' && activeTab === 'info' && device.id"
:device="device"
:product="product"
/>
</Tabs.TabPane>
<Tabs.TabPane key="model" tab="物模型数据">
<DeviceDetailsThingModel
v-if="activeTab === 'model' && device.id"
v-else-if="item.key === 'model' && activeTab === 'model' && device.id"
:device-id="device.id"
:thing-model-list="thingModelList"
/>
</Tabs.TabPane>
<Tabs.TabPane
v-if="product.deviceType === DeviceTypeEnum.GATEWAY"
key="subDevice"
tab="子设备管理"
>
<DeviceDetailsSubDevice
v-if="activeTab === 'subDevice' && device.id"
v-else-if="
item.key === 'subDevice' && activeTab === 'subDevice' && device.id
"
:device-id="device.id"
/>
</Tabs.TabPane>
<Tabs.TabPane key="log" tab="设备消息">
<DeviceDetailsMessage
v-if="activeTab === 'log' && device.id"
v-else-if="item.key === 'log' && activeTab === 'log' && device.id"
:device-id="device.id"
/>
</Tabs.TabPane>
<Tabs.TabPane key="simulator" tab="模拟设备">
<DeviceDetailsSimulator
v-if="activeTab === 'simulator' && device.id"
v-else-if="
item.key === 'simulator' && activeTab === 'simulator' && device.id
"
:device="device"
:product="product"
:thing-model-list="thingModelList"
/>
</Tabs.TabPane>
<Tabs.TabPane key="config" tab="设备配置">
<DeviceDetailConfig
v-if="activeTab === 'config' && device.id"
v-else-if="
item.key === 'config' && activeTab === 'config' && device.id
"
:device="device"
@success="() => getDeviceData(id)"
/>
</Tabs.TabPane>
<Tabs.TabPane
v-if="
[
ProtocolTypeEnum.MODBUS_TCP_CLIENT,
ProtocolTypeEnum.MODBUS_TCP_SERVER,
].includes(product.protocolType as ProtocolTypeEnum)
"
key="modbus"
tab="Modbus 配置"
>
<DeviceModbusConfig
v-if="activeTab === 'modbus' && device.id"
v-else-if="
item.key === 'modbus' && activeTab === 'modbus' && device.id
"
:device="device"
:product="product"
:thing-model-list="thingModelList"
/>
</Tabs.TabPane>
</template>
</Tabs>
</Page>
</template>

View File

@ -18,30 +18,35 @@ const props = defineProps<{
}>();
const activeTab = ref('property'); //
const thingModelTabItems = [
{ key: 'property', label: '设备属性(运行状态)' },
{ key: 'event', label: '设备事件上报' },
{ key: 'service', label: '设备服务调用' },
];
</script>
<template>
<ContentWrap>
<Tabs v-model:active-key="activeTab" class="!h-auto !p-0">
<Tabs.TabPane key="property" tab="设备属性(运行状态)">
<Tabs
v-model:active-key="activeTab"
:items="thingModelTabItems"
class="!h-auto !p-0"
>
<template #contentRender="{ item }">
<DeviceDetailsThingModelProperty
v-if="activeTab === 'property'"
v-if="item.key === 'property' && activeTab === 'property'"
:device-id="deviceId"
/>
</Tabs.TabPane>
<Tabs.TabPane key="event" tab="设备事件上报">
<DeviceDetailsThingModelEvent
v-if="activeTab === 'event'"
v-else-if="item.key === 'event' && activeTab === 'event'"
:device-id="props.deviceId"
:thing-model-list="props.thingModelList"
/>
</Tabs.TabPane>
<Tabs.TabPane key="service" tab="设备服务调用">
<DeviceDetailsThingModelService
v-if="activeTab === 'service'"
v-else-if="item.key === 'service' && activeTab === 'service'"
:device-id="deviceId"
:thing-model-list="props.thingModelList"
/>
</Tabs.TabPane>
</template>
</Tabs>
</ContentWrap>
</template>

View File

@ -98,9 +98,12 @@ watch(
<template>
<Card title="升级设备记录">
<Tabs v-model:active-key="activeTab" @change="handleTabChange" class="mb-4">
<Tabs.TabPane v-for="tab in statusTabs" :key="tab.key" :tab="tab.label" />
</Tabs>
<Tabs
v-model:active-key="activeTab"
:items="statusTabs"
@change="handleTabChange"
class="mb-4"
/>
<Grid>
<template #actions="{ row }">
<TableAction

View File

@ -23,6 +23,10 @@ const id = Number(route.params.id);
const loading = ref(true);
const product = ref<IotProductApi.Product>({} as IotProductApi.Product);
const activeTab = ref('info');
const productTabItems = [
{ key: 'info', label: '产品信息' },
{ key: 'thingModel', label: '物模型(功能定义)' },
];
/** 向子组件提供产品信息 */
provide(IOT_PROVIDE_KEY.PRODUCT, product);
@ -77,13 +81,16 @@ onMounted(async () => {
:product="product"
@refresh="() => getProductData(id)"
/>
<Tabs v-model:active-key="activeTab" class="mt-4">
<Tabs.TabPane key="info" tab="产品信息">
<ProductDetailsInfo v-if="activeTab === 'info'" :product="product" />
</Tabs.TabPane>
<Tabs.TabPane key="thingModel" tab="物模型(功能定义)">
<IoTProductThingModel v-if="activeTab === 'thingModel'" />
</Tabs.TabPane>
<Tabs v-model:active-key="activeTab" :items="productTabItems" class="mt-4">
<template #contentRender="{ item }">
<ProductDetailsInfo
v-if="item.key === 'info' && activeTab === 'info'"
:product="product"
/>
<IoTProductThingModel
v-else-if="item.key === 'thingModel' && activeTab === 'thingModel'"
/>
</template>
</Tabs>
</Page>
</template>

View File

@ -9,17 +9,19 @@ import DataRuleList from './rule/index.vue';
import DataSinkList from './sink/index.vue';
const activeTabName = ref('rule');
const ruleDataTabItems = [
{ key: 'rule', label: '规则' },
{ key: 'sink', label: '目的' },
];
</script>
<template>
<Page auto-content-height>
<Tabs v-model:active-key="activeTabName">
<Tabs.TabPane key="rule" tab="规则">
<DataRuleList />
</Tabs.TabPane>
<Tabs.TabPane key="sink" tab="目的">
<DataSinkList />
</Tabs.TabPane>
<Tabs v-model:active-key="activeTabName" :items="ruleDataTabItems">
<template #contentRender="{ item }">
<DataRuleList v-if="item.key === 'rule'" />
<DataSinkList v-else-if="item.key === 'sink'" />
</template>
</Tabs>
</Page>
</template>