Compare commits
5 Commits
3153f5f9b9
...
72fd575dde
| Author | SHA1 | Date |
|---|---|---|
|
|
72fd575dde | |
|
|
74fbae3095 | |
|
|
b271979372 | |
|
|
dabdc0551e | |
|
|
8df27644fb |
|
|
@ -34,6 +34,14 @@ export function getDepartmentTree() {
|
|||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
getOrgTree, getUserByName, getRole,getDepartmentTree
|
||||
//根据角色或者部门获取到对应的数据
|
||||
export function getUserTree(type,chooseId){
|
||||
return request({
|
||||
url:`/admin/user/choose/${type}/${chooseId}`,
|
||||
method:'get'
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
getOrgTree, getUserByName, getRole,getDepartmentTree,getUserTree
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Vue.prototype.$axios = axios;
|
|||
|
||||
export function getBaseUrl(){
|
||||
return "http://gateway.mytwins.top"
|
||||
// return "http://192.168.101.7:8000"
|
||||
// return "http://localhost:8000"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,25 +5,40 @@
|
|||
<div class="candidate" v-loading="loading">
|
||||
<div style="padding: 5px 8px;">
|
||||
<el-input v-model="filterText" style="width: 100%;" size="small"
|
||||
clearable placeholder="输入关键字进行过滤" prefix-icon="el-icon-search" />
|
||||
clearable placeholder="输入关键字进行过滤" prefix-icon="el-icon-search"/>
|
||||
<div style="margin-top: 5px">
|
||||
<el-button size="mini" type="primary" plain style="padding:4px 6px;">人员</el-button>
|
||||
<el-button size="mini" type="primary" plain style="padding:4px 6px;">部门</el-button>
|
||||
<el-radio-group v-model="radio" size="mini" @input="radioChange">
|
||||
<el-radio-button :label="0">角色</el-radio-button>
|
||||
<el-radio-button :label="1">部门</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 人员选择 -->
|
||||
<el-empty :image-size="100" description="似乎没有数据" v-show="deptList.length === 0"/>
|
||||
<el-scrollbar style="height:350px">
|
||||
<el-tree :data="deptList" ref="tree" :props="deptProps" empty-text="" node-key="value" default-expand-all
|
||||
:show-checkbox="showCheckbox" highlight-current :check-strictly="multiple===false"
|
||||
@check-change="handleCheckChange" @node-click="(node,check)=>handle(node,check)"
|
||||
:filter-node-method="filterNode">
|
||||
<div class="custom-tree-node" slot-scope="{ node }" style="width: 100%">
|
||||
<i class="el-icon-folder-opened" style="margin-right: 5px"></i>{{ node.label }}
|
||||
<el-empty :image-size="100" description="似乎没有数据" v-show="dataList.length === 0"/>
|
||||
<el-scrollbar style="height:317px">
|
||||
<el-tree :data="dataList" ref="tree" :props="defaultProps" empty-text="" node-key="value"
|
||||
:default-expanded-keys="expandedKeys"
|
||||
@node-click="handleChange"
|
||||
:filter-node-method="filterNode"
|
||||
>
|
||||
<div class="tree-node" slot-scope="{ node,data }">
|
||||
<div v-if="data.type === 0" style="display: flex;align-items: center">
|
||||
<el-avatar :src="data.avatar"></el-avatar>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div v-else-if="data.type === 1">
|
||||
<el-icon class="el-icon-user-solid"/>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-icon class="el-icon-folder-opened"/>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
</div>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
|
||||
<div class="selected">
|
||||
<div class="count">
|
||||
<span>已选 {{ selectList.length }} 项</span>
|
||||
|
|
@ -32,9 +47,9 @@
|
|||
<div class="org-items" style="height: 350px;">
|
||||
<el-empty :image-size="100" description="请点击左侧列表选择数据" v-show="selectList.length === 0"/>
|
||||
<div v-for="(selectItem, selectIndex) in selectList" :key="selectIndex" class="org-item">
|
||||
<i class="el-icon-folder-opened"></i>
|
||||
<span>{{ selectItem.label }}</span>
|
||||
<i class="el-icon-close" @click="noSelected(selectItem)" v-if="showCheckbox===false"></i>
|
||||
<el-avatar :src="selectItem.avatar" style="margin-right: 5px;"></el-avatar>
|
||||
{{ selectItem.name }}
|
||||
<i class="el-icon-close" @click="noSelected(selectItem)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -44,10 +59,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getDepartmentTree} from "@/api/org";
|
||||
import {getUserTree} from "@/api/org";
|
||||
|
||||
export default {
|
||||
name: "departmentPicker",
|
||||
name: "Test",
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
|
|
@ -66,16 +81,24 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
radio: 0,
|
||||
chooseId: 0,
|
||||
selectItem: {
|
||||
type: -1,
|
||||
value: '0',
|
||||
},
|
||||
activeNames: ['1'],
|
||||
visible: false,
|
||||
loading: false,
|
||||
title: "请选择",
|
||||
selectList: [],
|
||||
filterText: "",
|
||||
deptList: [],
|
||||
deptProps: {
|
||||
dataList: [],
|
||||
expandedKeys: [],
|
||||
defaultProps: {
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
children: 'children'
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
@ -84,9 +107,6 @@ export default {
|
|||
this.$refs.tree.filter(val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getDepartmentTree();
|
||||
},
|
||||
computed: {
|
||||
_value: {
|
||||
get() {
|
||||
|
|
@ -98,111 +118,77 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
//获取部门信息
|
||||
getDepartmentTree() {
|
||||
getDepartmentTree().then(res => {
|
||||
// const jsona = JSON.stringify(res.data) // 把接口返回的res.data数据转成字符串
|
||||
// const jsonb = jsona.replace(/"value"/g, '"deptId"') // 修改成你要的字段
|
||||
// const jsonc = jsonb.replace(/"label"/g, '"deptName"')
|
||||
this.deptList = res.data
|
||||
// console.log("获取部门信息===========", this.deptList);
|
||||
radioChange(e) {
|
||||
this.selectItem.type = -2
|
||||
this.chooseId = 0
|
||||
this.radio = e
|
||||
this.expandedKeys = []
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
getUserTree(this.radio, this.chooseId).then(res => {
|
||||
if (res.data) {
|
||||
if (this.selectItem.type === -1 || this.selectItem.type === -2) {
|
||||
this.dataList = this.setData(res.data)
|
||||
} else if (this.selectItem.type === 1) {
|
||||
this.selectItem.children = res.data
|
||||
} else if (this.selectItem.type === 2) {
|
||||
this.selectItem.children = this.setData(res.data)
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
setData(source) {
|
||||
for (let item of source) {
|
||||
this.$set(item, "value", this.selectItem.value + "-" + item.id)
|
||||
this.$set(item, "children", [])
|
||||
}
|
||||
return source;
|
||||
},
|
||||
//通过关键字过滤树节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.deptName.indexOf(value) !== -1;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
},
|
||||
//用于弹开部门选择
|
||||
//用于用户选择
|
||||
showUserPicker() {
|
||||
this.getList();
|
||||
this.visible = true;
|
||||
},
|
||||
/**
|
||||
* 选中部门
|
||||
* @param data 选择的每个节点item
|
||||
* @param checked 是否选中
|
||||
*/
|
||||
handleCheckChange(data, checked) {
|
||||
// 左侧有选择框
|
||||
if (this.showCheckbox) {
|
||||
// 左侧有选择框 + 多选
|
||||
if (this.multiple ) {
|
||||
//不添加重复的数据到右边
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].value === data.value) {
|
||||
this.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checked) {
|
||||
if(data.children === undefined){
|
||||
this.selectList.push(data);
|
||||
}
|
||||
} else if (data === '1') {
|
||||
this.$refs.tree.setCheckedKeys([]);
|
||||
this.selectList = [];
|
||||
}
|
||||
} else {// 左侧有选择框 + 单选
|
||||
//不添加重复的数据到右边
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].value === data.value) {
|
||||
this.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checked) {
|
||||
this.$refs.tree.setCheckedNodes([data]);
|
||||
// this.$refs.tree.setCheckedKeys([]);
|
||||
this.selectList = [data];
|
||||
} else if (data === '1') {
|
||||
this.selectList = [];
|
||||
this.$refs.tree.setCheckedKeys([]);
|
||||
}
|
||||
}
|
||||
//渲染子节点用户或部门及用户数据
|
||||
handleChange(item, check) {
|
||||
this.selectItem = item
|
||||
this.expandedKeys.push(item.value)
|
||||
if (item.type !== 0) {
|
||||
this.chooseId = item.id
|
||||
this.getList()
|
||||
}
|
||||
this._value = this.selectList
|
||||
},
|
||||
|
||||
//左侧没有选择框时,点击tree-item
|
||||
/**
|
||||
* 可以点击树节点deptName,进行选择
|
||||
* @param node 选择的每个节点item
|
||||
* @param check checked(checkbox选择框)是否选中
|
||||
*/
|
||||
handle(node, check) {
|
||||
if (check.isLeaf !== false) {
|
||||
if (!item.children) {
|
||||
if (this.multiple) {
|
||||
//不添加重复的数据到右边
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].value === node.value) {
|
||||
if (this.selectList[i].id === item.id) {
|
||||
this.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
check.checked = true
|
||||
this.selectList.push(node);
|
||||
this.selectList.push(item);
|
||||
console.log('多选this.selectList', this.selectList);
|
||||
} else {
|
||||
check.checked = true
|
||||
this.selectList = [node];
|
||||
this.selectList = [item];
|
||||
}
|
||||
}
|
||||
this._value = this.selectList
|
||||
},
|
||||
//左侧无选择框时,右侧显示×
|
||||
//右侧的×
|
||||
noSelected(selectItem) {
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].value === selectItem.value) {
|
||||
this.selectList.splice(i, 1);
|
||||
this.$refs.tree.setCheckedKeys(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.showCheckbox) {
|
||||
// 左侧有选择框 + 单选
|
||||
if (this.multiple === false) {
|
||||
this.$refs.tree.setCheckedKeys([]);
|
||||
}
|
||||
}
|
||||
selectItem.selected = false;
|
||||
},
|
||||
//清空
|
||||
clearSelected() {
|
||||
|
|
@ -211,11 +197,7 @@ export default {
|
|||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
if (!this.showCheckbox) {
|
||||
this.selectList = []
|
||||
}else {
|
||||
this.handleCheckChange("1");
|
||||
}
|
||||
this.selectList = []
|
||||
});
|
||||
},
|
||||
//确定按钮
|
||||
|
|
@ -229,16 +211,33 @@ export default {
|
|||
|
||||
<style lang="less" scoped>
|
||||
@containWidth: 278px;
|
||||
/deep/ .el-tree-node {
|
||||
.el-tree-node__children {
|
||||
.el-tree-node__content {
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///deep/ .el-tree-node {
|
||||
// .is-leaf + .el-checkbox .el-checkbox__inner {
|
||||
// display: inline-block;
|
||||
// }
|
||||
//
|
||||
// .el-checkbox .el-checkbox__inner {
|
||||
// display: none;
|
||||
// }
|
||||
//}
|
||||
.tree-node {
|
||||
div {
|
||||
.el-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .el-tree-node {
|
||||
.is-leaf + .el-checkbox .el-checkbox__inner {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.el-checkbox .el-checkbox__inner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .el-dialog__body {
|
||||
padding: 10px 20px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,331 @@
|
|||
<template>
|
||||
<w-dialog :border="false" closeFree width="600px" @ok="selectConfirm" :title="title" v-model="visible">
|
||||
<div>
|
||||
<div class="picker">
|
||||
<div class="candidate" v-loading="loading">
|
||||
<div style="padding: 5px 8px;">
|
||||
<el-input v-model="filterText" style="width: 100%;" size="small"
|
||||
clearable placeholder="输入关键字进行过滤" prefix-icon="el-icon-search"/>
|
||||
<div style="margin-top: 5px">
|
||||
<el-radio-group v-model="radio" size="mini" @input="radioChange">
|
||||
<el-radio-button :label="0">角色</el-radio-button>
|
||||
<el-radio-button :label="1">部门</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 人员选择 -->
|
||||
<el-empty :image-size="100" description="似乎没有数据" v-show="dataList.length === 0"/>
|
||||
<el-scrollbar style="height:317px">
|
||||
<el-tree :data="dataList" ref="tree" :props="defaultProps" empty-text="" node-key="value"
|
||||
:default-expanded-keys="expandedKeys"
|
||||
@node-click="handleChange"
|
||||
:filter-node-method="filterNode"
|
||||
>
|
||||
<div class="tree-node" slot-scope="{ node,data }">
|
||||
<div v-if="data.type === 0" style="display: flex;align-items: center">
|
||||
<el-avatar :src="data.avatar"></el-avatar>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div v-else-if="data.type === 1">
|
||||
<el-icon class="el-icon-user-solid"/>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-icon class="el-icon-folder-opened"/>
|
||||
{{ node.label }}
|
||||
</div>
|
||||
</div>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
|
||||
<div class="selected">
|
||||
<div class="count">
|
||||
<span>已选 {{ selectList.length }} 项</span>
|
||||
<span @click="clearSelected">清空</span>
|
||||
</div>
|
||||
<div class="org-items" style="height: 350px;">
|
||||
<el-empty :image-size="100" description="请点击左侧列表选择数据" v-show="selectList.length === 0"/>
|
||||
<div v-for="(selectItem, selectIndex) in selectList" :key="selectIndex" class="org-item">
|
||||
<el-avatar :src="selectItem.avatar" style="margin-right: 5px;"></el-avatar>
|
||||
{{ selectItem.name }}
|
||||
<i class="el-icon-close" @click="noSelected(selectItem)"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</w-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getUserTree} from "@/api/org";
|
||||
|
||||
export default {
|
||||
name: "UserPicker",
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
multiple: { //是否多选
|
||||
default: true,
|
||||
type: Boolean
|
||||
},
|
||||
showCheckbox: { //是否显示左侧选择框
|
||||
default: true,
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
radio: 0,
|
||||
chooseId: 0,
|
||||
selectItem: {
|
||||
type: -1,
|
||||
value: '0',
|
||||
},
|
||||
activeNames: ['1'],
|
||||
visible: false,
|
||||
loading: false,
|
||||
title: "请选择",
|
||||
selectList: [],
|
||||
filterText: "",
|
||||
dataList: [],
|
||||
expandedKeys: [],
|
||||
defaultProps: {
|
||||
value: 'value',
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
filterText(val) {
|
||||
this.$refs.tree.filter(val);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_value: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit("input", val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
radioChange(e) {
|
||||
this.selectItem.type = -2
|
||||
this.chooseId = 0
|
||||
this.radio = e
|
||||
this.expandedKeys = []
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
getUserTree(this.radio, this.chooseId).then(res => {
|
||||
if (res.data) {
|
||||
if (this.selectItem.type === -1 || this.selectItem.type === -2) {
|
||||
this.dataList = this.setData(res.data)
|
||||
} else if (this.selectItem.type === 1) {
|
||||
this.selectItem.children = res.data
|
||||
} else if (this.selectItem.type === 2) {
|
||||
this.selectItem.children = this.setData(res.data)
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
setData(source) {
|
||||
for (let item of source) {
|
||||
this.$set(item, "value", this.selectItem.value + "-" + item.id)
|
||||
this.$set(item, "children", [])
|
||||
}
|
||||
return source;
|
||||
},
|
||||
//通过关键字过滤树节点
|
||||
filterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
},
|
||||
//用于用户选择
|
||||
showUserPicker() {
|
||||
this.getList();
|
||||
this.visible = true;
|
||||
},
|
||||
//渲染子节点用户或部门及用户数据
|
||||
handleChange(item, check) {
|
||||
this.selectItem = item
|
||||
this.expandedKeys.push(item.value)
|
||||
if (item.type !== 0) {
|
||||
this.chooseId = item.id
|
||||
this.getList()
|
||||
}
|
||||
if (!item.children) {
|
||||
if (this.multiple) {
|
||||
//不添加重复的数据到右边
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].id === item.id) {
|
||||
this.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.selectList.push(item);
|
||||
} else {
|
||||
this.selectList = [item];
|
||||
}
|
||||
}
|
||||
// this._value = this.selectList
|
||||
},
|
||||
//右侧的×
|
||||
noSelected(selectItem) {
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].value === selectItem.value) {
|
||||
this.selectList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectItem.selected = false;
|
||||
},
|
||||
//清空
|
||||
clearSelected() {
|
||||
this.$confirm("您确定要清空已选中的项?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.selectList = []
|
||||
});
|
||||
},
|
||||
//确定按钮
|
||||
selectConfirm() {
|
||||
this.$emit("ok", this.selectList);
|
||||
this.visible = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@containWidth: 278px;
|
||||
/deep/ .el-tree-node {
|
||||
.el-tree-node__children {
|
||||
.el-tree-node__content {
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-node {
|
||||
div {
|
||||
.el-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .el-tree-node {
|
||||
.is-leaf + .el-checkbox .el-checkbox__inner {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.el-checkbox .el-checkbox__inner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .el-dialog__body {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.picker {
|
||||
height: 402px;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
|
||||
.candidate {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.candidate, .selected {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
width: @containWidth;
|
||||
height: 400px;
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.selected {
|
||||
border-left: none;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
.count {
|
||||
width: calc(@containWidth - 20px);
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
margin-bottom: 5px;
|
||||
|
||||
& > span:nth-child(2) {
|
||||
float: right;
|
||||
color: #c75450;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.org-items {
|
||||
overflow-y: auto;
|
||||
height: 350px;
|
||||
|
||||
.el-icon-close {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
cursor: pointer;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.org-item {
|
||||
margin: 0 5px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
padding: 7px 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .el-scrollbar .el-scrollbar__wrap {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
float: right;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 16px;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -8,6 +8,7 @@ export default new Vuex.Store({
|
|||
state: {
|
||||
nodeMap: new Map(),
|
||||
parentMap: new Map(),
|
||||
selectUserMap: new Map(),
|
||||
isEdit: null,
|
||||
selectedNode: {},
|
||||
selectFormItem: null,
|
||||
|
|
@ -29,7 +30,11 @@ export default new Vuex.Store({
|
|||
state.isEdit = val
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
getters: {
|
||||
selectedNode(){
|
||||
return state.selectedNode
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
modules: {}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
<script>
|
||||
import ProcessTree from './process/ProcessTree.vue'
|
||||
// import ProcessTree from './process/ProcessTreeBack.vue'
|
||||
import NodeConfig from '../../common/process/config/NodeConfig'
|
||||
//流程设计器
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
<el-main>
|
||||
<div class="design" :style="'transform: scale('+ scale / 100 +');'">
|
||||
<process-tree ref="process-tree-view"/>
|
||||
<process-tree ref="process-tree"/>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
|
|
@ -34,6 +34,21 @@ export default {
|
|||
},
|
||||
beforeDestroy() {
|
||||
this.$store.state.diagramMode = "design";
|
||||
},
|
||||
methods:{
|
||||
//校验数据配置的合法性
|
||||
validate() {
|
||||
return this.$refs["process-tree"].validateProcess()
|
||||
},
|
||||
validate_ASSIGN_USER(err) {
|
||||
if (this.config.props.assignedUser.length > 0) {
|
||||
return true;
|
||||
} else {
|
||||
this.errorInfo = '请指定审批人员'
|
||||
err.push(`${this.config.name} 未指定审批人员`)
|
||||
return false
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<!--todo 预览时渲染的component-->
|
||||
<component ref="form" :is="config.name" :mode="mode" :perm="perm" v-model="_value" v-bind="config.props"/>
|
||||
<component ref="form" :is="config.name" :config="config" :mode="mode" :perm="perm" v-model="_value" v-bind="config.props"/>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
|
|
|
|||
|
|
@ -261,6 +261,7 @@ export default {
|
|||
},
|
||||
//选中一个节点
|
||||
selectNode(node) {
|
||||
console.log(node)
|
||||
this.$store.commit('selectedNode', node)
|
||||
console.log(node, "node")
|
||||
if (!this.isConcurrentNode(node)) {
|
||||
|
|
|
|||
|
|
@ -2,39 +2,50 @@
|
|||
<div style="max-width: 350px">
|
||||
<template v-if="mode === 'DESIGN'">
|
||||
<el-button disabled icon="el-icon-user" type="primary" size="mini" round>选择人员</el-button>
|
||||
<span class="placeholder"> {{placeholder}}</span>
|
||||
<span class="placeholder"> {{ placeholder }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-if="perm === 'E'">
|
||||
<el-button icon="el-icon-user" type="primary" size="mini" round @click="$refs.userPicker.showUserPicker()">选择人员</el-button>
|
||||
<org-picker type="user" :multiple="multiple" ref="userPicker" :selected="_value" @ok="selected"/>
|
||||
<span class="placeholder"> {{placeholder}}</span>
|
||||
<div style="margin-top: 5px">
|
||||
<el-tag size="mini" style="margin: 5px" closable v-for="(user, i) in _value" :key="i" @close="delDept(i)">{{user.label}}</el-tag>
|
||||
<el-button icon="el-icon-user" type="primary" size="mini" round @click="$refs.userPicker.showUserPicker()">
|
||||
选择人员
|
||||
</el-button>
|
||||
<user-select type="user" :multiple="multiple" ref="userPicker" :selected="_value" @ok="selected"/>
|
||||
<span class="placeholder"> {{ placeholder }}</span>
|
||||
<div style="display: flex;">
|
||||
<div class="userStyle" v-for="(user, i) in _value" :key="i">
|
||||
<span @click="delDept(i)">×</span>
|
||||
<el-avatar :src="user.avatar"/>
|
||||
<el-tooltip class="item" effect="dark" :content="user.name" placement="bottom-start">
|
||||
<span>{{ user.name }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="perm === 'R'">
|
||||
<div v-for="(user, i) in _value" :key="i">
|
||||
{{user.label}}
|
||||
<div style="display: flex;">
|
||||
<div v-for="(user, i) in _value" :key="i" class="view_user">
|
||||
<el-avatar :src="user.avatar"/>
|
||||
<el-tooltip effect="dark" :content="user.name" placement="bottom-start">
|
||||
<span>{{ user.name }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import componentMinxins from '../ComponentMinxins'
|
||||
import OrgPicker from "@/components/common/Test";
|
||||
import UserSelect from "@/components/common/UserPicker";
|
||||
|
||||
export default {
|
||||
mixins: [componentMinxins],
|
||||
name: "UserPicker",
|
||||
components: {OrgPicker},
|
||||
components: {UserSelect},
|
||||
props: {
|
||||
value:{
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
|
|
@ -48,32 +59,75 @@ export default {
|
|||
type: String,
|
||||
default: '请选择人员'
|
||||
},
|
||||
multiple:{
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showOrgSelect: false
|
||||
showPickerSelect: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selected(values){
|
||||
this.showOrgSelect = false
|
||||
selected(values) {
|
||||
this.showPickerSelect = false
|
||||
this._value = values
|
||||
},
|
||||
delDept(i){
|
||||
delDept(i) {
|
||||
this._value.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.placeholder{
|
||||
<style scoped lang="less">
|
||||
.placeholder {
|
||||
margin-left: 10px;
|
||||
color: #adabab;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.userStyle {
|
||||
width: 45px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
margin-right: 10px;
|
||||
|
||||
span:first-child {
|
||||
position: absolute;
|
||||
right: -3px;
|
||||
top: -11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span:last-child {
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden
|
||||
}
|
||||
}
|
||||
|
||||
.view_user {
|
||||
width: 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 10px;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</el-radio-group>
|
||||
<div v-if="nodeProps.assignedType === 'ASSIGN_USER'">
|
||||
<el-button size="mini" icon="el-icon-plus" type="primary" @click="selectUser" round>选择人员</el-button>
|
||||
<org-items v-model="nodeProps.assignedUser"/>
|
||||
<avatar-ellipsis :row="3" :user-info="nodeProps.assignedUser"/>
|
||||
</div>
|
||||
<div v-else-if="nodeProps.assignedType === 'SELF_SELECT'">
|
||||
<el-radio-group size="mini" v-model="nodeProps.selfSelect.multiple">
|
||||
|
|
@ -118,8 +118,8 @@
|
|||
</el-form-item>
|
||||
<el-form-item label="🙅 如果审批被驳回 👇">
|
||||
<el-radio-group v-model="nodeProps.refuse.type">
|
||||
<el-radio label="TO_END">直接结束流程</el-radio>
|
||||
<!-- <el-radio label="TO_BEFORE">驳回到上级审批节点</el-radio>-->
|
||||
<el-radio label="TO_INITIAL">直接结束流程</el-radio>
|
||||
<el-radio label="TO_BEFORE">驳回到上级审批节点</el-radio>
|
||||
<!-- <el-radio label="TO_NODE">驳回到指定节点</el-radio>-->
|
||||
</el-radio-group>
|
||||
<div v-if="nodeProps.refuse.type === 'TO_NODE'">
|
||||
|
|
@ -133,19 +133,22 @@
|
|||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<role-picker :title="pickerTitle" multiple ref="rolePicker" :v-model="select" @ok="selectedRole"/>
|
||||
<role-picker title="请选择人员" multiple ref="rolePicker" :v-model="roleList" @ok="selectedRole"/>
|
||||
<user-picker title="请选择系统角色" multiple ref="userPicker" :v-model="assignedUser" @ok="selectedUser"/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RolePicker from "@/components/common/RolePicker";
|
||||
import UserPicker from "@/components/common/UserPicker";
|
||||
import RoleItems from "../RoleItems";
|
||||
import OrgItems from "../OrgItems";
|
||||
|
||||
|
||||
export default {
|
||||
name: "ApprovalNodeConfig",
|
||||
components: {RoleItems, OrgItems, RolePicker},
|
||||
components: {RoleItems, OrgItems, RolePicker, UserPicker},
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
|
|
@ -158,7 +161,6 @@ export default {
|
|||
return {
|
||||
showOrgSelect: false,
|
||||
orgPickerSelected: [],
|
||||
orgPickerType: "user",
|
||||
approvalTypes: [
|
||||
{name: "指定人员", type: "ASSIGN_USER"},
|
||||
{name: "发起人自选", type: "SELF_SELECT"},
|
||||
|
|
@ -174,27 +176,27 @@ export default {
|
|||
nodeProps() {
|
||||
return this.$store.state.selectedNode.props;
|
||||
},
|
||||
select() {
|
||||
return this.config.assignedUser || [];
|
||||
assignedUser: {
|
||||
get() {
|
||||
return this.config.assignedUser || [];
|
||||
},
|
||||
set(val) {
|
||||
this.config.assignedUser = val
|
||||
}
|
||||
},
|
||||
roleList() {
|
||||
return this.config.roleList || [];
|
||||
roleList:{
|
||||
get() {
|
||||
return this.config.roleList || [];
|
||||
},
|
||||
set(val) {
|
||||
this.config.roleList = val
|
||||
}
|
||||
},
|
||||
forms() {
|
||||
return this.$store.state.design.formItems.filter(f => {
|
||||
return f.name === "UserPicker";
|
||||
});
|
||||
},
|
||||
pickerTitle() {
|
||||
switch (this.orgPickerType) {
|
||||
case "user":
|
||||
return "请选择人员";
|
||||
case "role":
|
||||
return "请选择系统角色";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
nodeOptions() {
|
||||
let values = [];
|
||||
const excType = ["ROOT", "EMPTY", "CONDITION", "CONDITIONS", "CONCURRENT", "CONCURRENTS"];
|
||||
|
|
@ -224,34 +226,30 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
selectUser() {
|
||||
this.orgPickerSelected = this.select;
|
||||
this.orgPickerType = "user";
|
||||
this.$refs.orgPicker.show();
|
||||
this.$refs.userPicker.showUserPicker()
|
||||
},
|
||||
selectNoSetUser() {
|
||||
this.orgPickerSelected = this.config.nobody.assignedUser;
|
||||
this.orgPickerType = "user";
|
||||
this.$refs.orgPicker.show();
|
||||
|
||||
},
|
||||
//弹出角色选择器,选择系统角色
|
||||
selectRole() {
|
||||
this.orgPickerType = "role";
|
||||
this.$refs.rolePicker.showRolePicker();
|
||||
},
|
||||
selectedRole(select) {
|
||||
select.forEach(val => {
|
||||
for (let i = 0; i < this.roleList.length; i++) {
|
||||
if (this.roleList[i].roleId === val.roleId) {
|
||||
this.roleList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.roleList.push(val);
|
||||
});
|
||||
this.roleList = select
|
||||
},
|
||||
selectedUser(select) {
|
||||
let userInfoList = []
|
||||
for (let val of select) {
|
||||
let userInfo = {
|
||||
id: val.id,
|
||||
name: val.name,
|
||||
avatar: val.avatar,
|
||||
}
|
||||
userInfoList.push(userInfo)
|
||||
}
|
||||
this.assignedUser = userInfoList
|
||||
},
|
||||
removeOrgItem(index) {
|
||||
this.select.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-button size="mini" icon="el-icon-plus" type="primary" @click="selectOrg" round>选择抄送人</el-button>
|
||||
<el-button size="mini" icon="el-icon-plus" type="primary" @click="selectUser" round>选择抄送人</el-button>
|
||||
<div class="option">
|
||||
<el-checkbox label="允许发起人添加抄送人" v-model="config.shouldAdd"></el-checkbox>
|
||||
<el-checkbox label="允许发起人添加抄送人" v-model="shouldAdd"></el-checkbox>
|
||||
</div>
|
||||
<org-items v-model="select"/>
|
||||
<org-picker multiple ref="orgPicker" :selected="select" @ok="selected"/>
|
||||
<!-- <org-items v-model="select"/>-->
|
||||
<avatar-ellipsis :row="3" :user-info="assignedUser"/>
|
||||
<user-picker title="请选择系统角色" multiple ref="userPicker" :v-model="assignedUser" @ok="selectedUser"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import OrgPicker from "@/components/common/Test";
|
||||
import OrgItems from "../OrgItems";
|
||||
import UserPicker from "@/components/common/UserPicker";
|
||||
|
||||
export default {
|
||||
name: "CcNodeConfig.vue",
|
||||
components: {OrgPicker, OrgItems},
|
||||
components: {UserPicker},
|
||||
props:{
|
||||
config:{
|
||||
type: Object,
|
||||
|
|
@ -25,7 +25,16 @@ export default {
|
|||
}
|
||||
},
|
||||
computed:{
|
||||
select: {
|
||||
shouldAdd:{
|
||||
get(){
|
||||
return this.config.shouldAdd || false
|
||||
},
|
||||
set(val){
|
||||
console.log("asdjhajdhasjdhasdhasjdad")
|
||||
this.config.shouldAdd = val
|
||||
}
|
||||
},
|
||||
assignedUser: {
|
||||
get(){
|
||||
return this.config.assignedUser || []
|
||||
},
|
||||
|
|
@ -38,16 +47,21 @@ export default {
|
|||
return {}
|
||||
},
|
||||
methods: {
|
||||
selectOrg() {
|
||||
this.$refs.orgPicker.show()
|
||||
selectUser() {
|
||||
this.$refs.userPicker.showUserPicker()
|
||||
},
|
||||
selected(select) {
|
||||
console.log(select)
|
||||
this.select = Object.assign([], select)
|
||||
selectedUser(select) {
|
||||
let userInfoList = []
|
||||
for (let val of select) {
|
||||
let userInfo = {
|
||||
id: val.id,
|
||||
name: val.name,
|
||||
avatar: val.avatar,
|
||||
}
|
||||
userInfoList.push(userInfo)
|
||||
}
|
||||
this.assignedUser = userInfoList
|
||||
},
|
||||
removeOrgItem(index){
|
||||
this.select.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
<template>
|
||||
<node :title="config.name" :show-error="showError" :content="content" :user-info="config.props.assignedUser" :error-info="errorInfo"
|
||||
<node :title="config.name" :show-error="showError" :content="content"
|
||||
:show-avatar="config.props.assignedType === 'ASSIGN_USER'" :user-info="assignedUser"
|
||||
:error-info="errorInfo"
|
||||
:select-user="selectUser"
|
||||
@selected="$emit('selected')" @delNode="$emit('delNode')" @insertNode="type => $emit('insertNode', type)"
|
||||
placeholder="请设置审批人" :header-bgc="headerBgc" header-icon="el-icon-s-check"/>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -10,8 +12,8 @@ import Node from './Node'
|
|||
|
||||
export default {
|
||||
name: "ApprovalNode",
|
||||
props:{
|
||||
config:{
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
|
|
@ -25,120 +27,136 @@ export default {
|
|||
errorInfo: '',
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
viewer(){
|
||||
computed: {
|
||||
selectUser() {
|
||||
return {
|
||||
show: this.config.props.assignedType === 'SELF_SELECT',
|
||||
multiple: this.config.props.selfSelect.multiple
|
||||
};
|
||||
},
|
||||
assignedUser() {
|
||||
if (this.config.props.assignedType === 'SELF_SELECT') {
|
||||
this.config.props.assignedUser = []
|
||||
}
|
||||
return this.config.props.assignedUser;
|
||||
},
|
||||
viewer() {
|
||||
return this.$store.state.diagramMode === 'viewer'
|
||||
},
|
||||
preview(){
|
||||
preview() {
|
||||
return this.$store.state.preview;
|
||||
},
|
||||
headerBgc() {
|
||||
if (this.preview || !this.viewer){
|
||||
if (this.preview || !this.viewer) {
|
||||
return '#ff943e'
|
||||
}else {
|
||||
} else {
|
||||
return this.config.props.headerBgc
|
||||
}
|
||||
},
|
||||
content(){
|
||||
content() {
|
||||
const config = this.config.props
|
||||
switch (config.assignedType){
|
||||
switch (config.assignedType) {
|
||||
case "ASSIGN_USER":
|
||||
if (config.assignedUser.length > 0){
|
||||
if (config.assignedUser.length > 0) {
|
||||
let texts = []
|
||||
config.assignedUser.forEach(org => texts.push(org.name))
|
||||
return String(texts).replaceAll(',', '、')
|
||||
}else {
|
||||
} else {
|
||||
return '请指定审批人'
|
||||
}
|
||||
case "SELF":
|
||||
return '发起人自己'
|
||||
case "SELF_SELECT":
|
||||
return config.selfSelect.multiple ? '发起人自选多人':'发起人自选一人'
|
||||
return config.selfSelect.multiple ? '发起人自选多人' : '发起人自选一人'
|
||||
case "LEADER_TOP":
|
||||
return '多级主管依次审批'
|
||||
case "LEADER":
|
||||
return config.leader.level > 1 ? '发起人的第 ' + config.leader.level + ' 级主管' : '发起人的直接主管'
|
||||
case "FORM_USER":
|
||||
if (!config.formUser || config.formUser === ''){
|
||||
if (!config.formUser || config.formUser === '') {
|
||||
return '表单内联系人(未选择)'
|
||||
}else {
|
||||
} else {
|
||||
let text = this.getFormItemById(config.formUser)
|
||||
if (text && text.title){
|
||||
if (text && text.title) {
|
||||
return `表单(${text.title})内的人员`
|
||||
}else {
|
||||
} else {
|
||||
return '该表单已被移除😥'
|
||||
}
|
||||
}
|
||||
case "ROLE":
|
||||
if (config.roleList.length > 0){
|
||||
return config.roleList.map(role=>{
|
||||
if (config.roleList.length > 0) {
|
||||
return config.roleList.map(role => {
|
||||
return role.roleName;
|
||||
}).join("、")
|
||||
}else {
|
||||
} else {
|
||||
return '指定角色(未设置)'
|
||||
}
|
||||
default: return '未知设置项😥'
|
||||
default:
|
||||
return '未知设置项😥'
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
getFormItemById(id){
|
||||
getFormItemById(id) {
|
||||
return this.$store.state.design.formItems.find(item => item.id === id)
|
||||
},
|
||||
//校验数据配置的合法性
|
||||
validate(err){
|
||||
validate(err) {
|
||||
try {
|
||||
this.showError = !this[`validate_${this.config.props.assignedType}`](err)
|
||||
|
||||
if (this.config.props.nobody.handler === 'TO_USER' && this.config.props.nobody.assignedUser.length === 0) {
|
||||
this.errorInfo = '审批人为空时, 转交给指定人员:【请指定一个具体的人】'
|
||||
err.push('审批人为空时, 转交给指定人员:【请指定一个具体的人】')
|
||||
this.showError = true
|
||||
} else if (this.viewer) {
|
||||
this.showError = !this.validate_ASSIGN_USER(err)
|
||||
console.log(this.showError)
|
||||
}
|
||||
|
||||
return this.showError
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return true;
|
||||
}
|
||||
},
|
||||
validate_ASSIGN_USER(err){
|
||||
if(this.config.props.assignedUser.length > 0){
|
||||
validate_ASSIGN_USER(err) {
|
||||
if (this.config.props.assignedUser.length > 0) {
|
||||
return true;
|
||||
}else {
|
||||
} else {
|
||||
this.errorInfo = '请指定审批人员'
|
||||
err.push(`${this.config.name} 未指定审批人员`)
|
||||
return false
|
||||
}
|
||||
},
|
||||
validate_SELF_SELECT(err){
|
||||
validate_SELF_SELECT(err) {
|
||||
return true;
|
||||
},
|
||||
validate_LEADER_TOP(err){
|
||||
validate_LEADER_TOP(err) {
|
||||
return true;
|
||||
},
|
||||
validate_LEADER(err){
|
||||
validate_LEADER(err) {
|
||||
return true;
|
||||
},
|
||||
validate_ROLE(err){
|
||||
if (this.config.props.roleList.length <= 0){
|
||||
validate_ROLE(err) {
|
||||
if (this.config.props.roleList.length <= 0) {
|
||||
this.errorInfo = '请指定负责审批的系统角色'
|
||||
err.push(`${this.config.name} 未指定审批角色`)
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validate_SELF(err){
|
||||
validate_SELF(err) {
|
||||
return true;
|
||||
},
|
||||
validate_FORM_USER(err){
|
||||
if (this.config.props.formUser === ''){
|
||||
validate_FORM_USER(err) {
|
||||
if (this.config.props.formUser === '') {
|
||||
this.errorInfo = '请指定表单中的人员组件'
|
||||
err.push(`${this.config.name} 审批人为表单中人员,但未指定`)
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validate_REFUSE(err){
|
||||
validate_REFUSE(err) {
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<node :title="config.name" :show-error="showError" :content="content" :error-info="errorInfo" :user-info="config.props.assignedUser"
|
||||
<node :title="config.name" :show-error="showError" :select-user="selectUser" :content="content" :error-info="errorInfo" :show-avatar="true" :user-info="config.props.assignedUser"
|
||||
@selected="$emit('selected')" @delNode="$emit('delNode')" @insertNode="type => $emit('insertNode', type)"
|
||||
placeholder="请设置抄送人" :header-bgc="headerBgc" header-icon="el-icon-s-promotion"/>
|
||||
</template>
|
||||
|
|
@ -25,6 +25,12 @@ export default {
|
|||
}
|
||||
},
|
||||
computed:{
|
||||
selectUser(){
|
||||
return {
|
||||
show: this.config.props.shouldAdd,
|
||||
multiple: true
|
||||
};
|
||||
},
|
||||
viewer(){
|
||||
return this.$store.state.diagramMode === 'viewer'
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,27 +1,26 @@
|
|||
<template>
|
||||
<div :class="{'node': true, 'root': isRoot || !show, 'node-error-state': showError}">
|
||||
<div v-if="show" @click="$emit('selected')" :class="{'node-body': true, 'error': showError}" >
|
||||
<div v-if="show" @click="$emit('selected')" :class="{'node-body': true, 'error': showError}">
|
||||
<div>
|
||||
<div class="node-body-header" :style="{'background-color': headerBgc}">
|
||||
<i :class="headerIcon" style="margin-right: 5px" v-if="(headerIcon || '') !== ''"></i>
|
||||
<ellipsis class="name" hover-tip :content="title"/>
|
||||
<i class="el-icon-close" v-if="!isRoot && $store.state.diagramMode !== 'viewer'" style="float:right;" @click="$emit('delNode')"></i>
|
||||
<i class="el-icon-close" v-if="!isRoot && $store.state.diagramMode !== 'viewer'" style="float:right;"
|
||||
@click="$emit('delNode')"></i>
|
||||
</div>
|
||||
<div class="node-body-content">
|
||||
<i :class="leftIcon" v-if="leftIcon"></i>
|
||||
<template v-if="$store.state.diagramMode !== 'viewer'">
|
||||
<span class="placeholder" v-if="(content || '').trim() === ''">{{placeholder}}</span>
|
||||
<ellipsis :row="3" :content="content" v-else/>
|
||||
<i class="el-icon-arrow-right"></i>
|
||||
<template v-if="viewer && selectUser.show">
|
||||
<el-button type="primary" icon="el-icon-plus" circle @click="$refs.userPicker.showUserPicker()"/>
|
||||
<avatar-ellipsis :row="3" v-if="userInfo.length > 0" :user-info="userInfo"/>
|
||||
</template>
|
||||
<template v-else-if="showAvatar">
|
||||
<span class="placeholder" v-if="userInfo.length === 0">{{ placeholder }}</span>
|
||||
<avatar-ellipsis :row="3" :user-info="userInfo" v-else/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-if="userInfo.length > 0">
|
||||
<avatar-ellipsis :row="3" :user-info="userInfo"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="placeholder" v-if="(content || '').trim() === ''">{{placeholder}}</span>
|
||||
<ellipsis :row="3" :content="content" v-else/>
|
||||
</template>
|
||||
<span class="placeholder" v-if="(content || '').trim() === ''">{{ placeholder }}</span>
|
||||
<ellipsis :row="3" :content="content" v-else/>
|
||||
</template>
|
||||
</div>
|
||||
<div class="node-error" v-if="showError">
|
||||
|
|
@ -32,21 +31,29 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="node-footer">
|
||||
<div v-if="merge" class="branch-merge"><img data-v-1e7b1da5="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABXlJREFUeF7tmm2IVGUUx3/nLkQUqxmkpAVhSPUllZX8EEGhvVgZQWCU6wcpsqi2mXtnoaBwoqLCufeO9oJYUJQiFZWlZPQCfYiIXkylstTyS1oWWeYWCe6cuLsz7t3r3Ll3du6907oz35bnPM9z/r895zznmWeECf6RCa6fDoBOBExwAp0UmOAB0CmCnRTopECbCZi2nivK1CMD7FpXlH+ydqctKZBz9QyjwkqFG4HzfKK/0gpvl/ulmBWIzAHkVmlRDFY2EihwwLFkRhYQxgzAtHW2CpcBc4CpOsg26eK7yVPYVFwu/9ZzPufq2VLhQBxhAk85lvSF2Y5l/3prjQlAvqR3IjwJTKqz6DeGssQuyLfBsbyjz6PcFgeAZyOwzLFk/QnrjHH/RACYtj6ncHuUCDWYXs7Lz367XEn3inB+1NzauMLGsiW3+u1b2b9lAH22LuiCD2IJED5yTbmiZpt3dAbKT7Hmjhjtdi25oPZnK/uH7dtUCpi2vqVwQ1wRWuHhWkW3StpTEb6IO3fIThhwTemuzWll/0QA5G39FTgrtghhs2vKELA7inra6d38HXvusOEnriWXHo+iFvZvGUDfap3VdYzdzQgIHmd5W7cBc2Ovoax1C3KXZ5/E/i3VgCQciNMD+J1Ug55yXjxo7QfgOdFKCvjyeL/C9MgoEBa5przrt0ti/+C+mRVB/8amrWsU7m2Ql/c5lqwJjre9CDZ1DMFnriXzw0SatvZW4FqBW6o2vwGvCGxyLPmw3rym9g8cwy0XQV8Ix2qEgH0C1ziWNCyceVu1uvZrriVLGqVGsainHO7mRyDynlCvEWupCI7Kxcat6BFg+OwW9ohyfSMIcQF44v/sZovAlRH1I7QVTwyAt1Cjy8hfh9hYvepGQogDoI74HYbSXzHwusTYl7FEAURVcdPWN+NAiAJQTzzCda4p+6N8iDPe1CkQZ8FAtY+E0AhA2uKHszTlT1QkhAHIQnwmAKr1IjQS6gHISnxmABpBCALIUnymAMIgKHxf6wMmH6E3cNTtSLLgZXoKNOgAR6UDyqyq7esKk3znfOriM48AXzc5AmGE1EFgWvXPTMS3DcAJ6TA6XDIT31YAoRCEc5JqcuKc8Kn3AVFO+E4BryvJVHzbI8BzwAdgi2vJ4ihgSY//nyIg8jqctPi2RYBp61wV5qsyR2BFVdhBhBe0wtdisNU15VAagoNrZh4BOVsfFcVCODVUoLBn6E2hIBvShpApgLyt3nvhRXFFCWxwLOmNaz8Wu8wA5G31ntQWNOukwD2OJc80Oy+ufSYAciVdJsJLcZ0K2nV1MbuUk51jnd9oXuoACmW9eHCQj49/T+j3RtiJslPgFxXmoVxe11nhPdeUq8clANPWPoXVQef9D6e1saEHVINHUBYF7Q1lnl2QL5OGkHoE5G19GRhVyBQ+L1tyST0xoa/Iygq3IOvGI4BdwIWjHBeecE15IExM3tYfgJmBOetcU2o9Q2IcsoiAw8Gf0qhyU7kgb4QCcPRTlNGvSspmtzD81J7kJ30AJX0fYeHo2seLjiXLG0TA78CZ/nGFB8uWPJakeG+t9AE4+jjK/XGLWtgTusBix5It4w5ArqRLRTjhl14IW40KD/kre66ki0R4p57IrgozS/2yb9wByDvqhbKX07Xv/oIavMfOP6pFb0pdgcqrbkFuTlp8JingbRIaBfEUHUOYltbtMPUaUNNo2rpeYWk8zSNWqvSmeSvMDIAnybT1boWnY0I4aigL7YJ4bXRqn0wBeCqG7gYVVqFcFapKWXt0gP5nizKQmvLqwpkDqAkaanmhB4MelOkI27XCDjHY7pqyN23htfXbBiArgVH7dABEETrZxzsRcLL/h6P0/Qc1qphfvB2K3wAAAABJRU5ErkJggg==" alt=""></div>
|
||||
<div v-if="merge" class="branch-merge">
|
||||
<img data-v-1e7b1da5=""
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABXlJREFUeF7tmm2IVGUUx3/nLkQUqxmkpAVhSPUllZX8EEGhvVgZQWCU6wcpsqi2mXtnoaBwoqLCufeO9oJYUJQiFZWlZPQCfYiIXkylstTyS1oWWeYWCe6cuLsz7t3r3Ll3du6907oz35bnPM9z/r895zznmWeECf6RCa6fDoBOBExwAp0UmOAB0CmCnRTopECbCZi2nivK1CMD7FpXlH+ydqctKZBz9QyjwkqFG4HzfKK/0gpvl/ulmBWIzAHkVmlRDFY2EihwwLFkRhYQxgzAtHW2CpcBc4CpOsg26eK7yVPYVFwu/9ZzPufq2VLhQBxhAk85lvSF2Y5l/3prjQlAvqR3IjwJTKqz6DeGssQuyLfBsbyjz6PcFgeAZyOwzLFk/QnrjHH/RACYtj6ncHuUCDWYXs7Lz367XEn3inB+1NzauMLGsiW3+u1b2b9lAH22LuiCD2IJED5yTbmiZpt3dAbKT7Hmjhjtdi25oPZnK/uH7dtUCpi2vqVwQ1wRWuHhWkW3StpTEb6IO3fIThhwTemuzWll/0QA5G39FTgrtghhs2vKELA7inra6d38HXvusOEnriWXHo+iFvZvGUDfap3VdYzdzQgIHmd5W7cBc2Ovoax1C3KXZ5/E/i3VgCQciNMD+J1Ug55yXjxo7QfgOdFKCvjyeL/C9MgoEBa5przrt0ti/+C+mRVB/8amrWsU7m2Ql/c5lqwJjre9CDZ1DMFnriXzw0SatvZW4FqBW6o2vwGvCGxyLPmw3rym9g8cwy0XQV8Ix2qEgH0C1ziWNCyceVu1uvZrriVLGqVGsainHO7mRyDynlCvEWupCI7Kxcat6BFg+OwW9ohyfSMIcQF44v/sZovAlRH1I7QVTwyAt1Cjy8hfh9hYvepGQogDoI74HYbSXzHwusTYl7FEAURVcdPWN+NAiAJQTzzCda4p+6N8iDPe1CkQZ8FAtY+E0AhA2uKHszTlT1QkhAHIQnwmAKr1IjQS6gHISnxmABpBCALIUnymAMIgKHxf6wMmH6E3cNTtSLLgZXoKNOgAR6UDyqyq7esKk3znfOriM48AXzc5AmGE1EFgWvXPTMS3DcAJ6TA6XDIT31YAoRCEc5JqcuKc8Kn3AVFO+E4BryvJVHzbI8BzwAdgi2vJ4ihgSY//nyIg8jqctPi2RYBp61wV5qsyR2BFVdhBhBe0wtdisNU15VAagoNrZh4BOVsfFcVCODVUoLBn6E2hIBvShpApgLyt3nvhRXFFCWxwLOmNaz8Wu8wA5G31ntQWNOukwD2OJc80Oy+ufSYAciVdJsJLcZ0K2nV1MbuUk51jnd9oXuoACmW9eHCQj49/T+j3RtiJslPgFxXmoVxe11nhPdeUq8clANPWPoXVQef9D6e1saEHVINHUBYF7Q1lnl2QL5OGkHoE5G19GRhVyBQ+L1tyST0xoa/Iygq3IOvGI4BdwIWjHBeecE15IExM3tYfgJmBOetcU2o9Q2IcsoiAw8Gf0qhyU7kgb4QCcPRTlNGvSspmtzD81J7kJ30AJX0fYeHo2seLjiXLG0TA78CZ/nGFB8uWPJakeG+t9AE4+jjK/XGLWtgTusBix5It4w5ArqRLRTjhl14IW40KD/kre66ki0R4p57IrgozS/2yb9wByDvqhbKX07Xv/oIavMfOP6pFb0pdgcqrbkFuTlp8JingbRIaBfEUHUOYltbtMPUaUNNo2rpeYWk8zSNWqvSmeSvMDIAnybT1boWnY0I4aigL7YJ4bXRqn0wBeCqG7gYVVqFcFapKWXt0gP5nizKQmvLqwpkDqAkaanmhB4MelOkI27XCDjHY7pqyN23htfXbBiArgVH7dABEETrZxzsRcLL/h6P0/Qc1qphfvB2K3wAAAABJRU5ErkJggg=="
|
||||
alt=""></div>
|
||||
<div class="btn">
|
||||
<insert-button v-show="$store.state.diagramMode !== 'viewer'" @insertNode="type => $emit('insertNode', type)"></insert-button>
|
||||
<insert-button v-show="$store.state.diagramMode !== 'viewer'"
|
||||
@insertNode="type => $emit('insertNode', type)"></insert-button>
|
||||
</div>
|
||||
</div>
|
||||
<user-picker v-if="selectUser.show" title="请选择系统角色" :multiple="selectUser.multiple" ref="userPicker"
|
||||
:v-model="userInfo"
|
||||
@ok="selectedUser"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserPicker from "@/components/common/UserPicker";
|
||||
import InsertButton from '@/views/common/InsertButton.vue'
|
||||
|
||||
export default {
|
||||
name: "Node",
|
||||
components: {InsertButton},
|
||||
props:{
|
||||
components: {InsertButton, UserPicker},
|
||||
props: {
|
||||
//是否为根节点
|
||||
isRoot: {
|
||||
type: Boolean,
|
||||
|
|
@ -70,13 +77,29 @@ export default {
|
|||
//节点内容区域文字
|
||||
userInfo: {
|
||||
type: Array,
|
||||
default: []
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
title:{
|
||||
//节点内容区域文字
|
||||
showAvatar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
selectUser: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
show: false,
|
||||
multiple: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "标题"
|
||||
},
|
||||
placeholder:{
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "请设置"
|
||||
},
|
||||
|
|
@ -86,49 +109,71 @@ export default {
|
|||
default: undefined
|
||||
},
|
||||
//头部图标
|
||||
headerIcon:{
|
||||
headerIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//头部背景色
|
||||
headerBgc:{
|
||||
headerBgc: {
|
||||
type: String,
|
||||
default: '#576a95'
|
||||
},
|
||||
//是否显示错误状态
|
||||
showError:{
|
||||
showError: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
errorInfo:{
|
||||
errorInfo: {
|
||||
type: String,
|
||||
default: '无信息'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return{}
|
||||
},
|
||||
methods: {}
|
||||
computed: {
|
||||
viewer() {
|
||||
return this.$store.state.diagramMode === 'viewer'
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
selectedUser(select) {
|
||||
let userInfoList = []
|
||||
for (let val of select) {
|
||||
let userInfo = {
|
||||
id: val.id,
|
||||
name: val.name,
|
||||
avatar: val.avatar,
|
||||
}
|
||||
userInfoList.push(userInfo)
|
||||
}
|
||||
this.userInfo = userInfoList
|
||||
this.$store.state.selectUserMap.set(this.$store.state.selectedNode.id,userInfoList)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.root{
|
||||
&:before{
|
||||
.root {
|
||||
&:before {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.node-error-state{
|
||||
.node-body{
|
||||
|
||||
.node-error-state {
|
||||
.node-body {
|
||||
box-shadow: 0px 0px 5px 0px #F56C6C !important;
|
||||
}
|
||||
}
|
||||
.node{
|
||||
|
||||
.node {
|
||||
padding: 0 50px;
|
||||
width: 220px;
|
||||
position: relative;
|
||||
&:before{
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
|
|
@ -141,15 +186,18 @@ export default {
|
|||
border-color: #CACACA transparent transparent;
|
||||
background: #F5F5F7;
|
||||
}
|
||||
.node-body{
|
||||
|
||||
.node-body {
|
||||
cursor: pointer;
|
||||
max-height: 120px;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
background-color: white;
|
||||
box-shadow: 0px 0px 5px 0px #d8d8d8;
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0px 0px 3px 0px @theme-primary;
|
||||
|
||||
.node-body-header {
|
||||
.el-icon-close {
|
||||
display: inline;
|
||||
|
|
@ -157,36 +205,43 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
.node-body-header{
|
||||
|
||||
.node-body-header {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
padding: 5px 15px;
|
||||
color: white;
|
||||
font-size: xx-small;
|
||||
.el-icon-close{
|
||||
|
||||
.el-icon-close {
|
||||
display: none;
|
||||
}
|
||||
.name{
|
||||
|
||||
.name {
|
||||
height: 14px;
|
||||
width: 150px;
|
||||
display: inline-block
|
||||
}
|
||||
}
|
||||
.node-body-content{
|
||||
|
||||
.node-body-content {
|
||||
padding: 18px;
|
||||
color: #656363;
|
||||
font-size: 14px;
|
||||
i{
|
||||
|
||||
i {
|
||||
position: absolute;
|
||||
top: 55%;
|
||||
right: 5px;
|
||||
font-size: medium;
|
||||
}
|
||||
.placeholder{
|
||||
|
||||
.placeholder {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
}
|
||||
.node-error{
|
||||
|
||||
.node-error {
|
||||
position: absolute;
|
||||
right: -40px;
|
||||
top: 20px;
|
||||
|
|
@ -195,9 +250,10 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.node-footer{
|
||||
.node-footer {
|
||||
position: relative;
|
||||
.branch-merge{
|
||||
|
||||
.branch-merge {
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
width: 38px;
|
||||
|
|
@ -210,17 +266,20 @@ export default {
|
|||
flex-direction: column;
|
||||
box-shadow: 0 0 5px 0 #d8d8d8;
|
||||
}
|
||||
.btn{
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 20px 0 32px;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
/deep/ .el-button{
|
||||
|
||||
/deep/ .el-button {
|
||||
height: 32px;
|
||||
}
|
||||
&::before{
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<node title="发起人" :is-root="true" :content="content" :user-info="config.props.assignedUser"
|
||||
<node title="发起人" :is-root="true" :content="content" show-avatar :user-info="config.props.assignedUser"
|
||||
@selected="$emit('selected')" @insertNode="type => $emit('insertNode', type)"
|
||||
placeholder="所有人" :header-bgc="config.props.headerBgc" header-icon="el-icon-user-solid"/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
</div>
|
||||
<div style="display: flex;justify-content: center;flex-direction: column;min-width: 1036px;">
|
||||
<span style="font-size: 18px;text-align: center;padding-top: 20px;">审批流程</span>
|
||||
<process-diagram-viewer/>
|
||||
<process-diagram-viewer ref="processDiagramViewer"/>
|
||||
<!--渲染流程执行过程-->
|
||||
<el-timeline :reverse="false">
|
||||
<!-- <el-timeline-item v-for="(activity, index) in activities" :key="index">-->
|
||||
|
|
@ -75,6 +75,7 @@ export default {
|
|||
},
|
||||
validate(call) {
|
||||
this.$refs.initiateForm.validate(call);
|
||||
this.$refs.processDiagramViewer.validate(call);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ export default {
|
|||
let processInstance = this.$refs.processInstance;
|
||||
let paramsData = {
|
||||
processDefinitionId: this.selectForm.processDefinitionId,
|
||||
formData: JSON.stringify(processInstance.formData)
|
||||
formData: JSON.stringify(processInstance.formData),
|
||||
selectUserMap: this.$store.state.selectUserMap
|
||||
}
|
||||
processInstance.validate(valid => {
|
||||
if (valid) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue