浏览代码

审批流组件,审批人设置组件

cxmo 1 年之前
父节点
当前提交
0ac0a42cf7

+ 50 - 12
src/views/approve_manage/components/flowEdiotr.vue

@@ -1,13 +1,21 @@
 <template>
     <!-- 审批流内容 -->
     <div class="flow-editor">
-        <StartNode :flowNode="mockFlow"></StartNode>
+        <component v-for="(node,index) in flowData" :key="index"
+            :is="node.nodeName"
+            :flowNode="{...node,...{index}}"
+            @addNode="addFlowNode"
+            @removeNode="removeNode">
+        </component>
+        <!-- <StartNode :flowNode="mockFlow"></StartNode> -->
     </div>
 </template>
 
 <script>
 import StartNode from './flowNode/startNode.vue';
-
+import AddNode from './flowNode/addNode.vue';
+import ApproveNode from './flowNode/approveNode.vue';
+import EndNode from './flowNode/endNode.vue';
 export default {
     data() {
         return {
@@ -20,15 +28,50 @@ export default {
                     nodeName: 'ApproveNode',
                     approvers: ['审批人1', '审批人2'],
                     childrenNode: {
-                        nodeType:3,
-                        nodeName:'EndNode',
+                        nodeType:2,
+                        nodeName:'ApproveNode',
+                        approvers:[],
+                        childrenNode: {
+                            nodeType:3,
+                            nodeName:'EndNode',
+                        }
                     }
                 }
-            }
+            },
+            flowData:[]
         };
     },
-    methods: {},
-    components: { StartNode }
+    methods: {
+        getNode(node) {
+            let result = []
+            let _getNode = function (node) {
+                let tmp =JSON.parse(JSON.stringify(node))
+                delete tmp.childrenNode
+                result.push(tmp) //移除拍平数组的子元素,只保留节点相干元素
+                let child = node.childrenNode
+                if (child != undefined) {
+                    _getNode(child)
+                }
+            }
+            _getNode(node)
+            _getNode=null
+            return result
+        },
+        addFlowNode(node){
+            const {prevNode} = node
+            delete node.prevNode
+            const {index} = prevNode
+            this.flowData.splice(index+1,0,node)
+        },
+        removeNode(node){
+            const {index} = node
+            this.flowData.splice(index,1)
+        }
+    },
+    mounted(){
+        this.flowData = this.getNode(this.mockFlow)
+    },
+    components: { StartNode,AddNode,ApproveNode,EndNode }
 };
 </script>
 
@@ -39,10 +82,5 @@ export default {
     height: 100%;
     overflow:auto;
     background-color: gray;
-    .node{
-        width:200px;
-        height:300px;
-        background-color: white;
-    }
 }
 </style>

+ 39 - 5
src/views/approve_manage/components/flowNode/addNode.vue

@@ -3,25 +3,59 @@
         <div class="node-content">
             <div class="line"></div>
             <span class="line-arrow"></span>
-            <span class="add-btn el-icon-circle-plus">
-            </span>
+            <el-popover placement="right-start" trigger="hover" v-model="visible">
+                <div class="add-node-popover-body">
+                    <div class="popover-item" @click="handleAddApprove">
+                        <div class="icon"><i class="el-icon-s-check"></i></div>
+                        <p>审批人</p>
+                    </div>
+                </div>
+                <span class="add-btn el-icon-circle-plus" slot="reference"></span>
+            </el-popover>
         </div>
     </div>
 </template>
 
 <script>
 export default {
+    props:["node"],
     data() {
         return {
-
+            visible:false,
         };
     },
     methods: {
-
+        handleAddApprove(){
+            this.visible = false
+            const data = {
+                nodeType:2,
+                nodeName:'ApproveNode',
+                approvers:['AA'],
+                prevNode:this.node
+            }
+            this.$emit("addNode",data)
+        }
     },
 };
 </script>
 
