324 lines
11 KiB
Vue
324 lines
11 KiB
Vue
<template>
|
||
<div class="person-comp-box">
|
||
<a-steps direction="vertical">
|
||
<!-- 没有currentNode说明流程已经结束了,图标和线都显示已经走过的样式 -->
|
||
<a-step v-for="(step, index) in stepsData" :key="step.id" :status="step.nodeName === currentNode ? 'process' : 'wait'"
|
||
:class="{'red-tail': currentNode ? index < currentNodeIndex : true}">
|
||
<template #icon>
|
||
<div class="step-cus-icon"
|
||
:class="{'step-cus-icon-done': currentNode ? index < currentNodeIndex : true, 'step-cus-icon-now': index === currentNodeIndex}">
|
||
<i class="iconfont icon-user" />
|
||
</div>
|
||
</template>
|
||
<!-- 流程节点标题-->
|
||
<!--<template #title>-->
|
||
<!-- <a-tooltip>-->
|
||
<!-- <template #title>{{ step.nodeName }}</template>-->
|
||
<!-- <div class="step-title">{{ step.nodeName }}</div>-->
|
||
<!-- </a-tooltip>-->
|
||
<!--</template>-->
|
||
<!-- 流程节点选人内容-->
|
||
<template #description>
|
||
<div class="personnel-container">
|
||
<div class="personnel-container-title" :class="{'personnel-container-select-title': index === 0}">
|
||
<a-tooltip>
|
||
<template #title>{{ step.nodeName }}</template>
|
||
<div class="personnel-container-title-text">{{ step.nodeName }}</div>
|
||
</a-tooltip>
|
||
</div>
|
||
<div class="personnel-container-content">
|
||
<div class="personnel-container-content-text">
|
||
<template v-if="step.canChoose && index >= currentNodeIndex">
|
||
<user-select-by-work-group v-if="step.chooseSource === 'workGroup'"
|
||
v-model="step.linkUserIds"
|
||
:type="step.chooseType"
|
||
:name-str="step.linkUserIds_dictText"
|
||
:filedName="step.variableName"
|
||
@nameChange="nameChange"
|
||
input-type="textarea" />
|
||
<user-select-by-contact v-else-if="step.chooseSource === 'contactManage'"
|
||
v-model="step.linkUserIds"
|
||
:type="step.chooseType"
|
||
:name-str="step.linkUserIds_dictText"
|
||
:filedName="step.variableName"
|
||
@nameChange="nameChange"
|
||
input-type="textarea" />
|
||
<user-selection v-else-if="step.chooseSource === 'user'"
|
||
:type="step.chooseType"
|
||
v-model="step.linkUserIds"
|
||
:name-str="step.linkUserIds_dictText"
|
||
:filedName="step.variableName"
|
||
@nameChange="nameChange"
|
||
input-type="textarea" />
|
||
</template>
|
||
<div class="personnel-container-content-echo-text" v-else>{{ step.userList }}</div>
|
||
</div>
|
||
<a-icon type="clock-circle" theme="filled" v-if="index === currentNodeIndex" class="personnel-container-content-icon" />
|
||
<a-icon type="check"
|
||
v-if="index < currentNodeIndex"
|
||
class="personnel-container-content-icon personnel-container-content-icon-now" />
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</a-step>
|
||
</a-steps>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import '@assets/less/common.less'
|
||
import UserSelection from './selection/UserSelection.vue'
|
||
import UserSelectByWorkGroup from './selection/UserSelectByWorkGroup'
|
||
import UserSelectByContact from './selection/UserSelectByContact'
|
||
|
||
export default {
|
||
name: 'PersonnelInfo',
|
||
components: { UserSelectByContact, UserSelectByWorkGroup, UserSelection },
|
||
props: {
|
||
// 数据
|
||
data: {
|
||
type: Array,
|
||
required: true,
|
||
default: () => {
|
||
return []
|
||
}
|
||
},
|
||
// 当前节点
|
||
currentNode: {
|
||
type: String,
|
||
required: false,
|
||
default: null
|
||
},
|
||
// 特殊流程需要用indexOf判断的前缀
|
||
specialProcessNodePrefix: {
|
||
type: String,
|
||
required: false,
|
||
default: null
|
||
},
|
||
// 不需要做必填校验的字段,用于应对第一个节点选没选人决定节点跳不跳过的问题
|
||
notPermissField: {
|
||
type: Array,
|
||
required: false,
|
||
default: () => {
|
||
return []
|
||
}
|
||
}
|
||
},
|
||
data () {
|
||
return {
|
||
stepsData: []
|
||
}
|
||
},
|
||
computed: {
|
||
// 当前节点的位置
|
||
currentNodeIndex () {
|
||
if (this.specialProcessNodePrefix) {
|
||
return this.stepsData.findIndex(tt => tt.xmlNodeId.indexOf(this.specialProcessNodePrefix) === 0)
|
||
}
|
||
return this.stepsData.findIndex(tt => tt.xmlNodeId === this.currentNode)
|
||
}
|
||
},
|
||
watch: {
|
||
data: {
|
||
handler () {
|
||
this.stepsData = JSON.parse(JSON.stringify(this.data))
|
||
},
|
||
deep: true,
|
||
immediate: true
|
||
}
|
||
},
|
||
methods: {
|
||
// 获取人员对象,无校验
|
||
getDataObj () {
|
||
const personnelObj = {}
|
||
// for (let i = 0; i < this.stepsData.length; i++) {
|
||
// // 该属性还没有人就给他赋值
|
||
// if ((this.stepsData[i].canChoose || i === 0) && !personnelObj[this.stepsData[i].variableName]) {
|
||
// personnelObj[this.stepsData[i].variableName] = this.stepsData[i].linkUserIds
|
||
// personnelObj[this.stepsData[i].variableName + '_dictText'] = this.stepsData[i].linkUserIds_dictText || this.stepsData[i].userList
|
||
// }
|
||
// }
|
||
for (const item of this.stepsData) {
|
||
console.log(item)
|
||
// 该属性还没有人就给他赋值
|
||
if (!personnelObj[item.variableName]) {
|
||
personnelObj[item.variableName] = item.linkUserIds
|
||
personnelObj[item.variableName + '_dictText'] = item.linkUserIds_dictText || item.userList
|
||
}
|
||
// if ((item.canChoose || item.sort === 1) && !personnelObj[item.variableName]) {
|
||
// personnelObj[item.variableName] = item.linkUserIds
|
||
// personnelObj[item.variableName + '_dictText'] = item.linkUserIds_dictText || item.userList
|
||
// }
|
||
}
|
||
return personnelObj
|
||
},
|
||
// 有校验的获取人员对象
|
||
getDataObjVerify () {
|
||
let personnelObj = {}
|
||
console.log(this.stepsData)
|
||
for (let i = 0; i < this.stepsData.length; i++) {
|
||
// 该属性还没有人就给他赋值,并且如果minLength有值的话,需要判断选的人数过了这个限制
|
||
if ((this.stepsData[i].canChoose || i === 0) && !personnelObj[this.stepsData[i].variableName]) {
|
||
if (this.stepsData[i].minLength) {
|
||
// 有设置至少选几人
|
||
if (this.stepsData[i].linkUserIds && this.stepsData[i].linkUserIds.split(',').length >= this.stepsData[i].minLength) {
|
||
// 说明人数通过了限制
|
||
personnelObj[this.stepsData[i].variableName] = this.stepsData[i].linkUserIds
|
||
personnelObj[this.stepsData[i].variableName + '_dictText'] = this.stepsData[i].linkUserIds_dictText || this.stepsData[i].userList
|
||
} else {
|
||
// 提示XX节点至少选择XX人
|
||
this.$message.warning(this.stepsData[i].nodeName + this.$t('node') + this.$t('atLeastSelect') + this.stepsData[i].minLength + this.$t('personnal'))
|
||
personnelObj[this.stepsData[i].variableName] = ''
|
||
return
|
||
}
|
||
} else {
|
||
personnelObj[this.stepsData[i].variableName] = this.stepsData[i].linkUserIds
|
||
personnelObj[this.stepsData[i].variableName + '_dictText'] = this.stepsData[i].linkUserIds_dictText || this.stepsData[i].userList
|
||
}
|
||
}
|
||
}
|
||
console.log(personnelObj)
|
||
for (const item in personnelObj) {
|
||
if (!this.notPermissField.includes(item) && !personnelObj[item]) {
|
||
// 不在不需要做必填校验的字段里,说明是必填并且没有数据
|
||
this.$message.warning(this.$t('pleaseEnterPersonnelInfo'))
|
||
personnelObj = false
|
||
break
|
||
}
|
||
}
|
||
return personnelObj
|
||
},
|
||
nameChange (value, fieldName) {
|
||
this.stepsData.find(item => item.variableName === fieldName).linkUserIds_dictText = value
|
||
this.stepsData.find(item => item.variableName === fieldName).userList = value
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.person-comp-box {
|
||
height: 100%;
|
||
}
|
||
|
||
/deep/ .ant-steps-vertical .ant-steps-item-icon {
|
||
margin-right: 0;
|
||
}
|
||
|
||
/deep/ .ant-steps-item-title {
|
||
max-width: 100%;
|
||
}
|
||
|
||
/deep/ .ant-steps-item-content {
|
||
padding: 0 12px 30px 12px;
|
||
|
||
}
|
||
|
||
.step-title {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-size: 16px;
|
||
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
|
||
color: #1D2129;
|
||
font-weight: 550;
|
||
}
|
||
|
||
.personnel-container {
|
||
&-title {
|
||
height: 36px;
|
||
background: #6A7484;
|
||
border-radius: 8px 8px 0 0;
|
||
padding: 0 16px;
|
||
|
||
&-text {
|
||
font-size: 16px;
|
||
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
|
||
color: #FFFFFF;
|
||
line-height: 36px;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
|
||
&-select-title {
|
||
background: #9F5258;
|
||
}
|
||
|
||
&-content {
|
||
background: #FFFFFF;
|
||
border-radius: 0 0 8px 8px;
|
||
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1);
|
||
padding: 16px;
|
||
min-height: 52px;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
&-text {
|
||
flex: 1;
|
||
width: 0;
|
||
}
|
||
|
||
&-icon {
|
||
margin-left: 16px;
|
||
color: @primary-color;
|
||
font-size: 20px;
|
||
}
|
||
|
||
&-icon-now {
|
||
font-size: 10px;
|
||
width: 20px;
|
||
height: 20px;
|
||
background: #FAE6E5;
|
||
border-radius: 10px 10px 10px 10px;
|
||
opacity: 1;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
&-echo-text {
|
||
font-size: 14px;
|
||
font-family: PingFang SC-Regular, PingFang SC, sans-serif;
|
||
font-weight: 400;
|
||
color: #4E5969;
|
||
line-height: 22px;
|
||
word-break: break-all;
|
||
}
|
||
}
|
||
}
|
||
|
||
/deep/ .user-organ-wrap .button-box {
|
||
height: 32px;
|
||
}
|
||
|
||
/deep/ .ant-steps-vertical > .ant-steps-item > .ant-steps-item-container > .ant-steps-item-tail {
|
||
left: 14px;
|
||
padding: 31px 0 4px;
|
||
}
|
||
|
||
.step-cus-icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
background: #F2F3F5;
|
||
border-radius: 32px 32px 32px 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
&-done {
|
||
background: rgba(0, 100, 250, 0.08);
|
||
color: @primary-color;
|
||
}
|
||
|
||
&-now {
|
||
color: white;
|
||
background: @primary-color;
|
||
}
|
||
}
|
||
|
||
/deep/ .red-tail > .ant-steps-item-container > .ant-steps-item-tail::after {
|
||
background-color: @primary-color;
|
||
}
|
||
</style>
|