You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
10 KiB
339 lines
10 KiB
<template>
|
|
<div>
|
|
<vxe-modal
|
|
:value="visible"
|
|
show-footer
|
|
:z-index="zIndex"
|
|
title="流转"
|
|
show-zoom
|
|
:fullscreen="$store.getters.device === 'mobile'"
|
|
show-confirm-button
|
|
transfer
|
|
resize
|
|
:width="defaultModalSize.sWidth"
|
|
:height="defaultModalSize.sHeight"
|
|
@input="e => $emit('update:visible',e)"
|
|
>
|
|
<div>
|
|
<div class="steps">
|
|
<el-steps :space="120" finish-status="success" align-center>
|
|
<el-step
|
|
:title="node.name"
|
|
status="finish"
|
|
:icon="isLastNode ? 'el-icon-check' : 'el-icon-edit'"
|
|
></el-step>
|
|
<el-step
|
|
v-if="!isLastNode"
|
|
title="流转到下一节点"
|
|
icon="el-icon-right"
|
|
status="wait"
|
|
></el-step>
|
|
</el-steps>
|
|
</div>
|
|
|
|
<el-divider></el-divider>
|
|
|
|
<template v-if="!isLastNode">
|
|
<div class="next-nodes">
|
|
<div class="next-nodes__label">下一节点</div>
|
|
|
|
<div>
|
|
<el-radio-group v-model="form.next_node_id" @change="nodePick">
|
|
<el-radio v-for="node in node.nextNodes" :label="node.id">{{ node.name }}</el-radio>
|
|
</el-radio-group>
|
|
</div>
|
|
</div>
|
|
|
|
<el-divider></el-divider>
|
|
|
|
<div class="users">
|
|
<div class="users__label">承办人员<br>(是否短信通知)</div>
|
|
|
|
<template v-if="isJointlySign">
|
|
<div>
|
|
<div>
|
|
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
|
|
</div>
|
|
<el-checkbox-group v-model="form.user_id" @change="handleCheckedUsersChange">
|
|
<div v-for="group in pickUsers" :key="group.id">
|
|
<div class="group-name">{{ group.name }}</div>
|
|
<el-checkbox v-for="user in group.users" :label="user.id">
|
|
{{ user.name }}
|
|
<el-switch style="margin-left: 6px;" :value="smsUsers.indexOf(user.id) !== -1" :width="34" active-icon-class="el-icon-message" @input="e => smsUserChange(e, user.id)"></el-switch>
|
|
</el-checkbox>
|
|
</div>
|
|
</el-checkbox-group>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
<div>
|
|
<el-radio-group v-model="form.user_id">
|
|
<div v-for="group in pickUsers" :key="group.id">
|
|
<div class="group-name">{{ group.name }}</div>
|
|
<el-radio v-for="user in group.users" :label="user.id">
|
|
{{ user.name }}
|
|
<el-switch style="margin-left: 6px;" :value="smsUsers.indexOf(user.id) !== -1" :width="34" active-icon-class="el-icon-message" @input="e => smsUserChange(e, user.id)"></el-switch>
|
|
</el-radio>
|
|
</div>
|
|
</el-radio-group>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- 抄送-->
|
|
<template v-if="node.cc_open">
|
|
<el-divider></el-divider>
|
|
<div class="users">
|
|
<div class="users__label">抄送人员</div>
|
|
|
|
<div>
|
|
<div>
|
|
<el-checkbox :indeterminate="ccIsIndeterminate" v-model="ccCheckAll" @change="handleCCCheckAllChange">全选</el-checkbox>
|
|
</div>
|
|
<el-checkbox-group v-model="form.cc_users" @change="handleCCCheckedUsersChange">
|
|
<div v-for="group in shareConfig.cc_users" :key="group.id">
|
|
<div class="group-name">{{ group.name }}</div>
|
|
<el-checkbox v-for="user in group.users"
|
|
:key="user.id"
|
|
:disabled="(shareConfig.flow && shareConfig.flow.ccs) ? (!!shareConfig.flow.ccs.find(j => j.user_id === user.id)) : false"
|
|
:label="user.id">{{ user.name }}{{ user.position ? `(${user.position})` : '' }}</el-checkbox>
|
|
</div>
|
|
</el-checkbox-group>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
<span slot="footer" class="dialog-footer">
|
|
<el-button type="primary" @click="submit"
|
|
>{{ isLastNode ? '结束流程' : '确 定'}}</el-button
|
|
>
|
|
</span>
|
|
</vxe-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getNextNode, getNextNodeUsers, assign, preShare } from "@/api/flow";
|
|
import { PopupManager } from 'element-ui/lib/utils/popup'
|
|
import {defaultModalSize} from "@/settings";
|
|
|
|
export default {
|
|
props: {
|
|
multiple: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
multipleIds: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
visible: {
|
|
type: Boolean,
|
|
default: false,
|
|
required: true
|
|
},
|
|
config: Object,
|
|
result: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
isIndeterminate: false,
|
|
checkAll: false,
|
|
|
|
defaultModalSize,
|
|
zIndex: PopupManager.nextZIndex(),
|
|
form: {
|
|
cc_users: [],
|
|
user_id: [],
|
|
next_node_id: "",
|
|
sms_config: []
|
|
},
|
|
|
|
node: {},
|
|
node2Users: new Map(),
|
|
pickUsers: [],
|
|
smsUsers: [],
|
|
|
|
shareConfig: {},
|
|
ccIsIndeterminate: false,
|
|
ccCheckAll: false,
|
|
};
|
|
},
|
|
methods: {
|
|
smsUserChange(e, id) {
|
|
let index = this.smsUsers.indexOf(id)
|
|
index === -1 ? this.smsUsers.push(id) : this.smsUsers.splice(index, 1)
|
|
},
|
|
|
|
nodePick() {
|
|
this.pickUsers = this.node2Users.get(this.form.next_node_id)
|
|
this.form.user_id = ''
|
|
if (!this.isJointlySign) {
|
|
if (this.pickUsers.length === 1) {
|
|
if (this.pickUsers[0].users?.length === 1) {
|
|
this.form.user_id = this.pickUsers[0].users[0].id
|
|
}
|
|
}
|
|
}
|
|
},
|
|
handleCheckAllChange(val) {
|
|
this.form.user_id = val ? this.pickUsers?.map(i => i.users.map(j => j.id))?.flat() : [];
|
|
this.isIndeterminate = false;
|
|
},
|
|
handleCheckedUsersChange(value) {
|
|
let checkedCount = value.length;
|
|
let dataLength = this.pickUsers?.map(i => i.users.map(j => j.id))?.flat()?.length ?? 0;
|
|
this.checkAll = checkedCount === dataLength
|
|
this.isIndeterminate = checkedCount > 0 && checkedCount < dataLength;
|
|
},
|
|
handleCCCheckAllChange(val) {
|
|
this.form.cc_users = val ? this.shareConfig?.cc_users?.map(i => i.users.map(j => j.id))?.flat() : [];
|
|
this.ccIsIndeterminate = false;
|
|
},
|
|
handleCCCheckedUsersChange(value) {
|
|
let checkedCount = value.length;
|
|
let dataLength = this.shareConfig?.cc_users?.map(i => i.users.map(j => j.id))?.flat()?.length ?? 0;
|
|
this.ccCheckAll = checkedCount === dataLength
|
|
this.ccIsIndeterminate = checkedCount > 0 && checkedCount < dataLength;
|
|
},
|
|
|
|
async getPreShare() {
|
|
try {
|
|
const res = await preShare(this.result.id);
|
|
this.shareConfig = res;
|
|
this.form.cc_users = res.exists_users;
|
|
} catch (err) {
|
|
console.error(err)
|
|
}
|
|
},
|
|
|
|
async getNextNode() {
|
|
try {
|
|
const res = await getNextNode({
|
|
id: this.result.id
|
|
})
|
|
this.node = res.currentNode || {}
|
|
} catch(err) {
|
|
console.error(err)
|
|
}
|
|
},
|
|
|
|
async getNextNodesUsers() {
|
|
try {
|
|
const nodeIds = this.node?.nextNodes?.map(node => node.id);
|
|
this.form.next_node_id = nodeIds[0];
|
|
const res = await Promise.all(nodeIds.map(nodeId => getNextNodeUsers({
|
|
id: this.result.id,
|
|
next_node_id: nodeId,
|
|
},false)));
|
|
|
|
res.forEach((group, index) => {
|
|
this.node2Users.set(nodeIds[index], group.users)
|
|
})
|
|
this.pickUsers = this.node2Users.get(this.form.next_node_id)
|
|
if (!this.isJointlySign) {
|
|
if (this.pickUsers.length === 1) {
|
|
if (this.pickUsers[0].users?.length === 1) {
|
|
this.form.user_id = this.pickUsers[0].users[0].id
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(err)
|
|
}
|
|
},
|
|
|
|
async submit() {
|
|
try {
|
|
if(this.isLastNode) {
|
|
if (this.multiple) {
|
|
await Promise.all(this.multipleIds.map(i => assign(i)))
|
|
} else {
|
|
await assign(this.result.id)
|
|
this.$router.push("/flow/list/handled");
|
|
}
|
|
} else {
|
|
if (typeof this.form.user_id === 'number') {
|
|
this.form.sms_config = [
|
|
{
|
|
[this.form.user_id]: (this.smsUsers.indexOf(this.form.user_id) !== -1) ? 1 : 0
|
|
}
|
|
]
|
|
} else {
|
|
this.form.sms_config = this.form.user_id.map(id => ({
|
|
[id]: (this.smsUsers.indexOf(id) !== -1) ? 1 : 0
|
|
}))
|
|
}
|
|
// this.form.sms_config = this.form.user_id
|
|
if (this.multiple) {
|
|
await Promise.all(this.multipleIds.map(i => assign(i, this.form)))
|
|
} else {
|
|
await assign(this.result.id, this.form)
|
|
this.$router.push("/flow/list/handled");
|
|
}
|
|
}
|
|
this.$emit('update:visible', false)
|
|
this.$emit('refresh')
|
|
} catch(err) {
|
|
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
title() {
|
|
return this.config?.customModel?.name + '流转'
|
|
},
|
|
isLastNode() {
|
|
return this.node?.category === 'end'
|
|
},
|
|
isJointlySign() {
|
|
return this.node?.nextNodes?.find(i => i.id === this.form.next_node_id)?.is_jointly_sign
|
|
}
|
|
},
|
|
watch: {
|
|
async visible(newVal) {
|
|
if(newVal) {
|
|
this.zIndex = PopupManager.nextZIndex()
|
|
|
|
await this.getNextNode()
|
|
if(this.node && this.node.nextNodes && this.node.nextNodes?.length > 0 && !this.isLastNode) {
|
|
await this.getNextNodesUsers()
|
|
this.getPreShare()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
created() {}
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.next-nodes,.users {
|
|
display: flex;
|
|
|
|
&__label {
|
|
flex-basis: 100px;
|
|
font-weight: 600;
|
|
color: #666;
|
|
}
|
|
.group-name {
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
color: #98a6ad;
|
|
line-height: 2;
|
|
}
|
|
}
|
|
.dialog-footer {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
::v-deep .steps {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
</style>
|