CMVR-IOT-UI/src/views/flow/components/NodeState.vue

177 lines
3.7 KiB
Vue
Raw Normal View History

2026-04-14 17:22:08 +08:00
<template>
2026-04-15 10:59:17 +08:00
<div>
<div class="state__container" :class="`nodeState-${props.state}`">
<div class="context" v-show="showState !== 'NORMAL'">
<div class="state">
<el-icon>
<SuccessFilled v-if="props.state === 'SUCCESS'" />
<CircleCloseFilled v-if="['FAILED', 'STOPPED'].includes(props.state)" />
<VideoPause v-if="props.state === 'PAUSED'" />
<Loading v-if="props.state === 'RUNNING'" />
</el-icon>
<div class="text">{{ getStateText() }}</div>
<el-tag :type="props.state === 'SUCCESS' ? 'success' : 'danger'">
{{ props.runtimes }}ms
</el-tag>
2026-04-14 17:22:08 +08:00
</div>
2026-04-15 10:59:17 +08:00
<div
class="resultText"
v-popover="popoverRef"
@click="popoverVisible = !popoverVisible"
>
{{ popoverVisible ? "隐藏结果" : "展示结果" }}
2026-04-14 17:22:08 +08:00
</div>
2026-04-15 10:59:17 +08:00
</div>
2026-04-14 17:22:08 +08:00
</div>
2026-04-15 10:59:17 +08:00
<el-popover
ref="popoverRef"
virtual-triggering
persistent
placement="right-start"
:visible="popoverVisible"
:teleported="false"
popper-class="popover__container"
>
<template #default>
<div class="params__container input">
<div class="paramsTitle">输入</div>
<div>
<slot name="input"></slot>
</div>
</div>
<div class="params__container output" v-if="slots.output">
<div class="paramsTitle">输出</div>
<div>
<slot name="output"></slot>
</div>
</div>
</template>
</el-popover>
</div>
2026-04-14 17:22:08 +08:00
</template>
<script setup lang="js">
2026-04-15 10:59:17 +08:00
import { ref, useSlots, watch } from 'vue'
2026-04-14 17:22:08 +08:00
import { SuccessFilled, CircleCloseFilled, Loading, VideoPause } from '@element-plus/icons-vue'
const props = defineProps({
state: {
type: String,
default: 'NORMAL'
},
runtimes: {
type: Number,
default: 0
2026-04-15 10:59:17 +08:00
},
2026-04-14 17:22:08 +08:00
})
const slots = useSlots()
const getStateText = () => {
const map = {
SUCCESS: '成功',
RUNNING: '运行中',
FAILED: '失败',
PAUSED: '已暂停',
STOPPED: '已停止',
NORMAL: ''
}
return map[props.state]
}
const popoverRef = ref();
const popoverVisible = ref(false);
2026-04-15 10:59:17 +08:00
const showState = ref('NORMAL')
watch(() => props.state, (newVal) => {
showState.value = newVal;
});
const closePopover = () => {
showState.value = 'NORMAL';
popoverVisible.value = false;
};
defineExpose({ closePopover })
2026-04-14 17:22:08 +08:00
</script>
<style lang="scss" scoped>
.state__container {
2026-04-15 10:59:17 +08:00
display: none;
margin-bottom: 8px;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.context {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px;
font-size: 12px;
.state {
2026-04-14 17:22:08 +08:00
display: flex;
align-items: center;
2026-04-15 10:59:17 +08:00
.text {
margin: 0 8px;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.resultText {
color: #1664ff;
cursor: pointer;
2026-04-14 17:22:08 +08:00
}
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.nodeState-SUCCESS {
display: block;
background-color: #eef9f1;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.el-icon {
font-size: 16px;
color: #309256;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.nodeState-FAILED {
display: block;
background-color: #fdf5f5;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.el-icon {
font-size: 16px;
color: #ee3f38;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.nodeState-STOPPED {
display: block;
background-color: #fdf5f5;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.el-icon {
font-size: 16px;
color: #ee3f38;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.nodeState-PAUSED {
display: block;
background-color: #cbcbcb;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.el-icon {
font-size: 16px;
color: #666;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.nodeState-RUNNING {
display: block;
background-color: #f4f7ff;
2026-04-14 17:22:08 +08:00
2026-04-15 10:59:17 +08:00
.el-icon {
color: #68a2e4;
font-size: 16px;
animation: rotateAnimation 2s linear infinite;
2026-04-14 17:22:08 +08:00
}
2026-04-15 10:59:17 +08:00
}
</style>