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