2026-04-14 17:22:08 +08:00
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="state__container" :class="`nodeState-${props.state}`">
|
|
|
|
|
<div class="context">
|
|
|
|
|
<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>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="resultText" v-popover="popoverRef" @click="popoverVisible = !popoverVisible">{{ popoverVisible ? '隐藏结果' : '展示结果' }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<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>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup lang="js">
|
|
|
|
|
import { ref, useSlots } from 'vue'
|
|
|
|
|
import { SuccessFilled, CircleCloseFilled, Loading, VideoPause } from '@element-plus/icons-vue'
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
state: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: 'NORMAL'
|
|
|
|
|
},
|
|
|
|
|
runtimes: {
|
|
|
|
|
type: Number,
|
|
|
|
|
default: 0
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const slots = useSlots()
|
|
|
|
|
|
|
|
|
|
const getStateText = () => {
|
|
|
|
|
const map = {
|
|
|
|
|
SUCCESS: '成功',
|
|
|
|
|
RUNNING: '运行中',
|
|
|
|
|
FAILED: '失败',
|
|
|
|
|
PAUSED: '已暂停',
|
|
|
|
|
STOPPED: '已停止',
|
|
|
|
|
NORMAL: ''
|
|
|
|
|
}
|
|
|
|
|
return map[props.state]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const popoverRef = ref();
|
|
|
|
|
const popoverVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.state__container {
|
|
|
|
|
display: none;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
|
|
.context {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
padding: 4px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
|
|
.state {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
.text {
|
|
|
|
|
margin: 0 8px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.resultText {
|
|
|
|
|
color: #1664ff;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nodeState-SUCCESS {
|
|
|
|
|
display: block;
|
|
|
|
|
background-color: #eef9f1;
|
|
|
|
|
|
|
|
|
|
.el-icon {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #309256;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nodeState-FAILED {
|
|
|
|
|
display: block;
|
|
|
|
|
background-color: #fdf5f5;
|
|
|
|
|
|
|
|
|
|
.el-icon {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #ee3f38;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nodeState-STOPPED {
|
|
|
|
|
display: block;
|
|
|
|
|
background-color: #fdf5f5;
|
|
|
|
|
|
|
|
|
|
.el-icon {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #ee3f38;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nodeState-PAUSED {
|
|
|
|
|
display: block;
|
|
|
|
|
background-color: #cbcbcb;
|
|
|
|
|
|
|
|
|
|
.el-icon {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.nodeState-RUNNING {
|
|
|
|
|
display: block;
|
|
|
|
|
background-color: #f4f7ff;
|
|
|
|
|
|
|
|
|
|
.el-icon {
|
|
|
|
|
color: #68a2e4;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
animation: rotateAnimation 2s linear infinite;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-21 14:11:58 +08:00
|
|
|
</style>
|