workflow-engine-web/flowable-engine-web/src/views/common/process/nodes/Node.vue

298 lines
8.5 KiB
Vue

<template>
<div :class="{'node': true, 'root': isRoot || !show, 'node-error-state': showError}">
<div v-if="show" @click="$emit('selected')" :class="{'node-body': true, 'error': showError}">
<div>
<div class="node-body-header" :style="{'background-color': headerBgc}">
<i :class="headerIcon" style="margin-right: 5px" v-if="(headerIcon || '') !== ''"></i>
<ellipsis class="name" hover-tip :content="title"/>
<i class="el-icon-close" v-if="!isRoot && $store.state.diagramMode !== 'viewer'" style="float:right;"
@click="$emit('delNode')"></i>
</div>
<div class="node-body-content">
<i :class="leftIcon" v-if="leftIcon"></i>
<template v-if="viewer && selectUser.show">
<el-button type="primary" icon="el-icon-plus" circle @click="$refs.userPicker.showUserPicker()"/>
<avatar-ellipsis :row="3" v-if="userInfo.length > 0" :user-info="userInfo"/>
</template>
<template v-else-if="showAvatar">
<span class="placeholder" v-if="userInfo.length === 0">{{ placeholder }}</span>
<avatar-ellipsis :row="3" :user-info="userInfo" v-else/>
</template>
<template v-else>
<span class="placeholder" v-if="(content || '').trim() === ''">{{ placeholder }}</span>
<ellipsis :row="3" :content="content" v-else/>
</template>
</div>
<div class="node-error" v-if="showError">
<el-tooltip effect="dark" :content="errorInfo" placement="top-start">
<i class="el-icon-warning-outline"></i>
</el-tooltip>
</div>
</div>
</div>
<div class="node-footer">
<div v-if="merge" class="branch-merge">
<img data-v-1e7b1da5=""
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABXlJREFUeF7tmm2IVGUUx3/nLkQUqxmkpAVhSPUllZX8EEGhvVgZQWCU6wcpsqi2mXtnoaBwoqLCufeO9oJYUJQiFZWlZPQCfYiIXkylstTyS1oWWeYWCe6cuLsz7t3r3Ll3du6907oz35bnPM9z/r895zznmWeECf6RCa6fDoBOBExwAp0UmOAB0CmCnRTopECbCZi2nivK1CMD7FpXlH+ydqctKZBz9QyjwkqFG4HzfKK/0gpvl/ulmBWIzAHkVmlRDFY2EihwwLFkRhYQxgzAtHW2CpcBc4CpOsg26eK7yVPYVFwu/9ZzPufq2VLhQBxhAk85lvSF2Y5l/3prjQlAvqR3IjwJTKqz6DeGssQuyLfBsbyjz6PcFgeAZyOwzLFk/QnrjHH/RACYtj6ncHuUCDWYXs7Lz367XEn3inB+1NzauMLGsiW3+u1b2b9lAH22LuiCD2IJED5yTbmiZpt3dAbKT7Hmjhjtdi25oPZnK/uH7dtUCpi2vqVwQ1wRWuHhWkW3StpTEb6IO3fIThhwTemuzWll/0QA5G39FTgrtghhs2vKELA7inra6d38HXvusOEnriWXHo+iFvZvGUDfap3VdYzdzQgIHmd5W7cBc2Ovoax1C3KXZ5/E/i3VgCQciNMD+J1Ug55yXjxo7QfgOdFKCvjyeL/C9MgoEBa5przrt0ti/+C+mRVB/8amrWsU7m2Ql/c5lqwJjre9CDZ1DMFnriXzw0SatvZW4FqBW6o2vwGvCGxyLPmw3rym9g8cwy0XQV8Ix2qEgH0C1ziWNCyceVu1uvZrriVLGqVGsainHO7mRyDynlCvEWupCI7Kxcat6BFg+OwW9ohyfSMIcQF44v/sZovAlRH1I7QVTwyAt1Cjy8hfh9hYvepGQogDoI74HYbSXzHwusTYl7FEAURVcdPWN+NAiAJQTzzCda4p+6N8iDPe1CkQZ8FAtY+E0AhA2uKHszTlT1QkhAHIQnwmAKr1IjQS6gHISnxmABpBCALIUnymAMIgKHxf6wMmH6E3cNTtSLLgZXoKNOgAR6UDyqyq7esKk3znfOriM48AXzc5AmGE1EFgWvXPTMS3DcAJ6TA6XDIT31YAoRCEc5JqcuKc8Kn3AVFO+E4BryvJVHzbI8BzwAdgi2vJ4ihgSY//nyIg8jqctPi2RYBp61wV5qsyR2BFVdhBhBe0wtdisNU15VAagoNrZh4BOVsfFcVCODVUoLBn6E2hIBvShpApgLyt3nvhRXFFCWxwLOmNaz8Wu8wA5G31ntQWNOukwD2OJc80Oy+ufSYAciVdJsJLcZ0K2nV1MbuUk51jnd9oXuoACmW9eHCQj49/T+j3RtiJslPgFxXmoVxe11nhPdeUq8clANPWPoXVQef9D6e1saEHVINHUBYF7Q1lnl2QL5OGkHoE5G19GRhVyBQ+L1tyST0xoa/Iygq3IOvGI4BdwIWjHBeecE15IExM3tYfgJmBOetcU2o9Q2IcsoiAw8Gf0qhyU7kgb4QCcPRTlNGvSspmtzD81J7kJ30AJX0fYeHo2seLjiXLG0TA78CZ/nGFB8uWPJakeG+t9AE4+jjK/XGLWtgTusBix5It4w5ArqRLRTjhl14IW40KD/kre66ki0R4p57IrgozS/2yb9wByDvqhbKX07Xv/oIavMfOP6pFb0pdgcqrbkFuTlp8JingbRIaBfEUHUOYltbtMPUaUNNo2rpeYWk8zSNWqvSmeSvMDIAnybT1boWnY0I4aigL7YJ4bXRqn0wBeCqG7gYVVqFcFapKWXt0gP5nizKQmvLqwpkDqAkaanmhB4MelOkI27XCDjHY7pqyN23htfXbBiArgVH7dABEETrZxzsRcLL/h6P0/Qc1qphfvB2K3wAAAABJRU5ErkJggg=="
alt=""></div>
<div class="btn">
<insert-button v-show="$store.state.diagramMode !== 'viewer'"
@insertNode="type => $emit('insertNode', type)"></insert-button>
</div>
</div>
<user-picker v-if="selectUser.show" title="请选择系统角色" :multiple="selectUser.multiple" ref="userPicker"
:v-model="userInfo"
@ok="selectedUser"/>
</div>
</template>
<script>
import UserPicker from "@/components/common/UserPicker";
import InsertButton from '@/views/common/InsertButton.vue'
export default {
name: "Node",
components: {InsertButton, UserPicker},
props: {
//是否为根节点
isRoot: {
type: Boolean,
default: false
},
//是否显示节点体
show: {
type: Boolean,
default: true
},
//是否显示节点体
merge: {
type: Boolean,
default: false
},
//节点内容区域文字
content: {
type: String,
default: ""
},
//节点内容区域文字
userInfo: {
type: Array,
default(){
return []
}
},
//节点内容区域文字
showAvatar: {
type: Boolean,
default: false
},
selectUser: {
type: Object,
default() {
return {
show: false,
multiple: false,
}
}
},
title: {
type: String,
default: "标题"
},
placeholder: {
type: String,
default: "请设置"
},
//节点体左侧图标
leftIcon: {
type: String,
default: undefined
},
//头部图标
headerIcon: {
type: String,
default: ''
},
//头部背景色
headerBgc: {
type: String,
default: '#576a95'
},
//是否显示错误状态
showError: {
type: Boolean,
default: false
},
errorInfo: {
type: String,
default: '无信息'
},
},
data() {
return{}
},
computed: {
viewer() {
return this.$store.state.diagramMode === 'viewer'
},
},
methods: {
selectedUser(select) {
let userInfoList = []
for (let val of select) {
let userInfo = {
id: val.id,
name: val.name,
avatar: val.avatar,
}
userInfoList.push(userInfo)
}
this.userInfo = userInfoList
this.$store.state.selectUserMap.set(this.$store.state.selectedNode.id,userInfoList)
},
}
}
</script>
<style lang="less" scoped>
.root {
&:before {
display: none !important;
}
}
.node-error-state {
.node-body {
box-shadow: 0px 0px 5px 0px #F56C6C !important;
}
}
.node {
padding: 0 50px;
width: 220px;
position: relative;
&:before {
content: '';
position: absolute;
top: -12px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
width: 0;
border-style: solid;
border-width: 8px 6px 4px;
border-color: #CACACA transparent transparent;
background: #F5F5F7;
}
.node-body {
cursor: pointer;
max-height: 120px;
position: relative;
border-radius: 5px;
background-color: white;
box-shadow: 0px 0px 5px 0px #d8d8d8;
&:hover {
box-shadow: 0px 0px 3px 0px @theme-primary;
.node-body-header {
.el-icon-close {
display: inline;
font-size: medium;
}
}
}
.node-body-header {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
padding: 5px 15px;
color: white;
font-size: xx-small;
.el-icon-close {
display: none;
}
.name {
height: 14px;
width: 150px;
display: inline-block
}
}
.node-body-content {
padding: 18px;
color: #656363;
font-size: 14px;
i {
position: absolute;
top: 55%;
right: 5px;
font-size: medium;
}
.placeholder {
color: #8c8c8c;
}
}
.node-error {
position: absolute;
right: -40px;
top: 20px;
font-size: 25px;
color: #F56C6C;
}
}
.node-footer {
position: relative;
.branch-merge {
font-size: 12px;
display: flex;
width: 38px;
border-radius: 50%;
left: 0;
right: 0;
margin: -20px auto 0;
background: #fff;
justify-content: center;
flex-direction: column;
box-shadow: 0 0 5px 0 #d8d8d8;
}
.btn {
width: 100%;
display: flex;
padding: 20px 0 32px;
justify-content: center;
z-index: 10;
}
/deep/ .el-button {
height: 32px;
}
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
margin: auto;
width: 2px;
height: 100%;
background-color: #CACACA;
}
}
}
</style>