先瞅瞅产品提供的丑陋至极的原型效果
再看看经过本人精雕细琢之后的惊艳效果
Show me the code
流程设计弹出层
<template>
<el-dialog width="760px" class="hkt-dlg-darkblue" :title="`流程设计:${formData.name}`" :visible.sync="isShow" destroy-on-close :close-on-click-modal="false">
<div class="dialog-wrap" v-loading="loading">
<div style="min-height:50vh">
<div class="info-block">
<el-row class="hkt-block-title">
<el-col :span="12"><div><span class="title-name">流程配置</span></div></el-col>
<el-col :span="12" class="text-right">
<el-button type="text" @click="formModalChange('New', null)"><i class="el-icon-plus"></i> 添加审核节点</el-button>
</el-col>
</el-row>
<div class="info-content">
<el-steps direction="vertical" :active="nodes.length">
<el-step v-for="(step, stepIndex) in nodes" class="step-item-wrap" :class="'step-item-signmodel-' + step.signModel" :key="step + stepIndex">
<div slot="title">
<div style="line-height:32px;heihgt:38px;">
<el-row>
<el-col :span="12">
<span class="step-name" v-text="step.nodeName"></span>
</el-col>
<el-col :span="12">
<div class="step-item-oprations text-right">
<el-button size="mini" type="text" @click="stepSort(stepIndex, 'up')" v-if="stepIndex > 0"><i class="el-icon-top"></i> 上移</el-button>
<el-button size="mini" type="text"@click="stepSort(stepIndex, 'down')" v-if="stepIndex < nodes.length - 1"><i class="el-icon-bottom"></i> 下移</el-button>
<el-button size="mini" type="text" @click="formModalChange('Edit', step, stepIndex)"><i class="el-icon-edit"></i> 修改</el-button>
<el-button size="mini" type="text" @click="removeStep(step, stepIndex)"><i class="el-icon-close"></i> 删除</el-button>
<el-button size="mini" type="text" @click="addPersons(step, stepIndex)"><i class="el-icon-user"></i> 配置审批人</el-button>
</div>
</el-col>
</el-row>
</div>
</div>
<div slot="description">
<div v-if="step.approveNames.length === 0">
<span class="color-gray">暂未配置审批人员</span>
</div>
<div v-else class="step-item-content-wrap">
<div class="person-item">
<el-tag v-for="(person, personIndex) in step.approveNames" :key="person" disable-transitions @close="removePerson(stepIndex, personIndex)" closable>{{person}}</el-tag>
</div>
</div>
</div>
</el-step>
</el-steps>
<div v-if="nodes.length === 0">
<h3 style="padding-top:40px;font-weight:normal;color:#dedede;font-size: 22px; text-align:center"><p>当前流程暂未配置审核节点信息,</p><p>请单击右上角的“添加审核节点”按钮进行配置</p></h3>
</div>
</div>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer-wrap text-center">
<el-button @click="isShow = false">取 消</el-button>
<el-button type="primary" :loading="submitting" @click="save">{{submitting ? '保存中': '确 定'}}</el-button>
</div>
<step-form-modal :show.sync="formModalVisible" v-if="formModalVisible" :formData="currentRow" :mode="formMode" @callback="formCallback" />
</el-dialog>
</template>
<script>
import stepFormModal from './stepFormModal.vue'
export default {
name: 'flowDesignModal',
desc: '流程设计器',
components: {
stepFormModal
},
props: {
show: {
type: Boolean,
required: true,
default: false
},
formData: {
// 适用于编辑
type: Object,
required: false
},
mode: {
type: String,
required: false
}
},
data () {
return {
loading: true,
form: {
},
nodes: [],
formModalVisible: false,
currentRow: null,
currentStepIndex: null,
formMode:'New', // New || Edit
submitting: false
}
},
computed: {
isShow: {
get () {
return this.show
},
set (val) {
this.$emit('update:show', val)
}
}
},
created() {
this.init()
},
methods: {
init () {
if (this.formData) {
this.getFlowNodes()
// this.form = this.$hktUtils.deepClone(this.formData)
}
},
stepSort (index, type) {
const steps = this.nodes
if (type === 'up') {
;[steps[index], steps[index - 1]] = [steps[index - 1], steps[index]]
} else {
;[steps[index], steps[index + 1]] = [steps[index + 1], steps[index]]
}
// 触发页面更新
this.nodes = steps.concat()
},
async getFlowNodes () {
this.loading = true
const res = await this.$request.get(`/v1/manager/flow/node/listByFlowId?flowId=${this.formData.id}`)
if (res.success) {
this.nodes = res.data
}
this.loading = false
},
// 添加或编辑流程节点
formModalChange (mode, formData, stepIndex) {
this.formMode = mode
this.currentRow = formData
this.currentStepIndex = stepIndex
this.formModalVisible = true
},
formCallback (item) {
// TODO 判断步骤名称是否已存在
if (this.formMode === 'New') {
item.flowId = this.formData.id
item.approveArray = []
item.approveNames = []
this.nodes.push(item)
} else if (this.currentStepIndex >= 0) {
this.nodes[this.currentStepIndex] = item
this.currentStepIndex = null
}
},
addPersons (row, stepIndex) {
const dialogProps = {
multipleFlag: 'Y'
}
if (row.approveArray && row.approveArray.length > 0) {
dialogProps.initRightUsers = row.approveArray.join(',')
}
window.hktCommon.selectUser(`配置 ${row.nodeName} 节点的审批人`, dialogProps, (res) => {
row.approveArray = res.map(item => item.id)
row.approveNames = res.map(item => item.name)
this.nodes.splice(stepIndex, 1, this.$hktUtils.deepClone(row))
})
},
removePerson(stepIndex, personIndex) {
this.nodes[stepIndex].approveArray.splice(personIndex, 1)
this.nodes[stepIndex].approveNames.splice(personIndex, 1)
},
removeStep(stepItem, stepIndex) {
this.$confirm(`本操作不可恢复,确定删除该步骤(${stepItem.nodeName})?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
this.nodes.splice(stepIndex, 1)
}).catch(() => {})
},
// 保存
async save () {
const flowNodes = this.$hktUtils.deepClone(this.nodes)
const existNodeNames = []// 用于校验名称是否重复
for (let i = 0; i < flowNodes.length; i++) {
const flowNode = flowNodes[i]
if (flowNode.approveArray.length === 0) {
this.$message({
message: `审核步骤(${flowNode.nodeName})至少需选择一个的审批人`,
type: 'warning'
})
return
}
if (existNodeNames.includes(flowNode.nodeName)) {
this.$message({
message: `存在相同的审核节点名称:${flowNode.nodeName}`,
type: 'warning'
})
return
}
existNodeNames.push(flowNode.nodeName)
flowNode.orders = i +1
flowNode.approveIds = flowNode.approveArray.join(',')
}
this.submitting = true
// 执行保存入库相关操作
const res = await this.$request.post(`/v1/manager/flow/node/add`, flowNodes).catch(err => {
this.submitting = false
})
this.submitting = false
if (res && res.success) {
this.$emit('callback', flowNodes)
this.isShow = false
}
}
}
}
</script>
<style lang="scss" scoped>
.form-body-item {
background-color:#fff;
padding:10px;
border-radius: 4px;
margin-bottom: 10px;
}
.form-item-zones {
border-bottom: solid 1px #DCDFE6 ;
margin-bottom:20px;
.block-title {
font-weight:bold;
display: inline-block;
line-height: 36px;
font-size:14px;
}
}
.step-item-oprations {
display: none;
}
.step-item-wrap {
/deep/ .el-step__main {
padding: 0 10px 10px;
}
}
.step-item-wrap:hover {
/deep/ .el-step__main {
background-color:#F5F7FA;
border-radius: 5px;
}
.step-item-oprations {
display: block;
}
}
.step-item-content-wrap {
padding: 10px;
}
.btn-choose {
margin-left:10px;
vertical-align: middle;
}
.person-item /deep/ {
display: inline-block;
.el-tag {
vertical-align: middle;
position: relative;
overflow: initial;
margin-bottom:10px;
.el-tag__close {
padding: 2px;
box-sizing: content-box;
position:absolute;
background-color: #D1E9FF;
// display: none;
top:-10px;
right: -10px;
&:hover {
background-color: #1890ff;
}
}
&:hover {
.el-tag__close {
display:block;
}
}
}
.el-tag + .el-tag {
margin-left: 40px;
&:before {
content: '或';
position: absolute;
left: -26px;
color: #666666;
}
}
}
// 会签模式步骤的审批人之间是用和
.info-content /deep/ .step-item-signmodel-1 .person-item {
.el-tag + .el-tag {
&:before {
content: '和'
}
}
}
.step-name {
color:#101010;
font-weight: bold;
}
</style>
步骤编辑弹出层
<template>
<el-dialog width="460px" class="hkt-dlg-darkblue" :title="(form.id ? '编辑' : '新建') + '步骤'" :visible.sync="isShow" append-to-body destroy-on-close :close-on-click-modal="false">
<div class="dialog-wrap">
<el-form ref="form" :model="form">
<el-form-item label="步骤名称" prop="nodeName" :rules="[{required: true, message: '请填写步骤名称', trigger: 'change'}]">
<el-input v-model="form.nodeName" style="width:250px"></el-input>
</el-form-item>
<el-form-item label="是否会签模式">
<el-switch v-model="form.signModel" :active-value="1" :inactive-value="2" active-text="是" inactive-text="否"></el-switch>
</el-form-item>
<el-form-item label="是否可办结">
<el-switch v-model="form.isOver" :active-value="1" :inactive-value="0" active-text="是" inactive-text="否"></el-switch>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer-wrap text-center">
<el-button @click="isShow = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'stepFormModal',
desc: '流程步骤表单',
props: {
show: {
type: Boolean,
required: true,
default: false
},
formData: {
// 适用于编辑
type: Object,
required: false
},
mode: {
type: String,
required: false
}
},
data () {
return {
form: {
nodeName: '',
signModel: 2,
isOver: 0
}
}
},
computed: {
isShow: {
get () {
return this.show
},
set (val) {
this.$emit('update:show', val)
}
}
},
created() {
this.init()
},
methods: {
init () {
if (this.formData) {
this.form = this.$hktUtils.deepClone(this.formData)
}
},
save () {
this.$refs['form'].validate(async (valid) => {
if (valid) {
this.$emit('callback', this.form)
this.isShow = false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.form-body-item {
background-color:#fff;
padding:10px;
border-radius: 4px;
margin-bottom: 10px;
}
.form-item-zones {
border-bottom: solid 1px #DCDFE6 ;
margin-bottom:20px;
.block-title {
font-weight:bold;
display: inline-block;
line-height: 36px;
font-size:14px;
}
}
.step-item-oprations {
display: none;
}
.step-item-wrap:hover {
background-color:#D1E9FF;
.step-item-oprations {
display: block;
}
}
.step-item-content-wrap {
padding: 10px;
}
.btn-choose {
margin-left:10px;
vertical-align: middle;
}
.person-item /deep/ {
display: inline-block;
.el-tag {
vertical-align: middle;
position: relative;
overflow: initial;
.el-tag__close {
padding: 2px;
box-sizing: content-box;
position:absolute;
background-color: #D1E9FF;
// display: none;
top:-10px;
right: -10px;
&:hover {
background-color: #1890ff;
}
}
&:hover {
.el-tag__close {
display:block;
}
}
}
.el-tag + .el-tag {
margin-left: 40px;
&:before {
content: '或';
position: absolute;
left: -26px;
color: #666666;
}
}
}
.step-name {
color:#101010;
font-weight: bold;
}
</style>
该组件涉及人员选择相关公共组件的封装,详细见 分享一个在管理系统中一些公共组件的调用方式
评论 (0)