bpmn.js增加bpmnlint的lint验证

1,281 阅读3分钟

前端用bpmn画流程图时,如何能在画的过程中给出一定的提示,无疑能增加一定的体验感。就像写js时可以用eslint进行实时验证,bpmn相应的存在bpmnlint。

安装依赖

npm install -S bpmn-js-bpmnlint bpmnlint bpmnlint-loader

其中,bpmnlint是bpmn-js-bpmnlint的的依赖包,bpmnlint-loader是bpmnlint配置文件的webpack加载器。

bpmnlint的配置文件

在对应的文件夹创建bpmnlint的配置文件.bpmnlintrc,使用bpmnlint默认的校验,

{
    "extends": "bpmnlint:recommended",
    "rules": {}
}

其中,rules是可以配置的规则有

image.png

例如:

{
    "extends": "bpmnlint:recommended",
    "rules": {
        "label-required": "off"
    }
}

配置wepback

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.bpmnlintrc$/,
        use: [
          {
            loader: 'bpmnlint-loader',
          }
        ]
      }
    ]
  }
};

使用

import lintModule from 'bpmn-js-bpmnlint';

import 'bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css';

import BpmnModeler from 'bpmn-js/lib/Modeler';

import bpmnlintConfig from './.bpmnlintrc';

const modeler = new BpmnModeler({
  linting: {
    bpmnlint: bpmnlintConfig
  },
  additionalModules: [
    lintModule
  ]
});

modeler.get('editorActions').trigger('toggleLinting') // 开启

bpmnlint汉化

在创建modeler时,导入汉化包就可以的。

// customTranslate.js
export default function customTranslate(translations) {
    return function(template, replacements) {
        replacements = replacements || {}
        // Translate
        template = translations[template] || template

        // Replace
        return template.replace(/{([^}]+)}/g, function(_, key) {
            let str = replacements[key]
            if (translations[replacements[key]] !== null && translations[replacements[key]] !== undefined) {
                // eslint-disable-next-line no-mixed-spaces-and-tabs
                str = translations[replacements[key]]
                // eslint-disable-next-line no-mixed-spaces-and-tabs
            }
            return str || '{' + key + '}'
        })
    }
}

汉化json文件,zh.json

