height?: string
//
流程图高度
const ViewBpmn: React.FC
<viewProps> = ({ info, highLightData, height = '60vh' }) => {
const [bpmnModler, setBpmnModler] = useState<any>(null)
const bpmnRef = useRef<any>()
const createDiagram = async () => {
const xmlstr = await processDetail(info)
bpmnModler && bpmnModler.destroy && bpmnModler.destroy()
const newBpmn = new BpmnViewer({
container: bpmnRef.current,
height,
const canvas = newBpmn.get('canvas')
newBpmn.importXML(xmlstr, (err: string) => {
if (err) {
message.error(err)
} else {
canvas.zoom('fit-viewport', 'auto')
setBpmnModler(newBpmn)
return
(
<Spin spinning={spinLoading} tip="正在加载...">
{info.instanceId
?
(
<div className={styles.tip}>
<div className={styles.item}>
<div className={styles.susitem} />
<span>已审核</span>
<div className={styles.item}>
<div className={styles.proitem} />
<span>当前审核</span>
<div className={styles.item}>
<div className={styles.unitem} />
<span>待审核</span>
) :
null
}
<div id="canvas" ref={bpmnRef} className={styles.canvas} />
</Spin>
export
default
ViewBpmn
3. 获取已审批和正在审批的节点与线段id,设置样式 我们这里拿到的数据是这样的,主要是节点与线的id
interface viewProps {
info: any
highLightData?: any // 高亮节点
height?: string // 流程图高度
const ViewBpmn: React.FC<viewProps> = ({ info, highLightData, height = '60vh' }) => {
const [bpmnModler, setBpmnModler] = useState<any>(null)
const bpmnRef = useRef<any>()
const createDiagram = async () => {
const xmlstr = await processDetail(info)
bpmnModler && bpmnModler.destroy && bpmnModler.destroy()
const newBpmn = new BpmnViewer({
container: bpmnRef.current,
height,
const canvas = newBpmn.get('canvas')
newBpmn.importXML(xmlstr, (err: string) => {
if (err) {
message.error(err)
} else {
canvas.zoom('fit-viewport', 'auto')
if (highLightData) {
const successIds = highLightData.highLine.concat(highLightData.highPoint)
const procesingIds = highLightData.waitingToDo
setNodeColor(successIds, newBpmn, 'nodeSuccess')
setNodeColor(procesingIds, newBpmn, 'nodeProcing')
setBpmnModler(newBpmn)
return (
<Spin spinning={spinLoading} tip="正在加载...">
{info.instanceId ? (
<div className={styles.tip}>
<div className={styles.item}>
<div className={styles.susitem} />
<span>已审核</span>
<div className={styles.item}>
<div className={styles.proitem} />
<span>当前审核</span>
<div className={styles.item}>
<div className={styles.unitem} />
<span>待审核</span>
) : null}
<div id="canvas" ref={bpmnRef} className={styles.canvas} />
</Spin>
export default ViewBpmn
4. 设置不同颜色的样式,通过增加class类名来控制
// 设置节点颜色
const setNodeColor = (ids: any, newBpmn: any, colorClass: string) => {
const elementRegistry = newBpmn.get('elementRegistry')
ids.forEach((item: any) => {
if (elementRegistry._elements[item]) {
const element = elementRegistry._elements[item].gfx
element.classList.add(colorClass)
// console.log(elementRegistry, element)
5. less样式文件
.canvas {
width: 100%;
height: 100%;
:global(.nodeSuccess .djs-visual > :nth-child(1)) {
stroke: #52c41a !important;
stroke-width: 3px;
:global(.nodeProcing .djs-visual > :nth-child(1)) {
stroke: #1890ff !important;
stroke-width: 3px;
package.json 版本
"dependencies": {
"@types/codemirror": "^5.60.5",
"@umijs/route-utils": "^2.0.0",
"antd": "^4.19.0",
"bpmn-js": "^6.3.4",
"bpmn-js-bpmnlint": "^0.15.0",
"bpmn-js-properties-panel": "^0.33.2",
"bpmn-moddle": "^6.0.0",
"bpmnlint": "^6.4.0",
"braft-editor": "^2.3.9",
"classnames": "^2.3.0",
"codemirror": "^5.59.2",
"echarts": "^5.3.2",
"file-saver": "^2.0.5",
"js-cookie": "^3.0.1",
"lodash": "^4.17.0",
"moment": "^2.29.0",
"omit.js": "^2.0.2",
"rc-menu": "^9.1.0",
"rc-util": "^5.16.0",
"react": "^17.0.0",
"react-codemirror2": "^7.2.1",
"react-dev-inspector": "^1.7.0",
"react-dom": "^17.0.0",
"react-helmet-async": "^1.2.0",
"umi": "^3.5.0",
"umi-plugin-keep-alive": "^0.0.1-beta.30"
"devDependencies": {
"@ant-design/pro-cli": "^2.1.0",
"@playwright/test": "^1.17.0",
"@types/express": "^4.17.0",
"@types/history": "^4.7.0",
"@types/jest": "^26.0.0",
"@types/lodash": "^4.14.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-helmet": "^6.1.0",
"@umijs/fabric": "^2.8.0",
"@umijs/openapi": "^1.3.0",
"@umijs/plugin-blocks": "^2.2.0",
"@umijs/plugin-esbuild": "^1.4.0",
"@umijs/plugin-openapi": "^1.3.0",
"@umijs/preset-ant-design-pro": "^1.3.0",
"@umijs/preset-dumi": "^1.1.0",
"@umijs/preset-react": "^2.1.0",
"cross-env": "^7.0.0",
"cross-port-killer": "^1.3.0",
"detect-installer": "^1.0.0",
"eslint": "^7.32.0",
"gh-pages": "^3.2.0",
"husky": "^7.0.4",
"jsdom-global": "^3.0.0",
"lint-staged": "^10.0.0",
"mockjs": "^1.1.0",
"prettier": "^2.5.0",
"stylelint": "^13.0.0",
"swagger-ui-react": "^3.52.0",
"typescript": "^4.5.0",
"umi-serve": "^1.9.10"
import React, { useState, useEffect, useRef } from 'react'
import { Spin, message } from 'antd'
import { processDetail, processApprovalDetail } from '@/services'
import BpmnViewer from 'bpmn-js/lib/Viewer'
import styles from './index.less'
interface viewProps {
info: any
highLightData?: any
height?: string
const ViewBpmn: React.FC<viewProps> = ({ info, highLightData, height = '60vh' }) => {
const [spinLoading, setSpinLoading] = useState<boolean>(true)
const [bpmnModler, setBpmnModler] = useState<any>(null)
const bpmnRef = useRef<any>()
// 设置节点颜色
const setNodeColor = (ids: any, newBpmn: any, colorClass: string) => {
const elementRegistry = newBpmn.get('elementRegistry')
ids.forEach((item: any) => {
if (elementRegistry._elements[item]) {
const element = elementRegistry._elements[item].gfx
element.classList.add(colorClass)
// console.log(elementRegistry, element)
const createDiagram = (xmlstr: string) => {
bpmnModler && bpmnModler.destroy && bpmnModler.destroy()
const newBpmn = new BpmnViewer({
container: bpmnRef.current,
height,
const canvas = newBpmn.get('canvas')
newBpmn.importXML(xmlstr, (err: string) => {
if (err) {
message.error(err)
} else {
canvas.zoom('fit-viewport', 'auto')
if (highLightData) {
const successIds = highLightData.highLine.concat(highLightData.highPoint)
const procesingIds = highLightData.waitingToDo
setNodeColor(successIds, newBpmn, 'nodeSuccess')
setNodeColor(procesingIds, newBpmn, 'nodeProcing')
setBpmnModler(newBpmn)
const getProcessDetail = async () => {
let diagramXML
if (info.instanceId) {
// 如果是审批详情
diagramXML = await processApprovalDetail(info.instanceId)
} else {
diagramXML = await processDetail(info)
createDiagram(diagramXML)
setSpinLoading(false)
useEffect(() => {
getProcessDetail()
}, [])
return (
<Spin spinning={spinLoading} tip="正在加载...">
{info.instanceId ? (
<div className={styles.tip}>
<div className={styles.item}>
<div className={styles.susitem} />
<span>已审核</span>
<div className={styles.item}>
<div className={styles.proitem} />
<span>当前审核</span>
<div className={styles.item}>
<div className={styles.unitem} />
<span>待审核</span>
) : null}
<div id="canvas" ref={bpmnRef} className={styles.canvas} />
</Spin>
export default ViewBpmn