diff --git a/README.md b/README.md
index 2c5ce5999..62d89fe60 100644
--- a/README.md
+++ b/README.md
@@ -21,10 +21,10 @@
* 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款。
* 集成阿里云、腾讯云、云片等短信渠道,集成阿里云、腾讯云、七牛云等云存储服务。
-| 项目名 | 说明 | 传说门 |
-| ---- | ---- | ---- |
-| `ruoyi-vue-pro` | Spring Boot 版本 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)** [Github](https://github.com/YunaiV/ruoyi-vue-pro) |
-| `ruoyi-vue-cloud` | Spring Cloud 版本 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-cloud)** [Github](https://github.com/YunaiV/onemall) |
+| 项目名 | 说明 | 传说门 |
+| ---- |------------------------| ---- |
+| `ruoyi-vue-pro` | Spring Boot 多模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)** [Github](https://github.com/YunaiV/ruoyi-vue-pro) |
+| `ruoyi-vue-cloud` | Spring Cloud 微服务 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-cloud)** [Github](https://github.com/YunaiV/onemall) |
| `Spring-Boot-Labs` | Spring Boot & Cloud 入门 | **[Gitee](https://gitee.com/zhijiantianya/SpringBoot-Labs)** [Github](https://github.com/YunaiV/SpringBoot-Labs) |
## 🐶 在线体验
diff --git a/sql/activiti.sql b/sql/bpm-activiti.sql
similarity index 100%
rename from sql/activiti.sql
rename to sql/bpm-activiti.sql
diff --git a/sql/bpm-flowable.sql b/sql/bpm-flowable.sql
new file mode 100644
index 000000000..d5d4ee33d
--- /dev/null
+++ b/sql/bpm-flowable.sql
@@ -0,0 +1,1329 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server : 127.0.0.1
+ Source Server Type : MySQL
+ Source Server Version : 80026
+ Source Host : localhost:3306
+ Source Schema : ruoyi-vue-pro-flowable
+
+ Target Server Type : MySQL
+ Target Server Version : 80026
+ File Encoding : 65001
+
+ Date: 28/02/2022 00:57:25
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for ACT_EVT_LOG
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_EVT_LOG`;
+CREATE TABLE `ACT_EVT_LOG` (
+ `LOG_NR_` bigint NOT NULL AUTO_INCREMENT,
+ `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TIME_STAMP_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DATA_` longblob,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `IS_PROCESSED_` tinyint DEFAULT '0',
+ PRIMARY KEY (`LOG_NR_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_EVT_LOG
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_GE_BYTEARRAY
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_GE_BYTEARRAY`;
+CREATE TABLE `ACT_GE_BYTEARRAY` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `BYTES_` longblob,
+ `GENERATED_` tinyint DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_FK_BYTEARR_DEPL` (`DEPLOYMENT_ID_`),
+ CONSTRAINT `ACT_FK_BYTEARR_DEPL` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `ACT_RE_DEPLOYMENT` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_GE_BYTEARRAY
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_GE_BYTEARRAY` VALUES ('7bac85f2-97ed-11ec-a2b9-862bc1a4a054', 2, 'source', NULL, 0x3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D225554462D38223F3E0A3C62706D6E323A646566696E6974696F6E7320786D6C6E733A7873693D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612D696E7374616E63652220786D6C6E733A62706D6E323D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F4D4F44454C2220786D6C6E733A62706D6E64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F44492220786D6C6E733A64633D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44432220786D6C6E733A64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F4449222069643D226469616772616D5F50726F636573735F3136343539383036353033313122207461726765744E616D6573706163653D22687474703A2F2F61637469766974692E6F72672F62706D6E223E3C62706D6E323A70726F636573732069643D22666C6F7761626C655F303122206E616D653D22666C6F7761626C65E6B58BE8AF952220697345786563757461626C653D2274727565223E3C62706D6E323A73746172744576656E742069643D224576656E745F3169727578696D223E3C62706D6E323A6F7574676F696E673E466C6F775F30383034676D6F3C2F62706D6E323A6F7574676F696E673E3C2F62706D6E323A73746172744576656E743E3C62706D6E323A757365725461736B2069643D227461736B303122206E616D653D227461736B3031223E3C62706D6E323A696E636F6D696E673E466C6F775F30383034676D6F3C2F62706D6E323A696E636F6D696E673E3C62706D6E323A6F7574676F696E673E466C6F775F306378343739783C2F62706D6E323A6F7574676F696E673E3C2F62706D6E323A757365725461736B3E3C62706D6E323A73657175656E6365466C6F772069643D22466C6F775F30383034676D6F2220736F757263655265663D224576656E745F3169727578696D22207461726765745265663D227461736B303122202F3E3C62706D6E323A656E644576656E742069643D224576656E745F316D647363637A223E3C62706D6E323A696E636F6D696E673E466C6F775F306378343739783C2F62706D6E323A696E636F6D696E673E3C2F62706D6E323A656E644576656E743E3C62706D6E323A73657175656E6365466C6F772069643D22466C6F775F306378343739782220736F757263655265663D227461736B303122207461726765745265663D224576656E745F316D647363637A22202F3E3C2F62706D6E323A70726F636573733E3C62706D6E64693A42504D4E4469616772616D2069643D2242504D4E4469616772616D5F31223E3C62706D6E64693A42504D4E506C616E652069643D22666C6F7761626C655F30315F6469222062706D6E456C656D656E743D22666C6F7761626C655F3031223E3C62706D6E64693A42504D4E456467652069643D22466C6F775F306378343739785F6469222062706D6E456C656D656E743D22466C6F775F30637834373978223E3C64693A776179706F696E7420783D223434302220793D2233353022202F3E3C64693A776179706F696E7420783D223439322220793D2233353022202F3E3C2F62706D6E64693A42504D4E456467653E3C62706D6E64693A42504D4E456467652069643D22466C6F775F30383034676D6F5F6469222062706D6E456C656D656E743D22466C6F775F30383034676D6F223E3C64693A776179706F696E7420783D223238382220793D2233353022202F3E3C64693A776179706F696E7420783D223334302220793D2233353022202F3E3C2F62706D6E64693A42504D4E456467653E3C62706D6E64693A42504D4E53686170652069643D224576656E745F3169727578696D5F6469222062706D6E456C656D656E743D224576656E745F3169727578696D223E3C64633A426F756E647320783D223235322220793D22333332222077696474683D22333622206865696768743D22333622202F3E3C2F62706D6E64693A42504D4E53686170653E3C62706D6E64693A42504D4E53686170652069643D227461736B30315F6469222062706D6E456C656D656E743D227461736B3031223E3C64633A426F756E647320783D223334302220793D22333130222077696474683D2231303022206865696768743D22383022202F3E3C2F62706D6E64693A42504D4E53686170653E3C62706D6E64693A42504D4E53686170652069643D224576656E745F316D647363637A5F6469222062706D6E456C656D656E743D224576656E745F316D647363637A223E3C64633A426F756E647320783D223439322220793D22333332222077696474683D22333622206865696768743D22333622202F3E3C2F62706D6E64693A42504D4E53686170653E3C2F62706D6E64693A42504D4E506C616E653E3C2F62706D6E64693A42504D4E4469616772616D3E3C2F62706D6E323A646566696E6974696F6E733E, NULL);
+INSERT INTO `ACT_GE_BYTEARRAY` VALUES ('bfb4c0a4-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01.bpmn', 'bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', 0x3C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D225554462D38223F3E0A3C62706D6E323A646566696E6974696F6E7320786D6C6E733A7873693D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612D696E7374616E63652220786D6C6E733A62706D6E323D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F4D4F44454C2220786D6C6E733A62706D6E64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F42504D4E2F32303130303532342F44492220786D6C6E733A64633D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F44432220786D6C6E733A64693D22687474703A2F2F7777772E6F6D672E6F72672F737065632F44442F32303130303532342F4449222069643D226469616772616D5F50726F636573735F3136343539383036353033313122207461726765744E616D6573706163653D22687474703A2F2F61637469766974692E6F72672F62706D6E223E3C62706D6E323A70726F636573732069643D22666C6F7761626C655F303122206E616D653D22666C6F7761626C65E6B58BE8AF952220697345786563757461626C653D2274727565223E3C62706D6E323A73746172744576656E742069643D224576656E745F3169727578696D223E3C62706D6E323A6F7574676F696E673E466C6F775F30383034676D6F3C2F62706D6E323A6F7574676F696E673E3C2F62706D6E323A73746172744576656E743E3C62706D6E323A757365725461736B2069643D227461736B303122206E616D653D227461736B3031223E3C62706D6E323A696E636F6D696E673E466C6F775F30383034676D6F3C2F62706D6E323A696E636F6D696E673E3C62706D6E323A6F7574676F696E673E466C6F775F306378343739783C2F62706D6E323A6F7574676F696E673E3C2F62706D6E323A757365725461736B3E3C62706D6E323A73657175656E6365466C6F772069643D22466C6F775F30383034676D6F2220736F757263655265663D224576656E745F3169727578696D22207461726765745265663D227461736B303122202F3E3C62706D6E323A656E644576656E742069643D224576656E745F316D647363637A223E3C62706D6E323A696E636F6D696E673E466C6F775F306378343739783C2F62706D6E323A696E636F6D696E673E3C2F62706D6E323A656E644576656E743E3C62706D6E323A73657175656E6365466C6F772069643D22466C6F775F306378343739782220736F757263655265663D227461736B303122207461726765745265663D224576656E745F316D647363637A22202F3E3C2F62706D6E323A70726F636573733E3C62706D6E64693A42504D4E4469616772616D2069643D2242504D4E4469616772616D5F31223E3C62706D6E64693A42504D4E506C616E652069643D22666C6F7761626C655F30315F6469222062706D6E456C656D656E743D22666C6F7761626C655F3031223E3C62706D6E64693A42504D4E456467652069643D22466C6F775F306378343739785F6469222062706D6E456C656D656E743D22466C6F775F30637834373978223E3C64693A776179706F696E7420783D223434302220793D2233353022202F3E3C64693A776179706F696E7420783D223439322220793D2233353022202F3E3C2F62706D6E64693A42504D4E456467653E3C62706D6E64693A42504D4E456467652069643D22466C6F775F30383034676D6F5F6469222062706D6E456C656D656E743D22466C6F775F30383034676D6F223E3C64693A776179706F696E7420783D223238382220793D2233353022202F3E3C64693A776179706F696E7420783D223334302220793D2233353022202F3E3C2F62706D6E64693A42504D4E456467653E3C62706D6E64693A42504D4E53686170652069643D224576656E745F3169727578696D5F6469222062706D6E456C656D656E743D224576656E745F3169727578696D223E3C64633A426F756E647320783D223235322220793D22333332222077696474683D22333622206865696768743D22333622202F3E3C2F62706D6E64693A42504D4E53686170653E3C62706D6E64693A42504D4E53686170652069643D227461736B30315F6469222062706D6E456C656D656E743D227461736B3031223E3C64633A426F756E647320783D223334302220793D22333130222077696474683D2231303022206865696768743D22383022202F3E3C2F62706D6E64693A42504D4E53686170653E3C62706D6E64693A42504D4E53686170652069643D224576656E745F316D647363637A5F6469222062706D6E456C656D656E743D224576656E745F316D647363637A223E3C64633A426F756E647320783D223439322220793D22333332222077696474683D22333622206865696768743D22333622202F3E3C2F62706D6E64693A42504D4E53686170653E3C2F62706D6E64693A42504D4E506C616E653E3C2F62706D6E64693A42504D4E4469616772616D3E3C2F62706D6E323A646566696E6974696F6E733E, 0);
+INSERT INTO `ACT_GE_BYTEARRAY` VALUES ('c0bae605-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01.flowable_01.png', 'bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', 0x89504E470D0A1A0A0000000D494844520000021A000001900806000000E87AC905000010174944415478DAEDDD0B8896F59E07F0531854D8952516929038D021160A3AD0424B146C6450ED093273D4AC316D2D1BEDA25D305BCDAE6BB638854442EDD9A2C432375BCE76BCA4633A8A5D5C2F15999D2E8EB38EBA9AE6F136F5ECF37B9877781C9D1C67E6BDCCF8F9C01FDF79DF77DE9197E7F93FDFE77FFDCD6F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A2549923EDF7CF3CD9C952B57FEBC68D1A264C182054A89CBC2850B93BABABAED6919EA8804A0578990B16CD9B2A4A9A9293970E08052A6B26DDBB664E9D2A53FA6A1E366472500BD46B46408191513360E2C58B0E00B472500BD467497B8C8574E4983C621472500BD468C117081AFA8A091382A0138E182C64FBB1A936F56BF9A6C5838252BF1389E130E040D00E852D0D8B3B32159FFC163C9FFFCD7F8C34A3C17AF0908820600743A68FCB0E1BD234246A16CDE305F40103400A0F341E38B0F9F6D3768C46B0282A001009D0E1AEB17FC4BBB41235E1310040D001034040D00A8BCA011B34CDA0B1AF19A8020680040A783C6C6E52FB61B34E2350141D000804E078D1D0D6B93F57F7EFCC86E93F4B9784D40103400A0D34123CA5F3EFEE31141239E130E040D00E85AD0D8BF3FD9B862E691DD26E973F19A8020680040A78246ACFCF9D5F2DA76C768C46B5607153400E0F882C6FEFD49E3C6C5C9BAFF7EB4DD905128F19E78AFD60D4103008E19348ED58AA17543D000804E078D8EB462FC5AEB86C020680040BB41A3B321A3500406410300DA0D1A8AA0512EB7DF7EFBD9B7DE7AEBCD69A94D4B7D5A1AD392E44AFC5C3F68D0A057060F1E3C342D7FE32C064A6AF3E6CD97BCFBEEBBFFF6D24B2FAD9F3871E29E3163C6FC3C64C890D68A6AE4C891071F78E0811D93274FAE9B366DDA3FA715DBA982860BBCA0515E6970B83E3D3FE7A7C1A1B94DB03866497F67415AFE70D55557F5510302459124499FFAFAFA093366CC684C8344F2F4D34F2773E7CE4DD6AC599334343424CDCDCD49C18E1D3B92B56BD726F3E6CD4B5E7CF1C5240D1ACDE3C78F5F515D5D7D89A0A1081AA5950685DFA72161E5F1868B76CAEAF4B306A811816EB574E9D2EA175E7861CFDD77DF9DCC993327696C6C4C8EC7CE9D3BB3CAFD9E7BEE39545353B33CADACFA0B1A8AA0515CD1FA908682A78FD682F1D0430F65E7F2F2E5CB93EFBFFF3ED9B76F5F76AE1E3C7830FB79E5CA95D98DC4638F3DD65EE0A83DD15B2A816E6AC5983D7BF6BAEAEAEAE4CD37DF6CAD8C3A2B5A3DA29563D8B06187468C18F190A0A1081AC53164C8907E6D5B31D2F32E79F5D5578FFB46E1DB6FBF4D66CD9A152D936DC3C6BAF83B6A4AA053D2CAA87F6D6D6DD3B871E3B28AA63BC5E7DD77DF7DFB468E1CF9FA8970572468081AA594068CDF5555556DC98782E8EA6C6A6AEAD2791B5DA253A64C691B367E38D15A28816E0A19D15512CDA6D1ED510CD13AF2E4934FEE1D3162C49F7AFB00334143D028654B463E64442BC692254B0E1B43D555CB962DCB3E57D8003A25BA4BA22523424657BB4A3AD2953275EAD4DD69A5354BD050048DAE691993D1DA5D1233C1BEFCF2CBA29CBB3186A34D57CABA810307F6558302C7146332A2BB64F7EEDD49294498A9A9A9D99D568A13040D45D0E8BC18F8996FC92856C8C8878DFCB4F61820AA06057E555D5DDDC818F8D9DD63323A326623ADB0F6A57744BF15341441E3F8B54C616D9D5D12DD25A510DD286DD6DB30F51538BAE83279FEF9E77F8AD925E53077EEDC5D69D8982B68288246A75A3356E6077E76E7988C6369334074B545BD80A38AC5B8629D8C628FCBF8B5F11AD5D5D55BABAAAA2E15341441A3E35A56FC6CED32E9EAEC92CECC46C98FD7881544D5A8C011A64F9FDE180BF894D3FCF9F363F4FA7F081A8AA0D171B1AC78E1221FEB6494C3EBAFBF7ED872E56A54E030B177492C2B7EBC0BF974B7984A5B5555F57FBD6D6D0D4143D02896D8202D3F36A35CE770B4A2E40786DA880D384C6C90F6DC73CF2595E091471E591D4DC13DE17B6BD968EA1F040D41A35CC757CB2EACADCB8A97537EB9F2D8F555CD0AB49A3163C686D8D7A012BCF6DA6BEB7ACA34B97C53711A8EFE5ED010344A7D7CB56CF59EBDAFDC5D9F518714FE2FB1C5BC9A1568155BBDC72EAC95E0D34F3FDD985654F53DE942902B7F3ADA1DA8A0216814EBF88A73A5F07A6C90564EB1AE46EEFF5AAF66055A8D1933E6E7728FCF28D8BE7DFB4F6925D5D8432F04AD77A0F90B82A0216814EBF88A73A5F07CECBA5A4E0D0D0DF9FF67A39A15681583B84A39EFFE58A2A2EAC91782FC1D6834790B1A8246B18EAFFCCFB1C57B39C5DFCFFF7FD4ACC061155A25E94005DBA38AA05159A5B71D5F855269E7AE9A15A8D4168D3DBDA045239B39535821F1440A1AFBF7EF3FEAF33FFEF863B6189C168DEE3DBEF2CF976BB13D2D1AC0318D1E3DFA40A58CD1D8BA75EBFA1E3C46E3B080515029412342C0AC59B39237DE78A353BFFFD65B6FC5C52379E79D778E786DEAD4A9C959679D959C79E699D934C7FC6BB18854FCDECC9933058D6E3EBEF263344ABD4791311A40874D9830E17F2B65D6497D7DFD921E38EBA43E965D6E6F8F874A091A2B56ACC82EF8D3A64DEB52D078FBEDB70F7B3E8E9D934E3A29B9EEBAEB921B6EB8217B4FCC40D8B3674FF2ECB3CF26A79F7EBAA051A4E3CBAC13A047983265CA9F2B651D8DE9D3A7CFEF41EB681CB505A35283C6A5975E9A5DF0CF3DF7DCA4B6B6366B6ABFF3CE3B93F3CF3F3F39F5D45393ABAFBE3ABB2B8DD6ADE84E3BEFBCF392BE7DFB66FB58446B483E68BCF2CA2B49FFFEFD93B163C726CF3CF34CF67C0499CF3EFB2C7BFCF8E38F27AB56ADCA3EF7C61B6F14348A747CE5D7D1983D7BB6753480CA94DE75DE91DEE5FE520941E3AEBBEE9ADF535606EDA84A091AE3C78FCF2EF8D1F250575797BCF7DE7B5957C7A44993927BEFBD377B2D02C4C48913B3C7D1CD128F2FBEF8E2ECFD85A0317AF4E8E494534E49AEBCF2CA6CEC454D4D4DF6FCC68D1B93CD9B37678F478D1A956CD9B225F9EAABAF92850B170A1AC50B235606052A5FEC2D525D5D7D3076612CF31A1A313E639BBD4E4AD775B278F1E264C28409C965975D96BD165B7EBFFFFEFBD9E3E8F2B8E69A6BB280B077EFDED6A051281F7DF451F61963C68CC97EFEFAEBAF5B8346B49414FE86A051D473F7ECF49C3954B8C06FDAB4A96C7B9D545555FD62AF13A05DE9DDD087F3E7CF2F6BD0A8ADADFD77BBB7962E6844EB45A185235A35E2F1134F3CD13A80F3A69B6ECA5A3CE2F9E86A29048D0B2FBC3039EDB4D3926BAFBD367B6FFC4E3C1F5D256BD7AECD1EE707840A1A456FD568DDBDF5E5975FB67B2B5099AAABAB2F19356A5473B9A6C8353737FF9056505FA77745970A1AC5291F7FFC7176C14FBFE3E4934F3EC9BA37E2E70F3EF82079F4D147B3C7D155124DF0E79C734E12C133C663C4F3E3C68D6B0D1A3116E0E1871FCE1E47F74B74ABC4E341830625B7DD765BF6385A4A048DD288AEC6C2457ED8B06159EB4229454BE8F0E1C3F3AD197F50A302473576ECD8A5E51A14FAD4534FBD965652737AE3F75A294163E7CE9D49BF7EFDB28BFE830F3E18337C920B2EB820FBF9F2CB2F4FCE38E38CAC15E3BBEFBE4BAEB8E28AA44F9F3E59CBC5800103B22E91FCF4D6EDDBB76783452FBAE8A26C5069749F9C7CF2C9D9EC937CB789A051B2568DD6D927D1FD55CA7571E2EFE5A7E01E6B703470021B3870E0DFDE71C71D074A3D1FFFF3CF3F5F9A56507BD2BFFF5B41A3B825C65A4468C8AFAD11334D8EF6DEB853DDB56B57873F3BDEBF6DDB364B9097C12DB7DCF28FF93537962C5952927377D9B2656DF76119A026057E55555555CDB871E3FE5AAA2E94F4C2B721FD9B1BD24AEAC1DEFA9D5A825CD02851ABC6BF162EF8313D394240B1D7CD183A74E82FB9A051AB06053A64C488117F9C3C7972D1C3467373F3B7D5D5D58BD30A6A666FFE3E050D41A3145A9624AFCF878D622DE2152163F8F0E13FE742C6BA810307F6557B021DAEB0D200F09F93264DDA5DACB0112D1969A0F930C665F4B6E9AC8286A0512E69B8E8979E531BF36123BA51BA73CC46B494B469C9F8212DFDD59CC071878DAAAAAA976B6A6A7677F7988D1893D1D25D32B3B7870C4143D028B5B8E8E7C3466180685767A3C4189C36033F850CA0EB060D1A3426BD2BFA69F6ECD93B6377C6AE4E616D995DB2A7378FC91034048D0A69D9A8CF878298FA1AEBA31CEF068A1150629D8CFC14D64277899001748B988D3278F0E0B7D38A66D79C397336A57736878E77C5CF588C2BFD8C2FA3AB24FDF77727D2F72768081AE56A954C6F145E38DA56F3B16E4AAC87126338A2C5B2701311FFC62CA41883316FDEBC6CE1B5FC8A9FF9819FC66400C568DDF8BBD82C29AD7876DF7FFFFD6B66CD9AB566D5AA559BB66CD9B237972BF644B0885D586383B4D8BB2496154FC3C59BBD71312E4143D0A8742D535FEB8F16383A51569BC20A145D8CAB68A9BC623A5D0CE8FC4B7EBF85B434B6546CB5B16AE189300E43D010347AC08DC2F52DCB951F3ADE8011CB8AB7B7553D0082862268E46F14CE4E43C7AD2D5BCCD7B7DC18246D6F14A2F53276618DAE53673180A0A1081A00081A8AA001008286A0010082862268002068B8C00B1A002068081A00206828820600081A820600081A820600081A8AA001008286A001008286A00100828622680080A021680080A021680080A0A1081A002068081A00502E8B162D7281AF9CB22F0D1A871C9500F41A7575758D4D4D4D2EF215501A1A1ADE4A83C6178E4A007A8DC58B17FFD392254B766DDDBAF5AF2EF6E56BC98890B170E1C2EFD272B3A312805E25BDB85D9FDE49AF8E66FB1823A094BCC4F7FE859001000000000000000000000000000000000000F408FF0FC85213564CA9202B0000000049454E44AE426082, 1);
+INSERT INTO `ACT_GE_BYTEARRAY` VALUES ('c969093d-97ed-11ec-a2b9-862bc1a4a054', 1, 'hist.var-field122', NULL, 0xACED0005737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000178, NULL);
+INSERT INTO `ACT_GE_BYTEARRAY` VALUES ('c969304e-97ed-11ec-a2b9-862bc1a4a054', 1, 'hist.detail.var-field122', NULL, 0xACED0005737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65787000000001770400000001737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000178, NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_GE_PROPERTY
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_GE_PROPERTY`;
+CREATE TABLE `ACT_GE_PROPERTY` (
+ `NAME_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `VALUE_` varchar(300) COLLATE utf8_bin DEFAULT NULL,
+ `REV_` int DEFAULT NULL,
+ PRIMARY KEY (`NAME_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_GE_PROPERTY
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('batch.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('cfg.execution-related-entities-count', 'true', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('cfg.task-related-entities-count', 'true', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('common.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('entitylink.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('eventsubscription.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('identitylink.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('job.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('next.dbid', '1', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('schema.history', 'create(6.7.0.0)', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('task.schema.version', '6.7.0.0', 1);
+INSERT INTO `ACT_GE_PROPERTY` VALUES ('variable.schema.version', '6.7.0.0', 1);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_ACTINST
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_ACTINST`;
+CREATE TABLE `ACT_HI_ACTINST` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT '1',
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `ACT_ID_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CALL_PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_TIME_` datetime(3) NOT NULL,
+ `END_TIME_` datetime(3) DEFAULT NULL,
+ `TRANSACTION_ORDER_` int DEFAULT NULL,
+ `DURATION_` bigint DEFAULT NULL,
+ `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_ACT_INST_START` (`START_TIME_`),
+ KEY `ACT_IDX_HI_ACT_INST_END` (`END_TIME_`),
+ KEY `ACT_IDX_HI_ACT_INST_PROCINST` (`PROC_INST_ID_`,`ACT_ID_`),
+ KEY `ACT_IDX_HI_ACT_INST_EXEC` (`EXECUTION_ID_`,`ACT_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_ACTINST
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_ACTINST` VALUES ('c9695761-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', 'Event_1iruxim', NULL, NULL, NULL, 'startEvent', NULL, '2022-02-28 00:53:28.382', '2022-02-28 00:53:28.388', 1, 6, NULL, '');
+INSERT INTO `ACT_HI_ACTINST` VALUES ('c96b0512-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', 'Flow_0804gmo', NULL, NULL, NULL, 'sequenceFlow', NULL, '2022-02-28 00:53:28.392', '2022-02-28 00:53:28.392', 2, 0, NULL, '');
+INSERT INTO `ACT_HI_ACTINST` VALUES ('c96b0513-97ed-11ec-a2b9-862bc1a4a054', 2, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', 'task01', 'c97146a4-97ed-11ec-a2b9-862bc1a4a054', NULL, 'task01', 'userTask', '1', '2022-02-28 00:53:28.392', '2022-02-28 00:53:34.789', 3, 6397, NULL, '');
+INSERT INTO `ACT_HI_ACTINST` VALUES ('cd3b6e08-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', 'Flow_0cx479x', NULL, NULL, NULL, 'sequenceFlow', NULL, '2022-02-28 00:53:34.792', '2022-02-28 00:53:34.792', 1, 0, NULL, '');
+INSERT INTO `ACT_HI_ACTINST` VALUES ('cd3be339-97ed-11ec-a2b9-862bc1a4a054', 1, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', 'Event_1mdsccz', NULL, NULL, NULL, 'endEvent', NULL, '2022-02-28 00:53:34.794', '2022-02-28 00:53:34.796', 2, 2, NULL, '');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_ATTACHMENT
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_ATTACHMENT`;
+CREATE TABLE `ACT_HI_ATTACHMENT` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `URL_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CONTENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TIME_` datetime(3) DEFAULT NULL,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_ATTACHMENT
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_COMMENT
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_COMMENT`;
+CREATE TABLE `ACT_HI_COMMENT` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TIME_` datetime(3) NOT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACTION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `MESSAGE_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `FULL_MSG_` longblob,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_COMMENT
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_DETAIL
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_DETAIL`;
+CREATE TABLE `ACT_HI_DETAIL` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `VAR_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REV_` int DEFAULT NULL,
+ `TIME_` datetime(3) NOT NULL,
+ `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DOUBLE_` double DEFAULT NULL,
+ `LONG_` bigint DEFAULT NULL,
+ `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_DETAIL_PROC_INST` (`PROC_INST_ID_`),
+ KEY `ACT_IDX_HI_DETAIL_ACT_INST` (`ACT_INST_ID_`),
+ KEY `ACT_IDX_HI_DETAIL_TIME` (`TIME_`),
+ KEY `ACT_IDX_HI_DETAIL_NAME` (`NAME_`),
+ KEY `ACT_IDX_HI_DETAIL_TASK_ID` (`TASK_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_DETAIL
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_DETAIL` VALUES ('c9681eda-97ed-11ec-a2b9-862bc1a4a054', 'VariableUpdate', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, 'field121', 'string', 0, '2022-02-28 00:53:28.373', NULL, NULL, NULL, 'AAA', NULL);
+INSERT INTO `ACT_HI_DETAIL` VALUES ('c969304f-97ed-11ec-a2b9-862bc1a4a054', 'VariableUpdate', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, 'field122', 'serializable', 0, '2022-02-28 00:53:28.379', 'c969304e-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_ENTITYLINK
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_ENTITYLINK`;
+CREATE TABLE `ACT_HI_ENTITYLINK` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `LINK_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` datetime(3) DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ROOT_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ROOT_SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HIERARCHY_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_ENT_LNK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_HI_ENT_LNK_REF_SCOPE` (`REF_SCOPE_ID_`,`REF_SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_HI_ENT_LNK_ROOT_SCOPE` (`ROOT_SCOPE_ID_`,`ROOT_SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_HI_ENT_LNK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`,`LINK_TYPE_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_ENTITYLINK
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_IDENTITYLINK
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_IDENTITYLINK`;
+CREATE TABLE `ACT_HI_IDENTITYLINK` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` datetime(3) DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_USER` (`USER_ID_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_TASK` (`TASK_ID_`),
+ KEY `ACT_IDX_HI_IDENT_LNK_PROCINST` (`PROC_INST_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_IDENTITYLINK
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_IDENTITYLINK` VALUES ('c9651198-97ed-11ec-a2b9-862bc1a4a054', NULL, 'starter', '1', NULL, '2022-02-28 00:53:28.353', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL);
+INSERT INTO `ACT_HI_IDENTITYLINK` VALUES ('c9769dd5-97ed-11ec-a2b9-862bc1a4a054', NULL, 'assignee', '1', 'c97146a4-97ed-11ec-a2b9-862bc1a4a054', '2022-02-28 00:53:28.468', NULL, NULL, NULL, NULL, NULL);
+INSERT INTO `ACT_HI_IDENTITYLINK` VALUES ('c978e7c6-97ed-11ec-a2b9-862bc1a4a054', NULL, 'participant', '1', NULL, '2022-02-28 00:53:28.483', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL);
+INSERT INTO `ACT_HI_IDENTITYLINK` VALUES ('cd377667-97ed-11ec-a2b9-862bc1a4a054', NULL, 'participant', '1', NULL, '2022-02-28 00:53:34.765', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_PROCINST
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_PROCINST`;
+CREATE TABLE `ACT_HI_PROCINST` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT '1',
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `START_TIME_` datetime(3) NOT NULL,
+ `END_TIME_` datetime(3) DEFAULT NULL,
+ `DURATION_` bigint DEFAULT NULL,
+ `START_USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `END_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUPER_PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CALLBACK_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CALLBACK_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REFERENCE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REFERENCE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROPAGATED_STAGE_INST_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ UNIQUE KEY `PROC_INST_ID_` (`PROC_INST_ID_`),
+ KEY `ACT_IDX_HI_PRO_INST_END` (`END_TIME_`),
+ KEY `ACT_IDX_HI_PRO_I_BUSKEY` (`BUSINESS_KEY_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_PROCINST
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_PROCINST` VALUES ('c964c377-97ed-11ec-a2b9-862bc1a4a054', 3, 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', '2022-02-28 00:53:28.351', '2022-02-28 00:53:34.899', 6548, '1', 'Event_1iruxim', 'Event_1mdsccz', NULL, NULL, '', 'flowable测试', NULL, NULL, NULL, NULL, NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_TASKINST
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_TASKINST`;
+CREATE TABLE `ACT_HI_TASKINST` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT '1',
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROPAGATED_STAGE_INST_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_TIME_` datetime(3) NOT NULL,
+ `CLAIM_TIME_` datetime(3) DEFAULT NULL,
+ `END_TIME_` datetime(3) DEFAULT NULL,
+ `DURATION_` bigint DEFAULT NULL,
+ `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `PRIORITY_` int DEFAULT NULL,
+ `DUE_DATE_` datetime(3) DEFAULT NULL,
+ `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `LAST_UPDATED_TIME_` datetime(3) DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_TASK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_TASK_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_TASK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_TASK_INST_PROCINST` (`PROC_INST_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_TASKINST
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_TASKINST` VALUES ('c97146a4-97ed-11ec-a2b9-862bc1a4a054', 2, 'flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', NULL, 'task01', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c9695760-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL, NULL, 'task01', NULL, NULL, NULL, '1', '2022-02-28 00:53:28.392', NULL, '2022-02-28 00:53:34.779', 6387, NULL, 50, NULL, NULL, NULL, '', '2022-02-28 00:53:34.779');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_TSK_LOG
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_TSK_LOG`;
+CREATE TABLE `ACT_HI_TSK_LOG` (
+ `ID_` bigint NOT NULL AUTO_INCREMENT,
+ `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `TIME_STAMP_` timestamp(3) NOT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DATA_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_TSK_LOG
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_HI_VARINST
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_HI_VARINST`;
+CREATE TABLE `ACT_HI_VARINST` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT '1',
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `VAR_TYPE_` varchar(100) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DOUBLE_` double DEFAULT NULL,
+ `LONG_` bigint DEFAULT NULL,
+ `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` datetime(3) DEFAULT NULL,
+ `LAST_UPDATED_TIME_` datetime(3) DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_HI_PROCVAR_NAME_TYPE` (`NAME_`,`VAR_TYPE_`),
+ KEY `ACT_IDX_HI_VAR_SCOPE_ID_TYPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_VAR_SUB_ID_TYPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_HI_PROCVAR_PROC_INST` (`PROC_INST_ID_`),
+ KEY `ACT_IDX_HI_PROCVAR_TASK_ID` (`TASK_ID_`),
+ KEY `ACT_IDX_HI_PROCVAR_EXE` (`EXECUTION_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_HI_VARINST
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_HI_VARINST` VALUES ('c9678299-97ed-11ec-a2b9-862bc1a4a054', 0, 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, 'field121', 'string', NULL, NULL, NULL, NULL, NULL, NULL, 'AAA', NULL, '2022-02-28 00:53:28.373', '2022-02-28 00:53:28.373');
+INSERT INTO `ACT_HI_VARINST` VALUES ('c969093c-97ed-11ec-a2b9-862bc1a4a054', 0, 'c964c377-97ed-11ec-a2b9-862bc1a4a054', 'c964c377-97ed-11ec-a2b9-862bc1a4a054', NULL, 'field122', 'serializable', NULL, NULL, NULL, 'c969093d-97ed-11ec-a2b9-862bc1a4a054', NULL, NULL, NULL, NULL, '2022-02-28 00:53:28.379', '2022-02-28 00:53:28.379');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_BYTEARRAY
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_BYTEARRAY`;
+CREATE TABLE `ACT_ID_BYTEARRAY` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `BYTES_` longblob,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_BYTEARRAY
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_GROUP
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_GROUP`;
+CREATE TABLE `ACT_ID_GROUP` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_GROUP
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_INFO
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_INFO`;
+CREATE TABLE `ACT_ID_INFO` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `USER_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `VALUE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PASSWORD_` longblob,
+ `PARENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_INFO
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_MEMBERSHIP
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_MEMBERSHIP`;
+CREATE TABLE `ACT_ID_MEMBERSHIP` (
+ `USER_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `GROUP_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ PRIMARY KEY (`USER_ID_`,`GROUP_ID_`),
+ KEY `ACT_FK_MEMB_GROUP` (`GROUP_ID_`),
+ CONSTRAINT `ACT_FK_MEMB_GROUP` FOREIGN KEY (`GROUP_ID_`) REFERENCES `ACT_ID_GROUP` (`ID_`),
+ CONSTRAINT `ACT_FK_MEMB_USER` FOREIGN KEY (`USER_ID_`) REFERENCES `ACT_ID_USER` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_MEMBERSHIP
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_PRIV
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_PRIV`;
+CREATE TABLE `ACT_ID_PRIV` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,
+ PRIMARY KEY (`ID_`),
+ UNIQUE KEY `ACT_UNIQ_PRIV_NAME` (`NAME_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_PRIV
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_PRIV_MAPPING
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_PRIV_MAPPING`;
+CREATE TABLE `ACT_ID_PRIV_MAPPING` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `PRIV_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_FK_PRIV_MAPPING` (`PRIV_ID_`),
+ KEY `ACT_IDX_PRIV_USER` (`USER_ID_`),
+ KEY `ACT_IDX_PRIV_GROUP` (`GROUP_ID_`),
+ CONSTRAINT `ACT_FK_PRIV_MAPPING` FOREIGN KEY (`PRIV_ID_`) REFERENCES `ACT_ID_PRIV` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_PRIV_MAPPING
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_PROPERTY
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_PROPERTY`;
+CREATE TABLE `ACT_ID_PROPERTY` (
+ `NAME_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `VALUE_` varchar(300) COLLATE utf8_bin DEFAULT NULL,
+ `REV_` int DEFAULT NULL,
+ PRIMARY KEY (`NAME_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_PROPERTY
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_ID_PROPERTY` VALUES ('schema.version', '6.7.0.0', 1);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_TOKEN
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_TOKEN`;
+CREATE TABLE `ACT_ID_TOKEN` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `TOKEN_VALUE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TOKEN_DATE_` timestamp(3) NULL DEFAULT NULL,
+ `IP_ADDRESS_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `USER_AGENT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TOKEN_DATA_` varchar(2000) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_TOKEN
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_ID_USER
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_ID_USER`;
+CREATE TABLE `ACT_ID_USER` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `FIRST_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `LAST_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DISPLAY_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EMAIL_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PWD_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PICTURE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_ID_USER
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_PROCDEF_INFO
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_PROCDEF_INFO`;
+CREATE TABLE `ACT_PROCDEF_INFO` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `INFO_JSON_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ UNIQUE KEY `ACT_UNIQ_INFO_PROCDEF` (`PROC_DEF_ID_`),
+ KEY `ACT_IDX_INFO_PROCDEF` (`PROC_DEF_ID_`),
+ KEY `ACT_FK_INFO_JSON_BA` (`INFO_JSON_ID_`),
+ CONSTRAINT `ACT_FK_INFO_JSON_BA` FOREIGN KEY (`INFO_JSON_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_INFO_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_PROCDEF_INFO
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RE_DEPLOYMENT
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RE_DEPLOYMENT`;
+CREATE TABLE `ACT_RE_DEPLOYMENT` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `DEPLOY_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `DERIVED_FROM_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DERIVED_FROM_ROOT_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_DEPLOYMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ENGINE_VERSION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RE_DEPLOYMENT
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_RE_DEPLOYMENT` VALUES ('bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', 'flowable测试', '1', 'flowable_01', '', '2022-02-28 00:53:12.098', NULL, NULL, 'bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', NULL);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RE_MODEL
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RE_MODEL`;
+CREATE TABLE `ACT_RE_MODEL` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LAST_UPDATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `VERSION_` int DEFAULT NULL,
+ `META_INFO_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EDITOR_SOURCE_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EDITOR_SOURCE_EXTRA_VALUE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_FK_MODEL_SOURCE` (`EDITOR_SOURCE_VALUE_ID_`),
+ KEY `ACT_FK_MODEL_SOURCE_EXTRA` (`EDITOR_SOURCE_EXTRA_VALUE_ID_`),
+ KEY `ACT_FK_MODEL_DEPLOYMENT` (`DEPLOYMENT_ID_`),
+ CONSTRAINT `ACT_FK_MODEL_DEPLOYMENT` FOREIGN KEY (`DEPLOYMENT_ID_`) REFERENCES `ACT_RE_DEPLOYMENT` (`ID_`),
+ CONSTRAINT `ACT_FK_MODEL_SOURCE` FOREIGN KEY (`EDITOR_SOURCE_VALUE_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_MODEL_SOURCE_EXTRA` FOREIGN KEY (`EDITOR_SOURCE_EXTRA_VALUE_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RE_MODEL
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_RE_MODEL` VALUES ('4b4909d8-97e7-11ec-8e20-862bc1a4a054', 6, 'flowable测试', 'flowable_01', '1', '2022-02-28 00:06:59.795', '2022-02-28 00:53:13.893', 1, '{\"description\":\"ooxx\",\"formType\":10,\"formId\":11,\"formCustomCreatePath\":null,\"formCustomViewPath\":null}', 'bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', '7bac85f2-97ed-11ec-a2b9-862bc1a4a054', NULL, '');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RE_PROCDEF
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RE_PROCDEF`;
+CREATE TABLE `ACT_RE_PROCDEF` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `KEY_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `VERSION_` int NOT NULL,
+ `DEPLOYMENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DGRM_RESOURCE_NAME_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `HAS_START_FORM_KEY_` tinyint DEFAULT NULL,
+ `HAS_GRAPHICAL_NOTATION_` tinyint DEFAULT NULL,
+ `SUSPENSION_STATE_` int DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `ENGINE_VERSION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DERIVED_FROM_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DERIVED_FROM_ROOT_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DERIVED_VERSION_` int NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID_`),
+ UNIQUE KEY `ACT_UNIQ_PROCDEF` (`KEY_`,`VERSION_`,`DERIVED_VERSION_`,`TENANT_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RE_PROCDEF
+-- ----------------------------
+BEGIN;
+INSERT INTO `ACT_RE_PROCDEF` VALUES ('flowable_01:1:c0bb5b36-97ed-11ec-a2b9-862bc1a4a054', 2, '1', 'flowable测试', 'flowable_01', 1, 'bfb4c0a3-97ed-11ec-a2b9-862bc1a4a054', 'flowable_01.bpmn', 'flowable_01.flowable_01.png', NULL, 0, 1, 1, '', NULL, NULL, NULL, 0);
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_ACTINST
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_ACTINST`;
+CREATE TABLE `ACT_RU_ACTINST` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT '1',
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `ACT_ID_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CALL_PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_TIME_` datetime(3) NOT NULL,
+ `END_TIME_` datetime(3) DEFAULT NULL,
+ `DURATION_` bigint DEFAULT NULL,
+ `TRANSACTION_ORDER_` int DEFAULT NULL,
+ `DELETE_REASON_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_RU_ACTI_START` (`START_TIME_`),
+ KEY `ACT_IDX_RU_ACTI_END` (`END_TIME_`),
+ KEY `ACT_IDX_RU_ACTI_PROC` (`PROC_INST_ID_`),
+ KEY `ACT_IDX_RU_ACTI_PROC_ACT` (`PROC_INST_ID_`,`ACT_ID_`),
+ KEY `ACT_IDX_RU_ACTI_EXEC` (`EXECUTION_ID_`),
+ KEY `ACT_IDX_RU_ACTI_EXEC_ACT` (`EXECUTION_ID_`,`ACT_ID_`),
+ KEY `ACT_IDX_RU_ACTI_TASK` (`TASK_ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_ACTINST
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_DEADLETTER_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_DEADLETTER_JOB`;
+CREATE TABLE `ACT_RU_DEADLETTER_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `EXCLUSIVE_` tinyint(1) DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CORRELATION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DUEDATE_` timestamp(3) NULL DEFAULT NULL,
+ `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_DEADLETTER_JOB_EXCEPTION_STACK_ID` (`EXCEPTION_STACK_ID_`),
+ KEY `ACT_IDX_DEADLETTER_JOB_CUSTOM_VALUES_ID` (`CUSTOM_VALUES_ID_`),
+ KEY `ACT_IDX_DEADLETTER_JOB_CORRELATION_ID` (`CORRELATION_ID_`),
+ KEY `ACT_IDX_DJOB_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_DJOB_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_DJOB_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_DEADLETTER_JOB_EXECUTION` (`EXECUTION_ID_`),
+ KEY `ACT_FK_DEADLETTER_JOB_PROCESS_INSTANCE` (`PROCESS_INSTANCE_ID_`),
+ KEY `ACT_FK_DEADLETTER_JOB_PROC_DEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_DEADLETTER_JOB_CUSTOM_VALUES` FOREIGN KEY (`CUSTOM_VALUES_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_DEADLETTER_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_DEADLETTER_JOB_EXECUTION` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_DEADLETTER_JOB_PROC_DEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_DEADLETTER_JOB_PROCESS_INSTANCE` FOREIGN KEY (`PROCESS_INSTANCE_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_DEADLETTER_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_ENTITYLINK
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_ENTITYLINK`;
+CREATE TABLE `ACT_RU_ENTITYLINK` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CREATE_TIME_` datetime(3) DEFAULT NULL,
+ `LINK_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REF_SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ROOT_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ROOT_SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HIERARCHY_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_ENT_LNK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_ENT_LNK_REF_SCOPE` (`REF_SCOPE_ID_`,`REF_SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_ENT_LNK_ROOT_SCOPE` (`ROOT_SCOPE_ID_`,`ROOT_SCOPE_TYPE_`,`LINK_TYPE_`),
+ KEY `ACT_IDX_ENT_LNK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`,`LINK_TYPE_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_ENTITYLINK
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_EVENT_SUBSCR
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_EVENT_SUBSCR`;
+CREATE TABLE `ACT_RU_EVENT_SUBSCR` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `EVENT_TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `EVENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACTIVITY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CONFIGURATION_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CREATED_` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_EVENT_SUBSCR_CONFIG_` (`CONFIGURATION_`),
+ KEY `ACT_FK_EVENT_EXEC` (`EXECUTION_ID_`),
+ CONSTRAINT `ACT_FK_EVENT_EXEC` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_EVENT_SUBSCR
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_EXECUTION
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_EXECUTION`;
+CREATE TABLE `ACT_RU_EXECUTION` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `BUSINESS_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SUPER_EXEC_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ROOT_PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `IS_ACTIVE_` tinyint DEFAULT NULL,
+ `IS_CONCURRENT_` tinyint DEFAULT NULL,
+ `IS_SCOPE_` tinyint DEFAULT NULL,
+ `IS_EVENT_SCOPE_` tinyint DEFAULT NULL,
+ `IS_MI_ROOT_` tinyint DEFAULT NULL,
+ `SUSPENSION_STATE_` int DEFAULT NULL,
+ `CACHED_ENT_STATE_` int DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_ACT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `START_TIME_` datetime(3) DEFAULT NULL,
+ `START_USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `LOCK_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `IS_COUNT_ENABLED_` tinyint DEFAULT NULL,
+ `EVT_SUBSCR_COUNT_` int DEFAULT NULL,
+ `TASK_COUNT_` int DEFAULT NULL,
+ `JOB_COUNT_` int DEFAULT NULL,
+ `TIMER_JOB_COUNT_` int DEFAULT NULL,
+ `SUSP_JOB_COUNT_` int DEFAULT NULL,
+ `DEADLETTER_JOB_COUNT_` int DEFAULT NULL,
+ `EXTERNAL_WORKER_JOB_COUNT_` int DEFAULT NULL,
+ `VAR_COUNT_` int DEFAULT NULL,
+ `ID_LINK_COUNT_` int DEFAULT NULL,
+ `CALLBACK_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CALLBACK_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REFERENCE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `REFERENCE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROPAGATED_STAGE_INST_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_EXEC_BUSKEY` (`BUSINESS_KEY_`),
+ KEY `ACT_IDC_EXEC_ROOT` (`ROOT_PROC_INST_ID_`),
+ KEY `ACT_IDX_EXEC_REF_ID_` (`REFERENCE_ID_`),
+ KEY `ACT_FK_EXE_PROCINST` (`PROC_INST_ID_`),
+ KEY `ACT_FK_EXE_PARENT` (`PARENT_ID_`),
+ KEY `ACT_FK_EXE_SUPER` (`SUPER_EXEC_`),
+ KEY `ACT_FK_EXE_PROCDEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_EXE_PARENT` FOREIGN KEY (`PARENT_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`) ON DELETE CASCADE,
+ CONSTRAINT `ACT_FK_EXE_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_EXE_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `ACT_FK_EXE_SUPER` FOREIGN KEY (`SUPER_EXEC_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_EXECUTION
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_EXTERNAL_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_EXTERNAL_JOB`;
+CREATE TABLE `ACT_RU_EXTERNAL_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EXCLUSIVE_` tinyint(1) DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CORRELATION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `RETRIES_` int DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DUEDATE_` timestamp(3) NULL DEFAULT NULL,
+ `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_EXTERNAL_JOB_EXCEPTION_STACK_ID` (`EXCEPTION_STACK_ID_`),
+ KEY `ACT_IDX_EXTERNAL_JOB_CUSTOM_VALUES_ID` (`CUSTOM_VALUES_ID_`),
+ KEY `ACT_IDX_EXTERNAL_JOB_CORRELATION_ID` (`CORRELATION_ID_`),
+ KEY `ACT_IDX_EJOB_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_EJOB_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_EJOB_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ CONSTRAINT `ACT_FK_EXTERNAL_JOB_CUSTOM_VALUES` FOREIGN KEY (`CUSTOM_VALUES_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_EXTERNAL_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_EXTERNAL_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_HISTORY_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_HISTORY_JOB`;
+CREATE TABLE `ACT_RU_HISTORY_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `RETRIES_` int DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ADV_HANDLER_CFG_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_HISTORY_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_IDENTITYLINK
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_IDENTITYLINK`;
+CREATE TABLE `ACT_RU_IDENTITYLINK` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `GROUP_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `USER_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_IDENT_LNK_USER` (`USER_ID_`),
+ KEY `ACT_IDX_IDENT_LNK_GROUP` (`GROUP_ID_`),
+ KEY `ACT_IDX_IDENT_LNK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_IDENT_LNK_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_IDENT_LNK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_ATHRZ_PROCEDEF` (`PROC_DEF_ID_`),
+ KEY `ACT_FK_TSKASS_TASK` (`TASK_ID_`),
+ KEY `ACT_FK_IDL_PROCINST` (`PROC_INST_ID_`),
+ CONSTRAINT `ACT_FK_ATHRZ_PROCEDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_IDL_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_TSKASS_TASK` FOREIGN KEY (`TASK_ID_`) REFERENCES `ACT_RU_TASK` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_IDENTITYLINK
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_JOB`;
+CREATE TABLE `ACT_RU_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EXCLUSIVE_` tinyint(1) DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CORRELATION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `RETRIES_` int DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DUEDATE_` timestamp(3) NULL DEFAULT NULL,
+ `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_JOB_EXCEPTION_STACK_ID` (`EXCEPTION_STACK_ID_`),
+ KEY `ACT_IDX_JOB_CUSTOM_VALUES_ID` (`CUSTOM_VALUES_ID_`),
+ KEY `ACT_IDX_JOB_CORRELATION_ID` (`CORRELATION_ID_`),
+ KEY `ACT_IDX_JOB_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_JOB_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_JOB_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_JOB_EXECUTION` (`EXECUTION_ID_`),
+ KEY `ACT_FK_JOB_PROCESS_INSTANCE` (`PROCESS_INSTANCE_ID_`),
+ KEY `ACT_FK_JOB_PROC_DEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_JOB_CUSTOM_VALUES` FOREIGN KEY (`CUSTOM_VALUES_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_JOB_EXECUTION` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_JOB_PROC_DEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_JOB_PROCESS_INSTANCE` FOREIGN KEY (`PROCESS_INSTANCE_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_SUSPENDED_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_SUSPENDED_JOB`;
+CREATE TABLE `ACT_RU_SUSPENDED_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `EXCLUSIVE_` tinyint(1) DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CORRELATION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `RETRIES_` int DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DUEDATE_` timestamp(3) NULL DEFAULT NULL,
+ `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_SUSPENDED_JOB_EXCEPTION_STACK_ID` (`EXCEPTION_STACK_ID_`),
+ KEY `ACT_IDX_SUSPENDED_JOB_CUSTOM_VALUES_ID` (`CUSTOM_VALUES_ID_`),
+ KEY `ACT_IDX_SUSPENDED_JOB_CORRELATION_ID` (`CORRELATION_ID_`),
+ KEY `ACT_IDX_SJOB_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_SJOB_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_SJOB_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_SUSPENDED_JOB_EXECUTION` (`EXECUTION_ID_`),
+ KEY `ACT_FK_SUSPENDED_JOB_PROCESS_INSTANCE` (`PROCESS_INSTANCE_ID_`),
+ KEY `ACT_FK_SUSPENDED_JOB_PROC_DEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_SUSPENDED_JOB_CUSTOM_VALUES` FOREIGN KEY (`CUSTOM_VALUES_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_SUSPENDED_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_SUSPENDED_JOB_EXECUTION` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_SUSPENDED_JOB_PROC_DEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_SUSPENDED_JOB_PROCESS_INSTANCE` FOREIGN KEY (`PROCESS_INSTANCE_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_SUSPENDED_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_TASK
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_TASK`;
+CREATE TABLE `ACT_RU_TASK` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PROPAGATED_STAGE_INST_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `PARENT_TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DESCRIPTION_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_DEF_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ASSIGNEE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `DELEGATION_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PRIORITY_` int DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `DUE_DATE_` datetime(3) DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUSPENSION_STATE_` int DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ `FORM_KEY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CLAIM_TIME_` datetime(3) DEFAULT NULL,
+ `IS_COUNT_ENABLED_` tinyint DEFAULT NULL,
+ `VAR_COUNT_` int DEFAULT NULL,
+ `ID_LINK_COUNT_` int DEFAULT NULL,
+ `SUB_TASK_COUNT_` int DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_TASK_CREATE` (`CREATE_TIME_`),
+ KEY `ACT_IDX_TASK_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_TASK_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_TASK_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_TASK_EXE` (`EXECUTION_ID_`),
+ KEY `ACT_FK_TASK_PROCINST` (`PROC_INST_ID_`),
+ KEY `ACT_FK_TASK_PROCDEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_TASK_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_TASK_PROCDEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_TASK_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_TASK
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_TIMER_JOB
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_TIMER_JOB`;
+CREATE TABLE `ACT_RU_TIMER_JOB` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `CATEGORY_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `LOCK_EXP_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `LOCK_OWNER_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `EXCLUSIVE_` tinyint(1) DEFAULT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROCESS_INSTANCE_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_DEF_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `ELEMENT_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_DEFINITION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `CORRELATION_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `RETRIES_` int DEFAULT NULL,
+ `EXCEPTION_STACK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `EXCEPTION_MSG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `DUEDATE_` timestamp(3) NULL DEFAULT NULL,
+ `REPEAT_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `HANDLER_CFG_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `CUSTOM_VALUES_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `CREATE_TIME_` timestamp(3) NULL DEFAULT NULL,
+ `TENANT_ID_` varchar(255) COLLATE utf8_bin DEFAULT '',
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_TIMER_JOB_EXCEPTION_STACK_ID` (`EXCEPTION_STACK_ID_`),
+ KEY `ACT_IDX_TIMER_JOB_CUSTOM_VALUES_ID` (`CUSTOM_VALUES_ID_`),
+ KEY `ACT_IDX_TIMER_JOB_CORRELATION_ID` (`CORRELATION_ID_`),
+ KEY `ACT_IDX_TIMER_JOB_DUEDATE` (`DUEDATE_`),
+ KEY `ACT_IDX_TJOB_SCOPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_TJOB_SUB_SCOPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_TJOB_SCOPE_DEF` (`SCOPE_DEFINITION_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_TIMER_JOB_EXECUTION` (`EXECUTION_ID_`),
+ KEY `ACT_FK_TIMER_JOB_PROCESS_INSTANCE` (`PROCESS_INSTANCE_ID_`),
+ KEY `ACT_FK_TIMER_JOB_PROC_DEF` (`PROC_DEF_ID_`),
+ CONSTRAINT `ACT_FK_TIMER_JOB_CUSTOM_VALUES` FOREIGN KEY (`CUSTOM_VALUES_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_TIMER_JOB_EXCEPTION` FOREIGN KEY (`EXCEPTION_STACK_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_TIMER_JOB_EXECUTION` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_TIMER_JOB_PROC_DEF` FOREIGN KEY (`PROC_DEF_ID_`) REFERENCES `ACT_RE_PROCDEF` (`ID_`),
+ CONSTRAINT `ACT_FK_TIMER_JOB_PROCESS_INSTANCE` FOREIGN KEY (`PROCESS_INSTANCE_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_TIMER_JOB
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for ACT_RU_VARIABLE
+-- ----------------------------
+DROP TABLE IF EXISTS `ACT_RU_VARIABLE`;
+CREATE TABLE `ACT_RU_VARIABLE` (
+ `ID_` varchar(64) COLLATE utf8_bin NOT NULL,
+ `REV_` int DEFAULT NULL,
+ `TYPE_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `NAME_` varchar(255) COLLATE utf8_bin NOT NULL,
+ `EXECUTION_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `PROC_INST_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `TASK_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SUB_SCOPE_ID_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `SCOPE_TYPE_` varchar(255) COLLATE utf8_bin DEFAULT NULL,
+ `BYTEARRAY_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL,
+ `DOUBLE_` double DEFAULT NULL,
+ `LONG_` bigint DEFAULT NULL,
+ `TEXT_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ `TEXT2_` varchar(4000) COLLATE utf8_bin DEFAULT NULL,
+ PRIMARY KEY (`ID_`),
+ KEY `ACT_IDX_RU_VAR_SCOPE_ID_TYPE` (`SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_IDX_RU_VAR_SUB_ID_TYPE` (`SUB_SCOPE_ID_`,`SCOPE_TYPE_`),
+ KEY `ACT_FK_VAR_BYTEARRAY` (`BYTEARRAY_ID_`),
+ KEY `ACT_IDX_VARIABLE_TASK_ID` (`TASK_ID_`),
+ KEY `ACT_FK_VAR_EXE` (`EXECUTION_ID_`),
+ KEY `ACT_FK_VAR_PROCINST` (`PROC_INST_ID_`),
+ CONSTRAINT `ACT_FK_VAR_BYTEARRAY` FOREIGN KEY (`BYTEARRAY_ID_`) REFERENCES `ACT_GE_BYTEARRAY` (`ID_`),
+ CONSTRAINT `ACT_FK_VAR_EXE` FOREIGN KEY (`EXECUTION_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`),
+ CONSTRAINT `ACT_FK_VAR_PROCINST` FOREIGN KEY (`PROC_INST_ID_`) REFERENCES `ACT_RU_EXECUTION` (`ID_`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;
+
+-- ----------------------------
+-- Records of ACT_RU_VARIABLE
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 127835b6f..d42256024 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -399,6 +399,11 @@
${revision}
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-flowable
+ ${revision}
+
org.flowable
flowable-spring-boot-starter-basic
diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml
index 85533c9a2..8c4a9b586 100644
--- a/yudao-framework/pom.xml
+++ b/yudao-framework/pom.xml
@@ -35,12 +35,13 @@
yudao-spring-boot-starter-biz-social
yudao-spring-boot-starter-biz-tenant
yudao-spring-boot-starter-biz-data-permission
+ yudao-spring-boot-starter-flowable
yudao-framework
该包是技术组件,每个子包,代表一个组件。每个组件包括两部分:
- 1. core 包:是该组件的核心分装
+ 1. core 包:是该组件的核心封装
2. config 包:是该组件基于 Spring 的配置
技术组件,也分成两类:
diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
index d00cb780e..2e4d9ab95 100644
--- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
+++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java
@@ -29,6 +29,8 @@ public interface WebFilterOrderEnum {
int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面
+ int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
+
int DEMO_FILTER = Integer.MAX_VALUE;
}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml
new file mode 100644
index 000000000..0ad946284
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/pom.xml
@@ -0,0 +1,37 @@
+
+
+
+ yudao-framework
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+
+ yudao-spring-boot-starter-flowable
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-security
+
+
+
+
+ org.flowable
+ flowable-spring-boot-starter-basic
+
+
+ org.flowable
+ flowable-spring-boot-starter-actuator
+
+
+
+
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
new file mode 100644
index 000000000..4061339d6
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.framework.flowable.config;
+
+import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
+import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class YudaoFlowableConfiguration {
+
+ /**
+ * 配置 flowable Web 过滤器
+ */
+ @Bean
+ public FilterRegistrationBean flowableWebFilter() {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(new FlowableWebFilter());
+ registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER);
+ return registrationBean;
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
new file mode 100644
index 000000000..de8d6279d
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.framework.flowable.core;
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
new file mode 100644
index 000000000..3621d9d99
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.framework.flowable.core.util;
+
+import org.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.common.engine.impl.identity.Authentication;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class FlowableUtils {
+
+ public static void setAuthenticatedUserId(Long userId) {
+ Authentication.setAuthenticatedUserId(String.valueOf(userId));
+ }
+
+ public static void clearAuthenticatedUserId() {
+ Authentication.setAuthenticatedUserId(null);
+ }
+
+ /**
+ * 获得 BPMN 流程中,指定的元素们
+ *
+ * @param model
+ * @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
+ * @return 元素们
+ */
+ public static List getBpmnModelElements(BpmnModel model, Class clazz) {
+ List result = new ArrayList<>();
+ model.getProcesses().forEach(process -> {
+ process.getFlowElements().forEach(flowElement -> {
+ if (flowElement.getClass().isAssignableFrom(clazz)) {
+ result.add((T) flowElement);
+ }
+ });
+ });
+ return result;
+ }
+
+ /**
+ * 比较 两个bpmnModel 是否相同
+ * @param oldModel 老的bpmn model
+ * @param newModel 新的bpmn model
+ */
+ public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
+ // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
+ return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
+ }
+
+ /**
+ * 把 bpmnModel 转换成 byte[]
+ * @param model bpmnModel
+ */
+ public static byte[] getBpmnBytes(BpmnModel model) {
+ if (model == null) {
+ return new byte[0];
+ }
+ BpmnXMLConverter converter = new BpmnXMLConverter();
+ return converter.convertToXML(model);
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java
new file mode 100644
index 000000000..d9845a394
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/web/FlowableWebFilter.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.framework.flowable.core.web;
+
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+/**
+ * flowable Web 过滤器,将 userId 设置到 {@link org.flowable.common.engine.impl.identity.Authentication} 中
+ *
+ * @author jason
+ */
+public class FlowableWebFilter extends OncePerRequestFilter {
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
+ try {
+ // 设置工作流的用户
+ Long userId = SecurityFrameworkUtils.getLoginUserId();
+ if (userId != null) {
+ FlowableUtils.setAuthenticatedUserId(userId);
+ }
+ // 过滤
+ chain.doFilter(request, response);
+ } finally {
+ // 清理
+ FlowableUtils.clearAuthenticatedUserId();
+ }
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
new file mode 100644
index 000000000..324d3de0e
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.framework.flowable;
diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..c667d5e55
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration
diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml
index ff6cd817f..44081d86b 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml
@@ -12,7 +12,7 @@
jar
${project.artifactId}
- 用户的认证、权限的校验
+ Web 框架,全局异常、API 日志等
https://github.com/YunaiV/ruoyi-vue-pro
diff --git a/yudao-module-bpm/yudao-module-bpm-base/pom.xml b/yudao-module-bpm/yudao-module-bpm-base/pom.xml
index 44a0dbd2a..1980a094d 100644
--- a/yudao-module-bpm/yudao-module-bpm-base/pom.xml
+++ b/yudao-module-bpm/yudao-module-bpm-base/pom.xml
@@ -32,6 +32,10 @@
cn.iocoder.boot
yudao-spring-boot-starter-biz-operatelog
+
+ cn.iocoder.boot
+ yudao-spring-boot-starter-biz-data-permission
+
diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java
index a90fc9760..80355ef5e 100644
--- a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java
+++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java
@@ -88,4 +88,12 @@ public interface BpmFormService {
*/
PageResult getFormPage(BpmFormPageReqVO pageReqVO);
+ /**
+ * 校验流程表单已配置
+ *
+ * @param configStr configStr 字段
+ * @return 流程表单
+ */
+ BpmFormDO checkFormConfig(String configStr);
+
}
diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
index 42f1b145c..d64684b82 100644
--- a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.service.definition;
import cn.hutool.core.lang.Assert;
+import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
@@ -8,18 +9,20 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 动态表单 Service 实现类
@@ -87,6 +90,29 @@ public class BpmFormServiceImpl implements BpmFormService {
return formMapper.selectPage(pageReqVO);
}
+
+ @Override
+ public BpmFormDO checkFormConfig(String configStr) {
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(configStr, BpmModelMetaInfoRespDTO.class);
+ if (metaInfo == null || metaInfo.getFormType() == null) {
+ throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
+ }
+ // 校验表单存在
+ if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
+ BpmFormDO form = getForm(metaInfo.getFormId());
+ if (form == null) {
+ throw exception(FORM_NOT_EXISTS);
+ }
+ return form;
+ }
+ return null;
+ }
+
+ private void checkKeyNCName(String key) {
+ if (!ValidationUtils.isXmlNCName(key)) {
+ throw exception(MODEL_KEY_VALID);
+ }
+ }
/**
* 校验 Field,避免 field 重复
*
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
similarity index 90%
rename from yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
index e50dae3c3..3a36b0eeb 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
+++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java
@@ -5,7 +5,7 @@ import lombok.Data;
/**
* BPM 流程 MetaInfo Response DTO
- * 主要用于 {@link org.activiti.engine.repository.Model#setMetaInfo(String)} 的存储
+ * 主要用于 { Model#setMetaInfo(String)} 的存储
*
* @author 芋道源码
*/
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
similarity index 100%
rename from yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
index a1d05e4fc..ff3966025 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
@@ -8,7 +8,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
/**
- * 流程实例 Api 实现类
+ * Activiti 流程实例 Api 实现类
*
* @author 芋道源码
*/
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
index 4a570d1fc..5d8b4bfcc 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
@@ -93,5 +93,4 @@ public class BpmModelController {
bpmModelService.updateModelState(reqVO.getId(), reqVO.getState());
return success(true);
}
-
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
index 1be0b7487..b51a4661b 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
@@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.bpm.controller.admin.definition;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -32,7 +32,7 @@ public class BpmTaskAssignRuleController {
@ApiOperation(value = "获得任务分配规则列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "modelId", value = "模型编号", example = "1024", dataTypeClass = String.class),
- @ApiImplicitParam(name = "processDefinitionId", value = "刘晨定义的编号", example = "2048", dataTypeClass = String.class)
+ @ApiImplicitParam(name = "processDefinitionId", value = "流程定义的编号", example = "2048", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:query')")
public CommonResult> getTaskAssignRuleList(
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
index 3c3542aa3..6b8f6dff0 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -37,7 +37,7 @@ public class BpmTaskController {
@GetMapping("done-page")
@ApiOperation("获取 Done 已办任务分页")
@PreAuthorize("@ss.hasPermission('bpm:task:query')")
- public CommonResult> getTodoTaskPage(@Valid BpmTaskDonePageReqVO pageVO) {
+ public CommonResult> getDoneTaskPage(@Valid BpmTaskDonePageReqVO pageVO) {
return success(taskService.getDoneTaskPage(getLoginUserId(), pageVO));
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
index 445911c8c..171bbbb53 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.bpm.convert.definition;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import org.activiti.engine.impl.persistence.entity.SuspensionState;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
index 17a4fb144..b789bc000 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
@@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.bpm.convert.definition;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import org.activiti.engine.impl.persistence.entity.SuspensionState;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java
index d394f8631..76f0d97a0 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java
@@ -44,7 +44,7 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
@Override
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
- BpmUserTaskActivitiBehavior userTaskActivityBehavior = new BpmUserTaskActivitiBehavior(userTask);
+ BpmUserTaskActivityBehavior userTaskActivityBehavior = new BpmUserTaskActivityBehavior(userTask);
userTaskActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService);
userTaskActivityBehavior.setPermissionApi(permissionApi);
userTaskActivityBehavior.setDeptApi(deptApi);
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java
similarity index 98%
rename from yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java
rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java
index 9fb1f5abb..ed95b4c8a 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java
@@ -44,7 +44,7 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_F
* @author 芋道源码
*/
@Slf4j
-public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior {
+public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
@Setter
private BpmTaskAssignRuleService bpmTaskRuleService;
@@ -64,7 +64,7 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior {
*/
private Map scriptMap = Collections.emptyMap();
- public BpmUserTaskActivitiBehavior(UserTask userTask) {
+ public BpmUserTaskActivityBehavior(UserTask userTask) {
super(userTask);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
index e0714731a..4b0a7c1eb 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;
@@ -15,6 +16,7 @@ import java.util.Set;
public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
@Override
+ @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
public Set calculateTaskCandidateUsers(TaskEntity task) {
return calculateTaskCandidateUsers(task, 1);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
index 7ad928c8d..41ee8254b 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;
@@ -15,6 +16,7 @@ import java.util.Set;
public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
@Override
+ @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
public Set calculateTaskCandidateUsers(TaskEntity task) {
return calculateTaskCandidateUsers(task, 2);
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
index ec2d6a0c9..fea5398a7 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
@@ -12,7 +12,6 @@ import javax.validation.Valid;
* @author yunlongn
*/
public interface BpmModelService {
-
/**
* 获得流程模型分页
*
@@ -21,14 +20,6 @@ public interface BpmModelService {
*/
PageResult getModelPage(BpmModelPageReqVO pageVO);
- /**
- * 获得流程模块
- *
- * @param id 编号
- * @return 流程模型
- */
- BpmModelRespVO getModel(String id);
-
/**
* 创建流程模型
*
@@ -38,6 +29,14 @@ public interface BpmModelService {
*/
String createModel(@Valid BpmModelCreateReqVO modelVO, String bpmnXml);
+ /**
+ * 获得流程模块
+ *
+ * @param id 编号
+ * @return 流程模型
+ */
+ BpmModelRespVO getModel(String id);
+
/**
* 修改流程模型
*
@@ -63,7 +62,7 @@ public interface BpmModelService {
* 修改模型的状态,实际更新的部署的流程定义的状态
*
* @param id 编号
- * @param state 状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
+ * @param state 状态
*/
void updateModelState(String id, Integer state);
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
index 3626bd58c..319f732d7 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.bpm.service.definition;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
-import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
-import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
@@ -47,16 +47,15 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
@Service
@Validated
@Slf4j
-public class BpmModelServiceImpl implements BpmModelService {
+public class BpmModelServiceImpl implements BpmModelService {
@Resource
private RepositoryService repositoryService;
@Resource
- private BpmFormService bpmFormService;
- @Resource
private BpmProcessDefinitionService processDefinitionService;
@Resource
- @Lazy // 解决循环依赖
+ private BpmFormService bpmFormService;
+ @Resource
private BpmTaskAssignRuleService taskAssignRuleService;
@Override
@@ -167,9 +166,9 @@ public class BpmModelServiceImpl implements BpmModelService {
}
// TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
// 校验表单已配
- BpmFormDO form = checkFormConfig(model);
+ BpmFormDO form = checkFormConfig(model.getMetaInfo());
// 校验任务分配规则已配置
- checkTaskAssignRuleAllConfig(id);
+ taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
// 校验模型是否发生修改。如果未修改,则不允许创建
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
@@ -194,48 +193,6 @@ public class BpmModelServiceImpl implements BpmModelService {
taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
}
- /**
- * 校验流程模型的任务分配规则全部都配置了
- * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
- *
- * @param id 流程模型编号
- */
- private void checkTaskAssignRuleAllConfig(String id) {
- // 一个用户任务都没配置,所以无需配置规则
- List taskAssignRules = taskAssignRuleService.getTaskAssignRuleList(id, null);
- if (CollUtil.isEmpty(taskAssignRules)) {
- return;
- }
- // 校验未配置规则的任务
- taskAssignRules.forEach(rule -> {
- if (CollUtil.isEmpty(rule.getOptions())) {
- throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
- }
- });
- }
-
- /**
- * 校验流程表单已配置
- *
- * @param model 流程模型
- * @return 流程表单
- */
- private BpmFormDO checkFormConfig(Model model) {
- BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
- if (metaInfo == null || metaInfo.getFormType() == null) {
- throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
- }
- // 校验表单存在
- if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
- BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
- if (form == null) {
- throw exception(FORM_NOT_EXISTS);
- }
- return form;
- }
- return null;
- }
-
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteModel(String id) {
@@ -297,4 +254,26 @@ public class BpmModelServiceImpl implements BpmModelService {
}
}
+ /**
+ * 校验流程表单已配置
+ *
+ * @param metaInfoStr 流程模型 metaInfo 字段
+ * @return 流程表单
+ */
+ private BpmFormDO checkFormConfig(String metaInfoStr) {
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
+ if (metaInfo == null || metaInfo.getFormType() == null) {
+ throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
+ }
+ // 校验表单存在
+ if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
+ BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
+ if (form == null) {
+ throw exception(FORM_NOT_EXISTS);
+ }
+ return form;
+ }
+ return null;
+ }
+
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
index 7fe2a28de..46be4b64f 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
@@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
@@ -35,12 +35,20 @@ public interface BpmProcessDefinitionService {
PageResult getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
/**
- * 获得流程定义列表
+ * 创建流程定义
*
- * @param listReqVO 列表入参
- * @return 流程定义列表
+ * @param createReqDTO 创建信息
+ * @return 流程编号
*/
- List getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
+ String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+ /**
+ * 更新流程定义状态
+ *
+ * @param id 流程定义的编号
+ * @param state 状态
+ */
+ void updateProcessDefinitionState(String id, Integer state);
/**
* 获得流程定义对应的 BPMN XML
@@ -50,6 +58,30 @@ public interface BpmProcessDefinitionService {
*/
String getProcessDefinitionBpmnXML(String id);
+ /**
+ * 获得需要创建的流程定义,是否和当前激活的流程定义相等
+ *
+ * @param createReqDTO 创建信息
+ * @return 是否相等
+ */
+ boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+ /**
+ * 获得编号对应的 BpmProcessDefinitionExtDO
+ *
+ * @param id 编号
+ * @return 流程定义拓展
+ */
+ BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
+
+ /**
+ * 获得流程定义列表
+ *
+ * @param listReqVO 列表入参
+ * @return 流程定义列表
+ */
+ List getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
+
/**
* 获得 Bpmn 模型
*
@@ -84,14 +116,6 @@ public interface BpmProcessDefinitionService {
*/
ProcessDefinition getActiveProcessDefinition(String key);
- /**
- * 获得编号对应的 BpmProcessDefinitionExtDO
- *
- * @param id 编号
- * @return 流程定义拓展
- */
- BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
-
/**
* 获得 id 对应的 Deployment
*
@@ -134,28 +158,4 @@ public interface BpmProcessDefinitionService {
*/
List getProcessDefinitionListByDeploymentIds(Set deploymentIds);
- /**
- * 获得需要创建的流程定义,是否和当前激活的流程定义相等
- *
- * @param createReqDTO 创建信息
- * @return 是否相等
- */
- boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
-
- /**
- * 创建流程定义
- *
- * @param createReqDTO 创建信息
- * @return 流程编号
- */
- String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
-
- /**
- * 更新流程定义的挂起状态
- *
- * @param id 流程定义的编号
- * @param state 挂起状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
- */
- void updateProcessDefinitionState(String id, Integer state);
-
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
index 538e2a05c..5d41da654 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
-import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
@@ -15,6 +14,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
index 19e7f9684..079451597 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
@@ -76,4 +76,12 @@ public interface BpmTaskAssignRuleService {
*/
void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId);
+ /**
+ * 校验流程模型的任务分配规则全部都配置了
+ * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
+ *
+ * @param id 流程模型编号
+ */
+ void checkTaskAssignRuleAllConfig(String id);
+
}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
index 2f4eaa310..93eedb514 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -173,6 +173,21 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
taskRuleMapper.insertBatch(newRules);
}
+ @Override
+ public void checkTaskAssignRuleAllConfig(String id) {
+ // 一个用户任务都没配置,所以无需配置规则
+ List taskAssignRules = getTaskAssignRuleList(id, null);
+ if (CollUtil.isEmpty(taskAssignRules)) {
+ return;
+ }
+ // 校验未配置规则的任务
+ taskAssignRules.forEach(rule -> {
+ if (CollUtil.isEmpty(rule.getOptions())) {
+ throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
+ }
+ });
+ }
+
private void validTaskAssignRuleOptions(Integer type, Set options) {
if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
roleApi.validRoles(options);
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java
similarity index 98%
rename from yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java
rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java
index b05b712a3..dad383a59 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java
+++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java
@@ -33,10 +33,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest {
+public class BpmUserTaskActivityBehaviorTest extends BaseMockitoUnitTest {
@InjectMocks
- private BpmUserTaskActivitiBehavior behavior;
+ private BpmUserTaskActivityBehavior behavior;
@Mock
private BpmTaskAssignRuleService bpmTaskRuleService;
@Mock
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
index ec16d5275..bf4626d05 100644
--- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml
@@ -16,14 +16,23 @@
+
+ cn.iocoder.boot
+ yudao-module-bpm-base
+ ${revision}
+
+
- org.flowable
- flowable-spring-boot-starter-basic
+ cn.iocoder.boot
+ yudao-spring-boot-starter-flowable
+
+
- org.flowable
- flowable-spring-boot-starter-actuator
+ cn.iocoder.boot
+ yudao-spring-boot-starter-test
+ test
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java
new file mode 100644
index 000000000..2137e2203
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * bpm API 实现类,定义暴露给其它模块的 API
+ */
+package cn.iocoder.yudao.module.bpm.api;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
new file mode 100644
index 000000000..596c9981a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.bpm.api.task;
+
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+/**
+ * Flowable 流程实例 Api 实现类
+ *
+ * @author 芋道源码
+ * @author jason
+ */
+@Service
+@Validated
+public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
+
+ @Resource
+ private BpmProcessInstanceService processInstanceService;
+
+ @Override
+ public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) {
+ return processInstanceService.createProcessInstance(userId, reqDTO);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
new file mode 100644
index 000000000..3dd0a0a4d
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
@@ -0,0 +1,97 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.io.IoUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import java.io.IOException;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 流程模型")
+@RestController
+@RequestMapping("/bpm/model")
+@Validated
+public class BpmModelController {
+
+ @Resource
+ private BpmModelService modelService;
+
+ @GetMapping("/page")
+ @ApiOperation(value = "获得模型分页")
+ public CommonResult> getModelPage(BpmModelPageReqVO pageVO) {
+ return success(modelService.getModelPage(pageVO));
+ }
+
+ @GetMapping("/get")
+ @ApiOperation("获得模型")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:model:query')")
+ public CommonResult getModel(@RequestParam("id") String id) {
+ BpmModelRespVO model = modelService.getModel(id);
+ return success(model);
+ }
+
+ @PostMapping("/create")
+ @ApiOperation(value = "新建模型")
+ @PreAuthorize("@ss.hasPermission('bpm:model:create')")
+ public CommonResult createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) {
+ return success(modelService.createModel(createRetVO, null));
+ }
+
+ @PutMapping("/update")
+ @ApiOperation(value = "修改模型")
+ @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+ public CommonResult updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) {
+ modelService.updateModel(modelVO);
+ return success(true);
+ }
+
+ @PostMapping("/import")
+ @ApiOperation(value = "导入模型")
+ @PreAuthorize("@ss.hasPermission('bpm:model:import')")
+ public CommonResult importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException {
+ BpmModelCreateReqVO createReqVO = BpmModelConvert.INSTANCE.convert(importReqVO);
+ // 读取文件
+ String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
+ return success(modelService.createModel(createReqVO, bpmnXml));
+ }
+
+ @PostMapping("/deploy")
+ @ApiOperation(value = "部署模型")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
+ public CommonResult deployModel(@RequestParam("id") String id) {
+ modelService.deployModel(id);
+ return success(true);
+ }
+
+ @PutMapping("/update-state")
+ @ApiOperation(value = "修改模型的状态", notes = "实际更新的部署的流程定义的状态")
+ @PreAuthorize("@ss.hasPermission('bpm:model:update')")
+ public CommonResult updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
+ modelService.updateModelState(reqVO.getId(), reqVO.getState());
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @ApiOperation("删除模型")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:model:delete')")
+ public CommonResult deleteModel(@RequestParam("id") String id) {
+ modelService.deleteModel(id);
+ return success(true);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
new file mode 100644
index 000000000..ebcaad05b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 流程定义")
+@RestController
+@RequestMapping("/bpm/process-definition")
+@Validated
+public class BpmProcessDefinitionController {
+
+ @Resource
+ private BpmProcessDefinitionService bpmDefinitionService;
+
+ @GetMapping("/page")
+ @ApiOperation(value = "获得流程定义分页")
+ @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+ public CommonResult> getProcessDefinitionPage(
+ BpmProcessDefinitionPageReqVO pageReqVO) {
+ return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO));
+ }
+
+ @GetMapping ("/list")
+ @ApiOperation(value = "获得流程定义列表")
+ @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+ public CommonResult> getProcessDefinitionList(
+ BpmProcessDefinitionListReqVO listReqVO) {
+ return success(bpmDefinitionService.getProcessDefinitionList(listReqVO));
+ }
+
+ @GetMapping ("/get-bpmn-xml")
+ @ApiOperation(value = "获得流程定义的 BPMN XML")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
+ public CommonResult getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
+ String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id);
+ return success(bpmnXML);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
new file mode 100644
index 000000000..3e946707a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 任务分配规则")
+@RestController
+@RequestMapping("/bpm/task-assign-rule")
+@Validated
+public class BpmTaskAssignRuleController {
+
+ @Resource
+ private BpmTaskAssignRuleService taskAssignRuleService;
+
+ @GetMapping("/list")
+ @ApiOperation(value = "获得任务分配规则列表")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "modelId", value = "模型编号", example = "1024", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "processDefinitionId", value = "流程定义的编号", example = "2048", dataTypeClass = String.class)
+ })
+ @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:query')")
+ public CommonResult> getTaskAssignRuleList(
+ @RequestParam(value = "modelId", required = false) String modelId,
+ @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {
+ return success(taskAssignRuleService.getTaskAssignRuleList(modelId, processDefinitionId));
+ }
+
+ @PostMapping("/create")
+ @ApiOperation(value = "创建任务分配规则")
+ @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:create')")
+ public CommonResult createTaskAssignRule(@Valid @RequestBody BpmTaskAssignRuleCreateReqVO reqVO) {
+ return success(taskAssignRuleService.createTaskAssignRule(reqVO));
+ }
+
+ @PutMapping("/update")
+ @ApiOperation(value = "更新任务分配规则")
+ @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:update')")
+ public CommonResult updateTaskAssignRule(@Valid @RequestBody BpmTaskAssignRuleUpdateReqVO reqVO) {
+ taskAssignRuleService.updateTaskAssignRule(reqVO);
+ return success(true);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java
new file mode 100644
index 000000000..24d89cd36
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.task;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
+import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 流程活动实例")
+@RestController
+@RequestMapping("/bpm/activity")
+@Validated
+public class BpmActivityController {
+
+ @Resource
+ private BpmActivityService activityService;
+
+ @GetMapping("/list")
+ @ApiOperation(value = "生成指定流程实例的高亮流程图",
+ notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成")
+ @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:task:query')")
+ public CommonResult> getActivityList(
+ @RequestParam("processInstanceId") String processInstanceId) {
+ return success(activityService.getActivityListByProcessInstanceId(processInstanceId));
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
new file mode 100644
index 000000000..851a83ce5
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.task;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Api(tags = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请”
+@RestController
+@RequestMapping("/bpm/process-instance")
+@Validated
+public class BpmProcessInstanceController {
+ @Resource
+ private BpmProcessInstanceService processInstanceService;
+
+ @GetMapping("/my-page")
+ @ApiOperation(value = "获得我的实例分页列表", notes = "在【我的流程】菜单中,进行调用")
+ @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
+ public CommonResult> getMyProcessInstancePage(
+ @Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
+ return success(processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO));
+ }
+
+ @PostMapping("/create")
+ @ApiOperation("新建流程实例")
+ @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
+ public CommonResult createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) {
+ return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO));
+ }
+
+ @GetMapping("/get")
+ @ApiOperation(value = "获得指定流程实例", notes = "在【流程详细】界面中,进行调用")
+ @ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
+ public CommonResult getProcessInstance(@RequestParam("id") String id) {
+ return success(processInstanceService.getProcessInstanceVO(id));
+ }
+
+ @DeleteMapping("/cancel")
+ @ApiOperation(value = "取消流程实例", notes = "撤回发起的流程")
+ @PreAuthorize("@ss.hasPermission('bpm:process-instance:cancel')")
+ public CommonResult cancelProcessInstance(@Valid @RequestBody BpmProcessInstanceCancelReqVO cancelReqVO) {
+ processInstanceService.cancelProcessInstance(getLoginUserId(), cancelReqVO);
+ return success(true);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
new file mode 100644
index 000000000..52b16297d
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
@@ -0,0 +1,79 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.task;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
+import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.engine.TaskService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
+
+@Api(tags = "管理后台 - 流程任务实例")
+@RestController
+@RequestMapping("/bpm/task")
+@Validated
+public class BpmTaskController {
+
+ @Resource
+ private BpmTaskService taskService;
+
+ @GetMapping("todo-page")
+ @ApiOperation("获取 Todo 待办任务分页")
+ @PreAuthorize("@ss.hasPermission('bpm:task:query')")
+ public CommonResult> getTodoTaskPage(@Valid BpmTaskTodoPageReqVO pageVO) {
+ return success(taskService.getTodoTaskPage(getLoginUserId(), pageVO));
+ }
+
+ @GetMapping("done-page")
+ @ApiOperation("获取 Done 已办任务分页")
+ @PreAuthorize("@ss.hasPermission('bpm:task:query')")
+ public CommonResult> getDoneTaskPage(@Valid BpmTaskDonePageReqVO pageVO) {
+ return success(taskService.getDoneTaskPage(getLoginUserId(), pageVO));
+ }
+
+ @GetMapping("/list-by-process-instance-id")
+ @ApiOperation(value = "获得指定流程实例的任务列表", notes = "包括完成的、未完成的")
+ @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class)
+ @PreAuthorize("@ss.hasPermission('bpm:task:query')")
+ public CommonResult> getTaskListByProcessInstanceId(
+ @RequestParam("processInstanceId") String processInstanceId) {
+ return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
+ }
+
+ @PutMapping("/approve")
+ @ApiOperation("通过任务")
+ @PreAuthorize("@ss.hasPermission('bpm:task:update')")
+ public CommonResult approveTask(@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
+ taskService.approveTask(getLoginUserId(), reqVO);
+ return success(true);
+ }
+
+ @PutMapping("/reject")
+ @ApiOperation("不通过任务")
+ @PreAuthorize("@ss.hasPermission('bpm:task:update')")
+ public CommonResult rejectTask(@Valid @RequestBody BpmTaskRejectReqVO reqVO) {
+ taskService.rejectTask(getLoginUserId(), reqVO);
+ return success(true);
+ }
+
+ @PutMapping("/update-assignee")
+ @ApiOperation(value = "更新任务的负责人", notes = "用于【流程详情】的【转派】按钮")
+ @PreAuthorize("@ss.hasPermission('bpm:task:update')")
+ public CommonResult updateTaskAssignee(@Valid @RequestBody BpmTaskUpdateAssigneeReqVO reqVO) {
+ taskService.updateTaskAssignee(getLoginUserId(), reqVO);
+ return success(true);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java
new file mode 100644
index 000000000..e8d285e35
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位
+ */
+package cn.iocoder.yudao.module.bpm.controller.app;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java
new file mode 100644
index 000000000..d1930bd6a
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * 提供 RESTful API 给前端:
+ * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
+ * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
+ */
+package cn.iocoder.yudao.module.bpm.controller;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
new file mode 100644
index 000000000..4d1b2a003
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
@@ -0,0 +1,140 @@
+package cn.iocoder.yudao.module.bpm.convert.definition;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.Model;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.mapstruct.Mapper;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 流程模型 Convert
+ *
+ * @author yunlongn
+ */
+@Mapper
+public interface BpmModelConvert {
+
+ BpmModelConvert INSTANCE = Mappers.getMapper(BpmModelConvert.class);
+
+ default List convertList(List list, Map formMap,
+ Map deploymentMap,
+ Map processDefinitionMap) {
+ return CollectionUtils.convertList(list, model -> {
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+ BpmFormDO form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null;
+ Deployment deployment = model.getDeploymentId() != null ? deploymentMap.get(model.getDeploymentId()) : null;
+ ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null;
+ return convert(model, form, deployment, processDefinition);
+ });
+ }
+
+ default BpmModelPageItemRespVO convert(Model model, BpmFormDO form, Deployment deployment, ProcessDefinition processDefinition) {
+ BpmModelPageItemRespVO modelRespVO = new BpmModelPageItemRespVO();
+ modelRespVO.setId(model.getId());
+ modelRespVO.setCreateTime(model.getCreateTime());
+ // 通用 copy
+ copyTo(model, modelRespVO);
+ // Form
+ if (form != null) {
+ modelRespVO.setFormId(form.getId());
+ modelRespVO.setFormName(form.getName());
+ }
+ // ProcessDefinition
+ modelRespVO.setProcessDefinition(this.convert(processDefinition));
+ if (modelRespVO.getProcessDefinition() != null) {
+ modelRespVO.getProcessDefinition().setSuspensionState(processDefinition.isSuspended() ?
+ SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
+ modelRespVO.getProcessDefinition().setDeploymentTime(deployment.getDeploymentTime());
+ }
+ return modelRespVO;
+ }
+
+ default BpmModelRespVO convert(Model model) {
+ BpmModelRespVO modelRespVO = new BpmModelRespVO();
+ modelRespVO.setId(model.getId());
+ modelRespVO.setCreateTime(model.getCreateTime());
+ // 通用 copy
+ copyTo(model, modelRespVO);
+ return modelRespVO;
+ }
+
+ default void copyTo(Model model, BpmModelBaseVO to) {
+ to.setName(model.getName());
+ to.setKey(model.getKey());
+ to.setCategory(model.getCategory());
+ // metaInfo
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+ copyTo(metaInfo, to);
+ }
+
+ BpmModelCreateReqVO convert(BpmModeImportReqVO bean);
+
+ default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
+ BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
+ createReqDTO.setModelId(model.getId());
+ createReqDTO.setName(model.getName());
+ createReqDTO.setKey(model.getKey());
+ createReqDTO.setCategory(model.getCategory());
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+ // metaInfo
+ copyTo(metaInfo, createReqDTO);
+ // form
+ if (form != null) {
+ createReqDTO.setFormConf(form.getConf());
+ createReqDTO.setFormFields(form.getFields());
+ }
+ return createReqDTO;
+ }
+
+ void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
+
+ void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
+
+ BpmModelPageItemRespVO.ProcessDefinition convert(ProcessDefinition bean);
+
+ default void copy(Model model, BpmModelCreateReqVO bean) {
+ model.setName(bean.getName());
+ model.setKey(bean.getKey());
+ model.setMetaInfo(buildMetaInfoStr(null, bean.getDescription(), null, null,
+ null, null));
+ }
+
+ default void copy(Model model, BpmModelUpdateReqVO bean) {
+ model.setName(bean.getName());
+ model.setCategory(bean.getCategory());
+ model.setMetaInfo(buildMetaInfoStr(JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class),
+ bean.getDescription(), bean.getFormType(), bean.getFormId(),
+ bean.getFormCustomCreatePath(), bean.getFormCustomViewPath()));
+ }
+
+ default String buildMetaInfoStr(BpmModelMetaInfoRespDTO metaInfo, String description, Integer formType,
+ Long formId, String formCustomCreatePath, String formCustomViewPath) {
+ if (metaInfo == null) {
+ metaInfo = new BpmModelMetaInfoRespDTO();
+ }
+ // 只有非空,才进行设置,避免更新时的覆盖
+ if (StrUtil.isNotEmpty(description)) {
+ metaInfo.setDescription(description);
+ }
+ if (Objects.nonNull(formType)) {
+ metaInfo.setFormType(formType);
+ metaInfo.setFormId(formId);
+ metaInfo.setFormCustomCreatePath(formCustomCreatePath);
+ metaInfo.setFormCustomViewPath(formCustomViewPath);
+ }
+ return JsonUtils.toJsonString(metaInfo);
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
new file mode 100644
index 000000000..8f5bfcd26
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
@@ -0,0 +1,82 @@
+package cn.iocoder.yudao.module.bpm.convert.definition;
+
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.Named;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Bpm 流程定义的 Convert
+ *
+ * @author yunlong.li
+ */
+@Mapper
+public interface BpmProcessDefinitionConvert {
+
+ BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class);
+
+ BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
+
+ BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
+
+ default List convertList(List list, Map deploymentMap,
+ Map processDefinitionDOMap, Map formMap) {
+ return CollectionUtils.convertList(list, definition -> {
+ Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null;
+ BpmProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
+ BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null;
+ return convert(definition, deployment, definitionDO, form);
+ });
+ }
+
+ default List convertList3(List list,
+ Map processDefinitionDOMap) {
+ return CollectionUtils.convertList(list, processDefinition -> {
+ BpmProcessDefinitionRespVO respVO = convert3(processDefinition);
+ BpmProcessDefinitionExtDO processDefinitionExtDO = processDefinitionDOMap.get(processDefinition.getId());
+ // 复制通用属性
+ copyTo(processDefinitionExtDO, respVO);
+ return respVO;
+ });
+ }
+
+ @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
+ BpmProcessDefinitionRespVO convert3(ProcessDefinition bean);
+
+ @Named("convertSuspendedToSuspensionState")
+ default Integer convertSuspendedToSuspensionState(boolean suspended) {
+ return suspended ? SuspensionState.SUSPENDED.getStateCode() :
+ SuspensionState.ACTIVE.getStateCode();
+ }
+
+ default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
+ BpmProcessDefinitionExtDO processDefinitionExtDO, BpmFormDO form) {
+ BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
+ respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
+ if (deployment != null) {
+ respVO.setDeploymentTime(deployment.getDeploymentTime());
+ }
+ if (form != null) {
+ respVO.setFormName(form.getName());
+ }
+ // 复制通用属性
+ copyTo(processDefinitionExtDO, respVO);
+ return respVO;
+ }
+
+ @Mapping(source = "from.id", target = "to.id", ignore = true)
+ void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessDefinitionRespVO to);
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java
new file mode 100644
index 000000000..c616e90b0
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.bpm.convert.definition;
+
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import org.flowable.bpmn.model.UserTask;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface BpmTaskAssignRuleConvert {
+ BpmTaskAssignRuleConvert INSTANCE = Mappers.getMapper(BpmTaskAssignRuleConvert.class);
+
+ default List convertList(List tasks, List rules) {
+ Map ruleMap = CollectionUtils.convertMap(rules, BpmTaskAssignRuleDO::getTaskDefinitionKey);
+ // 以 UserTask 为主维度,原因是:流程图编辑后,一些规则实际就没用了。
+ return CollectionUtils.convertList(tasks, task -> {
+ BpmTaskAssignRuleRespVO respVO = convert(ruleMap.get(task.getId()));
+ if (respVO == null) {
+ respVO = new BpmTaskAssignRuleRespVO();
+ respVO.setTaskDefinitionKey(task.getId());
+ }
+ respVO.setTaskDefinitionName(task.getName());
+ return respVO;
+ });
+ }
+
+ BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean);
+
+ BpmTaskAssignRuleDO convert(BpmTaskAssignRuleCreateReqVO bean);
+
+ BpmTaskAssignRuleDO convert(BpmTaskAssignRuleUpdateReqVO bean);
+
+ List convertList2(List list);
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java
new file mode 100644
index 000000000..6db6ebc46
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * 提供 POJO 类的实体转换
+ *
+ * 目前使用 MapStruct 框架
+ */
+package cn.iocoder.yudao.module.bpm.convert;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java
new file mode 100644
index 000000000..509408457
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.bpm.convert.task;
+
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
+import org.flowable.engine.history.HistoricActivityInstance;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * BPM 活动 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface BpmActivityConvert {
+
+ BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
+
+ List convertList(List list);
+
+ @Mappings({
+ @Mapping(source = "activityId", target = "key"),
+ @Mapping(source = "activityType", target = "type")
+ })
+ BpmActivityRespVO convert(HistoricActivityInstance bean);
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
new file mode 100644
index 000000000..c6f6cbee5
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
@@ -0,0 +1,116 @@
+package cn.iocoder.yudao.module.bpm.convert.task;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
+import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent;
+import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
+import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.Mappings;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * 流程实例 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface BpmProcessInstanceConvert {
+
+ BpmProcessInstanceConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceConvert.class);
+
+ default PageResult convertPage(PageResult page,
+ Map> taskMap) {
+ List list = convertList(page.getList());
+ list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()))));
+ return new PageResult<>(list, page.getTotal());
+ }
+
+ List convertList(List list);
+
+ @Mapping(source = "processInstanceId", target = "id")
+ BpmProcessInstancePageItemRespVO convert(BpmProcessInstanceExtDO bean);
+
+ List convertList2(List tasks);
+
+ default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt,
+ ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt,
+ String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) {
+ BpmProcessInstanceRespVO respVO = convert2(processInstance);
+ copyTo(processInstanceExt, respVO);
+ // definition
+ respVO.setProcessDefinition(convert2(processDefinition));
+ copyTo(processDefinitionExt, respVO.getProcessDefinition());
+ respVO.getProcessDefinition().setBpmnXml(bpmnXml);
+ // user
+ if (startUser != null) {
+ respVO.setStartUser(convert2(startUser));
+ if (dept != null) {
+ respVO.getStartUser().setDeptName(dept.getName());
+ }
+ }
+ return respVO;
+ }
+
+ BpmProcessInstanceRespVO convert2(HistoricProcessInstance bean);
+
+ @Mapping(source = "from.id", target = "to.id", ignore = true)
+ void copyTo(BpmProcessInstanceExtDO from, @MappingTarget BpmProcessInstanceRespVO to);
+
+ BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean);
+
+ @Mapping(source = "from.id", target = "to.id", ignore = true)
+ void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessInstanceRespVO.ProcessDefinition to);
+
+ BpmProcessInstanceRespVO.User convert2(AdminUserRespDTO bean);
+
+ default BpmProcessInstanceResultEvent convert(Object source, HistoricProcessInstance instance, Integer result) {
+ BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
+ event.setId(instance.getId());
+ event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
+ event.setBusinessKey(instance.getBusinessKey());
+ event.setResult(result);
+ return event;
+ }
+
+ default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) {
+ BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
+ event.setId(instance.getId());
+ event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
+ event.setBusinessKey(instance.getBusinessKey());
+ event.setResult(result);
+ return event;
+ }
+
+ default BpmMessageSendWhenProcessInstanceApproveReqDTO convert2ApprovedReq(ProcessInstance instance){
+ return new BpmMessageSendWhenProcessInstanceApproveReqDTO()
+ .setStartUserId(NumberUtils.parseLong(instance.getStartUserId()))
+ .setProcessInstanceId(instance.getId())
+ .setProcessInstanceName(instance.getName());
+ }
+
+ default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String comment) {
+ return new BpmMessageSendWhenProcessInstanceRejectReqDTO()
+ .setProcessInstanceName(instance.getName())
+ .setProcessInstanceId(instance.getId())
+ .setComment(comment)
+ .setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
new file mode 100644
index 000000000..d128dba2c
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
@@ -0,0 +1,147 @@
+package cn.iocoder.yudao.module.bpm.convert.task;
+
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
+import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.flowable.task.api.history.HistoricTaskInstance;
+import org.mapstruct.*;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Bpm 任务 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface BpmTaskConvert {
+
+ BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
+
+ default List convertList1(List tasks, Map processInstanceMap,
+ Map userMap) {
+ return CollectionUtils.convertList(tasks, task -> {
+ BpmTaskTodoPageItemRespVO respVO = convert1(task);
+ ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
+ if (processInstance != null) {
+ AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
+ respVO.setProcessInstance(convert(processInstance, startUser));
+ }
+ return respVO;
+ });
+ }
+
+ @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState")
+ BpmTaskTodoPageItemRespVO convert1(Task bean);
+
+ @Named("convertSuspendedToSuspensionState")
+ default Integer convertSuspendedToSuspensionState(boolean suspended) {
+ return suspended ? SuspensionState.SUSPENDED.getStateCode() :
+ SuspensionState.ACTIVE.getStateCode();
+ }
+
+ default List convertList2(List tasks, Map bpmTaskExtDOMap,
+ Map historicProcessInstanceMap,
+ Map userMap) {
+ return CollectionUtils.convertList(tasks, task -> {
+ BpmTaskDonePageItemRespVO respVO = convert2(task);
+ BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
+ copyTo(taskExtDO, respVO);
+ HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId());
+ if (processInstance != null) {
+ AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
+ respVO.setProcessInstance(convert(processInstance, startUser));
+ }
+ return respVO;
+ });
+ }
+
+ BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean);
+
+ @Mappings({
+ @Mapping(source = "processInstance.id", target = "id"),
+ @Mapping(source = "processInstance.name", target = "name"),
+ @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+ @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+ @Mapping(source = "startUser.nickname", target = "startUserNickname")
+ })
+ BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
+
+ default List convertList3(List tasks, Map bpmTaskExtDOMap,
+ HistoricProcessInstance processInstance, Map userMap,
+ Map deptMap) {
+ return CollectionUtils.convertList(tasks, task -> {
+ BpmTaskRespVO respVO = convert3(task);
+ BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
+ copyTo(taskExtDO, respVO);
+ if (processInstance != null) {
+ AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
+ respVO.setProcessInstance(convert(processInstance, startUser));
+ }
+ AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee()));
+ if (assignUser != null) {
+ respVO.setAssigneeUser(convert3(assignUser));
+ DeptRespDTO dept = deptMap.get(assignUser.getDeptId());
+ if (dept != null) {
+ respVO.getAssigneeUser().setDeptName(dept.getName());
+ }
+ }
+ return respVO;
+ });
+ }
+
+ @Mapping(source = "taskDefinitionKey", target = "definitionKey")
+ BpmTaskRespVO convert3(HistoricTaskInstance bean);
+
+ BpmTaskRespVO.User convert3(AdminUserRespDTO bean);
+
+ @Mapping(target = "id", ignore = true)
+ void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
+
+ @Mappings({
+ @Mapping(source = "processInstance.id", target = "id"),
+ @Mapping(source = "processInstance.name", target = "name"),
+ @Mapping(source = "processInstance.startUserId", target = "startUserId"),
+ @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"),
+ @Mapping(source = "startUser.nickname", target = "startUserNickname")
+ })
+ BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, AdminUserRespDTO startUser);
+
+ default BpmTaskExtDO convert2TaskExt(Task task){
+ BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
+ .setTaskId(task.getId())
+ .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
+ .setName(task.getName())
+ .setProcessDefinitionId(task.getProcessDefinitionId())
+ .setProcessInstanceId(task.getProcessInstanceId());
+ taskExtDO.setCreateTime(task.getCreateTime());
+ return taskExtDO;
+ }
+
+ default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, Task task) {
+ BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
+ reqDTO.setProcessInstanceId(processInstance.getProcessInstanceId())
+ .setProcessInstanceName(processInstance.getName())
+ .setStartUserId(startUser.getId())
+ .setStartUserNickname(startUser.getNickname())
+ .setTaskId(task.getId())
+ .setTaskName(task.getName())
+ .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()));
+ return reqDTO;
+ }
+}
+
+
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
new file mode 100644
index 000000000..8153487b7
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
@@ -0,0 +1 @@
+
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
new file mode 100644
index 000000000..bf2feb840
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.config;
+
+import cn.hutool.core.collection.ListUtil;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
+import org.flowable.spring.SpringProcessEngineConfiguration;
+import org.flowable.spring.boot.EngineConfigurationConfigurer;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+/**
+ * BPM 模块的 Flowable 配置类
+ *
+ * @author jason
+ */
+@Configuration
+public class BpmFlowableConfiguration {
+
+ /**
+ * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类:
+ *
+ * 1. 设置各种监听器
+ * 2. 设置自定义的 ActivityBehaviorFactory 实现
+ */
+ @Bean
+ public EngineConfigurationConfigurer bpmProcessEngineConfigurationConfigurer(
+ ObjectProvider listeners,
+ BpmActivityBehaviorFactory bpmActivityBehaviorFactory) {
+ return configuration -> {
+ // 注册监听器,例如说 BpmActivitiEventListener
+ configuration.setEventListeners(ListUtil.toList(listeners.iterator()));
+ // 设置 ActivityBehaviorFactory 实现类,用于流程任务的审核人的自定义
+ configuration.setActivityBehaviorFactory(bpmActivityBehaviorFactory);
+ };
+ }
+
+ @Bean
+ public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService,
+ BpmUserGroupService userGroupService,
+ PermissionApi permissionApi,
+ DeptApi deptApi,
+ AdminUserApi adminUserApi,
+ List scripts) {
+ BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
+ bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
+ bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
+ bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
+ bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
+ bpmActivityBehaviorFactory.setDeptApi(deptApi);
+ bpmActivityBehaviorFactory.setScripts(scripts);
+ return bpmActivityBehaviorFactory;
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
new file mode 100644
index 000000000..0d8de4f62
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
+
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Setter;
+import lombok.ToString;
+import org.flowable.bpmn.model.UserTask;
+import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
+import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
+
+import java.util.List;
+
+/**
+ * 自定义的 ActivityBehaviorFactory 实现类,目的如下:
+ * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
+ *
+ * @author 芋道源码
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
+
+ @Setter
+ private BpmTaskAssignRuleService bpmTaskRuleService;
+ @Setter
+ private BpmUserGroupService userGroupService;
+
+ @Setter
+ private PermissionApi permissionApi;
+ @Setter
+ private DeptApi deptApi;
+ @Setter
+ private AdminUserApi adminUserApi;
+ @Setter
+ private List scripts;
+
+ @Override
+ public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
+ BpmUserTaskActivityBehavior userTaskActivityBehavior = new BpmUserTaskActivityBehavior(userTask);
+ userTaskActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService);
+ userTaskActivityBehavior.setPermissionApi(permissionApi);
+ userTaskActivityBehavior.setDeptApi(deptApi);
+ userTaskActivityBehavior.setUserGroupService(userGroupService);
+ userTaskActivityBehavior.setAdminUserApi(adminUserApi);
+ userTaskActivityBehavior.setScripts(scripts);
+ return userTaskActivityBehavior;
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
new file mode 100644
index 000000000..fb2551cbc
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
@@ -0,0 +1,195 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
+import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import com.google.common.annotations.VisibleForTesting;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.model.UserTask;
+import org.flowable.common.engine.api.FlowableException;
+import org.flowable.common.engine.impl.el.ExpressionManager;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
+import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
+import org.flowable.engine.impl.util.TaskHelper;
+import org.flowable.task.service.TaskService;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
+
+/**
+ * 自定义的流程任务的 assignee 负责人的分配
+ * 第一步,获得对应的分配规则;
+ * 第二步,根据分配规则,计算出分配任务的候选人。如果找不到,则直接报业务异常,不继续执行后续的流程;
+ * 第三步,随机选择一个候选人,则选择作为 assignee 负责人。
+ *
+ * @author 芋道源码
+ */
+@Slf4j
+public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
+
+ @Setter
+ private BpmTaskAssignRuleService bpmTaskRuleService;
+ @Setter
+ private BpmUserGroupService userGroupService;
+ @Setter
+ private DeptApi deptApi;
+ @Setter
+ private AdminUserApi adminUserApi;
+ @Setter
+ private PermissionApi permissionApi;
+
+ /**
+ * 任务分配脚本
+ */
+ private Map scriptMap = Collections.emptyMap();
+
+ public BpmUserTaskActivityBehavior(UserTask userTask) {
+ super(userTask);
+ }
+ public void setScripts(List scripts) {
+ this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
+ }
+
+ @Override
+ protected void handleAssignments(TaskService taskService, String assignee, String owner, List candidateUsers, List candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
+ // 第一步,获得任务的规则
+ BpmTaskAssignRuleDO rule = getTaskRule(task);
+ // 第二步,获得任务的候选用户们
+ Set candidateUserIds = calculateTaskCandidateUsers(task, rule);
+ // 第三步,设置一个作为负责人
+ Long assigneeUserId = chooseTaskAssignee(candidateUserIds);
+ TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));
+ }
+
+ private BpmTaskAssignRuleDO getTaskRule(TaskEntity task) {
+ List taskRules = bpmTaskRuleService.getTaskAssignRuleListByProcessDefinitionId(task.getProcessDefinitionId(),
+ task.getTaskDefinitionKey());
+ if (CollUtil.isEmpty(taskRules)) {
+ throw new FlowableException(StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则",
+ task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey()));
+ }
+ if (taskRules.size() > 1) {
+ throw new FlowableException(StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})",
+ task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), taskRules.size()));
+ }
+ return taskRules.get(0);
+ }
+
+ @VisibleForTesting
+ Set calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ Set assigneeUserIds = null;
+ if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
+ } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
+ assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
+ }
+
+ // 移除被禁用的用户
+ removeDisableUsers(assigneeUserIds);
+ // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人
+ if (CollUtil.isEmpty(assigneeUserIds)) {
+ log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]",
+ task.getId(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule));
+ throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER);
+ }
+ return assigneeUserIds;
+ }
+
+ private Set calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions());
+ }
+
+ private Set calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ List users = adminUserApi.getUsersByDeptIds(rule.getOptions());
+ return convertSet(users, AdminUserRespDTO::getId);
+ }
+
+ private Set calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ List depts = deptApi.getDepts(rule.getOptions());
+ return convertSet(depts, DeptRespDTO::getLeaderUserId);
+ }
+
+ private Set calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ List users = adminUserApi.getUsersByPostIds(rule.getOptions());
+ return convertSet(users, AdminUserRespDTO::getId);
+ }
+
+ private Set calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ return rule.getOptions();
+ }
+
+ private Set calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ List userGroups = userGroupService.getUserGroupList(rule.getOptions());
+ Set userIds = new HashSet<>();
+ userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds()));
+ return userIds;
+ }
+
+ private Set calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
+ // 获得对应的脚本
+ List scripts = new ArrayList<>(rule.getOptions().size());
+ rule.getOptions().forEach(id -> {
+ BpmTaskAssignScript script = scriptMap.get(id);
+ if (script == null) {
+ throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
+ }
+ scripts.add(script);
+ });
+ // 逐个计算任务
+ Set userIds = new HashSet<>();
+ scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
+ return userIds;
+ }
+
+ private Long chooseTaskAssignee(Set candidateUserIds) {
+ // TODO 芋艿:未来可以优化下,改成轮询的策略
+ int index = RandomUtil.randomInt(candidateUserIds.size());
+ return CollUtil.get(candidateUserIds, index);
+ }
+
+ @VisibleForTesting
+ void removeDisableUsers(Set assigneeUserIds) {
+ if (CollUtil.isEmpty(assigneeUserIds)) {
+ return;
+ }
+ //TODO 芋艿 这里有数据权限的问题。默认会加上数据权限 dept_id IN (deptId). 导致查询不到数据
+ Map userMap = adminUserApi.getUserMap(assigneeUserIds);
+ assigneeUserIds.removeIf(id -> {
+ AdminUserRespDTO user = userMap.get(id);
+ return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus());
+ });
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
new file mode 100644
index 000000000..10392c714
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
+
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+
+import java.util.Set;
+
+/**
+ * Bpm 任务分配的自定义 Script 脚本
+ * 使用场景:
+ * 1. 设置审批人为发起人
+ * 2. 设置审批人为发起人的 Leader
+ * 3. 甚至审批人为发起人的 Leader 的 Leader
+ *
+ * @author 芋道源码
+ */
+public interface BpmTaskAssignScript {
+
+ /**
+ * 基于流程任务,获得任务的候选用户们
+ *
+ * @param task 任务
+ * @return 候选人用户的编号数组
+ */
+ Set calculateTaskCandidateUsers(TaskEntity task);
+
+ /**
+ * 获得枚举值
+ *
+ * @return 枚举值
+ */
+ BpmTaskRuleScriptEnum getEnum();
+}
+
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
new file mode 100644
index 000000000..06b8c52f0
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.util.Assert;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
+import static java.util.Collections.emptySet;
+
+/**
+ * 分配给发起人的 Leader 审批的 Script 实现类
+ * 目前 Leader 的定义是,
+ *
+ * @author 芋道源码
+ */
+public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
+
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmProcessInstanceService bpmProcessInstanceService;
+
+ protected Set calculateTaskCandidateUsers(TaskEntity task, int level) {
+ Assert.isTrue(level > 0, "level 必须大于 0");
+ // 获得发起人
+ ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
+ Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
+ // 获得对应 leve 的部门
+ DeptRespDTO dept = null;
+ for (int i = 0; i < level; i++) {
+ // 获得 level 对应的部门
+ if (dept == null) {
+ dept = getStartUserDept(startUserId);
+ if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
+ return emptySet();
+ }
+ } else {
+ DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
+ if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
+ break;
+ }
+ dept = parentDept;
+ }
+ }
+ return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
+ }
+
+ private DeptRespDTO getStartUserDept(Long startUserId) {
+ AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
+ if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则
+ return null;
+ }
+ return deptApi.getDept(startUser.getDeptId());
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
new file mode 100644
index 000000000..adcece67b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 分配给发起人的一级 Leader 审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
+
+ @Override
+ @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
+ public Set calculateTaskCandidateUsers(TaskEntity task) {
+ return calculateTaskCandidateUsers(task, 1);
+ }
+
+ @Override
+ public BpmTaskRuleScriptEnum getEnum() {
+ return BpmTaskRuleScriptEnum.LEADER_X1;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
new file mode 100644
index 000000000..59c0732dc
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+/**
+ * 分配给发起人的二级 Leader 审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
+
+
+ @Override
+ @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
+ public Set calculateTaskCandidateUsers(TaskEntity task) {
+ return calculateTaskCandidateUsers(task, 2);
+ }
+
+ @Override
+ public BpmTaskRuleScriptEnum getEnum() {
+ return BpmTaskRuleScriptEnum.LEADER_X2;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
new file mode 100644
index 000000000..653918b0b
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
+
+import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
+
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.service.impl.persistence.entity.TaskEntity;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+/**
+ * 分配给发起人审批的 Script 实现类
+ *
+ * @author 芋道源码
+ */
+@Component
+public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
+
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmProcessInstanceService bpmProcessInstanceService;
+
+ @Override
+ public Set calculateTaskCandidateUsers(TaskEntity task) {
+ ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
+ Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
+ return SetUtils.asSet(startUserId);
+ }
+
+ @Override
+ public BpmTaskRuleScriptEnum getEnum() {
+ return BpmTaskRuleScriptEnum.START_USER;
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
new file mode 100644
index 000000000..82d5e9be6
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
+
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import com.google.common.collect.ImmutableSet;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
+import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
+import org.flowable.engine.delegate.event.FlowableCancelledEvent;
+import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Set;
+/**
+ * 监听 {@link ProcessInstance} 的开始与完成,创建与更新对应的 {@link BpmProcessInstanceExtDO} 记录
+ *
+ * @author jason
+ */
+@Component
+public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
+
+ @Resource
+ @Lazy
+ private BpmProcessInstanceService processInstanceService;
+
+ public static final Set PROCESS_INSTANCE_EVENTS = ImmutableSet.builder()
+ .add(FlowableEngineEventType.PROCESS_CREATED)
+ .add(FlowableEngineEventType.PROCESS_CANCELLED)
+ .add(FlowableEngineEventType.PROCESS_COMPLETED)
+ .build();
+
+ public BpmProcessInstanceEventListener(){
+ super(PROCESS_INSTANCE_EVENTS);
+ }
+
+ @Override
+ protected void processCreated(FlowableEngineEntityEvent event) {
+ processInstanceService.createProcessInstanceExt((ProcessInstance)event.getEntity());
+ }
+
+ @Override
+ protected void processCancelled(FlowableCancelledEvent event) {
+ processInstanceService.updateProcessInstanceExtCancel(event);
+ }
+
+ @Override
+ protected void processCompleted(FlowableEngineEntityEvent event) {
+ processInstanceService.updateProcessInstanceExtComplete((ProcessInstance)event.getEntity());
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
new file mode 100644
index 000000000..f9c9cb769
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
+
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
+import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
+import com.google.common.collect.ImmutableSet;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
+import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
+import org.flowable.task.api.Task;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Set;
+
+/**
+ * 监听 {@link org.flowable.task.api.Task} 的开始与完成,创建与更新对应的 {@link BpmTaskExtDO} 记录
+ *
+ * @author jason
+ */
+@Component
+public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
+
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmTaskService taskService;
+
+ public static final Set TASK_EVENTS = ImmutableSet.builder()
+ .add(FlowableEngineEventType.TASK_CREATED)
+ .add(FlowableEngineEventType.TASK_ASSIGNED)
+ .add(FlowableEngineEventType.TASK_COMPLETED)
+ .build();
+
+ public BpmTaskEventListener(){
+ super(TASK_EVENTS);
+ }
+
+ @Override
+ protected void taskCreated(FlowableEngineEntityEvent event) {
+ taskService.createTaskExt((Task) event.getEntity());
+ }
+
+ @Override
+ protected void taskCompleted(FlowableEngineEntityEvent event) {
+ taskService.updateTaskExtComplete((Task)event.getEntity());
+ }
+
+ @Override
+ protected void taskAssigned(FlowableEngineEntityEvent event) {
+ taskService.updateTaskExtAssign((Task)event.getEntity());
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java
new file mode 100644
index 000000000..52fdb7f93
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * 属于 bpm 模块的 framework 封装
+ *
+ * @author 芋道源码
+ */
+package cn.iocoder.yudao.module.bpm.framework;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java
new file mode 100644
index 000000000..5713e495c
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java
@@ -0,0 +1,12 @@
+/**
+ * bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 activiti 7 版本实现。
+ * 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等
+ *
+ * bpm 解释:https://baike.baidu.com/item/BPM/1933
+ *
+ * 1. Controller URL:以 /bpm/ 开头,避免和其它 Module 冲突
+ * 2. DataObject 表名:以 bpm_ 开头,方便在数据库中区分
+ *
+ * 注意,由于 Bpm 模块下,容易和其它模块重名,所以类名都加载 Pay 的前缀~
+ */
+package cn.iocoder.yudao.module.bpm;
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
new file mode 100644
index 000000000..a4e4f83d1
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
+import org.flowable.bpmn.model.BpmnModel;
+
+import javax.validation.Valid;
+
+/**
+ * Flowable流程模型接口
+ *
+ * @author yunlongn
+ */
+public interface BpmModelService {
+ /**
+ * 获得流程模型分页
+ *
+ * @param pageVO 分页查询
+ * @return 流程模型分页
+ */
+ PageResult getModelPage(BpmModelPageReqVO pageVO);
+
+ /**
+ * 创建流程模型
+ *
+ * @param modelVO 创建信息
+ * @param bpmnXml BPMN XML
+ * @return 创建的流程模型的编号
+ */
+ String createModel(@Valid BpmModelCreateReqVO modelVO, String bpmnXml);
+
+ /**
+ * 获得流程模块
+ *
+ * @param id 编号
+ * @return 流程模型
+ */
+ BpmModelRespVO getModel(String id);
+
+ /**
+ * 修改流程模型
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateModel(@Valid BpmModelUpdateReqVO updateReqVO);
+
+ /**
+ * 将流程模型,部署成一个流程定义
+ *
+ * @param id 编号
+ */
+ void deployModel(String id);
+
+ /**
+ * 删除模型
+ *
+ * @param id 编号
+ */
+ void deleteModel(String id);
+
+ /**
+ * 修改模型的状态,实际更新的部署的流程定义的状态
+ *
+ * @param id 编号
+ * @param state 状态
+ */
+ void updateModelState(String id, Integer state);
+
+ /**
+ * 获得流程模型编号对应的 BPMN Model
+ *
+ * @param id 流程模型编号
+ * @return BPMN Model
+ */
+ BpmnModel getBpmnModel(String id);
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
new file mode 100644
index 000000000..dcb0b9e47
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -0,0 +1,286 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.common.engine.impl.util.io.BytesStreamSource;
+import org.flowable.engine.RepositoryService;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.Model;
+import org.flowable.engine.repository.ModelQuery;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+
+/**
+ * Flowable流程模型实现
+ * 主要进行 Flowable {@link Model} 的维护
+ *
+ * @author yunlongn
+ * @author 芋道源码
+ * @author jason
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmModelServiceImpl implements BpmModelService {
+
+ @Resource
+ private RepositoryService repositoryService;
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+ @Resource
+ private BpmFormService bpmFormService;
+ @Resource
+ private BpmTaskAssignRuleService taskAssignRuleService;
+
+ @Override
+ public PageResult getModelPage(BpmModelPageReqVO pageVO) {
+ ModelQuery modelQuery = repositoryService.createModelQuery();
+ if (StrUtil.isNotBlank(pageVO.getKey())) {
+ modelQuery.modelKey(pageVO.getKey());
+ }
+ if (StrUtil.isNotBlank(pageVO.getName())) {
+ modelQuery.modelNameLike("%" + pageVO.getName() + "%"); // 模糊匹配
+ }
+ if (StrUtil.isNotBlank(pageVO.getCategory())) {
+ modelQuery.modelCategory(pageVO.getCategory());
+ }
+ // 执行查询
+ List models = modelQuery.orderByCreateTime().desc()
+ .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
+
+ // 获得 Form Map
+ Set formIds = CollectionUtils.convertSet(models, model -> {
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
+ return metaInfo != null ? metaInfo.getFormId() : null;
+ });
+ Map formMap = bpmFormService.getFormMap(formIds);
+
+ // 获得 Deployment Map
+ Set deploymentIds = new HashSet<>();
+ models.forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId()));
+ Map deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds);
+ // 获得 ProcessDefinition Map
+ List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds);
+ Map processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId);
+
+ // 拼接结果
+ long modelCount = modelQuery.count();
+ return new PageResult<>(BpmModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public String createModel(@Valid BpmModelCreateReqVO createReqVO, String bpmnXml) {
+ checkKeyNCName(createReqVO.getKey());
+ // 校验流程标识已经存在
+ Model keyModel = this.getModelByKey(createReqVO.getKey());
+ if (keyModel != null) {
+ throw exception(MODEL_KEY_EXISTS, createReqVO.getKey());
+ }
+
+ // 创建流程定义
+ Model model = repositoryService.newModel();
+ BpmModelConvert.INSTANCE.copy(model, createReqVO);
+ // 保存流程定义
+ repositoryService.saveModel(model);
+ // 保存 BPMN XML
+ saveModelBpmnXml(model, bpmnXml);
+ return model.getId();
+ }
+
+ private Model getModelByKey(String key) {
+ return repositoryService.createModelQuery().modelKey(key).singleResult();
+ }
+
+ @Override
+ public BpmModelRespVO getModel(String id) {
+ Model model = repositoryService.getModel(id);
+ if (model == null) {
+ return null;
+ }
+ BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model);
+ // 拼接 bpmn XML
+ byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
+ modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes));
+ return modelRespVO;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
+ public void updateModel(@Valid BpmModelUpdateReqVO updateReqVO) {
+ // 校验流程模型存在
+ Model model = repositoryService.getModel(updateReqVO.getId());
+ if (model == null) {
+ throw exception(MODEL_NOT_EXISTS);
+ }
+
+ // 修改流程定义
+ BpmModelConvert.INSTANCE.copy(model, updateReqVO);
+ // 更新模型
+ repositoryService.saveModel(model);
+ // 更新 BPMN XML
+ saveModelBpmnXml(model, updateReqVO.getBpmnXml());
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务
+ public void deployModel(String id) {
+ // 校验流程模型存在
+ Model model = repositoryService.getModel(id);
+ if (ObjectUtils.isEmpty(model)) {
+ throw exception(MODEL_NOT_EXISTS);
+ }
+ // 校验流程图
+ byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId());
+ if (bpmnBytes == null) {
+ throw exception(MODEL_NOT_EXISTS);
+ }
+ // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
+ // 校验表单已配
+ BpmFormDO form = checkFormConfig(model.getMetaInfo());
+ //校验任务分配规则已配置
+ taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
+
+ BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
+ //校验模型是否发生修改。如果未修改,则不允许创建
+ if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
+ ProcessDefinition oldProcessInstance = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
+ if (oldProcessInstance != null && taskAssignRuleService.isTaskAssignRulesEquals(model.getId(), oldProcessInstance.getId())) {
+ throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
+ }
+ }
+ // 创建流程定义
+ String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
+
+ // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
+ updateProcessDefinitionSuspended(model.getDeploymentId());
+
+ // 更新 model 的 deploymentId,进行关联
+ ProcessDefinition definition = processDefinitionService.getProcessDefinition(definitionId);
+ model.setDeploymentId(definition.getDeploymentId());
+ repositoryService.saveModel(model);
+
+ //复制任务分配规则
+ taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
+ }
+
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteModel(String id) {
+ // 校验流程模型存在
+ Model model = repositoryService.getModel(id);
+ if (model == null) {
+ throw exception(MODEL_NOT_EXISTS);
+ }
+ // 执行删除
+ repositoryService.deleteModel(id);
+ // 禁用流程实例
+ updateProcessDefinitionSuspended(model.getDeploymentId());
+ }
+
+ @Override
+ public void updateModelState(String id, Integer state) {
+ // 校验流程模型存在
+ Model model = repositoryService.getModel(id);
+ if (model == null) {
+ throw exception(MODEL_NOT_EXISTS);
+ }
+ // 校验流程定义存在
+ ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
+ if (definition == null) {
+ throw exception(PROCESS_DEFINITION_NOT_EXISTS);
+ }
+
+ // 更新状态
+ processDefinitionService.updateProcessDefinitionState(definition.getId(), state);
+ }
+
+ @Override
+ public BpmnModel getBpmnModel(String id) {
+ byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
+ if (ArrayUtil.isEmpty(bpmnBytes)) {
+ return null;
+ }
+ BpmnXMLConverter converter = new BpmnXMLConverter();
+ return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
+ }
+
+ private void checkKeyNCName(String key) {
+ if (!ValidationUtils.isXmlNCName(key)) {
+ throw exception(MODEL_KEY_VALID);
+ }
+ }
+
+ /**
+ * 校验流程表单已配置
+ *
+ * @param metaInfoStr 流程模型 metaInfo 字段
+ * @return 流程表单
+ */
+ private BpmFormDO checkFormConfig(String metaInfoStr) {
+ BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
+ if (metaInfo == null || metaInfo.getFormType() == null) {
+ throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
+ }
+ // 校验表单存在
+ if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
+ BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
+ if (form == null) {
+ throw exception(FORM_NOT_EXISTS);
+ }
+ return form;
+ }
+ return null;
+ }
+
+ private void saveModelBpmnXml(Model model, String bpmnXml) {
+ if (StrUtil.isEmpty(bpmnXml)) {
+ return;
+ }
+ repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
+ }
+
+ /**
+ * 挂起 deploymentId 对应的流程定义。 这里一个deploymentId 只关联一个流程定义
+ * @param deploymentId 流程发布Id.
+ */
+ private void updateProcessDefinitionSuspended(String deploymentId) {
+ if (StrUtil.isEmpty(deploymentId)) {
+ return;
+ }
+ ProcessDefinition oldDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(deploymentId);
+ if (oldDefinition == null) {
+ return;
+ }
+ processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
+ }
+
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
new file mode 100644
index 000000000..7c26b644e
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
@@ -0,0 +1,159 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+/**
+ * Flowable流程定义接口
+ *
+ * @author yunlong.li
+ * @author ZJQ
+ * @author 芋道源码
+ */
+public interface BpmProcessDefinitionService {
+
+ /**
+ * 获得流程定义分页
+ *
+ * @param pageReqVO 分页入参
+ * @return 流程定义 Page
+ */
+ PageResult getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
+
+ /**
+ * 获得流程定义列表
+ *
+ * @param listReqVO 列表入参
+ * @return 流程定义列表
+ */
+ List getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
+
+ /**
+ * 创建流程定义
+ *
+ * @param createReqDTO 创建信息
+ * @return 流程编号
+ */
+ String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+ /**
+ * 更新流程定义状态
+ *
+ * @param id 流程定义的编号
+ * @param state 状态
+ */
+ void updateProcessDefinitionState(String id, Integer state);
+
+ /**
+ * 获得流程定义对应的 BPMN XML
+ *
+ * @param id 流程定义编号
+ * @return BPMN XML
+ */
+ String getProcessDefinitionBpmnXML(String id);
+
+ /**
+ * 获得需要创建的流程定义,是否和当前激活的流程定义相等
+ *
+ * @param createReqDTO 创建信息
+ * @return 是否相等
+ */
+ boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
+
+ /**
+ * 获得编号对应的 BpmProcessDefinitionExtDO
+ *
+ * @param id 编号
+ * @return 流程定义拓展
+ */
+ BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
+
+ /**
+ * 获得编号对应的 ProcessDefinition
+ *
+ * @param id 编号
+ * @return 流程定义
+ */
+ ProcessDefinition getProcessDefinition(String id);
+
+ /**
+ * 获得编号对应的 ProcessDefinition
+ *
+ * 相比 {@link #getProcessDefinition(String)} 方法,category 的取值是正确
+ *
+ * @param id 编号
+ * @return 流程定义
+ */
+ ProcessDefinition getProcessDefinition2(String id);
+
+ /**
+ * 获得 deploymentId 对应的 ProcessDefinition
+ *
+ * @param deploymentId 部署编号
+ * @return 流程定义
+ */
+ ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
+
+ /**
+ * 获得 deploymentIds 对应的 ProcessDefinition 数组
+ *
+ * @param deploymentIds 部署编号的数组
+ * @return 流程定义的数组
+ */
+ List getProcessDefinitionListByDeploymentIds(Set deploymentIds);
+
+ /**
+ * 获得流程定义标识对应的激活的流程定义
+ *
+ * @param key 流程定义的标识
+ * @return 流程定义
+ */
+ ProcessDefinition getActiveProcessDefinition(String key);
+
+ /**
+ * 获得 ids 对应的 Deployment Map
+ *
+ * @param ids 部署编号的数组
+ * @return 流程部署 Map
+ */
+ default Map getDeploymentMap(Set ids) {
+ return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId);
+ }
+
+ /**
+ * 获得 ids 对应的 Deployment 数组
+ *
+ * @param ids 部署编号的数组
+ * @return 流程部署的数组
+ */
+ List getDeployments(Set ids);
+
+ /**
+ * 获得 id 对应的 Deployment
+ *
+ * @param id 部署编号
+ * @return 流程部署
+ */
+ Deployment getDeployment(String id);
+
+ /**
+ * 获得 Bpmn 模型
+ *
+ * @param processDefinitionId 流程定义的编号
+ * @return Bpmn 模型
+ */
+ BpmnModel getBpmnModel(String processDefinitionId);
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
new file mode 100644
index 000000000..a6591bd93
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -0,0 +1,284 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
+import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.converter.BpmnXMLConverter;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.common.engine.impl.db.SuspensionState;
+import org.flowable.common.engine.impl.util.io.BytesStreamSource;
+import org.flowable.engine.RepositoryService;
+import org.flowable.engine.repository.Deployment;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.flowable.engine.repository.ProcessDefinitionQuery;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
+import static java.util.Collections.emptyList;
+
+/**
+ * 流程定义实现
+ * 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
+ *
+ * @author yunlongn
+ * @author ZJQ
+ * @author 芋道源码
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService {
+
+ private static final String BPMN_FILE_SUFFIX = ".bpmn";
+
+ @Resource
+ private RepositoryService repositoryService;
+
+ @Resource
+ private BpmProcessDefinitionExtMapper processDefinitionMapper;
+
+ @Resource
+ private BpmFormService formService;
+
+ @Override
+ public ProcessDefinition getProcessDefinition(String id) {
+ return repositoryService.getProcessDefinition(id);
+ }
+
+ @Override
+ public ProcessDefinition getProcessDefinition2(String id) {
+ return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
+ }
+
+ @Override
+ public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
+ if (StrUtil.isEmpty(deploymentId)) {
+ return null;
+ }
+ return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
+ }
+
+ @Override
+ public List getProcessDefinitionListByDeploymentIds(Set deploymentIds) {
+ if (CollUtil.isEmpty(deploymentIds)) {
+ return emptyList();
+ }
+ return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
+ }
+
+ @Override
+ public ProcessDefinition getActiveProcessDefinition(String key) {
+ return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active().singleResult();
+ }
+
+ @Override
+ public List getDeployments(Set ids) {
+ if (CollUtil.isEmpty(ids)) {
+ return emptyList();
+ }
+ List list = new ArrayList<>(ids.size());
+ for (String id : ids) {
+ addIfNotNull(list, getDeployment(id));
+ }
+ return list;
+ }
+
+ @Override
+ public Deployment getDeployment(String id) {
+ if (StrUtil.isEmpty(id)) {
+ return null;
+ }
+ return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
+ }
+
+ @Override
+ public BpmnModel getBpmnModel(String processDefinitionId) {
+ return repositoryService.getBpmnModel(processDefinitionId);
+ }
+
+ @Override
+ public String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
+ // 创建 Deployment 部署
+ Deployment deploy = repositoryService.createDeployment()
+ .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
+ .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
+ .deploy();
+
+ // 设置 ProcessDefinition 的 category 分类
+ ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
+ repositoryService.setProcessDefinitionCategory(definition.getId(), createReqDTO.getCategory());
+ // 注意 1,ProcessDefinition 的 key 和 name 是通过 BPMN 中的 的 id 和 name 决定
+ // 注意 2,目前该项目的设计上,需要保证 Model、Deployment、ProcessDefinition 使用相同的 key,保证关联性。
+ // 否则,会导致 ProcessDefinition 的分页无法查询到。
+ if (!Objects.equals(definition.getKey(), createReqDTO.getKey())) {
+ throw exception(PROCESS_DEFINITION_KEY_NOT_MATCH, createReqDTO.getKey(), definition.getKey());
+ }
+ if (!Objects.equals(definition.getName(), createReqDTO.getName())) {
+ throw exception(PROCESS_DEFINITION_NAME_NOT_MATCH, createReqDTO.getName(), definition.getName());
+ }
+
+ // 插入拓展表
+ BpmProcessDefinitionExtDO definitionDO = BpmProcessDefinitionConvert.INSTANCE.convert2(createReqDTO)
+ .setProcessDefinitionId(definition.getId());
+ processDefinitionMapper.insert(definitionDO);
+ return definition.getId();
+ }
+
+ @Override
+ public void updateProcessDefinitionState(String id, Integer state) {
+ // 激活
+ if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
+ repositoryService.activateProcessDefinitionById(id, false, null);
+ return;
+ }
+ // 挂起
+ if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
+ // suspendProcessInstances = false,进行中的任务,不进行挂起。
+ // 原因:只要新的流程不允许发起即可,老流程继续可以执行。
+ repositoryService.suspendProcessDefinitionById(id, false, null);
+ return;
+ }
+ log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
+ }
+
+ @Override
+ public String getProcessDefinitionBpmnXML(String id) {
+ BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
+ if (bpmnModel == null) {
+ return null;
+ }
+ BpmnXMLConverter converter = new BpmnXMLConverter();
+ return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
+ }
+
+ @Override
+ public boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
+ // 校验 name、description 是否更新
+ ProcessDefinition oldProcessDefinition = getActiveProcessDefinition(createReqDTO.getKey());
+ if (oldProcessDefinition == null) {
+ return false;
+ }
+ BpmProcessDefinitionExtDO oldProcessDefinitionExt = getProcessDefinitionExt(oldProcessDefinition.getId());
+ if (!StrUtil.equals(createReqDTO.getName(), oldProcessDefinition.getName())
+ || !StrUtil.equals(createReqDTO.getDescription(), oldProcessDefinitionExt.getDescription())
+ || !StrUtil.equals(createReqDTO.getCategory(), oldProcessDefinition.getCategory())) {
+ return false;
+ }
+ // 校验 form 信息是否更新
+ if (!ObjectUtil.equal(createReqDTO.getFormType(), oldProcessDefinitionExt.getFormType())
+ || !ObjectUtil.equal(createReqDTO.getFormId(), oldProcessDefinitionExt.getFormId())
+ || !ObjectUtil.equal(createReqDTO.getFormConf(), oldProcessDefinitionExt.getFormConf())
+ || !ObjectUtil.equal(createReqDTO.getFormFields(), oldProcessDefinitionExt.getFormFields())
+ || !ObjectUtil.equal(createReqDTO.getFormCustomCreatePath(), oldProcessDefinitionExt.getFormCustomCreatePath())
+ || !ObjectUtil.equal(createReqDTO.getFormCustomViewPath(), oldProcessDefinitionExt.getFormCustomViewPath())) {
+ return false;
+ }
+ // 校验 BPMN XML 信息
+ BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
+ BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
+ //TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
+ if (FlowableUtils.equals(oldModel, newModel)) {
+ return false;
+ }
+ // 最终发现都一致,则返回 true
+ return true;
+ }
+
+ /**
+ * 构建对应的 BPMN Model
+ *
+ * @param bpmnBytes 原始的 BPMN XML 字节数组
+ * @return BPMN Model
+ */
+ private BpmnModel buildBpmnModel(byte[] bpmnBytes) {
+ // 转换成 BpmnModel 对象
+ BpmnXMLConverter converter = new BpmnXMLConverter();
+ return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
+ }
+
+
+
+ @Override
+ public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
+ return processDefinitionMapper.selectByProcessDefinitionId(id);
+ }
+
+ @Override
+ public List getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO) {
+ // 拼接查询条件
+ ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
+ if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), listReqVO.getSuspensionState())) {
+ definitionQuery.suspended();
+ } else if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), listReqVO.getSuspensionState())) {
+ definitionQuery.active();
+ }
+ // 执行查询
+ List processDefinitions = definitionQuery.list();
+
+ // 获得 BpmProcessDefinitionDO Map
+ List processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
+ convertList(processDefinitions, ProcessDefinition::getId));
+ Map processDefinitionDOMap = convertMap(processDefinitionDOs,
+ BpmProcessDefinitionExtDO::getProcessDefinitionId);
+ // 执行查询,并返回
+ return BpmProcessDefinitionConvert.INSTANCE.convertList3(processDefinitions, processDefinitionDOMap);
+ }
+
+ @Override
+ public PageResult getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) {
+ ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
+ if (StrUtil.isNotBlank(pageVO.getKey())) {
+ definitionQuery.processDefinitionKey(pageVO.getKey());
+ }
+
+ // 执行查询
+ List processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
+ .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
+
+ if (CollUtil.isEmpty(processDefinitions)) {
+ return new PageResult<>(emptyList(), definitionQuery.count());
+ }
+ // 获得 Deployment Map
+ Set deploymentIds = new HashSet<>();
+ processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId()));
+ Map deploymentMap = getDeploymentMap(deploymentIds);
+
+ // 获得 BpmProcessDefinitionDO Map
+ List processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
+ convertList(processDefinitions, ProcessDefinition::getId));
+ Map processDefinitionDOMap = convertMap(processDefinitionDOs,
+ BpmProcessDefinitionExtDO::getProcessDefinitionId);
+
+ // 获得 Form Map
+ Set formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
+ Map formMap = formService.getFormMap(formIds);
+
+ // 拼接结果
+ long definitionCount = definitionQuery.count();
+ return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap,
+ processDefinitionDOMap, formMap), definitionCount);
+ }
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
new file mode 100644
index 000000000..079451597
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
@@ -0,0 +1,87 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import org.springframework.lang.Nullable;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * BPM 任务分配规则 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface BpmTaskAssignRuleService {
+
+ /**
+ * 获得流程定义的任务分配规则数组
+ *
+ * @param processDefinitionId 流程定义的编号
+ * @param taskDefinitionKey 流程任务定义的 Key。允许空
+ * @return 任务规则数组
+ */
+ List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
+ @Nullable String taskDefinitionKey);
+
+ /**
+ * 获得流程模型的任务规则数组
+ *
+ * @param modelId 流程模型的编号
+ * @return 任务规则数组
+ */
+ List getTaskAssignRuleListByModelId(String modelId);
+
+ /**
+ * 获得流程定义的任务分配规则数组
+ *
+ * @param modelId 流程模型的编号
+ * @param processDefinitionId 流程定义的编号
+ * @return 任务规则数组
+ */
+ List getTaskAssignRuleList(String modelId, String processDefinitionId);
+
+ /**
+ * 创建任务分配规则
+ *
+ * @param reqVO 创建信息
+ * @return 规则编号
+ */
+ Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO);
+
+ /**
+ * 更新任务分配规则
+ *
+ * @param reqVO 创建信息
+ */
+ void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO);
+
+ /**
+ * 判断指定流程模型和流程定义的分配规则是否相等
+ *
+ * @param modelId 流程模型编号
+ * @param processDefinitionId 流程定义编号
+ * @return 是否相等
+ */
+ boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId);
+
+ /**
+ * 将流程流程模型的任务分配规则,复制一份给流程定义
+ * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义
+ *
+ * @param fromModelId 流程模型编号
+ * @param toProcessDefinitionId 流程定义编号
+ */
+ void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId);
+
+ /**
+ * 校验流程模型的任务分配规则全部都配置了
+ * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
+ *
+ * @param id 流程模型编号
+ */
+ void checkTaskAssignRuleAllConfig(String id);
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
new file mode 100644
index 000000000..6d6430da8
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
@@ -0,0 +1,208 @@
+package cn.iocoder.yudao.module.bpm.service.definition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
+import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
+import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.PostApi;
+import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
+import cn.iocoder.yudao.module.system.api.permission.RoleApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.UserTask;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+
+/**
+ * BPM 任务分配规则 Service 实现类
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
+
+ @Resource
+ private BpmTaskAssignRuleMapper taskRuleMapper;
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmModelService modelService;
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmProcessDefinitionService processDefinitionService;
+ @Resource
+ private BpmUserGroupService userGroupService;
+ @Resource
+ private RoleApi roleApi;
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ private PostApi postApi;
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DictDataApi dictDataApi;
+
+ @Override
+ public List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) {
+ return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
+ }
+
+ @Override
+ public List getTaskAssignRuleListByModelId(String modelId) {
+ return taskRuleMapper.selectListByModelId(modelId);
+ }
+
+ @Override
+ public List getTaskAssignRuleList(String modelId, String processDefinitionId) {
+ // 获得规则
+ List rules = Collections.emptyList();
+ BpmnModel model = null;
+ if (StrUtil.isNotEmpty(modelId)) {
+ rules = getTaskAssignRuleListByModelId(modelId);
+ model = modelService.getBpmnModel(modelId);
+ } else if (StrUtil.isNotEmpty(processDefinitionId)) {
+ rules = getTaskAssignRuleListByProcessDefinitionId(processDefinitionId, null);
+ model = processDefinitionService.getBpmnModel(processDefinitionId);
+ }
+ if (model == null) {
+ return Collections.emptyList();
+ }
+ // 获得用户任务,只有用户任务才可以设置分配规则
+ List userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
+ if (CollUtil.isEmpty(userTasks)) {
+ return Collections.emptyList();
+ }
+ // 转换数据
+ return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
+ }
+
+ @Override
+ public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
+ // 校验参数
+ validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
+ // 校验是否已经配置
+ BpmTaskAssignRuleDO existRule = taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(
+ reqVO.getModelId(), reqVO.getTaskDefinitionKey());
+ if (existRule != null) {
+ throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
+ }
+
+ // 存储
+ BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
+ .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
+ taskRuleMapper.insert(rule);
+ return rule.getId();
+ }
+
+ @Override
+ public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) {
+ // 校验参数
+ validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
+ // 校验是否存在
+ BpmTaskAssignRuleDO existRule = taskRuleMapper.selectById(reqVO.getId());
+ if (existRule == null) {
+ throw exception(TASK_ASSIGN_RULE_NOT_EXISTS);
+ }
+ // 只允许修改流程模型的规则
+ if (!Objects.equals(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL, existRule.getProcessDefinitionId())) {
+ throw exception(TASK_UPDATE_FAIL_NOT_MODEL);
+ }
+
+ // 执行更新
+ taskRuleMapper.updateById(BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO));
+ }
+
+ @Override
+ public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) {
+ // 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性
+ List modelRules = getTaskAssignRuleList(modelId, null);
+ List processInstanceRules = getTaskAssignRuleList(null, processDefinitionId);
+ if (modelRules.size() != processInstanceRules.size()) {
+ return false;
+ }
+
+ // 遍历,匹配对应的规则
+ Map processInstanceRuleMap = CollectionUtils.convertMap(processInstanceRules,
+ BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
+ for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
+ BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
+ if (processInstanceRule == null) {
+ return false;
+ }
+ if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType())
+ || !ObjectUtil.equal(modelRule.getOptions(), processInstanceRule.getOptions())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) {
+ List rules = getTaskAssignRuleList(fromModelId, null);
+ if (CollUtil.isEmpty(rules)) {
+ return;
+ }
+ // 开始复制
+ List newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
+ newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null)
+ .setCreateTime(null).setUpdateTime(null));
+ taskRuleMapper.insertBatch(newRules);
+ }
+
+ @Override
+ public void checkTaskAssignRuleAllConfig(String id) {
+ // 一个用户任务都没配置,所以无需配置规则
+ List taskAssignRules = getTaskAssignRuleList(id, null);
+ if (CollUtil.isEmpty(taskAssignRules)) {
+ return;
+ }
+ // 校验未配置规则的任务
+ taskAssignRules.forEach(rule -> {
+ if (CollUtil.isEmpty(rule.getOptions())) {
+ throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
+ }
+ });
+ }
+
+ private void validTaskAssignRuleOptions(Integer type, Set options) {
+ if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
+ roleApi.validRoles(options);
+ } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
+ BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
+ deptApi.validDepts(options);
+ } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
+ postApi.validPosts(options);
+ } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {
+ adminUserApi.validUsers(options);
+ } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
+ userGroupService.validUserGroups(options);
+ } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
+ dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT,
+ CollectionUtils.convertSet(options, String::valueOf));
+ } else {
+ throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type));
+ }
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java
new file mode 100644
index 000000000..20d71ec24
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
+
+import java.util.List;
+
+/**
+ * BPM 活动实例 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface BpmActivityService {
+
+ /**
+ * 获得指定流程实例的活动实例列表
+ *
+ * @param processInstanceId 流程实例的编号
+ * @return 活动实例列表
+ */
+ List getActivityListByProcessInstanceId(String processInstanceId);
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
new file mode 100644
index 000000000..fdab5a884
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.hutool.core.io.IoUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
+import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import lombok.extern.slf4j.Slf4j;
+
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.history.HistoricActivityInstance;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.image.ProcessDiagramGenerator;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
+
+/**
+ * BPM 活动实例 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Slf4j
+@Validated
+public class BpmActivityServiceImpl implements BpmActivityService {
+
+ @Resource
+ private HistoryService historyService;
+
+ @Override
+ public List getActivityListByProcessInstanceId(String processInstanceId) {
+ List activityList = historyService.createHistoricActivityInstanceQuery()
+ .processInstanceId(processInstanceId).list();
+ return BpmActivityConvert.INSTANCE.convertList(activityList);
+ }
+
+
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
new file mode 100644
index 000000000..831af4d3d
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
@@ -0,0 +1,149 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
+import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
+import org.flowable.engine.delegate.event.FlowableCancelledEvent;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.runtime.ProcessInstance;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 流程实例 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface BpmProcessInstanceService {
+
+ /**
+ * 获得流程实例
+ *
+ * @param id 流程实例的编号
+ * @return 流程实例
+ */
+ ProcessInstance getProcessInstance(String id);
+
+ /**
+ * 获得流程实例列表
+ *
+ * @param ids 流程实例的编号集合
+ * @return 流程实例列表
+ */
+ List getProcessInstances(Set ids);
+
+ /**
+ * 获得流程实例 Map
+ *
+ * @param ids 流程实例的编号集合
+ * @return 流程实例列表 Map
+ */
+ default Map getProcessInstanceMap(Set ids) {
+ return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
+ }
+
+ /**
+ * 获得流程实例的分页
+ *
+ * @param userId 用户编号
+ * @param pageReqVO 分页请求
+ * @return 流程实例的分页
+ */
+ PageResult getMyProcessInstancePage(Long userId,
+ @Valid BpmProcessInstanceMyPageReqVO pageReqVO);
+ /**
+ * 创建流程实例(提供给前端)
+ *
+ * @param userId 用户编号
+ * @param createReqVO 创建信息
+ * @return 实例的编号
+ */
+ String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO);
+
+ /**
+ * 创建流程实例(提供给内部)
+ *
+ * @param userId 用户编号
+ * @param createReqDTO 创建信息
+ * @return 实例的编号
+ */
+ String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO);
+
+ /**
+ * 获得流程实例 VO 信息
+ *
+ * @param id 流程实例的编号
+ * @return 流程实例
+ */
+ BpmProcessInstanceRespVO getProcessInstanceVO(String id);
+
+ /**
+ * 取消流程实例
+ *
+ * @param userId 用户编号
+ * @param cancelReqVO 取消信息
+ */
+ void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO);
+
+ /**
+ * 获得历史的流程实例
+ *
+ * @param id 流程实例的编号
+ * @return 历史的流程实例
+ */
+ HistoricProcessInstance getHistoricProcessInstance(String id);
+
+ /**
+ * 获得历史的流程实例列表
+ *
+ * @param ids 流程实例的编号集合
+ * @return 历史的流程实例列表
+ */
+ List getHistoricProcessInstances(Set ids);
+
+ /**
+ * 获得历史的流程实例 Map
+ *
+ * @param ids 流程实例的编号集合
+ * @return 历史的流程实例列表 Map
+ */
+ default Map getHistoricProcessInstanceMap(Set ids) {
+ return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
+ }
+
+ /**
+ * 创建 ProcessInstance 拓展记录
+ *
+ * @param instance 流程任务
+ */
+ void createProcessInstanceExt(ProcessInstance instance);
+
+ /**
+ * 更新 ProcessInstance 拓展记录为取消
+ *
+ * @param event 流程取消事件
+ */
+ void updateProcessInstanceExtCancel(FlowableCancelledEvent event);
+
+ /**
+ * 更新 ProcessInstance 拓展记录为完成
+ *
+ * @param instance 流程任务
+ */
+ void updateProcessInstanceExtComplete(ProcessInstance instance);
+
+ /**
+ * 更新 ProcessInstance 拓展记录为不通过
+ *
+ * @param id 流程编号
+ * @param comment 理由。例如说,审批不通过时,需要传递该值
+ */
+ void updateProcessInstanceExtReject(String id, String comment);
+
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
new file mode 100644
index 000000000..9c21bd8a9
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
@@ -0,0 +1,300 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
+import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
+import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.delegate.event.FlowableCancelledEvent;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF;
+
+/**
+ * 流程实例 Service 实现类
+ *
+ * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
+ * 1. https://blog.csdn.net/bobozai86/article/details/105210414
+ *
+ * HistoricProcessInstance & ProcessInstance 的关系:
+ * 1.https://my.oschina.net/843294669/blog/719024
+ * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+@Slf4j
+public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
+
+ @Resource
+ private RuntimeService runtimeService;
+ @Resource
+ private BpmProcessInstanceExtMapper processInstanceExtMapper;
+ @Resource
+ @Lazy // 解决循环依赖
+ private BpmTaskService taskService;
+ @Resource
+ private BpmProcessDefinitionService processDefinitionService;
+ @Resource
+ private HistoryService historyService;
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher;
+ @Resource
+ private BpmMessageService messageService;
+ @Override
+ public ProcessInstance getProcessInstance(String id) {
+ return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
+ }
+
+ @Override
+ public List getProcessInstances(Set ids) {
+ return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
+ }
+
+ @Override
+ public PageResult getMyProcessInstancePage(Long userId,
+ BpmProcessInstanceMyPageReqVO pageReqVO) {
+ // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页
+ PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO);
+ if (CollUtil.isEmpty(pageResult.getList())) {
+ return new PageResult<>(pageResult.getTotal());
+ }
+
+ // 获得流程 Task Map
+ List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId);
+ Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds);
+ // 转换返回
+ return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
+ // 获得流程定义
+ ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
+ // 发起流程
+ return createProcessInstance0(userId, definition, createReqVO.getVariables(), null);
+ }
+
+ @Override
+ public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
+ // 获得流程定义
+ ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
+ // 发起流程
+ return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
+ }
+
+ @Override
+ public BpmProcessInstanceRespVO getProcessInstanceVO(String id) {
+ // 获得流程实例
+ HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
+ if (processInstance == null) {
+ return null;
+ }
+ BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id);
+ Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id);
+
+ // 获得流程定义
+ ProcessDefinition processDefinition = processDefinitionService
+ .getProcessDefinition(processInstance.getProcessDefinitionId());
+ Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId());
+ BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt(
+ processInstance.getProcessDefinitionId());
+ Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id);
+ String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
+
+ // 获得 User
+ AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
+ DeptRespDTO dept = null;
+ if (startUser != null) {
+ dept = deptApi.getDept(startUser.getDeptId());
+ }
+
+ // 拼接结果
+ return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt,
+ processDefinition, processDefinitionExt, bpmnXml, startUser, dept);
+ }
+
+ @Override
+ public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
+ // 校验流程实例存在
+ ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
+ if (instance == null) {
+ throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
+ }
+ // 只能取消自己的
+ if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
+ throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
+ }
+
+ // 通过删除流程实例,实现流程实例的取消,
+ // 删除流程实例,正则执行任务ACT_RU_TASK. 任务会被删除。通过历史表查询
+ deleteProcessInstance(cancelReqVO.getId(),
+ BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason()));
+ }
+
+ /**
+ * 获得历史的流程实例
+ *
+ * @param id 流程实例的编号
+ * @return 历史的流程实例
+ */
+ @Override
+ public HistoricProcessInstance getHistoricProcessInstance(String id) {
+ return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
+ }
+
+ @Override
+ public List getHistoricProcessInstances(Set ids) {
+ return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
+ }
+
+ @Override
+ public void createProcessInstanceExt(ProcessInstance instance) {
+ // 获得流程定义
+ ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId());
+ // 插入 BpmProcessInstanceExtDO 对象
+ BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
+ .setProcessInstanceId(instance.getId())
+ .setProcessDefinitionId(definition.getId())
+ .setName(instance.getProcessDefinitionName())
+ .setStartUserId(Long.valueOf(instance.getStartUserId()))
+ .setCategory(definition.getCategory())
+ .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus())
+ .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
+
+ processInstanceExtMapper.insert(instanceExtDO);
+ }
+
+ @Override
+ public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) {
+ // 判断是否为 Reject 不通过。如果是,则不进行更新
+ if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) {
+ return;
+ }
+
+ // 需要主动查询,因为 instance 只有 id 属性
+ // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
+ HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId());
+ // 更新拓展表
+ BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
+ .setProcessInstanceId(event.getProcessInstanceId())
+ .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
+ .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
+ .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult());
+
+ processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
+
+ // 发送流程实例的状态事件
+ processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
+ BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
+ }
+
+ @Override
+ public void updateProcessInstanceExtComplete(ProcessInstance instance) {
+ // 需要主动查询,因为 instance 只有 id 属性
+ // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance
+ HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId());
+ // 更新拓展表
+ BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO()
+ .setProcessInstanceId(instance.getProcessInstanceId())
+ .setEndTime(new Date()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置
+ .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
+ .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过
+ processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
+
+ // 发送流程被通过的消息
+ messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance));
+
+ // 发送流程实例的状态事件
+ processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
+ BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ public void updateProcessInstanceExtReject(String id, String comment) {
+ // 需要主动查询,因为 instance 只有 id 属性
+ ProcessInstance processInstance = getProcessInstance(id);
+ // 删除流程实例,以实现驳回任务时,取消整个审批流程
+ deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
+
+ // 更新 status + result
+ // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法,
+ // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的
+ BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id)
+ .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus())
+ .setResult(BpmProcessInstanceResultEnum.REJECT.getResult());
+ processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
+
+ // 发送流程被不通过的消息
+ messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, comment));
+
+ // 发送流程实例的状态事件
+ processInstanceResultEventPublisher.sendProcessInstanceResultEvent(
+ BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult()));
+ }
+
+ private void deleteProcessInstance(String id, String reason) {
+ runtimeService.deleteProcessInstance(id, reason);
+ }
+
+ private String createProcessInstance0(Long userId, ProcessDefinition definition,
+ Map variables, String businessKey) {
+ // 校验流程定义
+ if (definition == null) {
+ throw exception(PROCESS_DEFINITION_NOT_EXISTS);
+ }
+ if (definition.isSuspended()) {
+ throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
+ }
+
+ // 创建流程实例
+ ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
+ // 设置流程名字
+ runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
+
+ // 补全流程实例的拓展表
+ processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
+ .setFormVariables(variables));
+
+ return instance.getId();
+ }
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
new file mode 100644
index 000000000..e8aab6aa8
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
@@ -0,0 +1,117 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
+import org.flowable.task.api.Task;
+
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 流程任务实例 Service 接口
+ *
+ * @author jason
+ * @author 芋道源码
+ */
+public interface BpmTaskService {
+ /**
+ * 获得待办的流程任务分页
+ *
+ * @param userId 用户编号
+ * @param pageReqVO 分页请求
+ * @return 流程任务分页
+ */
+ PageResult getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
+ /**
+ * 获得已办的流程任务分页
+ *
+ * @param userId 用户编号
+ * @param pageReqVO 分页请求
+ * @return 流程任务分页
+ */
+ PageResult getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
+
+ /**
+ * 获得流程任务 Map
+ *
+ * @param processInstanceIds 流程实例的编号数组
+ * @return 流程任务 Map
+ */
+ default Map> getTaskMapByProcessInstanceIds(List processInstanceIds) {
+ return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
+ Task::getProcessInstanceId);
+ }
+
+ /**
+ * 获得流程任务列表
+ *
+ * @param processInstanceIds 流程实例的编号数组
+ * @return 流程任务列表
+ */
+ List getTasksByProcessInstanceIds(List processInstanceIds);
+
+ /**
+ * 获得指令流程实例的流程任务列表,包括所有状态的
+ *
+ * @param processInstanceId 流程实例的编号
+ * @return 流程任务列表
+ */
+ List getTaskListByProcessInstanceId(String processInstanceId);
+
+ /**
+ * 通过任务
+ *
+ * @param userId 用户编号
+ * @param reqVO 通过请求
+ */
+ void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO);
+
+ /**
+ * 不通过任务
+ *
+ * @param userId 用户编号
+ * @param reqVO 不通过请求
+ */
+ void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
+
+ /**
+ * 将流程任务分配给指定用户
+ *
+ * @param userId 用户编号
+ * @param reqVO 分配请求
+ */
+ void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO);
+
+ /**
+ * 将流程任务分配给指定用户
+ *
+ * @param id 流程任务编号
+ * @param userId 用户编号
+ */
+ void updateTaskAssignee(String id, Long userId);
+
+ /**
+ * 创建 Task 拓展记录
+ *
+ * @param task 任务实体
+ */
+ void createTaskExt(Task task);
+
+ /**
+ * 更新 Task 拓展记录为完成
+ *
+ * @param task 任务实体
+ */
+ void updateTaskExtComplete(Task task);
+
+ /**
+ * 更新 Task 拓展记录,并发送通知
+ *
+ * @param task 任务实体
+ */
+ void updateTaskExtAssign(Task task);
+
+}
diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
new file mode 100644
index 000000000..5c004977c
--- /dev/null
+++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -0,0 +1,270 @@
+package cn.iocoder.yudao.module.bpm.service.task;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.common.util.object.PageUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
+import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
+import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskQuery;
+import org.flowable.task.api.history.HistoricTaskInstance;
+import org.flowable.task.api.history.HistoricTaskInstanceQuery;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.*;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
+
+/**
+ * 流程任务实例 Service 实现类
+ *
+ * @author 芋道源码
+ * @author jason
+ */
+@Slf4j
+@Service
+public class BpmTaskServiceImpl implements BpmTaskService{
+
+ @Resource
+ private TaskService taskService;
+ @Resource
+ private HistoryService historyService;
+
+ @Resource
+ private BpmProcessInstanceService processInstanceService;
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+ @Resource
+ private BpmTaskExtMapper taskExtMapper;
+ @Resource
+ private BpmMessageService messageService;
+
+ @Override
+ public PageResult getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
+ // 查询待办任务
+ TaskQuery taskQuery = taskService.createTaskQuery()
+ .taskAssignee(String.valueOf(userId)) // 分配给自己
+ .orderByTaskCreateTime().desc(); // 创建时间倒序
+ if (StrUtil.isNotBlank(pageVO.getName())) {
+ taskQuery.taskNameLike("%" + pageVO.getName() + "%");
+ }
+ if (pageVO.getBeginCreateTime() != null) {
+ taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
+ }
+ if (pageVO.getEndCreateTime() != null) {
+ taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
+ }
+ // 执行查询
+ List tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
+ if (CollUtil.isEmpty(tasks)) {
+ return PageResult.empty(taskQuery.count());
+ }
+
+ // 获得 ProcessInstance Map
+ Map processInstanceMap = processInstanceService.getProcessInstanceMap(
+ convertSet(tasks, Task::getProcessInstanceId));
+ // 获得 User Map
+ Map userMap = adminUserApi.getUserMap(
+ convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+ // 拼接结果
+ return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap),
+ taskQuery.count());
+ }
+
+ @Override
+ public PageResult getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
+ // 查询已办任务
+ HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
+ .finished() // 已完成
+ .taskAssignee(String.valueOf(userId)) // 分配给自己
+ .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
+ if (StrUtil.isNotBlank(pageVO.getName())) {
+ taskQuery.taskNameLike("%" + pageVO.getName() + "%");
+ }
+ if (pageVO.getBeginCreateTime() != null) {
+ taskQuery.taskCreatedAfter(pageVO.getBeginCreateTime());
+ }
+ if (pageVO.getEndCreateTime() != null) {
+ taskQuery.taskCreatedBefore(pageVO.getEndCreateTime());
+ }
+ // 执行查询
+ List tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
+ if (CollUtil.isEmpty(tasks)) {
+ return PageResult.empty(taskQuery.count());
+ }
+
+ // 获得 TaskExtDO Map
+ List bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
+ Map bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
+ // 获得 ProcessInstance Map
+ Map historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
+ convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
+ // 获得 User Map
+ Map userMap = adminUserApi.getUserMap(
+ convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+ // 拼接结果
+ return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
+ taskQuery.count());
+ }
+
+ @Override
+ public List getTasksByProcessInstanceIds(List processInstanceIds) {
+ if (CollUtil.isEmpty(processInstanceIds)) {
+ return Collections.emptyList();
+ }
+ return taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
+ }
+
+ @Override
+ public List getTaskListByProcessInstanceId(String processInstanceId) {
+ // 获得任务列表
+ List tasks = historyService.createHistoricTaskInstanceQuery()
+ .processInstanceId(processInstanceId)
+ .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
+ .list();
+ if (CollUtil.isEmpty(tasks)) {
+ return Collections.emptyList();
+ }
+
+ // 获得 TaskExtDO Map
+ List bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
+ Map bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
+ // 获得 ProcessInstance Map
+ HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
+ // 获得 User Map
+ Set userIds = convertSet(tasks, task -> NumberUtils.parseLong(task.getAssignee()));
+ userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
+ Map userMap = adminUserApi.getUserMap(userIds);
+ // 获得 Dept Map
+ Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+
+ // 拼接数据
+ return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
+ // 校验任务存在
+ Task task = checkTask(userId, reqVO.getId());
+ // 校验流程实例存在
+ ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+ if (instance == null) {
+ throw exception(PROCESS_INSTANCE_NOT_EXISTS);
+ }
+
+ // 完成任务,审批通过
+ taskService.complete(task.getId(), instance.getProcessVariables());
+ // 更新任务拓展表为通过
+ taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
+ .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setComment(reqVO.getComment()));
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
+ Task task = checkTask(userId, reqVO.getId());
+ // 校验流程实例存在
+ ProcessInstance instance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+ if (instance == null) {
+ throw exception(PROCESS_INSTANCE_NOT_EXISTS);
+ }
+
+ // 更新流程实例为不通过
+ processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
+
+ // 更新任务拓展表为不通过
+ taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
+ .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
+ }
+
+ @Override
+ public void updateTaskAssignee(Long userId, BpmTaskUpdateAssigneeReqVO reqVO) {
+ // 校验任务存在
+ Task task = checkTask(userId, reqVO.getId());
+ // 更新负责人
+ updateTaskAssignee(task.getId(), reqVO.getAssigneeUserId());
+ }
+
+ @Override
+ public void updateTaskAssignee(String id, Long userId) {
+ taskService.setAssignee(id, String.valueOf(userId));
+ }
+
+
+ @Override
+ public void createTaskExt(Task task) {
+ BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
+ .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
+ taskExtMapper.insert(taskExtDO);
+ }
+
+ @Override
+ public void updateTaskExtComplete(Task task) {
+ BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
+ .setEndTime(new Date());
+ taskExtMapper.updateByTaskId(taskExtDO);
+ }
+
+ @Override
+ public void updateTaskExtAssign(Task task) {
+ BpmTaskExtDO taskExtDO = new BpmTaskExtDO()
+ .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
+ .setTaskId(task.getId());
+ taskExtMapper.updateByTaskId(taskExtDO);
+ // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+ @Override
+ public void afterCommit() {
+ ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
+ AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
+ messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
+ }
+ });
+ }
+
+ /**
+ * 校验任务是否存在, 并且是否是分配给自己的任务
+ * @param userId 用户 id
+ * @param taskId task id
+ */
+ private Task checkTask(Long userId, String taskId) {
+ Task task = getTask(taskId);
+ if (task == null) {
+ throw exception(TASK_COMPLETE_FAIL_NOT_EXISTS);
+ }
+ if (!Objects.equals(userId, NumberUtils.parseLong(task.getAssignee()))) {
+ throw exception(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
+ }
+ return task;
+ }
+
+ private Task getTask(String id) {
+ return taskService.createTaskQuery().taskId(id).singleResult();
+ }
+}
diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/UserController.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/UserController.java
new file mode 100644
index 000000000..ce5667d32
--- /dev/null
+++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/UserController.java
@@ -0,0 +1,4 @@
+package cn.iocoder.yudao.module.member.controller.admin.user;
+
+public class UserController {
+}
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java
diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java
similarity index 89%
rename from yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java
index c67a526d4..7146b98ef 100644
--- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.framework.security.core.enums;
+package cn.iocoder.yudao.module.system.enums.permission;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java
similarity index 100%
rename from yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java
rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java
new file mode 100644
index 000000000..c4946c371
--- /dev/null
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java
@@ -0,0 +1,4 @@
+package cn.iocoder.yudao.module.system.controller.app.dict;
+
+public class AppDictDataController {
+}
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java
index ce58219b5..4944be16b 100644
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.permission;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
-import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
deleted file mode 100644
index 2f845fd10..000000000
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package cn.iocoder.yudao.module.system.enums.logger;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 登录日志的类型枚举
- */
-@Getter
-@AllArgsConstructor
-public enum LoginLogTypeEnum {
-
- LOGIN_USERNAME(100), // 使用账号登录
- LOGIN_SOCIAL(101), // 使用社交登录
- LOGIN_MOCK(102), // 使用 Mock 登录
- LOGIN_MOBILE(103), // 使用手机登陆
- LOGIN_SMS(104), // 使用短信登陆
-
- LOGOUT_SELF(200), // 自己主动登出
- LOGOUT_TIMEOUT(201), // 超时登出
- LOGOUT_DELETE(202), // 强制退出
- ;
-
- /**
- * 日志类型
- */
- private final Integer type;
-
-}
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java
deleted file mode 100644
index 7084e13da..000000000
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.system.enums.logger;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 登录结果的枚举类
- */
-@Getter
-@AllArgsConstructor
-public enum LoginResultEnum {
-
- SUCCESS(0), // 成功
- BAD_CREDENTIALS(10), // 账号或密码不正确
- USER_DISABLED(20), // 用户被禁用
- CAPTCHA_NOT_FOUND(30), // 图片验证码不存在
- CAPTCHA_CODE_ERROR(31), // 图片验证码不正确
-
- UNKNOWN_ERROR(100), // 未知异常
- ;
-
- /**
- * 结果
- */
- private final Integer result;
-
-}
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
index f47e83b02..15c4396bd 100644
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
@@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
index 1c47dc35a..ebea1f88c 100644
--- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
@@ -6,7 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO;
diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
index f9b636340..9e2e95e1e 100644
--- a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
+++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.module.system.test.BaseDbUnitTest;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java
index 6e8f291ab..21f46b8bb 100644
--- a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java
+++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.service.permission;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO;
diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml
index c9163a0f4..1b7bdbe94 100644
--- a/yudao-server/pom.xml
+++ b/yudao-server/pom.xml
@@ -47,12 +47,17 @@
yudao-module-pay-impl
${revision}
-
+
cn.iocoder.boot
- yudao-module-bpm-impl-activiti
+ yudao-module-bpm-impl-flowable
${revision}
+
+
+
+
+
diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml
index ef43d2b4d..3e8b3b636 100644
--- a/yudao-server/src/main/resources/application-local.yaml
+++ b/yudao-server/src/main/resources/application-local.yaml
@@ -43,13 +43,15 @@ spring:
primary: master
datasource:
master:
- name: ruoyi-vue-pro
+# name: ruoyi-vue-pro俺吧
+ name: ruoyi-vue-pro-flowable
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
slave: # 模拟从库,可根据自己需要修改
- name: ruoyi-vue-pro
+# name: ruoyi-vue-pro
+ name: ruoyi-vue-pro-flowable
url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml
index 67c06c7f4..cd42d7fac 100644
--- a/yudao-server/src/main/resources/application.yaml
+++ b/yudao-server/src/main/resources/application.yaml
@@ -27,10 +27,21 @@ spring:
# 3. create_drop: 启动时自动创建表,关闭时自动删除表
# 4. drop_create: 启动时,删除旧表,再创建新表
database-schema-update: false # 设置为 false,可通过 sql/activiti.sql 初始化
- db-history-used: true # activiti7 默认不生成历史信息表,需手动设置开启
+ db-history-used: true # activiti7 默认 false 不生成历史信息表,需手动设置开启
check-process-definitions: false # 设置为 false,禁用 /resources/processes 自动部署 BPMN XML 流程
history-level: full # full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
+# 工作流 Flowable 配置
+flowable:
+ # 1. false: 默认值,activiti启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
+ # 2. true: 启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
+ # 3. create_drop: 启动时自动创建表,关闭时自动删除表
+ # 4. drop_create: 启动时,删除旧表,再创建新表
+ database-schema-update: false # 设置为 false,可通过 https://github.com/flowable/flowable-sql 初始化
+ db-history-used: true # flowable6 默认 true 生成信息表,无需手动设置
+ check-process-definitions: false # 设置为 false,禁用 /resources/processes 自动部署 BPMN XML 流程
+ history-level: full # full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
+
# MyBatis Plus 的配置项
mybatis-plus:
configuration:
diff --git a/yudao-ui-admin/src/views/bpm/model/index.vue b/yudao-ui-admin/src/views/bpm/model/index.vue
index d3f157b33..029ad9f60 100644
--- a/yudao-ui-admin/src/views/bpm/model/index.vue
+++ b/yudao-ui-admin/src/views/bpm/model/index.vue
@@ -291,7 +291,7 @@ export default {
// 设置上传的请求头部
headers: getBaseHeader(),
// 上传的地址
- url: process.env.VUE_APP_BASE_API + '/admin-api/' + "/bpm/model/import",
+ url: process.env.VUE_APP_BASE_API + '/admin-api' + "/bpm/model/import",
// 表单
form: {},
// 校验规则