21 changed files with 43365 additions and 9520 deletions
File diff suppressed because it is too large
@ -0,0 +1,220 @@ |
|||
<template> |
|||
<div class="add-node-btn-box"> |
|||
<div class="add-node-btn"> |
|||
<el-popover placement="right-start" v-model="visible" width="auto"> |
|||
<div class="add-node-popover-body"> |
|||
<a class="add-node-popover-item approver" @click="addType(1)"> |
|||
<div class="item-wrapper"> |
|||
<span class="iconfont"></span> |
|||
</div> |
|||
<p>审批人</p> |
|||
</a> |
|||
<a class="add-node-popover-item notifier" @click="addType(2)"> |
|||
<div class="item-wrapper"> |
|||
<span class="iconfont"></span> |
|||
</div> |
|||
<p>抄送人</p> |
|||
</a> |
|||
<a class="add-node-popover-item condition" @click="addType(4)"> |
|||
<div class="item-wrapper"> |
|||
<span class="iconfont"></span> |
|||
</div> |
|||
<p>条件分支</p> |
|||
</a> |
|||
</div> |
|||
<template #reference> |
|||
<button class="btn" type="button"> |
|||
<span class="iconfont"></span> |
|||
</button> |
|||
</template> |
|||
</el-popover> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
import { ref } from 'vue' |
|||
let props = defineProps({ |
|||
childNodeP: { |
|||
type: Object, |
|||
default: ()=> ({}) |
|||
} |
|||
}) |
|||
let emits = defineEmits(['update:childNodeP']) |
|||
let visible = ref(false) |
|||
const addType = (type)=> { |
|||
visible.value = false; |
|||
if (type != 4) { |
|||
var data; |
|||
if (type == 1) { |
|||
data = { |
|||
"nodeName": "审核人", |
|||
"error": true, |
|||
"type": 1, |
|||
"settype": 1, |
|||
"selectMode": 0, |
|||
"selectRange": 0, |
|||
"directorLevel": 1, |
|||
"examineMode": 1, |
|||
"noHanderAction": 1, |
|||
"examineEndDirectorLevel": 0, |
|||
"childNode": props.childNodeP, |
|||
"nodeUserList": [] |
|||
} |
|||
} else if (type == 2) { |
|||
data = { |
|||
"nodeName": "抄送人", |
|||
"type": 2, |
|||
"ccSelfSelectFlag": 1, |
|||
"childNode": props.childNodeP, |
|||
"nodeUserList": [] |
|||
} |
|||
} |
|||
emits("update:childNodeP", data) |
|||
} else { |
|||
emits("update:childNodeP", { |
|||
"nodeName": "路由", |
|||
"type": 4, |
|||
"childNode": null, |
|||
"conditionNodes": [{ |
|||
"nodeName": "条件1", |
|||
"error": true, |
|||
"type": 3, |
|||
"priorityLevel": 1, |
|||
"conditionList": [], |
|||
"nodeUserList": [], |
|||
"childNode": props.childNodeP, |
|||
}, { |
|||
"nodeName": "条件2", |
|||
"type": 3, |
|||
"priorityLevel": 2, |
|||
"conditionList": [], |
|||
"nodeUserList": [], |
|||
"childNode": null |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
</script> |
|||
<style scoped lang="less"> |
|||
.add-node-btn-box { |
|||
width: 240px; |
|||
display: -webkit-inline-box; |
|||
display: -ms-inline-flexbox; |
|||
display: inline-flex; |
|||
-ms-flex-negative: 0; |
|||
flex-shrink: 0; |
|||
-webkit-box-flex: 1; |
|||
-ms-flex-positive: 1; |
|||
position: relative; |
|||
&:before { |
|||
content: ""; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: -1; |
|||
margin: auto; |
|||
width: 2px; |
|||
height: 100%; |
|||
background-color: #cacaca |
|||
} |
|||
.add-node-btn { |
|||
user-select: none; |
|||
width: 240px; |
|||
padding: 20px 0 32px; |
|||
display: flex; |
|||
-webkit-box-pack: center; |
|||
justify-content: center; |
|||
flex-shrink: 0; |
|||
-webkit-box-flex: 1; |
|||
flex-grow: 1; |
|||
.btn { |
|||
outline: none; |
|||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1); |
|||
width: 30px; |
|||
height: 30px; |
|||
background: #3296fa; |
|||
border-radius: 50%; |
|||
position: relative; |
|||
border: none; |
|||
line-height: 30px; |
|||
-webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1); |
|||
transition: all .3s cubic-bezier(.645, .045, .355, 1); |
|||
.iconfont { |
|||
color: #fff; |
|||
font-size: 16px |
|||
} |
|||
&:hover { |
|||
transform: scale(1.3); |
|||
box-shadow: 0 13px 27px 0 rgba(0, 0, 0, .1) |
|||
} |
|||
&:active { |
|||
transform: none; |
|||
background: #1e83e9; |
|||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
<style lang="less"> |
|||
.add-node-popover-body { |
|||
display: flex; |
|||
.add-node-popover-item { |
|||
margin-right: 10px; |
|||
cursor: pointer; |
|||
text-align: center; |
|||
flex: 1; |
|||
color: #191f25!important; |
|||
.item-wrapper { |
|||
user-select: none; |
|||
display: inline-block; |
|||
width: 80px; |
|||
height: 80px; |
|||
margin-bottom: 5px; |
|||
background: #fff; |
|||
border: 1px solid #e2e2e2; |
|||
border-radius: 50%; |
|||
transition: all .3s cubic-bezier(.645, .045, .355, 1); |
|||
.iconfont { |
|||
font-size: 35px; |
|||
line-height: 80px |
|||
} |
|||
} |
|||
&.approver{ |
|||
.item-wrapper { |
|||
color: #ff943e |
|||
} |
|||
} |
|||
&.notifier{ |
|||
.item-wrapper { |
|||
color: #3296fa |
|||
} |
|||
} |
|||
&.condition{ |
|||
.item-wrapper { |
|||
color: #15bc83 |
|||
} |
|||
} |
|||
&:hover{ |
|||
.item-wrapper { |
|||
background: #3296fa; |
|||
box-shadow: 0 10px 20px 0 rgba(50, 150, 250, .4) |
|||
} |
|||
.iconfont { |
|||
color: #fff |
|||
} |
|||
} |
|||
&:active{ |
|||
.item-wrapper { |
|||
box-shadow: none; |
|||
background: #eaeaea |
|||
} |
|||
.iconfont { |
|||
color: inherit |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,46 @@ |
|||
/* |
|||
* @Date: 2022-08-29 14:00:42 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-29 15:53:05 |
|||
* @FilePath: /Workflow-Vue3/src/components/dialog/common.js |
|||
*/ |
|||
|
|||
import { getRoles, getDepartments, getEmployees } from '@/api/index.js' |
|||
import $func from '@/utils/index.js' |
|||
import { ref } from 'vue' |
|||
export let searchVal = ref('') |
|||
export let departments = ref({ |
|||
titleDepartments: [], |
|||
childDepartments: [], |
|||
employees: [], |
|||
}) |
|||
export let roles = ref({}) |
|||
export let getRoleList = async () => { |
|||
let { data: { list } } = await getRoles() |
|||
roles.value = list; |
|||
} |
|||
export let getDepartmentList = async (parentId = 0) => { |
|||
let { data } = await getDepartments({ parentId }) |
|||
departments.value = data; |
|||
} |
|||
export let getDebounceData = (event, type = 1) => { |
|||
$func.debounce(async () => { |
|||
if (event.target.value) { |
|||
let data = { |
|||
searchName: event.target.value, |
|||
pageNum: 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(); |
|||
} |
|||
})() |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
<template> |
|||
<el-dialog title="选择成员" v-model="visibleDialog" :width="600" append-to-body class="promoter_person"> |
|||
<div class="person_body clear"> |
|||
<div class="person_tree l"> |
|||
<input type="text" placeholder="搜索成员" v-model="searchVal" @input="getDebounceData($event)"> |
|||
<p class="ellipsis tree_nav" v-if="!searchVal"> |
|||
<span @click="getDepartmentList(0)" class="ellipsis">天下</span> |
|||
<span v-for="(item,index) in departments.titleDepartments" class="ellipsis" |
|||
:key="index+'a'" @click="getDepartmentList(item.id)">{{item.departmentName}}</span> |
|||
</p> |
|||
<selectBox :list="list"/> |
|||
</div> |
|||
<selectResult :total="total" @del="delList" :list="resList"/> |
|||
</div> |
|||
<template #footer> |
|||
<el-button @click="$emit('update:visible',false)">取 消</el-button> |
|||
<el-button type="primary" @click="saveDialog">确 定</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import selectBox from '../selectBox.vue'; |
|||
import selectResult from '../selectResult.vue'; |
|||
import { computed, watch, ref } from 'vue'; |
|||
import { departments, getDebounceData, getDepartmentList, searchVal } from './common' |
|||
import $func from '@/utils/index.js' |
|||
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 checkedDepartmentList = ref([]) |
|||
let checkedEmployessList = ref([]) |
|||
let list = computed(()=> { |
|||
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(()=>{ |
|||
let data = [{ |
|||
type: 'employee', |
|||
data: checkedEmployessList.value, |
|||
cancel: (item)=> $func.removeEle(checkedEmployessList.value, item) |
|||
}] |
|||
if(props.isDepartment){ |
|||
data.unshift({ |
|||
type: 'department', |
|||
data: checkedDepartmentList.value, |
|||
cancel: (item)=> $func.removeEle(checkedDepartmentList.value, item) |
|||
}) |
|||
} |
|||
return data |
|||
}) |
|||
watch(()=> props.visible, (val)=>{ |
|||
if(val){ |
|||
getDepartmentList(); |
|||
searchVal.value = ""; |
|||
checkedEmployessList.value = props.data.filter(item=>item.type===1).map(({name,targetId})=>({ |
|||
employeeName: name, |
|||
id: targetId |
|||
})); |
|||
checkedDepartmentList.value = props.data.filter(item=>item.type===3).map(({name,targetId})=>({ |
|||
departmentName: name, |
|||
id: targetId |
|||
})); |
|||
} |
|||
}) |
|||
|
|||
const closeDialog = ()=> { |
|||
emits('update:visible', false) |
|||
} |
|||
|
|||
let total = computed(()=> checkedDepartmentList.value.length + checkedEmployessList.value.length) |
|||
|
|||
let saveDialog = ()=> { |
|||
let checkedList = [ |
|||
...checkedDepartmentList.value, |
|||
...checkedEmployessList.value |
|||
].map(item=>({ |
|||
type: item.employeeName ? 1: 3, |
|||
targetId: item.id, |
|||
name: item.employeeName || item.departmentName |
|||
})) |
|||
emits('change',checkedList) |
|||
} |
|||
const delList = ()=> { |
|||
checkedDepartmentList.value = []; |
|||
checkedEmployessList.value = [] |
|||
} |
|||
</script> |
|||
<style> |
|||
@import "@/css/dialog.css"; |
|||
</style> |
|||
@ -0,0 +1,160 @@ |
|||
<template> |
|||
<el-dialog title="选择成员" v-model="visibleDialog" :width="600" append-to-body class="promoter_person"> |
|||
<div class="person_body clear"> |
|||
<div class="person_tree l"> |
|||
<input type="text" placeholder="搜索成员" v-model="searchVal" @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 class="ellipsis tree_nav" v-if="activeName === '1' && !searchVal"> |
|||
<span @click="getDepartmentList(0)" class="ellipsis">天下</span> |
|||
<span v-for="(item,index) in departments.titleDepartments" class="ellipsis" |
|||
:key="index+'a'" @click="getDepartmentList(item.id)">{{item.departmentName}}</span> |
|||
</p> |
|||
<selectBox :list="list" style="height: 360px;"/> |
|||
</div> |
|||
<selectResult :total="total" @del="delList" :list="resList"/> |
|||
</div> |
|||
<template #footer> |
|||
<el-button @click="$emit('update:visible',false)">取 消</el-button> |
|||
<el-button type="primary" @click="saveDialog">确 定</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import selectBox from '../selectBox.vue'; |
|||
import selectResult from '../selectResult.vue'; |
|||
import { computed, watch, ref } from 'vue' |
|||
import $func from '@/utils/index.js' |
|||
import { departments, roles, getDebounceData, getRoleList, getDepartmentList, searchVal } from './common' |
|||
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(()=> { |
|||
if(activeName.value === '2'){ |
|||
return [{ |
|||
type: 'role', |
|||
not: false, |
|||
data: roles.value, |
|||
isActiveItem: (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(()=>{ |
|||
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)=>{ |
|||
if(val){ |
|||
activeName.value = "1"; |
|||
getDepartmentList(); |
|||
searchVal.value = ""; |
|||
checkedEmployessList.value = props.data.filter(item=>item.type===1).map(({name,targetId})=>({ |
|||
employeeName: name, |
|||
id: targetId |
|||
})); |
|||
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 |
|||
})) |
|||
emits('change',checkedList) |
|||
} |
|||
const delList = ()=> { |
|||
checkedEmployessList.value = []; |
|||
checkedRoleList.value = []; |
|||
checkedDepartmentList.value = []; |
|||
} |
|||
const closeDialog = ()=> { |
|||
emits('update:visible', false) |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
@import "@/css/dialog.css"; |
|||
</style> |
|||
@ -0,0 +1,77 @@ |
|||
<!-- |
|||
* @Date: 2022-08-25 14:05:59 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-29 16:05:54 |
|||
* @FilePath: /Workflow-Vue3/src/components/dialog/errorDialog.vue |
|||
--> |
|||
<template> |
|||
<el-dialog title="提示" v-model="visibleDialog" :width="520"> |
|||
<div class="ant-confirm-body"> |
|||
<i class="anticon anticon-close-circle" style="color: #f00;"></i> |
|||
<span class="ant-confirm-title">当前无法发布</span> |
|||
<div class="ant-confirm-content"> |
|||
<div> |
|||
<p class="error-modal-desc">以下内容不完善,需进行修改</p> |
|||
<div class="error-modal-list"> |
|||
<div class="error-modal-item" v-for="(item,index) in list" :key="index"> |
|||
<div class="error-modal-item-label">流程设计</div> |
|||
<div class="error-modal-item-content">{{item.name}} 未选择{{item.type}}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<template #footer> |
|||
<el-button @click="visibleDialog = false">我知道了</el-button> |
|||
<el-button type="primary" @click="visibleDialog = false">前往修改</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed } from 'vue' |
|||
let props = defineProps({ |
|||
list: { |
|||
type: Array, |
|||
default: () => [] |
|||
}, |
|||
visible: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}) |
|||
let emits = defineEmits(['update:visible']) |
|||
|
|||
let visibleDialog = computed({ |
|||
get() { |
|||
return props.visible |
|||
}, |
|||
set(val) { |
|||
emits('update:visible', val) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.ant-confirm-body .ant-confirm-title { |
|||
color: rgba(0, 0, 0, .85); |
|||
font-weight: 500; |
|||
font-size: 16px; |
|||
line-height: 1.4; |
|||
display: block; |
|||
overflow: hidden |
|||
} |
|||
|
|||
.ant-confirm-body .ant-confirm-content { |
|||
margin-left: 38px; |
|||
font-size: 14px; |
|||
color: rgba(0, 0, 0, .65); |
|||
margin-top: 8px |
|||
} |
|||
|
|||
.ant-confirm-body>.anticon { |
|||
font-size: 22px; |
|||
margin-right: 16px; |
|||
float: left |
|||
} |
|||
</style> |
|||
@ -0,0 +1,96 @@ |
|||
<!-- |
|||
* @Date: 2022-08-25 14:05:59 |
|||
* * @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-15 14:59:19 |
|||
* @FilePath: /Workflow-Vue3/src/components/dialog/roleDialog.vue |
|||
--> |
|||
<template> |
|||
<el-dialog title="选择角色" v-model="visibleDialog" :width="600" append-to-body class="promoter_person"> |
|||
<div class="person_body clear"> |
|||
<div class="person_tree l"> |
|||
<input type="text" placeholder="搜索角色" v-model="searchVal" @input="getDebounceData($event,2)"> |
|||
<selectBox :list="list" /> |
|||
</div> |
|||
<selectResult :total="total" @del="delList" :list="resList"/> |
|||
</div> |
|||
<template #footer> |
|||
<el-button @click="closeDialog">取 消</el-button> |
|||
<el-button type="primary" @click="saveDialog">确 定</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
<script setup> |
|||
import selectBox from '../selectBox.vue'; |
|||
import selectResult from '../selectResult.vue'; |
|||
import { computed, watch, ref } from 'vue' |
|||
import $func from '@/utils/index.js' |
|||
import { roles, getDebounceData, getRoleList, searchVal } from './common' |
|||
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> |
|||
|
|||
<style> |
|||
@import "@/css/dialog.css"; |
|||
</style> |
|||
@ -0,0 +1,231 @@ |
|||
<template> |
|||
<el-drawer :append-to-body="true" title="审批人设置" v-model="visible" custom-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-group> |
|||
<el-button type="primary" @click="addApprover" v-if="approverConfig.settype==1">添加/修改成员</el-button> |
|||
<p class="selected_list" v-if="approverConfig.settype==1"> |
|||
<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 class="approver_manager" v-if="approverConfig.settype==2"> |
|||
<p> |
|||
<span>发起人的:</span> |
|||
<select v-model="approverConfig.directorLevel"> |
|||
<option v-for="item in directorMaxLevel" :value="item" :key="item">{{item==1?'直接':'第'+item+'级'}}主管</option> |
|||
</select> |
|||
</p> |
|||
<p class="tip">找不到主管时,由上级主管代审批</p> |
|||
</div> |
|||
<div class="approver_self" v-if="approverConfig.settype==5"> |
|||
<p>该审批节点设置“发起人自己”后,审批人默认为发起人</p> |
|||
</div> |
|||
<div class="approver_self_select" v-show="approverConfig.settype==4"> |
|||
<el-radio-group v-model="approverConfig.selectMode" style="width: 100%;"> |
|||
<el-radio v-for="({value, label}) in selectModes" :label="value" :key="value">{{label}}</el-radio> |
|||
</el-radio-group> |
|||
<h3>选择范围</h3> |
|||
<el-radio-group v-model="approverConfig.selectRange" style="width: 100%;" @change="changeRange"> |
|||
<el-radio v-for="({value, label}) in selectRanges" :label="value" :key="value">{{label}}</el-radio> |
|||
</el-radio-group> |
|||
<template v-if="approverConfig.selectRange==2||approverConfig.selectRange==3"> |
|||
<el-button type="primary" @click="addApprover" v-if="approverConfig.selectRange==2">添加/修改成员</el-button> |
|||
<el-button type="primary" @click="addRoleApprover" v-else>添加/修改角色</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> |
|||
</p> |
|||
</template> |
|||
|
|||
</div> |
|||
<div class="approver_manager" v-if="approverConfig.settype==7"> |
|||
<p>审批终点</p> |
|||
<p style="padding-bottom:20px"> |
|||
<span>发起人的:</span> |
|||
<select v-model="approverConfig.examineEndDirectorLevel"> |
|||
<option v-for="item in directorMaxLevel" :value="item" :key="item">{{item==1?'最高':'第'+item}}层级主管</option> |
|||
</select> |
|||
</p> |
|||
</div> |
|||
<div class="approver_some" v-if="(approverConfig.settype==1&&approverConfig.nodeUserList.length>1)||approverConfig.settype==2||(approverConfig.settype==4&&approverConfig.selectMode==2)"> |
|||
<p>多人审批时采用的审批方式</p> |
|||
<el-radio-group v-model="approverConfig.examineMode" class="clear"> |
|||
<el-radio :label="1">依次审批</el-radio> |
|||
<br/> |
|||
<el-radio :label="2" v-if="approverConfig.settype!=2">会签(须所有审批人同意)</el-radio> |
|||
</el-radio-group> |
|||
</div> |
|||
<div class="approver_some" v-if="approverConfig.settype==2||approverConfig.settype==7"> |
|||
<p>审批人为空时</p> |
|||
<el-radio-group v-model="approverConfig.noHanderAction" class="clear"> |
|||
<el-radio :label="1">自动审批通过/不允许发起</el-radio> |
|||
<br/> |
|||
<el-radio :label="2">转交给审核管理员</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> |
|||
<script setup> |
|||
import {ref, watch, computed} from 'vue' |
|||
import $func from '@/utils/index' |
|||
import { setTypes, selectModes, selectRanges } from '@/utils/const' |
|||
import { mapState, mapMutations } from '@/utils/lib' |
|||
import employeesDialog from '../dialog/employeesDialog.vue' |
|||
import roleDialog from '../dialog/roleDialog.vue' |
|||
|
|||
let props = defineProps({ |
|||
directorMaxLevel: { |
|||
type: Number, |
|||
default: 0 |
|||
} |
|||
}); |
|||
let approverConfig = ref({}) |
|||
let approverVisible = ref(false) |
|||
let approverRoleVisible = ref(false) |
|||
let checkedRoleList = ref([]) |
|||
let checkedList = ref([]) |
|||
let { approverConfig1, approverDrawer } = mapState() |
|||
let visible = computed({ |
|||
get(){ |
|||
return approverDrawer.value |
|||
}, |
|||
set(){ |
|||
closeDrawer() |
|||
} |
|||
}) |
|||
watch(approverConfig1, (val)=>{ |
|||
approverConfig.value = val.value |
|||
}) |
|||
let { setApproverConfig, setApprover} = mapMutations() |
|||
let changeRange = ()=> { |
|||
approverConfig.value.nodeUserList = []; |
|||
} |
|||
const changeType = (val)=> { |
|||
approverConfig.value.nodeUserList = []; |
|||
approverConfig.value.examineMode = 1; |
|||
approverConfig.value.noHanderAction = 2; |
|||
if (val == 2) { |
|||
approverConfig.value.directorLevel = 1; |
|||
} else if (val == 4) { |
|||
approverConfig.value.selectMode = 1; |
|||
approverConfig.value.selectRange = 1; |
|||
} else if (val == 7) { |
|||
approverConfig.value.examineEndDirectorLevel = 1 |
|||
} |
|||
} |
|||
const addApprover = ()=> { |
|||
approverVisible.value = true; |
|||
checkedList.value = approverConfig.value.nodeUserList |
|||
} |
|||
const addRoleApprover = ()=> { |
|||
approverRoleVisible.value = true; |
|||
checkedRoleList.value = approverConfig.value.nodeUserList |
|||
} |
|||
const sureApprover = (data)=> { |
|||
approverConfig.value.nodeUserList = data; |
|||
approverVisible.value = false; |
|||
} |
|||
const sureRoleApprover = (data)=> { |
|||
approverConfig.value.nodeUserList = data; |
|||
approverRoleVisible.value = false; |
|||
} |
|||
const saveApprover = ()=> { |
|||
approverConfig.value.error = !$func.setApproverStr(approverConfig.value) |
|||
setApproverConfig({ |
|||
value: approverConfig.value, |
|||
flag: true, |
|||
id: approverConfig1.value.id |
|||
}) |
|||
closeDrawer() |
|||
} |
|||
const closeDrawer = ()=> { |
|||
setApprover(false) |
|||
} |
|||
</script> |
|||
<style lang="less"> |
|||
.set_promoter{ |
|||
.approver_content { |
|||
padding-bottom: 10px; |
|||
border-bottom: 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 0; |
|||
} |
|||
.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; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,363 @@ |
|||
<!-- |
|||
* @Date: 2023-03-15 14:44:17 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-29 15:53:11 |
|||
* @FilePath: /Workflow-Vue3/src/components/drawer/conditionDrawer.vue |
|||
--> |
|||
|
|||
<template> |
|||
<el-drawer :append-to-body="true" title="条件设置" v-model="visible" custom-class="condition_copyer" :show-close="false" :size="550" :before-close="saveCondition"> |
|||
<template #header="{ titleId, titleClass }"> |
|||
<h3 :id="titleId" :class="titleClass">条件设置</h3> |
|||
<select v-model="conditionConfig.priorityLevel" class="priority_level"> |
|||
<option v-for="item in conditionsConfig.conditionNodes.length" :value="item" :key="item">优先级{{item}}</option> |
|||
</select> |
|||
</template> |
|||
<div class="demo-drawer__content"> |
|||
<div class="condition_content drawer_content"> |
|||
<p class="tip">当审批单同时满足以下条件时进入此流程</p> |
|||
<ul> |
|||
<li v-for="(item,index) in conditionConfig.conditionList" :key="index"> |
|||
<span class="ellipsis">{{item.type==1 ? '发起人':item.showName}}:</span> |
|||
<div v-if="item.type==1"> |
|||
<p :class="conditionConfig.nodeUserList.length > 0?'selected_list':''" @click.self="addConditionRole" style="cursor:text"> |
|||
<span v-for="(item1,index1) in conditionConfig.nodeUserList" :key="index1"> |
|||
{{item1.name}}<img src="@/assets/images/add-close1.png" @click="$func.removeEle(conditionConfig.nodeUserList,item1,'targetId')"> |
|||
</span> |
|||
<input type="text" placeholder="请选择具体人员/角色/部门" v-if="conditionConfig.nodeUserList.length == 0" @click="addConditionRole"> |
|||
</p> |
|||
</div> |
|||
<div v-else-if="item.columnType == 'String' && item.showType == 3"> |
|||
<p class="check_box"> |
|||
<a :class="$func.toggleStrClass(item,item1.key)&&'active'" @click="toStrChecked(item,item1.key)" |
|||
v-for="(item1,index1) in JSON.parse(item.fixedDownBoxValue)" :key="index1">{{item1.value}}</a> |
|||
</p> |
|||
</div> |
|||
<div v-else> |
|||
<p> |
|||
<select v-model="item.optType" :style="'width:'+(item.optType==6?370:100)+'px'" @change="changeOptType(item)"> |
|||
<option v-for="({value, label}) in optTypes" :value="value" :key="value">{{ label }}</option> |
|||
</select> |
|||
<input v-if="item.optType!=6" type="text" :placeholder="'请输入'+item.showName" v-enter-number="2" v-model="item.zdy1"> |
|||
</p> |
|||
<p v-if="item.optType==6"> |
|||
<input type="text" style="width:75px;" class="mr_10" v-enter-number="2" v-model="item.zdy1"> |
|||
<select style="width:60px;" v-model="item.opt1"> |
|||
<option v-for="({value, label}) in opt1s" :value="value" :key="value">{{ label }}</option> |
|||
</select> |
|||
<span class="ellipsis" style="display:inline-block;width:60px;vertical-align: text-bottom;">{{item.showName}}</span> |
|||
<select style="width:60px;" class="ml_10" v-model="item.opt2"> |
|||
<option v-for="({value, label}) in opt1s" :value="value" :key="value">{{ label }}</option> |
|||
</select> |
|||
<input type="text" style="width:75px;" v-enter-number="2" v-model="item.zdy2"> |
|||
</p> |
|||
</div> |
|||
<a v-if="item.type==1" @click="conditionConfig.nodeUserList= [];$func.removeEle(conditionConfig.conditionList,item,'columnId')">删除</a> |
|||
<a v-if="item.type==2" @click="$func.removeEle(conditionConfig.conditionList,item,'columnId')">删除</a> |
|||
</li> |
|||
</ul> |
|||
<el-button type="primary" @click="addCondition">添加条件</el-button> |
|||
<el-dialog title="选择条件" v-model="conditionVisible" :width="480" append-to-body class="condition_list"> |
|||
<p>请选择用来区分审批流程的条件字段</p> |
|||
<p class="check_box"> |
|||
<a :class="$func.toggleClass(conditionList,{columnId:0},'columnId')&&'active'" @click="$func.toChecked(conditionList,{columnId:0},'columnId')">发起人</a> |
|||
<a v-for="(item,index) in conditions" :key="index" :class="$func.toggleClass(conditionList,item,'columnId')&&'active'" |
|||
@click="$func.toChecked(conditionList,item,'columnId')">{{item.showName}}</a> |
|||
</p> |
|||
<template #footer> |
|||
<el-button @click="conditionVisible = false">取 消</el-button> |
|||
<el-button type="primary" @click="sureCondition">确 定</el-button> |
|||
</template> |
|||
</el-dialog> |
|||
</div> |
|||
<employees-role-dialog |
|||
v-model:visible="conditionRoleVisible" |
|||
:data="checkedList" |
|||
@change="sureConditionRole" |
|||
:isDepartment="true" |
|||
/> |
|||
<div class="demo-drawer__footer clear"> |
|||
<el-button type="primary" @click="saveCondition">确 定</el-button> |
|||
<el-button @click="closeDrawer">取 消</el-button> |
|||
</div> |
|||
</div> |
|||
</el-drawer> |
|||
</template> |
|||
<script setup> |
|||
import { ref, watch, computed } from 'vue' |
|||
import $func from '@/utils/index' |
|||
import { mapState, mapMutations } from '@/utils/lib' |
|||
import { optTypes, opt1s } from '@/utils/const' |
|||
import { getConditions } from '@/api/index' |
|||
import employeesRoleDialog from '../dialog/employeesRoleDialog.vue' |
|||
|
|||
let conditionVisible = ref(false) |
|||
let conditionsConfig = ref({ |
|||
conditionNodes: [], |
|||
}) |
|||
let conditionConfig = ref({}) |
|||
let PriorityLevel = ref('') |
|||
let conditions = ref([]) |
|||
let conditionList = ref([]) |
|||
let checkedList = ref([]) |
|||
let conditionRoleVisible = ref(false) |
|||
|
|||
let { tableId, conditionsConfig1, conditionDrawer } = mapState() |
|||
let visible = computed({ |
|||
get() { |
|||
return conditionDrawer.value |
|||
}, |
|||
set() { |
|||
closeDrawer() |
|||
} |
|||
}) |
|||
watch(conditionsConfig1, (val) => { |
|||
conditionsConfig.value = val.value; |
|||
PriorityLevel.value = val.priorityLevel |
|||
conditionConfig.value = val.priorityLevel |
|||
? conditionsConfig.value.conditionNodes[val.priorityLevel - 1] |
|||
: { nodeUserList: [], conditionList: [] } |
|||
}) |
|||
let { setCondition, setConditionsConfig } = mapMutations() |
|||
|
|||
const changeOptType = (item) => { |
|||
if (item.optType == 1) { |
|||
item.zdy1 = 2; |
|||
} else { |
|||
item.zdy1 = 1; |
|||
item.zdy2 = 2; |
|||
} |
|||
} |
|||
const toStrChecked = (item, key) => { |
|||
let a = item.zdy1 ? item.zdy1.split(",") : [] |
|||
var isIncludes = $func.toggleStrClass(item, key); |
|||
if (!isIncludes) { |
|||
a.push(key) |
|||
item.zdy1 = a.toString() |
|||
} else { |
|||
removeStrEle(item, key); |
|||
} |
|||
} |
|||
const removeStrEle = (item, key) => { |
|||
let a = item.zdy1 ? item.zdy1.split(",") : [] |
|||
var includesIndex; |
|||
a.map((item, index) => { |
|||
if (item == key) { |
|||
includesIndex = index |
|||
} |
|||
}); |
|||
a.splice(includesIndex, 1); |
|||
item.zdy1 = a.toString() |
|||
} |
|||
const addCondition = async () => { |
|||
conditionList.value = []; |
|||
conditionVisible.value = true; |
|||
let { data } = await getConditions({ tableId: tableId.value }) |
|||
conditions.value = data; |
|||
if (conditionConfig.value.conditionList) { |
|||
for (var i = 0; i < conditionConfig.value.conditionList.length; i++) { |
|||
var { columnId } = conditionConfig.value.conditionList[i] |
|||
if (columnId == 0) { |
|||
conditionList.value.push({ columnId: 0 }) |
|||
} else { |
|||
conditionList.value.push(conditions.value.filter(item => { return item.columnId == columnId; })[0]) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
const sureCondition = () => { |
|||
//1.弹窗有,外面无+ |
|||
//2.弹窗有,外面有不变 |
|||
for (var i = 0; i < conditionList.value.length; i++) { |
|||
var { columnId, showName, columnName, showType, columnType, fixedDownBoxValue } = conditionList.value[i]; |
|||
if ($func.toggleClass(conditionConfig.value.conditionList, conditionList.value[i], "columnId")) { |
|||
continue; |
|||
} |
|||
if (columnId == 0) { |
|||
conditionConfig.value.nodeUserList = []; |
|||
conditionConfig.value.conditionList.push({ |
|||
"type": 1, |
|||
"columnId": columnId, |
|||
"showName": '发起人' |
|||
}); |
|||
} else { |
|||
if (columnType == "Double") { |
|||
conditionConfig.value.conditionList.push({ |
|||
"showType": showType, |
|||
"columnId": columnId, |
|||
"type": 2, |
|||
"showName": showName, |
|||
"optType": "1", |
|||
"zdy1": "2", |
|||
"opt1": "<", |
|||
"zdy2": "", |
|||
"opt2": "<", |
|||
"columnDbname": columnName, |
|||
"columnType": columnType, |
|||
}) |
|||
} else if (columnType == "String" && showType == "3") { |
|||
conditionConfig.value.conditionList.push({ |
|||
"showType": showType, |
|||
"columnId": columnId, |
|||
"type": 2, |
|||
"showName": showName, |
|||
"zdy1": "", |
|||
"columnDbname": columnName, |
|||
"columnType": columnType, |
|||
"fixedDownBoxValue": fixedDownBoxValue |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
//3.弹窗无,外面有- |
|||
for (let i = conditionConfig.value.conditionList.length - 1; i >= 0; i--) { |
|||
if (!$func.toggleClass(conditionList.value, conditionConfig.value.conditionList[i], "columnId")) { |
|||
conditionConfig.value.conditionList.splice(i, 1); |
|||
} |
|||
} |
|||
conditionConfig.value.conditionList.sort(function (a, b) { return a.columnId - b.columnId; }); |
|||
conditionVisible.value = false; |
|||
} |
|||
const saveCondition = () => { |
|||
closeDrawer() |
|||
var a = conditionsConfig.value.conditionNodes.splice(PriorityLevel.value - 1, 1)//截取旧下标 |
|||
conditionsConfig.value.conditionNodes.splice(conditionConfig.value.priorityLevel - 1, 0, a[0])//填充新下标 |
|||
conditionsConfig.value.conditionNodes.map((item, index) => { |
|||
item.priorityLevel = index + 1 |
|||
}); |
|||
for (var i = 0; i < conditionsConfig.value.conditionNodes.length; i++) { |
|||
conditionsConfig.value.conditionNodes[i].error = $func.conditionStr(conditionsConfig.value, i) == "请设置条件" && i != conditionsConfig.value.conditionNodes.length - 1 |
|||
} |
|||
setConditionsConfig({ |
|||
value: conditionsConfig.value, |
|||
flag: true, |
|||
id: conditionsConfig1.value.id |
|||
}) |
|||
} |
|||
const addConditionRole = () => { |
|||
conditionRoleVisible.value = true; |
|||
checkedList.value = conditionConfig.value.nodeUserList |
|||
} |
|||
const sureConditionRole = (data) => { |
|||
conditionConfig.value.nodeUserList = data; |
|||
conditionRoleVisible.value = false; |
|||
} |
|||
const closeDrawer = (val) => { |
|||
setCondition(false) |
|||
} |
|||
</script> |
|||
<style lang="less"> |
|||
.condition_copyer { |
|||
.priority_level { |
|||
position: absolute; |
|||
top: 11px; |
|||
right: 30px; |
|||
width: 100px; |
|||
height: 32px; |
|||
background: rgba(255, 255, 255, 1); |
|||
border-radius: 4px; |
|||
border: 1px solid rgba(217, 217, 217, 1); |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.condition_content { |
|||
padding: 20px 20px 0; |
|||
|
|||
p.tip { |
|||
margin: 20px 0; |
|||
width: 510px; |
|||
text-indent: 17px; |
|||
line-height: 45px; |
|||
background: rgba(241, 249, 255, 1); |
|||
border: 1px solid rgba(64, 163, 247, 1); |
|||
color: #46a6fe; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
ul { |
|||
max-height: 500px; |
|||
overflow-y: scroll; |
|||
margin-bottom: 20px; |
|||
|
|||
li { |
|||
&>span { |
|||
float: left; |
|||
margin-right: 8px; |
|||
width: 70px; |
|||
line-height: 32px; |
|||
text-align: right; |
|||
} |
|||
|
|||
&>div { |
|||
display: inline-block; |
|||
width: 370px; |
|||
|
|||
&>p:not(:last-child) { |
|||
margin-bottom: 10px; |
|||
} |
|||
} |
|||
|
|||
&:not(:last-child)>div>p { |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
&>a { |
|||
float: right; |
|||
margin-right: 10px; |
|||
margin-top: 7px; |
|||
} |
|||
|
|||
select, |
|||
input { |
|||
width: 100%; |
|||
height: 32px; |
|||
background: rgba(255, 255, 255, 1); |
|||
border-radius: 4px; |
|||
border: 1px solid rgba(217, 217, 217, 1); |
|||
} |
|||
|
|||
select+input { |
|||
width: 260px; |
|||
} |
|||
|
|||
select { |
|||
margin-right: 10px; |
|||
width: 100px; |
|||
} |
|||
|
|||
p.selected_list { |
|||
padding-left: 10px; |
|||
border-radius: 4px; |
|||
min-height: 32px; |
|||
border: 1px solid rgba(217, 217, 217, 1); |
|||
word-break: break-word; |
|||
} |
|||
|
|||
p.check_box { |
|||
line-height: 32px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.el-button { |
|||
margin-bottom: 20px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.condition_list { |
|||
.el-dialog__body { |
|||
padding: 16px 26px; |
|||
} |
|||
|
|||
p { |
|||
color: #666666; |
|||
margin-bottom: 10px; |
|||
|
|||
&>.check_box { |
|||
margin-bottom: 0; |
|||
line-height: 36px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,95 @@ |
|||
<!-- |
|||
* @Date: 2022-08-25 14:05:59 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-16 16:13:48 |
|||
* @FilePath: /Workflow-Vue3/src/components/drawer/copyerDrawer.vue |
|||
--> |
|||
<template> |
|||
<el-drawer :append-to-body="true" title="抄送人设置" v-model="visible" custom-class="set_copyer" :show-close="false" :size="550" :before-close="saveCopyer"> |
|||
<div class="demo-drawer__content"> |
|||
<div class="copyer_content drawer_content"> |
|||
<el-button type="primary" @click="addCopyer">添加成员</el-button> |
|||
<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&©erConfig.nodeUserList.length!=0" @click="copyerConfig.nodeUserList=[]">清除</a> |
|||
</p> |
|||
<el-checkbox-group v-model="ccSelfSelectFlag" class="clear"> |
|||
<el-checkbox :label="1">允许发起人自选抄送人</el-checkbox> |
|||
</el-checkbox-group> |
|||
</div> |
|||
<div class="demo-drawer__footer clear"> |
|||
<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> |
|||
<script setup> |
|||
import employeesRoleDialog from '../dialog/employeesRoleDialog.vue' |
|||
import $func from '@/utils/index' |
|||
import { mapState, mapMutations } from '@/utils/lib.js' |
|||
import { ref, watch, computed } from 'vue' |
|||
let copyerConfig = ref({}) |
|||
let ccSelfSelectFlag = ref([]) |
|||
let copyerVisible = ref(false) |
|||
let checkedList = ref([]) |
|||
let { copyerDrawer, copyerConfig1 } = mapState() |
|||
let visible = computed({ |
|||
get() { |
|||
return copyerDrawer.value |
|||
}, |
|||
set() { |
|||
closeDrawer() |
|||
} |
|||
}) |
|||
let { setCopyerConfig, setCopyer } = mapMutations() |
|||
watch(copyerConfig1, (val) => { |
|||
copyerConfig.value = val.value; |
|||
ccSelfSelectFlag.value = copyerConfig.value.ccSelfSelectFlag == 0 ? [] : [copyerConfig.value.ccSelfSelectFlag] |
|||
}) |
|||
|
|||
const addCopyer = () => { |
|||
copyerVisible.value = true; |
|||
checkedList.value = copyerConfig.value.nodeUserList |
|||
} |
|||
const sureCopyer = (data) => { |
|||
copyerConfig.value.nodeUserList = data; |
|||
copyerVisible.value = false; |
|||
} |
|||
const saveCopyer = () => { |
|||
copyerConfig.value.ccSelfSelectFlag = ccSelfSelectFlag.value.length == 0 ? 0 : 1; |
|||
copyerConfig.value.error = !$func.copyerStr(copyerConfig.value); |
|||
setCopyerConfig({ |
|||
value: copyerConfig.value, |
|||
flag: true, |
|||
id: copyerConfig1.value.id |
|||
}) |
|||
closeDrawer(); |
|||
} |
|||
const closeDrawer = () => { |
|||
setCopyer(false) |
|||
} |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.set_copyer { |
|||
.copyer_content { |
|||
padding: 20px 20px 0; |
|||
|
|||
.el-button { |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.el-checkbox { |
|||
margin-bottom: 20px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,85 @@ |
|||
<!-- |
|||
* @Date: 2022-08-25 14:05:59 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-03-17 16:06:24 |
|||
* @FilePath: /Workflow-Vue3/src/components/drawer/promoterDrawer.vue |
|||
--> |
|||
<template> |
|||
<el-drawer :append-to-body="true" title="发起人" v-model="visible" custom-class="set_promoter" :show-close="false" :size="550" :before-close="savePromoter"> |
|||
<div class="demo-drawer__content"> |
|||
<div class="promoter_content drawer_content"> |
|||
<p>{{ $func.arrToStr(flowPermission) || '所有人' }}</p> |
|||
<el-button type="primary" @click="addPromoter">添加/修改发起人</el-button> |
|||
</div> |
|||
<div class="demo-drawer__footer clear"> |
|||
<el-button type="primary" @click="savePromoter">确 定</el-button> |
|||
<el-button @click="closeDrawer">取 消</el-button> |
|||
</div> |
|||
<employees-dialog |
|||
:isDepartment="true" |
|||
v-model:visible="promoterVisible" |
|||
:data="checkedList" |
|||
@change="surePromoter" |
|||
/> |
|||
</div> |
|||
</el-drawer> |
|||
</template> |
|||
<script setup> |
|||
import employeesDialog from '../dialog/employeesDialog.vue' |
|||
import $func from '@/utils/index' |
|||
import { mapState, mapMutations } from '@/utils/lib' |
|||
import { computed, ref, watch } from 'vue' |
|||
let flowPermission = ref([]) |
|||
let promoterVisible = ref(false) |
|||
let checkedList = ref([]) |
|||
let { promoterDrawer, flowPermission1 } = mapState() |
|||
let visible = computed({ |
|||
get() { |
|||
return promoterDrawer.value |
|||
}, |
|||
set() { |
|||
closeDrawer() |
|||
} |
|||
}) |
|||
watch(flowPermission1, (val) => { |
|||
flowPermission.value = val.value |
|||
}) |
|||
|
|||
let { setPromoter, setFlowPermission } = mapMutations() |
|||
|
|||
const addPromoter = () => { |
|||
checkedList.value = flowPermission.value |
|||
promoterVisible.value = true; |
|||
} |
|||
const surePromoter = (data) => { |
|||
flowPermission.value = data; |
|||
promoterVisible.value = false; |
|||
} |
|||
const savePromoter = () => { |
|||
setFlowPermission({ |
|||
value: flowPermission.value, |
|||
flag: true, |
|||
id: flowPermission1.value.id |
|||
}) |
|||
closeDrawer() |
|||
} |
|||
const closeDrawer = () => { |
|||
setPromoter(false) |
|||
} |
|||
</script> |
|||
<style lang="less"> |
|||
.set_promoter { |
|||
.promoter_content { |
|||
padding: 0 20px; |
|||
.el-button { |
|||
margin-bottom: 20px; |
|||
} |
|||
p { |
|||
padding: 18px 0; |
|||
font-size: 14px; |
|||
line-height: 20px; |
|||
color: #000000; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,311 @@ |
|||
<!-- |
|||
* @Date: 2022-09-21 14:41:53 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2023-04-12 17:48:26 |
|||
* @FilePath: /Workflow-Vue3/src/components/nodeWrap.vue |
|||
--> |
|||
<template> |
|||
<div class="node-wrap" v-if="nodeConfig.type < 3"> |
|||
<div class="node-wrap-box" :class="(nodeConfig.type == 0 ? 'start-node ' : '') +(isTried && nodeConfig.error ? 'active error' : '')"> |
|||
<div class="title" :style="`background: rgb(${bgColors[nodeConfig.type]});`"> |
|||
<span v-if="nodeConfig.type == 0">{{ nodeConfig.nodeName }}</span> |
|||
<template v-else> |
|||
<span class="iconfont">{{nodeConfig.type == 1?'':''}}</span> |
|||
<input |
|||
v-if="isInput" |
|||
type="text" |
|||
class="ant-input editable-title-input" |
|||
@blur="blurEvent()" |
|||
@focus="$event.currentTarget.select()" |
|||
v-focus |
|||
v-model="nodeConfig.nodeName" |
|||
:placeholder="defaultText" |
|||
/> |
|||
<span v-else class="editable-title" @click="clickEvent()">{{ nodeConfig.nodeName }}</span> |
|||
<i class="anticon anticon-close close" @click="delNode"></i> |
|||
</template> |
|||
</div> |
|||
<div class="content" @click="setPerson"> |
|||
<div class="text"> |
|||
<span class="placeholder" v-if="!showText">请选择{{defaultText}}</span> |
|||
{{showText}} |
|||
</div> |
|||
<i class="anticon anticon-right arrow"></i> |
|||
</div> |
|||
<div class="error_tip" v-if="isTried && nodeConfig.error"> |
|||
<i class="anticon anticon-exclamation-circle"></i> |
|||
</div> |
|||
</div> |
|||
<addNode v-model:childNodeP="nodeConfig.childNode" /> |
|||
</div> |
|||
<div class="branch-wrap" v-if="nodeConfig.type == 4"> |
|||
<div class="branch-box-wrap"> |
|||
<div class="branch-box"> |
|||
<button class="add-branch" @click="addTerm">添加条件</button> |
|||
<div class="col-box" v-for="(item, index) in nodeConfig.conditionNodes" :key="index"> |
|||
<div class="condition-node"> |
|||
<div class="condition-node-box"> |
|||
<div class="auto-judge" :class="isTried && item.error ? 'error active' : ''"> |
|||
<div class="sort-left" v-if="index != 0" @click="arrTransfer(index, -1)"><</div> |
|||
<div class="title-wrapper"> |
|||
<input |
|||
v-if="isInputList[index]" |
|||
type="text" |
|||
class="ant-input editable-title-input" |
|||
@blur="blurEvent(index)" |
|||
@focus="$event.currentTarget.select()" |
|||
v-focus |
|||
v-model="item.nodeName" |
|||
/> |
|||
<span v-else class="editable-title" @click="clickEvent(index)">{{ item.nodeName }}</span> |
|||
<span class="priority-title" @click="setPerson(item.priorityLevel)">优先级{{ item.priorityLevel }}</span> |
|||
<i class="anticon anticon-close close" @click="delTerm(index)"></i> |
|||
</div> |
|||
<div class="sort-right" v-if="index != nodeConfig.conditionNodes.length - 1" @click="arrTransfer(index)">></div> |
|||
<div class="content" @click="setPerson(item.priorityLevel)">{{ $func.conditionStr(nodeConfig, index) }}</div> |
|||
<div class="error_tip" v-if="isTried && item.error"> |
|||
<i class="anticon anticon-exclamation-circle"></i> |
|||
</div> |
|||
</div> |
|||
<addNode v-model:childNodeP="item.childNode" /> |
|||
</div> |
|||
</div> |
|||
<nodeWrap v-if="item.childNode" v-model:nodeConfig="item.childNode" /> |
|||
<template v-if="index == 0"> |
|||
<div class="top-left-cover-line"></div> |
|||
<div class="bottom-left-cover-line"></div> |
|||
</template> |
|||
<template v-if="index == nodeConfig.conditionNodes.length - 1"> |
|||
<div class="top-right-cover-line"></div> |
|||
<div class="bottom-right-cover-line"></div> |
|||
</template> |
|||
</div> |
|||
</div> |
|||
<addNode v-model:childNodeP="nodeConfig.childNode" /> |
|||
</div> |
|||
</div> |
|||
<nodeWrap v-if="nodeConfig.childNode" v-model:nodeConfig="nodeConfig.childNode"/> |
|||
</template> |
|||
<script setup> |
|||
import { onMounted, ref, watch, getCurrentInstance, computed } from "vue"; |
|||
import $func from "@/utils/index"; |
|||
import { mapState, mapMutations } from "@/utils/lib"; |
|||
import { bgColors, placeholderList } from '@/utils/const' |
|||
let _uid = getCurrentInstance().uid; |
|||
|
|||
let props = defineProps({ |
|||
nodeConfig: { |
|||
type: Object, |
|||
default: () => ({}), |
|||
}, |
|||
flowPermission: { |
|||
type: Object, |
|||
default: () => [], |
|||
}, |
|||
}); |
|||
|
|||
let defaultText = computed(() => { |
|||
return placeholderList[props.nodeConfig.type] |
|||
}); |
|||
let showText = computed(() => { |
|||
if (props.nodeConfig.type == 0) return $func.arrToStr(props.flowPermission) || '所有人' |
|||
if (props.nodeConfig.type == 1) return $func.setApproverStr(props.nodeConfig) |
|||
return $func.copyerStr(props.nodeConfig) |
|||
}); |
|||
|
|||
let isInputList = ref([]); |
|||
let isInput = ref(false); |
|||
const resetConditionNodesErr = () => { |
|||
for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) { |
|||
props.nodeConfig.conditionNodes[i].error = $func.conditionStr(props.nodeConfig, i) == "请设置条件" && i != props.nodeConfig.conditionNodes.length - 1; |
|||
} |
|||
} |
|||
onMounted(() => { |
|||
if (props.nodeConfig.type == 1) { |
|||
props.nodeConfig.error = !$func.setApproverStr(props.nodeConfig); |
|||
} else if (props.nodeConfig.type == 2) { |
|||
props.nodeConfig.error = !$func.copyerStr(props.nodeConfig); |
|||
} else if (props.nodeConfig.type == 4) { |
|||
resetConditionNodesErr() |
|||
} |
|||
}); |
|||
let emits = defineEmits(["update:flowPermission", "update:nodeConfig"]); |
|||
let { |
|||
isTried, |
|||
flowPermission1, |
|||
approverConfig1, |
|||
copyerConfig1, |
|||
conditionsConfig1, |
|||
} = mapState(); |
|||
watch(flowPermission1, (flow) => { |
|||
if (flow.flag && flow.id === _uid) { |
|||
emits("update:flowPermission", flow.value); |
|||
} |
|||
}); |
|||
watch(approverConfig1, (approver) => { |
|||
if (approver.flag && approver.id === _uid) { |
|||
emits("update:nodeConfig", approver.value); |
|||
} |
|||
}); |
|||
watch(copyerConfig1, (copyer) => { |
|||
if (copyer.flag && copyer.id === _uid) { |
|||
emits("update:nodeConfig", copyer.value); |
|||
} |
|||
}); |
|||
watch(conditionsConfig1, (condition) => { |
|||
if (condition.flag && condition.id === _uid) { |
|||
emits("update:nodeConfig", condition.value); |
|||
} |
|||
}); |
|||
let { |
|||
setPromoter, |
|||
setApprover, |
|||
setCopyer, |
|||
setCondition, |
|||
setFlowPermission, |
|||
setApproverConfig, |
|||
setCopyerConfig, |
|||
setConditionsConfig, |
|||
} = mapMutations(); |
|||
const clickEvent = (index) => { |
|||
if (index || index === 0) { |
|||
isInputList.value[index] = true; |
|||
} else { |
|||
isInput.value = true; |
|||
} |
|||
}; |
|||
const blurEvent = (index) => { |
|||
if (index || index === 0) { |
|||
isInputList.value[index] = false; |
|||
props.nodeConfig.conditionNodes[index].nodeName = props.nodeConfig.conditionNodes[index].nodeName || "条件"; |
|||
} else { |
|||
isInput.value = false; |
|||
props.nodeConfig.nodeName = props.nodeConfig.nodeName || defaultText |
|||
} |
|||
}; |
|||
const delNode = () => { |
|||
emits("update:nodeConfig", props.nodeConfig.childNode); |
|||
}; |
|||
const addTerm = () => { |
|||
let len = props.nodeConfig.conditionNodes.length + 1; |
|||
props.nodeConfig.conditionNodes.push({ |
|||
nodeName: "条件" + len, |
|||
type: 3, |
|||
priorityLevel: len, |
|||
conditionList: [], |
|||
nodeUserList: [], |
|||
childNode: null, |
|||
}); |
|||
resetConditionNodesErr() |
|||
emits("update:nodeConfig", props.nodeConfig); |
|||
}; |
|||
const delTerm = (index) => { |
|||
props.nodeConfig.conditionNodes.splice(index, 1); |
|||
props.nodeConfig.conditionNodes.map((item, index) => { |
|||
item.priorityLevel = index + 1; |
|||
item.nodeName = `条件${index + 1}`; |
|||
}); |
|||
resetConditionNodesErr() |
|||
emits("update:nodeConfig", props.nodeConfig); |
|||
if (props.nodeConfig.conditionNodes.length == 1) { |
|||
if (props.nodeConfig.childNode) { |
|||
if (props.nodeConfig.conditionNodes[0].childNode) { |
|||
reData(props.nodeConfig.conditionNodes[0].childNode, props.nodeConfig.childNode); |
|||
} else { |
|||
props.nodeConfig.conditionNodes[0].childNode = props.nodeConfig.childNode; |
|||
} |
|||
} |
|||
emits("update:nodeConfig", props.nodeConfig.conditionNodes[0].childNode); |
|||
} |
|||
}; |
|||
const reData = (data, addData) => { |
|||
if (!data.childNode) { |
|||
data.childNode = addData; |
|||
} else { |
|||
reData(data.childNode, addData); |
|||
} |
|||
}; |
|||
const setPerson = (priorityLevel) => { |
|||
var { type } = props.nodeConfig; |
|||
if (type == 0) { |
|||
setPromoter(true); |
|||
setFlowPermission({ |
|||
value: props.flowPermission, |
|||
flag: false, |
|||
id: _uid, |
|||
}); |
|||
} else if (type == 1) { |
|||
setApprover(true); |
|||
setApproverConfig({ |
|||
value: { |
|||
...JSON.parse(JSON.stringify(props.nodeConfig)), |
|||
...{ settype: props.nodeConfig.settype ? props.nodeConfig.settype : 1 }, |
|||
}, |
|||
flag: false, |
|||
id: _uid, |
|||
}); |
|||
} else if (type == 2) { |
|||
setCopyer(true); |
|||
setCopyerConfig({ |
|||
value: JSON.parse(JSON.stringify(props.nodeConfig)), |
|||
flag: false, |
|||
id: _uid, |
|||
}); |
|||
} else { |
|||
setCondition(true); |
|||
setConditionsConfig({ |
|||
value: JSON.parse(JSON.stringify(props.nodeConfig)), |
|||
priorityLevel, |
|||
flag: false, |
|||
id: _uid, |
|||
}); |
|||
} |
|||
}; |
|||
const arrTransfer = (index, type = 1) => { |
|||
//向左-1,向右1 |
|||
props.nodeConfig.conditionNodes[index] = props.nodeConfig.conditionNodes.splice( |
|||
index + type, |
|||
1, |
|||
props.nodeConfig.conditionNodes[index] |
|||
)[0]; |
|||
props.nodeConfig.conditionNodes.map((item, index) => { |
|||
item.priorityLevel = index + 1; |
|||
}); |
|||
resetConditionNodesErr() |
|||
emits("update:nodeConfig", props.nodeConfig); |
|||
}; |
|||
</script> |
|||
<style> |
|||
.error_tip { |
|||
position: absolute; |
|||
top: 0px; |
|||
right: 0px; |
|||
transform: translate(150%, 0px); |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.promoter_person .el-dialog__body { |
|||
padding: 10px 20px 14px 20px; |
|||
} |
|||
|
|||
.selected_list { |
|||
margin-bottom: 20px; |
|||
line-height: 30px; |
|||
} |
|||
|
|||
.selected_list span { |
|||
margin-right: 10px; |
|||
padding: 3px 6px 3px 9px; |
|||
line-height: 12px; |
|||
white-space: nowrap; |
|||
border-radius: 2px; |
|||
border: 1px solid rgba(220, 220, 220, 1); |
|||
} |
|||
|
|||
.selected_list img { |
|||
margin-left: 5px; |
|||
width: 7px; |
|||
height: 7px; |
|||
cursor: pointer; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,82 @@ |
|||
<!-- |
|||
* @Date: 2022-08-26 17:18:14 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2022-09-21 14:36:25 |
|||
* @FilePath: /Workflow-Vue3/src/components/selectBox.vue |
|||
--> |
|||
<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="{active: elem.isActive && elem.isActive(item), not: elem.not}" |
|||
@click="elem.change(item)"> |
|||
<a :title="item.description" :class="{active: elem.isActiveItem && elem.isActiveItem(item)}"> |
|||
<img src="@/assets/images/icon_role.png">{{item.roleName}} |
|||
</a> |
|||
</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> |
|||
</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 src="@/assets/images/icon_people.png">{{item.employeeName}} |
|||
</a> |
|||
</li> |
|||
</template> |
|||
</template> |
|||
</ul> |
|||
</template> |
|||
<script setup> |
|||
defineProps({ |
|||
list: { |
|||
type: Array, |
|||
default: () => [] |
|||
} |
|||
}) |
|||
</script> |
|||
<style lang="less"> |
|||
.select-box { |
|||
height: 420px; |
|||
overflow-y: auto; |
|||
|
|||
li { |
|||
padding: 5px 0; |
|||
|
|||
i { |
|||
float: right; |
|||
padding-left: 24px; |
|||
padding-right: 10px; |
|||
color: #3195f8; |
|||
font-size: 12px; |
|||
cursor: pointer; |
|||
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); |
|||
pointer-events: none; |
|||
} |
|||
|
|||
img { |
|||
width: 14px; |
|||
vertical-align: middle; |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,98 @@ |
|||
<!-- |
|||
* @Date: 2022-08-26 16:29:24 |
|||
* @LastEditors: StavinLi 495727881@qq.com |
|||
* @LastEditTime: 2022-09-21 14:36:30 |
|||
* @FilePath: /Workflow-Vue3/src/components/selectResult.vue |
|||
--> |
|||
<template> |
|||
<div class="select-result l"> |
|||
<p class="clear">已选({{total}}) |
|||
<a @click="emits('del')">清空</a> |
|||
</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"> |
|||
<span>{{item.roleName}}</span> |
|||
<img src="@/assets/images/cancel.png" @click="cancel(item)"> |
|||
</li> |
|||
</template> |
|||
<template v-if="type === 'department'"> |
|||
<li v-for="item in data" :key="item.id"> |
|||
<img src="@/assets/images/icon_file.png"> |
|||
<span>{{item.departmentName}}</span> |
|||
<img src="@/assets/images/cancel.png" @click="cancel(item)"> |
|||
</li> |
|||
</template> |
|||
<template v-if="type === 'employee'"> |
|||
<li v-for="item in data" :key="item.id"> |
|||
<img src="@/assets/images/icon_people.png"> |
|||
<span>{{item.employeeName}}</span> |
|||
<img src="@/assets/images/cancel.png" @click="cancel(item)"> |
|||
</li> |
|||
</template> |
|||
</template> |
|||
</ul> |
|||
</div> |
|||
</template> |
|||
<script setup> |
|||
defineProps({ |
|||
total: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
list: { |
|||
type: Array, |
|||
default: () => [{ type: 'role', data, cancel }] |
|||
} |
|||
}) |
|||
let emits = defineEmits(['del']) |
|||
</script> |
|||
|
|||
<style lang="less"> |
|||
.select-result { |
|||
width: 276px; |
|||
height: 100%; |
|||
font-size: 12px; |
|||
|
|||
ul { |
|||
height: 460px; |
|||
overflow-y: auto; |
|||
|
|||
li { |
|||
margin: 11px 26px 13px 19px; |
|||
line-height: 17px; |
|||
|
|||
span { |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
img { |
|||
&:first-of-type { |
|||
width: 14px; |
|||
vertical-align: middle; |
|||
margin-right: 5px; |
|||
} |
|||
|
|||
&:last-of-type { |
|||
float: right; |
|||
margin-top: 2px; |
|||
width: 14px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
p { |
|||
padding-left: 19px; |
|||
padding-right: 20px; |
|||
line-height: 37px; |
|||
border-bottom: 1px solid #f2f2f2; |
|||
|
|||
a { |
|||
float: right; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,23 @@ |
|||
import Layout from "@/layout/index.vue"; |
|||
|
|||
const workflowRouter = [{ |
|||
path: '/workflow', |
|||
component: Layout, |
|||
redirect: '/workflow', |
|||
name: 'workflow', |
|||
meta: { |
|||
title: '工作流', |
|||
icon: 'School' |
|||
}, |
|||
children: [ |
|||
{ |
|||
path: 'workflow', |
|||
component: () => import('@/views/workflow/index.vue'), |
|||
name: 'work-flow', |
|||
meta: { title: '工作流', keepAlive: true , icon: 'MenuIcon'} |
|||
}, |
|||
|
|||
] |
|||
}] |
|||
|
|||
export default workflowRouter |
|||
@ -0,0 +1,14 @@ |
|||
<!-- |
|||
@ 作者: 秦东 |
|||
@ 时间: 2023-05-09 15:22:33 |
|||
@ 备注: |
|||
--> |
|||
<template> |
|||
|
|||
</template> |
|||
<script lang='ts' setup> |
|||
|
|||
</script> |
|||
<style lang='scss' scoped> |
|||
|
|||
</style> |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue