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

195 lines
6.1 KiB
Vue

<template>
<j-row :gutter="24">
<j-col :span="16">
<j-row :gutter="24" style="margin-bottom: 20px">
<j-col :span="12" v-for="item in messageArr" :key="item">
<div
:style="messageStyleMap.get(item.status)"
class="message-status"
>
<j-badge
:status="messageStatusMap.get(item.status)"
style="margin-right: 5px"
/>
<span>{{ item.text }}</span>
</div>
</j-col>
</j-row>
<div>
<TitleComponent data="调试" />
<div class="content">
<div class="dialog" id="dialog">
<template v-for="item in dialogList" :key="item.key">
<Dialog :data="item" />
</template>
</div>
</div>
<div><Function /></div>
</div>
</j-col>
<j-col :span="8">
<div class="right-log">
<TitleComponent data="日志" />
<div :style="{ marginTop: '10px' }">
<template v-if="logList.length">
<Log
v-for="item in logList"
:data="item"
:key="item.key"
/>
</template>
<j-empty v-else />
</div>
</div>
</j-col>
</j-row>
</template>
<script lang="ts" setup>
import type { MessageType } from './util';
import { messageStatusMap, messageStyleMap } from './util';
import Dialog from './Dialog/index.vue';
import Function from './Function/index.vue';
import Log from './Log/index.vue';
import { map } from 'rxjs/operators';
import { useInstanceStore } from '@/store/instance';
import { getWebSocket } from '@/utils/websocket';
import { randomString } from '@/utils/utils';
import _ from 'lodash';
const message = reactive<MessageType>({
up: {
text: '上行消息诊断中',
status: 'loading',
},
down: {
text: '下行消息诊断中',
status: 'loading',
},
});
const instanceStore = useInstanceStore();
const allDialogList = ref<Record<string, any>[]>([]);
const dialogList = ref<Record<string, any>[]>([]);
const logList = ref<Record<string, any>[]>([]);
const diagnoseRef = ref();
const messageArr = computed(() => {
const arr = Object.keys(message) || [];
return arr.map((i) => {
return { ...message[i], key: i };
});
});
const subscribeLog = () => {
const id = `device-debug-${instanceStore.current?.id}`;
const topic = `/debug/device/${instanceStore.current?.id}/trace`;
diagnoseRef.value = getWebSocket(id, topic, {})
?.pipe(map((res: any) => res.payload))
.subscribe((payload) => {
if (payload.type === 'log') {
logList.value.push({
key: randomString(),
...payload,
});
} else {
const data = { key: randomString(), ...payload };
allDialogList.value.push(data);
const flag = allDialogList.value
.filter(
(i: any) =>
i.traceId === data.traceId &&
(data.downstream === i.downstream ||
data.upstream === i.upstream),
)
.every((item: any) => {
return !item.error;
});
if (!data.upstream) {
message.down = {
text: !flag ? '下行消息通信异常' : '下行消息通信正常',
status: !flag ? 'error' : 'success',
};
} else {
message.up = {
text: !flag ? '上行消息通信异常' : '上行消息通信正常',
status: !flag ? 'error' : 'success',
};
}
const list: any[] = _.cloneDeep(dialogList.value);
const t = list.find(
(item) =>
item.traceId === data.traceId &&
data.downstream === item.downstream &&
data.upstream === item.upstream,
);
if (t) {
const arr = list.map((item) => {
if (item.traceId === data.traceId) {
item.list.push(data);
}
return item;
});
dialogList.value = _.cloneDeep(arr);
} else {
list.push({
key: randomString(),
traceId: data.traceId,
downstream: data.downstream,
upstream: data.upstream,
list: [data],
});
dialogList.value = _.cloneDeep(list);
}
}
const chatBox = document.getElementById('dialog');
if (chatBox) {
chatBox.scrollTop = chatBox.scrollHeight;
}
});
};
const topState: any = inject('topState') || '';
watchEffect(() => {
if (topState && topState?.value === 'success') {
subscribeLog();
}
});
onUnmounted(() => {
if (diagnoseRef.value) {
diagnoseRef.value.unsubscribe();
}
});
</script>
<style lang="less" scoped>
.message-status {
padding: 8px 24px;
}
.content {
width: 100%;
}
.dialog {
width: 100%;
min-height: 300px;
max-height: 500px;
padding: 24px;
overflow: hidden;
overflow-y: auto;
background-color: #f2f5f7;
}
.right-log {
padding-left: 20px;
border-left: 1px solid rgba(0, 0, 0, 0.09);
overflow: hidden;
max-height: 600px;
overflow-y: auto;
min-height: 400px;
}
</style>