iot-ui-vue/src/views/device/Instance/Detail/index.vue

317 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<page-container
:tabList="list"
@back="onBack"
:tabActiveKey="instanceStore.tabActiveKey"
@tabChange="onTabChange"
>
<template #title>
<div>
<div style="display: flex; align-items: center">
<j-button @click="onBack" size="small">返回</j-button>
<div style="margin-left: 20px; font-size: 24px">
{{ instanceStore.current.name }}
</div>
<j-divider type="vertical" />
<j-space>
<span
style="font-size: 14px; color: rgba(0, 0, 0, 0.85)"
>
状态
<j-badge
:status="
statusMap.get(
instanceStore.current.state?.value,
)
"
/>
{{ instanceStore.current.state?.text }}
</span>
<PermissionButton
v-if="
instanceStore.current.state?.value ===
'notActive'
"
type="link"
style="margin-top: -5px; padding: 0 20px"
:popConfirm="{
title: '确认启用设备',
onConfirm: handleAction,
}"
hasPermission="device/Instance:action"
>
启用设备
</PermissionButton>
<PermissionButton
v-if="
instanceStore.current.state?.value === 'online'
"
type="link"
style="margin-top: -5px; padding: 0 20px"
:popConfirm="{
title: '确认断开连接?',
onConfirm: handleDisconnect,
}"
hasPermission="device/Instance:action"
>
断开连接
</PermissionButton>
<j-tooltip
v-if="
instanceStore.current?.accessProvider ===
'child-device' &&
instanceStore.current?.state?.value ===
'offline'
"
:title="
instanceStore.current?.features?.find(
(item) => item.id === 'selfManageState',
)
? '该设备的在线状态与父设备(网关设备)保持一致'
: '该设备在线状态由设备自身运行状态决定,不继承父设备(网关设备)的在线状态'
"
>
<AIcon
type="QuestionCircleOutlined"
style="font-size: 14px"
/>
</j-tooltip>
</j-space>
</div>
<div style="padding-top: 24px">
<j-descriptions size="small" :column="4">
<j-descriptions-item label="ID">{{
instanceStore.current.id
}}</j-descriptions-item>
<j-descriptions-item label="所属产品">
<PermissionButton
type="link"
style="margin-top: -5px; padding: 0"
@click="jumpProduct"
hasPermission="device/Product:view"
>
{{ instanceStore.current.productName }}
</PermissionButton>
</j-descriptions-item>
</j-descriptions>
</div>
</div>
</template>
<template #extra>
<img
@click="handleRefresh"
:src="getImage('/device/button.png')"
style="margin-right: 20px; cursor: pointer"
/>
</template>
<component
:is="tabs[instanceStore.tabActiveKey]"
v-bind="{ type: 'device' }"
@onJump="onTabChange"
/>
</page-container>
</template>
<script lang="ts" setup>
import { useInstanceStore } from '@/store/instance';
import Info from './Info/index.vue';
import Running from './Running/index.vue';
import Metadata from '../../components/Metadata/index.vue';
import ChildDevice from './ChildDevice/index.vue';
import Diagnose from './Diagnose/index.vue';
import Function from './Function/index.vue';
import Modbus from './Modbus/index.vue';
import OPCUA from './OPCUA/index.vue';
import EdgeMap from './EdgeMap/index.vue';
import Parsing from './Parsing/index.vue';
import Log from './Log/index.vue';
import { _deploy, _disconnect } from '@/api/device/instance';
import { message } from 'jetlinks-ui-components';
import { getImage } from '@/utils/comm';
import { getWebSocket } from '@/utils/websocket';
import { useMenuStore } from '@/store/menu';
const menuStory = useMenuStore();
const route = useRoute();
const instanceStore = useInstanceStore();
const statusMap = new Map();
statusMap.set('online', 'success');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'warning');
const statusRef = ref();
const list = ref([
{
key: 'Info',
tab: '实例信息',
},
{
key: 'Running',
tab: '运行状态',
},
{
key: 'Metadata',
tab: '物模型',
},
{
key: 'Function',
tab: '设备功能',
},
{
key: 'Log',
tab: '日志管理',
},
]);
const tabs = {
Info,
Metadata,
Running,
ChildDevice,
Diagnose,
Function,
Modbus,
OPCUA,
EdgeMap,
Parsing,
Log,
};
const getStatus = (id: string) => {
statusRef.value = getWebSocket(
`instance-editor-info-status-${id}`,
`/dashboard/device/status/change/realTime`,
{
deviceId: id,
},
).subscribe(() => {
instanceStore.refresh(id);
});
};
watch(
() => route.params.id,
(newId) => {
if (newId) {
instanceStore.refresh(String(newId));
getStatus(String(newId));
}
},
{ immediate: true, deep: true },
);
onMounted(() => {
instanceStore.tabActiveKey = history.state?.params?.tab || 'Info';
});
const onBack = () => {
menuStory.jumpPage('device/Instance');
};
const onTabChange = (e: string) => {
instanceStore.tabActiveKey = e;
};
const handleAction = async () => {
if (instanceStore.current.id) {
const resp = await _deploy(instanceStore.current.id);
if (resp.status === 200) {
message.success('操作成功!');
instanceStore.refresh(instanceStore.current.id);
}
}
};
const handleDisconnect = async () => {
if (instanceStore.current.id) {
const resp = await _disconnect(instanceStore.current.id);
if (resp.status === 200) {
message.success('操作成功!');
instanceStore.refresh(instanceStore.current.id);
}
}
};
const handleRefresh = async () => {
if (instanceStore.current.id) {
await instanceStore.refresh(instanceStore.current.id);
message.success('操作成功');
}
};
const jumpProduct = () => {
menuStory.jumpPage('device/Product/Detail', {
id: instanceStore.current.productId,
});
};
watchEffect(() => {
const keys = list.value.map((i) => i.key);
if (
instanceStore.current.protocol &&
!['modbus-tcp', 'opc-ua'].includes(instanceStore.current.protocol) &&
!keys.includes('Diagnose')
) {
list.value.push({
key: 'Diagnose',
tab: '设备诊断',
});
}
if (
instanceStore.current.features?.find(
(item: any) => item.id === 'transparentCodec',
) &&
!keys.includes('Parsing')
) {
list.value.push({
key: 'Parsing',
tab: '数据解析',
});
}
if (
instanceStore.current.protocol === 'modbus-tcp' &&
!keys.includes('Modbus')
) {
list.value.push({
key: 'Modbus',
tab: 'Modbus TCP',
});
}
if (
instanceStore.current.protocol === 'opc-ua' &&
!keys.includes('OPCUA')
) {
list.value.push({
key: 'OPCUA',
tab: 'OPC UA',
});
}
if (
instanceStore.current.deviceType?.value === 'gateway' &&
!keys.includes('ChildDevice')
) {
// 产品类型为网关的情况下才显示此模块
list.value.push({
key: 'ChildDevice',
tab: '子设备',
});
}
if (
instanceStore.current.accessProvider === 'edge-child-device' &&
instanceStore.current.parentId &&
!keys.includes('EdgeMap')
) {
list.value.push({
key: 'EdgeMap',
tab: '边缘端映射',
});
}
});
onUnmounted(() => {
statusRef.value && statusRef.value.unsubscribe();
});
</script>