+<style lang="scss">
+.add-node-popover-body{
+    display: flex;
+    .popover-item{
+        text-align: center;
+        .icon{
+            width:40px;
+            height:40px;
+            border-radius: 50%;
+            font-size: 24px;
+            line-height: 40px;
+            border:1px solid black;
+            margin-bottom: 10px;
+        }
+    }
+}
+</style>
 <style scoped lang="scss">
 .add-node-wrap{
     position:relative;
@@ -36,7 +70,7 @@ export default {
     .line{
         width:2px;
         height:calc(100px - 10px);
-        background-color: green;
+        background-color: #cacaca;
     }
     .line-arrow{
         height: 0;

+ 142 - 12
src/views/approve_manage/components/flowNode/approveNode.vue

@@ -1,28 +1,158 @@
 <template>
-    <div class="approve-node-wrap">
-        <p>审批人节点</p>
-        <AddNode />
-        <component 
-            :is="flowNode.childrenNode.nodeName"
-            :flowNode="flowNode.childrenNode"
-            v-if="flowNode.childrenNode"
-        />
+    <div class="approve-node-wrap node-wrap">
+        <div class="node-content">
+            <div class="head">
+                <span class="icon"><i class="el-icon-s-check"></i></span>
+                <span class="name">审核人</span>
+                <span class="icon-btn" @click="removeNode"><i class="el-icon-close"></i></span>
+            </div>
+            <div class="content" @click="showDrawer">{{flowNode.approvers[0]||'请选择审批人'}}</div>
+        </div>
+        <AddNode :node="flowNode" v-on="$listeners"/>
+        <el-drawer
+            direction="rtl"
+            :visible.sync="drawer"
+            :withHeader="false"
+            :modal-append-to-body="false"
+            >
+            <div class="approve-drawer-wrap">
+                <div class="header">
+                    <p>审批人设置</p>
+                    <span class="close-icon"><i class="el-icon-close"></i></span>
+                </div>
+                <div class="drawer-content">
+                    <div class="block">
+                        <p>选择审批人</p>
+                        <div class="choose-box">
+                            <el-radio v-model="block1" :label="1">指定人员</el-radio>
+                            <el-button @click="chooseDialogShow=true">选择人员</el-button>
+                        </div>
+                        <div class="approve-list">
+                            <TreeTransfer/>
+                        </div>
+                    </div>
+                    <!-- <div class="block">
+                        <p>多人审批时</p>
+                        <el-radio-group v-model="block2">
+                            <el-radio :label="1">
+                                依次审批
+                                <el-tooltip effect="dark" placement="top" content="多个审批人依次进行审批;只有当所有审批人同意,该节点才能通过;按选择顺序审批" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-warning-outline"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                            <el-radio :label="2">
+                                会签
+                                <el-tooltip effect="dark" placement="top" content="所有审批人同意,该节点才能通过;审批无先后顺序" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-warning-outline"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                            <el-radio :label="3">
+                                或签
+                                <el-tooltip effect="dark" placement="top" content="所有审批人同意,该节点才能通过;审批无先后顺序" >
+                                    <span class="hint-text">
+                                        <i class="el-icon-warning-outline"></i>
+                                    </span>
+                                </el-tooltip>
+                            </el-radio>
+                        </el-radio-group>
+                    </div> -->
+                </div>
+                <div class="drawer-btn">
+                    <el-button>取消</el-button>
+                    <el-button>确认</el-button>
+                </div>
+            </div>
+        </el-drawer>
+        <!-- 选择人员弹窗 -->
+        <el-dialog 
+            title="选择人员"
+            width="600"
+            :visible.sync="chooseDialogShow"
+            :modal-append-to-body="false"
+            :append-to-body="false"
+        >
+            <div class="dialog-wrap">
+                <TreeTransfer />
+            </div>
+        </el-dialog>
     </div>
 </template>
 
 <script>
+import TreeTransfer from '../treeTransfer.vue';
 import mixin from './nodeMixin'
 export default {
-    mixins:[mixin],
+    mixins: [mixin],
     data() {
-        return {};
+        return {
+            drawer: false,
+            block1: 1,
+            block2: 1,
+            chooseDialogShow: false,
+        };
     },
-    methods: {},
+    methods: {
+        removeNode() {
+            this.$emit('removeNode', this.flowNode);
+        },
+        showDrawer() {
+            //设置一下里面的文字啥的
+            this.drawer = true;
+        },
+    },
+    created() { console.log('test', this.flowNode); },
+    mounted() {
+        console.log('test', this.flowNode);
+    },
+    components: { TreeTransfer }
 };
 </script>
 
+<style lang="scss">
+.approve-node-wrap{
+    .el-drawer__body{
+        overflow: hidden;
+    }
+}
+</style>
 <style scoped lang="scss">
 .approve-node-wrap{
-    background-color: brown;
+    .head{
+        background-color: brown;
+    }
+    .approve-drawer-wrap{
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        overflow: hidden;
+        .header{
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            font-weight: bold;
+            font-size: 18px;
+            height:35px;
+            padding:10px;
+            border-bottom: 1px solid gray;
+        }
+        .drawer-content{
+            flex:1;
+            overflow-y: auto;
+            box-sizing: border-box;
+            padding:10px;
+            .block{
+                height: 500px;
+            }
+        }
+        .drawer-btn{
+            text-align: right;
+            margin:10px 10px 10px 0;
+        }
+    }
+    
 }
 </style>

+ 12 - 3
src/views/approve_manage/components/flowNode/endNode.vue

@@ -1,6 +1,6 @@
 <template>
-    <div class="end-node-wrap">
-        结束节点
+    <div class="end-node-wrap node-wrap">
+        <div class="end-content">流程结束</div>
     </div>
 </template>
 
@@ -19,6 +19,15 @@ export default {
 
 <style scoped lang="scss">
 .end-node-wrap{
-    background-color: blueviolet;
+    margin-bottom: 20px;
+    .end-content{
+        cursor: pointer;
+        width:150px;
+        height:35px;
+        border-radius: 16px;
+        background-color: blueviolet;
+        text-align: center;
+        line-height: 35px;
+    }
 }
 </style>

+ 1 - 3
src/views/approve_manage/components/flowNode/nodeMixin.js

@@ -1,8 +1,6 @@
 import AddNode from './addNode.vue';
-import ApproveNode from './approveNode.vue';
-import EndNode from './endNode.vue';
 export default{
-    components: { AddNode,ApproveNode,EndNode },
+    components: { AddNode},
     props:{
         flowNode:{
             type:Object,

+ 4 - 11
src/views/approve_manage/components/flowNode/startNode.vue

@@ -1,24 +1,16 @@
 <template>
     <div class="start-node-wrap node-wrap">
         <div class="node-content">
-            <div class="head">开始节点</div>
+            <div class="head">发起人</div>
+            <div class="content">张三</div>
         </div>
-        <AddNode />
-        <component 
-            :is="flowNode.childrenNode.nodeName"
-            :flowNode="flowNode.childrenNode"
-            v-if="flowNode.childrenNode"
-        />
-        
+        <AddNode :node="flowNode" v-on="$listeners"/>
     </div>
 </template>
 
 <script>
-//ApproveNode会调用自身,在开始节点引入一次防止渲染报错
-import ApproveNode from './approveNode.vue';
 import mixin from './nodeMixin'
 export default {
-    components: {ApproveNode},
     mixins:[mixin],
     data() {
         return {};
@@ -29,6 +21,7 @@ export default {
 
 <style scoped lang="scss">
 .start-node-wrap{
+    margin-top:20px;
     .head{
         background-color: #02BBD1;
     }

+ 97 - 0
src/views/approve_manage/components/treeTransfer.vue

@@ -0,0 +1,97 @@
+<template>
+    <!-- 支持树形结构的穿梭框,不需要树形的直接用el-transfer -->
+    <div class="tree-transfer">
+        <div class="before-transfer transfer">
+            <div class="head">{{beforeNum}}项</div>
+            <div class="search">
+                <el-input placeholder="搜索" v-model="searchText" @input="$refs['trans-tree'].filter(searchText)"></el-input>
+            </div>
+            <div class="content">
+                <el-tree 
+                    ref="trans-tree"
+                    show-checkbox
+                    :data="treeData"
+                    :props="{
+                        label:'ItemName',
+                        children:'Children'
+                    }"
+                    :filter-node-method="filterNode"
+                    @check="SetCheckedNode"
+                ></el-tree>
+            </div>
+        </div>
+        <div class="after-transfer transfer">
+            <div class="head"><span>已选{{choosedList.length}}项</span><span>清空</span></div>
+            <ul class="content">
+                <li v-for="item in choosedList" :key="item.ItemId">{{item.ItemName}}</li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+import { dataAuthInterface } from "@/api/api.js";
+export default {
+    data() {
+        return {
+            beforeNum:10,
+            treeData:[],
+            searchText:'',
+            afterNum:5,
+            choosedList:[]
+        };
+    },
+    methods: {
+        getTreeData(){
+            ///datamanage/manual/sysuser/search?KeyWord= ,要用新接口再换
+            dataAuthInterface.userSearch({
+                KeyWord: ''
+            }).then(res => {
+                if(res.Ret === 200) {
+                    this.treeData = res.Data||[];
+                }
+            })
+        },
+        filterNode(value,data){
+            if(!value) return true
+            return data.ItemName.indexOf(value)!==-1
+        },
+        SetCheckedNode(data,{checkedNodes}){
+            this.choosedList = checkedNodes.filter(i=>{
+                if(i.ItemId<10000&&!i.Children)
+                    return i
+            })
+            this.$emit("chooseList",this.choosedList)
+        }
+    },
+    mounted(){
+        this.getTreeData()
+    }
+};
+</script>
+
+<style scoped lang="scss">
+.tree-transfer{
+    display: flex;
+    align-items: center;
+    .transfer{
+        display: flex;
+        flex-direction: column;
+        width:200px;
+        height: 400px;
+        border:1px solid gray;
+        border-radius: 4px;
+        .head,.search,.content{
+            padding:10px;
+        }
+        .head{
+            border-bottom: 1px solid gray;
+        }
+        .content{
+            flex:1;
+            overflow-y: scroll;
+            margin-bottom: 10px;
+        }
+    }
+}
+</style>

+ 12 - 3
src/views/approve_manage/css/nodeStyle.scss

@@ -3,6 +3,7 @@
     flex-direction: column;
     align-items: center;
     .node-content{
+        cursor: pointer;
         border-radius: 4px;
         width:300px;
         min-height: 100px;
@@ -13,9 +14,17 @@
             display: flex;
             align-items: center;
             padding: 5px;
+            justify-content: space-between;
+            .name{
+                margin-left: 5px;
+                margin-right: auto;
+            }
         }
+        .content{
+            padding:5px;
+        }
+    }
+    div{
+        box-sizing: border-box;
     }
-}
-* {
-    box-sizing: border-box;
 }