Browse Source

审批节点条件判断

local_v3_liwenxuan
超级管理员 2 years ago
parent
commit
51ffeb06e9
  1. 1
      package.json
  2. 1
      src/App.vue
  3. 16
      src/api/displayboardapi/indexapi.ts
  4. 18
      src/api/workflowapi/index.ts
  5. BIN
      src/assets/images/checkbox.png
  6. BIN
      src/assets/images/checkbox_true.png
  7. 77
      src/components/workflow/addNode.vue
  8. 31
      src/components/workflow/dialog/common.ts
  9. 10
      src/components/workflow/dialog/employeesDialog.vue
  10. 190
      src/components/workflow/dialog/employeesRoleDialog.vue
  11. 103
      src/components/workflow/dialog/roleDialog.vue
  12. 155
      src/components/workflow/drwer/approverDrawer.vue
  13. 2
      src/components/workflow/drwer/conditionDrawer.vue
  14. 104
      src/components/workflow/drwer/copyerDrawer.vue
  15. 12
      src/components/workflow/nodeWrap.vue
  16. 56
      src/components/workflow/selectBox.vue
  17. 121
      src/components/workflow/selectBoxs.vue
  18. 5
      src/components/workflow/selectResult.vue
  19. 5
      src/utils/workflow/const.ts
  20. 10
      src/utils/workflow/index.ts
  21. 14
      src/views/sysworkflow/flow/flowDrawingBoard.vue
  22. 21
      src/views/sysworkflow/flow/index.vue

1
package.json

@ -61,6 +61,7 @@
"screenfull": "^6.0.0",
"tinymce": "^6.7.0",
"ts-md5": "^1.3.1",
"uuid": "^9.0.1",
"vue": "^3.3.1",
"vue-i18n": "9.2.2",
"vue-router": "^4.2.0",

1
src/App.vue

@ -9,3 +9,4 @@ const appStore = useAppStore();
<router-view />
</el-config-provider>
</template>

16
src/api/displayboardapi/indexapi.ts

@ -70,3 +70,19 @@ export const getOrgEveryonePeople = (data?: publicId): AxiosPromise<orgAndPeople
data: data
})
}
//搜索成员(新版)
export const getEmployees = (data?: any) => {
return request({
url: '/kpiapi/powerpc/search_people',
method: 'post',
data: data
})
}
//搜索角色(新版)
export const getRoles = (data?: any) => {
return request({
url: '/kpiapi/powerpc/system_role_list_flow',
method: 'post',
data: data
})
}

18
src/api/workflowapi/index.ts