{
    "Activate the global connect tool": "激活全局连接工具",
    "Append {type}": "追加 {type}",
    "Append EndEvent": "追加 结束事件 ",
    "Append Task": "追加 任务",
    "Append Gateway": "追加 网关",
    "Append Intermediate/Boundary Event": "追加 中间/边界 事件",
    "Add Lane above": "在上面添加道",
    "Divide into two Lanes": "分割成两个道",
    "Divide into three Lanes": "分割成三个道",
    "Add Lane below": "在下面添加道",
    "Append compensation activity": "追加补偿活动",
    "Change type": "修改类型",
    "Connect using Association": "使用关联连接",
    "Connect using Sequence/MessageFlow or Association": "使用顺序/消息流或者关联连接",
    "Connect using DataInputAssociation": "使用数据输入关联连接",
    "Remove": "移除",
    "Activate the hand tool": "激活抓手工具",
    "Activate the lasso tool": "激活套索工具",
    "Activate the create/remove space tool": "激活创建/删除空间工具",
    "Create expanded SubProcess": "创建扩展子过程",
    "Create IntermediateThrowEvent/BoundaryEvent": "创建中间抛出事件/边界事件",
    "Create Pool/Participant": "创建池/参与者",
    "Parallel Multi Instance": "并行多重事件",
    "Sequential Multi Instance": "时序多重事件",
    "DataObjectReference": "数据对象参考",
    "DataStoreReference": "数据存储参考",
    "Loop": "循环",
    "Ad-hoc": "即席",
    "Create {type}": "创建 {type}",
    "Create Task": "创建任务",
    "Create StartEvent": "创建开始事件",
    "Create EndEvent": "创建结束事件",
    "Create Group": "创建组",
    "Task": "任务",
    "Send Task": "发送任务",
    "Receive Task": "接收任务",
    "User Task": "用户任务",
    "Manual Task": "手工任务",
    "Business Rule Task": "业务规则任务",
    "Service Task": "服务任务",
    "Script Task": "脚本任务",
    "Call Activity": "调用活动",
    "Sub Process (collapsed)": "子流程 (折叠的)",
    "Sub Process (expanded)": "子流程 (展开的)",
    "Start Event": "开始事件",
    "StartEvent": "开始事件",
    "Intermediate Throw Event": "中间事件",
    "End Event": "结束事件",
    "EndEvent": "结束事件",
    "Create Gateway": "创建网关",
    "GateWay": "网关",
    "Create Intermediate/Boundary Event": "创建中间/边界事件",
    "Message Start Event": "消息开始事件",
    "Timer Start Event": "定时开始事件",
    "Conditional Start Event": "条件开始事件",
    "Signal Start Event": "信号开始事件",
    "Error Start Event": "错误开始事件",
    "Escalation Start Event": "升级开始事件",
    "Compensation Start Event": "补偿开始事件",
    "Message Start Event (non-interrupting)": "消息开始事件 (非中断)",
    "Timer Start Event (non-interrupting)": "定时开始事件 (非中断)",
    "Conditional Start Event (non-interrupting)": "条件开始事件 (非中断)",
    "Signal Start Event (non-interrupting)": "信号开始事件 (非中断)",
    "Escalation Start Event (non-interrupting)": "升级开始事件 (非中断)",
    "Message Intermediate Catch Event": "消息中间捕获事件",
    "Message Intermediate Throw Event": "消息中间抛出事件",
    "Timer Intermediate Catch Event": "定时中间捕获事件",
    "Escalation Intermediate Throw Event": "升级中间抛出事件",
    "Conditional Intermediate Catch Event": "条件中间捕获事件",
    "Link Intermediate Catch Event": "链接中间捕获事件",
    "Link Intermediate Throw Event": "链接中间抛出事件",
    "Compensation Intermediate Throw Event": "补偿中间抛出事件",
    "Signal Intermediate Catch Event": "信号中间捕获事件",
    "Signal Intermediate Throw Event": "信号中间抛出事件",
    "Message End Event": "消息结束事件",
    "Escalation End Event": "定时结束事件",
    "Error End Event": "错误结束事件",
    "Cancel End Event": "取消结束事件",
    "Compensation End Event": "补偿结束事件",
    "Signal End Event": "信号结束事件",
    "Terminate End Event": "终止结束事件",
    "Message Boundary Event": "消息边界事件",
    "Message Boundary Event (non-interrupting)": "消息边界事件 (非中断)",
    "Timer Boundary Event": "定时边界事件",
    "Timer Boundary Event (non-interrupting)": "定时边界事件 (非中断)",
    "Escalation Boundary Event": "升级边界事件",
    "Escalation Boundary Event (non-interrupting)": "升级边界事件 (非中断)",
    "Conditional Boundary Event": "条件边界事件",
    "Conditional Boundary Event (non-interrupting)": "条件边界事件 (非中断)",
    "Error Boundary Event": "错误边界事件",
    "Cancel Boundary Event": "取消边界事件",
    "Signal Boundary Event": "信号边界事件",
    "Signal Boundary Event (non-interrupting)": "信号边界事件 (非中断)",
    "Compensation Boundary Event": "补偿边界事件",
    "Exclusive Gateway": "互斥网关",
    "Parallel Gateway": "并行网关",
    "Inclusive Gateway": "相容网关",
    "Complex Gateway": "复杂网关",
    "Event based Gateway": "事件网关",
    "Transaction": "转运",
    "Sub Process": "子流程",
    "Event Sub Process": "事件子流程",
    "Collapsed Pool": "折叠池",
    "Expanded Pool": "展开池",
    "no parent for {element} in {parent}": "在{parent}里,{element}没有父类",
    "no shape type specified": "没有指定的形状类型",
    "flow elements must be children of pools/participants": "流元素必须是池/参与者的子类",
    "out of bounds release": "out of bounds release",
    "more than {count} child lanes": "子道大于{count} ",
    "element required": "元素不能为空",
    "diagram not part of bpmn:Definitions": "流程图不符合bpmn规范",
    "no diagram to display": "没有可展示的流程图",
    "no process or collaboration to display": "没有可展示的流程/协作",
    "element {element} referenced by {referenced}#{property} not yet drawn": "由{referenced}#{property}引用的{element}元素仍未绘制",
    "already rendered {element}": "{element} 已被渲染",
    "failed to import {element}": "导入{element}失败",
    "Id": "编号",
    "Name": "名称",
    "General": "常规",
    "Details": "详情",
    "Message Name": "消息名称",
    "Message": "消息",
    "Initiator": "创建者",
    "Asynchronous Continuations": "持续异步",
    "Asynchronous Before": "异步前",
    "Asynchronous After": "异步后",
    "Job Configuration": "工作配置",
    "Exclusive": "排除",
    "Job Priority": "工作优先级",
    "Retry Time Cycle": "重试时间周期",
    "Documentation": "文档",
    "Element Documentation": "元素文档",
    "History Configuration": "历史配置",
    "History Time To Live": "历史的生存时间",
    "Forms": "表单",
    "Form Key": "表单key",
    "Form Fields": "表单字段",
    "Business Key": "业务key",
    "Form Field": "表单字段",
    "ID": "编号",
    "Type": "类型",
    "Label": "名称",
    "Default Value": "默认值",
    "Validation": "校验",
    "Add Constraint": "添加约束",
    "Config": "配置",
    "Properties": "属性",
    "Add Property": "添加属性",
    "Value": "值",
    "Add": "添加",
    "Values": "值",
    "Add Value": "添加值",
    "Listeners": "监听器",
    "Execution Listener": "执行监听",
    "Event Type": "事件类型",
    "Listener Type": "监听器类型",
    "Java Class": "Java类",
    "Expression": "表达式",
    "Must provide a value": "必须提供一个值",
    "Delegate Expression": "代理表达式",
    "Script": "脚本",
    "Script Format": "脚本格式",
    "Script Type": "脚本类型",
    "Inline Script": "内联脚本",
    "External Script": "外部脚本",
    "Resource": "资源",
    "Field Injection": "字段注入",
    "Extensions": "扩展",
    "Input/Output": "输入/输出",
    "Input Parameters": "输入参数",
    "Output Parameters": "输出参数",
    "Parameters": "参数",
    "Output Parameter": "输出参数",
    "Timer Definition Type": "定时器定义类型",
    "Timer Definition": "定时器定义",
    "Date": "日期",
    "Duration": "持续",
    "Cycle": "循环",
    "Signal": "信号",
    "Signal Name": "信号名称",
    "Escalation": "升级",
    "Error": "错误",
    "Link Name": "链接名称",
    "Condition": "条件名称",
    "Variable Name": "变量名称",
    "Variable Event": "变量事件",
    "Specify more than one variable change event as a comma separated list.": "多个变量事件以逗号隔开",
    "Wait for Completion": "等待完成",
    "Activity Ref": "活动参考",
    "Version Tag": "版本标签",
    "Executable": "可执行文件",
    "External Task Configuration": "扩展任务配置",
    "Task Priority": "任务优先级",
    "External": "外部",
    "Connector": "连接器",
    "Must configure Connector": "必须配置连接器",
    "Connector Id": "连接器编号",
    "Implementation": "实现方式",
    "Field Injections": "字段注入",
    "Fields": "字段",
    "Result Variable": "结果变量",
    "Topic": "主题",
    "Configure Connector": "配置连接器",
    "Input Parameter": "输入参数",
    "Assignee": "代理人",
    "Candidate Users": "候选用户",
    "Candidate Groups": "候选组",
    "Due Date": "到期时间",
    "Follow Up Date": "跟踪日期",
    "Priority": "优先级",
    "The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)": "跟踪日期必须符合EL表达式,例如 ${someDate} ,或者一个ISO标准日期(如,2015-06-26T09:54:00)",
    "The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)": "跟踪日期必须符合EL表达式,例如 ${someDate} ,或者一个ISO标准日期(如,2015-06-26T09:54:00)",
    "Variables": "变量",
    "Candidate Starter Configuration": "候选开始配置",
    "Task Listener": "任务监听器",
    "Candidate Starter Groups": "候选开始组",
    "Candidate Starter Users": "候选开始用户",
    "Tasklist Configuration": "任务列表配置",
    "Startable": "启动",
    "Specify more than one group as a comma separated list.": "指定多个组,用逗号分隔",
    "Specify more than one user as a comma separated list.": "指定多个用户,用逗号分隔",
    "This maps to the process definition key.": "这会映射为流程定义的键",
    "CallActivity Type": "调用活动类型",
    "Condition Type": "条件类型",
    "Create UserTask": "创建用户任务",
    "Create CallActivity": "创建调用活动",
    "Called Element": "调用元素",
    "Create DataObjectReference": "创建数据对象引用",
    "Create DataStoreReference": "创建数据存储引用",
    "Multi Instance": "多实例",
    "Loop Cardinality": "实例数量",
    "Collection": "任务参与人列表",
    "Element Variable": "元素变量",
    "Completion Condition": "完成条件",
    // 以下是bpmnlint的汉化
    "{errors} Errors, {warnings} Warnings": "{errors} 错误, {warnings} 警告",
    "Process is missing end event": "流程缺少结束节点",
    "Sub process is missing end event": "子流程缺少结束节点",
    "Process is missing start event": "流程缺少结束节点",
    "Sub process is missing start event": "子流程缺少结束节点",
    "Sequence flow is missing condition": "顺序流缺少条件",
    "Start event is missing event definition": "开始节点缺少事件定义",
    "Incoming flows do not join": "传入流不能连接",
    "Element has disallowed type <{type}>": "元素存在不允许类型<{type}>",
    "Element is missing label/name": "元素缺少标签或者名称",
    "Element is missing bpmndi": "元素缺少bpmni",
    "Element is not connected": "元素缺少连接",
    "SequenceFlow is a duplicate": "流入流出存在重复",
    "Duplicate outgoing sequence flows": "存在重复的流出",
    "Duplicate incoming sequence flows": "存在重复的流入",
    "Gateway forks and joins": "网关同时存在分叉和连接",
    "Flow splits implicitly": "流程隐性分割",
    "Process has multiple blank start events": "流程存在多个空的开始节点",
    "Sub process has multiple blank start events": "子流程存在多个空的开始节点",
    "Event has multiple event definitions": "事件节点存在多个事件定义",
    "Start event must be blank": "不需要开始节点",
    "Gateway is superfluous. It only has one source and target.": "网关是多余的。它只有一个源和目标。"
}

导入汉化

import lintModule from 'bpmn-js-bpmnlint';

import 'bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css';

import BpmnModeler from 'bpmn-js/lib/Modeler';

import bpmnlintConfig from './.bpmnlintrc';

import customTranslate from './translate/customTranslate'
import translationsCN from './translate/zh.json'

const modeler = new BpmnModeler({
  linting: {
    bpmnlint: bpmnlintConfig
  },
  additionalModules: [
    lintModule,
    {
        translate: ['value', customTranslate(translationsCN)]
    }
  ]
});

modeler.get('editorActions').trigger('toggleLinting') // 开启

自定义验证规则

image.png

参考这个,进行相关规则的自定义。