应用开发平台集成工作流——流程建模功能前端集成与改造

背景

对于流程设置不友好的问题,国内钉钉另行设计与实现了一套流程建模模式,跟bpmn规范无关,有人仿照实现了下,并做了开源(https://github.com/StavinLi/Workflow-Vue3),效果图如下:

实现大致原理是基于无限嵌套的子节点,输出json数据,传给后端,今天来说说前端的集成工作。

流程建模组件封装

新增flowDesign.vue组件,用于封装流程建模的操作,调整流程模板的编辑视图,将模型属性,使用flowDesign.vue组件替代。样式如下:
image.png
源码

<template>
  <div class="w-full">
    <el-input disabled style="width: 152px" />
    <el-button-group>
      <el-button icon="grid" @click="init" style="border-left-width: 0; padding: 10px" />
      <el-button icon="delete" @click="clear" style="border-left-width: 0; padding: 10px" />
    </el-button-group>
    <Dialog title="流程建模" v-model="visible" fullscreen>
      <div>
        <div class="fd-nav">
          <div class="fd-nav-left">
            <!-- TODO 显示流程模板名称 -->
            <div class="fd-nav-title">{
   
   { flowTemplateName }}</div>
          </div>
          <div class="fd-nav-right">
            <el-button type="primary" @click="save">保存</el-button>
          </div>
        </div>
        <div class="fd-nav-content">
          <section class="dingflow-design">
            <div class="zoom">
              <div class="zoom-out" :class="nowVal == 50 && 'disabled'" @click="zoomSize(1)"></div>
              <span>{
   
   { nowVal }}%</span>
              <div class="zoom-in" :class="nowVal == 300 && 'disabled'" @click="zoomSize(2)"></div>
            </div>
            <div class="box-scale" :style="`transform: scale(${nowVal / 100});`">
              <nodeWrap v-model:nodeConfig="nodeConfig" v-model:flowPermission="flowPermission" />
              <div class="end-node">
                <div class="end-node-circle"></div>
                <div class="end-node-text">流程结束</div>
              </div>
            </div>
          </section>
        </div>
        <errorDialog v-model:visible="tipVisible" :list="tipList" />
        <promoterDrawer />
        <approverDrawer :directorMaxLevel="directorMaxLevel" />
        <copyerDrawer />
        <conditionDrawer />
      </div>
    </Dialog>
  </div>
</template>

<script>
import { Dialog } from '@/components/abc/Dialog'
import errorDialog from './model/components/dialog/errorDialog.vue'
import promoterDrawer from './model/components/drawer/promoterDrawer.vue'
import approverDrawer from './model/components/drawer/approverDrawer.vue'
import copyerDrawer from './model/components/drawer/copyerDrawer.vue'
import conditionDrawer from './model/components/drawer/conditionDrawer.vue'
import nodeWrap from './model/components/nodeWrap.vue'
// import addNode from './model/components/drawer/conditionDrawer.vue'
export default {
  components: {
    Dialog,
    errorDialog,
    promoterDrawer,
    approverDrawer,
    copyerDrawer,
    conditionDrawer,
    nodeWrap
  },
  props: {
    modelValue: {
      type: String
    },
    flowTemplateName: {
      type: String
    }
  },
  data() {
    return {
      visible: false,
      // 当前缩放值
      nowVal: 100,
      // 模型配置
      nodeConfig: {},
      flowPermission: [],
      tipVisible: false,
      directorMaxLevel: 0,
      tipList: [],
      // 初始化数据
      defaultNodeConfig: {
        nodeName: '发起人',
        type: 0,
        priorityLevel: '',
        settype: '',
        selectMode: '',
        selectRange: '',
        directorLevel: '',
        examineMode: '',
        noHanderAction: '',
        examineEndDirectorLevel: '',
        ccSelfSelectFlag: '',
        conditionList: [],
        nodeUserList: [],
        childNode: {
          nodeName: '审核人',
          error: false,
          type: 1,
          settype: 2,
          selectMode: 0,
          selectRange: 0,
          directorLevel: 1,
          examineMode: 1,
          noHanderAction: 2,
          examineEndDirectorLevel: 0,
          childNode: {
            nodeName: '抄送人',
            type: 2,
            ccSelfSelectFlag: 1,
            childNode: null,
            nodeUserList: [],
            error: false
          },
          nodeUserList: []
        },
        conditionNodes: []
      }
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      if (this.modelValue != '{}') {
        // 绑定数据不为空,则使用绑定数据初始化
        this.nodeConfig = JSON.parse(this.modelValue)
      } else {
        // 否则,加载默认配置
        this.nodeConfig = this.defaultNodeConfig
      }

      this.visible = true
    },
    save() {
      this.$emit('update:modelValue', JSON.stringify(this.nodeConfig))
      this.visible = false
    },
    // 清空配置
    clear() {
      this.$confirm('此操作将重置流程配置为初始状态, 是否继续?', '确认', {
        type: 'warning'
      })
        .then(() => {
          this.$emit('update:modelValue', '{}')
        })
        .catch(() => {
          this.$message.info('已取消')
        })
    },
    zoomSize(type) {
      if (type == 1) {
        if (this.nowVal == 50) {
          return
        }
        this.nowVal -= 10
      } else {
        if (this.nowVal == 300) {
          return
        }
        this.nowVal += 10
      }
    }
  }
}
</script>

<style>
@import './model/css/workflow.css';
.error-modal-list {
  width: 455px;
}
</style>

流程建模组件功能集成

之前集成和使用的vue-simple-uploader、vue-echarts等,直接安装npm包即可。
流程建模功能则不是这么简单,需要跟自己的平台或系统进行深度集成。Workflow-Vue3这个开源项目提供的不是一个简单的组件功能,而是一个独立的前端项目,封装也不多,集成更多地是参照源码进行调整,涉及到大量的改造,难度比较大,遇到的问题也比较多,下面详细展开说说。

组件迁移

在模块workflow的view目录下flowTemplate目录下,新建一个model文件夹,集中存放开源项目Workflow-Vue3的相关文件,包括components、css、stores、utils等目录。
image.png
此外,还有部分图片资源,放到了平台assets目录下
image.png

引用关系调整

文件迁移过来后,接下来,大量的工作是调整引用关系,原项目大量使用@这种根目录src指向,而在平台中,放在一个目录去管理,需要调整引用路径。
如原项目,引用如下:

import { useStore } from '@/stores/index'
import { bgColors, placeholderList } from '@/utils/const'

需要调整为:

import { useStore } from '../stores/index'
import { bgColors, placeholderList } from '../utils/const'

几乎所有的迁移过来的vue文件引用都要改一遍,并且,不仅仅是vue组件间的引用,还有css样式和图片的引用地址,也需要进行相应调整。

组件注册

独立项目调整为组件使用,需要做一些适应性调整。
原项目将两个核心组件在main.js全局注册,如下:

import nodeWrap from '@/components/nodeWrap.vue'
app.component('nodeWrap', nodeWrap); 
import addNode from '@/components/addNode.vue'
app.component('addNode', addNode); 

在平台中,流程建模只是工作流模块的一个功能而已,其他地方都不会用到,因此只在自行封装中的flowDesign.vue组件进行了引用。

import nodeWrap from './model/components/nodeWrap.vue'

而addNode组件,会在nodeWrap组件内部用到,因此在nodeWrap组件内部进行了引用。

开源项目workflow-vue3自身没啥集成说明和注意事项,因此大多是看着源码和报错一点点调整。比较耗时。

样式缺失问题

完成上面工作后,js不再输出错误信息,页面能加载内容,建模页面如下:
image.png
明显是css缺失导致的,原项目是加在了setting页面,我加到对应的flowDesign页面,发现仍然是变形的,在nodeWrap组件也追加了后显示正常。
@import ‘…/css/workflow.css’;
image.png
这时候,实际是产生了一个疑问,为啥原项目只需要在外围页面添加一次就行,而我需要在多个页面添加。

图标缺失问题

上面解决了css样式缺失问题,整体显示正常了,但是图标是缺失的,如下图所示:
image.png
这个地方问题排查花了很长时间,一度怀疑是iconfont使用命名与平台原来某个组件重名导致的异常,最后才发现,是css作用域问题,即需要把scoped去除,令其全局生效……这样也解决了上一章节css多次引入问题。

不过,这地方存在一个隐患,即流程建模的css样式,去除了作用域scoped限制,会影响到平台自身一些样式和功能,这块不好排查,等发现了再处理。

后端请求处理

原项目模拟量后端请求调用,包括组织机构、人员、角色、流程配置等,我做了临时性处理,将其注释,或使用静态json数据替换,待后面深度集成时再进行处理,更换为平台真正的后端数据。

运行效果

完成上述工作后,已经可以正常显示跟原项目演示效果一样的预览效果了,如下图:
image.png
这里做了一个默认示例,使用到了发起人、审核人和抄送人,作为初始的示例数据。
image.png

开发平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。

猜你喜欢

转载自blog.csdn.net/seawaving/article/details/131917054
今日推荐