@ -21,7 +21,7 @@ export function setWorkFlowData(data: any):any {
data: data
});
}
//保存工作流
//保存工作流
export function getConditions(data: any):any {
return request({
url: '/systemapi/task_flow/init_workflow',
@ -29,3 +29,19 @@ export function getConditions(data: any):any {
data: data
});
}
//审批线已经存在得节点
export function getAllParentNode(data: any) {
return request({
url: '/kpiapi/workflowapi/get_all_parent_node',
method: 'post',
data: data
});
}
//判断是否显示(指定审批节点自选)选项及可选节点
export function judgeOptionalNode(data: any) {
return request({
url: '/kpiapi/workflowapi/judge_optional_node',
method: 'post',
data: data
});
}

BIN
src/assets/images/checkbox.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/assets/images/checkbox_true.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

77
src/components/workflow/addNode.vue

@ -4,7 +4,12 @@
@ 备注: 添加节点弹窗
-->
<script lang='ts' setup>
import { v4 as uuidv4 } from "uuid";
let props = defineProps({
nodeConfig: {
type: Object,
default: () => ({}),
},
childNodeP: {
type: Object,
default: ()=> ({})
@ -14,11 +19,39 @@ let emits = defineEmits(['update:childNodeP'])
let visible = ref(false)
//
const addType = (type:any)=> {
// console.log("props.nodeConfig",props.nodeConfig)
// console.log("props.childNodeP",props.childNodeP)
visible.value = false;
let onlyNumber = uuidv4().replaceAll('-','').toString(); //
// console.log('136', onlyNumber,props.nodeConfig,props.childNodeP)
let fromNodeNumber = ""; //
let gotoNodeNumber = ""; //
if(props.nodeConfig != null && props.nodeConfig.nodeNumber != null && props.nodeConfig.nodeNumber != "") {
fromNodeNumber = props.nodeConfig.nodeNumber
// eslint-disable-next-line vue/no-mutating-props
props.nodeConfig.gotoNode = [onlyNumber]
// console.log("p1",props.nodeConfig)
}
if(props.childNodeP != null) {
if(props.childNodeP.nodeNumber != null && props.childNodeP.nodeNumber != ""){
gotoNodeNumber = props.childNodeP.nodeNumber
// console.log("p2",props.nodeConfig)
}
// eslint-disable-next-line vue/no-mutating-props
props.childNodeP.fromNode = onlyNumber
if(props.childNodeP.childNode){
if(props.childNodeP.childNode.nodeNumber != null && props.childNodeP.childNode.nodeNumber != ""){
// eslint-disable-next-line vue/no-mutating-props
props.childNodeP.gotoNode = [props.childNodeP.childNode.nodeNumber]
// console.log("p3",props.childNodeP)
}
}
}
if (type != 4) {
var data;
if (type == 1) {
data = {
"nodeNumber":onlyNumber,
"nodeName": "审核人",
"error": true,
"type": 1,
@ -30,19 +63,28 @@ const addType = (type:any)=> {
"noHanderAction": 1,
"examineEndDirectorLevel": 0,
"childNode": props.childNodeP,
"nodeUserList": []
"nodeUserList": [],
"fromNode": fromNodeNumber,
"gotoNode":[gotoNodeNumber],
"sendBackNode":"beginnode"
}
// console.log("p4",data)
} else if (type == 2) {
data = {
"nodeNumber":onlyNumber,
"nodeName": "抄送人",
"type": 2,
"ccSelfSelectFlag": 1,
"childNode": props.childNodeP,
"nodeUserList": []
"nodeUserList": [],
"fromNode": fromNodeNumber,
"gotoNode":[gotoNodeNumber],
}
// console.log("p5",data)
}else if (type == 3) {
data = {
"nodeName": "审核人",
"nodeNumber":onlyNumber,
"nodeName": "执行人",
"error": true,
"type": 3,
"settype": 1,
@ -53,16 +95,30 @@ const addType = (type:any)=> {
"noHanderAction": 1,
"examineEndDirectorLevel": 0,
"childNode": props.childNodeP,
"nodeUserList": []
"nodeUserList": [],
"fromNode": fromNodeNumber,
"gotoNode":[gotoNodeNumber],
"sendBackNode":"beginnode"
}
// console.log("p6",data)
}
emits("update:childNodeP", data)
} else {
emits("update:childNodeP", {
const snowflake1 = uuidv4().replaceAll('-','').toString();
const snowflake2 = uuidv4().replaceAll('-','').toString();
if(props.childNodeP){
// eslint-disable-next-line vue/no-mutating-props
props.childNodeP.fromNode =snowflake1 //1
}
let data = {
"nodeNumber":onlyNumber,
"nodeName": "路由",
"type": 5,
"childNode": null,
"fromNode": fromNodeNumber,
"gotoNode":[snowflake1,snowflake2],
"conditionNodes": [{
"nodeNumber":snowflake1,
"nodeName": "条件1",
"error": true,
"type": 3,
@ -70,15 +126,22 @@ const addType = (type:any)=> {
"conditionList": [],
"nodeUserList": [],
"childNode": props.childNodeP,
"fromNode": onlyNumber,
"gotoNode":gotoNodeNumber,
}, {
"nodeNumber":snowflake2,
"nodeName": "条件2",
"type": 3,
"priorityLevel": 2,
"conditionList": [],
"nodeUserList": [],
"childNode": null
"childNode": null,
"fromNode": onlyNumber,
"gotoNode":[],
}]
})
}
// console.log("p7",data)
emits("update:childNodeP", data)
}
}
</script>

31
src/components/workflow/dialog/common.ts

@ -1,11 +1,11 @@
import $func from '@/utils/workflow/index'
import { outputOrgAndUser } from '@/api/displayboardapi/types'
import { getBasisOrgChiled } from '@/api/displayboardapi/indexapi'
import { getBasisOrgChiled,getEmployees,getRoles } from '@/api/displayboardapi/indexapi'
export let searchVal = ref<any>('')
export let departments = ref<outputOrgAndUser>()
export let departments = ref<any>()
export let roles = ref({})
//获取行政组织及人员
@ -17,3 +17,30 @@ export let getDepartmentList = async (parentId:any = 0) => {
console.log("data---->",data)
departments.value = data;
}
//搜索成员
export let getDebounceData = (event:any, type = 1) => {
$func.debounce(async () => {
if (event.target.value) {
let data = {
name: event.target.value,
page: 1,
pagesize: 30
}
if (type == 1) {
departments.value.childDepartments = [];
let res = await getEmployees(data)
departments.value.employees = res.data.list
} else {
let res = await getRoles(data)
roles.value = res.data.list
}
} else {
type == 1 ? await getDepartmentList() : await getRoleList();
}
})()
}
//角色列表
export let getRoleList = async () => {
let { data: { list } } = await getRoles()
roles.value = list;
}

10
src/components/workflow/dialog/employeesDialog.vue

@ -4,12 +4,12 @@
@ 备注: 人员选择
-->
<script lang='ts' setup>
import { departments, getDepartmentList,searchVal } from '@/components/workflow/dialog/common'
import { departments, getDepartmentList,searchVal,getDebounceData } from '@/components/workflow/dialog/common'
import $func from '@/utils/workflow/index'
//
import '@/styles/workflowcss/dialog.scss'
//
import selectBox from '@/components/workflow/selectBox.vue'
import selectBox from '@/components/workflow/selectBoxs.vue'
import selectResult from '@/components/workflow/selectResult.vue'
let props = defineProps({
@ -40,7 +40,7 @@ let checkedEmployessList = ref<any>([])
//
let list = computed(()=> {
return [{
isDepartment: props.isDepartment,
isDepartment: props.isdepartment,
type: 'department',
data: departments.value.childDepartments,
isActive: (item)=> $func.toggleClass(checkedDepartmentList.value, item),
@ -59,7 +59,7 @@ let resList = computed(()=>{
data: checkedEmployessList.value,
cancel: (item)=> $func.removeEle(checkedEmployessList.value, item)
}]
if(props.isDepartment){
if(props.isdepartment){
data.unshift({
type: 'department',
data: checkedDepartmentList.value,
@ -88,7 +88,7 @@ watch(()=> props.visible, (val)=>{
if(val){
getDepartmentList();
searchVal.value = "";
console.log("props.data:",props.data)
// console.log("props.data:",props.data)
if(props.data){
checkedEmployessList.value = props.data.filter(item=>item.type===1).map(({name,targetId})=>({
employeeName: name,

190
src/components/workflow/dialog/employeesRoleDialog.vue

@ -0,0 +1,190 @@
<!--
@ 作者: 秦东
@ 时间: 2023-10-17 15:39:19
@ 备注: 选择人员或角色
-->
<script lang='ts' setup>
import { departments, roles, getDebounceData, getRoleList, getDepartmentList, searchVal } from '@/components/workflow/dialog/common'
import $func from '@/utils/workflow/index'
//
import '@/styles/workflowcss/dialog.scss'
//
import selectBox from '@/components/workflow/selectBoxs.vue'
import selectResult from '@/components/workflow/selectResult.vue'
let props = defineProps({
visible: {
type: Boolean,
default: false
},
data:{
type: Array,
default: ()=> []
},
isDepartment: {
type: Boolean,
default: false
},
});
let emits = defineEmits(['update:visible', 'change'])
let visibleDialog = computed({
get(){
return props.visible
},
set(){
closeDialog()
}
})
let checkedRoleList = ref([])
let checkedEmployessList = ref([])
let checkedDepartmentList = ref([])
let activeName = ref('1')
let list = computed(()=> {
// console.log("--->",activeName.value)
if(activeName.value === '2'){
return [{
type: 'role',
not: false,
data: roles.value,
isActive: (item)=> $func.toggleClass(checkedRoleList.value, item, 'roleId'),
change: (item)=> $func.toChecked(checkedRoleList.value, item, 'roleId')
}]
}else{
return [
{
isDepartment: props.isDepartment,
type: 'department',
data: departments.value.childDepartments,
isActive: (item)=> $func.toggleClass(checkedDepartmentList.value, item),
change: (item)=> $func.toChecked(checkedDepartmentList.value, item),
next: (item)=> getDepartmentList(item.id)
},{
type: 'employee',
data: departments.value.employees,
isActive: (item)=> $func.toggleClass(checkedEmployessList.value, item),
change: (item)=> $func.toChecked(checkedEmployessList.value, item),
}
]
}
})
let resList = computed(()=>{
// console.log("list---->data",checkedEmployessList.value)
let data = [{
type: 'role',
data: checkedRoleList.value,
cancel: (item)=> $func.removeEle(checkedRoleList.value, item, 'roleId')
},{
type: 'employee',
data: checkedEmployessList.value,
cancel: (item)=> $func.removeEle(checkedEmployessList.value, item)
}]
if(props.isDepartment){
data.splice(1, 0, {
type: 'department',
data: checkedDepartmentList.value,
cancel: (item)=> $func.removeEle(checkedDepartmentList.value, item)
})
}
return data
})
watch(()=> props.visible, (val)=>{
// console.log("props.data====",props.data)
if(val){
activeName.value = "1";
getDepartmentList();
searchVal.value = "";
checkedEmployessList.value = props.data.filter(item=>item.type===1).map(({name,targetId,icon,iconToBase64})=>({
employeeName: name,
id: targetId,
icon: icon,
iconToBase64: iconToBase64
}));
checkedRoleList.value = props.data.filter(item=>item.type===2).map(({name,targetId})=>({
roleName: name,
roleId: targetId
}));
checkedDepartmentList.value = props.data.filter(item=>item.type===3).map(({name,targetId})=>({
departmentName: name,
id: targetId
}));
}
});
let total = computed(()=> {
return checkedEmployessList.value.length
+ checkedRoleList.value.length
+ checkedDepartmentList.value.length
})
const handleClick = ()=> {
searchVal.value = "";
if (activeName.value === '1') {
getDepartmentList();
} else {
getRoleList();
}
}
const saveDialog = ()=> {
let checkedList = [
...checkedRoleList.value,
...checkedEmployessList.value,
...checkedDepartmentList.value
].map(item=>({
type: item.employeeName?1:(item.roleName?2:3),
targetId: item.id || item.roleId,
name: item.employeeName || item.roleName || item.departmentName,
icon: item.icon,
iconToBase64: item.iconToBase64
}))
// console.log("checkedList-saveDialog-->",checkedList)
emits('change',checkedList)
}
const delList = ()=> {
checkedEmployessList.value = [];
checkedRoleList.value = [];
checkedDepartmentList.value = [];
}
const closeDialog = ()=> {
emits('update:visible', false)
}
onMounted(()=> {
getDepartmentList();
})
</script>
<template>
<el-dialog v-model="visibleDialog" title="选择成员" :width="600" append-to-body class="promoter_person">
<div class="person_body clear">
<el-row>
<el-col :span="12">
<div class="person_tree l">
<input v-model="searchVal" type="text" placeholder="搜索成员" @input="getDebounceData($event,activeName)">
<el-tabs v-model="activeName" @tab-change="handleClick">
<el-tab-pane label="组织架构" name="1"></el-tab-pane>
<el-tab-pane label="角色列表" name="2"></el-tab-pane>
</el-tabs>
<p v-if="activeName ===1 && !searchVal" class="ellipsis tree_nav">
<span class="ellipsis" @click="getDepartmentList(0)">全部</span>
<span v-for="(item,index) in departments.titleDepartments" :key="index+'a'" class="ellipsis" @click="getDepartmentList(item.id)">{{item.departmentName}}</span>
</p>
<selectBox :list="list" style="height: 360px;"/>
</div>
</el-col>
<el-col :span="12">
<selectResult :total="total" :list="resList" @del="delList"/>
</el-col>
</el-row>
</div>
<template #footer>
<el-button @click="$emit('update:visible',false)"> </el-button>
<el-button type="primary" @click="saveDialog"> </el-button>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
</style>

103
src/components/workflow/dialog/roleDialog.vue

@ -0,0 +1,103 @@
<!--
@ 作者: 秦东
@ 时间: 2023-10-17 13:20:34
@ 备注: 选择角色
-->
<script lang='ts' setup>
import { roles, getDebounceData, getRoleList, searchVal } from '@/components/workflow/dialog/common'
import $func from '@/utils/workflow/index'
//
import '@/styles/workflowcss/dialog.scss'
//
import selectBox from '@/components/workflow/selectBoxs.vue'
import selectResult from '@/components/workflow/selectResult.vue'
let props = defineProps({
visible: {
type: Boolean,
default: false
},
data: {
type: Array,
default: () => []
}
});
let checkedRoleList = ref([])
let emits = defineEmits(['update:visible', 'change'])
let list = computed(() => {
return [{
type: 'role',
not: true,
data: roles.value,
isActive: (item) => $func.toggleClass(checkedRoleList.value, item, 'roleId'),
change: (item) => {
checkedRoleList.value = [item]
}
}]
})
let resList = computed(() => {
return [{
type: 'role',
data: checkedRoleList.value,
cancel: (item) => $func.removeEle(checkedRoleList.value, item, 'roleId')
}]
})
let visibleDialog = computed({
get() {
return props.visible
},
set(val) {
closeDialog()
}
})
watch(() => props.visible, (val) => {
if (val) {
getRoleList();
searchVal.value = "";
checkedRoleList.value = props.data.map(({ name, targetId }) => ({
roleName: name,
roleId: targetId
}));
}
})
let total = computed(() => checkedRoleList.value.length)
const saveDialog = () => {
let checkedList = checkedRoleList.value.map(item => ({
type: 2,
targetId: item.roleId,
name: item.roleName
}))
emits('change', checkedList)
}
const delList = () => {
checkedRoleList.value = [];
}
const closeDialog = () => {
emits('update:visible', false)
}
</script>
<template>
<el-dialog v-model="visibleDialog" title="选择角色" :width="600" append-to-body class="promoter_person">
<div class="person_body clear">
<el-row>
<el-col :span="12">
<div class="person_tree l">
<input v-model="searchVal" type="text" placeholder="搜索角色" @input="getDebounceData($event,2)">
<selectBox :list="list"/>
</div>
</el-col>
<el-col :span="12">
<selectResult :list="resList" :total="total" @del="delList"/>
</el-col>
</el-row>
</div>
<template #footer>
<el-button @click="closeDialog"> </el-button>
<el-button type="primary" @click="saveDialog"> </el-button>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
</style>

155
src/components/workflow/drwer/approverDrawer.vue

@ -7,13 +7,21 @@
import $func from '@/utils/workflow/index'
import { setTypes, selectModes, selectRanges } from '@/utils/workflow/const'
import { useStore } from '@/store/workflow/index'
import { getAllParentNode,judgeOptionalNode } from '@/api/workflowapi/index'
let props = defineProps({
nodeConfig:{
type: Object,
default: () => ({}),
},
directormaxlevel: {
type: Number,
default: 0
default: 4
}
});
const nodeTitle = ref<string>("审批人设置")
const nodeOptional = ref<any[]>() //线
const nodeAllVerify = ref<any[]>()
let approverConfig = ref<any>({})
let approverVisible = ref(false)
let approverRoleVisible = ref(false)
@ -31,8 +39,33 @@ let visible = computed({
closeDrawer()
}
})
watch(approverConfig1, (val:any)=>{
// console.log("directormaxlevel",props.directormaxlevel)
approverConfig.value = val.value
if(val.type == 3){
nodeTitle.value = "执行人设置"
}else{
nodeTitle.value = "审批人设置"
}
judgeOptionalNode(props.nodeConfig)
.then((data)=>{
if(data.code == 0){
let sendData = {
id:val.value.fromNode,
allcont:data.data.allcont
}
getAllParentNode(sendData)
.then((data)=>{
if(data.code == 0){
nodeOptional.value = data.data.allcont
}
})
}
})
})
let changeRange = ()=> {
approverConfig.value.nodeUserList = [];
@ -80,34 +113,35 @@ const closeDrawer = ()=> {
}
</script>
<template>
<el-drawer v-model="visible" :append-to-body="true" title="审批人设置" class="set_promoter" :show-close="false" :size="550" :before-close="saveApprover">
<el-drawer v-model="visible" :append-to-body="true" :title="nodeTitle" class="set_promoter" :show-close="false" :size="550" :before-close="saveApprover">
<div class="demo-drawer__content">
<!--审批人设置主体-->
<div class="drawer_content">
<div class="approver_content">
<el-radio-group v-model="approverConfig.settype" class="clear" @change="changeType">
<el-radio v-for="({value, label}) in setTypes" :key="value" :label="value">{{label}}</el-radio>
<el-radio v-for="({value, label}) in setTypes" :key="value" :label="value" style="width:auto">{{label}}=>{{value}}</el-radio>
</el-radio-group>
<el-button v-if="approverConfig.settype==1" type="primary" @click="addApprover">添加/修改成员</el-button>
<p v-if="approverConfig.settype==1" class="selected_list">
<span v-for="(item,index) in approverConfig.nodeUserList" :key="index">{{item.name}}
<img src="@/assets/images/add-close1.png" @click="$func.removeEle(approverConfig.nodeUserList,item,'targetId')">
</span>
<a v-if="approverConfig.nodeUserList.length!=0" @click="approverConfig.nodeUserList=[]">清除</a>
</p>
</div>
<!--指定成员-->
<div v-if="approverConfig.settype==1" class="approver_manager">
<el-button type="primary" @click="addApprover">添加/修改成员</el-button>
<p class="selected_list">
<el-tag v-for="(item,index) in approverConfig.nodeUserList" :key="index" closable type="info" effect="plain" class="tag_us" @close="$func.removeEle(approverConfig.nodeUserList,item,'targetId')">{{item.name}}</el-tag>
<el-tag v-if="approverConfig.nodeUserList.length!=0" type="danger" effect="dark" @click="approverConfig.nodeUserList=[]">清除</el-tag>
</p>
</div>
<!--主管-->
<div v-if="approverConfig.settype==2" class="approver_manager">
<p>
<span>发起人的</span>
<select v-model="approverConfig.directorLevel">
<option v-for="item in directorMaxLevel" :key="item" :value="item">{{item==1?'直接':''+item+''}}主管</option>
<option v-for="item in props.directormaxlevel" :key="item" :value="item">{{item==1?'直接':''+item+''}}主管</option>
</select>
</p>
<p class="tip">找不到主管时由上级主管代审批</p>
</div>
<div v-if="approverConfig.settype==5" class="approver_self">
<p>该审批节点设置发起人自己审批人默认为发起人</p>
</div>
<!--发起人自选-->
<div v-show="approverConfig.settype==4" class="approver_self_select">
<el-radio-group v-model="approverConfig.selectMode" style="width: 100%;">
<el-radio v-for="({value, label}) in selectModes" :key="value" :label="value">{{label}}</el-radio>
@ -120,32 +154,45 @@ const closeDrawer = ()=> {
<el-button v-if="approverConfig.selectRange==2" type="primary" @click="addApprover">添加/修改成员</el-button>
<el-button v-else type="primary" @click="addRoleApprover">添加/修改角色</el-button>
<p class="selected_list">
<span v-for="(item,index) in approverConfig.nodeUserList" :key="index">{{item.name}}
<img src="@/assets/images/add-close1.png" @click="$func.removeEle(approverConfig.nodeUserList,item,'targetId')">
</span>
<a v-if="approverConfig.nodeUserList.length!=0&&approverConfig.selectRange!=1" @click="approverConfig.nodeUserList=[]">清除</a>
<el-tag v-for="(item,index) in approverConfig.nodeUserList" :key="index" closable type="info" effect="plain" class="tag_us" @close="$func.removeEle(approverConfig.nodeUserList,item,'targetId')">{{item.name}}</el-tag>
<el-tag v-if="approverConfig.nodeUserList.length!=0&&approverConfig.selectRange!=1" type="danger" effect="dark" @click="approverConfig.nodeUserList=[]">清除</el-tag>
</p>
</template>
</div>
<div v-if="approverConfig.settype==7" class="approver_manager">
<!--发起人自己-->
<div v-if="approverConfig.settype==5" class="approver_self">
<p>该审批节点设置发起人自己审批人默认为发起人</p>
</div>
<!--连续多级主管-->
<div v-if="approverConfig.settype==6" class="approver_manager">
<p>审批终点</p>
<p style="padding-bottom:20px">
<span>发起人的</span>
<select v-model="approverConfig.examineEndDirectorLevel">
<option v-for="item in directorMaxLevel" :key="item" :value="item">{{item==1?'最高':''+item}}层级主管</option>
<option v-for="item in props.directormaxlevel" :key="item" :value="item">{{item==1?'直接':''+item}}层级主管</option>
</select>
</p>
</div>
<!--指定审批节点为本节点设置审批人-->
<div v-if="approverConfig.settype==7" class="approver_manager">
<p>可选节点列表</p>
<el-radio-group v-model="approverConfig.customNode" class="clear">
<el-radio label="beginnode" >发起人</el-radio>
<el-radio v-for="item in nodeOptional" :key="item.nodeNumber" :label="item.nodeNumber" class="nodeGroupRadio">{{ item.nodeName }}编号{{ item.nodeNumber }}</el-radio>
</el-radio-group>
</div>
<!--补充审批信息-->
<div v-if="(approverConfig.settype==1&&approverConfig.nodeUserList.length>1)||approverConfig.settype==2||(approverConfig.settype==4&&approverConfig.selectMode==2)" class="approver_some">
<p>多人审批时采用的审批方式</p>
<el-radio-group v-model="approverConfig.examineMode" class="clear">
<el-radio :label="1">依次审批</el-radio>
<br/>
<el-radio v-if="approverConfig.settype!=2" :label="2">会签(须所有审批人同意)</el-radio>
<el-radio v-if="approverConfig.settype!=2" :label="3">非会签(有一位审批人同意即可)</el-radio>
</el-radio-group>
</div>
<div v-if="approverConfig.settype==2||approverConfig.settype==7" class="approver_some">
<div v-if="approverConfig.settype==2||approverConfig.settype==6" class="approver_some">
<p>审批人为空时</p>
<el-radio-group v-model="approverConfig.noHanderAction" class="clear">
<el-radio :label="1">自动审批通过/不允许发起</el-radio>
@ -153,20 +200,64 @@ const closeDrawer = ()=> {
<el-radio :label="2">转交给审核管理员</el-radio>
</el-radio-group>
</div>
<div class="approver_some">
<p>退回设置</p>
<el-radio-group v-model="approverConfig.sendBackNode" class="clear">
<el-radio label="beginnode" >发起人</el-radio>
<el-radio v-for="item in nodeOptional" :key="item.nodeNumber" :label="item.nodeNumber" >{{ item.nodeName }}编号{{ item.nodeNumber }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="demo-drawer__footer clear">
<el-button type="primary" @click="saveApprover"> </el-button>
<el-button @click="closeDrawer"> </el-button>
</div>
<!--选择成员-->
<employees-dialog
v-model:visible="approverVisible"
:data="checkedList"
@change="sureApprover"
/>
<!--选择角色-->
<role-dialog
v-model:visible="approverRoleVisible"
:data="checkedRoleList"
@change="sureRoleApprover"
/>
</div>
</el-drawer>
</template>
<style lang='scss' scoped>
.approver_some .el-radio-group {
display: block;
}
.approver_manager .el-radio-group{
display: block;
}
.approver_some .el-radio {
display: block;
}
.set_promoter{
.approver_content {
padding-bottom: 10px;
border-bottom: 1px solid #f2f2f2;
border-bottom: 0px solid #f2f2f2;
.el-radio{
width:auto;
}
}
.approver_manager,.approver_self_select,.approver_some,.approver_self{
border-top: 1px solid #f2f2f2;
}
.approver_self_select,
.approver_content{
.el-button{
@ -208,7 +299,7 @@ const closeDrawer = ()=> {
.approver_manager,
.approver_content,
.approver_some {
padding: 20px 20px 0;
padding: 20px 20px 20px 20px;
}
.approver_manager p:first-of-type,
.approver_some p {
@ -223,4 +314,18 @@ const closeDrawer = ()=> {
line-height: 19px;
}
}
.selected_list{
margin: 0;
line-height: 0;
.tag_us{
margin-right: 10px;
}
span{
margin-top: 10px;
}
a{
margin-top: 15px;
}
}
</style>

2
src/components/workflow/drwer/conditionDrawer.vue

@ -33,7 +33,7 @@ let visible = computed({
}
})
watch(conditionsConfig1, (val:any) => {
console.log("val.priorityLevel",val.priorityLevel)
// console.log("val.priorityLevel",val.priorityLevel)
conditionsConfig.value = val.value;
PriorityLevel.value = val.priorityLevel
conditionConfig.value = val.priorityLevel

104
src/components/workflow/drwer/copyerDrawer.vue

@ -4,6 +4,7 @@
@ 备注: 抄送配置
-->
<script lang='ts' setup>
import employeesDialog from '@/components/workflow/dialog/employeesDialog.vue'
import $func from '@/utils/workflow/index'
import { useStore } from '@/store/workflow/index'
let copyerConfig = ref({})
@ -32,6 +33,7 @@ const addCopyer = () => {
checkedList.value = copyerConfig.value.nodeUserList
}
const sureCopyer = (data) => {
// console.log("",data)
copyerConfig.value.nodeUserList = data;
copyerVisible.value = false;
}
@ -54,12 +56,18 @@ const closeDrawer = () => {
<div class="demo-drawer__content">
<div class="copyer_content drawer_content">
<el-button type="primary" @click="addCopyer">添加成员</el-button>
<p class="selected_list">
<!-- <p class="selected_list">
<span v-for="(item,index) in copyerConfig.nodeUserList" :key="index">{{item.name}}
<img src="@/assets/images/add-close1.png" @click="$func.removeEle(copyerConfig.nodeUserList,item,'targetId')">
</span>
<a v-if="copyerConfig.nodeUserList&&copyerConfig.nodeUserList.length!=0" @click="copyerConfig.nodeUserList=[]">清除</a>
</p> -->
<p class="selected_list">
<el-tag v-for="(item,index) in copyerConfig.nodeUserList" :key="index" closable type="info" effect="plain" class="tag_us" @close="$func.removeEle(copyerConfig.nodeUserList,item,'targetId')">{{item.name}}</el-tag>
<el-tag v-if="copyerConfig.nodeUserList&&copyerConfig.nodeUserList.length!=0" type="danger" effect="dark" @click="copyerConfig.nodeUserList=[]">清除</el-tag>
</p>
<el-checkbox-group v-model="ccSelfSelectFlag" class="clear">
<el-checkbox :label="1">允许发起人自选抄送人</el-checkbox>
</el-checkbox-group>
@ -68,6 +76,11 @@ const closeDrawer = () => {
<el-button type="primary" @click="saveCopyer"> </el-button>
<el-button @click="closeDrawer"> </el-button>
</div>
<employees-role-dialog
v-model:visible="copyerVisible"
:data="checkedList"
@change="sureCopyer"
/>
</div>
</el-drawer>
</template>
@ -85,4 +98,93 @@ const closeDrawer = () => {
}
}
}
.approver_some .el-radio-group {
display: block;
}
.approver_some .el-radio {
display: block;
}
.set_promoter{
.approver_content {
padding-bottom: 10px;
border-bottom: 0px solid #f2f2f2;
.el-radio{
width:auto;
}
}
.approver_manager,.approver_self_select,.approver_some,.approver_self{
border-top: 1px solid #f2f2f2;
}
.approver_self_select,
.approver_content{
.el-button{
margin-bottom: 20px;
}
}
.approver_content,
.approver_some,
.approver_self_select{
.el-radio-group{
display: unset;
}
.el-radio{
width: 27%;
margin-bottom: 20px;
height: 16px;
}
}
.approver_manager p {
line-height: 32px;
}
.approver_manager select {
width: 420px;
height: 32px;
background: rgba(255, 255, 255, 1);
border-radius: 4px;
border: 1px solid rgba(217, 217, 217, 1);
}
.approver_manager p.tip {
margin: 10px 0 22px 0;
font-size: 12px;
line-height: 16px;
color: #f8642d;
}
.approver_self {
padding: 28px 20px;
}
.approver_self_select,
.approver_manager,
.approver_content,
.approver_some {
padding: 20px 20px 20px 20px;
}
.approver_manager p:first-of-type,
.approver_some p {
line-height: 19px;
font-size: 14px;
margin-bottom: 14px;
}
.approver_self_select h3 {
margin: 5px 0 20px;
font-size: 14px;
font-weight: bold;
line-height: 19px;
}
}
.selected_list{
margin: 0;
line-height: 0;
.tag_us{
margin-right: 10px;
}
span{
margin-top: 10px;
}
a{
margin-top: 15px;
}
}
</style>

12
src/components/workflow/nodeWrap.vue

@ -45,8 +45,10 @@ let defaultText = computed(() => {
return placeholderList[props.nodeConfig.type]
});
let showText = computed(() => {
// console.log("props.nodeConfig.type===>",props.nodeConfig);
if (props.nodeConfig.type == 0) return $func.arrToStr(props.flowPermission) || '所有人'
if (props.nodeConfig.type == 1) return $func.setApproverStr(props.nodeConfig)
// console.log("props.nodeConfig.type",props.nodeConfig.type);
return $func.copyerStr(props.nodeConfig)
});
let isInputList = ref([]);
@ -230,7 +232,7 @@ onMounted(() => {
<div class="content" @click="setPerson">
<div class="text">
<span v-if="!showText" class="placeholder">请选择{{defaultText}}</span>
{{showText}}
{{showText}}{{ nodeConfig.nodeNumber }}
</div>
<i class="anticon anticon-right arrow"></i>
</div>
@ -240,7 +242,7 @@ onMounted(() => {
</div>
</div>
<!--eslint-disable-next-line vue/no-mutating-props-->
<addNode v-model:childNodeP="nodeConfig.childNode" />
<addNode v-model:childNodeP="nodeConfig.childNode" :node-config="props.nodeConfig" />
</div>
<!--路由模块-->
<div v-if="nodeConfig.type == 5" class="node-wrap" >
@ -268,12 +270,12 @@ onMounted(() => {
<i class="anticon anticon-close close" @click="delTerm(index)"></i>
</div>
<div v-if="index != nodeConfig.conditionNodes.length - 1" class="sort-right" @click="arrTransfer(index)">&gt;</div>
<div class="content" @click="setPerson(item.priorityLevel)">{{ $func.conditionStr(nodeConfig, index) }}</div>
<div class="content" @click="setPerson(item.priorityLevel)">{{ $func.conditionStr(nodeConfig, index) }}{{ item.nodeNumber }}</div>
<div v-if="isTried && item.error" class="error_tip" >
<i class="anticon anticon-exclamation-circle"></i>
</div>
</div>
<addNode v-model:childNodeP="item.childNode" />
<addNode v-model:childNodeP="item.childNode" :node-config="item" />
</div>
</div>
<nodeWrap v-if="item.childNode" v-model:nodeConfig="item.childNode" />
@ -288,7 +290,7 @@ onMounted(() => {
</div>
</div>
<!--eslint-disable-next-line vue/no-mutating-props-->
<addNode v-model:childNodeP="nodeConfig.childNode" />
<addNode v-model:childNodeP="nodeConfig.childNode" :node-config="props.nodeConfig" />
</div>
</div>
<!--循环组件-->

56
src/components/workflow/selectBox.vue

@ -25,37 +25,37 @@ defineProps({
</li>
</template>
<template v-if="elem.type === 'department'">
<li v-for="item in elem.data" :key="item.id" class="check_box" :class="{not: !elem.isDepartment}">
<a v-if="elem.isDepartment"
:class="elem.isActive(item) && 'active'"
@click="elem.change(item)">
<img src="@/assets/images/icon_file.png">{{item.departmentName}}</a>
<a v-else><img src="@/assets/images/icon_file.png">{{item.departmentName}}</a>
<i @click="elem.next(item)">下级</i>
<li v-for="item in elem.data" :key="item.id" class="check_box not" :class="{not: !elem.isDepartment}">
<a v-if="elem.isDepartment" :class="elem.isActive(item) && 'active'" @click="elem.change(item)">
<img src="@/assets/images/icon_file.png">{{item.departmentName}}
</a>
<a v-else><img src="@/assets/images/icon_file.png">{{item.departmentName}}</a>
<i @click="elem.next(item)">下级</i>
</li>
</template>
<template v-if="elem.type === 'employee'">
<li v-for="item in elem.data" :key="item.id" class="check_box">
<a :class="elem.isActive(item) && 'active'"
@click="elem.change(item)"
:title="item.departmentNames">
<img v-if="item.icon != ''" :src="item.icon">
<img v-if="item.icon == '' && item.iconToBase64 != ''" :src="item.iconToBase64">
<img v-if="item.icon == '' && item.iconToBase64 == ''" src="@/assets/images/icon_people.png">{{item.employeeName}}
<a :class="elem.isActive(item) && 'active'" :title="item.departmentNames" @click="elem.change(item)" >
<img v-if="item.icon != ''" :src="item.icon">
<img v-if="item.icon == '' && item.iconToBase64 != ''" :src="item.iconToBase64">
<img v-if="item.icon == '' && item.iconToBase64 == ''" src="@/assets/images/icon_people.png">{{item.employeeName}}
</a>
</li>
</template>
</template>
</ul>
</template>
<style lang="less">
.select-box {
height: 420px;
overflow-y: auto;
li {
padding: 5px 0;
i {
float: right;
padding-left: 24px;
@ -66,7 +66,7 @@ defineProps({
background: url('../../assets/images/next_level_active.png') no-repeat 10px center;
border-left: 1px solid rgb(238, 238, 238);
}
a.active+i {
color: rgb(197, 197, 197);
background-image: url('../../assets/images/next_level.png');
@ -80,4 +80,30 @@ defineProps({
}
}
}
.not{
a{
padding-left:20px
}
}
.not a::before {
position: absolute;
width: 14px;
height: 14px;
border: 1px solid #dcdfe6;
border-radius: 2px;
left: 0;
top: 1px;
content: "";
}
.not a.active {
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
top: 3px;
left: 3px;
content: "";
background: url("../../assets/images/check_box.png") no-repeat center;
}
</style>

121
src/components/workflow/selectBoxs.vue

@ -0,0 +1,121 @@
<!--
@ 作者: 秦东
@ 时间: 2023-10-16 08:36:15
@ 备注: 通用左侧选择
-->
<script lang='ts' setup>
defineProps({
list: {
type: Array,
default: () => []
}
})
</script>
<template>
<ul class="select-box">
<template v-for="(elem, i) in list" :key="i">
<!--角色列表遍历-->
<template v-if="elem.type === 'role'">
<li v-for="item in elem.data" :key="item.roleId" class="check_box" :class="{not: !elem.isDepartment}">
<div :class="elem.isActive(item) && 'active'">
<a :title="item.departmentNames" @click="elem.change(item)">
<img src="@/assets/images/icon_role.png">{{item.roleName}}
</a>
</div>
</li>
</template>
<!--行政组织遍历-->
<template v-if="elem.type === 'department'">
<li v-for="item in elem.data" :key="item.id" class="check_box" :class="{not: !elem.isDepartment}">
<div :class="elem.isActive(item) && 'active'">
<a v-if="elem.isDepartment" @click="elem.change(item)">
<span></span><img src="@/assets/images/icon_file.png">{{item.departmentName}}
</a>
<a v-else><img src="@/assets/images/icon_file.png">{{item.departmentName}}</a>
<i @click="elem.next(item)">下级</i>
</div>
</li>
</template>
<!--人员信息遍历-->
<template v-if="elem.type === 'employee'">
<li v-for="item in elem.data" :key="item.id" class="check_box" :class="{not: !elem.isDepartment}">
<div :class="elem.isActive(item) && 'active'">
<a :title="item.departmentNames" @click="elem.change(item)">
<span></span><img v-if="item.icon != ''" :src="item.icon">
<img v-if="item.icon == '' && item.iconToBase64 != ''" :src="item.iconToBase64">
<img v-if="item.icon == '' && item.iconToBase64 == ''" src="@/assets/images/icon_people.png">
{{item.employeeName}}
</a>
</div>
</li>
</template>
</template>
</ul>
</template>
<style lang='scss' scoped>
.select-box {
height: 420px;
overflow-y: auto;
li{
padding: 5px 0;
div{
display: flex;
box-sizing: border-box;
justify-content: space-between;
i{
padding-left: 24px;
padding-right: 10px;
color: #3195f8;
cursor: pointer;
border-left: 1px solid rgb(238, 238, 238);
background: url("@/assets/images/next_level_active.png") no-repeat 10px center;
}
a::before{
border: none;
}
span{
display:inline-block;
width:15px;
height:15px;
background: url("@/assets/images/checkbox.png");
background-size:cover;
}
a {
img{
margin-left:5px;
width: 14px;
vertical-align: middle;
margin-right: 5px;
}
}
}
div.active{
a{
color: rgb(197, 197, 197);
img{
margin-left:5px;
}
}
i{
color: rgb(197, 197, 197);
background-image: url("@/assets/images/next_level.png");
pointer-events: none;
}
span{
display:inline-block;
width:15px;
height:15px;
background: url("@/assets/images/checkbox_true.png");
background-size:cover;
}
}
}
}
</style>

5
src/components/workflow/selectResult.vue

@ -4,7 +4,7 @@
@ 备注: 已选择得内容
-->
<script lang='ts' setup>
defineProps({
let props = defineProps({
total: {
type: Number,
default: 0
@ -15,6 +15,7 @@ defineProps({
}
})
let emits = defineEmits(['del'])
</script>
<template>
<div class="select-result l">
@ -23,6 +24,7 @@ let emits = defineEmits(['del'])
</p>
<ul>
<template v-for="({type, data, cancel}) in list" :key="type">
<template v-if="type === 'role'">
<li v-for="item in data" :key="item.roleId">
<img src="@/assets/images/icon_role.png">
@ -44,6 +46,7 @@ let emits = defineEmits(['del'])
<img v-if="item.icon == '' && item.iconToBase64 == ''" src="@/assets/images/icon_people.png">
<span>{{item.employeeName}}</span>
<img src="@/assets/images/cancel.png" @click="cancel(item)">
</li>
</template>
</template>

5
src/utils/workflow/const.ts

@ -7,9 +7,12 @@ export let placeholderList = ["发起人", "审核人", "抄送人", "执行人"
export let setTypes = [
{value: 1, label: '指定成员'},
{value: 2, label: '主管'},
{value: 3, label: '行政岗位'},
{value: 4, label: '发起人自选'},
{value: 5, label: '发起人自己'},
{value: 7, label: '连续多级主管'},
{value: 6, label: '连续多级主管'},
{value: 7, label: '指定前置审批为本节点设置审批人'},
{value: 8, label: '表单字段'},
]
export let selectModes = [

10
src/utils/workflow/index.ts

@ -59,6 +59,7 @@ All.prototype = {
arr.splice(includesIndex, 1);
},
setApproverStr(nodeConfig:any) {
// console.log("setApproverStr",nodeConfig);
if (nodeConfig.settype == 1) {
if (nodeConfig.nodeUserList.length == 1) {
return nodeConfig.nodeUserList[0].name
@ -67,6 +68,8 @@ All.prototype = {
return this.arrToStr(nodeConfig.nodeUserList)
} else if (nodeConfig.examineMode == 2) {
return nodeConfig.nodeUserList.length + "人会签"
}else if (nodeConfig.examineMode == 3) {
return nodeConfig.nodeUserList.length + "人非会签"
}
}
} else if (nodeConfig.settype == 2) {
@ -77,6 +80,7 @@ All.prototype = {
return level + "会签"
}
} else if (nodeConfig.settype == 4) {
console.log("nodeConfig.selectRange",nodeConfig.selectRange,nodeConfig.nodeUserList);
if (nodeConfig.selectRange == 1) {
return "发起人自选"
} else {
@ -92,9 +96,11 @@ All.prototype = {
}
} else if (nodeConfig.settype == 5) {
return "发起人自己"
} else if (nodeConfig.settype == 7) {
} else if (nodeConfig.settype == 6) {
return '从直接主管到通讯录中级别最高的第' + nodeConfig.examineEndDirectorLevel + '个层级主管'
}
}else if (nodeConfig.settype == 7){
return "指定前置审批为本节点设置审批人"
}
},
dealStr(str:any, obj:any) {
let arr: any[] = [];

14
src/views/sysworkflow/flow/flowDrawingBoard.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2023-10-18 09:02:53
@ 备注: 工作流画板
-->
<script lang='ts' setup>
</script>
<template>
<div></div>
</template>
<style lang='scss' scoped>
</style>

21
src/views/sysworkflow/flow/index.vue

@ -22,7 +22,7 @@ const drawer = ref(false)
const drawerWidht = ref()
const openfloaw = ()=>{
drawerWidht.value = flowcont.value?.clientWidth
console.log("clientHeight--->",drawerWidht.value)
// console.log("clientHeight--->",drawerWidht.value)
drawer.value = true
}
@ -35,7 +35,7 @@ let processConfig = ref<any>({});
let nodeConfig = ref({});
let workFlowDef = ref({});
let flowPermission = ref([]);
let directorMaxLevel = ref(0);
let directorMaxLeveling = ref<number>(0);
//
onMounted(async ()=>{
@ -44,19 +44,20 @@ onMounted(async ()=>{
//
const initWorkFlowData = async() => {
let { data } = await initializeWorkFlow({name:""})
console.log("data",data)
// console.log("data-=------>",data)
let {
nodeConfig: nodes,
flowPermission: flows,
directorMaxLevel: directors,
directorMaxLevel: directorMaxLevel,
workFlowDef: works,
tableId,
} = data;
nodeConfig.value = nodes;
flowPermission.value = flows;
directorMaxLevel.value = directors;
directorMaxLeveling = directorMaxLevel;
workFlowDef.value = works;
setTableId(tableId);
// console.log("max--->",flowPermission.value)
}
//
const reErr = ({ childNode }:any) => {
@ -89,14 +90,16 @@ const reErr = ({ childNode }:any) => {
const saveSet = async () => {
setIsTried(true);
tipList.value = [];
processConfig.value.flowPermission = flowPermission.value;
// eslint-disable-next-line no-console
// console.log("processConfig",JSON.stringify(nodeConfig.value));
// console.log("processConfig",nodeConfig.value);
reErr(nodeConfig.value);
if (tipList.value.length != 0) {
tipVisible.value = true;
return;
}
processConfig.value.flowPermission = flowPermission.value;
// eslint-disable-next-line no-console
console.log(JSON.stringify(processConfig.value));
let res = await setWorkFlowData(processConfig.value);
if (res.code == 200) {
ElMessage.success("设置成功")
@ -168,7 +171,7 @@ const clearCanvas = () =>{
</div>
<errorDialog v-model:visible="tipVisible" :list="tipList" />
<promoterDrawer />
<approverDrawer :directormaxlevel="directorMaxLevel" />
<approverDrawer :directormaxlevel="directorMaxLeveling" :node-config="nodeConfig" />
<copyerDrawer />
<conditionDrawer />
</div>

Loading…
Cancel
Save