123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
- <template>
- <div class="FlowChartComponent">
- <!-- <Alert show-icon closable v-if="currentSteps === 1">双击空白区域即可直接新增一个中间节点,双击节点可编辑</Alert> -->
- <div class="chartContent">
- <div id="paletteDiv"></div>
- <div id="goChart" v-show="currentSteps === 1">
- </div>
- <div id="showChart" v-show="currentSteps === 2">
- </div>
- </div>
- <!-- 全局侧滑模块 -->
- <Drawer
- v-model="drawerObject.show"
- transfer
- :title="drawerObject.title"
- :width="472"
- :mask-closable="false"
- :closable="false"
- scrollable
- >
- <components
- v-if="drawerObject.show"
- :configData="drawerObject.configData"
- :data="drawerObject.configData"
- :is="drawerObject.component"
- :TABLE_ID="drawerObject.TABLE_ID"
- :node="drawerObject.node"
- :status="drawerObject.status"
- :rejectedNodes="rejectedNodes"
- :assignedNodes="assignedNodes"
- :readOnly="readOnly"
- :moduleType="data.moduleType"
- @closeDrawer="closeDrawer"
- >
- </components>
- </Drawer>
- </div>
- </template>
- <script>
- import '@/utils/go'
- import FlowDesinger from '@/utils/flow-desinger';
- import startNodeInfo from '@/components/startNodeInfo'
- import endNodeInfo from '@/components/endNodeInfo'
- import linkInfo from '@/components/linkInfo'
- import ProcessNodeConfig from '@/components/ProcessNodeConfig'
- import DynamicProcessNodeConfig from '@/components/DynamicProcessNodeConfig'
- import ServiceNodeConfig from '@/components/ServiceNodeConfig'
- import FlowDisplay from '@/utils/flow-display';
- export default {
- components:{
- startNodeInfo, endNodeInfo, linkInfo, ProcessNodeConfig, DynamicProcessNodeConfig, ServiceNodeConfig
- },
- props:{
- editable:{ //是否可编辑
- type:Boolean,
- default:true
- },
- fresh:{
- type:Boolean,
- default:false
- },
- currentSteps:{
- type:Number,
- default:null
- },
- noFreshFlag:{
- type:Boolean,
- default:false
- },
- readOnly:{
- type:Boolean,
- default:false
- },
- data:{
- type:Object,
- default () {
- return {
- }
- }
- }
- },
- data () {
- return {
- myDesigner:null, //画布实例
- drawerObject:{
- show:false
- },
- nodeMsg:{}, //存放节点数据
- pathMsg:{}, //存放路径数据
- rejectedNodes:[], //驳回节点
- assignedNodes: [], //指派节点
- }
- },
- activated () {
- if(!this.noFreshFlag){
- this.init()
- }
- },
- deactivated () { //keep-alive 组件停用时调用
- if(this.currentSteps === 1 && this.myDesigner){
- this.data.guiStyle = JSON.parse(this.myDesigner.getFlowData())
- }
- },
- methods:{
- init () {
- if(!Array.isArray(this.data.nodeMsg)){
- let nodeMsg = []
- Object.keys(this.data.nodeMsg).map(item => {
- nodeMsg.push(this.data.nodeMsg[item])
- return item
- })
- this.data.nodeMsg = nodeMsg
- let pathMsg = []
- Object.keys(this.data.pathMsg).map(item => {
- pathMsg.push(this.data.pathMsg[item])
- return item
- })
- this.data.pathMsg = pathMsg
- }
- this.dataProcessing()
- if(this.currentSteps === 1){
- // 流程图设计器
- if(!this.myDesigner){
- this.myDesigner= new FlowDesinger('goChart',{
- showEditNode:this.showEditNode, //节点双击编辑
- SelectionDeleted:this.SelectionDeleted, //删除事件
- LinkDrawn:this.LinkDrawn, //线的生成
- externalobjectsdropped:this.externalobjectsdropped, //节点生成
- LinkRelinked: this.LinkRelinked //连线修改
- });
- }
- this.initToolbar = this.myDesigner.initToolbar('paletteDiv',this.data.moduleType)
- this.myDesigner.displayFlow(JSON.parse(JSON.stringify(this.data.guiStyle)));// 在设计面板中显示流程图
- this.data.myDisplay = this.myDesigner.diagram
- }else{
- if(this.myDisplay){
- this.myDisplay.loadFlow(JSON.parse(JSON.stringify(this.data.guiStyle)))
- }else{
- this.myDisplay = new FlowDisplay('showChart',{
- showEditNode:this.showEditNode, //节点双击编辑
- });
- this.myDisplay.loadFlow(JSON.parse(JSON.stringify(this.data.guiStyle)))
- }
- // this.data.myDisplay = this.myDisplay.diagram
- }
- },
- compare (property) {
- return function(a,b) {
- var value1 = a[property];
- var value2 = b[property];
- return value1 - value2
- }
- },
- dataProcessing () { //处理后端返回节点数据和路径数据
- if(this.data.nodeMsg){
- this.data.nodeMsg.forEach(item => {
- this.nodeMsg[item.key] = item
- if(item.type === 2){ //结束节点对数据排序,区分执行程序还是抄送人
- this.nodeMsg[item.key].actionConfig.sort(this.compare('handleType'))
- }
- })
- this.data.nodeMsg = this.nodeMsg
- }
- if(this.data.pathMsg){
- this.data.pathMsg.forEach(item => {
- this.pathMsg[item.key] = item
- })
- this.data.pathMsg = this.pathMsg
- }
- this.data.removePath = []
- this.data.removeNode = []
- },
- showEditNode (node) { //双击编辑
- // node.findNodesOutOf()
- if(node.data.type === 1){
- let defaultObj = {
- conditionType: 0,
- ruleList: [],
- priority: null,
- defaultPriority: null,
- modifyId: null,
- id:null,
- triggerBt:[],
- visibleBt:[]
- }
- if(!node.data.id){
- this.nodeMsg[node.data.key] = Object.assign(defaultObj,this.nodeMsg[node.data.key])
- }
- this.drawerObject = {
- show: true,
- component: 'startNodeInfo',
- configData: this.nodeMsg[node.data.key],
- title:'开始节点配置'
- }
- }
- if(node.data.type === 2){
- let defaultObj = {
- id:null,
- manualConfig:null,
- actionConfig:[]
- }
- if(!node.data.id){
- this.nodeMsg[node.data.key] = Object.assign(defaultObj,this.nodeMsg[node.data.key])
- }
- this.drawerObject = {
- show: true,
- component: 'endNodeInfo',
- configData: this.nodeMsg[node.data.key],
- title:'结束节点配置'
- }
- }
- // 审批节点和操作节点用同一个配置界面,根据参数控制展示项
- if(node.data.category === "Approval" || node.data.category === "Operation"){
- this.rejectedNodes = []
- this.assignedNodes = []
- this.findNodesInto(node)
- this.findNodesOutOf(node)
- // 默认节点配置
- let defaultObj = {
- actServiceS:[],
- actionConfig:[],
- approvelList:[],
- backId:null,
- id:null,
- manualConfig:0,
- modifiableField:[],
- moduleId:null,
- name:'中间节点',
- nodeType:0,
- ruleList:[],
- inevitable: 1, //节点必经
- approveCondition: 0, //审批条件
- assignBack: 0, //驳回操作
- whetherBack: 0, //可为驳回节点
- nodeCancle: 0, //作废操作
- assignNext: 1, //指派流转节点
- assignNode: 1, //节点是否是必需指派
- assignApprover: 1, //是否动态指派操作人
- visibleBt:[], //可见按钮
- nodeBack: 0, //驳回按钮开关
- nodeAgree: 0, //同意按钮
- }
- if(this.data.moduleType === 0){
- defaultObj = {
- actServiceS:[],
- actionConfig:[],
- approvelList:[],
- backId:null,
- id:null,
- manualConfig:0,
- modifiableField:'',
- modifiableFieldName:'',
- moduleId:null,
- name:'审批节点',
- nodeType:0,
- ruleList:[]
- }
- }
- if(!node.data.id){
- this.nodeMsg[node.data.key] = Object.assign(defaultObj,this.nodeMsg[node.data.key])
- }
- this.drawerObject = {
- show: true,
- component: this.data.moduleType === 0?'ProcessNodeConfig':'DynamicProcessNodeConfig',
- configData: this.nodeMsg[node.data.key],
- node: node,
- title:node.data.category === "Approval"?'审批节点配置':'操作节点'
- }
- }
- // 服务节点
- if(node.data.category === 'Service'){
- let defaultObj = {
- id:null,
- actionConfig:[{
- "id":null, //新增不传,修改传
- "handleValue":null, //具体的关于请求状态,url之类的json
- "handleType":null, //51:rest服务实现,52:消息系统
- "extraMsg":null //相关参数
- }]
- }
- if(!node.data.id){
- this.nodeMsg[node.data.key] = Object.assign(defaultObj,this.nodeMsg[node.data.key])
- }
- this.drawerObject = {
- show: true,
- component: 'ServiceNodeConfig',
- configData: this.nodeMsg[node.data.key],
- title:'服务节点配置'
- }
- }
- if(node.data.from !== undefined){
- if(this.nodeMsg[node.data.from].category === 'Service' && this.data.moduleType === 1){
- return
- }
- // 默认连线配置
- let defaultObj = {
- endNode:null,
- moduleId:null,
- name:null,
- ruleList:[],
- sources:null,
- startNode:null,
- status:null
- }
- if(!node.data.moduleId){
- this.pathMsg[node.data.key] = Object.assign(defaultObj,this.pathMsg[node.data.key])
- }
- let tableConfig = [{
- ID: this.nodeMsg[node.data.from].nodeFormId,
- value: this.nodeMsg[node.data.from].nodeForm
- }]
- if(this.nodeMsg[node.data.from].category === 'Start'){
- tableConfig = [{
- ID: this.nodeMsg[node.data.from].businessType,
- value: this.nodeMsg[node.data.from].businessTypeName
- }]
- }
- this.drawerObject = {
- show: true,
- component: 'linkInfo',
- configData: this.pathMsg[node.data.key],
- TABLE_ID: this.data.moduleType === 1?tableConfig:this.data.businessType,
- title:'连接线配置'
- }
- }
- },
- findNodesInto (node) { //查找父节点
- let parents = node.findNodesInto()
- if(parents.count > 0){
- node.findNodesInto().map(item => {
- this.rejectedNodes.push({
- value:item.data.key,
- label:item.data.text
- })
- this.findNodesInto(item)
- })
- }else{
- return
- }
- },
- findNodesOutOf (node) { //查找子节点
- let childrens = node.findNodesOutOf()
- if(childrens.count > 0){
- node.findNodesOutOf().map(item => {
- if(item.data.key != -2){
- this.assignedNodes.push({
- value:item.data.key,
- label:item.data.text
- })
- this.findNodesOutOf(item)
- }
- })
- }else{
- return
- }
- },
- SelectionDeleted (node) { //删除节点或者线
- if(node.fromPort !== undefined){ //线的删除
- delete this.pathMsg[node.key]
- if(node.id){ //已保存的线
- this.data.removePath.push(node.id)
- }
- }else{ //节点删除
- delete this.nodeMsg[node.key]
- if(node.id){
- this.data.removeNode.push({
- id:node.id,
- type:node.type
- })
- }
- }
- },
- LinkDrawn (node) { //连线生成
- if(!this.judgeLoop()){
- this.$Modal.fcWarning({
- title:'警告',
- content:'流程图中存在回路,请重新设置!!',
- mask:true
- })
- this.data.guiStyle = JSON.parse(this.myDesigner.getFlowData())
- let linkDataArray = this.data.guiStyle.linkDataArray
- linkDataArray = linkDataArray.filter(item => {
- return item.key !== node.key
- })
- this.data.guiStyle.linkDataArray = linkDataArray
- this.init()
- // reject()
- return
- }else{
- this.pathMsg[node.key] = node
- this.pathMsg[node.key].ruleList = []
- }
- },
- LinkRelinked (node) { //连线修改
- this.pathMsg[node.key].from = node.from
- this.pathMsg[node.key].to = node.to
- this.pathMsg[node.key].fromPort = node.fromPort
- this.pathMsg[node.key].toPort = node.toPort
- },
- judgeLoop () { //判断是否存在闭环 true为没有闭环 false有闭环
- // 获取所有的节点
- let data = JSON.parse(this.myDesigner.getFlowData())
- const edges = data.linkDataArray?data.linkDataArray:JSON.parse(data).linkDataArray;
- const nodes = [];
- const list = {}; // 邻接表
- const queue = []; // 入度为0的节点集合
- const indegree = {};
- edges.forEach(e => {
- const { from, to } = e;
- if (!nodes.includes(from)) {
- nodes.push(from);
- }
- if (!nodes.includes(to)) {
- nodes.push(to);
- }
- addEdge(from, to);
- });
- const V = nodes.length;
- nodes.forEach(node => {
- if (!indegree[node]) indegree[node] = 0;
- if (!list[node]) list[node] = [];
- });
- function addEdge(source, target) {
- if (!list[source]) list[source] = [];
- if (!indegree[target]) indegree[target] = 0;
- list[source].push(target);
- indegree[target] += 1;
- }
- function sort() {
- Object.keys(indegree).forEach(id => {
- if (indegree[id] === 0) {
- queue.push(id);
- }
- });
- let count = 0;
- while (queue.length) {
- ++count;
- const currentNode = queue.pop();
- const nodeTargets = list[currentNode];
- for (let i = 0; i < nodeTargets.length; i++) {
- const target = nodeTargets[i];
- indegree[target] -= 1;
- if (indegree[target] === 0) {
- queue.push(target);
- }
- }
- }
- // false 没有输出全部顶点,有向图中有回路
- return !(count < V);
- }
- return sort();
- },
- externalobjectsdropped (node) { //节点生成
- if(node.category === 'Service' || node.category === 'Subprocesses'){
- this.nodeMsg[node.key] = node
- this.nodeMsg[node.key].name = node.text
- return
- }
- this.nodeMsg[node.key] = node
- this.nodeMsg[node.key].ruleList = []
- this.nodeMsg[node.key].actServiceS =[
- {
- status:1,
- handleValue:null,
- handleType:11
- },
- {
- status:1,
- handleValue:null,
- handleType:20
- }
- ]
- this.nodeMsg[node.key].actionConfig =[]
- this.nodeMsg[node.key].approvelList = []
- this.nodeMsg[node.key].approverStyle = 0
- this.nodeMsg[node.key].name = node.text
- },
- closeDrawer () { //关闭策划块
- this.drawerObject = {
- show: false
- }
- }
- }
- }
- </script>
- <style lang=scss" >
- .FlowChartComponent{
- width: 100%;
- height: 100%;
- overflow: hidden;
- display: flex;
- position: relative;
- flex-direction: column;
- .burgeon-alert{
- margin-bottom: 0;
- }
- .chartContent{
- flex: 1;
- display: flex;
- }
- #paletteDiv{
- padding: 5px;
- width: 160px;
- height: 100%;
- display: inline-block;
- border-right: 1px solid #dcdee2;
- }
- canvas{
- outline: none;
- }
- #goChart,#showChart{
- flex-grow: 1;
- flex: 1;
- // border: solid 1px black
- }
- }
- </style>
|