Commit deef74ef by 赵剑炜

整合项目

parent 3abf09a8
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Zeppelin ignored files
/ZeppelinRemoteNotebooks/
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="jyzb-process" />
<module name="jyzb-api" />
<module name="jyzb-biz" />
<module name="jyzb-boot" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="junmp-jyzb-app" options="-parameters" />
<module name="jyzb-api" options="-parameters" />
<module name="jyzb-biz" options="-parameters" />
<module name="jyzb-boot" options="-parameters" />
<module name="jyzb-process" options="-parameters" />
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/jyzb-api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-biz/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-biz/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-boot/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-boot/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-process/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jyzb-process/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="aliyun" />
<option name="name" value="aliyun" />
<option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="junmp-public" />
<option name="name" value="junmp-public" />
<option name="url" value="http://maven.sothing.top/repository/junmp-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="oss" />
<option name="name" value="oss" />
<option name="url" value="https://oss.sonatype.org/content/groups/public" />
</remote-repository>
<remote-repository>
<option name="id" value="spring-milestones" />
<option name="name" value="Spring Milestones" />
<option name="url" value="https://repo.spring.io/libs-milestone" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/jyzb-process/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="19" project-jdk-type="JavaSDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -2,14 +2,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>junmp-gold-app</artifactId>
<groupId>com.junmp.gold</groupId>
<artifactId>junmp-jyzb-app</artifactId>
<groupId>com.junmp.jyzb</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gold-api</artifactId>
<artifactId>jyzb-api</artifactId>
<version>1.0.0</version>
<name>gold-api</name>
<name>jyzb-api</name>
<dependencies>
<dependency>
......
artifactId=jyzb-api
groupId=com.junmp.jyzb
version=1.0.0
com\junmp\gold\api\bean\vo\ProductSkuVo.class
com\junmp\gold\api\exception\enums\CompanyExceptionEnum.class
com\junmp\gold\api\exception\enums\ProductExceptionEnum.class
com\junmp\gold\api\bean\dto\ProductProcessDto.class
com\junmp\gold\api\bean\req\ProductSkuReq.class
com\junmp\gold\api\bean\dto\ProductTagDto.class
com\junmp\gold\api\bean\dto\ProductBatchDto.class
com\junmp\gold\api\bean\vo\TagInfoVo.class
com\junmp\gold\api\constant\GoldConstant.class
com\junmp\gold\api\bean\vo\NDefContentVo.class
com\junmp\gold\api\bean\vo\TagInfoVo$TagInfoVoBuilder.class
com\junmp\gold\api\bean\req\DbAccessReq.class
com\junmp\gold\api\util\GenCodeUtil.class
com\junmp\gold\api\bean\req\CompanyReq.class
com\junmp\gold\api\bean\req\ProductBatchReq.class
com\junmp\gold\api\bean\req\ProductTagReq.class
com\junmp\gold\api\bean\dto\SimpleTagDto.class
com\junmp\gold\api\exception\GoldAppException.class
com\junmp\gold\api\bean\req\ProductReq.class
com\junmp\gold\api\bean\vo\AuthAccessVo.class
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\ProductTagReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\dto\ProductTagDto.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\util\GenCodeUtil.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\DbAccessReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\exception\enums\package-info.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\exception\enums\ProductExceptionEnum.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\exception\enums\CompanyExceptionEnum.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\exception\GoldAppException.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\ProductReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\vo\AuthAccessVo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\ProductBatchReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\CompanyReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\constant\GoldConstant.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\dto\ProductProcessDto.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\vo\NDefContentVo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\dto\ProductBatchDto.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\req\ProductSkuReq.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\vo\ProductSkuVo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\dto\SimpleTagDto.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-api\src\main\java\com\junmp\gold\api\bean\vo\TagInfoVo.java
......@@ -2,14 +2,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>junmp-gold-app</artifactId>
<groupId>com.junmp.gold</groupId>
<artifactId>junmp-jyzb-app</artifactId>
<groupId>com.junmp.jyzb</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gold-biz</artifactId>
<artifactId>jyzb-biz</artifactId>
<version>1.0.0</version>
<name>gold-biz</name>
<name>jyzb-biz</name>
<dependencies>
<dependency>
......@@ -31,8 +31,8 @@
</dependency>
<dependency>
<groupId>com.junmp.gold</groupId>
<artifactId>gold-api</artifactId>
<groupId>com.junmp.jyzb</groupId>
<artifactId>jyzb-api</artifactId>
</dependency>
<dependency>
<groupId>com.junmp.v2</groupId>
......
......@@ -23,4 +23,9 @@ public interface CompanyMapper extends BaseMapper<Company> {
* 获取当前最大序号
*/
Integer getMaxSn();
/**
* 获取当前最大序号
*/
Integer getMaxSn1();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.junmp.gold.mapper.CompanyMapper">
<select id="getMaxSn" resultType="java.lang.Integer">
select ifnull(max(s1.sn), 0) as sn
from biz_company s1
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.junmp.gold.mapper.ProductBatchMapper">
<select id="getMaxSn" resultType="java.lang.Integer">
select ifnull(max(s1.sn), 0) as sn
from biz_product_batch s1
</select>
<select id="getBatchProcess" resultType="com.junmp.gold.api.bean.dto.ProductBatchDto">
select *
from v_product_batch_process
where batchId = #{batchId}
</select>
<select id="getBatchPage" resultType="com.junmp.gold.api.bean.dto.ProductBatchDto">
select * from v_product_batch_process s1 where 1=1
<if test="null != batch">
<if test="null != batch.batchId">
and s1.batchId = #{batch.batchId}
</if>
<if test="null != batch.productId">
and s1.productId = #{batch.productId}
</if>
<if test="null != batch.specId">
and s1.specId = #{batch.specId}
</if>
<if test="null != batch.batchNo">
and s1.batchNo like concat('%',#{batch.batchNo},'%')
</if>
</if>
order by s1.createTime desc
</select>
<select id="getBatchProcessPage" resultType="com.junmp.gold.api.bean.dto.ProductProcessDto">
select * from v_product_batch_check s1 where 1=1
<if test="null != batch">
<if test="null != batch.batchId">
and s1.batchId = #{batch.batchId}
</if>
<if test="null != batch.productId">
and s1.productId = #{batch.productId}
</if>
<if test="null != batch.specId">
and s1.specId = #{batch.specId}
</if>
<if test="null != batch.batchNo">
and s1.batchNo like concat('%',#{batch.batchNo},'%')
</if>
</if>
order by s1.createTime desc
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.junmp.gold.mapper.ProductMapper">
<select id="getMaxSn" resultType="java.lang.Integer">
select ifnull(max(s1.sn), 0) as sn
from biz_product s1
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.junmp.gold.mapper.ProductSkuMapper">
<!-- 获取当前产品最大序号 -->
<select id="getMaxSn" resultType="java.lang.Integer">
select ifnull(max(s1.sn), 0) as sn
from biz_product_sku s1
where s1.product_id = #{productId}
</select>
<!-- 删除产品对应的号型 -->
<delete id="delByProductId">
delete
from biz_product_sku
where product_id = #{productId}
</delete>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.junmp.gold.mapper.ProductTagMapper">
<!-- limit 0,1-->
<select id="getInitTagInfo" resultType="com.junmp.gold.api.bean.dto.SimpleTagDto">
select s1.tag_id as tagId,s1.product_code as productCode
from biz_product_tag s1
where s1.batch_id = #{batchId}
and s1.has_init = 0
order by s1.serial_id asc limit 0,1
</select>
<select id="getTagInfoByTagId" resultType="com.junmp.gold.api.bean.dto.ProductTagDto">
SELECT s1.tagId,
s1.productCode,
s1.produceTime,
s1.productName,
s1.spec,
s1.material,
s1.weight,
s1.companyName,
s1.password,
s1.ciphertext,
s1.adInfo
FROM v_product_tag_info s1
WHERE s1.tagId = #{tagId}
</select>
</mapper>
artifactId=jyzb-biz
groupId=com.junmp.jyzb
version=1.0.0
com\junmp\gold\controller\ProductSkuController.class
com\junmp\gold\controller\ProductController.class
com\junmp\gold\entity\Product.class
com\junmp\gold\entity\ProductSku.class
com\junmp\gold\doc\ProductBatchDoc.class
com\junmp\gold\controller\LoginController.class
com\junmp\gold\mapper\CompanyMapper.class
com\junmp\gold\doc\ProductSkuDoc.class
com\junmp\gold\controller\ProductBatchController.class
com\junmp\gold\doc\ProductDoc.class
com\junmp\gold\controller\CompanyController.class
com\junmp\gold\service\ProductBatchService.class
com\junmp\gold\entity\Company.class
com\junmp\gold\service\impl\ProductSkuServiceImpl.class
com\junmp\gold\doc\CompanyDoc.class
com\junmp\gold\service\CompanyService.class
com\junmp\gold\mapper\ProductBatchMapper.class
com\junmp\gold\service\ProductSkuService.class
com\junmp\gold\doc\ProductTagDoc.class
com\junmp\gold\entity\ProductTag.class
com\junmp\gold\service\ProductTagService.class
com\junmp\gold\service\impl\CompanyServiceImpl.class
com\junmp\gold\controller\PublicController.class
com\junmp\gold\cache\GoldRedisCache.class
com\junmp\gold\entity\ProductBatch.class
com\junmp\gold\mapper\ProductTagMapper.class
com\junmp\gold\service\impl\ProductBatchServiceImpl.class
com\junmp\gold\mapper\ProductSkuMapper.class
com\junmp\gold\controller\ProductTagController.class
com\junmp\gold\mapper\ProductMapper.class
com\junmp\gold\doc\LoginDoc.class
com\junmp\gold\service\ProductService.class
com\junmp\gold\service\impl\ProductServiceImpl.class
com\junmp\gold\service\impl\ProductTagServiceImpl.class
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\LoginDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\mapper\ProductSkuMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\impl\ProductTagServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\CompanyDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\entity\Company.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\ProductTagService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\entity\Product.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\mapper\ProductMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\ProductController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\ProductTagDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\ProductBatchDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\ProductSkuService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\ProductBatchService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\mapper\ProductTagMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\impl\CompanyServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\ProductTagController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\entity\ProductTag.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\mapper\CompanyMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\CompanyService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\ProductBatchController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\impl\ProductBatchServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\CompanyController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\ProductSkuController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\PublicController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\ProductDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\cache\GoldRedisCache.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\doc\ProductSkuDoc.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\controller\LoginController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\ProductService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\impl\ProductSkuServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\mapper\ProductBatchMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\service\impl\ProductServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\entity\ProductBatch.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-biz\src\main\java\com\junmp\gold\entity\ProductSku.java
......@@ -2,14 +2,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>junmp-gold-app</artifactId>
<groupId>com.junmp.gold</groupId>
<artifactId>junmp-jyzb-app</artifactId>
<groupId>com.junmp.jyzb</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gold-boot</artifactId>
<artifactId>jyzb-boot</artifactId>
<version>1.0.0</version>
<name>gold-boot</name>
<name>jyzb-boot</name>
<dependencies>
......@@ -74,14 +74,14 @@
</dependency>
<dependency>
<groupId>com.junmp.gold</groupId>
<artifactId>gold-biz</artifactId>
<groupId>com.junmp.jyzb</groupId>
<artifactId>jyzb-biz</artifactId>
</dependency>
</dependencies>
<build>
<finalName>gold-boot</finalName>
<finalName>jyzb-boot</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
......@@ -95,7 +95,7 @@
</executions>
<configuration>
<!-- 如果没有该项配置,则devtools不会起作用,即应用不会restart -->
<mainClass>com.junmp.gold.boot.GoldBootApplication</mainClass>
<mainClass>com.junmp.jyzb.boot.JyzbBootApplication</mainClass>
<fork>true</fork>
</configuration>
</plugin>
......
package com.junmp.gold.boot;
package com.junmp.jyzb.boot;
import com.junmp.v2.db.starter.JpDataSourceAutoConfiguration;
import org.springframework.boot.SpringApplication;
......@@ -25,14 +25,14 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@SpringBootApplication(scanBasePackages = {"com.junmp"}, exclude = {FlywayAutoConfiguration.class,
JpDataSourceAutoConfiguration.class})
public class GoldBootApplication extends SpringBootServletInitializer {
public class JyzbBootApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(GoldBootApplication.class, args);
SpringApplication.run(JyzbBootApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(GoldBootApplication.class);
return builder.sources(JyzbBootApplication.class);
}
}
package com.junmp.gold.boot.config;
package com.junmp.jyzb.boot.config;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.junmp.gold.boot.module.JpJacksonModule;
import com.junmp.jyzb.boot.module.JpJacksonModule;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
......
package com.junmp.gold.boot.config;
package com.junmp.jyzb.boot.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
......
package com.junmp.gold.boot.core.handle;
package com.junmp.jyzb.boot.core.handle;
import cn.hutool.core.util.StrUtil;
import com.junmp.v2.auth.api.exception.AuthException;
......
package com.junmp.gold.boot.module;
package com.junmp.jyzb.boot.module;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
......
......@@ -26,15 +26,15 @@ knife4j:
spring:
datasource:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver #com.mysql.cj.jdbc.Driver
url: jdbc:p6spy:mysql://localhost:13306/db_gold_app?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true
username: root
password: ning2022
url: jdbc:p6spy:mysql://127.0.0.1:3306/db_jyzb?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true
username: junmp123
password: 123456
redis:
host: localhost
host: 127.0.0.1
port: 6379
database: 1
password: junmptech
password:
......
......@@ -21,11 +21,12 @@
<appender-ref ref="STDOUT"/>
</root>
<!--本项目的日志级别-->
<!--本项目的日志级别
<logger name="org.springframework" level="ERROR"/>
<logger name="com.junmp" level="info" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
-->
</springProfile>
<!-- ********************************************************************************************** -->
......
scanner:
open: false
# 配置第三方请求
junmp:
swagger:
base-package: com.junmp
id:
worker-id: 1
data-center-id: 1
epoch: 1656036996843
max: 9999
log:
type: db
ds: true #是否多数据源
knife4j:
enable: true
setting:
enableDebug: false
basic:
enable: true
username: ning
password: ning
spring:
datasource:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver #com.mysql.cj.jdbc.Driver
url: jdbc:p6spy:mysql://127.0.0.1:3306/db_jyzb?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true
username: junmp123
password: 123456
redis:
host: 127.0.0.1
port: 6379
database: 1
password:
scanner:
open: false
junmp:
swagger:
base-package: com.junmp
log:
type: db
bz:
config-storage:
knife4j:
enable: true
setting:
enableDebug: false
basic:
enable: true
username: ning
password: ning
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/chirpstack_as
username: junmp
password: junmp.com.cn
server:
port: 10030
spring:
main:
#bea同名类进行注册时,准许覆盖注册
allow-bean-definition-overriding: true
application:
name: gold-app
profiles:
active: local
servlet:
multipart:
max-request-size: 200MB
max-file-size: 200MB
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
locale: zh_CN
serialization:
indent_output: false
flyway:
enable: ture
locations: classpath:db/migration
# 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移
baseline-on-migrate: true
# 是否允许无序的迁移 开发环境最好开启, 生产环境关闭
out-of-order: true
# 关闭占位符替换,因为插入的sql里边可能包含${}关键字
placeholder-replacement: false
mybatis-plus:
configuration:
cache-enabled: true
lazy-loading-enabled: true
multiple-result-sets-enabled: true
map-underscore-to-camel-case: false
global-config:
banner: false
enable-sql-runner: true
db-config:
id-type: assign_id
table-underline: true
mapper-locations: classpath*:/mapper/**/*Mapper.xml
${AnsiColor.BRIGHT_YELLOW}
___ _____ _
|_ | |_ _| | |
| |_ _ _ __ _ __ ___ _ __ | | ___ ___| |__
| | | | | '_ \| '_ ` _ \| '_ \| |/ _ \/ __| '_ \
/\__/ / |_| | | | | | | | | | |_) | | __/ (__| | | |
\____/ \__,_|_| |_|_| |_| |_| .__/\_/\___|\___|_| |_|
| |
|_| 钧普科技,万物互联
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--日志格式应用spring boot默认的格式,也可以自己更改-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
<springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="app-log"/>
<!-- ****************************************************************************************** -->
<!-- ****************************** 本地开发只在控制台打印日志 ************************************ -->
<!-- ****************************************************************************************** -->
<springProfile name="local">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--默认所有的包以info-->
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<!--本项目的日志级别
<logger name="org.springframework" level="ERROR"/>
<logger name="com.junmp" level="info" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
-->
</springProfile>
<!-- ********************************************************************************************** -->
<!-- **** 放到服务器上不管在什么环境都只在文件记录日志,控制台(catalina.out)打印logback捕获不到的日志 **** -->
<!-- ********************************************************************************************** -->
<springProfile name="!local">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 日志记录器,日期滚动记录 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录 -->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_total.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/total/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--记录到文件时,记录两类一类是error日志,一个是所有日志-->
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="FILE_ALL"/>
</root>
</springProfile>
</configuration>
module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# \u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#\u65E5\u5FD7\u8F93\u51FA\u5230\u63A7\u5236\u53F0
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# \u4F7F\u7528\u65E5\u5FD7\u7CFB\u7EDF\u8BB0\u5F55 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# \u8BBE\u7F6E p6spy driver \u4EE3\u7406
deregisterdrivers=true
# \u53D6\u6D88JDBC URL\u524D\u7F00
useprefix=true
# \u914D\u7F6E\u8BB0\u5F55 Log \u4F8B\u5916,\u53EF\u53BB\u6389\u7684\u7ED3\u679C\u96C6\u6709error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# \u65E5\u671F\u683C\u5F0F
dateformat=yyyy-MM-dd HH:mm:ss
# \u5B9E\u9645\u9A71\u52A8\u53EF\u591A\u4E2A
driverlist=com.mysql.cj.jdbc.Driver
# \u662F\u5426\u5F00\u542F\u6162SQL\u8BB0\u5F55
outagedetection=true
# \u6162SQL\u8BB0\u5F55\u6807\u51C6 2 \u79D2
outagedetectioninterval=2
#
artifactId=jyzb-boot
groupId=com.junmp.jyzb
version=1.0.0
com\junmp\jyzb\boot\module\JpJacksonModule.class
com\junmp\jyzb\boot\config\GlobalCorsConfig.class
com\junmp\jyzb\boot\core\handle\GlobalExceptionHandler.class
com\junmp\jyzb\boot\JyzbBootApplication.class
com\junmp\jyzb\boot\config\MapperScanConfiguration.class
com\junmp\jyzb\boot\config\JsonSerializerConfig.class
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\config\GlobalCorsConfig.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\core\handle\GlobalExceptionHandler.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\module\JpJacksonModule.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\config\JsonSerializerConfig.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\config\MapperScanConfiguration.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-boot\src\main\java\com\junmp\jyzb\boot\JyzbBootApplication.java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>junmp-jyzb-app</artifactId>
<groupId>com.junmp.jyzb</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.junmp.jyzb</groupId>
<artifactId>jyzb-process</artifactId>
<version>1.0.0</version>
<properties>
<flowable.version>6.7.2</flowable.version>
<hutool-all.version>5.8.0</hutool-all.version>
<mybatis-plus.vesion>3.5.1</mybatis-plus.vesion>
<mybatis-plus.generator.vesion>3.4.1</mybatis-plus.generator.vesion>
<mybatis-plus.dynamic.vesion>3.5.1</mybatis-plus.dynamic.vesion>
<guava.version>31.1-jre</guava.version>
<fastjson.version>1.2.83</fastjson.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- JSON 解析器和生成器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.vesion}</version>
</dependency>
<!-- 代码生成 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.generator.vesion}</version>
<exclusions>
<exclusion>
<artifactId>mybatis-plus-extension</artifactId>
<groupId>com.baomidou</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${mybatis-plus.dynamic.vesion}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- flowable -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
<exclusions>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-app</artifactId>
</exclusion>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-form-spring-configurator</artifactId>
</exclusion>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-idm-spring-configurator</artifactId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-model</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<!--activiti modeler 5.22 end-->
<!-- 自动布局jar 包-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-layout</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-core</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-web</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-webmvc</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<!-- <name>jyzb-process</name>-->
<!-- <build>-->
<!-- <finalName>jyzb-process</finalName>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <goals>-->
<!-- <goal>repackage</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- <configuration>-->
<!-- &lt;!&ndash; 如果没有该项配置,则devtools不会起作用,即应用不会restart &ndash;&gt;-->
<!-- <mainClass>com.junmp.jyzb.boot.JyzbBootApplication</mainClass>-->
<!-- <fork>true</fork>-->
<!-- </configuration>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>-->
</project>
package org.modules.junmpProcess.common;
/**
*
*/
public interface CommonConstants {
/**
* {@code 500 Server Error} (HTTP/1.0 - RFC 1945)
*/
Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
/**
* {@code 200 OK} (HTTP/1.0 - RFC 1945)
*/
Integer SC_OK_200 = 200;
String FORM_VAR = "formData";
String PROCESS_STATUS = "processStatus";
String START_USER_INFO = "startUser";
String BUSINESS_STATUS_1 = "1"; //正在处理
String BUSINESS_STATUS_2 = "2";//撤销
String BUSINESS_STATUS_3 = "3";//驳回
String BUSINESS_STATUS_4 = "4";//已结束
}
package org.modules.junmpProcess.common;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* @author : willian fu
* @version : 1.0
*/
public class R {
public static Object badRequest(Object msg) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(msg);
}
public static Object notFound(Object msg) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(msg);
}
public static Object serverError(Object msg) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(msg);
}
public static Object noContent(Object msg) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(msg);
}
public static Object ok(Object msg) {
return ResponseEntity.ok(msg);
}
public static Object created(Object msg) {
return ResponseEntity.status(HttpStatus.CREATED).body(msg);
}
}
package org.modules.junmpProcess.common;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "接口返回对象", description = "接口返回对象")
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标志
*/
@ApiModelProperty(value = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
private String message = "操作成功!";
/**
* 返回代码
*/
@ApiModelProperty(value = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
private T result;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
private T data;
/**
* 时间戳
*/
@ApiModelProperty(value = "时间戳")
private long timestamp = System.currentTimeMillis();
public Result() {
}
public Result<T> success(String message) {
this.message = message;
this.code = CommonConstants.SC_OK_200;
this.success = true;
return this;
}
@Deprecated
public static Result<Object> ok() {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setMessage("成功");
return r;
}
@Deprecated
public static Result<Object> ok(String msg) {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setMessage(msg);
return r;
}
@Deprecated
public static Result<Object> ok(Object data) {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setResult(data);
return r;
}
public static <T> Result<T> OK() {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setMessage("成功");
return r;
}
public static <T> Result<T> OK(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setResult(data);
return r;
}
public static <T> Result<T> OK_data(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
// r.setResult(data);
r.setData(data);
return r;
}
public static <T> Result<T> OK(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstants.SC_OK_200);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static Result<Object> error(String msg) {
return error(CommonConstants.SC_INTERNAL_SERVER_ERROR_500, msg);
}
public static Result<Object> error(int code, String msg) {
Result<Object> r = new Result<Object>();
r.setCode(code);
r.setMessage(msg);
r.setSuccess(false);
return r;
}
public Result<T> error500(String message) {
this.message = message;
this.code = CommonConstants.SC_INTERNAL_SERVER_ERROR_500;
this.success = false;
return this;
}
@JsonIgnore
private String onlTable;
}
package org.modules.junmpProcess.common;
/**
* @author LoveMyOrange
* @create 2022-10-10 17:40
*/
public interface WorkFlowConstants {
String PROCESS_PREFIX = "Flowable";
String START_EVENT_ID = "startEventNode";
String END_EVENT_ID = "endEventNode";
String EXPRESSION_CLASS = "exUtils.";
}
package org.modules.junmpProcess.config;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.cfg.HttpClientConfig;
import org.flowable.engine.impl.cfg.DelegateExpressionFieldInjectionMode;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.job.service.JobHandler;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.modules.junmpProcess.job.CustomJobHandler;
import org.modules.junmpProcess.job.IdWorkerIdGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
/**
* @author
* @date
* @desc
*/
@Configuration
public class ActivitiConfig {
@Resource
private DataSource dataSource;
@Resource
private PlatformTransactionManager transactionManager;
@Resource
private IdWorkerIdGenerator idWorkerIdGenerator;
@Bean
public SpringProcessEngineConfiguration getSpringProcessEngineConfiguration() {
SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration();
config.setActivityFontName("宋体");
config.setAnnotationFontName("宋体");
config.setLabelFontName("黑体");
config.setDataSource(dataSource);
config.setTransactionManager(transactionManager);
config.setDisableIdmEngine(true);
config.setDatabaseType(ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL);
config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
config.setDelegateExpressionFieldInjectionMode(DelegateExpressionFieldInjectionMode.MIXED);
config.setIdGenerator(idWorkerIdGenerator);
config.setAsyncExecutorActivate(Boolean.TRUE);
HttpClientConfig httpClientConfig = new HttpClientConfig();
//连接超时
httpClientConfig.setConnectTimeout(10000);
//连接请求超时
httpClientConfig.setConnectionRequestTimeout(10000);
//双端建立socket连接
httpClientConfig.setSocketTimeout(10000);
//请求失败之后重试次数
httpClientConfig.setRequestRetryLimit(3);
config.setHttpClientConfig(httpClientConfig);
config.setKnowledgeBaseCacheLimit(200);
config.setProcessDefinitionCacheLimit(200);
List<JobHandler> customJobHandlers = new ArrayList<>();
customJobHandlers.add(new CustomJobHandler());
config.setCustomJobHandlers(customJobHandlers);
return config;
}
@Bean
@Primary
public TaskExecutor primaryTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}
package org.modules.junmpProcess.config;
import org.modules.junmpProcess.utils.IdWorker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author LoveMyOrange
* @create 2021-09-21 14:59
*/
@Configuration
public class IdWorkerConfig {
@Bean
public IdWorker idWorker() {
return new IdWorker();
}
}
package org.modules.junmpProcess.config.minio;//package org.jeecg.junmpProcess.config.minio;
//
//import org.springframework.boot.context.properties.ConfigurationProperties;
//
///**
// */
//@ConfigurationProperties(prefix = "config.minio")
//public class MinioConfigurationProperties {
// /**
// * 服务端地址
// */
// private String endpoint;
// /**
// * 账号
// */
// private String accessKey;
// /**
// * 密码
// */
// private String secretKey;
// /**
// * 地址
// */
// private String fileHost;
// public String getEndpoint() {
// return endpoint;
// }
//
// public void setEndpoint(String endpoint) {
// this.endpoint = endpoint;
// }
//
// public String getAccessKey() {
// return accessKey;
// }
//
// public void setAccessKey(String accessKey) {
// this.accessKey = accessKey;
// }
//
// public String getSecretKey() {
// return secretKey;
// }
//
// public void setSecretKey(String secretKey) {
// this.secretKey = secretKey;
// }
//
// public String getFileHost() {
// return fileHost;
// }
//
// public void setFileHost(String fileHost) {
// this.fileHost = fileHost;
// }
//}
package org.modules.junmpProcess.config.minio;//package org.jeecg.junmpProcess.config.minio;
//
//import io.minio.MinioClient;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.support.DefaultListableBeanFactory;
//import org.springframework.boot.context.properties.EnableConfigurationProperties;
//import org.springframework.context.annotation.Bean;
//import org.springframework.stereotype.Component;
//
///**
// * Minio客户端
// */
//@EnableConfigurationProperties(MinioConfigurationProperties.class)
//@Component
//public class MyMinioClient {
// @Autowired
// private MinioConfigurationProperties minioConfigurationProperties;
// @Autowired
// private DefaultListableBeanFactory defaultListableBeanFactory;
//
// @Bean
// public void minioClient(){
//// MinioClient minioClient = null;
//// if (StringUtils.isNotEmpty(minioConfigurationProperties.getAccessKey())){
//// minioClient = MinioClient.builder().endpoint(minioConfigurationProperties.getEndpoint()).credentials(minioConfigurationProperties.getAccessKey(),minioConfigurationProperties.getSecretKey()).build();
//// //将OSS对象手动注入到容器中
//// defaultListableBeanFactory.registerSingleton("minioClient",minioClient);
//// }else {
//// minioClient = MinioClient.builder().endpoint("yourEndpoint").credentials("yourAccessKey","yourSecretKey").build();
//// defaultListableBeanFactory.registerSingleton("minioClient",minioClient);
//// }
// }
//
//}
package org.modules.junmpProcess.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.modules.junmpProcess.service.Bussiness.WorkProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/Bpmn")
@Api(tags = "bnpm接口")
public class BpmnController {
@Autowired
private WorkProcessService ProcessService;
@SneakyThrows
@ApiOperation(value = "通过模板id查看流程信息 会附带流程定义id", notes = "获取所有Demo数据列表")
@PostMapping(value = "bpmn/create")
public boolean create(@RequestBody String nodeJson) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(nodeJson);
return ProcessService.createBpmn(jsonNode);
}
}
package org.modules.junmpProcess.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.modules.junmpProcess.common.Result;
import org.modules.junmpProcess.dto.ApplyDTO;
import org.modules.junmpProcess.dto.HandleDataDTO;
import org.modules.junmpProcess.dto.StartProcessInstanceDTO;
import org.modules.junmpProcess.dto.TaskDTO;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.service.Bussiness.WorkProcessService;
import org.modules.junmpProcess.vo.HandleDataVO;
import org.modules.junmpProcess.vo.HistoryProcessInstanceVO;
import org.modules.junmpProcess.vo.MultiVO;
import org.modules.junmpProcess.vo.TaskVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/MainProcess")
@Api(tags = "和Flowable有关的接口")
public class MainProcessController {
@Autowired
private WorkProcessService ProcessService;
@ApiOperation(value = "通过模板id查看流程信息 会附带流程定义id", notes = "获取所有Demo数据列表")
@GetMapping(value = "process/detail")
public Result<ProcessTemplates> detail(@RequestParam("templateId") String templateId) {
return ProcessService.detail(templateId);
}
@ApiOperation("新建流程")
@PostMapping("process/create")
public Result<Object> create(@RequestBody StartProcessInstanceDTO startProcessInstanceDTO) {
return ProcessService.start(startProcessInstanceDTO);
}
@ApiOperation("通过流程定义id启动流程")
@PostMapping("process/start")
public Result<Object> start(@RequestBody StartProcessInstanceDTO startProcessInstanceDTO) {
return ProcessService.start(startProcessInstanceDTO);
}
@ApiOperation("查看我发起的流程")
@PostMapping("process/applyList")
public Result<Page<HistoryProcessInstanceVO>> applyList(@RequestBody ApplyDTO applyDTO) {
return ProcessService.applyList(applyDTO);
}
@ApiOperation("查看我的待办")
@PostMapping("process/toDoList")
public Result<Page<TaskVO>> toDoList(@RequestBody TaskDTO taskDTO) {
return ProcessService.toDoList(taskDTO);
}
@ApiOperation("查看我的已办")
@PostMapping("process/doneList")
public Result<Page<TaskVO>> doneList(@RequestBody TaskDTO taskDTO) {
return ProcessService.doneList(taskDTO);
}
@ApiOperation("同意按钮")
@PostMapping("/agree")
public Result agree(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.agree(handleDataDTO);
}
@ApiOperation("委派按钮")
@PostMapping("/delegateTask")
public Result delegateTask(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.delegateTask(handleDataDTO);
}
@ApiOperation("委派人完成的按钮")
@PostMapping("/resolveTask")
public Result resolveTask(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.resolveTask(handleDataDTO);
}
@ApiOperation("拒绝按钮")
@PostMapping("/refuse")
public Result refuse(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.refuse(handleDataDTO);
}
@ApiOperation("撤销按钮")
@PostMapping("/revoke")
public Result revoke(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.revoke(handleDataDTO);
}
@ApiOperation("转办按钮")
@PostMapping("/assignee")
public Result assignee(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.assignee(handleDataDTO);
}
@ApiOperation("退回按钮")
@PostMapping("/rollback")
public Result rollback(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.rollback(handleDataDTO);
}
@ApiOperation("加签按钮")
@PostMapping("/addMulti")
public Result addMulti(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.addMulti(handleDataDTO);
}
@ApiOperation("查到签上的人")
@PostMapping("/queryMultiUsersInfo")
public Result<List<MultiVO>> queryMultiUsersInfo(@RequestBody Map<String, Object> map) {
return ProcessService.queryMultiUsersInfo(map);
}
@ApiOperation("减签按钮")
@PostMapping("/deleteMulti")
public Result deleteMulti(@RequestBody List<String> executionIds) {
return ProcessService.deleteMulti(executionIds);
}
@ApiOperation("评论按钮")
@PostMapping("/comments")
public Result comments(@RequestBody HandleDataDTO handleDataDTO) {
return ProcessService.comments(handleDataDTO);
}
@ApiOperation("通过流程实例id查看详情")
@PostMapping("process/instanceInfo")
public Result<HandleDataVO> instanceInfo(@RequestBody HandleDataDTO HandleDataDTO) {
return ProcessService.instanceInfo(HandleDataDTO);
}
// @ApiOperation("上传文件")
// @PostMapping("upLoadFile")
// public Result<AttachmentVO> upLoadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request){
// return ProcessService.upLoadFile(file,request);
// }
// @ApiOperation("下载文件")
// @PostMapping("downLoadFile")
// public void downLoadFile(@RequestParam("name") String name){
// ProcessService.downLoadFile(name);
// }
}
package org.modules.junmpProcess.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.modules.junmpProcess.service.Bussiness.OrgUserAndDeptService;
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;
/**
* @author : willian fu
* @version : 1.0
*/
@RestController
@RequestMapping("/OrgUserAndDept")
@Api(tags = "和用户组织机构有关的接口")
public class OrgUserAndDeptController {
@Resource
private OrgUserAndDeptService orgService;
/**
* 查询组织架构树
*
* @param deptId 部门id
* @return 组织架构树数据
*/
@ApiOperation("查询组织架构树")
@GetMapping("tree")
// @PermissionData(pageComponent = "jeecg/JeecgDemoList")
public Object getOrgTreeData(@RequestParam(defaultValue = "0") Integer deptId,
@RequestParam(defaultValue = "user") String type
) {
return orgService.getOrgTreeData(deptId, type);
}
/**
* 模糊搜索用户
*
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
@ApiOperation("模糊搜索用户")
@GetMapping("tree/search")
public Object getOrgTreeUser(@RequestParam String userName) {
return orgService.getOrgTreeUser(userName.trim());
}
}
package org.modules.junmpProcess.controller;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.modules.junmpProcess.common.R;
import org.modules.junmpProcess.dto.FlowEngineDTO;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.service.Bussiness.SettingService;
import org.modules.junmpProcess.vo.TemplateGroupVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* @author : willian fu
* @date : 2020/9/17
*/
@Slf4j
@RestController
@RequestMapping("/Setting")
@Api(tags = "和表单有关的接口")
public class SettingController {
@Autowired
private SettingService settingService;
/**
* 1>
*
* @param flowEngineDTO
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@PostMapping("/form")
public Object saveForm(@RequestBody FlowEngineDTO flowEngineDTO) throws InvocationTargetException, IllegalAccessException {
settingService.jsonToBpmn(flowEngineDTO);
return R.ok("保存成功");
}
/**
* 查询所有表单分组
*
* @return
*/
@GetMapping("form/group")
public Object getFormGroups() {
return settingService.getFormGroups(null, null);
}
/**
* 表单分组排序
*
* @param groups 分组数据
* @return 排序结果
*/
@PutMapping("form/group/sort")
public Object formGroupsSort(@RequestBody List<TemplateGroupVo> groups) {
return settingService.formGroupsSort(groups);
}
/**
* 修改分组
*
* @param id 分组ID
* @param name 分组名
* @return 修改结果
*/
@PutMapping("form/group")
public Object updateFormGroupName(@RequestParam Integer id,
@RequestParam String name) {
return settingService.updateFormGroupName(id, name);
}
/**
* 新增表单分组
*
* @param name 分组名
* @return 添加结果
*/
@PostMapping("form/group")
public Object createFormGroup(@RequestParam String name) {
return settingService.createFormGroup(name);
}
/**
* 删除分组
*
* @param id 分组ID
* @return 删除结果
*/
@DeleteMapping("form/group")
public Object deleteFormGroup(@RequestParam Integer id) {
return settingService.deleteFormGroup(id);
}
/**
* 查询表单模板数据
*
* @param templateId 模板id
* @return 模板详情数据
*/
@GetMapping("form/detail/{formId}")
public Object getFormTemplateById(@PathVariable("formId") String templateId) {
return settingService.getFormTemplateById(templateId);
}
/**
* 编辑表单
*
* @param templateId 摸板ID
* @param type 类型 stop using delete
* @return 操作结果
*/
@PutMapping("form")
public Object updateForm(@RequestParam String templateId,
@RequestParam String type,
@RequestParam(required = false) Integer groupId) {
return settingService.updateForm(templateId, type, groupId);
}
/**
* 编辑表单详情
*
* @param template 表单模板信息
* @return 修改结果
*/
@PutMapping("form/detail")
public Object updateFormDetail(@RequestBody ProcessTemplates template) {
return settingService.updateFormDetail(template);
}
}
package org.modules.junmpProcess.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.engine.task.Attachment;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.modules.junmpProcess.common.Result;
import org.modules.junmpProcess.dto.*;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.FormOperates;
import org.modules.junmpProcess.dto.json.SettingsInfo;
import org.modules.junmpProcess.dto.json.UserInfo;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.exception.WorkFlowException;
import org.modules.junmpProcess.service.Repository.ProcessTemplateService;
import org.modules.junmpProcess.service.Repository.UserService;
import org.modules.junmpProcess.vo.*;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;
import static org.modules.junmpProcess.common.CommonConstants.*;
import static org.modules.junmpProcess.common.WorkFlowConstants.PROCESS_PREFIX;
import static org.modules.junmpProcess.utils.BpmnModelUtils.getChildNode;
/**
* @author : willian fu
* @version : 1.0
*/
@RestController
@RequestMapping("/workspace")
@Api(tags = "原版flowable")
public class WorkspaceProcessController {
@Resource
private ProcessTemplateService processTemplateService;
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private HistoryService historyService;
@Resource
private TaskService taskService;
@Resource
private UserService userService;
@ApiOperation("通过模板id查看流程信息 会附带流程定义id")
@GetMapping("process/detail")
public Result<ProcessTemplates> detail(@RequestParam("templateId") String templateId) {
ProcessTemplates processTemplates = processTemplateService.getById(templateId);
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(PROCESS_PREFIX + templateId).latestVersion().singleResult();
if (processDefinition == null) {
throw new WorkFlowException("该流程暂未接入Flowable,请重试");
}
processTemplates.setProcessDefinitionId(processDefinition.getId());
return Result.OK(processTemplates);
}
@ApiOperation("通过流程定义id启动流程")
@PostMapping("process/start")
public Result<Object> start(@RequestBody StartProcessInstanceDTO startProcessInstanceDTO) {
try {
JSONObject formData = startProcessInstanceDTO.getFormData();
UserInfo startUserInfo = startProcessInstanceDTO.getStartUserInfo();
Authentication.setAuthenticatedUserId(startUserInfo.getId());
Map<String, Object> processVariables = new HashMap<>();
processVariables.put(FORM_VAR, formData);
processVariables.put(PROCESS_STATUS, BUSINESS_STATUS_1);
processVariables.put(START_USER_INFO, JSONObject.toJSONString(startUserInfo));
ArrayList<UserInfo> userInfos = CollUtil.newArrayList(startUserInfo);
processVariables.put("root", JSONObject.toJSONString(userInfos));
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
processVariables.putAll(formValue);
ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
ProcessInstance processInstance = processInstanceBuilder
.processDefinitionId(startProcessInstanceDTO.getProcessDefinitionId())
.variables(processVariables)
.businessStatus(BUSINESS_STATUS_1)
.start();
return Result.OK(processInstance.getId());
} catch (Exception e) {
Throwable cause = e.getCause();
if (cause instanceof WorkFlowException) {
WorkFlowException workFlowException = (WorkFlowException) cause;
return Result.error(workFlowException.getMessage());
}
e.printStackTrace();
return Result.error("启动流程失败");
}
}
@ApiOperation("查看我发起的流程")
@PostMapping("process/applyList")
public Result<Page<HistoryProcessInstanceVO>> applyList(@RequestBody ApplyDTO applyDTO) {
List<HistoricProcessInstance> historicProcessInstances =
historyService.createHistoricProcessInstanceQuery()
.includeProcessVariables()
.startedBy(applyDTO.getCurrentUserInfo().getId())
.orderByProcessInstanceStartTime().desc()
.listPage((applyDTO.getPageNo() - 1) * applyDTO.getPageSize(), applyDTO.getPageSize());
long count = historyService.createHistoricProcessInstanceQuery()
.startedBy(applyDTO.getCurrentUserInfo().getId()).count();
List<HistoryProcessInstanceVO> historyProcessInstanceVOS = new ArrayList<>();
Page<HistoryProcessInstanceVO> page = new Page<>();
for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
HistoryProcessInstanceVO historyProcessInstanceVO = new HistoryProcessInstanceVO();
historyProcessInstanceVO.setProcessInstanceId(historicProcessInstance.getId());
historyProcessInstanceVO.setProcessDefinitionName(historicProcessInstance.getProcessDefinitionName());
historyProcessInstanceVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
historyProcessInstanceVO.setStartTime(historicProcessInstance.getStartTime());
historyProcessInstanceVO.setEndTime(historicProcessInstance.getEndTime());
Boolean flag = historicProcessInstance.getEndTime() == null ? false : true;
historyProcessInstanceVO.setCurrentActivityName(getCurrentName(historicProcessInstance.getId(), flag, historicProcessInstance.getProcessDefinitionId()));
historyProcessInstanceVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
long totalTimes = historicProcessInstance.getEndTime() == null ?
(Calendar.getInstance().getTimeInMillis() - historicProcessInstance.getStartTime().getTime()) :
(historicProcessInstance.getEndTime().getTime() - historicProcessInstance.getStartTime().getTime());
long dayCount = totalTimes / (1000 * 60 * 60 * 24);//计算天
long restTimes = totalTimes % (1000 * 60 * 60 * 24);//剩下的时间用于计于小时
long hourCount = restTimes / (1000 * 60 * 60);//小时
restTimes = restTimes % (1000 * 60 * 60);
long minuteCount = restTimes / (1000 * 60);
String spendTimes = dayCount + "天" + hourCount + "小时" + minuteCount + "分";
historyProcessInstanceVO.setDuration(spendTimes);
historyProcessInstanceVOS.add(historyProcessInstanceVO);
}
page.setRecords(historyProcessInstanceVOS);
page.setCurrent(applyDTO.getPageNo());
page.setSize(applyDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
private String getCurrentName(String processInstanceId, Boolean flag, String processDefinitionId) {
if (flag) {
return "流程已结束";
}
Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();
String activityId = execution.getActivityId();
if (StringUtils.isBlank(activityId)) {
return "";
} else {
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(activityId);
return flowElement.getName();
}
}
@ApiOperation("查看我的待办")
@PostMapping("process/toDoList")
public Result<Page<TaskVO>> toDoList(@RequestBody TaskDTO taskDTO) {
List<Task> tasks = taskService.createTaskQuery().taskAssignee(taskDTO.getCurrentUserInfo().getId())
.includeProcessVariables()
.orderByTaskCreateTime().desc()
.listPage((taskDTO.getPageNo() - 1) * taskDTO.getPageSize(), taskDTO.getPageSize());
long count = taskService.createTaskQuery().taskAssignee(taskDTO.getCurrentUserInfo().getId()).count();
List<TaskVO> taskVOS = new ArrayList<>();
Page<TaskVO> page = new Page<>();
for (Task task : tasks) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Map<String, Object> processVariables = task.getProcessVariables();
TaskVO taskVO = new TaskVO();
taskVO.setTaskId(task.getId());
taskVO.setProcessInstanceId(task.getProcessInstanceId());
taskVO.setProcessDefinitionName(bpmnModel.getMainProcess().getName());
taskVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
taskVO.setStartTime(historicProcessInstance.getStartTime());
Execution execution = runtimeService.createExecutionQuery().executionId(task.getProcessInstanceId()).singleResult();
String activityId = execution.getActivityId();
if (StringUtils.isBlank(activityId)) {
taskVO.setCurrentActivityName("");
} else {
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(activityId);
taskVO.setCurrentActivityName(flowElement.getName());
}
taskVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
taskVO.setTaskCreatedTime(task.getCreateTime());
DelegationState delegationState = task.getDelegationState();
if (delegationState != null) {
taskVO.setDelegationState(delegationState);
}
taskVOS.add(taskVO);
}
page.setRecords(taskVOS);
page.setCurrent(taskDTO.getPageNo());
page.setSize(taskDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
@ApiOperation("查看我的已办")
@PostMapping("process/doneList")
public Result<Page<TaskVO>> doneList(@RequestBody TaskDTO taskDTO) {
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(taskDTO.getCurrentUserInfo().getId())
.finished()
.includeProcessVariables()
.orderByTaskCreateTime().desc()
.listPage((taskDTO.getPageNo() - 1) * taskDTO.getPageSize(), taskDTO.getPageSize());
long count = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(taskDTO.getCurrentUserInfo().getId()).count();
List<TaskVO> taskVOS = new ArrayList<>();
Page<TaskVO> page = new Page<>();
for (HistoricTaskInstance task : tasks) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
Boolean flag = historicProcessInstance.getEndTime() == null ? false : true;
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Map<String, Object> processVariables = task.getProcessVariables();
TaskVO taskVO = new TaskVO();
taskVO.setTaskId(task.getId());
taskVO.setProcessInstanceId(task.getProcessInstanceId());
taskVO.setProcessDefinitionName(bpmnModel.getMainProcess().getName());
taskVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
taskVO.setStartTime(historicProcessInstance.getStartTime());
taskVO.setCurrentActivityName(getCurrentName(task.getProcessInstanceId(), flag, task.getProcessDefinitionId()));
taskVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
taskVO.setEndTime(task.getEndTime());
long totalTimes = task.getEndTime() == null ?
(Calendar.getInstance().getTimeInMillis() - task.getStartTime().getTime()) :
(task.getEndTime().getTime() - task.getStartTime().getTime());
long dayCount = totalTimes / (1000 * 60 * 60 * 24);//计算天
long restTimes = totalTimes % (1000 * 60 * 60 * 24);//剩下的时间用于计于小时
long hourCount = restTimes / (1000 * 60 * 60);//小时
restTimes = restTimes % (1000 * 60 * 60);
long minuteCount = restTimes / (1000 * 60);
String spendTimes = dayCount + "天" + hourCount + "小时" + minuteCount + "分";
taskVO.setDuration(spendTimes);
taskVOS.add(taskVO);
}
page.setRecords(taskVOS);
page.setCurrent(taskDTO.getPageNo());
page.setSize(taskDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
@ApiOperation("同意按钮")
@PostMapping("/agree")
public Result agree(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);//设置进入当前流程
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.complete(task.getId());
return Result.OK();
}
@ApiOperation("委派按钮")
@PostMapping("/delegateTask")
public Result delegateTask(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
UserInfo delegateUserInfo = handleDataDTO.getDelegateUserInfo();
taskService.delegateTask(task.getId(), delegateUserInfo.getId());
return Result.OK();
}
@ApiOperation("委派人完成的按钮")
@PostMapping("/resolveTask")
public Result resolveTask(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.resolveTask(taskId);
return Result.OK();
}
@ApiOperation("拒绝按钮")
@PostMapping("/refuse")
public Result refuse(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_3);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "拒绝");
return Result.OK();
}
@ApiOperation("撤销按钮")
@PostMapping("/revoke")
public Result revoke(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_2);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "撤销");
return Result.OK();
}
@ApiOperation("转办按钮")
@PostMapping("/assignee")
public Result assignee(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.setAssignee(taskId, handleDataDTO.getTransferUserInfo().getId());
return Result.OK();
}
@ApiOperation("退回按钮")
@PostMapping("/rollback")
public Result rollback(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
String processInstanceId = handleDataDTO.getProcessInstanceId();
List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
Task task = null;
List<String> taskIds = new ArrayList<>();
for (Task task1 : list) {
if (task1.getId().equals(taskId)) {
task = task1;
}
taskIds.add(task1.getTaskDefinitionKey());
}
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_3);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(taskIds, handleDataDTO.getRollbackId())
.changeState();
return Result.OK();
}
@ApiOperation("加签按钮")
@PostMapping("/addMulti")
public Result addMulti(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
Map<String, Object> variableMap = new HashMap<>();
variableMap.put("assigneeName", handleDataDTO.getMultiAddUserInfo().getId());
ExecutionEntity execution = (ExecutionEntity) runtimeService.addMultiInstanceExecution(task.getTaskDefinitionKey(), task.getProcessInstanceId(), variableMap);
return Result.OK();
}
@ApiOperation("查到签上的人")
@PostMapping("/queryMultiUsersInfo")
public Result<List<MultiVO>> queryMultiUsersInfo(@RequestBody Map<String, Object> map) {
String taskId = MapUtil.getStr(map, "taskId");
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
List<Task> list = taskService.createTaskQuery()
.processInstanceId(task.getProcessInstanceId())
.taskDefinitionKey(task.getTaskDefinitionKey()).list();
Iterator<Task> iterator = list.iterator();
List<MultiVO> multiVOList = new ArrayList<>();
while (iterator.hasNext()) {
Task next = iterator.next();
if (!taskId.equals(next.getId())) {
MultiVO multiVO = new MultiVO();
multiVO.setTaskId(next.getId());
multiVO.setProcessInstanceId(next.getProcessInstanceId());
multiVO.setExecutionId(next.getExecutionId());
multiVO.setUserId(next.getAssignee());
multiVOList.add(multiVO);
}
}
return Result.OK(multiVOList);
}
@ApiOperation("减签按钮")
@PostMapping("/deleteMulti")
public Result deleteMulti(@RequestBody List<String> executionIds) {
for (String executionId : executionIds) {
runtimeService.deleteMultiInstanceExecution(executionId, true);
}
return Result.OK();
}
/**
* 添加流程模型并返回modelId
*
* @param processId 流程唯一标识key
* @param processAuthor 流程作者
* @param name 流程名称
* @param modelname 模型名称
* @param description 模型描述
* @param category 模型分类
* @return
* @throws UnsupportedEncodingException
*/
protected String createModel(String processId, String processAuthor, String name, String modelname, String description, String category) throws UnsupportedEncodingException {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvs");
editorNode.put("resourceId", "canvs");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
//命名空间(禁止修改)
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
//流程节点作者
stencilSetNode.put("author", "");
editorNode.set("stencilset", stencilSetNode);
ObjectNode propertiesNode = objectMapper.createObjectNode();
//流程唯一标识
propertiesNode.put("process_id", processId);
//流程作者
propertiesNode.put("process_author", processAuthor);
//流程名称
propertiesNode.put("name", name);
editorNode.set("properties", propertiesNode);
ObjectNode modelObjectNode = objectMapper.createObjectNode();
//模型名称
modelObjectNode.put("name", modelname);
//模型版本
modelObjectNode.put("revision", 1);
//模型描述
modelObjectNode.put("description", description);
Model modelData = repositoryService.newModel();
//模型分类
modelData.setCategory(category);
modelData.setDeploymentId(null);
modelData.setKey(null);
modelData.setMetaInfo(modelObjectNode.toString());
//模型名称
modelData.setName(modelname);
modelData.setTenantId("");
modelData.setVersion(1);
//保存模型,存储数据到表:act_re_model 流程设计模型部署表
repositoryService.saveModel(modelData);
//保存资源,存储数据到表:act_ge_bytearray 二进制数据表
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
return modelData.getId();
}
@ApiOperation("评论按钮")
@PostMapping("/comments")
public Result comments(@RequestBody HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "comments", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
return Result.OK();
}
@ApiOperation("通过流程实例id查看详情")
@PostMapping("process/instanceInfo")
public Result<HandleDataVO> instanceInfo(@RequestBody HandleDataDTO HandleDataDTO) {
String processInstanceId = HandleDataDTO.getProcessInstanceId();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId)
.includeProcessVariables().singleResult();
String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
ProcessTemplates processTemplates = processTemplateService.getById(processDefinitionKey.replace(PROCESS_PREFIX, ""));
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
processTemplates.setProcessDefinitionId(historicProcessInstance.getProcessDefinitionId());
HandleDataVO handleDataVO = new HandleDataVO();
Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
handleDataVO.setProcessInstanceId(historicProcessInstance.getId());
JSONObject jsonObject = (JSONObject) processVariables.get(FORM_VAR);
handleDataVO.setFormData(jsonObject);
String process = processTemplates.getProcess();
ChildNode childNode = JSONObject.parseObject(process, new TypeReference<ChildNode>() {
});
SettingsInfo settingsInfo = JSONObject.parseObject(processTemplates.getSettings(), new TypeReference<SettingsInfo>() {
});
Boolean sign = settingsInfo.getSign();
ChildNode currentNode = null;
if (StringUtils.isNotBlank(HandleDataDTO.getTaskId())) {
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(HandleDataDTO.getTaskId()).singleResult();
currentNode = getChildNode(childNode, historicTaskInstance.getTaskDefinitionKey());
List<FormOperates> formPerms = currentNode.getProps().getFormPerms();
if (CollUtil.isNotEmpty(formPerms)) {
Iterator<FormOperates> iterator = formPerms.iterator();
while (iterator.hasNext()) {
FormOperates next = iterator.next();
if ("H".equals(next.getPerm())) {
iterator.remove();
if (jsonObject != null) {
jsonObject.remove(next.getId());
}
}
}
}
handleDataVO.setCurrentNode(currentNode);
handleDataVO.setTaskId(HandleDataDTO.getTaskId());
}
if (sign) {
handleDataVO.setSignFlag(true);
}
if (StringUtils.isNotBlank(HandleDataDTO.getTaskId())) {
if (currentNode != null) {
if (currentNode.getProps().getSign()) {
handleDataVO.setSignFlag(true);
} else {
handleDataVO.setSignFlag(false);
}
}
}
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(historicProcessInstance.getId()).list();
Map<String, List<HistoricActivityInstance>> historicActivityInstanceMap = new HashMap<>();
for (HistoricActivityInstance historicActivityInstance : list) {
List<HistoricActivityInstance> historicActivityInstances = historicActivityInstanceMap.get(historicActivityInstance.getActivityId());
if (historicActivityInstances == null) {
historicActivityInstances = new ArrayList<>();
historicActivityInstances.add(historicActivityInstance);
historicActivityInstanceMap.put(historicActivityInstance.getActivityId(), historicActivityInstances);
} else {
historicActivityInstances.add(historicActivityInstance);
historicActivityInstanceMap.put(historicActivityInstance.getActivityId(), historicActivityInstances);
}
}
Process mainProcess = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()).getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
List<String> runningList = new ArrayList<>();
handleDataVO.setRunningList(runningList);
List<String> endList = new ArrayList<>();
handleDataVO.setEndList(endList);
List<String> noTakeList = new ArrayList<>();
handleDataVO.setNoTakeList(noTakeList);
Map<String, List<TaskDetailVO>> deatailMap = new HashMap<>();
List<Comment> processInstanceComments = taskService.getProcessInstanceComments(historicProcessInstance.getId());
List<Attachment> processInstanceAttachments = taskService.getProcessInstanceAttachments(historicProcessInstance.getId());
for (FlowElement flowElement : flowElements) {
List<TaskDetailVO> detailVOList = new ArrayList<>();
List<HistoricActivityInstance> historicActivityInstanceList = historicActivityInstanceMap.get(flowElement.getId());
if (CollUtil.isNotEmpty(historicActivityInstanceList)) {
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
if (historicActivityInstance.getEndTime() != null) {
if ("startEvent".equalsIgnoreCase(historicActivityInstance.getActivityType()) || "endEvent".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
TaskDetailVO taskDetailVO = new TaskDetailVO();
taskDetailVO.setActivityId(historicActivityInstance.getActivityId());
taskDetailVO.setName(historicActivityInstance.getActivityName());
taskDetailVO.setCreateTime(historicActivityInstance.getStartTime());
taskDetailVO.setEndTime(historicActivityInstance.getEndTime());
detailVOList.add(taskDetailVO);
deatailMap.put(historicActivityInstance.getActivityId(), detailVOList);
endList.add(historicActivityInstance.getActivityId());
} else if ("userTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
List<TaskDetailVO> voList = deatailMap.get(historicActivityInstance.getActivityId());
List<HistoricActivityInstance> activityInstanceList = list.stream().filter(h -> h.getActivityId().equals(historicActivityInstance.getActivityId()) && h.getEndTime() != null).collect(Collectors.toList());
if (voList != null) {
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
} else {
voList = new ArrayList<>();
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
}
deatailMap.put(historicActivityInstance.getActivityId(), voList);
endList.add(historicActivityInstance.getActivityId());
} else if ("serviceTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
}
} else {
if ("userTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
List<TaskDetailVO> voList = deatailMap.get(historicActivityInstance.getActivityId());
List<HistoricActivityInstance> activityInstanceList = list.stream().filter(h -> h.getActivityId().equals(historicActivityInstance.getActivityId()) && h.getEndTime() == null).collect(Collectors.toList());
if (voList != null) {
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
} else {
voList = new ArrayList<>();
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
}
deatailMap.put(historicActivityInstance.getActivityId(), voList);
if (endList.contains(historicActivityInstance.getActivityId())) {
endList.remove(historicActivityInstance.getActivityId());
runningList.add(historicActivityInstance.getActivityId());
} else {
runningList.add(historicActivityInstance.getActivityId());
}
} else if ("serviceTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
}
}
}
} else {
noTakeList.add(flowElement.getId());
}
}
handleDataVO.setProcessTemplates(processTemplates);
handleDataVO.setDetailVOList(deatailMap);
return Result.OK(handleDataVO);
}
private void collectUserTaskInfo(List<Comment> processInstanceComments,
List<Attachment> processInstanceAttachments,
HistoricActivityInstance historicActivityInstance,
List<TaskDetailVO> voList,
List<HistoricActivityInstance> activityInstanceList) {
for (HistoricActivityInstance activityInstance : activityInstanceList) {
TaskDetailVO taskDetailVO = new TaskDetailVO();
taskDetailVO.setTaskId(activityInstance.getTaskId());
taskDetailVO.setActivityId(activityInstance.getActivityId());
taskDetailVO.setName(activityInstance.getActivityName());
taskDetailVO.setCreateTime(activityInstance.getStartTime());
taskDetailVO.setEndTime(activityInstance.getEndTime());
Comment signComment = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("sign")).findFirst().orElse(null);
if (signComment != null) {
taskDetailVO.setSignImage(signComment.getFullMessage());
}
List<Attachment> attachments = processInstanceAttachments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(attachments)) {
List<AttachmentVO> attachmentVOList = new ArrayList<>();
for (Attachment attachment : attachments) {
AttachmentVO attachmentVO = new AttachmentVO();
attachmentVO.setId(attachment.getId());
attachmentVO.setName(attachment.getName());
attachmentVO.setUrl(attachment.getUrl());
attachmentVOList.add(attachmentVO);
}
taskDetailVO.setAttachmentVOList(attachmentVOList);
}
List<Comment> options = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("opinion")).collect(Collectors.toList());
if (CollUtil.isNotEmpty(options)) {
List<OptionVO> optionVOList = new ArrayList<>();
for (Comment option : options) {
OptionVO optionVO = new OptionVO();
optionVO.setComments(option.getFullMessage());
optionVO.setUserId(option.getUserId());
// optionVO.setUserName();
optionVO.setCreateTime(option.getTime());
optionVOList.add(optionVO);
}
taskDetailVO.setOptionVOList(optionVOList);
}
List<Comment> comments = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("comments")).collect(Collectors.toList());
if (CollUtil.isNotEmpty(comments)) {
List<CommentVO> commentsVOList = new ArrayList<>();
for (Comment comment : comments) {
CommentVO commentVO = new CommentVO();
commentVO.setComments(comment.getFullMessage());
commentVO.setUserId(comment.getUserId());
// commentVO.setUserName();
commentVO.setCreateTime(comment.getTime());
commentsVOList.add(commentVO);
}
taskDetailVO.setCommentVOList(commentsVOList);
}
voList.add(taskDetailVO);
}
}
// @ApiOperation("上传文件")
// @PostMapping("upLoadFile")
// public Result<AttachmentVO> upLoadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request){
// MinioUploadUtil minioUploadUtil = SpringContextHolder.getBean(MinioUploadUtil.class);
// MinioClient minioClient = SpringContextHolder.getBean(MinioClient.class);
// AttachmentVO attachmentVO= new AttachmentVO();
// attachmentVO.setName(file.getOriginalFilename());
// minioUploadUtil.uploadFile(file, "java", file.getOriginalFilename());
// try {
// String url = minioClient.getPresignedObjectUrl(
// GetPresignedObjectUrlArgs.builder()
// .bucket("java")
// .object(file.getOriginalFilename())
// .expiry(7, TimeUnit.DAYS) // 设置5秒的超时时间。
// .method(Method.GET)
// .build());
// attachmentVO.setUrl(url);
// } catch (ErrorResponseException e) {
// e.printStackTrace();
// } catch (InsufficientDataException e) {
// e.printStackTrace();
// } catch (InternalException e) {
// e.printStackTrace();
// } catch (InvalidKeyException e) {
// e.printStackTrace();
// } catch (InvalidResponseException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (XmlParserException e) {
// e.printStackTrace();
// } catch (ServerException e) {
// e.printStackTrace();
// }
// return Result.OK(attachmentVO);
// }
// @ApiOperation("下载文件")
// @PostMapping("downLoadFile")
// public void downLoadFile(@RequestParam("name") String name){
// MinioUploadUtil minioUploadUtil = SpringContextHolder.getBean(MinioUploadUtil.class);
// minioUploadUtil.downFile(name,"java",name);
// }
}
package org.modules.junmpProcess.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.modules.junmpProcess.dto.json.UserInfo;
/**
* @author LoveMyOrange
* @create 2022-10-14 23:47
*/
@Data
@ApiModel("我发起流程 需要返回给前端的DTO")
public class ApplyDTO extends PageDTO {
private UserInfo currentUserInfo;
}
package org.modules.junmpProcess.dto;
import lombok.Data;
/**
* @author LoveMyOrange
* @create 2022-10-15 17:04
*/
@Data
public class AttachmentDTO {
private String id;
private String name;
private String url;
}
package org.modules.junmpProcess.dto;
import lombok.Data;
/**
* 流程DTO
*/
@Data
public class FlowDTO {
//表单分类id
private String process;
private Integer groupId;
}
package org.modules.junmpProcess.dto;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 15:51
*/
@Data
public class FlowEngineDTO {
private String formId;
private String formItems;
private String formName;
//表单分类id
private Integer groupId;
private String logo;
private String process;
private String remark;
private String settings;
}
package org.modules.junmpProcess.dto;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.modules.junmpProcess.dto.json.UserInfo;
import java.util.List;
/**
* @author LoveMyOrange
* @create 2022-10-15 16:27
*/
@Data
@ApiModel("各个按钮 处理数据需要传递的参数")
public class HandleDataDTO {
@ApiModelProperty("任务id")
private String taskId;
@ApiModelProperty("流程实例id")
private String processInstanceId;
@ApiModelProperty("表单数据")
private JSONObject formData;
@ApiModelProperty("附件")
private List attachments;
@ApiModelProperty("意见")
private String comments;
@ApiModelProperty("签名信息")
private String signInfo;
@ApiModelProperty("转办用户信息")
private UserInfo transferUserInfo;
@ApiModelProperty("加签用户信息")
private UserInfo multiAddUserInfo;
@ApiModelProperty("退回节点id")
private String rollbackId;
@ApiModelProperty("当前用户信息")
private UserInfo currentUserInfo;
@ApiModelProperty("委派的人")
private UserInfo delegateUserInfo;
}
package org.modules.junmpProcess.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author LoveMyOrange
* @create 2022-10-15 10:33
*/
@Data
@ApiModel("分页DTO")
public class PageDTO {
@ApiModelProperty(value = "第几页", required = true)
private Integer pageNo;
@ApiModelProperty(value = "多少条", required = true)
private Integer pageSize;
}
package org.modules.junmpProcess.dto;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.modules.junmpProcess.dto.json.UserInfo;
import java.util.List;
import java.util.Map;
/**
* @author LoveMyOrange
* @create 2022-10-14 23:27
*/
@Data
public class StartProcessInstanceDTO {
private String processDefinitionId;
private JSONObject formData;
private Map<String, List<UserInfo>> processUsers;
private UserInfo startUserInfo;
}
package org.modules.junmpProcess.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.modules.junmpProcess.dto.json.UserInfo;
/**
* @author LoveMyOrange
* @create 2022-10-14 23:47
*/
@Data
@ApiModel("待办 需要返回给前端的VO")
public class TaskDTO extends PageDTO {
private UserInfo currentUserInfo;
}
package org.modules.junmpProcess.dto.json;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.util.List;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:20
* <p>
* process: "
* {\"id\":\"root\",\
* "parentId\":null,\
* "type\":\"ROOT\",\
* "name\":\"发起人\",\
* "desc\":\"任何人\",\
* "props\":{\
* "assignedUser\":
* <p>
* <p>
* [{\"id\":1486186,\"name\":\"xx科技有限公司\",\"type\":\"dept\",\"sex\":null,\"selected\":false}],\
* "formPerms\":[{\"id\":\"field6131501574832\",\"title\":\"单行文本输入\",\"required\":true,\"perm\":\"E\"}]},\
* "children\":{\"id\":\"node_040730749764\",\"parentId\":\"root\",\"props\":{\"assignedType\":\"ASSIGN_USER\",\"mode\":\"AND\",\"sign\":true,\"nobody\":{\"handler\":\"TO_PASS\",\"assignedUser\":[]},\"timeLimit\":{\"timeout\":{\"unit\":\"H\",\"value\":\"1\"},\"handler\":{\"type\":\"REFUSE\",\"notify\":{\"once\":true,\"hour\":1}}},\"assignedUser\":[{\"id\":381496,\"name\":\"旅人\",\"type\":\"user\",\"sex\":false,\"selected\":false}],\"formPerms\":[{\"id\":\"field6131501574832\",\"title\":\"单行文本输入\",\"required\":true,\"perm\":\"R\"}],\"selfSelect\":{\"multiple\":false},\"leaderTop\":{\"endCondition\":\"TOP\",\"endLevel\":1},\"leader\":{\"level\":1},\"role\":[],\"refuse\":{\"type\":\"TO_END\",\"target\":\"\"},\"formUser\":\"\"},\"type\":\"APPROVAL\",\"name\":\"审批人\",\"children\":{}}}"
*/
@Data
public class ChildNode {
private String id;
private String parentId;
private String type;
private String name;
private String desc;
private Properties props;
private ChildNode children;
private List<ChildNode> branchs;
private String parallelStr;
private JSONObject incoming = new JSONObject();
private Boolean typeElse;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
import java.util.List;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 18:57
*/
@Data
public class ConditionInfo {
private String id;
private String title;
private String valueType;
private String compare;
private List<Object> value;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
import java.util.List;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 20:08
*/
@Data
public class EmailInfo {
private String subject;
private List<String> to;
private String content;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 15:55
*/
@Data
public class FormItem {
private String title;
private String name;
private String icon;
private String value;
private String valueType;
private String id;
private FormItemProps props;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 15:57
*/
@Data
public class FormItemProps {
private Boolean required;
private Boolean enablePrint;
private String placeHolder;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:26
*/
@Data
public class FormOperates {
private String id;
private String title;
private Boolean required;
private String perm;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
import java.util.List;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 18:57
*/
@Data
public class GroupsInfo {
private String groupType;
private List<ConditionInfo> conditions;
private List<String> cids;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 20:04
*/
@Data
public class HttpInfo {
private String method;
private String url;
private List<Map<String, Object>> headers;
private String contentType;
private List<Map<String, Object>> params;
private Integer retry;
private Boolean handlerByScript;
private String success;
private String fail;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:05
*/
@Data
public class LogoInfo {
private String icon;
private String background;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:15
*/
@Data
public class NotifyType {
private String type;
private String name;
}
package org.modules.junmpProcess.dto.json;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:15
*/
@Data
public class NotifyTypeInfo {
private String title;
private JSONObject types;
}
package org.modules.junmpProcess.dto.json;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:30
* <p>
* \"assignedType\":\"ASSIGN_USER\",\"mode\":\"AND\",\"sign\":true,\
* "nobody\":{\"handler\":\"TO_PASS\",\"assignedUser\":[]},\
* "timeLimit\":{\"timeout\":{\"unit\":\"H\",\"value\":\"1\"},\
* "handler\":{\"type\":\"REFUSE\",\"notify\":{\"once\":true,\"hour\":1}}},\
* "assignedUser\":[{\"id\":381496,\"name\":\"旅人\",\"type\":\"user\",\"sex\":false,\"selected\":false}],\
* "formPerms\":[{\"id\":\"field6131501574832\",\"title\":\"单行文本输入\",\"required\":true,\"perm\":\"R\"}],\
* "selfSelect\":{\"multiple\":false},\
* "leaderTop\":{\"endCondition\":\"TOP\",\"endLevel\":1},\
* "leader\":{\"level\":1},\"role\":[],\
* "refuse\":{\"type\":\"TO_END\",\"target\":\"\"},\"formUser\":\"\"},\"type\":\"APPROVAL\",\"name\":\"审批人\",\"children\":{}}}"
*/
@Data
public class Properties {
private String assignedType;
private List<UserInfo> assignedUser;
//发起人自旋 multiple true false
private Map<String, Object> selfSelect;
//连续主管 endCondition TOP LEAVE endLevel level
private Map<String, Object> leaderTop = new HashMap<>();
//指定主管审批
private Map<String, Object> leader = new HashMap<>();
//系统角色
private List<Map<String, Object>> role;
//表单人员
private String formUser;
//审批人为空的规则 hander 和 assignedUser
private Map<String, Object> nobody;
private String mode;
private Boolean sign;
//审批超时
private JSONObject timeLimit;
private Map<String, Object> refuse;
private List<FormOperates> formPerms;
//------------------------------------->
private String groupsType;
private String expression;
private List<GroupsInfo> groups;
//
private Boolean shouldAdd;
//
private String type;
private Long time;
private String unit;
private String dateTime;
//
private HttpInfo http;
private EmailInfo email;
}
package org.modules.junmpProcess.dto.json;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.util.List;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:06
*/
@Data
public class SettingsInfo {
private List<String> commiter;
private List<UserInfo> admin;
private Boolean sign;
private JSONObject notify;
}
package org.modules.junmpProcess.dto.json;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 16:10
*/
@Data
public class UserInfo {
private String id;
private String name;
private String type;
private String sex;
private Boolean selected;
}
package org.modules.junmpProcess.dto.json.flowJson;
import lombok.Data;
import java.util.List;
@Data
public class FlowApproverGroups {
private String id;
private int approverType;
private int levelMode;
private List<String> approverIds;
private List<String> approverNames;
}
\ No newline at end of file
package org.modules.junmpProcess.dto.json.flowJson;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class FlowChildNode {
private String id;
private String name;
private int type;
private int status;
private boolean error;
private FlowChildNode childNode;
private boolean addable;
private List<FlowChildNode> conditionNodes;
private String pid;
private Map<String, Object> attr;
private List<FlowApproverGroups> approverGroups;
//不确定什么类型
private List<String> privileges;
private Map<String, Object> configure;
private List<FlowConditionNodes> FlowConditionNodes;
private boolean deletable;
private String content;
}
package org.modules.junmpProcess.dto.json.flowJson;
import lombok.Data;
@Data
public class FlowConditionGroup {
private String id;
private String condition;
private String name;
private int type;
private int status;
private boolean error;
private FlowChildNode childNode;
private FlowChildNode addable;
private FlowChildNode deletable;
private int conditionGroup;
private int attr;
private boolean content;
}
package org.modules.junmpProcess.dto.json.flowJson;
import lombok.Data;
import java.util.List;
@Data
public class FlowConditionNodes {
private String id;
private String pid;
private String name;
private int type;
private int status;
private boolean error;
private FlowChildNode childNode;
private FlowChildNode addable;
private FlowChildNode deletable;
private List<FlowConditionGroup> conditionGroup;
private int attr;
private boolean content;
}
package org.modules.junmpProcess.dto.json.flowJson;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.Properties;
import java.util.List;
@Data
public class FlowNode {
private String id;
private String name;
private int type;
private int status;
private boolean error;
private ChildNode childNode;
private boolean addable;
private String desc;
private Properties props;
private List<ChildNode> branchs;
private String parallelStr;
private JSONObject incoming = new JSONObject();
private Boolean typeElse;
}
\ No newline at end of file
package org.modules.junmpProcess.dto.json.flowJson;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Inout {
private String in;
private String out;
}
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (Departments)实体类
*
* @author makejava
* @since 2020-09-17 14:21:25
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("departments")
public class Departments implements Serializable {
private static final long serialVersionUID = -53409297247748263L;
/**
* 部门id
*/
@TableId(value = "dept_id", type = IdType.ASSIGN_ID)
private Long deptId;
/**
* 部门名
*/
private String deptName;
/**
* 部门主管
*/
private String leader;
/**
* 父部门id
*/
private Integer parentId;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
}
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (FormGroups)实体类
*
* @author makejava
* @since 2020-09-21 22:49:33
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "form_groups")
public class FormGroups implements Serializable {
private static final long serialVersionUID = -50696449296875480L;
@TableId(value = "group_id", type = IdType.AUTO)
/**
* id
*/
private Integer groupId;
/**
* 组名
*/
private String groupName;
/**
* 排序号
*/
private Integer sortNum;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
}
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (ProcessTemplates)实体类
*
* @author makejava
* @since 2020-09-21 22:50:29
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "process_templates")
@Builder
public class Process implements Serializable {
private static final long serialVersionUID = -95829441258242072L;
@TableId
/**
* 审批摸板ID
*/
private String templateId;
@TableField(exist = false)
private String formId;
@TableField(exist = false)
private String formName;
/**
* 摸板名称
*/
private String templateName;
private Integer groupId;
/**
* 摸板表单
*/
private String formItems;
private String settings;
private String process;
/**
* 图标
*/
private String icon;
/**
* 图标背景色
*/
private String background;
private String notify;
/**
* 谁能提交
*/
private String whoCommit;
/**
* 谁能编辑
*/
private String whoEdit;
/**
* 谁能导出数据
*/
private String whoExport;
private String remark;
/**
* 是否已停用
*/
private Boolean isStop;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
@TableField(exist = false)
private String logo;
@TableField(exist = false)
private String processDefinitionId;
}
\ No newline at end of file
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (ProcessTemplates)实体类
*
* @author makejava
* @since 2020-09-21 22:50:29
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "process_templates")
@Builder
public class ProcessTemplates implements Serializable {
private static final long serialVersionUID = -95829441258242072L;
@TableId
/**
* 审批摸板ID
*/
private String templateId;
@TableField(exist = false)
private String formId;
@TableField(exist = false)
private String formName;
/**
* 摸板名称
*/
private String templateName;
private Integer groupId;
/**
* 摸板表单
*/
private String formItems;
private String settings;
private String process;
/**
* 图标
*/
private String icon;
/**
* 图标背景色
*/
private String background;
private String notify;
/**
* 谁能提交
*/
private String whoCommit;
/**
* 谁能编辑
*/
private String whoEdit;
/**
* 谁能导出数据
*/
private String whoExport;
private String remark;
/**
* 是否已停用
*/
private Boolean isStop;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
@TableField(exist = false)
private String logo;
@TableField(exist = false)
private String processDefinitionId;
}
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (TemplateGroup)实体类
*
* @author makejava
* @since 2020-09-21 22:50:41
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "template_group")
public class TemplateGroup implements Serializable {
private static final long serialVersionUID = 296474043591142508L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String templateId;
private Integer groupId;
private Integer sortNum;
private Date created;
}
package org.modules.junmpProcess.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TemplateGroupBo {
private Integer id;
private Integer groupId;
private String groupName;
private String templateId;
private String templateName;
private String icon;
private Boolean isStop;
private String remark;
private Date updated;
private String background;
}
package org.modules.junmpProcess.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* (Users)实体类
*
* @author makejava
* @since 2020-09-17 14:18:47
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "users")
public class Users implements Serializable {
private static final long serialVersionUID = 147397842421109939L;
/**
* 用户id
*/
@TableId
private Long userId;
/**
* 用户名
*/
private String userName;
//拼音
private String pingyin;
/**
* 昵称
*/
private String alisa;
/**
* 头像
*/
private String avatar;
/**
* 性别
*/
private Boolean sex;
/**
* 部门id,分隔
*/
private String departmentIds;
/**
* 入职日期
*/
private Date entryDate;
/**
* 离职日期
*/
private Date leaveDate;
/**
* 管理级别 0=主管理员 1=子管理员 2=普通员工
*/
private Integer admin;
/**
* 创建时间
*/
private Date created;
/**
* 更新时间
*/
private Date updated;
}
package org.modules.junmpProcess.enums;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 18:15
*/
public enum AssigneeTypeEnums {
ASSIGN_USER("ASSIGN_USER"),
SELF_SELECT("SELF_SELECT"),
LEADER_TOP("LEADER_TOP"),
LEADER("LEADER"),
ROLE("ROLE"),
SELF("SELF"),
FORM_USER("FORM_USER");
private String typeName;
AssigneeTypeEnums(String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}
package org.modules.junmpProcess.enums;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/9 18:15
*/
public enum ModeEnums {
AND("AND"),
OR("OR"),
NEXT("NEXT");
private String typeName;
ModeEnums(String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}
package org.modules.junmpProcess.exception;
import lombok.extern.slf4j.Slf4j;
import org.modules.junmpProcess.common.R;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;
/**
* @date 2018/8/30
* 全局异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandlerResolver {
/**
* 全局异常.
*
* @param e the e
* @return R
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Object handleGlobalException(Exception e) {
log.error("全局异常信息 ex={}", e.getMessage(), e);
return R.badRequest(e.getLocalizedMessage());
}
/**
* validation Exception
*
* @param exception
* @return R
*/
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handleBodyValidException(MethodArgumentNotValidException exception) {
List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
log.error("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
return R.badRequest(fieldErrors.get(0).getDefaultMessage());
}
}
package org.modules.junmpProcess.exception;
/**
* 流程异常封装
*/
public class WorkFlowException extends RuntimeException {
public WorkFlowException(String message) {
super(message);
}
}
package org.modules.junmpProcess.job;
import com.alibaba.fastjson.JSONObject;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.job.api.Job;
import org.flowable.job.service.TimerJobService;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import java.io.Serializable;
import java.util.Date;
/**
* @author LoveMyOrange
* @create 2022-10-15 21:51
*/
public class CustomJobCmd implements Command<Void>, Serializable {
protected String processInstanceId;
protected String taskId;
protected String executionId;
protected Date dueDate;
protected String type;
protected String comment;
public CustomJobCmd(String processInstanceId, String comment, String taskId, String executionId, Date dueDate, String type) {
this.processInstanceId = processInstanceId;
this.comment = comment;
this.taskId = taskId;
this.executionId = executionId;
this.dueDate = dueDate;
this.type = type;
}
@Override
public Void execute(CommandContext commandContext) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("comment", this.comment);
jsonObject.put("task_id", this.taskId);
TimerJobService timerJobService = CommandContextUtil.getTimerJobService(commandContext);
TimerJobEntity job = timerJobService.createTimerJob();
job.setJobType(Job.JOB_TYPE_TIMER);
job.setExclusive(true);
// 作业处理器类型
job.setJobHandlerType(CustomJobHandler.TYPE);
// 处理时间
job.setDuedate(this.dueDate);
job.setExecutionId(null);
job.setProcessInstanceId(this.processInstanceId);
job.setJobHandlerConfiguration(jsonObject.toJSONString());
timerJobService.scheduleTimerJob(job);
return null;
}
}
package org.modules.junmpProcess.job;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.job.service.JobHandler;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.variable.api.delegate.VariableScope;
/**
* @author LoveMyOrange
* @create 2022-10-15 21:42
*/
@Slf4j
public class CustomJobHandler implements JobHandler {
public static final String TYPE = "custom-handler";
@Override
public String getType() {
return "custom-handler";
}
@Override
public void execute(JobEntity jobEntity, String s, VariableScope variableScope, CommandContext commandContext) {
log.info("============执行自定义定时任务============");
log.info("定时任务详情={}", JSON.toJSONString(jobEntity));
}
}
package org.modules.junmpProcess.job;
import org.flowable.common.engine.impl.cfg.IdGenerator;
import org.modules.junmpProcess.utils.SpringContextHolder;
import org.modules.junmpProcess.utils.IdWorker;
import org.springframework.stereotype.Component;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/17 13:01
*/
@Component
public class IdWorkerIdGenerator implements IdGenerator {
@Override
public String getNextId() {
return SpringContextHolder.getBean(IdWorker.class).nextId() + "";
}
}
package org.modules.junmpProcess.listener;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.Properties;
import org.modules.junmpProcess.dto.json.UserInfo;
import org.modules.junmpProcess.enums.AssigneeTypeEnums;
import org.modules.junmpProcess.exception.WorkFlowException;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.modules.junmpProcess.common.CommonConstants.START_USER_INFO;
import static org.modules.junmpProcess.utils.BpmnModelUtils.getChildNode;
/**
* @author LoveMyOrange
* @create 2022-10-15 13:35
*/
@Component
public class CounterSignListener implements ExecutionListener {
@Resource
private RepositoryService repositoryService;
@Override
public void notify(DelegateExecution execution) {
String currentActivityId = execution.getCurrentActivityId();
Process mainProcess = repositoryService.getBpmnModel(execution.getProcessDefinitionId()).getMainProcess();
UserTask userTask = (UserTask) mainProcess.getFlowElement(currentActivityId);
String dingDing = mainProcess.getAttributeValue("http://flowable.org/bpmn", "DingDing");
JSONObject jsonObject = JSONObject.parseObject(dingDing, new TypeReference<JSONObject>() {
});
String processJson = jsonObject.getString("processJson");
ChildNode childNode = JSONObject.parseObject(processJson, new TypeReference<ChildNode>() {
});
List<String> assigneeList = new ArrayList<>();
String variable = currentActivityId + "assigneeList";
List usersValue = (List) execution.getVariable(variable);
if (usersValue == null) {
ChildNode currentNode = getChildNode(childNode, currentActivityId);
if (currentNode == null) {
throw new WorkFlowException("查找审批人失败,请联系管理员重试");
}
Properties props = currentNode.getProps();
String assignedType = props.getAssignedType();
Map<String, Object> nobody = props.getNobody();
if (AssigneeTypeEnums.ASSIGN_USER.getTypeName().equals(assignedType)) {
List<UserInfo> assignedUser = props.getAssignedUser();
for (UserInfo userInfo : assignedUser) {
assigneeList.add(userInfo.getId());
}
} else if (AssigneeTypeEnums.SELF_SELECT.getTypeName().equals(assignedType)) {
} else if (AssigneeTypeEnums.LEADER_TOP.getTypeName().equals(assignedType)) {
throw new WorkFlowException("暂不做这个功能,等发版!");
} else if (AssigneeTypeEnums.LEADER.getTypeName().equals(assignedType)) {
/*
这里代码应该怎么写??? 你想想
应该是 通过leader 的code 查出来leader里面的人 然后添加到
assigneeList.addAll() 既可
不过本项目没有添加leader的CRUD页面 所以 先这样,
怎么实现就是上述实现手段
下面角色也一样, 希望我们<布尔什维克>的
同志们
可以举一反三 一通百通
*/
// throw new WorkFlowException("当前只是简单的系统 没有RBAC功能,各位可以自己实现!");
} else if (AssigneeTypeEnums.ROLE.getTypeName().equals(assignedType)) {
// throw new WorkFlowException("当前只是简单的系统 没有RBAC功能,各位可以自己实现!");
} else if (AssigneeTypeEnums.SELF.getTypeName().equals(assignedType)) {
String startUserJson = execution.getVariable(START_USER_INFO, String.class);
UserInfo userInfo = JSONObject.parseObject(startUserJson, new TypeReference<UserInfo>() {
});
assigneeList.add(userInfo.getId());
} else if (AssigneeTypeEnums.FORM_USER.getTypeName().equals(assignedType)) {
String formUser = props.getFormUser();
List<JSONObject> assigneeUsers = execution.getVariable(formUser, List.class);
if (assigneeUsers != null) {
for (JSONObject assigneeUser : assigneeUsers) {
assigneeList.add(assigneeUser.getString("id"));
}
}
}
if (CollUtil.isEmpty(assigneeList)) {
String handler = MapUtil.getStr(nobody, "handler");
if ("TO_PASS".equals(handler)) {
assigneeList.add("100000");
execution.setVariable(variable, assigneeList);
} else if ("TO_REFUSE".equals(handler)) {
execution.setVariable("autoRefuse", Boolean.TRUE);
assigneeList.add("100000");
execution.setVariable(variable, assigneeList);
} else if ("TO_ADMIN".equals(handler)) {
assigneeList.add("381496");
execution.setVariable(variable, assigneeList);
} else if ("TO_USER".equals(handler)) {
Object assignedUserObj = nobody.get("assignedUser");
if (assignedUserObj != null) {
List<JSONObject> assignedUser = (List<JSONObject>) assignedUserObj;
if (assignedUser.size() > 0) {
for (JSONObject object : assignedUser) {
assigneeList.add(object.getString("id"));
}
execution.setVariable(variable, assigneeList);
} else {
assigneeList.add("100000");
execution.setVariable(variable, assigneeList);
}
}
} else {
throw new WorkFlowException("找不到审批人,请检查配置!!!");
}
} else {
execution.setVariable(variable, assigneeList);
}
} else {
}
}
}
package org.modules.junmpProcess.listener;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import static org.modules.junmpProcess.common.CommonConstants.BUSINESS_STATUS_4;
import static org.modules.junmpProcess.common.CommonConstants.PROCESS_STATUS;
/**
* @author LoveMyOrange
* @create 2022-10-15 19:47
*/
@Component
public class ProcessListener implements ExecutionListener {
@Resource
private RepositoryService repositoryService;
@Override
public void notify(DelegateExecution execution) {
execution.setVariable(PROCESS_STATUS, BUSINESS_STATUS_4);
}
}
package org.modules.junmpProcess.listener;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author LoveMyOrange
* @create 2022-10-15 19:47
*/
@Component
public class ServiceListener implements ExecutionListener {
@Resource
private RepositoryService repositoryService;
@Override
public void notify(DelegateExecution execution) {
}
}
package org.modules.junmpProcess.listener;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
import org.modules.junmpProcess.utils.SpringContextHolder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author LoveMyOrange
* @create 2022-10-15 14:51
*/
@Component
public class TaskCreatedListener implements TaskListener {
@Resource
private TaskService taskService;
@Resource
private RepositoryService repositoryService;
@Override
public void notify(DelegateTask delegateTask) {
String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
if ("root".equalsIgnoreCase(taskDefinitionKey)) {
taskService.complete(delegateTask.getId());
} else {
if ("100000".equals(delegateTask.getAssignee())) {
Object autoRefuse = delegateTask.getVariable("autoRefuse");
if (autoRefuse == null) {
taskService.addComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "opinion", "审批人为空,自动通过");
taskService.complete(delegateTask.getId());
} else {
taskService.addComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), "opinion", "审批人为空,自动驳回");
RuntimeService runtimeService = SpringContextHolder.getBean(RuntimeService.class);
runtimeService.deleteProcessInstance(delegateTask.getProcessInstanceId(), "审批人为空,自动驳回");
}
}
}
}
}
package org.modules.junmpProcess.listener;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author LoveMyOrange
* @create 2022-10-15 19:47
*/
@Component
@Slf4j
public class TimerListener implements ExecutionListener {
@Resource
private RepositoryService repositoryService;
@Override
public void notify(DelegateExecution execution) {
log.info("========");
System.err.println("exection触发了");
}
}
package org.modules.junmpProcess.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.modules.junmpProcess.entity.Departments;
/**
* @author : willian fu
* @version : 1.0
*/
@Mapper
public interface DepartmentsMapper extends BaseMapper<Departments> {
}
package org.modules.junmpProcess.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.modules.junmpProcess.entity.FormGroups;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Mapper
public interface FormGroupsMapper extends BaseMapper<FormGroups> {
}
package org.modules.junmpProcess.mapper;//package org.jeecg.junmpProcess.mapper;
//
//
//import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//import org.apache.ibatis.annotations.Mapper;
//
//@Mapper
//public interface ProcessMapper extends BaseMapper<Process> {
//}
package org.modules.junmpProcess.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.modules.junmpProcess.entity.ProcessTemplates;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Mapper
public interface ProcessTemplatesMapper extends BaseMapper<ProcessTemplates> {
}
package org.modules.junmpProcess.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.modules.junmpProcess.entity.TemplateGroup;
import org.modules.junmpProcess.entity.TemplateGroupBo;
import java.util.List;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Mapper
public interface TemplateGroupMapper extends BaseMapper<TemplateGroup> {
/**
* 查询所有表单及组
*
* @return
*/
@Select("SELECT fg.group_id, tg.id, fg.group_name, pt.template_id, pt.remark, pt.is_stop, pt.updated, pt.template_name, " +
"pt.icon, pt.background FROM process_templates pt LEFT JOIN template_group tg ON pt.template_id = tg.template_id\n" +
"RIGHT JOIN form_groups fg ON tg.group_id = fg.group_id ORDER BY fg.sort_num ASC, tg.sort_num ASC")
List<TemplateGroupBo> getAllFormAndGroups();
}
package org.modules.junmpProcess.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.modules.junmpProcess.entity.Users;
/**
* @author : willian fu
* @version : 1.0
*/
@Mapper
public interface UsersMapper extends BaseMapper<Users> {
}
package org.modules.junmpProcess.service.Bussiness;
/**
* @author : willian fu
* @version : 1.0
*/
public interface OrgUserAndDeptService {
/**
* 查询组织架构树
*
* @param deptId 部门id
* @return 组织架构树数据
*/
Object getOrgTreeData(Integer deptId, String type);
/**
* 模糊搜索用户
*
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
Object getOrgTreeUser(String userName);
}
package org.modules.junmpProcess.service.Bussiness;
import org.modules.junmpProcess.dto.FlowEngineDTO;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.vo.TemplateGroupVo;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* @author : willian fu
* @date : 2020/9/21
*/
public interface SettingService {
/**
* 查询表单组
*
* @return 表单组数据
*/
Object getFormGroups(String token, String name);
/**
* 表单及分组排序
*
* @param groups 分组数据
* @return 排序结果
*/
Object formGroupsSort(List<TemplateGroupVo> groups);
/**
* 查询表单模板数据
*
* @param templateId 模板id
* @return 模板详情数据
*/
Object getFormTemplateById(String templateId);
/**
* 修改分组
*
* @param id 分组ID
* @param name 分组名
* @return 修改结果
*/
Object updateFormGroupName(Integer id, String name);
/**
* 新增表单分组
*
* @param name 分组名
* @return 添加结果
*/
Object createFormGroup(String name);
/**
* 删除分组
*
* @param id 分组ID
* @return 删除结果
*/
Object deleteFormGroup(Integer id);
/**
* 编辑表单
*
* @param templateId 摸板ID
* @param type 类型 stop using delete
* @return 操作结果
*/
Object updateForm(String templateId, String type, Integer groupId);
/**
* 编辑表单详情
*
* @param template 表单模板信息
* @return 修改结果
*/
Object updateFormDetail(ProcessTemplates template);
/**
* 保存表单
*
* @param
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
void jsonToBpmn(FlowEngineDTO flowEngineDTO) throws InvocationTargetException, IllegalAccessException;
}
package org.modules.junmpProcess.service.Bussiness;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import org.modules.junmpProcess.common.Result;
import org.modules.junmpProcess.dto.ApplyDTO;
import org.modules.junmpProcess.dto.HandleDataDTO;
import org.modules.junmpProcess.dto.StartProcessInstanceDTO;
import org.modules.junmpProcess.dto.TaskDTO;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.vo.HandleDataVO;
import org.modules.junmpProcess.vo.HistoryProcessInstanceVO;
import org.modules.junmpProcess.vo.MultiVO;
import org.modules.junmpProcess.vo.TaskVO;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import java.util.Map;
public interface WorkProcessService {
/**
* 创建表单
*
* @return
*/
boolean createBpmn(JsonNode flowdto);
/**
* 获取用户可见表单
*
* @return
*/
Object getFormGroups(String name);
/**
* 通过模板id查看流程信息 会附带流程定义id
*
* @return
*/
Result<ProcessTemplates> detail(String templateId);
/**
* 通过流程定义id启动流程
*
* @return
*/
Result<Object> start(StartProcessInstanceDTO startProcessInstanceDTO);
/**
* 查看我发起的流程
*
* @return
*/
Result<Page<HistoryProcessInstanceVO>> applyList(ApplyDTO applyDTO);
/**
* 查看我的待办
*
* @return
*/
Result<Page<TaskVO>> toDoList(TaskDTO taskDTO);
/**
* 查看我的已办
*
* @return
*/
Result<Page<TaskVO>> doneList(@RequestBody TaskDTO taskDTO);
/**
* 同意
*
* @return
*/
Result agree(HandleDataDTO handleDataDTO);
/**
* 委派
*
* @return
*/
Result delegateTask(HandleDataDTO handleDataDTO);
/**
* 委派人完成的按钮
*
* @return
*/
Result resolveTask(@RequestBody HandleDataDTO handleDataDTO);
/**
* 拒绝
*
* @return
*/
Result refuse(HandleDataDTO handleDataDTO);
/**
* 撤销按钮
*
* @return
*/
Result revoke(HandleDataDTO handleDataDTO);
/**
* 转办按钮
*
* @return
*/
Result assignee(HandleDataDTO handleDataDTO);
/**
* 退回按钮
*
* @return
*/
Result rollback(HandleDataDTO handleDataDTO);
/**
* 加签按钮
*
* @return
*/
Result addMulti(HandleDataDTO handleDataDTO);
/**
* 查到签上的人
*
* @return
*/
Result<List<MultiVO>> queryMultiUsersInfo(Map<String, Object> map);
/**
* 减签按钮
*
* @return
*/
Result deleteMulti(List<String> executionIds);
/**
* 评论按钮
*
* @return
*/
Result comments(HandleDataDTO handleDataDTO);
/**
* 通过流程实例id查看详情
*
* @return
*/
Result<HandleDataVO> instanceInfo(HandleDataDTO HandleDataDTO);
// /**
// * 上传文件
// * @return
// */
// Result<AttachmentVO> upLoadFile(MultipartFile file, HttpServletRequest request);
// /**
// * 下载文件
// * @return
// */
// void downLoadFile( String name);
}
package org.modules.junmpProcess.service.Bussiness.impl;
import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.modules.junmpProcess.common.R;
import org.modules.junmpProcess.entity.Departments;
import org.modules.junmpProcess.entity.Users;
import org.modules.junmpProcess.service.Bussiness.OrgUserAndDeptService;
import org.modules.junmpProcess.service.Repository.DepartmentsService;
import org.modules.junmpProcess.service.Repository.UserService;
import org.modules.junmpProcess.vo.OrgTreeVo;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.*;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class OrgUserAndDeptServiceImpl implements OrgUserAndDeptService {
@Resource
private DepartmentsService departmentsService;
@Resource
private UserService userService;
/**
* 查询组织架构树
*
* @param deptId 部门id
* @return 组织架构树数据
*/
@Override
public Object getOrgTreeData(Integer deptId, String type) {
LambdaQueryWrapper<Users> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (!ObjectUtils.isEmpty(deptId)) {
LambdaQueryWrapper<Departments> departmentsLambdaQueryWrapper = new LambdaQueryWrapper<>();
departmentsLambdaQueryWrapper.eq(Departments::getParentId, deptId);
lambdaQueryWrapper.like(Users::getDepartmentIds, "%" + deptId + "%")
.or()
.like(Users::getDepartmentIds, "%" + deptId + ",%")
.like(Users::getDepartmentIds, "%," + deptId + "%");
List<OrgTreeVo> orgTreeVos = new LinkedList<>();
departmentsService.list(departmentsLambdaQueryWrapper).forEach(dept -> {
orgTreeVos.add(OrgTreeVo.builder()
.id(dept.getDeptId())
.name(dept.getDeptName())
.selected(false)
.type("dept")
.build());
});
userService.list(lambdaQueryWrapper).forEach(user -> {
orgTreeVos.add(OrgTreeVo.builder()
.id(user.getUserId())
.name(user.getUserName())
.avatar(user.getAvatar())
.sex(user.getSex())
.type("user")
.selected(false)
.build());
});
return R.ok(orgTreeVos);
}
List<Users> users = userService.list();
List<Departments> departments = departmentsService.list();
//将人员按部门归类分组
Map<Long, List<Users>> deptUsers = new HashMap<>();
users.forEach(user -> {
for (String did : user.getDepartmentIds().split(",")) {
List<Users> usersList = deptUsers.get(Long.parseLong(did));
if (null == usersList) {
List<Users> list = new ArrayList<>();
list.add(user);
} else {
usersList.add(user);
}
}
});
//将部门及员工进行转换嵌套树形结构
departments.forEach(dept -> {
});
return R.ok(Collections.EMPTY_LIST);
}
/**
* 模糊搜索用户
*
* @param userName 用户名/拼音/首字母
* @return 匹配到的用户
*/
@Override
public Object getOrgTreeUser(String userName) {
LambdaQueryWrapper<Users> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (Validator.isChinese(userName)) {
lambdaQueryWrapper.like(Users::getUserName, "%" + userName + "%");
} else {
lambdaQueryWrapper.like(Users::getPingyin, "%" + userName + "%");
}
List<OrgTreeVo> list = new LinkedList<>();
userService.list(lambdaQueryWrapper).forEach(user -> {
list.add(OrgTreeVo.builder().type("user")
.sex(user.getSex())
.avatar(user.getAvatar())
.name(user.getUserName())
.id(user.getUserId())
.selected(false).build());
});
return R.ok(list);
}
}
package org.modules.junmpProcess.service.Bussiness.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.ExecutionListener;
import org.modules.junmpProcess.common.R;
import org.modules.junmpProcess.common.WorkFlowConstants;
import org.modules.junmpProcess.dto.FlowEngineDTO;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.SettingsInfo;
import org.modules.junmpProcess.entity.FormGroups;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.entity.TemplateGroup;
import org.modules.junmpProcess.entity.TemplateGroupBo;
import org.modules.junmpProcess.exception.WorkFlowException;
import org.modules.junmpProcess.mapper.TemplateGroupMapper;
import org.modules.junmpProcess.service.Bussiness.SettingService;
import org.modules.junmpProcess.service.Repository.FormGroupService;
import org.modules.junmpProcess.service.Repository.ProcessTemplateService;
import org.modules.junmpProcess.service.Repository.TemplateGroupService;
import org.modules.junmpProcess.utils.IdWorker;
import org.modules.junmpProcess.utils.SpringContextHolder;
import org.modules.junmpProcess.vo.TemplateGroupVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import static org.modules.junmpProcess.utils.BpmnModelUtils.*;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Service
public class SettingServiceImpl implements SettingService {
@Autowired
private ProcessTemplateService processTemplateService;
@Autowired
private TemplateGroupService templateGroupService;
@Autowired
private FormGroupService formGroupService;
@Resource
private IdWorker idWorker;
@Resource
private RepositoryService repositoryService;
/**
* 查询表单组
*
* @return 表单组数据
*/
@Override
public Object getFormGroups(String token, String name) {
TemplateGroupMapper templateGroupMapper = SpringContextHolder.getBean(TemplateGroupMapper.class);
List<TemplateGroupBo> allformAndGroups = templateGroupMapper.getAllFormAndGroups();
Map<Integer, List<TemplateGroupBo>> coverMap = new LinkedHashMap<>();
allformAndGroups.forEach(fg -> {
List<TemplateGroupBo> bos = coverMap.get(fg.getGroupId());
if (CollectionUtil.isEmpty(bos)) {
List<TemplateGroupBo> list = new ArrayList<>();
list.add(fg);
coverMap.put(fg.getGroupId(), list);
} else {
bos.add(fg);
}
});
List<TemplateGroupVo> results = new ArrayList<>();
coverMap.forEach((key, val) -> {
List<TemplateGroupVo.Template> templates = new ArrayList<>();
val.forEach(v -> {
if (ObjectUtil.isNotNull(v.getTemplateId())) {
templates.add(TemplateGroupVo.Template.builder()
.formId(v.getTemplateId())
.tgId(v.getId())
.remark(v.getRemark())
.formName(v.getTemplateName())
.icon(v.getIcon())
.isStop(v.getIsStop())
.updated(DateFormatUtils.format(v.getUpdated(), "yyyy年MM月dd日 HH时:mm分:ss秒"))
.background(v.getBackground())
.templateId(v.getTemplateId())
.logo(JSONObject.parseObject(v.getBackground(), new TypeReference<JSONObject>() {
}))
.build());
}
});
results.add(TemplateGroupVo.builder().id(key).name(val.get(0).getGroupName()).items(templates).build());
});
return R.ok(results);
}
/**
* 表单及分组排序
*
* @param groups 分组数据
* @return 排序结果
*/
@Override
@Transactional
public Object formGroupsSort(List<TemplateGroupVo> groups) {
int i = 0, j = 0;
try {
for (TemplateGroupVo group : groups) {
formGroupService.updateById(FormGroups.builder()
.groupId(group.getId())
.sortNum(group.getId().equals(0) ? 999999 : i + 2)
.build());
for (TemplateGroupVo.Template item : group.getItems()) {
templateGroupService.updateById(
TemplateGroup.builder()
.id(item.getTgId())
.groupId(group.getId())
.templateId(item.getFormId())
.sortNum(j + 1).build());
j++;
}
i++;
j = 0;
}
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return R.badRequest("排序异常 " + e.getMessage());
}
return R.ok("排序成功");
}
/**
* 查询表单模板数据
*
* @param templateId 模板id
* @return 模板详情数据
*/
@Override
public Object getFormTemplateById(String templateId) {
ProcessTemplates processTemplates = processTemplateService.getById(templateId);
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
return R.ok(processTemplates);
}
/**
* 修改分组
*
* @param id 分组ID
* @param name 分组名
* @return 修改结果
*/
@Override
public Object updateFormGroupName(Integer id, String name) {
if (id < 2) {
return R.badRequest("基础分组不允许修改");
}
formGroupService.updateById(FormGroups.builder()
.groupId(id).groupName(name.trim()).build());
return R.ok("修改成功");
}
/**
* 新增表单分组
*
* @param name 分组名
* @return 添加结果
*/
@Override
public Object createFormGroup(String name) {
LambdaQueryWrapper<FormGroups> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(FormGroups::getGroupName, name);
if (formGroupService.count(lambdaQueryWrapper) > 0) {
return R.badRequest("分组名称 [" + name + "] 已存在");
}
Date date = new Date();
FormGroups formGroups = FormGroups.builder().groupName(name)
.sortNum(1).created(date)
.updated(date).build();
formGroupService.save(
formGroups);
return R.ok("添加分组 " + name + " 成功");
}
/**
* 删除分组
*
* @param id 分组ID
* @return 删除结果
*/
@Override
@Transactional
public Object deleteFormGroup(Integer id) {
if (id < 2) {
return R.badRequest("基础分组不允许删除");
}
LambdaUpdateWrapper<TemplateGroup> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(TemplateGroup::getGroupId, 1);
lambdaUpdateWrapper.eq(TemplateGroup::getGroupId, id);
templateGroupService.update(lambdaUpdateWrapper);
formGroupService.removeById(id);
return R.ok("删除分组成功");
}
/**
* 编辑表单
*
* @param templateId 摸板ID
* @param type 类型 stop using delete
* @return 操作结果
*/
@Override
@Transactional
public Object updateForm(String templateId, String type, Integer groupId) {
boolean isStop = "stop".equals(type);
ProcessTemplates build = ProcessTemplates.builder().templateId(templateId).isStop(isStop)
.build();
if ("using".equals(type) || isStop) {
processTemplateService.updateById(
ProcessTemplates.builder().templateId(templateId).isStop(isStop).build());
LambdaUpdateWrapper<TemplateGroup> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(TemplateGroup::getTemplateId, templateId);
lambdaUpdateWrapper.set(TemplateGroup::getGroupId, isStop ? 0 : 1);
templateGroupService
.update(lambdaUpdateWrapper);
} else if ("delete".equals(type)) {
processTemplateService.removeById(templateId);
LambdaQueryWrapper<TemplateGroup> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(TemplateGroup::getTemplateId, templateId);
templateGroupService.remove(lambdaQueryWrapper);
} else if ("move".equals(type)) {
if (ObjectUtil.isNull(groupId)) {
return R.badRequest("分组ID必传");
}
LambdaUpdateWrapper<TemplateGroup> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(TemplateGroup::getTemplateId, templateId);
lambdaUpdateWrapper.set(TemplateGroup::getGroupId, groupId);
templateGroupService.update(lambdaUpdateWrapper);
} else {
return R.badRequest("不支持的操作");
}
return R.ok("操作成功");
}
/**
* 编辑表单详情
*
* @param template 表单模板信息
* @return 修改结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Object updateFormDetail(ProcessTemplates template) {
SettingsInfo settingsInfo = JSONObject.parseObject(template.getSettings(), new TypeReference<SettingsInfo>() {
});
ProcessTemplates processTemplates = processTemplateService.getById(template.getFormId());
processTemplates.setTemplateName(template.getFormName());
processTemplates.setGroupId(template.getGroupId());
processTemplates.setFormItems(template.getFormItems());
processTemplates.setSettings(template.getSettings());
processTemplates.setProcess(template.getProcess());
processTemplates.setIcon(template.getIcon());
processTemplates.setBackground(template.getBackground());
processTemplates.setNotify(settingsInfo.getNotify().toJSONString());
String adminInfo = JSONObject.toJSONString(settingsInfo.getAdmin());
processTemplates.setWhoCommit(adminInfo);
processTemplates.setWhoEdit(adminInfo);
processTemplates.setWhoExport(adminInfo);
processTemplates.setRemark(template.getRemark());
processTemplates.setUpdated(new Date());
processTemplateService.updateById(processTemplates);
ChildNode childNode = JSONObject.parseObject(template.getProcess(), new TypeReference<ChildNode>() {
});
JSONObject jsonObject = new JSONObject();
jsonObject.put("processJson", template.getProcess());
jsonObject.put("formJson", template.getFormItems());
BpmnModel bpmnModel = assemBpmnModel(jsonObject, childNode, template.getRemark(),
template.getFormName(), template.getGroupId(), template.getFormId());
repositoryService.createDeployment()
.addBpmnModel(template.getFormName() + ".bpmn", bpmnModel)
.name(template.getFormName())
.category(template.getGroupId() + "")
.deploy();
return R.ok("发布更新后的表单成功");
}
@Transactional(rollbackFor = Exception.class)
@Override
public void jsonToBpmn(FlowEngineDTO flowEngineDTO) throws InvocationTargetException, IllegalAccessException {
String processJson = flowEngineDTO.getProcess();
ChildNode childNode = JSONObject.parseObject(processJson, new TypeReference<ChildNode>() {
});
String settingsJson = flowEngineDTO.getSettings();
SettingsInfo settingsInfo = JSONObject.parseObject(settingsJson, new TypeReference<SettingsInfo>() {
});
String remark = flowEngineDTO.getRemark();
String formItems = flowEngineDTO.getFormItems();
String formName = flowEngineDTO.getFormName();
String logo = flowEngineDTO.getLogo();
Integer groupId = flowEngineDTO.getGroupId();
String templateId = idWorker.nextId() + "";
ProcessTemplates processTemplates = ProcessTemplates.builder().build();
processTemplates.setTemplateId(templateId);
processTemplates.setTemplateName(formName);
processTemplates.setGroupId(groupId);
processTemplates.setFormItems(formItems);
processTemplates.setProcess(processJson);
processTemplates.setIcon(logo);
processTemplates.setBackground(logo);
processTemplates.setNotify(settingsInfo.getNotify().toJSONString());
String adminInfo = JSONObject.toJSONString(settingsInfo.getAdmin());
processTemplates.setSettings(settingsJson);
processTemplates.setWhoCommit(adminInfo);
processTemplates.setWhoEdit(adminInfo);
processTemplates.setWhoExport(adminInfo);
processTemplates.setRemark(flowEngineDTO.getRemark());
processTemplates.setIsStop(false);
Date date = new Date();
processTemplates.setCreated(date);
processTemplates.setUpdated(date);
processTemplateService.save(processTemplates);
TemplateGroup templateGroup = new TemplateGroup();
templateGroup.setTemplateId(processTemplates.getTemplateId());
templateGroup.setGroupId(groupId);
templateGroup.setSortNum(0);
templateGroup.setCreated(date);
templateGroupService.save(templateGroup);
JSONObject jsonObject = new JSONObject();
jsonObject.put("processJson", processJson);
jsonObject.put("formJson", formItems);
BpmnModel bpmnModel = assemBpmnModel(jsonObject, childNode, remark, formName, groupId,
templateId);
repositoryService.createDeployment()
.addBpmnModel(formName + ".bpmn", bpmnModel)
.name(formName)
.category(groupId + "")
.deploy();
}
private BpmnModel assemBpmnModel(JSONObject jsonObject, ChildNode childNode, String remark,
String formName, Integer groupId, String templateId) {
BpmnModel bpmnModel = new BpmnModel();
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
Map<String, ChildNode> childNodeMap = new HashMap<>();
bpmnModel.setTargetNamespace(groupId + "");
ExtensionAttribute extensionAttribute = new ExtensionAttribute();
extensionAttribute.setName("DingDing");
extensionAttribute.setNamespace("http://flowable.org/bpmn");
extensionAttribute.setValue(jsonObject.toJSONString());
Process process = new Process();
process.setId(WorkFlowConstants.PROCESS_PREFIX + templateId);
process.setName(formName);
process.setDocumentation(remark);
process.addAttribute(extensionAttribute);
bpmnModel.addProcess(process);
StartEvent startEvent = createStartEvent();
process.addFlowElement(startEvent);
String lastNode = null;
try {
lastNode = create(startEvent.getId(), childNode, process, bpmnModel, sequenceFlows, childNodeMap);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new WorkFlowException("操作失败");
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new WorkFlowException("操作失败");
}
EndEvent endEvent = createEndEvent();
process.addFlowElement(endEvent);
process.addFlowElement(connect(lastNode, endEvent.getId(), sequenceFlows, childNodeMap, process));
List<FlowableListener> executionListeners = new ArrayList<>();
FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(ExecutionListener.EVENTNAME_END);
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
flowableListener.setImplementation("${processListener}");
executionListeners.add(flowableListener);
process.setExecutionListeners(executionListeners);
new BpmnAutoLayout(bpmnModel).execute();
return bpmnModel;
}
}
package org.modules.junmpProcess.service.Bussiness.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.engine.task.Attachment;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.modules.junmpProcess.common.Result;
import org.modules.junmpProcess.common.WorkFlowConstants;
import org.modules.junmpProcess.dto.*;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.FormOperates;
import org.modules.junmpProcess.dto.json.SettingsInfo;
import org.modules.junmpProcess.dto.json.UserInfo;
import org.modules.junmpProcess.dto.json.flowJson.FlowChildNode;
import org.modules.junmpProcess.dto.json.flowJson.Inout;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.exception.WorkFlowException;
import org.modules.junmpProcess.service.Bussiness.WorkProcessService;
import org.modules.junmpProcess.service.Repository.ProcessTemplateService;
import org.modules.junmpProcess.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import static org.modules.junmpProcess.common.CommonConstants.*;
import static org.modules.junmpProcess.common.WorkFlowConstants.PROCESS_PREFIX;
import static org.modules.junmpProcess.utils.BpmnModelUtils.*;
;
@Service
public class WorkProcessServiceImpl implements WorkProcessService {
@Autowired
private ProcessTemplateService processTemplateService;
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private HistoryService historyService;
@Resource
private TaskService taskService;
public boolean createBpmn(JsonNode FlowDTO) {
// 一.准备工作
BpmnModel bpmnModel = new BpmnModel();
Process process = new Process(); // 相当于图纸
bpmnModel.addProcess(process);
process.setId("Process_" + UUID.randomUUID());
process.setExecutable(true);
// 二.开始结束节点
StartEvent startEvent = new StartEvent();// 新建开始节点
startEvent.setId("_start");
process.addFlowElement(startEvent);// 绘制到图纸
EndEvent endEvent = new EndEvent(); // 新建结束节点
endEvent.setId("_end");// 绘制到图纸
process.addFlowElement(endEvent);
// 三.递归绘制节点
drawNode(process, FlowDTO, "_start", "_end", null);
// 四.自动布局
new BpmnAutoLayout(bpmnModel).execute();
// 五.转xml
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
byte[] convertToXML = bpmnXMLConverter.convertToXML(bpmnModel);
String xml = new String(convertToXML);
xml = xml.replaceAll("&lt;", "<").replaceAll("&gt;", ">");
return true;
}
/**
* 绘制节点
*
* @param process bpmn process 图纸
* @param node json的节点
* @param preId 上一节点id
* @param endId 结束节点
* @param preExpression 上一节点表达式
*/
public void drawNode(Process process, JsonNode node, String preId, String endId, String preExpression) {
// 根据type绘制不同种类的节点
Inout inout = drawNodeByType(process, node);
// 绘制前一根线
process.addFlowElement(createSequenceFlow(preId, inout.getIn(), preExpression));
if (node.get("childNode").toString().equals("null")) {
// 没有下一步, 绘制指向结束的线
process.addFlowElement(createSequenceFlow(inout.getOut(), endId, null));
} else {
// 有下一步, 递归绘制下一个节点
drawNode(process, node.get("childNode"), inout.getOut(), endId, null);
}
}
/**
* 绘制不同种类节点
*
* @param process
* @param node
* @return
*/
private Inout drawNodeByType(Process process, JsonNode node) {
if (node.get("type").toString().equals("0")) {//根节点或起始节点
return drawRootNode(process, node);
} else if (node.get("type").toString().equals("1")) {//审核节点
return drawAuditNode(process, node);
} else if (node.get("type").toString().equals("3")) {//分支节点
return drawExclusiveNode(process, node);
} else if (node.get("type").toString().equals("4")) {//分支节点
return drawExclusiveNode(process, node);
} else {
throw new IllegalArgumentException();
}
}
/**
* 绘制分支节点
*
* @param process
* @param node
* @return
*/
private Inout drawExclusiveNode(Process process, JsonNode node) {
// 开始网关
String startId = "Exclusive_" + UUID.randomUUID();
ExclusiveGateway startGateway = new ExclusiveGateway();
startGateway.setId(startId);
process.addFlowElement(startGateway);
// 结束网关
String endId = "Exclusive_" + UUID.randomUUID();
ExclusiveGateway endGateway = new ExclusiveGateway();
endGateway.setId(endId);
process.addFlowElement(endGateway);
// 绘制分支
// List<JsonNode> branches = node.get("FlowConditionNodes");
// 针对 gateway 空任务分支 添加条件表达式
// for (FlowConditionNodes branch : branches) {
// String expression = branch.getConditionGroup();
// if (branch.getChildNode()==null) {
// // 没有子流程,直接绘制结束线
// process.addFlowElement(createSequenceFlow(startId, endId, expression));
// } else {
// // 有子流程,递归绘制子流程
// drawNode(process, branch.getChildNode(), startId, endId, expression);
// }
// }
// int和out不一样
return new Inout(startId, endId);
}
/**
* 创建连线
*
* @param from
* @param to
* @return
*/
public SequenceFlow createSequenceFlow(String from, String to, String conditionExpression) {
SequenceFlow flow = new SequenceFlow();
flow.setId(from + "-" + to);
flow.setSourceRef(from);
flow.setTargetRef(to);
if (conditionExpression != null) {
flow.setConditionExpression(conditionExpression);
}
return flow;
}
/**
* 绘制根节点
*
* @param process
* @param node
* @return
*/
private Inout drawRootNode(Process process, JsonNode node) {
String id = "Node_" + UUID.randomUUID();
// 如果当前任务还有后续任务,则遍历创建后续任务
JsonNode nextNode = node.get("childNode");
UserTask userTask = new UserTask();
userTask.setName(node.get("name").toString());
userTask.setId(id);
process.addFlowElement(userTask);
return new Inout(id, id);
}
private static String createSimpleUserTask(JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) {
List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
// 自动生成id
String id = id("userTask");
if (incoming != null && !incoming.isEmpty()) {
UserTask userTask = new UserTask();
userTask.setName(flowNode.getString("name"));
userTask.setId(id);
process.addFlowElement(userTask);
process.addFlowElement(connect(incoming.get(0), id, sequenceFlows));
}
return id;
}
/**
* 连线
*
* @param from
* @param to
* @param sequenceFlows
* @return
*/
protected static SequenceFlow connect(String from, String to, List<SequenceFlow> sequenceFlows) {
SequenceFlow flow = new SequenceFlow();
flow.setId(id("sequenceFlow"));
flow.setSourceRef(from);
flow.setTargetRef(to);
sequenceFlows.add(flow);
return flow;
}
private static String id(String prefix) {
return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase();
}
/**
* 绘制审核节点
*
* @param process
* @param node
* @return
*/
private Inout drawAuditNode(Process process, JsonNode node) {
// 绘制节点
String id = "Node_" + UUID.randomUUID();
UserTask userTask = new UserTask();
userTask.setId(id);
userTask.setName(node.get("name").toString());
// 设置多实例
// userTask.setAssignee("${user}");
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
// if (node.getAssignee().getMultiMode().equals("顺序审批")) {
// multiInstanceLoopCharacteristics.setSequential(true);
// }
multiInstanceLoopCharacteristics.setElementVariable("user");
// 完成条件
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfInstances == nrOfCompletedInstances}");
multiInstanceLoopCharacteristics.setInputDataItem("${users}");
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
// 保存json节点配置到扩展属性
Map<String, Object> extensions = new HashMap<>();
extensions.put("node", node);
process.addFlowElement(userTask);
;
return new Inout(id, id);
}
private BpmnModel assemBpmnModel(FlowChildNode childNode,
Integer groupId) {
BpmnModel bpmnModel = new BpmnModel();
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
Map<String, ChildNode> childNodeMap = new HashMap<>();
bpmnModel.setTargetNamespace(groupId + "");
// ExtensionAttribute extensionAttribute=new ExtensionAttribute();
// extensionAttribute.setName("Junmp");
// extensionAttribute.setNamespace("http://flowable.org/bpmn");
// extensionAttribute.setValue(jsonObject.toJSONString());
Process process = new Process();
process.setId(WorkFlowConstants.PROCESS_PREFIX);
// process.setName(formName);
// process.setDocumentation(remark);
// process.addAttribute(extensionAttribute);
bpmnModel.addProcess(process);
StartEvent startEvent = createStartEvent();
process.addFlowElement(startEvent);
String lastNode = null;
// try {
// lastNode = create(startEvent.getId(), childNode,process,bpmnModel,sequenceFlows,childNodeMap);
// } catch (InvocationTargetException e) {
// e.printStackTrace();
// throw new WorkFlowException("操作失败");
// } catch (IllegalAccessException e) {
// e.printStackTrace();
// throw new WorkFlowException("操作失败");
// }
EndEvent endEvent = createEndEvent();
process.addFlowElement(endEvent);
// process.addFlowElement(connect(lastNode, endEvent.getId(),sequenceFlows,childNodeMap,process));
List<FlowableListener> executionListeners = new ArrayList<>();
FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(ExecutionListener.EVENTNAME_END);
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
flowableListener.setImplementation("${processListener}");
executionListeners.add(flowableListener);
process.setExecutionListeners(executionListeners);
new BpmnAutoLayout(bpmnModel).execute();
return bpmnModel;
}
@Override
public Object getFormGroups(String templateId) {
ProcessTemplates processTemplates = processTemplateService.getById(templateId);
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(PROCESS_PREFIX + templateId).latestVersion().singleResult();
if (processDefinition == null) {
throw new WorkFlowException("该流程暂未接入Flowable,请重试");
}
processTemplates.setProcessDefinitionId(processDefinition.getId());
return processTemplates;
// return null;
}
/**
* 通过模板id查看流程信息 会附带流程定义id
*
* @return
*/
@Override
public Result<ProcessTemplates> detail(String templateId) {
ProcessTemplates processTemplates = processTemplateService.getById(templateId);
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(PROCESS_PREFIX + templateId).latestVersion().singleResult();
if (processDefinition == null) {
throw new WorkFlowException("该流程暂未接入Flowable,请重试");
}
processTemplates.setProcessDefinitionId(processDefinition.getId());
return Result.OK(processTemplates);
}
/**
* 通过流程定义id启动流程
*
* @return
*/
@Override
public Result<Object> start(StartProcessInstanceDTO processInstanceDto) {
try {
JSONObject formData = processInstanceDto.getFormData();
UserInfo startUserInfo = processInstanceDto.getStartUserInfo();
Authentication.setAuthenticatedUserId(startUserInfo.getId());
Map<String, Object> processVariables = new HashMap<>();
processVariables.put(FORM_VAR, formData);
processVariables.put(PROCESS_STATUS, BUSINESS_STATUS_1);
processVariables.put(START_USER_INFO, JSONObject.toJSONString(startUserInfo));
ArrayList<UserInfo> userInfos = CollUtil.newArrayList(startUserInfo);
processVariables.put("root", JSONObject.toJSONString(userInfos));
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
processVariables.putAll(formValue);
ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
ProcessInstance processInstance = processInstanceBuilder
.processDefinitionId(processInstanceDto.getProcessDefinitionId())
.variables(processVariables)
.businessStatus(BUSINESS_STATUS_1)
.start();
return Result.OK(processInstance.getId());
} catch (Exception e) {
Throwable cause = e.getCause();
if (cause instanceof WorkFlowException) {
WorkFlowException workFlowException = (WorkFlowException) cause;
return Result.error(workFlowException.getMessage());
}
e.printStackTrace();
return Result.error("启动流程失败");
}
}
/**
* 查看我发起的流程
*
* @return
*/
@Override
public Result<Page<HistoryProcessInstanceVO>> applyList(ApplyDTO applyDTO) {
List<HistoricProcessInstance> historicProcessInstances =
historyService.createHistoricProcessInstanceQuery()
.includeProcessVariables()
.startedBy(applyDTO.getCurrentUserInfo().getId())
.orderByProcessInstanceStartTime().desc()
.listPage((applyDTO.getPageNo() - 1) * applyDTO.getPageSize(), applyDTO.getPageSize());
long count = historyService.createHistoricProcessInstanceQuery()
.startedBy(applyDTO.getCurrentUserInfo().getId()).count();
List<HistoryProcessInstanceVO> historyProcessInstanceVOS = new ArrayList<>();
Page<HistoryProcessInstanceVO> page = new Page<>();
for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
HistoryProcessInstanceVO historyProcessInstanceVO = new HistoryProcessInstanceVO();
historyProcessInstanceVO.setProcessInstanceId(historicProcessInstance.getId());
historyProcessInstanceVO.setProcessDefinitionName(historicProcessInstance.getProcessDefinitionName());
historyProcessInstanceVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
historyProcessInstanceVO.setStartTime(historicProcessInstance.getStartTime());
historyProcessInstanceVO.setEndTime(historicProcessInstance.getEndTime());
Boolean flag = historicProcessInstance.getEndTime() == null ? false : true;
historyProcessInstanceVO.setCurrentActivityName(getCurrentName(historicProcessInstance.getId(), flag, historicProcessInstance.getProcessDefinitionId()));
historyProcessInstanceVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
long totalTimes = historicProcessInstance.getEndTime() == null ?
(Calendar.getInstance().getTimeInMillis() - historicProcessInstance.getStartTime().getTime()) :
(historicProcessInstance.getEndTime().getTime() - historicProcessInstance.getStartTime().getTime());
long dayCount = totalTimes / (1000 * 60 * 60 * 24);//计算天
long restTimes = totalTimes % (1000 * 60 * 60 * 24);//剩下的时间用于计于小时
long hourCount = restTimes / (1000 * 60 * 60);//小时
restTimes = restTimes % (1000 * 60 * 60);
long minuteCount = restTimes / (1000 * 60);
String spendTimes = dayCount + "天" + hourCount + "小时" + minuteCount + "分";
historyProcessInstanceVO.setDuration(spendTimes);
historyProcessInstanceVOS.add(historyProcessInstanceVO);
}
page.setRecords(historyProcessInstanceVOS);
page.setCurrent(applyDTO.getPageNo());
page.setSize(applyDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
/**
* 查看我的待办
*
* @return
*/
@Override
public Result<Page<TaskVO>> toDoList(TaskDTO taskDTO) {
List<Task> tasks = taskService.createTaskQuery().taskAssignee(taskDTO.getCurrentUserInfo().getId())
.includeProcessVariables()
.orderByTaskCreateTime().desc()
.listPage((taskDTO.getPageNo() - 1) * taskDTO.getPageSize(), taskDTO.getPageSize());
long count = taskService.createTaskQuery().taskAssignee(taskDTO.getCurrentUserInfo().getId()).count();
List<TaskVO> taskVOS = new ArrayList<>();
Page<TaskVO> page = new Page<>();
for (Task task : tasks) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Map<String, Object> processVariables = task.getProcessVariables();
TaskVO taskVO = new TaskVO();
taskVO.setTaskId(task.getId());
taskVO.setProcessInstanceId(task.getProcessInstanceId());
taskVO.setProcessDefinitionName(bpmnModel.getMainProcess().getName());
taskVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
taskVO.setStartTime(historicProcessInstance.getStartTime());
Execution execution = runtimeService.createExecutionQuery().executionId(task.getProcessInstanceId()).singleResult();
String activityId = execution.getActivityId();
if (StringUtils.isBlank(activityId)) {
taskVO.setCurrentActivityName("");
} else {
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(activityId);
taskVO.setCurrentActivityName(flowElement.getName());
}
taskVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
taskVO.setTaskCreatedTime(task.getCreateTime());
DelegationState delegationState = task.getDelegationState();
if (delegationState != null) {
taskVO.setDelegationState(delegationState);
}
taskVOS.add(taskVO);
}
page.setRecords(taskVOS);
page.setCurrent(taskDTO.getPageNo());
page.setSize(taskDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
/**
* 查看我的已办
*
* @return
*/
@Override
public Result<Page<TaskVO>> doneList(TaskDTO taskDTO) {
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(taskDTO.getCurrentUserInfo().getId())
.finished()
.includeProcessVariables()
.orderByTaskCreateTime().desc()
.listPage((taskDTO.getPageNo() - 1) * taskDTO.getPageSize(), taskDTO.getPageSize());
long count = historyService.createHistoricTaskInstanceQuery()
.taskAssignee(taskDTO.getCurrentUserInfo().getId()).count();
List<TaskVO> taskVOS = new ArrayList<>();
Page<TaskVO> page = new Page<>();
for (HistoricTaskInstance task : tasks) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
Boolean flag = historicProcessInstance.getEndTime() == null ? false : true;
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
Map<String, Object> processVariables = task.getProcessVariables();
TaskVO taskVO = new TaskVO();
taskVO.setTaskId(task.getId());
taskVO.setProcessInstanceId(task.getProcessInstanceId());
taskVO.setProcessDefinitionName(bpmnModel.getMainProcess().getName());
taskVO.setStartUser(JSONObject.parseObject(MapUtil.getStr(processVariables, START_USER_INFO), new TypeReference<UserInfo>() {
}));
taskVO.setStartTime(historicProcessInstance.getStartTime());
taskVO.setCurrentActivityName(getCurrentName(task.getProcessInstanceId(), flag, task.getProcessDefinitionId()));
taskVO.setBusinessStatus(MapUtil.getStr(processVariables, PROCESS_STATUS));
taskVO.setEndTime(task.getEndTime());
long totalTimes = task.getEndTime() == null ?
(Calendar.getInstance().getTimeInMillis() - task.getStartTime().getTime()) :
(task.getEndTime().getTime() - task.getStartTime().getTime());
long dayCount = totalTimes / (1000 * 60 * 60 * 24);//计算天
long restTimes = totalTimes % (1000 * 60 * 60 * 24);//剩下的时间用于计于小时
long hourCount = restTimes / (1000 * 60 * 60);//小时
restTimes = restTimes % (1000 * 60 * 60);
long minuteCount = restTimes / (1000 * 60);
String spendTimes = dayCount + "天" + hourCount + "小时" + minuteCount + "分";
taskVO.setDuration(spendTimes);
taskVOS.add(taskVO);
}
page.setRecords(taskVOS);
page.setCurrent(taskDTO.getPageNo());
page.setSize(taskDTO.getPageSize());
page.setTotal(count);
return Result.OK(page);
}
@Override
public Result agree(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);//设置进入当前流程
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.complete(task.getId());
return Result.OK();
}
@Override
public Result delegateTask(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
UserInfo delegateUserInfo = handleDataDTO.getDelegateUserInfo();
taskService.delegateTask(task.getId(), delegateUserInfo.getId());
return Result.OK();
}
@Override
public Result resolveTask(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
runtimeService.setVariables(task.getProcessInstanceId(), map);
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.resolveTask(taskId);
return Result.OK();
}
@Override
public Result refuse(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_3);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "拒绝");
return Result.OK();
}
@Override
public Result revoke(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_2);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "撤销");
return Result.OK();
}
@Override
public Result assignee(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
taskService.setAssignee(taskId, handleDataDTO.getTransferUserInfo().getId());
return Result.OK();
}
@Override
public Result rollback(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
String processInstanceId = handleDataDTO.getProcessInstanceId();
List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
Task task = null;
List<String> taskIds = new ArrayList<>();
for (Task task1 : list) {
if (task1.getId().equals(taskId)) {
task = task1;
}
taskIds.add(task1.getTaskDefinitionKey());
}
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_3);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(taskIds, handleDataDTO.getRollbackId())
.changeState();
return Result.OK();
}
@Override
public Result addMulti(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "opinion", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
Map<String, Object> variableMap = new HashMap<>();
variableMap.put("assigneeName", handleDataDTO.getMultiAddUserInfo().getId());
ExecutionEntity execution = (ExecutionEntity) runtimeService.addMultiInstanceExecution(task.getTaskDefinitionKey(), task.getProcessInstanceId(), variableMap);
return Result.OK();
}
@Override
public Result<List<MultiVO>> queryMultiUsersInfo(Map<String, Object> map) {
String taskId = MapUtil.getStr(map, "taskId");
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
List<Task> list = taskService.createTaskQuery()
.processInstanceId(task.getProcessInstanceId())
.taskDefinitionKey(task.getTaskDefinitionKey()).list();
Iterator<Task> iterator = list.iterator();
List<MultiVO> multiVOList = new ArrayList<>();
while (iterator.hasNext()) {
Task next = iterator.next();
if (!taskId.equals(next.getId())) {
MultiVO multiVO = new MultiVO();
multiVO.setTaskId(next.getId());
multiVO.setProcessInstanceId(next.getProcessInstanceId());
multiVO.setExecutionId(next.getExecutionId());
multiVO.setUserId(next.getAssignee());
multiVOList.add(multiVO);
}
}
return Result.OK(multiVOList);
}
@Override
public Result deleteMulti(List<String> executionIds) {
for (String executionId : executionIds) {
runtimeService.deleteMultiInstanceExecution(executionId, true);
}
return Result.OK();
}
@Override
public Result comments(HandleDataDTO handleDataDTO) {
UserInfo currentUserInfo = handleDataDTO.getCurrentUserInfo();
Authentication.setAuthenticatedUserId(currentUserInfo.getId());
List<AttachmentDTO> attachments = handleDataDTO.getAttachments();
String comments = handleDataDTO.getComments();
JSONObject formData = handleDataDTO.getFormData();
String taskId = handleDataDTO.getTaskId();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
Map<String, Object> map = new HashMap<>();
if (formData != null && formData.size() > 0) {
Map formValue = JSONObject.parseObject(formData.toJSONString(), new TypeReference<Map>() {
});
map.putAll(formValue);
map.put(FORM_VAR, formData);
}
map.put(PROCESS_STATUS, BUSINESS_STATUS_1);
runtimeService.setVariables(task.getProcessInstanceId(), map);
if (StringUtils.isNotBlank(comments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "comments", comments);
}
if (attachments != null && attachments.size() > 0) {
for (AttachmentDTO attachment : attachments) {
taskService.createAttachment("option", taskId, task.getProcessInstanceId(), attachment.getName(), attachment.getName(), attachment.getUrl());
}
}
if (StringUtils.isNotBlank(handleDataDTO.getSignInfo())) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), "sign", handleDataDTO.getSignInfo());
}
return Result.OK();
}
@Override
public Result<HandleDataVO> instanceInfo(HandleDataDTO HandleDataDTO) {
String processInstanceId = HandleDataDTO.getProcessInstanceId();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId)
.includeProcessVariables().singleResult();
String processDefinitionKey = historicProcessInstance.getProcessDefinitionKey();
ProcessTemplates processTemplates = processTemplateService.getById(processDefinitionKey.replace(PROCESS_PREFIX, ""));
processTemplates.setLogo(processTemplates.getIcon());
processTemplates.setFormId(processTemplates.getTemplateId());
processTemplates.setFormName(processTemplates.getTemplateName());
processTemplates.setProcessDefinitionId(historicProcessInstance.getProcessDefinitionId());
HandleDataVO handleDataVO = new HandleDataVO();
Map<String, Object> processVariables = historicProcessInstance.getProcessVariables();
handleDataVO.setProcessInstanceId(historicProcessInstance.getId());
JSONObject jsonObject = (JSONObject) processVariables.get(FORM_VAR);
handleDataVO.setFormData(jsonObject);
String process = processTemplates.getProcess();
ChildNode childNode = JSONObject.parseObject(process, new TypeReference<ChildNode>() {
});
SettingsInfo settingsInfo = JSONObject.parseObject(processTemplates.getSettings(), new TypeReference<SettingsInfo>() {
});
Boolean sign = settingsInfo.getSign();
ChildNode currentNode = null;
if (StringUtils.isNotBlank(HandleDataDTO.getTaskId())) {
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(HandleDataDTO.getTaskId()).singleResult();
currentNode = getChildNode(childNode, historicTaskInstance.getTaskDefinitionKey());
List<FormOperates> formPerms = currentNode.getProps().getFormPerms();
if (CollUtil.isNotEmpty(formPerms)) {
Iterator<FormOperates> iterator = formPerms.iterator();
while (iterator.hasNext()) {
FormOperates next = iterator.next();
if ("H".equals(next.getPerm())) {
iterator.remove();
if (jsonObject != null) {
jsonObject.remove(next.getId());
}
}
}
}
handleDataVO.setCurrentNode(currentNode);
handleDataVO.setTaskId(HandleDataDTO.getTaskId());
}
if (sign) {
handleDataVO.setSignFlag(true);
}
if (StringUtils.isNotBlank(HandleDataDTO.getTaskId())) {
if (currentNode != null) {
if (currentNode.getProps().getSign()) {
handleDataVO.setSignFlag(true);
} else {
handleDataVO.setSignFlag(false);
}
}
}
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(historicProcessInstance.getId()).list();
Map<String, List<HistoricActivityInstance>> historicActivityInstanceMap = new HashMap<>();
for (HistoricActivityInstance historicActivityInstance : list) {
List<HistoricActivityInstance> historicActivityInstances = historicActivityInstanceMap.get(historicActivityInstance.getActivityId());
if (historicActivityInstances == null) {
historicActivityInstances = new ArrayList<>();
historicActivityInstances.add(historicActivityInstance);
historicActivityInstanceMap.put(historicActivityInstance.getActivityId(), historicActivityInstances);
} else {
historicActivityInstances.add(historicActivityInstance);
historicActivityInstanceMap.put(historicActivityInstance.getActivityId(), historicActivityInstances);
}
}
Process mainProcess = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()).getMainProcess();
Collection<FlowElement> flowElements = mainProcess.getFlowElements();
List<String> runningList = new ArrayList<>();
handleDataVO.setRunningList(runningList);
List<String> endList = new ArrayList<>();
handleDataVO.setEndList(endList);
List<String> noTakeList = new ArrayList<>();
handleDataVO.setNoTakeList(noTakeList);
Map<String, List<TaskDetailVO>> deatailMap = new HashMap<>();
List<Comment> processInstanceComments = taskService.getProcessInstanceComments(historicProcessInstance.getId());
List<Attachment> processInstanceAttachments = taskService.getProcessInstanceAttachments(historicProcessInstance.getId());
for (FlowElement flowElement : flowElements) {
List<TaskDetailVO> detailVOList = new ArrayList<>();
List<HistoricActivityInstance> historicActivityInstanceList = historicActivityInstanceMap.get(flowElement.getId());
if (CollUtil.isNotEmpty(historicActivityInstanceList)) {
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
if (historicActivityInstance.getEndTime() != null) {
if ("startEvent".equalsIgnoreCase(historicActivityInstance.getActivityType()) || "endEvent".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
TaskDetailVO taskDetailVO = new TaskDetailVO();
taskDetailVO.setActivityId(historicActivityInstance.getActivityId());
taskDetailVO.setName(historicActivityInstance.getActivityName());
taskDetailVO.setCreateTime(historicActivityInstance.getStartTime());
taskDetailVO.setEndTime(historicActivityInstance.getEndTime());
detailVOList.add(taskDetailVO);
deatailMap.put(historicActivityInstance.getActivityId(), detailVOList);
endList.add(historicActivityInstance.getActivityId());
} else if ("userTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
List<TaskDetailVO> voList = deatailMap.get(historicActivityInstance.getActivityId());
List<HistoricActivityInstance> activityInstanceList = list.stream().filter(h -> h.getActivityId().equals(historicActivityInstance.getActivityId()) && h.getEndTime() != null).collect(Collectors.toList());
if (voList != null) {
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
} else {
voList = new ArrayList<>();
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
}
deatailMap.put(historicActivityInstance.getActivityId(), voList);
endList.add(historicActivityInstance.getActivityId());
} else if ("serviceTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
}
} else {
if ("userTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
List<TaskDetailVO> voList = deatailMap.get(historicActivityInstance.getActivityId());
List<HistoricActivityInstance> activityInstanceList = list.stream().filter(h -> h.getActivityId().equals(historicActivityInstance.getActivityId()) && h.getEndTime() == null).collect(Collectors.toList());
if (voList != null) {
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
} else {
voList = new ArrayList<>();
collectUserTaskInfo(processInstanceComments, processInstanceAttachments, historicActivityInstance, voList, activityInstanceList);
}
deatailMap.put(historicActivityInstance.getActivityId(), voList);
if (endList.contains(historicActivityInstance.getActivityId())) {
endList.remove(historicActivityInstance.getActivityId());
runningList.add(historicActivityInstance.getActivityId());
} else {
runningList.add(historicActivityInstance.getActivityId());
}
} else if ("serviceTask".equalsIgnoreCase(historicActivityInstance.getActivityType())) {
}
}
}
} else {
noTakeList.add(flowElement.getId());
}
}
handleDataVO.setProcessTemplates(processTemplates);
handleDataVO.setDetailVOList(deatailMap);
return Result.OK(handleDataVO);
}
// @Override
// public Result<AttachmentVO> upLoadFile(MultipartFile file, HttpServletRequest request) {
// MinioUploadUtil minioUploadUtil = SpringContextHolder.getBean(MinioUploadUtil.class);
// MinioClient minioClient = SpringContextHolder.getBean(MinioClient.class);
// AttachmentVO attachmentVO= new AttachmentVO();
// attachmentVO.setName(file.getOriginalFilename());
// minioUploadUtil.uploadFile(file, "java", file.getOriginalFilename());
// try {
// String url = minioClient.getPresignedObjectUrl(
// GetPresignedObjectUrlArgs.builder()
// .bucket("java")
// .object(file.getOriginalFilename())
// .expiry(7, TimeUnit.DAYS) // 设置5秒的超时时间。
// .method(Method.GET)
// .build());
// attachmentVO.setUrl(url);
// } catch (ErrorResponseException e) {
// e.printStackTrace();
// } catch (InsufficientDataException e) {
// e.printStackTrace();
// } catch (InternalException e) {
// e.printStackTrace();
// } catch (InvalidKeyException e) {
// e.printStackTrace();
// } catch (InvalidResponseException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// } catch (NoSuchAlgorithmException e) {
// e.printStackTrace();
// } catch (XmlParserException e) {
// e.printStackTrace();
// } catch (ServerException e) {
// e.printStackTrace();
// }
// return Result.OK(attachmentVO);
// }
//
// @Override
// public void downLoadFile(String name) {
// MinioUploadUtil minioUploadUtil = SpringContextHolder.getBean(MinioUploadUtil.class);
// minioUploadUtil.downFile(name,"java",name);
// }
private void collectUserTaskInfo(List<Comment> processInstanceComments,
List<Attachment> processInstanceAttachments,
HistoricActivityInstance historicActivityInstance,
List<TaskDetailVO> voList,
List<HistoricActivityInstance> activityInstanceList) {
for (HistoricActivityInstance activityInstance : activityInstanceList) {
TaskDetailVO taskDetailVO = new TaskDetailVO();
taskDetailVO.setTaskId(activityInstance.getTaskId());
taskDetailVO.setActivityId(activityInstance.getActivityId());
taskDetailVO.setName(activityInstance.getActivityName());
taskDetailVO.setCreateTime(activityInstance.getStartTime());
taskDetailVO.setEndTime(activityInstance.getEndTime());
Comment signComment = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("sign")).findFirst().orElse(null);
if (signComment != null) {
taskDetailVO.setSignImage(signComment.getFullMessage());
}
List<Attachment> attachments = processInstanceAttachments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(attachments)) {
List<AttachmentVO> attachmentVOList = new ArrayList<>();
for (Attachment attachment : attachments) {
AttachmentVO attachmentVO = new AttachmentVO();
attachmentVO.setId(attachment.getId());
attachmentVO.setName(attachment.getName());
attachmentVO.setUrl(attachment.getUrl());
attachmentVOList.add(attachmentVO);
}
taskDetailVO.setAttachmentVOList(attachmentVOList);
}
List<Comment> options = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("opinion")).collect(Collectors.toList());
if (CollUtil.isNotEmpty(options)) {
List<OptionVO> optionVOList = new ArrayList<>();
for (Comment option : options) {
OptionVO optionVO = new OptionVO();
optionVO.setComments(option.getFullMessage());
optionVO.setUserId(option.getUserId());
// optionVO.setUserName();
optionVO.setCreateTime(option.getTime());
optionVOList.add(optionVO);
}
taskDetailVO.setOptionVOList(optionVOList);
}
List<Comment> comments = processInstanceComments.stream().filter(h -> h.getTaskId().equals(historicActivityInstance.getTaskId()) && h.getType().equals("comments")).collect(Collectors.toList());
if (CollUtil.isNotEmpty(comments)) {
List<CommentVO> commentsVOList = new ArrayList<>();
for (Comment comment : comments) {
CommentVO commentVO = new CommentVO();
commentVO.setComments(comment.getFullMessage());
commentVO.setUserId(comment.getUserId());
// commentVO.setUserName();
commentVO.setCreateTime(comment.getTime());
commentsVOList.add(commentVO);
}
taskDetailVO.setCommentVOList(commentsVOList);
}
voList.add(taskDetailVO);
}
}
private String getCurrentName(String processInstanceId, Boolean flag, String processDefinitionId) {
if (flag) {
return "流程已结束";
}
Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();
String activityId = execution.getActivityId();
if (StringUtils.isBlank(activityId)) {
return "";
} else {
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(activityId);
return flowElement.getName();
}
}
}
package org.modules.junmpProcess.service.Repository;
import com.baomidou.mybatisplus.extension.service.IService;
import org.modules.junmpProcess.entity.Departments;
/**
* @author : willian fu
* @version : 1.0
*/
public interface DepartmentsService extends IService<Departments> {
}
package org.modules.junmpProcess.service.Repository;
import com.baomidou.mybatisplus.extension.service.IService;
import org.modules.junmpProcess.entity.FormGroups;
/**
* @author : willian fu
* @version : 1.0
*/
public interface FormGroupService extends IService<FormGroups> {
}
package org.modules.junmpProcess.service.Repository;
import com.baomidou.mybatisplus.extension.service.IService;
import org.modules.junmpProcess.entity.ProcessTemplates;
/**
* @author : willian fu
* @version : 1.0
*/
public interface ProcessTemplateService extends IService<ProcessTemplates> {
}
package org.modules.junmpProcess.service.Repository;
import com.baomidou.mybatisplus.extension.service.IService;
import org.modules.junmpProcess.entity.TemplateGroup;
/**
* @author : willian fu
* @version : 1.0
*/
public interface TemplateGroupService extends IService<TemplateGroup> {
}
package org.modules.junmpProcess.service.Repository;
import com.baomidou.mybatisplus.extension.service.IService;
import org.modules.junmpProcess.entity.Users;
/**
* @author : willian fu
* @version : 1.0
*/
public interface UserService extends IService<Users> {
}
package org.modules.junmpProcess.service.Repository;
/**
* @author : willian fu
* @version : 1.0
*/
public interface WorkspaceProcessService {
/**
* 获取用户可见表单
*
* @return
*/
Object getFormGroups(String name);
}
package org.modules.junmpProcess.service.Repository.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.modules.junmpProcess.entity.Departments;
import org.modules.junmpProcess.mapper.DepartmentsMapper;
import org.modules.junmpProcess.service.Repository.DepartmentsService;
import org.springframework.stereotype.Service;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
class DepartmentsServiceImpl extends ServiceImpl<DepartmentsMapper, Departments> implements
DepartmentsService {
}
package org.modules.junmpProcess.service.Repository.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.modules.junmpProcess.entity.FormGroups;
import org.modules.junmpProcess.mapper.FormGroupsMapper;
import org.modules.junmpProcess.service.Repository.FormGroupService;
import org.springframework.stereotype.Service;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class FormGroupServiceImpl extends ServiceImpl<FormGroupsMapper, FormGroups> implements
FormGroupService {
}
package org.modules.junmpProcess.service.Repository.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.modules.junmpProcess.entity.ProcessTemplates;
import org.modules.junmpProcess.mapper.ProcessTemplatesMapper;
import org.modules.junmpProcess.service.Repository.ProcessTemplateService;
import org.springframework.stereotype.Service;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class ProcessTemplateServiceImpl extends ServiceImpl<ProcessTemplatesMapper, ProcessTemplates> implements
ProcessTemplateService {
}
package org.modules.junmpProcess.service.Repository.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.modules.junmpProcess.entity.TemplateGroup;
import org.modules.junmpProcess.mapper.TemplateGroupMapper;
import org.modules.junmpProcess.service.Repository.TemplateGroupService;
import org.springframework.stereotype.Service;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class TemplateGroupServiceImpl extends ServiceImpl<TemplateGroupMapper, TemplateGroup> implements
TemplateGroupService {
}
package org.modules.junmpProcess.service.Repository.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.modules.junmpProcess.entity.Users;
import org.modules.junmpProcess.mapper.UsersMapper;
import org.modules.junmpProcess.service.Repository.UserService;
import org.springframework.stereotype.Service;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class UserServiceImpl extends ServiceImpl<UsersMapper, Users> implements UserService {
}
package org.modules.junmpProcess.service.Repository.impl;
import org.modules.junmpProcess.service.Bussiness.SettingService;
import org.modules.junmpProcess.service.Repository.WorkspaceProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author : willian fu
* @version : 1.0
*/
@Service
public class WorkspaceProcessServiceImpl implements WorkspaceProcessService {
@Autowired
private SettingService settingService;
/**
* 获取用户可见表单
*
* @return
*/
@Override
public Object getFormGroups(String name) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
// String token = CookieUtil.getCookieValue(servletRequestAttributes.getRequest(), "token");
return null;
}
}
package org.modules.junmpProcess.utils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.delegate.TaskListener;
import org.modules.junmpProcess.common.WorkFlowConstants;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.dto.json.ConditionInfo;
import org.modules.junmpProcess.dto.json.GroupsInfo;
import org.modules.junmpProcess.dto.json.Properties;
import org.modules.junmpProcess.enums.ModeEnums;
import org.modules.junmpProcess.exception.WorkFlowException;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_CLASS;
import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;
/**
* @author LoveMyOrange
* @create 2022-10-10 17:47
*/
public class BpmnModelUtils {
private static String id(String prefix) {
return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase();
}
private static ServiceTask serviceTask(String name) {
ServiceTask serviceTask = new ServiceTask();
serviceTask.setName(name);
return serviceTask;
}
public static SequenceFlow connect(String from, String to, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap, Process process) {
SequenceFlow flow = new SequenceFlow();
String sequenceFlowId = id("sequenceFlow");
if (process.getFlowElement(from) != null && process.getFlowElement(from) instanceof ExclusiveGateway) {
ChildNode childNode = childNodeMap.get(to);
if (childNode != null) {
String parentId = childNode.getParentId();
if (StringUtils.isNotBlank(parentId)) {
ChildNode parentNode = childNodeMap.get(parentId);
if (parentNode != null) {
if (Type.CONDITION.type.equals(parentNode.getType())) {
sequenceFlowId = parentNode.getId();
flow.setName(parentNode.getName());
if (Boolean.FALSE.equals(parentNode.getTypeElse())) {
//解析条件表达式
Properties props = parentNode.getProps();
String expression = props.getExpression();
List<GroupsInfo> groups = props.getGroups();
String groupsType = props.getGroupsType();
if (StringUtils.isNotBlank(expression)) {
flow.setConditionExpression("${" + expression + "}");
} else {
StringBuffer conditionExpression = new StringBuffer();
conditionExpression.append("${ ");
for (int i = 0; i < groups.size(); i++) {
conditionExpression.append(" ( ");
GroupsInfo group = groups.get(i);
List<String> cids = group.getCids();
String groupType = group.getGroupType();
List<ConditionInfo> conditions = group.getConditions();
for (int j = 0; j < conditions.size(); j++) {
conditionExpression.append(" ");
ConditionInfo condition = conditions.get(j);
String compare = condition.getCompare();
String id = condition.getId();
String title = condition.getTitle();
List<Object> value = condition.getValue();
String valueType = condition.getValueType();
if ("String".equals(valueType)) {
if ("=".equals(compare)) {
String str = StringUtils.join(value, ",");
str = "'" + str + "'";
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "strEqualsMethod(" + id + "," + str + ") ");
} else {
List<String> tempList = new ArrayList<>();
for (Object o : value) {
String s = o.toString();
s = "'" + s + "'";
tempList.add(s);
}
String str = StringUtils.join(tempList, ",");
// String str = StringUtils.join(value, ",");
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "strContainsMethod(" + id + "," + str + ") ");
}
} else if ("Number".equals(valueType)) {
String str = StringUtils.join(value, ",");
if ("=".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberEquals(" + id + "," + str + ") ");
} else if (">".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberGt(" + id + "," + str + ") ");
} else if (">=".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberGtEquals(" + id + "," + str + ") ");
} else if ("<".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberLt(" + id + "," + str + ") ");
} else if ("<=".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberLtEquals(" + id + "," + str + ") ");
} else if ("IN".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "numberContains(" + id + "," + str + ") ");
} else if ("B".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "b(" + id + "," + str + ") ");
} else if ("AB".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "ab(" + id + "," + str + ") ");
} else if ("BA".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "ba(" + id + "," + str + ") ");
} else if ("ABA".equals(compare)) {
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "aba(" + id + "," + str + ") ");
}
} else if ("User".equals(valueType)) {
List<String> userIds = new ArrayList<>();
for (Object o : value) {
JSONObject obj = (JSONObject) o;
userIds.add(obj.getString("id"));
}
String str = StringUtils.join(userIds, ",");
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "userStrContainsMethod(" + id + "," + str + ") ");
} else if ("Dept".equals(valueType)) {
List<String> userIds = new ArrayList<>();
for (Object o : value) {
JSONObject obj = (JSONObject) o;
userIds.add(obj.getString("id"));
}
String str = StringUtils.join(userIds, ",");
conditionExpression.append(" " + WorkFlowConstants.EXPRESSION_CLASS + "deptStrContainsMethod(" + id + "," + str + ") ");
} else {
continue;
}
if (conditions.size() > 1 && j != (conditions.size() - 1)) {
if ("OR".equals(groupType)) {
conditionExpression.append(" || ");
} else {
conditionExpression.append(" && ");
}
}
if (i == (conditions.size() - 1)) {
conditionExpression.append(" ");
}
}
conditionExpression.append(" ) ");
if (groups.size() > 1 && i != (groups.size() - 1)) {
if ("OR".equals(groupsType)) {
conditionExpression.append(" || ");
} else {
conditionExpression.append(" && ");
}
}
}
conditionExpression.append("} ");
flow.setConditionExpression(conditionExpression.toString());
}
}
}
}
}
}
}
flow.setId(sequenceFlowId);
flow.setSourceRef(from);
flow.setTargetRef(to);
sequenceFlows.add(flow);
return flow;
}
private static String stringEquals(ConditionInfo condition) {
return null;
}
public static StartEvent createStartEvent() {
StartEvent startEvent = new StartEvent();
startEvent.setId(WorkFlowConstants.START_EVENT_ID);
startEvent.setInitiator("applyUserId");
return startEvent;
}
public static EndEvent createEndEvent() {
EndEvent endEvent = new EndEvent();
endEvent.setId(WorkFlowConstants.END_EVENT_ID);
return endEvent;
}
// public static String FlowCreate(String fromId, FlowChildNode flowNode, Process process, BpmnModel bpmnModel, List<SequenceFlow> sequenceFlows, Map<String,ChildNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
// Integer nodeType = flowNode.getType();
// if (FlowType.CONCURRENTS.isEqual(nodeType)) {
// return createParallelGatewayBuilder(fromId, flowNode,process,bpmnModel,sequenceFlows,childNodeMap);
// } else if (FlowType.CONDITIONS.isEqual(nodeType)) {
// return createExclusiveGatewayBuilder(fromId, flowNode,process,bpmnModel,sequenceFlows,childNodeMap);
// } else if (FlowType.USER_TASK.isEqual(nodeType)) {
// childNodeMap.put(flowNode.getId(),flowNode);
// JSONObject incoming = flowNode.getIncoming();
// incoming.put("incoming", Collections.singletonList(fromId));
// String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
// // 如果当前任务还有后续任务,则遍历创建后续任务
// ChildNode children = flowNode.getChildren();
// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
// } else {
// return id;
// }
// }
// else if(Type.ROOT.isEqual(nodeType)){
// childNodeMap.put(flowNode.getId(),flowNode);
// JSONObject incoming = flowNode.getIncoming();
// incoming.put("incoming", Collections.singletonList(fromId));
// String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
// // 如果当前任务还有后续任务,则遍历创建后续任务
// ChildNode children = flowNode.getChildren();
// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
// } else {
// return id;
// }
// }
// else if(Type.DELAY.isEqual(nodeType)){
// throw new WorkFlowException("还不想写这个功能");
//// childNodeMap.put(flowNode.getId(),flowNode);
//// JSONObject incoming = flowNode.getIncoming();
//// incoming.put("incoming", Collections.singletonList(fromId));
//// String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
//// // 如果当前任务还有后续任务,则遍历创建后续任务
//// ChildNode children = flowNode.getChildren();
//// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
//// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
//// } else {
//// return id;
//// }
// }
// else if(Type.TRIGGER.isEqual(nodeType)){
// throw new WorkFlowException("还不想写这个功能");
// }
// else if(Type.CC.isEqual(nodeType)){
// throw new WorkFlowException("代码呗回滚了 丢了,暂时先不做");
//// childNodeMap.put(flowNode.getId(),flowNode);
//// JSONObject incoming = flowNode.getIncoming();
//// incoming.put("incoming", Collections.singletonList(fromId));
//// String id = createServiceTask(process,flowNode,sequenceFlows,childNodeMap);
//// // 如果当前任务还有后续任务,则遍历创建后续任务
//// ChildNode children = flowNode.getChildren();
//// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
//// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
//// } else {
//// return id;
//// }
// }
// else {
// throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
// }
// }
public static String create(String fromId, ChildNode flowNode, Process process, BpmnModel bpmnModel, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
String nodeType = flowNode.getType();
if (Type.CONCURRENTS.isEqual(nodeType)) {
return createParallelGatewayBuilder(fromId, flowNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else if (Type.CONDITIONS.isEqual(nodeType)) {
return createExclusiveGatewayBuilder(fromId, flowNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else if (Type.USER_TASK.isEqual(nodeType)) {
childNodeMap.put(flowNode.getId(), flowNode);
JSONObject incoming = flowNode.getIncoming();
incoming.put("incoming", Collections.singletonList(fromId));
String id = createTask(process, flowNode, sequenceFlows, childNodeMap);
// 如果当前任务还有后续任务,则遍历创建后续任务
ChildNode children = flowNode.getChildren();
if (Objects.nonNull(children) && StringUtils.isNotBlank(children.getId())) {
return create(id, children, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
return id;
}
} else if (Type.ROOT.isEqual(nodeType)) {
childNodeMap.put(flowNode.getId(), flowNode);
JSONObject incoming = flowNode.getIncoming();
incoming.put("incoming", Collections.singletonList(fromId));
String id = createTask(process, flowNode, sequenceFlows, childNodeMap);
// 如果当前任务还有后续任务,则遍历创建后续任务
ChildNode children = flowNode.getChildren();
if (Objects.nonNull(children) && StringUtils.isNotBlank(children.getId())) {
return create(id, children, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
return id;
}
} else if (Type.DELAY.isEqual(nodeType)) {
throw new WorkFlowException("还不想写这个功能");
// childNodeMap.put(flowNode.getId(),flowNode);
// JSONObject incoming = flowNode.getIncoming();
// incoming.put("incoming", Collections.singletonList(fromId));
// String id = createTask(process,flowNode,sequenceFlows,childNodeMap);
// // 如果当前任务还有后续任务,则遍历创建后续任务
// ChildNode children = flowNode.getChildren();
// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
// } else {
// return id;
// }
} else if (Type.TRIGGER.isEqual(nodeType)) {
throw new WorkFlowException("还不想写这个功能");
} else if (Type.CC.isEqual(nodeType)) {
throw new WorkFlowException("代码呗回滚了 丢了,暂时先不做");
// childNodeMap.put(flowNode.getId(),flowNode);
// JSONObject incoming = flowNode.getIncoming();
// incoming.put("incoming", Collections.singletonList(fromId));
// String id = createServiceTask(process,flowNode,sequenceFlows,childNodeMap);
// // 如果当前任务还有后续任务,则遍历创建后续任务
// ChildNode children = flowNode.getChildren();
// if (Objects.nonNull(children) &&StringUtils.isNotBlank(children.getId())) {
// return create(id, children,process,bpmnModel,sequenceFlows,childNodeMap);
// } else {
// return id;
// }
} else {
throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
}
}
private static String createExclusiveGatewayBuilder(String formId, ChildNode flowNode, Process process, BpmnModel bpmnModel, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
childNodeMap.put(flowNode.getId(), flowNode);
String name = flowNode.getName();
String exclusiveGatewayId = flowNode.getId();
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
exclusiveGateway.setId(exclusiveGatewayId);
exclusiveGateway.setName(name);
process.addFlowElement(exclusiveGateway);
process.addFlowElement(connect(formId, exclusiveGatewayId, sequenceFlows, childNodeMap, process));
if (Objects.isNull(flowNode.getBranchs()) && Objects.isNull(flowNode.getChildren())) {
return exclusiveGatewayId;
}
List<ChildNode> flowNodes = flowNode.getBranchs();
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
List<JSONObject> conditions = Lists.newCopyOnWriteArrayList();
for (ChildNode element : flowNodes) {
Boolean typeElse = element.getTypeElse();
if (Boolean.TRUE.equals(typeElse)) {
exclusiveGateway.setDefaultFlow(element.getId());
}
childNodeMap.put(element.getId(), element);
ChildNode childNode = element.getChildren();
String nodeName = element.getName();
Properties props = element.getProps();
String expression = props.getExpression();
if (Objects.isNull(childNode) || StringUtils.isBlank(childNode.getId())) {
incoming.add(exclusiveGatewayId);
JSONObject condition = new JSONObject();
condition.fluentPut("nodeName", nodeName)
.fluentPut("expression", expression)
.fluentPut("groups", props.getGroups())
.fluentPut("groupsType", props.getGroupsType()
)
.fluentPut("elseSequenceFlowId", element.getId());
conditions.add(condition);
continue;
}
// 只生成一个任务,同时设置当前任务的条件
JSONObject incomingObj = childNode.getIncoming();
incomingObj.put("incoming", Collections.singletonList(exclusiveGatewayId));
String identifier = create(exclusiveGatewayId, childNode, process, bpmnModel, sequenceFlows, childNodeMap);
List<SequenceFlow> flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef()))
.collect(Collectors.toList());
flows.stream().forEach(
e -> {
if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) {
e.setName(nodeName);
}
// 设置条件表达式
if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) {
e.setConditionExpression(expression);
}
}
);
if (Objects.nonNull(identifier)) {
incoming.add(identifier);
}
}
ChildNode childNode = flowNode.getChildren();
if (Objects.nonNull(childNode) && StringUtils.isNotBlank(childNode.getId())) {
String parentId = childNode.getParentId();
ChildNode parentChildNode = childNodeMap.get(parentId);
boolean conFlag = Type.CONCURRENTS.type
.equals(parentChildNode.getType());
if (!conFlag) {
String type = childNode.getType();
if (!Type.EMPTY.type.equals(type)) {
} else {
if (Type.CONDITIONS.type.equals(parentChildNode.getType())) {
String endExId = parentChildNode.getId() + "end";
process.addFlowElement(createExclusiveGateWayEnd(endExId));
if (incoming == null || incoming.isEmpty()) {
return create(exclusiveGatewayId, childNode, process, bpmnModel, sequenceFlows,
childNodeMap);
} else {
JSONObject incomingObj = childNode.getIncoming();
// 所有 service task 连接 end exclusive gateway
incomingObj.put("incoming", incoming);
FlowElement flowElement = bpmnModel.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
ChildNode nextNode = childNode.getChildren();
childNode.setChildren(null);
String identifier = endExId;
for (int i = 0; i < incoming.size(); i++) {
process.addFlowElement(connect(incoming.get(i), identifier, sequenceFlows, childNodeMap, process));
}
// 针对 gateway 空任务分支 添加条件表达式
if (!conditions.isEmpty()) {
FlowElement flowElement1 = bpmnModel.getFlowElement(identifier);
// 获取从 gateway 到目标节点 未设置条件表达式的节点
List<SequenceFlow> flows = sequenceFlows.stream().filter(
flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef()))
.filter(
flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId))
.collect(Collectors.toList());
flows.stream().forEach(sequenceFlow -> {
if (!conditions.isEmpty()) {
JSONObject condition = conditions.get(0);
String nodeName = condition.getString("nodeName");
String expression = condition.getString("expression");
if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils
.isNotBlank(nodeName)) {
sequenceFlow.setName(nodeName);
}
// 设置条件表达式
if (Objects.isNull(sequenceFlow.getConditionExpression())
&& StringUtils.isNotBlank(expression)) {
sequenceFlow.setConditionExpression(expression);
}
FlowElement flowElement2 = process.getFlowElement(sequenceFlow.getId());
if (flowElement2 != null) {
flowElement2.setId(condition.getString("elseSequenceFlowId"));
exclusiveGateway.setDefaultFlow(flowElement2.getId());
;
}
conditions.remove(0);
}
});
}
// 1.1 边连接完成后,在进行 nextNode 创建
if (Objects.nonNull(nextNode) && StringUtils.isNotBlank(nextNode.getId())) {
return create(identifier, nextNode, process, bpmnModel, sequenceFlows,
childNodeMap);
} else {
return identifier;
}
}
}
}
} else {
System.err.println("-");
}
}
return exclusiveGatewayId;
}
public static ExclusiveGateway createExclusiveGateWayEnd(String id) {
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
exclusiveGateway.setId(id);
return exclusiveGateway;
}
private static ParallelGateway createParallelGateWayEnd(String id) {
ParallelGateway parallelGateway = new ParallelGateway();
parallelGateway.setId(id);
return parallelGateway;
}
private static String createParallelGatewayBuilder(String formId, ChildNode flowNode, Process process, BpmnModel bpmnModel, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
childNodeMap.put(flowNode.getId(), flowNode);
String name = flowNode.getName();
ParallelGateway parallelGateway = new ParallelGateway();
String parallelGatewayId = flowNode.getId();
parallelGateway.setId(parallelGatewayId);
parallelGateway.setName(name);
process.addFlowElement(parallelGateway);
process.addFlowElement(connect(formId, parallelGatewayId, sequenceFlows, childNodeMap, process));
if (Objects.isNull(flowNode.getBranchs()) && Objects.isNull(flowNode.getChildren())) {
return parallelGatewayId;
}
List<ChildNode> flowNodes = flowNode.getBranchs();
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
for (ChildNode element : flowNodes) {
childNodeMap.put(element.getId(), element);
ChildNode childNode = element.getChildren();
if (Objects.isNull(childNode) || StringUtils.isBlank(childNode.getId())) {
incoming.add(parallelGatewayId);
continue;
}
String identifier = create(parallelGatewayId, childNode, process, bpmnModel, sequenceFlows, childNodeMap);
if (Objects.nonNull(identifier)) {
incoming.add(identifier);
}
}
ChildNode childNode = flowNode.getChildren();
if (Objects.nonNull(childNode) && StringUtils.isNotBlank(childNode.getId())) {
String parentId = childNode.getParentId();
ChildNode parentChildNode = childNodeMap.get(parentId);
boolean conFlag = Type.CONCURRENTS.type
.equals(parentChildNode.getType());
if (!conFlag) {
String type = childNode.getType();
if (!Type.EMPTY.type.equals(type)) {
} else {
if (Type.CONCURRENTS.type.equals(parentChildNode.getType())) {
String endExId = parentChildNode.getId() + "end";
process.addFlowElement(createParallelGateWayEnd(endExId));
// 普通结束网关
if (CollectionUtils.isEmpty(incoming)) {
return create(parallelGatewayId, childNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
JSONObject incomingObj = childNode.getIncoming();
// 所有 service task 连接 end parallel gateway
incomingObj.put("incoming", incoming);
FlowElement flowElement = bpmnModel.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
ChildNode nextNode = childNode.getChildren();
childNode.setChildren(null);
String identifier = endExId;
for (int i = 0; i < incoming.size(); i++) {
FlowElement flowElement1 = bpmnModel.getFlowElement(incoming.get(i));
process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows, childNodeMap, process));
}
// 1.1 边连接完成后,在进行 nextNode 创建
if (Objects.nonNull(nextNode) && StringUtils.isNotBlank(nextNode.getId())) {
return create(identifier, nextNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
return identifier;
}
}
}
}
} else {
String type = childNode.getType();
if (!Type.EMPTY.type.equals(type)) {
} else {
if (Type.CONCURRENTS.type.equals(parentChildNode.getType())) {
String endExId = parentChildNode.getId() + "end";
process.addFlowElement(createParallelGateWayEnd(endExId));
// 普通结束网关
if (CollectionUtils.isEmpty(incoming)) {
return create(parallelGatewayId, childNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
JSONObject incomingObj = childNode.getIncoming();
// 所有 service task 连接 end parallel gateway
incomingObj.put("incoming", incoming);
FlowElement flowElement = bpmnModel.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
ChildNode nextNode = childNode.getChildren();
childNode.setChildren(null);
String identifier = endExId;
for (int i = 0; i < incoming.size(); i++) {
FlowElement flowElement1 = bpmnModel.getFlowElement(incoming.get(i));
process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows, childNodeMap, process));
}
// 1.1 边连接完成后,在进行 nextNode 创建
if (Objects.nonNull(nextNode) && StringUtils.isNotBlank(nextNode.getId())) {
return create(identifier, nextNode, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
return identifier;
}
}
}
}
}
}
return parallelGatewayId;
}
private static String createTask(Process process, ChildNode flowNode, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap) {
JSONObject incomingJson = flowNode.getIncoming();
List<String> incoming = incomingJson.getJSONArray("incoming").toJavaList(String.class);
// 自动生成id
// String id = id("serviceTask");
String id = flowNode.getId();
if (incoming != null && !incoming.isEmpty()) {
UserTask userTask = new UserTask();
userTask.setName(flowNode.getName());
userTask.setId(id);
process.addFlowElement(userTask);
process.addFlowElement(connect(incoming.get(0), id, sequenceFlows, childNodeMap, process));
ArrayList<FlowableListener> taskListeners = new ArrayList<>();
FlowableListener taskListener = new FlowableListener();
// 事件类型,
taskListener.setEvent(TaskListener.EVENTNAME_CREATE);
// 监听器类型
taskListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
// 设置实现了,这里设置监听器的类型是delegateExpression,这样可以在实现类注入Spring bean.
taskListener.setImplementation("${taskCreatedListener}");
taskListeners.add(taskListener);
userTask.setTaskListeners(taskListeners);
if ("root".equalsIgnoreCase(id)) {
} else {
ArrayList<FlowableListener> listeners = new ArrayList<>();
FlowableListener activitiListener = new FlowableListener();
// 事件类型,
activitiListener.setEvent(ExecutionListener.EVENTNAME_START);
// 监听器类型
activitiListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
// 设置实现了,这里设置监听器的类型是delegateExpression,这样可以在实现类注入Spring bean.
activitiListener.setImplementation("${counterSignListener}");
listeners.add(activitiListener);
userTask.setExecutionListeners(listeners);
Properties props = flowNode.getProps();
String mode = props.getMode();
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
// 审批人集合参数
multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + "assigneeList");
// 迭代集合
multiInstanceLoopCharacteristics.setElementVariable("assigneeName");
// 并行
multiInstanceLoopCharacteristics.setSequential(false);
userTask.setAssignee("${assigneeName}");
// 设置多实例属性
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
if (ModeEnums.OR.getTypeName().equals(mode)) {
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}");
} else if (ModeEnums.NEXT.getTypeName().equals(mode)) {
multiInstanceLoopCharacteristics.setSequential(true);
}
JSONObject timeLimit = props.getTimeLimit();
if (timeLimit != null && !timeLimit.isEmpty()) {
JSONObject timeout = timeLimit.getJSONObject("timeout");
if (timeout != null && !timeout.isEmpty()) {
String unit = timeout.getString("unit");
Integer value = timeout.getInteger("value");
if (value > 0) {
List<BoundaryEvent> boundaryEvents = new ArrayList<>();
BoundaryEvent boundaryEvent = new BoundaryEvent();
boundaryEvent.setId(id("boundaryEvent"));
boundaryEvent.setAttachedToRefId(id);
boundaryEvent.setAttachedToRef(userTask);
boundaryEvent.setCancelActivity(Boolean.TRUE);
TimerEventDefinition timerEventDefinition = new TimerEventDefinition();
timerEventDefinition.setTimeDuration("PT" + 1 + "M");
timerEventDefinition.setId(id("timerEventDefinition"));
boundaryEvent.addEventDefinition(timerEventDefinition);
FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(ExecutionListener.EVENTNAME_END);
flowableListener.setImplementationType(IMPLEMENTATION_TYPE_CLASS);
flowableListener.setImplementation("com.dingding.mid.listener.TimerListener");
List<FlowableListener> listenerList = new ArrayList<>();
listenerList.add(flowableListener);
boundaryEvent.setExecutionListeners(listenerList);
process.addFlowElement(boundaryEvent);
boundaryEvents.add(boundaryEvent);
userTask.setBoundaryEvents(boundaryEvents);
}
}
}
}
}
return id;
}
private static String createServiceTask(Process process, ChildNode flowNode, List<SequenceFlow> sequenceFlows, Map<String, ChildNode> childNodeMap) {
JSONObject incomingJson = flowNode.getIncoming();
List<String> incoming = incomingJson.getJSONArray("incoming").toJavaList(String.class);
String id = flowNode.getId();
if (incoming != null && !incoming.isEmpty()) {
}
return id;
}
private enum Type {
/**
* 并行事件
*/
CONCURRENTS("CONCURRENTS", ParallelGateway.class),
CONCURRENT("CONCURRENT", SequenceFlow.class),
/**
* 排他事件
*/
CONDITION("CONDITION", ExclusiveGateway.class),
CONDITIONS("CONDITIONS", ExclusiveGateway.class),
/**
* 任务
*/
USER_TASK("APPROVAL", UserTask.class),
EMPTY("EMPTY", Object.class),
ROOT("ROOT", UserTask.class),
CC("CC", ServiceTask.class),
TRIGGER("TRIGGER", ServiceTask.class),
DELAY("DELAY", IntermediateCatchEvent.class);
private String type;
private Class<?> typeClass;
Type(String type, Class<?> typeClass) {
this.type = type;
this.typeClass = typeClass;
}
public final static Map<String, Class<?>> TYPE_MAP = Maps.newHashMap();
static {
for (Type element : Type.values()) {
TYPE_MAP.put(element.type, element.typeClass);
}
}
public boolean isEqual(String type) {
return this.type.equals(type);
}
}
private enum FlowType {
/**
* 并行事件
*/
CONCURRENTS(0, ParallelGateway.class),
CONCURRENT(1, SequenceFlow.class),
/**
* 排他事件
*/
CONDITION(2, ExclusiveGateway.class),
CONDITIONS(3, ExclusiveGateway.class),
/**
* 任务
*/
USER_TASK(4, UserTask.class),
EMPTY(5, Object.class),
ROOT(6, UserTask.class),
CC(7, ServiceTask.class),
TRIGGER(8, ServiceTask.class),
DELAY(9, IntermediateCatchEvent.class);
private int type;
private Class<?> typeClass;
FlowType(int type, Class<?> typeClass) {
this.type = type;
this.typeClass = typeClass;
}
public final static Map<String, Class<?>> TYPE_MAP = Maps.newHashMap();
static {
for (Type element : Type.values()) {
TYPE_MAP.put(element.type, element.typeClass);
}
}
public boolean isEqual(int type) {
return this.type == (type);
}
}
public static ChildNode getChildNode(ChildNode childNode, String nodeId) {
Map<String, ChildNode> childNodeMap = new HashMap<>();
if (StringUtils.isNotBlank(childNode.getId())) {
getChildNode(childNode, childNodeMap);
}
Set<String> set = childNodeMap.keySet();
for (String s : set) {
if (StringUtils.isNotBlank(s)) {
if (s.equals(nodeId)) {
return childNodeMap.get(s);
}
}
}
return null;
}
private static void getChildNode(ChildNode childNode, Map<String, ChildNode> childNodeMap) {
childNodeMap.put(childNode.getId(), childNode);
List<ChildNode> branchs = childNode.getBranchs();
ChildNode children = childNode.getChildren();
if (branchs != null && branchs.size() > 0) {
for (ChildNode branch : branchs) {
if (StringUtils.isNotBlank(branch.getId())) {
childNodeMap.put(branch.getId(), branch);
getChildNode(branch, childNodeMap);
}
}
}
if (children != null) {
childNodeMap.put(children.getId(), children);
getChildNode(children, childNodeMap);
}
}
}
package org.modules.junmpProcess.utils;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* 类描述:时间操作定义类
*
* @Author: 张代浩
* @Date:2012-12-8 12:15:03
* @Version 1.0
*/
public class DateUtils extends PropertyEditorSupport {
public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy年MM月dd日");
}
};
public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm");
}
};
public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyyMMddHHmmss");
}
};
public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("HH:mm");
}
};
public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
// 以毫秒表示的时间
private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
private static final long HOUR_IN_MILLIS = 3600 * 1000;
private static final long MINUTE_IN_MILLIS = 60 * 1000;
private static final long SECOND_IN_MILLIS = 1000;
// 指定模式的时间格式
private static SimpleDateFormat getSDFormat(String pattern) {
return new SimpleDateFormat(pattern);
}
/**
* 当前日历,这里用中国时间表示
*
* @return 以当地时区表示的系统当前日历
*/
public static Calendar getCalendar() {
return Calendar.getInstance();
}
/**
* 指定毫秒数表示的日历
*
* @param millis 毫秒数
* @return 指定毫秒数表示的日历
*/
public static Calendar getCalendar(long millis) {
Calendar cal = Calendar.getInstance();
// --------------------cal.setTimeInMillis(millis);
cal.setTime(new Date(millis));
return cal;
}
// ////////////////////////////////////////////////////////////////////////////
// getDate
// 各种方式获取的Date
// ////////////////////////////////////////////////////////////////////////////
/**
* 当前日期
*
* @return 系统当前时间
*/
public static Date getDate() {
return new Date();
}
/**
* 指定毫秒数表示的日期
*
* @param millis 毫秒数
* @return 指定毫秒数表示的日期
*/
public static Date getDate(long millis) {
return new Date(millis);
}
/**
* 时间戳转换为字符串
*
* @param time
* @return
*/
public static String timestamptoStr(Timestamp time) {
Date date = null;
if (null != time) {
date = new Date(time.getTime());
}
return date2Str(date_sdf.get());
}
/**
* 字符串转换时间戳
*
* @param str
* @return
*/
public static Timestamp str2Timestamp(String str) {
Date date = str2Date(str, date_sdf.get());
return new Timestamp(date.getTime());
}
/**
* 字符串转换成日期
*
* @param str
* @param sdf
* @return
*/
public static Date str2Date(String str, SimpleDateFormat sdf) {
if (null == str || "".equals(str)) {
return null;
}
Date date = null;
try {
date = sdf.parse(str);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
/**
* 日期转换为字符串
*
* @param date_sdf 日期格式
* @return 字符串
*/
public static String date2Str(SimpleDateFormat date_sdf) {
Date date = getDate();
if (null == date) {
return null;
}
return date_sdf.format(date);
}
/**
* 格式化时间
*
* @param date
* @param format
* @return
*/
public static String dateformat(String date, String format) {
SimpleDateFormat sformat = new SimpleDateFormat(format);
Date _date = null;
try {
_date = sformat.parse(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sformat.format(_date);
}
/**
* 日期转换为字符串
*
* @param date 日期
* @param date_sdf 日期格式
* @return 字符串
*/
public static String date2Str(Date date, SimpleDateFormat date_sdf) {
if (null == date) {
return null;
}
return date_sdf.format(date);
}
/**
* 日期转换为字符串
*
* @param format 日期格式
* @return 字符串
*/
public static String getDate(String format) {
Date date = new Date();
if (null == date) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(date);
}
/**
* 指定毫秒数的时间戳
*
* @param millis 毫秒数
* @return 指定毫秒数的时间戳
*/
public static Timestamp getTimestamp(long millis) {
return new Timestamp(millis);
}
/**
* 以字符形式表示的时间戳
*
* @param time 毫秒数
* @return 以字符形式表示的时间戳
*/
public static Timestamp getTimestamp(String time) {
return new Timestamp(Long.parseLong(time));
}
/**
* 系统当前的时间戳
*
* @return 系统当前的时间戳
*/
public static Timestamp getTimestamp() {
return new Timestamp(System.currentTimeMillis());
}
/**
* 当前时间,格式 yyyy-MM-dd HH:mm:ss
*
* @return 当前时间的标准形式字符串
*/
public static String now() {
return datetimeFormat.get().format(getCalendar().getTime());
}
/**
* 指定日期的时间戳
*
* @param date 指定日期
* @return 指定日期的时间戳
*/
public static Timestamp getTimestamp(Date date) {
return new Timestamp(date.getTime());
}
/**
* 指定日历的时间戳
*
* @param cal 指定日历
* @return 指定日历的时间戳
*/
public static Timestamp getCalendarTimestamp(Calendar cal) {
// ---------------------return new Timestamp(cal.getTimeInMillis());
return new Timestamp(cal.getTime().getTime());
}
public static Timestamp gettimestamp() {
Date dt = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowTime = df.format(dt);
Timestamp buydate = Timestamp.valueOf(nowTime);
return buydate;
}
// ////////////////////////////////////////////////////////////////////////////
// getMillis
// 各种方式获取的Millis
// ////////////////////////////////////////////////////////////////////////////
/**
* 系统时间的毫秒数
*
* @return 系统时间的毫秒数
*/
public static long getMillis() {
return System.currentTimeMillis();
}
/**
* 指定日历的毫秒数
*
* @param cal 指定日历
* @return 指定日历的毫秒数
*/
public static long getMillis(Calendar cal) {
// --------------------return cal.getTimeInMillis();
return cal.getTime().getTime();
}
/**
* 指定日期的毫秒数
*
* @param date 指定日期
* @return 指定日期的毫秒数
*/
public static long getMillis(Date date) {
return date.getTime();
}
/**
* 指定时间戳的毫秒数
*
* @param ts 指定时间戳
* @return 指定时间戳的毫秒数
*/
public static long getMillis(Timestamp ts) {
return ts.getTime();
}
// ////////////////////////////////////////////////////////////////////////////
// formatDate
// 将日期按照一定的格式转化为字符串
// ////////////////////////////////////////////////////////////////////////////
/**
* 默认方式表示的系统当前日期,具体格式:年-月-日
*
* @return 默认日期按“年-月-日“格式显示
*/
public static String formatDate() {
return date_sdf.get().format(getCalendar().getTime());
}
/**
* 默认方式表示的系统当前日期,具体格式:yyyy-MM-dd HH:mm:ss
*
* @return 默认日期按“yyyy-MM-dd HH:mm:ss“格式显示
*/
public static String formatDateTime() {
return datetimeFormat.get().format(getCalendar().getTime());
}
/**
* 获取时间字符串
*/
public static String getDataString(SimpleDateFormat formatstr) {
return formatstr.format(getCalendar().getTime());
}
/**
* 指定日期的默认显示,具体格式:年-月-日
*
* @param cal 指定的日期
* @return 指定日期按“年-月-日“格式显示
*/
public static String formatDate(Calendar cal) {
return date_sdf.get().format(cal.getTime());
}
/**
* 指定日期的默认显示,具体格式:年-月-日
*
* @param date 指定的日期
* @return 指定日期按“年-月-日“格式显示
*/
public static String formatDate(Date date) {
return date_sdf.get().format(date);
}
/**
* 指定毫秒数表示日期的默认显示,具体格式:年-月-日
*
* @param millis 指定的毫秒数
* @return 指定毫秒数表示日期按“年-月-日“格式显示
*/
public static String formatDate(long millis) {
return date_sdf.get().format(new Date(millis));
}
/**
* 默认日期按指定格式显示
*
* @param pattern 指定的格式
* @return 默认日期按指定格式显示
*/
public static String formatDate(String pattern) {
return getSDFormat(pattern).format(getCalendar().getTime());
}
/**
* 指定日期按指定格式显示
*
* @param cal 指定的日期
* @param pattern 指定的格式
* @return 指定日期按指定格式显示
*/
public static String formatDate(Calendar cal, String pattern) {
return getSDFormat(pattern).format(cal.getTime());
}
/**
* 指定日期按指定格式显示
*
* @param date 指定的日期
* @param pattern 指定的格式
* @return 指定日期按指定格式显示
*/
public static String formatDate(Date date, String pattern) {
return getSDFormat(pattern).format(date);
}
// ////////////////////////////////////////////////////////////////////////////
// formatTime
// 将日期按照一定的格式转化为字符串
// ////////////////////////////////////////////////////////////////////////////
/**
* 默认方式表示的系统当前日期,具体格式:年-月-日 时:分
*
* @return 默认日期按“年-月-日 时:分“格式显示
*/
public static String formatTime() {
return time_sdf.get().format(getCalendar().getTime());
}
/**
* 指定毫秒数表示日期的默认显示,具体格式:年-月-日 时:分
*
* @param millis 指定的毫秒数
* @return 指定毫秒数表示日期按“年-月-日 时:分“格式显示
*/
public static String formatTime(long millis) {
return time_sdf.get().format(new Date(millis));
}
/**
* 指定日期的默认显示,具体格式:年-月-日 时:分
*
* @param cal 指定的日期
* @return 指定日期按“年-月-日 时:分“格式显示
*/
public static String formatTime(Calendar cal) {
return time_sdf.get().format(cal.getTime());
}
/**
* 指定日期的默认显示,具体格式:年-月-日 时:分
*
* @param date 指定的日期
* @return 指定日期按“年-月-日 时:分“格式显示
*/
public static String formatTime(Date date) {
return time_sdf.get().format(date);
}
// ////////////////////////////////////////////////////////////////////////////
// formatShortTime
// 将日期按照一定的格式转化为字符串
// ////////////////////////////////////////////////////////////////////////////
/**
* 默认方式表示的系统当前日期,具体格式:时:分
*
* @return 默认日期按“时:分“格式显示
*/
public static String formatShortTime() {
return short_time_sdf.get().format(getCalendar().getTime());
}
/**
* 指定毫秒数表示日期的默认显示,具体格式:时:分
*
* @param millis 指定的毫秒数
* @return 指定毫秒数表示日期按“时:分“格式显示
*/
public static String formatShortTime(long millis) {
return short_time_sdf.get().format(new Date(millis));
}
/**
* 指定日期的默认显示,具体格式:时:分
*
* @param cal 指定的日期
* @return 指定日期按“时:分“格式显示
*/
public static String formatShortTime(Calendar cal) {
return short_time_sdf.get().format(cal.getTime());
}
/**
* 指定日期的默认显示,具体格式:时:分
*
* @param date 指定的日期
* @return 指定日期按“时:分“格式显示
*/
public static String formatShortTime(Date date) {
return short_time_sdf.get().format(date);
}
// ////////////////////////////////////////////////////////////////////////////
// parseDate
// parseCalendar
// parseTimestamp
// 将字符串按照一定的格式转化为日期或时间
// ////////////////////////////////////////////////////////////////////////////
/**
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
*
* @param src 将要转换的原始字符窜
* @param pattern 转换的匹配格式
* @return 如果转换成功则返回转换后的日期
* @throws ParseException
*/
public static Date parseDate(String src, String pattern) throws ParseException {
return getSDFormat(pattern).parse(src);
}
/**
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
*
* @param src 将要转换的原始字符窜
* @param pattern 转换的匹配格式
* @return 如果转换成功则返回转换后的日期
* @throws ParseException
*/
public static Calendar parseCalendar(String src, String pattern) throws ParseException {
Date date = parseDate(src, pattern);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
Calendar cal;
cal = parseCalendar(src, pattern);
cal.add(Calendar.DATE, amount);
return formatDate(cal);
}
/**
* 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
*
* @param src 将要转换的原始字符窜
* @param pattern 转换的匹配格式
* @return 如果转换成功则返回转换后的时间戳
* @throws ParseException
*/
public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
Date date = parseDate(src, pattern);
return new Timestamp(date.getTime());
}
// ////////////////////////////////////////////////////////////////////////////
// dateDiff
// 计算两个日期之间的差值
// ////////////////////////////////////////////////////////////////////////////
/**
* 计算两个时间之间的差值,根据标志的不同而不同
*
* @param flag 计算标志,表示按照年/月/日/时/分/秒等计算
* @param calSrc 减数
* @param calDes 被减数
* @return 两个日期之间的差值
*/
public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {
long millisDiff = getMillis(calSrc) - getMillis(calDes);
if (flag == 'y') {
return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
}
if (flag == 'd') {
return (int) (millisDiff / DAY_IN_MILLIS);
}
if (flag == 'h') {
return (int) (millisDiff / HOUR_IN_MILLIS);
}
if (flag == 'm') {
return (int) (millisDiff / MINUTE_IN_MILLIS);
}
if (flag == 's') {
return (int) (millisDiff / SECOND_IN_MILLIS);
}
return 0;
}
/**
* String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
* HH:mm:ss“ * @param text String类型的时间值
*/
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
try {
if (text.indexOf(":") == -1 && text.length() == 10) {
setValue(DateUtils.date_sdf.get().parse(text));
} else if (text.indexOf(":") > 0 && text.length() == 19) {
setValue(DateUtils.datetimeFormat.get().parse(text));
} else {
throw new IllegalArgumentException("Could not parse date, date format is error ");
}
} catch (ParseException ex) {
IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
iae.initCause(ex);
throw iae;
}
} else {
setValue(null);
}
}
public static int getYear() {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(getDate());
return calendar.get(Calendar.YEAR);
}
}
package org.modules.junmpProcess.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.modules.junmpProcess.dto.json.UserInfo;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @author LoveMyOrange
* @create 2022-10-16 22:13
*/
@Component
public class ExUtils {
public Boolean strEqualsMethod(String controlId, String value) {
List<String> list = Arrays.asList(value);
String s = list.get(0);
return s.equals(controlId);
}
public Boolean strEqualsMethod(String controlId, String... values) {
List<String> list = Arrays.asList(values);
if (list.size() > 1) {
return Boolean.FALSE;
} else {
String s = list.get(0);
return s.equals(controlId);
}
}
public Boolean strContains(String controlId, String... values) {
List<String> list = Arrays.asList(values);
return list.contains(controlId);
}
public Boolean strContains(String controlId, Number... values) {
Long aLong = Long.valueOf(controlId);
List<Number> numbers = Arrays.asList(values);
return numbers.contains(aLong);
}
public Boolean strContainsMethod(String controlId, String... values) {
List<String> strings = Arrays.asList(values);
return strings.contains(controlId);
}
public Boolean userStrContainsMethod(String controlId, String... values) {
List<String> strings = Arrays.asList(values);
List<UserInfo> userInfos = JSONObject.parseObject(controlId, new TypeReference<List<UserInfo>>() {
});
List<String> idsList = new ArrayList<>();
for (UserInfo userInfo : userInfos) {
idsList.add(userInfo.getId());
}
Collection<String> intersection = CollUtil.intersection(strings, idsList);
if (CollUtil.isEmpty(intersection)) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
public Boolean deptStrContainsMethod(String controlId, String... values) {
List<String> strings = Arrays.asList(values);
List<UserInfo> userInfos = JSONObject.parseObject(controlId, new TypeReference<List<UserInfo>>() {
});
List<String> idsList = new ArrayList<>();
for (UserInfo userInfo : userInfos) {
idsList.add(userInfo.getId());
}
Collection<String> intersection = CollUtil.intersection(strings, idsList);
if (CollUtil.isEmpty(intersection)) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
public Boolean numberContains(Number controlId, Number... values) {
List<Number> list = Arrays.asList(values);
return list.contains(controlId);
}
public Boolean b(String controlId, Number... values) {
List<Number> numbers = Arrays.asList(values);
Long aLong = Long.valueOf(controlId);
if (aLong > numbers.get(0).longValue() && aLong < numbers.get(1).longValue()) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public Boolean ab(String controlId, Number... values) {
List<Number> numbers = Arrays.asList(values);
Long aLong = Long.valueOf(controlId);
if (aLong >= numbers.get(0).longValue() && aLong < numbers.get(1).longValue()) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public Boolean ba(String controlId, Number... values) {
List<Number> numbers = Arrays.asList(values);
Long aLong = Long.valueOf(controlId);
if (aLong > numbers.get(0).longValue() && aLong <= numbers.get(1).longValue()) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public Boolean aba(String controlId, Number... values) {
List<Number> numbers = Arrays.asList(values);
Long aLong = Long.valueOf(controlId);
if (aLong >= numbers.get(0).longValue() && aLong <= numbers.get(1).longValue()) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
/**
* conditionExpression.append(" "+ EXPRESSION_CLASS+"numberEquals("+id+","+str+") " );
* conditionExpression.append(" "+ EXPRESSION_CLASS+"numberGt("+id+","+str+") " );
* conditionExpression.append(" "+ EXPRESSION_CLASS+"numberGtEquals("+id+","+str+") " );
* conditionExpression.append(" "+ EXPRESSION_CLASS+"numberLt("+id+","+str+") " );
* conditionExpression.append(" "+ EXPRESSION_CLASS+"numberLtEquals("+id+","+str+") " );
*/
public Boolean numberEquals(String controlId, String value) {
Double a = Double.valueOf(controlId);
Double b = Double.valueOf(value);
boolean equals = a.equals(b);
return equals;
}
public Boolean numberGt(String controlId, String value) {
Double a = Double.valueOf(controlId);
BigDecimal a1 = BigDecimal.valueOf(a);
Double b = Double.valueOf(value);
BigDecimal a2 = BigDecimal.valueOf(b);
boolean greater = NumberUtil.isGreater(a1, a2);
return greater;
}
public Boolean numberGtEquals(String controlId, String value) {
Double a = Double.valueOf(controlId);
BigDecimal a1 = BigDecimal.valueOf(a);
Double b = Double.valueOf(value);
BigDecimal a2 = BigDecimal.valueOf(b);
boolean greater = NumberUtil.isGreaterOrEqual(a1, a2);
return greater;
}
public Boolean numberLt(String controlId, String value) {
Double a = Double.valueOf(controlId);
BigDecimal a1 = BigDecimal.valueOf(a);
Double b = Double.valueOf(value);
BigDecimal a2 = BigDecimal.valueOf(b);
boolean greater = NumberUtil.isLess(a1, a2);
return greater;
}
public Boolean numberLtEquals(String controlId, String value) {
Double a = Double.valueOf(controlId);
BigDecimal a1 = BigDecimal.valueOf(a);
Double b = Double.valueOf(value);
BigDecimal a2 = BigDecimal.valueOf(b);
boolean greater = NumberUtil.isLessOrEqual(a1, a2);
return greater;
}
}
//package org.modules.junmpProcess.utils;
//
//import lombok.Cleanup;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.fileupload.FileItem;
//import org.apache.commons.fileupload.FileItemFactory;
//import org.apache.commons.fileupload.disk.DiskFileItem;
//import org.apache.commons.fileupload.disk.DiskFileItemFactory;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.web.multipart.MultipartFile;
//import org.springframework.web.multipart.commons.CommonsMultipartFile;
//
//import java.io.*;
//import java.text.DateFormat;
//import java.text.DecimalFormat;
//import java.text.SimpleDateFormat;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Date;
//import java.util.List;
//import java.util.zip.ZipEntry;
//import java.util.zip.ZipOutputStream;
//
///**
// *
// */
//@Slf4j
//@SuppressWarnings("all")
//public class FileUtil {
//
// /**
// * 判断文件夹是否存在
// *
// * @param filePath 文件地址
// * @return
// */
// public static boolean fileIsExists(String filePath) {
// File f = new File(XSSEscape.escapePath(filePath));
// if (!f.exists()) {
// return false;
// }
// return true;
// }
//
// /**
// * 判断文件是否存在
// *
// * @param filePath
// * @return
// */
// public static boolean fileIsFile(String filePath) {
// File f = new File(XSSEscape.escapePath(filePath));
// if (!f.isFile()) {
// return false;
// }
// return true;
// }
//
// /**
// * 创建文件
// *
// * @param filePath 文件地址
// * @param fileName 文件名
// * @return
// */
// public static boolean createFile(String filePath, String fileName) {
// String strFilePath = XSSEscape.escapePath(filePath + fileName);
// ;
// File file = new File(XSSEscape.escapePath(filePath));
// if (!file.exists()) {
// /** 注意这里是 mkdirs()方法 可以创建多个文件夹 */
// file.mkdirs();
// }
// File subfile = new File(strFilePath);
// if (!subfile.exists()) {
// try {
// boolean b = subfile.createNewFile();
// return b;
// } catch (IOException e) {
// e.printStackTrace();
// }
// } else {
// return true;
// }
// return false;
// }
//
// /**
// * 创建文件夹
// *
// * @param filePath 文件夹地址
// * @return
// */
// public static void createDirs(String filePath) {
// File file = new File(XSSEscape.escapePath(filePath));
// if (!file.exists()) {
// /** 注意这里是 mkdirs()方法 可以创建多个文件夹 */
// file.mkdirs();
// }
// }
//
// /**
// * 遍历文件夹下当前文件
// *
// * @param file 地址
// */
// public static List<File> getFile(File file) {
// List<File> list = new ArrayList<>();
// File[] fileArray = file.listFiles();
// if (fileArray == null) {
// return list;
// } else {
// for (File f : fileArray) {
// if (f.isFile()) {
// list.add(0, f);
// }
// }
// }
// return list;
// }
//
// /**
// * 遍历文件夹下所有文件
// *
// * @param file 地址
// */
// public static List<File> getFile(File file, List<File> list) {
// File[] fileArray = file.listFiles();
// if (fileArray == null) {
// return list;
// } else {
// for (File f : fileArray) {
// if (f.isFile()) {
// list.add(0, f);
// } else {
// getFile(f, list);
// }
// }
// }
// return list;
// }
//
// /**
// * 删除文件或文件夹以及子文件夹和子文件等 【注意】请谨慎调用该方法,避免删除重要文件
// *
// * @param file
// */
// public static void deleteFileAll(File file) {
// if (file.exists()) {
// if (file.isFile()) {
// // 文件
// log.info(file.getAbsolutePath() + " 删除中...");
// file.delete();
// log.info("删除成功!");
// return;
// } else {
// // 文件夹
// File[] files = file.listFiles();
// for (int i = 0; i < files.length; i++) {
// deleteFileAll(files[i]);
// }
// file.delete();
// }
// } else {
// log.info(file.getAbsolutePath() + " 文件不存在!");
// }
// }
//
// /**
// * 删除单个文件
// *
// * @param filePath 文件路径
// */
// public static void deleteFile(String filePath) {
// File file = new File(XSSEscape.escapePath(filePath));
// if (file.exists() && file.isFile()) {
// file.delete();
// }
// }
//
// /**
// * 删除空文件夹、空的子文件夹
// *
// * @param file
// * @author cielo
// */
// public static void deleteEmptyDirectory(File file) {
// if (file != null && file.exists() && file.isDirectory()) {
// File[] files = file.listFiles();
// if (files != null && files.length > 0) {
// for (int i = 0; i < files.length; i++) {
// deleteEmptyDirectory(files[i]);
// }
// // 子文件夹里的删除完后,重新获取。判断空的子文件删除后,该文件夹是否为空
// files = file.listFiles();
// }
// if (files == null || files.length == 0) {
// String absolutePath = file.getAbsolutePath();
// file.delete();
// log.info("删除空文件夹!路径:" + absolutePath);
// }
// }
// }
//
// /**
// * 删除tmp文件
// *
// * @param multipartFile
// * @return
// */
// public static boolean deleteTmp(MultipartFile multipartFile) {
// try {
// CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
// DiskFileItem diskFileItem = (DiskFileItem) commonsMultipartFile.getFileItem();
// File storeLocation = diskFileItem.getStoreLocation();
// FileUtil.deleteEmptyDirectory(storeLocation);
// return true;
// } catch (Exception e) {
// log.error("删除tmp文件失败,错误:" + e.getMessage());
// return false;
// }
// }
//
// /**
// * 打开目录
// *
// * @param path
// */
// public static void open(String path) {
// // 打开输出目录
// try {
// String osName = System.getProperty("os.name");
// if (osName != null) {
// if (osName.contains("Mac")) {
// Runtime.getRuntime().exec("open " + path);
// } else if (osName.contains("Windows")) {
// Runtime.getRuntime().exec("cmd /c start " + path);
// } else {
// log.debug("文件输出目录:" + path);
// }
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// /**
// * 向文件中添加内容
// *
// * @param strcontent 内容
// * @param filePath 地址
// * @param fileName 文件名
// */
// public static void writeToFile(String strcontent, String filePath, String fileName) {
// //生成文件夹之后,再生成文件,不然会出错
// String strFilePath = filePath + fileName;
// // 每次写入时,都换行写
// File subfile = new File(XSSEscape.escapePath(strFilePath));
// RandomAccessFile raf = null;
// try {
// /** 构造函数 第二个是读写方式 */
// raf = new RandomAccessFile(subfile, "rw");
// /** 将记录指针移动到该文件的最后 */
// raf.seek(subfile.length());
// /** 向文件末尾追加内容 */
// raf.write(strcontent.getBytes());
// raf.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// /**
// * 修改文件内容(覆盖或者添加)
// *
// * @param path 文件地址
// * @param content 覆盖内容
// * @param append 指定了写入的方式,是覆盖写还是追加写(true=追加)(false=覆盖)
// */
// public static void modifyFile(String path, String content, boolean append) {
// try {
// @Cleanup FileWriter fileWriter = new FileWriter(path, append);
// @Cleanup BufferedWriter writer = new BufferedWriter(fileWriter);
// writer.append(content);
// writer.flush();
// writer.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//
// /**
// * 读取文件内容
// *
// * @param filePath 地址
// * @param filename 名称
// * @return 返回内容
// */
// public static String getString(String filePath, String filename) {
// StringBuffer sb = new StringBuffer("");
// String line;
// try {
// @Cleanup FileInputStream inputStream = new FileInputStream(new File(XSSEscape.escapePath(filePath + filename)));
// @Cleanup InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
// @Cleanup BufferedReader reader = new BufferedReader(inputStreamReader);
// while ((line = reader.readLine()) != null) {
// sb.append(line);
// sb.append("\n");
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// return sb.toString();
// }
//
// /**
// * 重命名文件
// *
// * @param oldPath 原来的文件地址
// * @param newPath 新的文件地址
// */
// public static void renameFile(String oldPath, String newPath) {
// File oleFile = new File(oldPath);
// File newFile = new File(newPath);
// //执行重命名
// oleFile.renameTo(newFile);
// }
//
// /**
// * 复制文件
// *
// * @param fromFile 要复制的文件目录
// * @param toFile 要粘贴的文件目录
// * @return 是否复制成功
// */
// public static boolean copy(String fromFile, String toFile) {
// //要复制的文件目录
// File[] currentFiles;
// File root = new File(fromFile);
// //如同判断SD卡是否存在或者文件是否存在
// //如果不存在则 return出去
// if (!root.exists()) {
// return false;
// }
// //如果存在则获取当前目录下的全部文件 填充数组
// currentFiles = root.listFiles();
// //目标目录
// File targetDir = new File(toFile);
// //创建目录
// if (!targetDir.exists()) {
// targetDir.mkdirs();
// }
// //遍历要复制该目录下的全部文件
// for (int i = 0; i < currentFiles.length; i++) {
// if (currentFiles[i].isDirectory()) {
// //如果当前项为子目录 进行递归
// copy(currentFiles[i].getPath() + "/", toFile + currentFiles[i].getName() + "/");
// } else {
// //如果当前项为文件则进行文件拷贝
// copyFile(currentFiles[i].getPath(), toFile + currentFiles[i].getName());
// }
// }
// return true;
// }
//
// /**
// * 文件拷贝
// * 要复制的目录下的所有非子目录(文件夹)文件拷贝
// *
// * @param fromFile
// * @param toFile
// * @return
// */
// public static boolean copyFile(String fromFile, String toFile) {
// try {
// @Cleanup InputStream fosfrom = new FileInputStream(XSSEscape.escapePath(fromFile));
// @Cleanup OutputStream fosto = new FileOutputStream(XSSEscape.escapePath(toFile));
// byte[] bt = new byte[1024];
// int c;
// while ((c = fosfrom.read(bt)) > 0) {
// fosto.write(bt, 0, c);
// }
// fosfrom.close();
// fosto.close();
// return true;
// } catch (Exception ex) {
// return false;
// }
// }
//
// /**
// * 文件拷贝
// *
// * @param fromFile
// * @param toFile
// * @param fileName
// * @return
// */
// public static boolean copyFile(String fromFile, String toFile, String fileName) {
// try {
// //目标目录
// File targetDir = new File(toFile);
// //创建目录
// if (!targetDir.exists()) {
// targetDir.mkdirs();
// }
// @Cleanup InputStream fosfrom = new FileInputStream(fromFile);
// @Cleanup OutputStream fosto = new FileOutputStream(toFile + fileName);
// byte[] bt = new byte[1024];
// int c;
// while ((c = fosfrom.read(bt)) > 0) {
// fosto.write(bt, 0, c);
// }
// fosfrom.close();
// fosto.close();
// return true;
// } catch (Exception ex) {
// return false;
// }
// }
//
// /**
// * 保存文件
// *
// * @param inputStream
// * @param path
// * @param fileName
// */
// public static void write(InputStream inputStream, String path, String fileName) {
// OutputStream os = null;
// long dateStr = System.currentTimeMillis();
// try {
// // 1K的数据缓冲
// byte[] bs = new byte[1024];
// // 读取到的数据长度
// int len;
// // 输出的文件流保存到本地文件
// File tempFile = new File(XSSEscape.escapePath(path));
// if (!tempFile.exists()) {
// tempFile.mkdirs();
// }
// String newFileName = tempFile.getPath() + File.separator + fileName;
// log.info("保存文件:" + newFileName);
// os = new FileOutputStream(XSSEscape.escapePath(newFileName));
// // 开始读取
// while ((len = inputStream.read(bs)) != -1) {
// os.write(bs, 0, len);
// }
// } catch (IOException e) {
// log.error("生成excel失败");
// } catch (Exception e) {
// log.error("生成excel失败");
// } finally {
// // 完毕,关闭所有链接
// try {
// if (os != null) {
// os.close();
// }
// inputStream.close();
// } catch (IOException e) {
// log.error("关闭链接失败" + e.getMessage());
// }
// }
// }
//
// /**
// * 写入文件
// *
// * @param inputStream
// * @param path
// * @param fileName
// */
// public static void writeFile(InputStream inputStream, String path, String fileName) {
// OutputStream os = null;
// try {
// // 1K的数据缓冲
// byte[] bs = new byte[1024];
// // 读取到的数据长度
// int len;
// // 输出的文件流保存到本地文件
// File tempFile = new File(XSSEscape.escapePath(path));
// if (!tempFile.exists()) {
// tempFile.mkdirs();
// }
// String newFileName = tempFile.getPath() + File.separator + fileName;
// log.info("保存文件:" + newFileName);
// os = new FileOutputStream(XSSEscape.escapePath(newFileName));
// // 开始读取
// while ((len = inputStream.read(bs)) != -1) {
// os.write(bs, 0, len);
// }
// } catch (IOException e) {
// log.error("生成excel失败");
// } catch (Exception e) {
// log.error("生成excel失败");
// } finally {
// // 完毕,关闭所有链接
// try {
// if (os != null) {
// os.close();
// }
// inputStream.close();
// } catch (IOException e) {
// log.error("关闭链接失败" + e.getMessage());
// }
// }
// }
//
// /**
// * 上传文件
// *
// * @param file 文件
// * @param filePath 保存路径
// * @param fileName 保存名称
// */
// public static void upFile(MultipartFile file, String filePath, String fileName) {
// try {
// String escapeFilePath = XSSEscape.escape(filePath);
// String escapeFileName = XSSEscape.escape(fileName);
// // 输出的文件流保存到本地文件
// File tempFile = new File(escapeFilePath);
// if (!tempFile.exists()) {
// tempFile.mkdirs();
// }
// File f = new File(escapeFilePath, escapeFileName);
// //将上传的文件存储到指定位置
// file.transferTo(f);
// } catch (Exception e) {
// log.error(e.getMessage());
// }
// }
//
// /**
// * 读取文件修改时间
// */
// public static String getCreateTime(String filePath) {
// DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// File file = new File(XSSEscape.escapePath(filePath));
// // 毫秒数
// long modifiedTime = file.lastModified();
// // 通过毫秒数构造日期 即可将毫秒数转换为日期
// Date date = new Date(modifiedTime);
// String dateString = format.format(date);
// return dateString;
// }
//
// /**
// * 获取文件类型
// */
// public static String getFileType(File file) {
// if (file.isFile()) {
// String fileName = file.getName();
// String fileTyle = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
// return fileTyle;
// }
// return null;
// }
//
// /**
// * 获取文件类型
// */
// public static String getFileType(String fileName) {
// int lastIndexOf = fileName.lastIndexOf(".") + 1;
// //获取文件的后缀名 jpg
// String suffix = fileName.substring(lastIndexOf);
// return suffix;
// }
//
// /**
// * 获取文件大小
// *
// * @param data
// * @return
// */
// public static String getSize(String data) {
// String size = "";
// if (data != null && !StringUtils.isEmpty(data)) {
// long fileS = Long.parseLong(data);
// DecimalFormat df = new DecimalFormat("#.00");
// if (fileS < 1024) {
// size = df.format((double) fileS) + "BT";
// } else if (fileS < 1048576) {
// size = df.format((double) fileS / 1024) + "KB";
// } else if (fileS < 1073741824) {
// size = df.format((double) fileS / 1048576) + "MB";
// } else {
// size = df.format((double) fileS / 1073741824) + "GB";
// }
// } else {
// size = "0BT";
// }
// return size;
// }
//
// private static final int BUFFER_SIZE = 2 * 1024;
//
// /**
// * 压缩文件夹
// *
// * @param srcDir 压缩文件夹路径
// * @param outDir 压缩文件路径
// * @param keepDirStructure 是否保留原来的目录结构,
// * true:保留目录结构;
// * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
// * @throws RuntimeException 压缩失败会抛出运行时异常
// */
// public static void toZip(String outDir, boolean keepDirStructure, String... srcDir) {
// try {
// @Cleanup OutputStream out = new FileOutputStream(new File(XSSEscape.escapePath(outDir)));
// @Cleanup ZipOutputStream zos = null;
// try {
// zos = new ZipOutputStream(out);
// List<File> sourceFileList = new ArrayList<File>();
// for (String dir : srcDir) {
// File sourceFile = new File(XSSEscape.escapePath(dir));
// sourceFileList.add(sourceFile);
// }
// compress(sourceFileList, zos, keepDirStructure);
// } catch (Exception e) {
// throw new RuntimeException("zip error from ZipUtils", e);
// } finally {
// if (zos != null) {
// try {
// zos.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// } catch (Exception e) {
// log.error("压缩失败:{}", e.getMessage());
// }
// }
//
// /**
// * 递归压缩方法
// *
// * @param sourceFile 源文件
// * @param zos zip输出流
// * @param name 压缩后的名称
// * @param keepDirStructure 是否保留原来的目录结构,
// * true:保留目录结构;
// * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
// * @throws Exception
// */
// private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure) throws Exception {
// byte[] buf = new byte[BUFFER_SIZE];
// if (sourceFile.isFile()) {
// zos.putNextEntry(new ZipEntry(name));
// int len;
// @Cleanup FileInputStream in = new FileInputStream(sourceFile);
// while ((len = in.read(buf)) != -1) {
// zos.write(buf, 0, len);
// }
// zos.closeEntry();
// in.close();
// } else {
// File[] listFiles = sourceFile.listFiles();
// if (listFiles == null || listFiles.length == 0) {
// if (keepDirStructure) {
// zos.putNextEntry(new ZipEntry(name + "/"));
// zos.closeEntry();
// }
// } else {
// for (File file : listFiles) {
// if (keepDirStructure) {
// compress(file, zos, name + "/" + file.getName(),
// keepDirStructure);
// } else {
// compress(file, zos, file.getName(), keepDirStructure);
// }
// }
// }
// }
// }
//
// private static void compress(List<File> sourceFileList, ZipOutputStream zos, boolean keepDirStructure) throws Exception {
// byte[] buf = new byte[BUFFER_SIZE];
// for (File sourceFile : sourceFileList) {
// String name = sourceFile.getName();
// if (sourceFile.isFile()) {
// zos.putNextEntry(new ZipEntry(name));
// int len;
// @Cleanup FileInputStream in = new FileInputStream(sourceFile);
// while ((len = in.read(buf)) != -1) {
// zos.write(buf, 0, len);
// }
// zos.closeEntry();
// in.close();
// } else {
// File[] listFiles = sourceFile.listFiles();
// if (listFiles == null || listFiles.length == 0) {
// if (keepDirStructure) {
// zos.putNextEntry(new ZipEntry(name + "/"));
// zos.closeEntry();
// }
// } else {
// for (File file : listFiles) {
// if (keepDirStructure) {
// compress(file, zos, name + "/" + file.getName(),
// keepDirStructure);
// } else {
// compress(file, zos, file.getName(),
// keepDirStructure);
// }
//
// }
// }
// }
// }
// }
//
// //=================================判断文件后缀==========================
//
// /**
// * 允许文件类型
// *
// * @param fileType 文件所有类型
// * @param fileExtension 当前文件类型
// * @return
// */
// public static boolean fileType(String fileType, String fileExtension) {
// String[] allowExtension = fileType.split(",");
// return Arrays.asList(allowExtension).contains(fileExtension.toLowerCase());
// }
//
// /**
// * 允许图片类型
// *
// * @param imageType 图片所有类型
// * @param fileExtension 当前图片类型
// * @return
// */
// public static boolean imageType(String imageType, String fileExtension) {
// String[] allowExtension = imageType.split(",");
// return Arrays.asList(allowExtension).contains(fileExtension.toLowerCase());
// }
//
// /**
// * 允许上传大小
// *
// * @param fileSize 文件大小
// * @param maxSize 最大的文件
// * @return
// */
// public static boolean fileSize(Long fileSize, int maxSize) {
// if (fileSize > maxSize) {
// return true;
// }
// return false;
// }
//
// /**
// * 导入生成临时文件后,获取文件内容
// *
// * @param multipartFile 文件
// * @param filePath 路径
// * @return
// */
// public static String getFileContent(MultipartFile multipartFile, String filePath) {
// //文件名
// String fileName = multipartFile.getName();
// //上传到项目文件路径中
// FileUtil.upFile(multipartFile, filePath, fileName);
// //读取文件文件内容
// String fileContent = FileUtil.getString(filePath, fileName);
// return fileContent;
// }
//
// /**
// * 判断是否为json格式且不为空
// *
// * @param multipartFile
// * @param type 类型
// * @return
// */
// public static boolean existsSuffix(MultipartFile multipartFile, String type) {
// if (!multipartFile.getOriginalFilename().endsWith("." + type) || multipartFile.getSize() < 1) {
// return true;
// }
// return false;
// }
//
// /**
// * File转MultipartFile
// *
// * @param file
// * @return
// */
// public static MultipartFile createFileItem(File file) {
// FileItemFactory factory = new DiskFileItemFactory(16, null);
// FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// try {
// @Cleanup FileInputStream fis = new FileInputStream(file);
// OutputStream os = item.getOutputStream();
// while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
// os.write(buffer, 0, bytesRead);
// }
// os.close();
// fis.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// MultipartFile multipartFile = new CommonsMultipartFile(item);
// return multipartFile;
// }
//
//}
package org.modules.junmpProcess.utils;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
/**
* <p>名称:IdWorker.java</p>
* <p>描述:分布式自增长ID</p>
* <pre>
* Twitter的 Snowflake JAVA实现方案
* </pre>
* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
* 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
* <p>
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
*
* @author Polim
*/
public class IdWorker {
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
private final static long twepoch = 1288834974657L;
// 机器标识位数
private final static long workerIdBits = 5L;
// 数据中心标识位数
private final static long datacenterIdBits = 5L;
// 机器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 数据中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 毫秒内自增位
private final static long sequenceBits = 12L;
// 机器ID偏左移12位
private final static long workerIdShift = sequenceBits;
// 数据中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits;
// 时间毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
/* 上次生产id时间戳 */
private static long lastTimestamp = -1L;
// 0,并发控制
private long sequence = 0L;
private final long workerId;
// 数据标识id部分
private final long datacenterId;
public IdWorker() {
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
/**
* @param workerId 工作机器ID
* @param datacenterId 序列号
*/
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* 获取下一个ID
*
* @return
*/
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// ID偏移组合生成最终的ID,并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
/**
* <p>
* 获取 maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (!name.isEmpty()) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
* MAC + PID 的 hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
/**
* <p>
* 数据标识id部分
* </p>
*/
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage());
}
return id;
}
}
package org.modules.junmpProcess.utils;//package org.jeecg.junmpProcess.utils;
//
//import io.minio.*;
//import io.minio.http.Method;
//import io.minio.messages.Bucket;
//import lombok.Cleanup;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.stereotype.Component;
//import org.springframework.web.multipart.MultipartFile;
//
//import javax.annotation.Resource;
//import javax.servlet.ServletOutputStream;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.*;
//import java.net.URLEncoder;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * minio文件上传工具类
// */
//@Component
//@Slf4j
//public class MinioUploadUtil {
// @Resource(name = "minioClient")
// private MinioClient minioClient;
//
// /**
// * 上传文件
// *
// * @param file
// * @param bucketName
// * @param fileName
// * @return
// */
// public void uploadFile(MultipartFile file, String bucketName, String fileName) {
// //判断文件是否为空
// if (null == file || 0 == file.getSize()) {
// log.error("文件不能为空");
// }
// //判断存储桶是否存在
// bucketExists(bucketName);
// //文件名
// if(file != null){
// String originalFilename = file.getOriginalFilename();
// //新的文件名 = 存储桶文件名_时间戳.后缀名
// assert originalFilename != null;
// //开始上传
// try {
// @Cleanup InputStream inputStream = file.getInputStream();
// minioClient.putObject(
// PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
// inputStream, file.getSize(), -1)
// .contentType(file.getContentType())
// .build());
// } catch (Exception e) {
// log.error(e.getMessage());
// }
// }
// }
//
// /**
// * 上传文件(可以传空) 数据备份使用
// * @param filePath
// * @param bucketName
// * @param fileName
// * @throws IOException
// */
// public void uploadFiles(String filePath, String bucketName, String fileName) throws IOException {
// MultipartFile file = FileUtil.createFileItem(new File(XSSEscape.escapePath(filePath)));
// //开始上传
// try {
// @Cleanup InputStream inputStream = file.getInputStream();
// minioClient.putObject(
// PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
// inputStream, file.getSize(), -1)
// .contentType(file.getContentType())
// .build());
// } catch (Exception e) {
// log.error(e.getMessage());
// }
// }
//
// /**
// * 下载文件
// *
// * @param fileName 文件名
// * @param bucketName 桶名(文件夹)
// * @return
// */
// public void downFile(String fileName, String bucketName, String downName) {
// InputStream inputStream = null;
// try {
// inputStream = minioClient.getObject(
// GetObjectArgs.builder()
// .bucket(bucketName)
// .object(fileName)
// .build());
// //下载文件
// HttpServletResponse response = ServletUtil.getResponse();
// HttpServletRequest request = ServletUtil.getRequest();
// try {
// @Cleanup BufferedInputStream bis = new BufferedInputStream(inputStream);
// if (StringUtils.isNotEmpty(downName)) {
// fileName = downName;
// }
// response.setCharacterEncoding("UTF-8");
// response.setContentType("text/plain");
// if(fileName.contains(".svg")){
// response.setContentType("image/svg+xml");
// }
// //编码的文件名字,关于中文乱码的改造
// String codeFileName = "";
// String agent = request.getHeader("USER-AGENT").toLowerCase();
// if (-1 != agent.indexOf("msie") || -1 != agent.indexOf("trident")) {
// //IE
// codeFileName = URLEncoder.encode(fileName, "UTF-8");
// } else if (-1 != agent.indexOf("mozilla")) {
// //火狐,谷歌
// codeFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
// } else {
// codeFileName = URLEncoder.encode(fileName, "UTF-8");
// }
// response.setHeader("Content-Disposition", "attachment;filename=" + XSSEscape.escape(new String(codeFileName.getBytes(), "utf-8")));
// @Cleanup OutputStream os = response.getOutputStream();
// int i;
// byte[] buff = new byte[1024 * 8];
// while ((i = bis.read(buff)) != -1) {
// os.write(buff, 0, i);
// }
// os.flush();
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// try {
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// } catch (Exception e) {
// log.error(e.getMessage());
// } finally {
// if (inputStream!=null){
// try {
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// }
//
// /**
// * 返回图片
// *
// * @param fileName 文件名
// * @param bucketName 桶名(文件夹)
// * @return
// */
// public void dowloadMinioFile(String fileName, String bucketName) {
// try {
// @Cleanup InputStream inputStream = minioClient.getObject(
// GetObjectArgs.builder()
// .bucket(bucketName)
// .object(fileName)
// .build());
// @Cleanup ServletOutputStream outputStream1 = ServletUtil.getResponse().getOutputStream();
// //读取指定路径下面的文件
// @Cleanup OutputStream outputStream = new BufferedOutputStream(outputStream1);
// //创建存放文件内容的数组
// byte[] buff = new byte[1024];
// //所读取的内容使用n来接收
// int n;
// //当没有读取完时,继续读取,循环
// while ((n = inputStream.read(buff)) != -1) {
// //将字节数组的数据全部写入到输出流中
// outputStream.write(buff, 0, n);
// }
// //强制将缓存区的数据进行输出
// outputStream.flush();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
//
// /**
// * 获取資源
// *
// * @param fileName
// * @param bucketName
// */
// public String getFile(String fileName, String bucketName) {
// String objectUrl = null;
// try {
// objectUrl = minioClient.getPresignedObjectUrl(
// GetPresignedObjectUrlArgs.builder()
// .method(Method.GET)
// .bucket(bucketName)
// .object(fileName)
// .build());
// } catch (Exception e) {
// log.error(e.getMessage());
// }
// return objectUrl;
// }
//
// /**
// * 下载文件
// *
// * @param fileName 文件名称
// * @param bucketName 存储桶名称
// * @return
// */
// public InputStream downloadMinio(String fileName, String bucketName) {
// try {
// @Cleanup InputStream stream =
// minioClient.getObject(
// GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
// return stream;
// } catch (Exception e) {
// e.printStackTrace();
// log.info(e.getMessage());
// return null;
// }
// }
//
// /**
// * 获取全部bucket
// *
// * @return
// */
// public List<String> getAllBuckets() throws Exception {
// return minioClient.listBuckets().stream().map(Bucket::name).collect(Collectors.toList());
// }
//
// /**
// * 根据bucketName删除信息
// *
// * @param bucketName bucket名称
// */
// public void removeBucket(String bucketName) throws Exception {
// minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
// }
//
// /**
// * 删除一个对象
// *
// * @param name
// * @return
// */
// public boolean removeFile(String bucketName, String name) {
// boolean isOK = true;
// try {
// minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(name).build());
// } catch (Exception e) {
// e.printStackTrace();
// isOK = false;
// }
// return isOK;
// }
//
// /**
// * 检查存储桶是否已经存在(不存在不创建)
// *
// * @param name
// * @return
// */
// public boolean bucketExists(String name) {
// boolean isExist = false;
// try {
// isExist = minioClient.bucketExists(getBucketExistsArgs(name));
// } catch (Exception e) {
// e.printStackTrace();
// }
// return isExist;
// }
//
// /**
// * 检查存储桶是否已经存在(不存在则创建)
// *
// * @param name
// * @return
// */
// public void bucketExistsCreate(String name) {
// try {
// minioClient.bucketExists(getBucketExistsArgs(name));
// minioClient.makeBucket(getMakeBucketArgs(name));
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
//
//
//
//
//
// /**
// * String转MakeBucketArgs
// *
// * @param name
// * @return
// */
// public static MakeBucketArgs getMakeBucketArgs(String name) {
// return MakeBucketArgs.builder().bucket(name).build();
// }
//
// /**
// * String转BucketExistsArgs
// *
// * @param name
// * @return
// */
// public static BucketExistsArgs getBucketExistsArgs(String name) {
// return BucketExistsArgs.builder().bucket(name).build();
// }
//
//
//
//
//}
package org.modules.junmpProcess.utils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import lombok.Cleanup;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
*
*/
public class ServletUtil {
/**
* 获取ServletPath
*/
public static String getServletPath() {
return ServletUtil.getRequest().getServletPath();
}
/**
* 获取Request Payload
*/
public static String getPayload() {
try {
@Cleanup ServletInputStream is = ServletUtil.getRequest().getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[10240 * 20];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0) {
nTotalRead = nTotalRead + nRead;
}
}
String str = new String(bytes, 0, nTotalRead, Constants.UTF_8);
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
/**
* 获取User-Agent
*/
public static String getUserAgent() {
return ServletUtil.getHeader("User-Agent");
}
/**
* 判断是否是手机端登陆
*/
public static boolean getIsMobileDevice() {
return isMobileDevice(ServletUtil.getUserAgent());
}
/**
* 获取HTTP头信息
*/
public static String getHeader(String name) {
if (getRequest() != null) {
return getRequest().getHeader(name);
}
return null;
}
/**
* 获取表单参数
*/
public static String getParameter(String name) {
return getRequest().getParameter(name);
}
/**
* 获取request
*/
public static HttpServletRequest getRequest() {
if (getRequestAttributes() != null) {
return getRequestAttributes().getRequest();
}
return null;
}
/**
* 获取response
*/
public static HttpServletResponse getResponse() {
return getRequestAttributes().getResponse();
}
/**
* 获取session
*/
public static HttpSession getSession() {
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
*/
public static String renderString(HttpServletResponse response, String string) {
try {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Cache-Control", "no-cache");
response.setContentType("application/json");
response.setCharacterEncoding(Constants.UTF_8);
response.getWriter().print(string);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 是否是Ajax异步请求
*
* @param request
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1) {
return true;
}
String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
return true;
}
String uri = request.getRequestURI();
if (inStringIgnoreCase(uri, ".json", ".xml")) {
return true;
}
String ajax = request.getParameter("__ajax");
if (inStringIgnoreCase(ajax, "json", "xml")) {
return true;
}
return false;
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs) {
if (str != null && strs != null) {
for (String s : strs) {
if (str.equalsIgnoreCase((s.trim()))) {
return true;
}
}
}
return false;
}
/**
* 返回JSONObject对象
*/
public static JSONObject getJsonObject() throws Exception {
String builder = ServletUtil.getPayload();
return JSONObject.parseObject(builder);
}
/**
* 判断是否是移动设备
*
* @param requestHeader
* @return
*/
public static boolean isMobileDevice(String requestHeader) {
String[] deviceArray = new String[]{"android", "windows phone", "iphone", "ios", "ipad", "mqqbrowser"};
if (requestHeader == null) {
return false;
}
requestHeader = requestHeader.toLowerCase();
for (int i = 0; i < deviceArray.length; i++) {
if (requestHeader.indexOf(deviceArray[i]) > 0) {
return true;
}
}
return false;
}
}
/*
*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*
*/
package org.modules.junmpProcess.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
*
*/
@Slf4j
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
/**
* 发布事件
*
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
/**
* SpringMvc下获取request
*
* @return
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (null == ra) {
return null;
}
HttpServletRequest request = ra.getRequest();
return request;
}
}
//package org.modules.junmpProcess.utils;
//
//import lombok.extern.slf4j.Slf4j;
//import org.owasp.validator.html.AntiSamy;
//import org.owasp.validator.html.CleanResults;
//import org.owasp.validator.html.Policy;
//
//import java.io.InputStream;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
///**
// * 防止XSS注入
// */
//@Slf4j
//public class XSSEscape {
//
//
// /**
// * 非法路径符号
// */
// private static final Pattern PATH_PATTERN = Pattern.compile("\\.\\.\\|\\.\\./|~/|~\\|[<]|>|\"|[*]|[|]|[?]", Pattern.CASE_INSENSITIVE);
//
// private static InputStream inputStream;
// private static Policy policy;
// private static Policy emptyPolicy;
//
// static {
// try {
// inputStream = XSSEscape.class.getClassLoader().getResourceAsStream("antisamy-ebay.xml");
// policy = Policy.getInstance(inputStream);
// inputStream.close();
// inputStream = XSSEscape.class.getClassLoader().getResourceAsStream("antisamy-empty.xml");
// emptyPolicy = Policy.getInstance(inputStream);
// inputStream.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// /**
// * 跨站式脚本攻击字符串过滤
// *
// * @param character 需要转义的字符串
// */
// public static String escape(String character) {
// try {
// AntiSamy antiSamy = new AntiSamy();
// CleanResults scan = antiSamy.scan(character, policy);
// String str = scan.getCleanHTML();
// str = str.replaceAll("&quot;", "\"");
// str = str.replaceAll("&amp;", "&");
// str = str.replaceAll("&lt;", "<");
// str = str.replaceAll("&gt;", ">");
// return str;
// } catch (Exception e) {
// log.error("转换错误:" + e.getMessage());
// }
// return null;
// }
//
//
// /**
// * 此方法伪过滤
// *
// * @param character 需要转义的字符串
// */
// public static String escapeEmpty(String character) {
// try {
// AntiSamy antiSamy = new AntiSamy();
// CleanResults scan = antiSamy.scan(character, emptyPolicy);
// return scan.getCleanHTML();
// } catch (Exception e) {
// }
// return character;
// }
//
// /**
// * 过滤非法路径
// *
// * @param path
// * @return
// */
// public static String escapePath(String path) {
// Matcher matcher = PATH_PATTERN.matcher(path);
// return escapeEmpty(matcher.replaceAll("").replaceAll("\\.\\.", "."));
// }
//
//
//}
package org.modules.junmpProcess.vo;
import lombok.Data;
/**
* @author LoveMyOrange
* @create 2022-10-15 17:04
*/
@Data
public class AttachmentVO {
private String id;
private String name;
private String url;
}
package org.modules.junmpProcess.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Date;
/**
* @author LoveMyOrange
* @create 2022-10-16 9:42
*/
@ApiModel("评论的VO")
@Data
public class CommentVO {
private String comments;
private String userId;
private String userName;
private Date createTime;
}
package org.modules.junmpProcess.vo;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.modules.junmpProcess.dto.json.ChildNode;
import org.modules.junmpProcess.entity.ProcessTemplates;
import java.util.List;
import java.util.Map;
/**
* @author LoveMyOrange
* @create 2022-10-15 16:27
*/
@Data
@ApiModel("详情VO")
public class HandleDataVO {
@ApiModelProperty("任务id")
private String taskId;
@ApiModelProperty("流程实例id")
private String processInstanceId;
@ApiModelProperty("表单数据")
private JSONObject formData;
@ApiModelProperty("前端是否打开 签名板")
private Boolean signFlag;
@ApiModelProperty("流程模板")
private ProcessTemplates processTemplates;
@ApiModelProperty("当前节点json数据 如果有taskId的话才返回")
private ChildNode currentNode;
@ApiModelProperty("任务详情")
private Map<String, List<TaskDetailVO>> detailVOList;
@ApiModelProperty("已经结束的节点")
List<String> endList;
@ApiModelProperty("正在运行的节点")
List<String> runningList;
@ApiModelProperty("还没运行的节点")
List<String> noTakeList;
}
package org.modules.junmpProcess.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.modules.junmpProcess.dto.json.UserInfo;
import java.util.Date;
/**
* @author LoveMyOrange
* @create 2022-10-14 23:47
*/
@Data
@ApiModel("我发起页面 需要返回给前端的VO")
public class HistoryProcessInstanceVO {
@ApiModelProperty("流程实例id")
private String processInstanceId;
@ApiModelProperty("审批类型")
private String processDefinitionName;
@ApiModelProperty("发起人")
private UserInfo startUser;
@ApiModelProperty("提交时间")
private Date startTime;
@ApiModelProperty("结束时间")
private Date endTime;
@ApiModelProperty("当前节点")
private String currentActivityName;
@ApiModelProperty("审批状态")
private String businessStatus;
@ApiModelProperty("耗时")
private String duration;
}
package org.modules.junmpProcess.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
* @Author:LoveMyOrange
* @Description:
* @Date:Created in 2022/10/22 15:33
*/
@ApiModel("减签前一步操作")
@Data
public class MultiVO {
private String taskId;
private String processInstanceId;
private String executionId;
private String userId;
private String userName;
}
package org.modules.junmpProcess.vo;
import lombok.Data;
import java.util.Date;
/**
* @author LoveMyOrange
* @create 2022-10-16 9:42
*/
@Data
public class OptionVO {
private String comments;
private String userId;
private String userName;
private Date createTime;
}
package org.modules.junmpProcess.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author : willian fu
* @version : 1.0
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrgTreeVo {
private Long id;
private String name;
private String type;
private String avatar;
private Boolean sex;
private Boolean selected;
}
package org.modules.junmpProcess.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.modules.junmpProcess.entity.ProcessTemplates;
import java.util.List;
/**
* @author LoveMyOrange
* @create 2022-10-15 16:09
*/
@Data
@ApiModel("查看详情 需要返回给前端的VO")
public class ProcessInstanceDetailVO {
private ProcessTemplates processTemplates;
private String formData;
private String processInstanceId;
private List<String> completeIdList;
private List<String> finishIdList;
private List<String> noneList;
private Boolean signFlag;
}
package org.modules.junmpProcess.vo;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* @author LoveMyOrange
* @create 2022-10-16 9:38
*/
@Data
public class TaskDetailVO {
private String taskId;
private String activityId;
private String name;
private Date createTime;
private Date endTime;
private String signImage;
private List<AttachmentVO> attachmentVOList;
private List<OptionVO> optionVOList;
private List<CommentVO> commentVOList;
}
package org.modules.junmpProcess.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.flowable.task.api.DelegationState;
import org.modules.junmpProcess.dto.json.UserInfo;
import java.util.Date;
/**
* @author LoveMyOrange
* @create 2022-10-14 23:47
*/
@Data
@ApiModel("待办 需要返回给前端的VO")
public class TaskVO {
@ApiModelProperty("任务id")
private String taskId;
@ApiModelProperty("任务id")
private String processInstanceId;
@ApiModelProperty("审批类型")
private String processDefinitionName;
@ApiModelProperty("发起人")
private UserInfo startUser;
@ApiModelProperty("提交时间")
private Date startTime;
@ApiModelProperty("任务到达时间")
private Date taskCreatedTime;
@ApiModelProperty("当前节点")
private String currentActivityName;
@ApiModelProperty("审批状态")
private String businessStatus;
@ApiModelProperty("结束时间")
private Date endTime;
@ApiModelProperty("耗时")
private String duration;
@ApiModelProperty("委派状态")
private DelegationState delegationState;
}
package org.modules.junmpProcess.vo;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author : willian fu
* @date : 2020/9/21
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TemplateGroupVo {
private Integer id;
private String name;
private List<Template> items;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class Template {
private String formId;
private Integer tgId;
private String formName;
private String icon;
private Boolean isStop;
private String remark;
private JSONObject logo;
private String background;
private String updated;
private String templateId;
}
}
package springfox.documentation.spring.web;
import com.fasterxml.classmate.ResolvedType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import springfox.documentation.RequestHandler;
import springfox.documentation.RequestHandlerKey;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spring.web.readers.operation.HandlerMethodResolver;
import springfox.documentation.spring.wrapper.NameValueExpression;
import springfox.documentation.spring.wrapper.PatternsRequestCondition;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import static java.util.Optional.ofNullable;
/**
* SpringBoot 2.6 Swagger无法使用
* 方法1:重写此类, 不影响SpringBoot匹配方式
* 方法2:改匹配方式为ANT
* spring:
* mvc:
* pathmatch:
* matching-strategy: ANT_PATH_MATCHER
*/
public class WebMvcRequestHandler implements RequestHandler {
private final String contextPath;
private final HandlerMethodResolver methodResolver;
private final RequestMappingInfo requestMapping;
private final HandlerMethod handlerMethod;
private static final org.springframework.web.servlet.mvc.condition.PatternsRequestCondition EMPTY_PATTERNS = new org.springframework.web.servlet.mvc.condition.PatternsRequestCondition();
private static final ParamsRequestCondition EMPTY_PARAMS = new ParamsRequestCondition();
private static final HeadersRequestCondition EMPTY_HEADERS = new HeadersRequestCondition();
private static final ConsumesRequestCondition EMPTY_CONSUMES = new ConsumesRequestCondition();
private static final ProducesRequestCondition EMPTY_PRODUCES = new ProducesRequestCondition();
public WebMvcRequestHandler(
String contextPath,
HandlerMethodResolver methodResolver,
RequestMappingInfo requestMapping,
HandlerMethod handlerMethod) {
this.contextPath = contextPath;
this.methodResolver = methodResolver;
this.requestMapping = requestMapping;
this.handlerMethod = handlerMethod;
}
@Override
public HandlerMethod getHandlerMethod() {
return handlerMethod;
}
@Override
public RequestHandler combine(RequestHandler other) {
return this;
}
@Override
public Class<?> declaringClass() {
return handlerMethod.getBeanType();
}
@Override
public boolean isAnnotatedWith(Class<? extends Annotation> annotation) {
return null != AnnotationUtils.findAnnotation(handlerMethod.getMethod(), annotation);
}
@Override
public PatternsRequestCondition getPatternsCondition() {
AbstractRequestCondition contition = requestMapping.getPatternsCondition();
if (contition == null) {
contition = new org.springframework.web.servlet.mvc.condition.PatternsRequestCondition(requestMapping.getPathPatternsCondition().getPatterns().stream().map(p -> p.getPatternString()).collect(Collectors.toList()).toArray(new String[]{}));
}
return new WebMvcPatternsRequestConditionWrapper(
contextPath,
(org.springframework.web.servlet.mvc.condition.PatternsRequestCondition) contition);
}
@Override
public String groupName() {
return ControllerNamingUtils.controllerNameAsGroup(handlerMethod);
}
@Override
public String getName() {
return handlerMethod.getMethod().getName();
}
@Override
public Set<RequestMethod> supportedMethods() {
return requestMapping.getMethodsCondition().getMethods();
}
@Override
public Set<MediaType> produces() {
return Optional.ofNullable(requestMapping.getProducesCondition()).orElseGet(() -> EMPTY_PRODUCES).getProducibleMediaTypes();
}
@Override
public Set<MediaType> consumes() {
return Optional.ofNullable(requestMapping.getConsumesCondition()).orElseGet(() -> EMPTY_CONSUMES).getConsumableMediaTypes();
}
@Override
public Set<NameValueExpression<String>> headers() {
return WebMvcNameValueExpressionWrapper.from(Optional.ofNullable(requestMapping.getHeadersCondition()).orElseGet(() -> EMPTY_HEADERS).getExpressions());
}
@Override
public Set<NameValueExpression<String>> params() {
return WebMvcNameValueExpressionWrapper.from(Optional.ofNullable(requestMapping.getParamsCondition()).orElseGet(() -> EMPTY_PARAMS).getExpressions());
}
@Override
public <T extends Annotation> Optional<T> findAnnotation(Class<T> annotation) {
return ofNullable(AnnotationUtils.findAnnotation(handlerMethod.getMethod(), annotation));
}
@Override
public RequestHandlerKey key() {
return new RequestHandlerKey(
Optional.ofNullable(requestMapping.getPatternsCondition()).orElseGet(() -> EMPTY_PATTERNS).getPatterns(),
requestMapping.getMethodsCondition().getMethods(),
Optional.ofNullable(requestMapping.getConsumesCondition()).orElseGet(() -> EMPTY_CONSUMES).getConsumableMediaTypes(),
Optional.ofNullable(requestMapping.getProducesCondition()).orElseGet(() -> EMPTY_PRODUCES).getProducibleMediaTypes());
}
@Override
public springfox.documentation.spring.wrapper.RequestMappingInfo<?> getRequestMapping() {
return new WebMvcRequestMappingInfoWrapper(requestMapping);
}
@Override
public List<ResolvedMethodParameter> getParameters() {
return methodResolver.methodParameters(handlerMethod);
}
@Override
public ResolvedType getReturnType() {
return methodResolver.methodReturnType(handlerMethod);
}
@Override
public <T extends Annotation> Optional<T> findControllerAnnotation(Class<T> annotation) {
return ofNullable(AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), annotation));
}
@Override
public String toString() {
return new StringJoiner(", ", WebMvcRequestHandler.class.getSimpleName() + "{", "}")
.add("requestMapping=" + requestMapping)
.add("handlerMethod=" + handlerMethod)
.add("key=" + key())
.toString();
}
}
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="20000"/>
<directive name="useXHTML" value="true"/>
<directive name="formatOutput" value="true"/>
<!--
remember, this won't work for relative URIs - AntiSamy doesn't
know anything about the URL or your web structure
-->
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
<!--
From W3C:
This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class
name or names. Multiple class names must be separated by white
space characters.
-->
<!-- The 16 colors defined by the HTML Spec (also used by the CSS Spec) -->
<regexp name="colorName"
value="(aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)"/>
<!-- HTML/CSS Spec allows 3 or 6 digit hex to specify color -->
<regexp name="colorCode" value="(#([0-9a-fA-F]{6}|[0-9a-fA-F]{3}))"/>
<regexp name="anything" value=".*"/>
<regexp name="numberOrPercent" value="(\d)+(%{0,1})"/>
<regexp name="paragraph" value="([\p{L}\p{N},'\.\s\-_\(\)]|&amp;[0-9]{2};)*"/>
<regexp name="htmlId" value="[a-zA-Z0-9\:\-_\.]+"/>
<regexp name="htmlTitle"
value="[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&amp;]*"/> <!-- force non-empty with a '+' at the end instead of '*' -->
<regexp name="htmlClass" value="[a-zA-Z0-9\s,\-_]+"/>
<regexp name="onsiteURL"
value="^(?!//)(?![\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*(&amp;colon))[\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*"/>
<regexp name="offsiteURL"
value="(\s)*((ht|f)tp(s?)://|mailto:)[\p{L}\p{N}]+[\p{L}\p{N}\p{Zs}\.\#@\$%\+&amp;;:\-_~,\?=/!\(\)]*(\s)*"/>
<regexp name="boolean" value="(true|false)"/>
<regexp name="singlePrintable" value="[a-zA-Z0-9]{1}"/> <!-- \w allows the '_' character -->
<!-- This is for elements (ex: elemName { ... }) -->
<regexp name="cssElementSelector" value="[a-zA-Z0-9\-_]+|\*"/>
<!-- This is to list out any element names that are *not* valid -->
<regexp name="cssElementExclusion" value=""/>
<!-- This if for classes (ex: .className { ... }) -->
<regexp name="cssClassSelector" value="\.[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any class names that are *not* valid -->
<regexp name="cssClassExclusion" value=""/>
<!-- This is for ID selectors (ex: #myId { ... } -->
<regexp name="cssIDSelector" value="#[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any IDs that are *not* valid - FIXME: What should the default be to avoid div hijacking? *? -->
<regexp name="cssIDExclusion" value=""/>
<!-- This is for pseudo-element selector (ex. foo:pseudo-element { ... } -->
<regexp name="cssPseudoElementSelector" value=":[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any psuedo-element names that are *not* valid -->
<regexp name="cssPsuedoElementExclusion" value=""/>
<!-- This is for attribute selectors (ex. foo[attr=value] { ... } -->
<regexp name="cssAttributeSelector" value="\[[a-zA-Z0-9\-_]+((=|~=|\|=){1}[a-zA-Z0-9\-_]+){1}\]"/>
<!-- This is to list out any attribute names that are *not* valid -->
<regexp name="cssAttributeExclusion" value=""/>
<!-- This is for resources referenced from CSS (such as background images and other imported stylesheets) -->
<regexp name="cssOnsiteUri" value="url\(([\p{L}\p{N}\\/\.\?=\#&amp;;\-_~]+|\#(\w)+)\)"/>
<regexp name="cssOffsiteUri"
value="url\((\s)*((ht|f)tp(s?)://)[\p{L}\p{N}]+[~\p{L}\p{N}\p{Zs}\-_\.@#$%&amp;;:,\?=/\+!]*(\s)*\)"/>
<!-- This if for CSS Identifiers -->
<regexp name="cssIdentifier" value="[a-zA-Z0-9\-_]+"/>
<!-- This is for comments within CSS (ex. /* comment */) -->
<regexp name="cssCommentText" value="[\p{L}\p{N}\-_,\/\\\.\s\(\)!\?\=\$#%\^&amp;:&quot;']+"/>
<regexp name="integer" value="(-|\+)?[0-9]+"/>
<regexp name="positiveInteger" value="(\+)?[0-9]+"/>
<regexp name="number" value="(-|\+)?([0-9]+(\.[0-9]+)?)"/>
<regexp name="angle" value="(-|\+)?([0-9]+(\.[0-9]+)?)(deg|grads|rad)"/>
<regexp name="time" value="([0-9]+(\.[0-9]+)?)(ms|s)"/>
<regexp name="frequency" value="([0-9]+(\.[0-9]+)?)(hz|khz)"/>
<regexp name="length" value="((-|\+)?0|(-|\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
<regexp name="positiveLength" value="((\+)?0|(\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
<regexp name="percentage" value="(-|\+)?([0-9]+(\.[0-9]+)?)%"/>
<regexp name="positivePercentage" value="(\+)?([0-9]+(\.[0-9]+)?)%"/>
<regexp name="absolute-size" value="(xx-small|x-small|small|medium|large|x-large|xx-large)"/>
<regexp name="relative-size" value="(larger|smaller)"/>
<!-- Used for CSS Color specifications (complex regexp expresses integer values of 0-255) -->
<regexp name="rgbCode"
value="rgb\(([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\)"/>
<!-- CSS2 Allowed System Color Values -->
<regexp name="systemColor"
value="(activeborder|activecaption|appworkspace|background|buttonface|buttonhighlight|buttonshadow|buttontext|captiontext|graytext|highlight|highlighttext|inactiveborder|inactivecaption|inactivecaptiontext|infobackground|infotext|menu|menutext|scrollbar|threeddarkshadow|threedface|threedhighlight|threedlightshadow|threedshadow|window|windowframe|windowtext)"/>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
<!-- Common to all HTML tags -->
<attribute name="id"
description="The 'id' of any HTML attribute should not contain anything besides letters and numbers">
<regexp-list>
<regexp name="htmlId"/>
</regexp-list>
</attribute>
<attribute name="class"
description="The 'class' of any HTML attribute is usually a single word, but it can also be a list of class names separated by spaces">
<regexp-list>
<regexp name="htmlClass"/>
</regexp-list>
</attribute>
<attribute name="lang"
description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
<regexp-list>
<regexp value="[a-zA-Z]{2,20}"/>
</regexp-list>
</attribute>
<attribute name="title"
description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
<regexp-list>
<regexp name="htmlTitle"/>
</regexp-list>
</attribute>
<attribute name="alt"
description="The 'alt' attribute provides alternative text to users when its visual representation is not available">
<regexp-list>
<regexp name="paragraph"/>
</regexp-list>
</attribute>
<!-- the "style" attribute will be validated by an inline stylesheet scanner, so no need to define anything here - i hate having to special case this but no other choice -->
<attribute name="style"
description="The 'style' attribute provides the ability for users to change many attributes of the tag's contents using a strict syntax"/>
<attribute name="media">
<regexp-list>
<regexp value="[a-zA-Z0-9,\-\s]+"/>
</regexp-list>
<literal-list>
<literal value="screen"/>
<literal value="tty"/>
<literal value="tv"/>
<literal value="projection"/>
<literal value="handheld"/>
<literal value="print"/>
<literal value="braille"/>
<literal value="aural"/>
<literal value="all"/>
</literal-list>
</attribute>
<!-- Anchor related -->
<!-- onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
<attribute name="href">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="name">
<regexp-list>
<regexp value="[a-zA-Z0-9\-_\$]+"/>
<!--
have to allow the $ for .NET controls - although,
will users be supplying input that has server-generated
.NET control names? methinks not, but i want to pass my
test cases
-->
</regexp-list>
</attribute>
<attribute name="shape" description="The 'shape' attribute defines the shape of the selectable area">
<literal-list>
<literal value="default"/>
<literal value="rect"/>
<literal value="circle"/>
<literal value="poly"/>
</literal-list>
</attribute>
<!-- Table attributes -->
<attribute name="border">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cellpadding">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cellspacing">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="colspan">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="rowspan">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="background">
<regexp-list>
<regexp name="onsiteURL"/>
</regexp-list>
</attribute>
<attribute name="bgcolor">
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
</regexp-list>
</attribute>
<attribute name="abbr">
<regexp-list>
<regexp name="paragraph"/>
</regexp-list>
</attribute>
<attribute name="headers" description="The 'headers' attribute is a space-separated list of cell IDs">
<regexp-list>
<regexp value="[a-zA-Z0-9\s*]*"/>
</regexp-list>
</attribute>
<attribute name="charoff">
<regexp-list>
<regexp value="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="char">
<regexp-list>
<regexp value=".{0,1}"/>
</regexp-list>
</attribute>
<attribute name="axis" description="The 'headers' attribute is a comma-separated list of related header cells">
<regexp-list>
<regexp value="[a-zA-Z0-9\s*,]*"/>
</regexp-list>
</attribute>
<attribute name="nowrap"
description="The 'nowrap' attribute tells the browser not to wrap text that goes over one line">
<regexp-list>
<regexp name="anything"/>
<!-- <regexp value="(nowrap){0,1}"/> -->
</regexp-list>
</attribute>
<!-- Common positioning attributes -->
<attribute name="width">
<regexp-list>
<regexp name="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="height">
<regexp-list>
<regexp name="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="align"
description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
<literal-list>
<literal value="center"/>
<literal value="middle"/>
<literal value="left"/>
<literal value="right"/>
<literal value="justify"/>
<literal value="char"/>
</literal-list>
</attribute>
<attribute name="valign"
description="The 'valign' attribute of an HTML attribute is a direction word, like 'baseline','bottom','middle' or 'top'">
<literal-list>
<literal value="baseline"/>
<literal value="bottom"/>
<literal value="middle"/>
<literal value="top"/>
</literal-list>
</attribute>
<!-- Intrinsic JavaScript Events -->
<attribute name="onFocus"
description="The 'onFocus' event is executed when the control associated with the tag gains focus">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onBlur"
description="The 'onBlur' event is executed when the control associated with the tag loses focus">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onClick"
description="The 'onClick' event is executed when the control associated with the tag is clicked">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onDblClick"
description="The 'onDblClick' event is executed when the control associated with the tag is clicked twice immediately">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseDown"
description="The 'onMouseDown' event is executed when the control associated with the tag is clicked but not yet released">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseUp"
description="The 'onMouseUp' event is executed when the control associated with the tag is clicked after the button is released">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseOver"
description="The 'onMouseOver' event is executed when the user's mouse hovers over the control associated with the tag">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="scope" description="The 'scope' attribute defines what's covered by the header cells">
<literal-list>
<literal value="row"/>
<literal value="col"/>
<literal value="rowgroup"/>
<literal value="colgroup"/>
</literal-list>
</attribute>
<!-- If you want users to be able to mess with tabindex, uncomment this -->
<!--
<attribute name="tabindex" description="...">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
-->
<!-- Input/form related common attributes -->
<attribute name="disabled">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="readonly">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="accesskey">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="size">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="autocomplete">
<literal-list>
<literal value="on"/>
<literal value="off"/>
</literal-list>
</attribute>
<attribute name="rows">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cols">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while? Even wars of attrition, surely?
-->
<global-tag-attributes>
<!-- Not valid in base, head, html, meta, param, script, style, and title elements. -->
<attribute name="id"/>
<attribute name="style"/>
<attribute name="title"/>
<attribute name="class"/>
<!-- Not valid in base, br, frame, frameset, hr, iframe, param, and script elements. -->
<attribute name="lang"/>
</global-tag-attributes>
<tags-to-encode>
<tag>g</tag>
<tag>grin</tag>
</tags-to-encode>
<tag-rules>
<!-- Tags related to JavaScript -->
<tag name="script" action="remove"/>
<tag name="noscript"
action="validate"/> <!-- although no javascript can fire inside a noscript tag, css is still a viable attack vector -->
<!-- Frame & related tags -->
<tag name="iframe" action="remove"/>
<tag name="frameset" action="remove"/>
<tag name="frame" action="remove"/>
<!-- Form related tags -->
<tag name="label" action="validate">
<attribute name="for">
<regexp-list>
<regexp name="htmlId"/>
</regexp-list>
</attribute>
</tag>
<!-- All formatting tags -->
<tag name="h1" action="validate"/>
<tag name="h2" action="validate"/>
<tag name="h3" action="validate"/>
<tag name="h4" action="validate"/>
<tag name="h5" action="validate"/>
<tag name="h6" action="validate"/>
<tag name="p" action="validate">
<attribute name="align"/>
</tag>
<tag name="i" action="validate"/>
<tag name="b" action="validate"/>
<tag name="u" action="validate"/>
<tag name="strong" action="validate"/>
<tag name="em" action="validate"/>
<tag name="small" action="validate"/>
<tag name="big" action="validate"/>
<tag name="pre" action="validate"/>
<tag name="code" action="validate"/>
<tag name="cite" action="validate"/>
<tag name="samp" action="validate"/>
<tag name="sub" action="validate"/>
<tag name="sup" action="validate"/>
<tag name="strike" action="validate"/>
<tag name="center" action="validate"/>
<tag name="blockquote" action="validate"/>
<tag name="hr" action="validate"/>
<tag name="br" action="validate"/>
<tag name="font" action="validate">
<attribute name="color">
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
</regexp-list>
</attribute>
<attribute name="face">
<regexp-list>
<regexp value="[\w;, \-]+"/>
</regexp-list>
</attribute>
<attribute name="size">
<regexp-list>
<regexp value="(\+|-){0,1}(\d)+"/>
</regexp-list>
</attribute>
</tag>
<!-- Anchor and anchor related tags -->
<tag name="a" action="validate">
<!-- onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
<attribute name="href"/>
<attribute name="onFocus"/>
<attribute name="onBlur"/>
<attribute name="nohref">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="nofollow"/>
</literal-list>
</attribute>
<attribute name="name"/>
</tag>
<tag name="map" action="validate"/>
<!-- base tag removed per demo - this could be enabled with literal-list values you allow -->
<!--
<tag name="base" action="validate">
<attribute name="href"/>
</tag>
-->
<!-- Stylesheet Tags -->
<tag name="style" action="validate">
<attribute name="type">
<literal-list>
<literal value="text/css"/>
</literal-list>
</attribute>
<attribute name="media"/>
</tag>
<tag name="span" action="validate"/>
<tag name="div" action="validate">
<attribute name="align"/>
</tag>
<!-- <attribute name="id"/> what could an attacker do if they could overwrite an existing div definition? prolly something bad -->
<!-- <attribute name="class"/> what could an attacker do if they could specify any class in the namespace? prolly something bad -->
<!-- Image & image related tags -->
<tag name="img" action="validate">
<attribute name="src" onInvalid="removeTag">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="name"/>
<attribute name="alt"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="border"/>
<attribute name="align"/>
<attribute name="hspace">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="vspace">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
</tag>
<!-- no way to do this safely without hooking up the same code to @import to embed the remote stylesheet (malicious user could change offsite resource to be malicious after validation -->
<!-- <attribute name="href" onInvalid="removeTag"/> -->
<tag name="link" action="validate">
<!-- <attribute name="href" onInvalid="removeTag"/> -->
<attribute name="media"/>
<attribute name="type" onInvalid="removeTag">
<literal-list>
<literal value="text/css"/>
<literal value="application/rss+xml"/>
<literal value="image/x-icon"/>
</literal-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="stylesheet"/>
<literal value="shortcut icon"/>
<literal value="search"/>
<literal value="copyright"/>
<literal value="top"/>
<literal value="alternate"/>
</literal-list>
</attribute>
</tag>
<!-- List tags -->
<tag name="ul" action="validate"/>
<tag name="ol" action="validate"/>
<tag name="li" action="validate"/>
<!-- Dictionary tags -->
<tag name="dd" action="truncate"/>
<tag name="dl" action="truncate"/>
<tag name="dt" action="truncate"/>
<!-- Table tags (tbody, thead, tfoot)-->
<tag name="thead" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="tbody" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="tfoot" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="table" action="validate">
<attribute name="height"/>
<attribute name="width"/>
<attribute name="border"/>
<attribute name="bgcolor"/>
<attribute name="cellpadding"/>
<attribute name="cellspacing"/>
<attribute name="background"/>
<attribute name="align"/>
<attribute name="noresize">
<literal-list>
<literal value="noresize"/>
<literal value=""/>
</literal-list>
</attribute>
</tag>
<tag name="td" action="validate">
<attribute name="background"/>
<attribute name="bgcolor"/>
<attribute name="abbr"/>
<attribute name="axis"/>
<attribute name="headers"/>
<attribute name="scope"/>
<attribute name="nowrap"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="colspan"/>
<attribute name="rowspan"/>
</tag>
<tag name="th" action="validate">
<attribute name="abbr"/>
<attribute name="axis"/>
<attribute name="headers"/>
<attribute name="scope"/>
<attribute name="nowrap"/>
<attribute name="bgcolor"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="colspan"/>
<attribute name="rowspan"/>
</tag>
<tag name="tr" action="validate">
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="valign"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="background"/>
</tag>
<tag name="colgroup" action="validate">
<attribute name="span">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="col" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="span">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="width"/>
</tag>
<tag name="fieldset" action="validate"/>
<tag name="legend" action="validate"/>
</tag-rules>
<!-- CSS validation processing rules -->
<css-rules>
<property name="azimuth"
description="This property is most likely to be implemented by mixing the same signal into different channels at differing volumes.">
<literal-list>
<literal value="left-side"/>
<literal value="far-left"/>
<literal value="left"/>
<literal value="center-left"/>
<literal value="center"/>
<literal value="center-right"/>
<literal value="right"/>
<literal value="far-right"/>
<literal value="right-side"/>
<literal value="behind"/>
<literal value="leftwards"/>
<literal value="rightwards"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="angle"/>
</regexp-list>
</property>
<property name="background"
description="The 'background' property is a shorthand property for setting the individual background properties (i.e., 'background-color', 'background-image', 'background-repeat', 'background-attachment' and 'background-position') at the same place in the style sheet.">
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="background-color"/>
<shorthand name="background-image"/>
<shorthand name="background-repeat"/>
<shorthand name="background-attachment"/>
<shorthand name="background-position"/>
</shorthand-list>
</property>
<property name="background-attachment"
description="If a background image is specified, this property specifies whether it is fixed with regard to the viewport ('fixed') or scrolls along with the document ('scroll').">
<literal-list>
<literal value="scroll"/>
<literal value="fixed"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="background-color"
description="This property sets the background color of an element, either a &lt;color&gt; value or the keyword 'transparent', to make the underlying colors shine through.">
<literal-list>
<literal value="transparent"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="background-image" description="This property sets the background image of an element.">
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="background-position"
description="If a background image has been specified, this property specifies its initial position.">
<literal-list>
<literal value="top"/>
<literal value="center"/>
<literal value="bottom"/>
<literal value="left"/>
<literal value="center"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="percentage"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="background-repeat"
description="If a background image is specified, this property specifies whether the image is repeated (tiled), and how.">
<literal-list>
<literal value="repeat"/>
<literal value="repeat-x"/>
<literal value="repeat-y"/>
<literal value="no-repeat"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- Begin simple properties -->
<property name="border-collapse" default="collapse" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="collapse"/>
<literal value="separate"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="border-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="transparent"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-top-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-right-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-bottom-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-left-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="bottom" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="caption-side" default="top" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="top"/>
<literal value="bottom"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="clear" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="left"/>
<literal value="right"/>
<literal value="both"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="cue-after" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="cue-before" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="direction" default="ltr" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="ltr"/>
<literal value="rtl"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="display" default="inline" description="">
<category-list>
<category value="all"/>
</category-list>
<literal-list>
<literal value="inline"/>
<literal value="block"/>
<literal value="list-item"/>
<literal value="run-in"/>
<literal value="compact"/>
<literal value="marker"/>
<literal value="table"/>
<literal value="inline-table"/>
<literal value="table-row-group"/>
<literal value="table-header-group"/>
<literal value="table-footer-group"/>
<literal value="table-row"/>
<literal value="table-column-group"/>
<literal value="table-column"/>
<literal value="table-cell"/>
<literal value="table-caption"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="elevation" default="level" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="below"/>
<literal value="level"/>
<literal value="above"/>
<literal value="higher"/>
<literal value="lower"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="angle"/>
</regexp-list>
</property>
<property name="empty-cells" default="show" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="show"/>
<literal value="hide"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="float" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="left"/>
<literal value="right"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-size" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="absolute-size"/>
<regexp name="relative-size"/>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="font-size-adjust" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="font-stretch" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="wider"/>
<literal value="narrower"/>
<literal value="ultra-condensed"/>
<literal value="extra-condensed"/>
<literal value="condensed"/>
<literal value="semi-condensed"/>
<literal value="semi-expanded"/>
<literal value="expanded"/>
<literal value="extra-expanded"/>
<literal value="ultra-expanded"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-style" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="italic"/>
<literal value="oblique"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-variant" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="small-caps"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-weight" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="bold"/>
<literal value="bolder"/>
<literal value="lighter"/>
<literal value="100"/>
<literal value="200"/>
<literal value="300"/>
<literal value="400"/>
<literal value="500"/>
<literal value="600"/>
<literal value="700"/>
<literal value="800"/>
<literal value="900"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="height" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="left" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="letter-spacing" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="line-height" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="list-style-image" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="list-style-position" default="outside" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inside"/>
<literal value="outside"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="list-style-type" default="disc" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="disc"/>
<literal value="circle"/>
<literal value="square"/>
<literal value="decimal"/>
<literal value="decimal-leading-zero"/>
<literal value="lower-roman"/>
<literal value="upper-roman"/>
<literal value="lower-greek"/>
<literal value="lower-alpha"/>
<literal value="lower-latin"/>
<literal value="upper-alpha"/>
<literal value="upper-latin"/>
<literal value="hebrew"/>
<literal value="armenian"/>
<literal value="georgian"/>
<literal value="cjk-ideographic"/>
<literal value="hiragana"/>
<literal value="katakana"/>
<literal value="hiragana-iroha"/>
<literal value="katakana-iroha"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="marker-offset" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="max-height" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="max-width" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="min-height" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="min-width" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="orphans" default="2" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="outline-color" default="invert" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="invert"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="overflow" default="visible" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="visible"/>
<literal value="hidden"/>
<literal value="scroll"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-after" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="always"/>
<literal value="avoid"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-before" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="always"/>
<literal value="avoid"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-inside" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="avoid"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="pause-after" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="pause-before" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="pitch" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="x-low"/>
<literal value="low"/>
<literal value="medium"/>
<literal value="high"/>
<literal value="x-high"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="frequency"/>
</regexp-list>
</property>
<property name="pitch-range" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="position" default="static" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="static"/>
<!-- possible to perform phishing attacks with the following -->
<!--
<literal value="relative"/>
<literal value="absolute"/>
<literal value="fixed"/>
-->
<literal value="inherit"/>
</literal-list>
</property>
<property name="richness" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="right" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="size" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="portrait"/>
<literal value="landscape"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="speak" default="normal" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="none"/>
<literal value="spell-out"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-header" default="once" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="once"/>
<literal value="always"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-numeral" default="continuous" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="digits"/>
<literal value="continuous"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-punctuation" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="code"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speech-rate" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="x-slow"/>
<literal value="slow"/>
<literal value="medium"/>
<literal value="fast"/>
<literal value="x-fast"/>
<literal value="faster"/>
<literal value="slower"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="stress" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="table-layout" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="fixed"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="text-indent" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="text-transform" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="capitalize"/>
<literal value="uppercase"/>
<literal value="lowercase"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="top" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="unicode-bidi" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="embed"/>
<literal value="bidi-override"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="vertical-align" default="baseline" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="baseline"/>
<literal value="sub"/>
<literal value="super"/>
<literal value="top"/>
<literal value="text-top"/>
<literal value="middle"/>
<literal value="bottom"/>
<literal value="text-bottom"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="percentage"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="visibility" default="inherit" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="visible"/>
<literal value="hidden"/>
<literal value="collapse"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="volume" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="silent"/>
<literal value="x-soft"/>
<literal value="soft"/>
<literal value="medium"/>
<literal value="loud"/>
<literal value="x-loud"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="white-space" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="pre"/>
<literal value="nowrap"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="widows" default="2" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="width" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="word-spacing" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<!-- end simple properties -->
<!-- begin medium properties -->
<property name="border-style" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="none"/>
<literal value="hidden"/>
<literal value="dotted"/>
<literal value="dashed"/>
<literal value="solid"/>
<literal value="double"/>
<literal value="groove"/>
<literal value="ridge"/>
<literal value="inset"/>
<literal value="outset"/>
</literal-list>
</property>
<property name="border-top-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
</property>
<property name="border-right-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-bottom-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-left-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-top-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-right-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-bottom-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-left-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-width" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="thin"/>
<literal value="medium"/>
<literal value="thick"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="margin" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="auto"/>
</literal-list>
<regexp-list>
<regexp name="positiveLength"/>
<regexp name="positivePercentage"/>
</regexp-list>
</property>
<property name="margin-top" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-right" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-bottom" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-left" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="outline-style" default="none" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="outline-width" default="medium" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="padding" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="padding-top" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-right" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-bottom" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-left" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<!-- end medium properties -->
<!-- begin hard properties -->
<property name="border" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-top" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-right" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-bottom" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-left" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="cue" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="cue-before"/>
<shorthand name="cue-after"/>
</shorthand-list>
</property>
<property name="list-style" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="list-style-type"/>
<shorthand name="list-style-position"/>
<shorthand name="list-style-image"/>
</shorthand-list>
</property>
<property name="marks" default="none" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="crop"/>
<literal value="cross"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="outline" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="outline-color"/>
<shorthand name="outline-style"/>
<shorthand name="outline-width"/>
</shorthand-list>
</property>
<property name="pause" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="text-decoration" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="underline"/>
<literal value="overline"/>
<literal value="line-through"/>
<literal value="blink"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- end hard properties -->
<!-- begin manual properties -->
<property name="border-spacing" default="0"
description="The lengths specify the distance that separates adjacent cell borders. If one length is specified, it gives both the horizontal and vertical spacing. If two are specified, the first gives the horizontal spacing and the second the vertical spacing. Lengths may not be negative.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="clip" default="auto"
description="The 'clip' property applies to elements that have a 'overflow' property with a value other than 'visible'.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="counter-increment" default="none"
description="The 'counter-increment' property accepts one or more names of counters (identifiers), each one optionally followed by an integer.">
<category-list>
<category value="all"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssIdentifier"/>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="cursor" default="auto"
description="This property specifies the type of cursor to be displayed for the pointing device.">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
<literal value="crosshair"/>
<literal value="default"/>
<literal value="pointer"/>
<literal value="move"/>
<literal value="e-resize"/>
<literal value="ne-resize"/>
<literal value="nw-resize"/>
<literal value="n-resize"/>
<literal value="se-resize"/>
<literal value="sw-resize"/>
<literal value="s-resize"/>
<literal value="w-resize| text"/>
<literal value="wait"/>
<literal value="help"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="text-shadow" default="none"
description="This property accepts a comma-separated list of shadow effects to be applied to the text of the element.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="font"
description="The 'font' property is, except as described below, a shorthand property for setting 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', and 'font-family', at the same place in the style sheet.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="/"/>
<literal value="caption"/>
<literal value="icon"/>
<literal value="menu"/>
<literal value="message-box"/>
<literal value="small-caption"/>
<literal value="status-bar"/>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="font-style"/>
<shorthand name="font-variant"/>
<shorthand name="font-weight"/>
<shorthand name="font-size"/>
<shorthand name="line-height"/>
<shorthand name="font-family"/>
</shorthand-list>
</property>
<property name="font-family"
description="This property specifies a prioritized list of font family names and/or generic family names.">
<category-list>
<category value="visual"/>
</category-list>
<!-- allowing only generic font families -->
<literal-list>
<literal value="serif"/>
<literal value="arial"/>
<literal value="lucida console"/>
<literal value="sans-serif"/>
<literal value="cursive"/>
<literal value="verdana"/>
<literal value="fantasy"/>
<literal value="monospace"/>
</literal-list>
<regexp-list>
<regexp value="[\w,\-&apos;&quot; ]+"/>
</regexp-list>
</property>
<property name="page"
description="The 'page' property can be used to specify a particular type of page where an element should be displayed.">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
</literal-list>
<regexp-list>
<regexp name="cssIdentifier"/>
</regexp-list>
</property>
<property name="play-during" default="auto"
description="Similar to the 'cue-before' and 'cue-after' properties, this property specifies a sound to be played as a background while an element's content is spoken.">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="mix"/>
<literal value="repeat"/>
<literal value="none"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="text-align" description="This property describes how inline content of a block is aligned.">
<category-list>
<category value="visual"/>
</category-list>
<!-- For safety, ignoring string alignment which can be used to line table cells on characters -->
<literal-list>
<literal value="left"/>
<literal value="right"/>
<literal value="center"/>
<literal value="justify"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="voice-family"
description="The value is a comma-separated, prioritized list of voice family names (compare with 'font-family').">
<category-list>
<category value="aural"/>
</category-list>
<!-- Allowing only generic voice family -->
<literal-list>
<literal value="male"/>
<literal value="female"/>
<literal value="child"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- end manual properties -->
</css-rules>
<allowed-empty-tags>
<literal-list>
<literal value="br"/>
<literal value="hr"/>
<literal value="a"/>
<literal value="img"/>
<literal value="link"/>
<literal value="iframe"/>
<literal value="script"/>
<literal value="object"/>
<literal value="applet"/>
<literal value="frame"/>
<literal value="base"/>
<literal value="param"/>
<literal value="meta"/>
<literal value="input"/>
<literal value="textarea"/>
<literal value="embed"/>
<literal value="basefont"/>
<literal value="col"/>
<literal value="div"/>
</literal-list>
</allowed-empty-tags>
</anti-samy-rules>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="0"/>
<directive name="useXHTML" value="true"/>
<directive name="formatOutput" value="false"/>
<!--
remember, this won't work for relative URIs - AntiSamy doesn't
know anything about the URL or your web structure
-->
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while? Even wars of attrition, surely?
-->
<global-tag-attributes>
</global-tag-attributes>
<tags-to-encode>
</tags-to-encode>
<tag-rules>
</tag-rules>
<!-- CSS validation processing rules -->
<css-rules>
<!-- end manual properties -->
</css-rules>
<allowed-empty-tags>
</allowed-empty-tags>
</anti-samy-rules>
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 8999 #tomcat端口
#===================== 数据源配置 =====================
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${MYSQL_USER:junmp123}
password: ${MYSQL_PWD:123456}
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DB:db_key_app}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true&queryTimeout=2400&nullCatalogMeansCurrent=true
#===================== Redis配置 =====================
redis:
database: 1 #缓存库编号
host: 192.168.3.128
port: 6379
password:
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
mail:
host: smtp.qq.com #邮件服务器的host
password: sb #邮件服务器的发件人密码
username: 6666@qq.com #邮件服务器的发件人
port: 25 #smtp默认端口
protocol: smtp #使用smtp协议
default-encoding: UTF-8 #邮件使用的字符集
properties:
mail:
debug: true #启调试模式(发送邮件的细节都能看出来) 默认值为fasle
debug.auth: true
smtp:
auth: true #如果为true ,则尝试使用auth命令对用户进行身份验证 默认为false
connectiontimeout: 20000 #套接字连接超时值(毫秒)。默认值为无限超时。
sendpartial: true #如果为true 并且邮件有一些有效和无效的地址 并使用SendFailException 报告部分失败, 如果设置为false(默认值) 如果存在无效的收件人地址, 则不会将邮件发送给任何收件人
starttls:
#如果为true,则在发出任何登录命令之前,启用starttl命令(如果服务器支持) 将连接切换到受TLS保护的连接,请注意,必须配置适当的信任存储,以便客户端信任服务器的证书,默认为false
enable: true
# 如果为true,则需要使用 starttl命令,如果服务器不支持此命令,或者该命令失败,connect()将失败,默认为false 如果此设置为true james邮件服务器会报错 STARTTLS is required but host does not support STARTTLS
required: false
timeout: 20000 #I/O超时值(ms) 默认为无限超时
userset: true #如果设置为true,则在isConnected()中使用RSET命令而不是NOOP命令 在某些情况下,sendmail在执行许多NOOP命令后响应缓存,使用RSET可以避免这个sendMail问题,默认为false
flowable:
dmn:
enabled: false
cmmn:
enabled: false
idm:
enabled: false
async-history-executor-activate: false
async-executor-activate: false
check-process-definitions: false
content:
enabled: false
app:
enabled: false
eventregistry:
enabled: false
config:
minio:
endpoint: http://192.168.0.147:9000/ #服务端地址
accessKey: admin #账号
secretKey: test. #密码
fileHost: http://192.168.0.147:9000/ #地址
spring: #环境 dev|test|pro|preview
profiles:
active: dev
servlet:
multipart: #文件传输配置
max-file-size: 100MB #单个数据大小限制
max-request-size: 100MB #请求总数据大小限制
enabled: true #是否启用分段上传支持
mvc:
hiddenmethod: #隐式方法过滤器
filter:
enabled: true #默认关闭。开启以支持:PUT,DELETE表单提交方法
jackson: #序列化和反序列化json框架
serialization:
write-dates-as-timestamps: true #是否写入日期时间时间戳格式
time-zone: GMT+8 #指定日期格式化时区
main:
allow-bean-definition-overriding: true #允许同名bean后者覆盖,默认:true
allow-circular-references: true #允许Bean相互引用,默认:false
server:
error:
whitelabel:
enabled: false
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--日志格式应用spring boot默认的格式,也可以自己更改-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
<springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log/systemLog"/>
<!-- ****************************************************************************************** -->
<!-- ****************************** 本地开发只在控制台打印日志 ************************************ -->
<!-- ****************************************************************************************** -->
<springProfile name="dev">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--默认所有的包以info-->
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<!--各个服务的包在本地执行的时候,打开debug模式-->
<logger name="com" level="debug" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
</springProfile>
<!-- ********************************************************************************************** -->
<!-- **** 放到服务器上不管在什么环境都只在文件记录日志,控制台(catalina.out)打印logback捕获不到的日志 **** -->
<!-- ********************************************************************************************** -->
<springProfile name="test,pro,me,preview">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 日志记录器,日期滚动记录,level为 ERROR 日志 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd,aux}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 INFO 日志 -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_info.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd,aux}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 WARN 日志 -->
<appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_warn.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 DEBUG 日志 -->
<appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_debug.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd,aux}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 ALL 日志 -->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_total.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/total/%d{yyyy-MM-dd,aux}/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--记录到文件时-->
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_WARN"/>
<appender-ref ref="FILE_DEBUG"/>
<appender-ref ref="FILE_ALL"/>
</root>
</springProfile>
</configuration>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="20000"/>
<directive name="useXHTML" value="true"/>
<directive name="formatOutput" value="true"/>
<!--
remember, this won't work for relative URIs - AntiSamy doesn't
know anything about the URL or your web structure
-->
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
<!--
From W3C:
This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class
name or names. Multiple class names must be separated by white
space characters.
-->
<!-- The 16 colors defined by the HTML Spec (also used by the CSS Spec) -->
<regexp name="colorName"
value="(aqua|black|blue|fuchsia|gray|grey|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow)"/>
<!-- HTML/CSS Spec allows 3 or 6 digit hex to specify color -->
<regexp name="colorCode" value="(#([0-9a-fA-F]{6}|[0-9a-fA-F]{3}))"/>
<regexp name="anything" value=".*"/>
<regexp name="numberOrPercent" value="(\d)+(%{0,1})"/>
<regexp name="paragraph" value="([\p{L}\p{N},'\.\s\-_\(\)]|&amp;[0-9]{2};)*"/>
<regexp name="htmlId" value="[a-zA-Z0-9\:\-_\.]+"/>
<regexp name="htmlTitle"
value="[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&amp;]*"/> <!-- force non-empty with a '+' at the end instead of '*' -->
<regexp name="htmlClass" value="[a-zA-Z0-9\s,\-_]+"/>
<regexp name="onsiteURL"
value="^(?!//)(?![\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*(&amp;colon))[\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*"/>
<regexp name="offsiteURL"
value="(\s)*((ht|f)tp(s?)://|mailto:)[\p{L}\p{N}]+[\p{L}\p{N}\p{Zs}\.\#@\$%\+&amp;;:\-_~,\?=/!\(\)]*(\s)*"/>
<regexp name="boolean" value="(true|false)"/>
<regexp name="singlePrintable" value="[a-zA-Z0-9]{1}"/> <!-- \w allows the '_' character -->
<!-- This is for elements (ex: elemName { ... }) -->
<regexp name="cssElementSelector" value="[a-zA-Z0-9\-_]+|\*"/>
<!-- This is to list out any element names that are *not* valid -->
<regexp name="cssElementExclusion" value=""/>
<!-- This if for classes (ex: .className { ... }) -->
<regexp name="cssClassSelector" value="\.[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any class names that are *not* valid -->
<regexp name="cssClassExclusion" value=""/>
<!-- This is for ID selectors (ex: #myId { ... } -->
<regexp name="cssIDSelector" value="#[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any IDs that are *not* valid - FIXME: What should the default be to avoid div hijacking? *? -->
<regexp name="cssIDExclusion" value=""/>
<!-- This is for pseudo-element selector (ex. foo:pseudo-element { ... } -->
<regexp name="cssPseudoElementSelector" value=":[a-zA-Z0-9\-_]+"/>
<!-- This is to list out any psuedo-element names that are *not* valid -->
<regexp name="cssPsuedoElementExclusion" value=""/>
<!-- This is for attribute selectors (ex. foo[attr=value] { ... } -->
<regexp name="cssAttributeSelector" value="\[[a-zA-Z0-9\-_]+((=|~=|\|=){1}[a-zA-Z0-9\-_]+){1}\]"/>
<!-- This is to list out any attribute names that are *not* valid -->
<regexp name="cssAttributeExclusion" value=""/>
<!-- This is for resources referenced from CSS (such as background images and other imported stylesheets) -->
<regexp name="cssOnsiteUri" value="url\(([\p{L}\p{N}\\/\.\?=\#&amp;;\-_~]+|\#(\w)+)\)"/>
<regexp name="cssOffsiteUri"
value="url\((\s)*((ht|f)tp(s?)://)[\p{L}\p{N}]+[~\p{L}\p{N}\p{Zs}\-_\.@#$%&amp;;:,\?=/\+!]*(\s)*\)"/>
<!-- This if for CSS Identifiers -->
<regexp name="cssIdentifier" value="[a-zA-Z0-9\-_]+"/>
<!-- This is for comments within CSS (ex. /* comment */) -->
<regexp name="cssCommentText" value="[\p{L}\p{N}\-_,\/\\\.\s\(\)!\?\=\$#%\^&amp;:&quot;']+"/>
<regexp name="integer" value="(-|\+)?[0-9]+"/>
<regexp name="positiveInteger" value="(\+)?[0-9]+"/>
<regexp name="number" value="(-|\+)?([0-9]+(\.[0-9]+)?)"/>
<regexp name="angle" value="(-|\+)?([0-9]+(\.[0-9]+)?)(deg|grads|rad)"/>
<regexp name="time" value="([0-9]+(\.[0-9]+)?)(ms|s)"/>
<regexp name="frequency" value="([0-9]+(\.[0-9]+)?)(hz|khz)"/>
<regexp name="length" value="((-|\+)?0|(-|\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
<regexp name="positiveLength" value="((\+)?0|(\+)?([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc))"/>
<regexp name="percentage" value="(-|\+)?([0-9]+(\.[0-9]+)?)%"/>
<regexp name="positivePercentage" value="(\+)?([0-9]+(\.[0-9]+)?)%"/>
<regexp name="absolute-size" value="(xx-small|x-small|small|medium|large|x-large|xx-large)"/>
<regexp name="relative-size" value="(larger|smaller)"/>
<!-- Used for CSS Color specifications (complex regexp expresses integer values of 0-255) -->
<regexp name="rgbCode"
value="rgb\(([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]),([1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\)"/>
<!-- CSS2 Allowed System Color Values -->
<regexp name="systemColor"
value="(activeborder|activecaption|appworkspace|background|buttonface|buttonhighlight|buttonshadow|buttontext|captiontext|graytext|highlight|highlighttext|inactiveborder|inactivecaption|inactivecaptiontext|infobackground|infotext|menu|menutext|scrollbar|threeddarkshadow|threedface|threedhighlight|threedlightshadow|threedshadow|window|windowframe|windowtext)"/>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
<!-- Common to all HTML tags -->
<attribute name="id"
description="The 'id' of any HTML attribute should not contain anything besides letters and numbers">
<regexp-list>
<regexp name="htmlId"/>
</regexp-list>
</attribute>
<attribute name="class"
description="The 'class' of any HTML attribute is usually a single word, but it can also be a list of class names separated by spaces">
<regexp-list>
<regexp name="htmlClass"/>
</regexp-list>
</attribute>
<attribute name="lang"
description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
<regexp-list>
<regexp value="[a-zA-Z]{2,20}"/>
</regexp-list>
</attribute>
<attribute name="title"
description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
<regexp-list>
<regexp name="htmlTitle"/>
</regexp-list>
</attribute>
<attribute name="alt"
description="The 'alt' attribute provides alternative text to users when its visual representation is not available">
<regexp-list>
<regexp name="paragraph"/>
</regexp-list>
</attribute>
<!-- the "style" attribute will be validated by an inline stylesheet scanner, so no need to define anything here - i hate having to special case this but no other choice -->
<attribute name="style"
description="The 'style' attribute provides the ability for users to change many attributes of the tag's contents using a strict syntax"/>
<attribute name="media">
<regexp-list>
<regexp value="[a-zA-Z0-9,\-\s]+"/>
</regexp-list>
<literal-list>
<literal value="screen"/>
<literal value="tty"/>
<literal value="tv"/>
<literal value="projection"/>
<literal value="handheld"/>
<literal value="print"/>
<literal value="braille"/>
<literal value="aural"/>
<literal value="all"/>
</literal-list>
</attribute>
<!-- Anchor related -->
<!-- onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
<attribute name="href">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="name">
<regexp-list>
<regexp value="[a-zA-Z0-9\-_\$]+"/>
<!--
have to allow the $ for .NET controls - although,
will users be supplying input that has server-generated
.NET control names? methinks not, but i want to pass my
test cases
-->
</regexp-list>
</attribute>
<attribute name="shape" description="The 'shape' attribute defines the shape of the selectable area">
<literal-list>
<literal value="default"/>
<literal value="rect"/>
<literal value="circle"/>
<literal value="poly"/>
</literal-list>
</attribute>
<!-- Table attributes -->
<attribute name="border">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cellpadding">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cellspacing">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="colspan">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="rowspan">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="background">
<regexp-list>
<regexp name="onsiteURL"/>
</regexp-list>
</attribute>
<attribute name="bgcolor">
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
</regexp-list>
</attribute>
<attribute name="abbr">
<regexp-list>
<regexp name="paragraph"/>
</regexp-list>
</attribute>
<attribute name="headers" description="The 'headers' attribute is a space-separated list of cell IDs">
<regexp-list>
<regexp value="[a-zA-Z0-9\s*]*"/>
</regexp-list>
</attribute>
<attribute name="charoff">
<regexp-list>
<regexp value="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="char">
<regexp-list>
<regexp value=".{0,1}"/>
</regexp-list>
</attribute>
<attribute name="axis" description="The 'headers' attribute is a comma-separated list of related header cells">
<regexp-list>
<regexp value="[a-zA-Z0-9\s*,]*"/>
</regexp-list>
</attribute>
<attribute name="nowrap"
description="The 'nowrap' attribute tells the browser not to wrap text that goes over one line">
<regexp-list>
<regexp name="anything"/>
<!-- <regexp value="(nowrap){0,1}"/> -->
</regexp-list>
</attribute>
<!-- Common positioning attributes -->
<attribute name="width">
<regexp-list>
<regexp name="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="height">
<regexp-list>
<regexp name="numberOrPercent"/>
</regexp-list>
</attribute>
<attribute name="align"
description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
<literal-list>
<literal value="center"/>
<literal value="middle"/>
<literal value="left"/>
<literal value="right"/>
<literal value="justify"/>
<literal value="char"/>
</literal-list>
</attribute>
<attribute name="valign"
description="The 'valign' attribute of an HTML attribute is a direction word, like 'baseline','bottom','middle' or 'top'">
<literal-list>
<literal value="baseline"/>
<literal value="bottom"/>
<literal value="middle"/>
<literal value="top"/>
</literal-list>
</attribute>
<!-- Intrinsic JavaScript Events -->
<attribute name="onFocus"
description="The 'onFocus' event is executed when the control associated with the tag gains focus">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onBlur"
description="The 'onBlur' event is executed when the control associated with the tag loses focus">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onClick"
description="The 'onClick' event is executed when the control associated with the tag is clicked">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onDblClick"
description="The 'onDblClick' event is executed when the control associated with the tag is clicked twice immediately">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseDown"
description="The 'onMouseDown' event is executed when the control associated with the tag is clicked but not yet released">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseUp"
description="The 'onMouseUp' event is executed when the control associated with the tag is clicked after the button is released">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="onMouseOver"
description="The 'onMouseOver' event is executed when the user's mouse hovers over the control associated with the tag">
<literal-list>
<literal value="javascript:void(0)"/>
<literal value="javascript:history.go(-1)"/>
</literal-list>
</attribute>
<attribute name="scope" description="The 'scope' attribute defines what's covered by the header cells">
<literal-list>
<literal value="row"/>
<literal value="col"/>
<literal value="rowgroup"/>
<literal value="colgroup"/>
</literal-list>
</attribute>
<!-- If you want users to be able to mess with tabindex, uncomment this -->
<!--
<attribute name="tabindex" description="...">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
-->
<!-- Input/form related common attributes -->
<attribute name="disabled">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="readonly">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="accesskey">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="size">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="autocomplete">
<literal-list>
<literal value="on"/>
<literal value="off"/>
</literal-list>
</attribute>
<attribute name="rows">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="cols">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while? Even wars of attrition, surely?
-->
<global-tag-attributes>
<!-- Not valid in base, head, html, meta, param, script, style, and title elements. -->
<attribute name="id"/>
<attribute name="style"/>
<attribute name="title"/>
<attribute name="class"/>
<!-- Not valid in base, br, frame, frameset, hr, iframe, param, and script elements. -->
<attribute name="lang"/>
</global-tag-attributes>
<tags-to-encode>
<tag>g</tag>
<tag>grin</tag>
</tags-to-encode>
<tag-rules>
<!-- Tags related to JavaScript -->
<tag name="script" action="remove"/>
<tag name="noscript"
action="validate"/> <!-- although no javascript can fire inside a noscript tag, css is still a viable attack vector -->
<!-- Frame & related tags -->
<tag name="iframe" action="remove"/>
<tag name="frameset" action="remove"/>
<tag name="frame" action="remove"/>
<!-- Form related tags -->
<tag name="label" action="validate">
<attribute name="for">
<regexp-list>
<regexp name="htmlId"/>
</regexp-list>
</attribute>
</tag>
<!-- All formatting tags -->
<tag name="h1" action="validate"/>
<tag name="h2" action="validate"/>
<tag name="h3" action="validate"/>
<tag name="h4" action="validate"/>
<tag name="h5" action="validate"/>
<tag name="h6" action="validate"/>
<tag name="p" action="validate">
<attribute name="align"/>
</tag>
<tag name="i" action="validate"/>
<tag name="b" action="validate"/>
<tag name="u" action="validate"/>
<tag name="strong" action="validate"/>
<tag name="em" action="validate"/>
<tag name="small" action="validate"/>
<tag name="big" action="validate"/>
<tag name="pre" action="validate"/>
<tag name="code" action="validate"/>
<tag name="cite" action="validate"/>
<tag name="samp" action="validate"/>
<tag name="sub" action="validate"/>
<tag name="sup" action="validate"/>
<tag name="strike" action="validate"/>
<tag name="center" action="validate"/>
<tag name="blockquote" action="validate"/>
<tag name="hr" action="validate"/>
<tag name="br" action="validate"/>
<tag name="font" action="validate">
<attribute name="color">
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
</regexp-list>
</attribute>
<attribute name="face">
<regexp-list>
<regexp value="[\w;, \-]+"/>
</regexp-list>
</attribute>
<attribute name="size">
<regexp-list>
<regexp value="(\+|-){0,1}(\d)+"/>
</regexp-list>
</attribute>
</tag>
<!-- Anchor and anchor related tags -->
<tag name="a" action="validate">
<!-- onInvalid="filterTag" has been removed as per suggestion at OWASP SJ 2007 - just "name" is valid -->
<attribute name="href"/>
<attribute name="onFocus"/>
<attribute name="onBlur"/>
<attribute name="nohref">
<regexp-list>
<regexp name="anything"/>
</regexp-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="nofollow"/>
</literal-list>
</attribute>
<attribute name="name"/>
</tag>
<tag name="map" action="validate"/>
<!-- base tag removed per demo - this could be enabled with literal-list values you allow -->
<!--
<tag name="base" action="validate">
<attribute name="href"/>
</tag>
-->
<!-- Stylesheet Tags -->
<tag name="style" action="validate">
<attribute name="type">
<literal-list>
<literal value="text/css"/>
</literal-list>
</attribute>
<attribute name="media"/>
</tag>
<tag name="span" action="validate"/>
<tag name="div" action="validate">
<attribute name="align"/>
</tag>
<!-- <attribute name="id"/> what could an attacker do if they could overwrite an existing div definition? prolly something bad -->
<!-- <attribute name="class"/> what could an attacker do if they could specify any class in the namespace? prolly something bad -->
<!-- Image & image related tags -->
<tag name="img" action="validate">
<attribute name="src" onInvalid="removeTag">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="name"/>
<attribute name="alt"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="border"/>
<attribute name="align"/>
<attribute name="hspace">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="vspace">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
</tag>
<!-- no way to do this safely without hooking up the same code to @import to embed the remote stylesheet (malicious user could change offsite resource to be malicious after validation -->
<!-- <attribute name="href" onInvalid="removeTag"/> -->
<tag name="link" action="validate">
<!-- <attribute name="href" onInvalid="removeTag"/> -->
<attribute name="media"/>
<attribute name="type" onInvalid="removeTag">
<literal-list>
<literal value="text/css"/>
<literal value="application/rss+xml"/>
<literal value="image/x-icon"/>
</literal-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="stylesheet"/>
<literal value="shortcut icon"/>
<literal value="search"/>
<literal value="copyright"/>
<literal value="top"/>
<literal value="alternate"/>
</literal-list>
</attribute>
</tag>
<!-- List tags -->
<tag name="ul" action="validate"/>
<tag name="ol" action="validate"/>
<tag name="li" action="validate"/>
<!-- Dictionary tags -->
<tag name="dd" action="truncate"/>
<tag name="dl" action="truncate"/>
<tag name="dt" action="truncate"/>
<!-- Table tags (tbody, thead, tfoot)-->
<tag name="thead" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="tbody" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="tfoot" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="table" action="validate">
<attribute name="height"/>
<attribute name="width"/>
<attribute name="border"/>
<attribute name="bgcolor"/>
<attribute name="cellpadding"/>
<attribute name="cellspacing"/>
<attribute name="background"/>
<attribute name="align"/>
<attribute name="noresize">
<literal-list>
<literal value="noresize"/>
<literal value=""/>
</literal-list>
</attribute>
</tag>
<tag name="td" action="validate">
<attribute name="background"/>
<attribute name="bgcolor"/>
<attribute name="abbr"/>
<attribute name="axis"/>
<attribute name="headers"/>
<attribute name="scope"/>
<attribute name="nowrap"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="colspan"/>
<attribute name="rowspan"/>
</tag>
<tag name="th" action="validate">
<attribute name="abbr"/>
<attribute name="axis"/>
<attribute name="headers"/>
<attribute name="scope"/>
<attribute name="nowrap"/>
<attribute name="bgcolor"/>
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="colspan"/>
<attribute name="rowspan"/>
</tag>
<tag name="tr" action="validate">
<attribute name="height"/>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="valign"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="background"/>
</tag>
<tag name="colgroup" action="validate">
<attribute name="span">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="width"/>
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
</tag>
<tag name="col" action="validate">
<attribute name="align"/>
<attribute name="char"/>
<attribute name="charoff"/>
<attribute name="valign"/>
<attribute name="span">
<regexp-list>
<regexp name="number"/>
</regexp-list>
</attribute>
<attribute name="width"/>
</tag>
<tag name="fieldset" action="validate"/>
<tag name="legend" action="validate"/>
</tag-rules>
<!-- CSS validation processing rules -->
<css-rules>
<property name="azimuth"
description="This property is most likely to be implemented by mixing the same signal into different channels at differing volumes.">
<literal-list>
<literal value="left-side"/>
<literal value="far-left"/>
<literal value="left"/>
<literal value="center-left"/>
<literal value="center"/>
<literal value="center-right"/>
<literal value="right"/>
<literal value="far-right"/>
<literal value="right-side"/>
<literal value="behind"/>
<literal value="leftwards"/>
<literal value="rightwards"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="angle"/>
</regexp-list>
</property>
<property name="background"
description="The 'background' property is a shorthand property for setting the individual background properties (i.e., 'background-color', 'background-image', 'background-repeat', 'background-attachment' and 'background-position') at the same place in the style sheet.">
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="background-color"/>
<shorthand name="background-image"/>
<shorthand name="background-repeat"/>
<shorthand name="background-attachment"/>
<shorthand name="background-position"/>
</shorthand-list>
</property>
<property name="background-attachment"
description="If a background image is specified, this property specifies whether it is fixed with regard to the viewport ('fixed') or scrolls along with the document ('scroll').">
<literal-list>
<literal value="scroll"/>
<literal value="fixed"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="background-color"
description="This property sets the background color of an element, either a &lt;color&gt; value or the keyword 'transparent', to make the underlying colors shine through.">
<literal-list>
<literal value="transparent"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="background-image" description="This property sets the background image of an element.">
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="background-position"
description="If a background image has been specified, this property specifies its initial position.">
<literal-list>
<literal value="top"/>
<literal value="center"/>
<literal value="bottom"/>
<literal value="left"/>
<literal value="center"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="percentage"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="background-repeat"
description="If a background image is specified, this property specifies whether the image is repeated (tiled), and how.">
<literal-list>
<literal value="repeat"/>
<literal value="repeat-x"/>
<literal value="repeat-y"/>
<literal value="no-repeat"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- Begin simple properties -->
<property name="border-collapse" default="collapse" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="collapse"/>
<literal value="separate"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="border-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="transparent"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-top-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-right-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-bottom-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="border-left-color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="bottom" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="caption-side" default="top" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="top"/>
<literal value="bottom"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="clear" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="left"/>
<literal value="right"/>
<literal value="both"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="color" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="cue-after" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="cue-before" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="direction" default="ltr" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="ltr"/>
<literal value="rtl"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="display" default="inline" description="">
<category-list>
<category value="all"/>
</category-list>
<literal-list>
<literal value="inline"/>
<literal value="block"/>
<literal value="list-item"/>
<literal value="run-in"/>
<literal value="compact"/>
<literal value="marker"/>
<literal value="table"/>
<literal value="inline-table"/>
<literal value="table-row-group"/>
<literal value="table-header-group"/>
<literal value="table-footer-group"/>
<literal value="table-row"/>
<literal value="table-column-group"/>
<literal value="table-column"/>
<literal value="table-cell"/>
<literal value="table-caption"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="elevation" default="level" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="below"/>
<literal value="level"/>
<literal value="above"/>
<literal value="higher"/>
<literal value="lower"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="angle"/>
</regexp-list>
</property>
<property name="empty-cells" default="show" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="show"/>
<literal value="hide"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="float" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="left"/>
<literal value="right"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-size" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="absolute-size"/>
<regexp name="relative-size"/>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="font-size-adjust" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="font-stretch" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="wider"/>
<literal value="narrower"/>
<literal value="ultra-condensed"/>
<literal value="extra-condensed"/>
<literal value="condensed"/>
<literal value="semi-condensed"/>
<literal value="semi-expanded"/>
<literal value="expanded"/>
<literal value="extra-expanded"/>
<literal value="ultra-expanded"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-style" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="italic"/>
<literal value="oblique"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-variant" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="small-caps"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="font-weight" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="bold"/>
<literal value="bolder"/>
<literal value="lighter"/>
<literal value="100"/>
<literal value="200"/>
<literal value="300"/>
<literal value="400"/>
<literal value="500"/>
<literal value="600"/>
<literal value="700"/>
<literal value="800"/>
<literal value="900"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="height" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="left" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="letter-spacing" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="line-height" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="list-style-image" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="list-style-position" default="outside" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inside"/>
<literal value="outside"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="list-style-type" default="disc" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="disc"/>
<literal value="circle"/>
<literal value="square"/>
<literal value="decimal"/>
<literal value="decimal-leading-zero"/>
<literal value="lower-roman"/>
<literal value="upper-roman"/>
<literal value="lower-greek"/>
<literal value="lower-alpha"/>
<literal value="lower-latin"/>
<literal value="upper-alpha"/>
<literal value="upper-latin"/>
<literal value="hebrew"/>
<literal value="armenian"/>
<literal value="georgian"/>
<literal value="cjk-ideographic"/>
<literal value="hiragana"/>
<literal value="katakana"/>
<literal value="hiragana-iroha"/>
<literal value="katakana-iroha"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="marker-offset" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="max-height" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="max-width" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="min-height" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="min-width" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="orphans" default="2" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="outline-color" default="invert" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="invert"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
</property>
<property name="overflow" default="visible" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="visible"/>
<literal value="hidden"/>
<literal value="scroll"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-after" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="always"/>
<literal value="avoid"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-before" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="always"/>
<literal value="avoid"/>
<literal value="left"/>
<literal value="right"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="page-break-inside" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="avoid"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="pause-after" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="pause-before" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="pitch" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="x-low"/>
<literal value="low"/>
<literal value="medium"/>
<literal value="high"/>
<literal value="x-high"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="frequency"/>
</regexp-list>
</property>
<property name="pitch-range" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="position" default="static" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="static"/>
<!-- possible to perform phishing attacks with the following -->
<!--
<literal value="relative"/>
<literal value="absolute"/>
<literal value="fixed"/>
-->
<literal value="inherit"/>
</literal-list>
</property>
<property name="richness" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="right" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="size" default="auto" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="portrait"/>
<literal value="landscape"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="speak" default="normal" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="none"/>
<literal value="spell-out"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-header" default="once" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="once"/>
<literal value="always"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-numeral" default="continuous" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="digits"/>
<literal value="continuous"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speak-punctuation" default="none" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="code"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="speech-rate" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="x-slow"/>
<literal value="slow"/>
<literal value="medium"/>
<literal value="fast"/>
<literal value="x-fast"/>
<literal value="faster"/>
<literal value="slower"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="stress" default="50" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
</regexp-list>
</property>
<property name="table-layout" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="fixed"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="text-indent" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="text-transform" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="capitalize"/>
<literal value="uppercase"/>
<literal value="lowercase"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="top" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="unicode-bidi" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="embed"/>
<literal value="bidi-override"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="vertical-align" default="baseline" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="baseline"/>
<literal value="sub"/>
<literal value="super"/>
<literal value="top"/>
<literal value="text-top"/>
<literal value="middle"/>
<literal value="bottom"/>
<literal value="text-bottom"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="percentage"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="visibility" default="inherit" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="visible"/>
<literal value="hidden"/>
<literal value="collapse"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="volume" default="medium" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="silent"/>
<literal value="x-soft"/>
<literal value="soft"/>
<literal value="medium"/>
<literal value="loud"/>
<literal value="x-loud"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="number"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="white-space" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="pre"/>
<literal value="nowrap"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="widows" default="2" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="width" default="auto" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="word-spacing" default="normal" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="normal"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<!-- end simple properties -->
<!-- begin medium properties -->
<property name="border-style" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="none"/>
<literal value="hidden"/>
<literal value="dotted"/>
<literal value="dashed"/>
<literal value="solid"/>
<literal value="double"/>
<literal value="groove"/>
<literal value="ridge"/>
<literal value="inset"/>
<literal value="outset"/>
</literal-list>
</property>
<property name="border-top-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
</property>
<property name="border-right-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-bottom-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-left-style" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-top-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-right-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-bottom-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-left-width" default="medium" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="border-width" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="thin"/>
<literal value="medium"/>
<literal value="thick"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="margin" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
<literal value="auto"/>
</literal-list>
<regexp-list>
<regexp name="positiveLength"/>
<regexp name="positivePercentage"/>
</regexp-list>
</property>
<property name="margin-top" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-right" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-bottom" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="margin-left" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="margin"/>
</shorthand-list>
</property>
<property name="outline-style" default="none" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="outline-width" default="medium" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="border-width"/>
</shorthand-list>
</property>
<property name="padding" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="padding-top" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-right" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-bottom" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<property name="padding-left" default="0" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="padding"/>
</shorthand-list>
</property>
<!-- end medium properties -->
<!-- begin hard properties -->
<property name="border" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-top" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-right" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-bottom" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="border-left" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
</regexp-list>
<shorthand-list>
<shorthand name="border-top-width"/>
<shorthand name="border-style"/>
</shorthand-list>
</property>
<property name="cue" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="cue-before"/>
<shorthand name="cue-after"/>
</shorthand-list>
</property>
<property name="list-style" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="list-style-type"/>
<shorthand name="list-style-position"/>
<shorthand name="list-style-image"/>
</shorthand-list>
</property>
<property name="marks" default="none" description="">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="crop"/>
<literal value="cross"/>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="outline" description="">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="outline-color"/>
<shorthand name="outline-style"/>
<shorthand name="outline-width"/>
</shorthand-list>
</property>
<property name="pause" description="">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="time"/>
<regexp name="percentage"/>
</regexp-list>
</property>
<property name="text-decoration" default="none" description="">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="underline"/>
<literal value="overline"/>
<literal value="line-through"/>
<literal value="blink"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- end hard properties -->
<!-- begin manual properties -->
<property name="border-spacing" default="0"
description="The lengths specify the distance that separates adjacent cell borders. If one length is specified, it gives both the horizontal and vertical spacing. If two are specified, the first gives the horizontal spacing and the second the vertical spacing. Lengths may not be negative.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="clip" default="auto"
description="The 'clip' property applies to elements that have a 'overflow' property with a value other than 'visible'.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="length"/>
</regexp-list>
</property>
<property name="counter-increment" default="none"
description="The 'counter-increment' property accepts one or more names of counters (identifiers), each one optionally followed by an integer.">
<category-list>
<category value="all"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssIdentifier"/>
<regexp name="integer"/>
</regexp-list>
</property>
<property name="cursor" default="auto"
description="This property specifies the type of cursor to be displayed for the pointing device.">
<category-list>
<category value="visual"/>
<category value="interactive"/>
</category-list>
<literal-list>
<literal value="auto"/>
<literal value="inherit"/>
<literal value="crosshair"/>
<literal value="default"/>
<literal value="pointer"/>
<literal value="move"/>
<literal value="e-resize"/>
<literal value="ne-resize"/>
<literal value="nw-resize"/>
<literal value="n-resize"/>
<literal value="se-resize"/>
<literal value="sw-resize"/>
<literal value="s-resize"/>
<literal value="w-resize| text"/>
<literal value="wait"/>
<literal value="help"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="text-shadow" default="none"
description="This property accepts a comma-separated list of shadow effects to be applied to the text of the element.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="none"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="colorName"/>
<regexp name="colorCode"/>
<regexp name="rgbCode"/>
<regexp name="systemColor"/>
<regexp name="length"/>
</regexp-list>
</property>
<property name="font"
description="The 'font' property is, except as described below, a shorthand property for setting 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', and 'font-family', at the same place in the style sheet.">
<category-list>
<category value="visual"/>
</category-list>
<literal-list>
<literal value="/"/>
<literal value="caption"/>
<literal value="icon"/>
<literal value="menu"/>
<literal value="message-box"/>
<literal value="small-caption"/>
<literal value="status-bar"/>
<literal value="inherit"/>
</literal-list>
<shorthand-list>
<shorthand name="font-style"/>
<shorthand name="font-variant"/>
<shorthand name="font-weight"/>
<shorthand name="font-size"/>
<shorthand name="line-height"/>
<shorthand name="font-family"/>
</shorthand-list>
</property>
<property name="font-family"
description="This property specifies a prioritized list of font family names and/or generic family names.">
<category-list>
<category value="visual"/>
</category-list>
<!-- allowing only generic font families -->
<literal-list>
<literal value="serif"/>
<literal value="arial"/>
<literal value="lucida console"/>
<literal value="sans-serif"/>
<literal value="cursive"/>
<literal value="verdana"/>
<literal value="fantasy"/>
<literal value="monospace"/>
</literal-list>
<regexp-list>
<regexp value="[\w,\-&apos;&quot; ]+"/>
</regexp-list>
</property>
<property name="page"
description="The 'page' property can be used to specify a particular type of page where an element should be displayed.">
<category-list>
<category value="visual"/>
<category value="paged"/>
</category-list>
<literal-list>
<literal value="auto"/>
</literal-list>
<regexp-list>
<regexp name="cssIdentifier"/>
</regexp-list>
</property>
<property name="play-during" default="auto"
description="Similar to the 'cue-before' and 'cue-after' properties, this property specifies a sound to be played as a background while an element's content is spoken.">
<category-list>
<category value="aural"/>
</category-list>
<literal-list>
<literal value="mix"/>
<literal value="repeat"/>
<literal value="none"/>
<literal value="auto"/>
<literal value="inherit"/>
</literal-list>
<regexp-list>
<regexp name="cssOffsiteUri"/>
<regexp name="cssOnsiteUri"/>
</regexp-list>
</property>
<property name="text-align" description="This property describes how inline content of a block is aligned.">
<category-list>
<category value="visual"/>
</category-list>
<!-- For safety, ignoring string alignment which can be used to line table cells on characters -->
<literal-list>
<literal value="left"/>
<literal value="right"/>
<literal value="center"/>
<literal value="justify"/>
<literal value="inherit"/>
</literal-list>
</property>
<property name="voice-family"
description="The value is a comma-separated, prioritized list of voice family names (compare with 'font-family').">
<category-list>
<category value="aural"/>
</category-list>
<!-- Allowing only generic voice family -->
<literal-list>
<literal value="male"/>
<literal value="female"/>
<literal value="child"/>
<literal value="inherit"/>
</literal-list>
</property>
<!-- end manual properties -->
</css-rules>
<allowed-empty-tags>
<literal-list>
<literal value="br"/>
<literal value="hr"/>
<literal value="a"/>
<literal value="img"/>
<literal value="link"/>
<literal value="iframe"/>
<literal value="script"/>
<literal value="object"/>
<literal value="applet"/>
<literal value="frame"/>
<literal value="base"/>
<literal value="param"/>
<literal value="meta"/>
<literal value="input"/>
<literal value="textarea"/>
<literal value="embed"/>
<literal value="basefont"/>
<literal value="col"/>
<literal value="div"/>
</literal-list>
</allowed-empty-tags>
</anti-samy-rules>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="0"/>
<directive name="useXHTML" value="true"/>
<directive name="formatOutput" value="false"/>
<!--
remember, this won't work for relative URIs - AntiSamy doesn't
know anything about the URL or your web structure
-->
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while? Even wars of attrition, surely?
-->
<global-tag-attributes>
</global-tag-attributes>
<tags-to-encode>
</tags-to-encode>
<tag-rules>
</tag-rules>
<!-- CSS validation processing rules -->
<css-rules>
<!-- end manual properties -->
</css-rules>
<allowed-empty-tags>
</allowed-empty-tags>
</anti-samy-rules>
# 应用服务器
server:
tomcat:
uri-encoding: UTF-8 #tomcat编码
port: 8999 #tomcat端口
#===================== 数据源配置 =====================
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${MYSQL_USER:junmp123}
password: ${MYSQL_PWD:123456}
url: jdbc:mysql://${MYSQL_HOST:127.0.0.1}:${MYSQL_PORT:3306}/${MYSQL_DB:db_key_app}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true&queryTimeout=2400&nullCatalogMeansCurrent=true
#===================== Redis配置 =====================
redis:
database: 1 #缓存库编号
host: 192.168.3.128
port: 6379
password:
timeout: 3000 #超时时间(单位:秒)
lettuce: #Lettuce为Redis的Java驱动包
pool:
max-active: 8 # 连接池最大连接数
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
min-idle: 0 # 连接池中的最小空闲连接
max-idle: 8 # 连接池中的最大空闲连接
mail:
host: smtp.qq.com #邮件服务器的host
password: sb #邮件服务器的发件人密码
username: 6666@qq.com #邮件服务器的发件人
port: 25 #smtp默认端口
protocol: smtp #使用smtp协议
default-encoding: UTF-8 #邮件使用的字符集
properties:
mail:
debug: true #启调试模式(发送邮件的细节都能看出来) 默认值为fasle
debug.auth: true
smtp:
auth: true #如果为true ,则尝试使用auth命令对用户进行身份验证 默认为false
connectiontimeout: 20000 #套接字连接超时值(毫秒)。默认值为无限超时。
sendpartial: true #如果为true 并且邮件有一些有效和无效的地址 并使用SendFailException 报告部分失败, 如果设置为false(默认值) 如果存在无效的收件人地址, 则不会将邮件发送给任何收件人
starttls:
#如果为true,则在发出任何登录命令之前,启用starttl命令(如果服务器支持) 将连接切换到受TLS保护的连接,请注意,必须配置适当的信任存储,以便客户端信任服务器的证书,默认为false
enable: true
# 如果为true,则需要使用 starttl命令,如果服务器不支持此命令,或者该命令失败,connect()将失败,默认为false 如果此设置为true james邮件服务器会报错 STARTTLS is required but host does not support STARTTLS
required: false
timeout: 20000 #I/O超时值(ms) 默认为无限超时
userset: true #如果设置为true,则在isConnected()中使用RSET命令而不是NOOP命令 在某些情况下,sendmail在执行许多NOOP命令后响应缓存,使用RSET可以避免这个sendMail问题,默认为false
flowable:
dmn:
enabled: false
cmmn:
enabled: false
idm:
enabled: false
async-history-executor-activate: false
async-executor-activate: false
check-process-definitions: false
content:
enabled: false
app:
enabled: false
eventregistry:
enabled: false
config:
minio:
endpoint: http://192.168.0.147:9000/ #服务端地址
accessKey: admin #账号
secretKey: test. #密码
fileHost: http://192.168.0.147:9000/ #地址
spring: #环境 dev|test|pro|preview
profiles:
active: dev
servlet:
multipart: #文件传输配置
max-file-size: 100MB #单个数据大小限制
max-request-size: 100MB #请求总数据大小限制
enabled: true #是否启用分段上传支持
mvc:
hiddenmethod: #隐式方法过滤器
filter:
enabled: true #默认关闭。开启以支持:PUT,DELETE表单提交方法
jackson: #序列化和反序列化json框架
serialization:
write-dates-as-timestamps: true #是否写入日期时间时间戳格式
time-zone: GMT+8 #指定日期格式化时区
main:
allow-bean-definition-overriding: true #允许同名bean后者覆盖,默认:true
allow-circular-references: true #允许Bean相互引用,默认:false
server:
error:
whitelabel:
enabled: false
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--日志格式应用spring boot默认的格式,也可以自己更改-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
<springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log/systemLog"/>
<!-- ****************************************************************************************** -->
<!-- ****************************** 本地开发只在控制台打印日志 ************************************ -->
<!-- ****************************************************************************************** -->
<springProfile name="dev">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--默认所有的包以info-->
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
<!--各个服务的包在本地执行的时候,打开debug模式-->
<logger name="com" level="debug" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
</springProfile>
<!-- ********************************************************************************************** -->
<!-- **** 放到服务器上不管在什么环境都只在文件记录日志,控制台(catalina.out)打印logback捕获不到的日志 **** -->
<!-- ********************************************************************************************** -->
<springProfile name="test,pro,me,preview">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 日志记录器,日期滚动记录,level为 ERROR 日志 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd,aux}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 INFO 日志 -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_info.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd,aux}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 WARN 日志 -->
<appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_warn.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 DEBUG 日志 -->
<appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_debug.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd,aux}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志记录器,日期滚动记录,level为 ALL 日志 -->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_total.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/total/%d{yyyy-MM-dd,aux}/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--日志最大的历史7天-->
<maxHistory>7</maxHistory>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--记录到文件时-->
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_WARN"/>
<appender-ref ref="FILE_DEBUG"/>
<appender-ref ref="FILE_ALL"/>
</root>
</springProfile>
</configuration>
org\modules\junmpProcess\vo\OrgTreeVo$OrgTreeVoBuilder.class
org\modules\junmpProcess\mapper\FormGroupsMapper.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$4.class
org\modules\junmpProcess\service\Bussiness\OrgUserAndDeptService.class
org\modules\junmpProcess\utils\DateUtils$3.class
org\modules\junmpProcess\controller\OrgUserAndDeptController.class
org\modules\junmpProcess\controller\WorkspaceProcessController$15.class
org\modules\junmpProcess\utils\BpmnModelUtils$Type.class
org\modules\junmpProcess\entity\FormGroups$FormGroupsBuilder.class
org\modules\junmpProcess\entity\Departments.class
org\modules\junmpProcess\dto\PageDTO.class
org\modules\junmpProcess\listener\TaskCreatedListener.class
org\modules\junmpProcess\dto\HandleDataDTO.class
org\modules\junmpProcess\dto\json\flowJson\FlowConditionGroup.class
org\modules\junmpProcess\enums\AssigneeTypeEnums.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$7.class
org\modules\junmpProcess\mapper\DepartmentsMapper.class
org\modules\junmpProcess\listener\ServiceListener.class
org\modules\junmpProcess\utils\BpmnModelUtils.class
org\modules\junmpProcess\controller\WorkspaceProcessController$12.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$11.class
org\modules\junmpProcess\dto\json\flowJson\FlowNode.class
org\modules\junmpProcess\entity\Users$UsersBuilder.class
org\modules\junmpProcess\vo\CommentVO.class
org\modules\junmpProcess\service\Repository\UserService.class
org\modules\junmpProcess\utils\DateUtils$6.class
org\modules\junmpProcess\dto\json\NotifyTypeInfo.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$14.class
org\modules\junmpProcess\vo\ProcessInstanceDetailVO.class
org\modules\junmpProcess\config\ActivitiConfig.class
org\modules\junmpProcess\vo\OptionVO.class
org\modules\junmpProcess\controller\WorkspaceProcessController$8.class
org\modules\junmpProcess\common\R.class
org\modules\junmpProcess\dto\json\NotifyType.class
org\modules\junmpProcess\utils\ExUtils$1.class
org\modules\junmpProcess\vo\TemplateGroupVo$Template$TemplateBuilder.class
org\modules\junmpProcess\dto\json\flowJson\FlowChildNode.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$12.class
org\modules\junmpProcess\service\Repository\impl\ProcessTemplateServiceImpl.class
org\modules\junmpProcess\dto\json\HttpInfo.class
org\modules\junmpProcess\vo\OrgTreeVo.class
org\modules\junmpProcess\vo\MultiVO.class
springfox\documentation\spring\web\WebMvcRequestHandler.class
org\modules\junmpProcess\controller\WorkspaceProcessController.class
org\modules\junmpProcess\controller\WorkspaceProcessController$5.class
org\modules\junmpProcess\utils\IdWorker.class
org\modules\junmpProcess\dto\json\flowJson\FlowApproverGroups.class
org\modules\junmpProcess\mapper\ProcessTemplatesMapper.class
org\modules\junmpProcess\vo\TemplateGroupVo.class
org\modules\junmpProcess\service\Repository\impl\WorkspaceProcessServiceImpl.class
org\modules\junmpProcess\service\Repository\ProcessTemplateService.class
org\modules\junmpProcess\utils\ServletUtil.class
org\modules\junmpProcess\entity\TemplateGroupBo.class
org\modules\junmpProcess\exception\GlobalExceptionHandlerResolver.class
org\modules\junmpProcess\dto\json\flowJson\FlowConditionNodes.class
org\modules\junmpProcess\job\CustomJobHandler.class
org\modules\junmpProcess\controller\BpmnController.class
org\modules\junmpProcess\dto\json\GroupsInfo.class
org\modules\junmpProcess\controller\WorkspaceProcessController$6.class
org\modules\junmpProcess\common\Result.class
org\modules\junmpProcess\mapper\TemplateGroupMapper.class
org\modules\junmpProcess\utils\DateUtils$7.class
org\modules\junmpProcess\common\WorkFlowConstants.class
org\modules\junmpProcess\dto\json\EmailInfo.class
org\modules\junmpProcess\controller\WorkspaceProcessController$10.class
org\modules\junmpProcess\entity\TemplateGroupBo$TemplateGroupBoBuilder.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$5.class
org\modules\junmpProcess\dto\StartProcessInstanceDTO.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl$4.class
org\modules\junmpProcess\entity\ProcessTemplates.class
org\modules\junmpProcess\utils\DateUtils$1.class
org\modules\junmpProcess\dto\AttachmentDTO.class
org\modules\junmpProcess\vo\HandleDataVO.class
org\modules\junmpProcess\service\Repository\impl\FormGroupServiceImpl.class
org\modules\junmpProcess\config\IdWorkerConfig.class
org\modules\junmpProcess\common\CommonConstants.class
org\modules\junmpProcess\vo\TemplateGroupVo$Template.class
org\modules\junmpProcess\dto\json\FormItemProps.class
org\modules\junmpProcess\controller\MainProcessController.class
org\modules\junmpProcess\controller\WorkspaceProcessController$11.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl.class
org\modules\junmpProcess\vo\TemplateGroupVo$TemplateGroupVoBuilder.class
org\modules\junmpProcess\dto\json\ChildNode.class
org\modules\junmpProcess\dto\json\flowJson\Inout.class
org\modules\junmpProcess\utils\DateUtils.class
org\modules\junmpProcess\enums\ModeEnums.class
org\modules\junmpProcess\dto\FlowDTO.class
org\modules\junmpProcess\controller\SettingController.class
org\modules\junmpProcess\controller\WorkspaceProcessController$4.class
org\modules\junmpProcess\dto\json\Properties.class
org\modules\junmpProcess\dto\json\FormOperates.class
org\modules\junmpProcess\utils\ExUtils.class
org\modules\junmpProcess\vo\HistoryProcessInstanceVO.class
org\modules\junmpProcess\job\IdWorkerIdGenerator.class
org\modules\junmpProcess\mapper\UsersMapper.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$13.class
org\modules\junmpProcess\service\Repository\impl\UserServiceImpl.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$10.class
org\modules\junmpProcess\dto\json\FormItem.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl$3.class
org\modules\junmpProcess\controller\WorkspaceProcessController$7.class
org\modules\junmpProcess\dto\TaskDTO.class
org\modules\junmpProcess\job\CustomJobCmd.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$3.class
org\modules\junmpProcess\vo\TaskVO.class
org\modules\junmpProcess\controller\WorkspaceProcessController$14.class
org\modules\junmpProcess\listener\CounterSignListener$1.class
org\modules\junmpProcess\service\Repository\TemplateGroupService.class
org\modules\junmpProcess\entity\TemplateGroup$TemplateGroupBuilder.class
org\modules\junmpProcess\entity\Process$ProcessBuilder.class
org\modules\junmpProcess\controller\WorkspaceProcessController$1.class
org\modules\junmpProcess\dto\json\UserInfo.class
org\modules\junmpProcess\utils\DateUtils$2.class
org\modules\junmpProcess\utils\BpmnModelUtils$FlowType.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl$5.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$6.class
org\modules\junmpProcess\service\Bussiness\SettingService.class
org\modules\junmpProcess\vo\AttachmentVO.class
org\modules\junmpProcess\entity\Users.class
org\modules\junmpProcess\controller\WorkspaceProcessController$13.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl$2.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$9.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$2.class
org\modules\junmpProcess\service\Repository\impl\DepartmentsServiceImpl.class
org\modules\junmpProcess\entity\TemplateGroup.class
org\modules\junmpProcess\dto\json\ConditionInfo.class
org\modules\junmpProcess\entity\FormGroups.class
org\modules\junmpProcess\entity\ProcessTemplates$ProcessTemplatesBuilder.class
org\modules\junmpProcess\listener\CounterSignListener.class
org\modules\junmpProcess\controller\WorkspaceProcessController$9.class
org\modules\junmpProcess\listener\CounterSignListener$2.class
org\modules\junmpProcess\listener\ProcessListener.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$15.class
org\modules\junmpProcess\service\Repository\WorkspaceProcessService.class
org\modules\junmpProcess\utils\DateUtils$5.class
org\modules\junmpProcess\entity\Departments$DepartmentsBuilder.class
org\modules\junmpProcess\service\Repository\DepartmentsService.class
org\modules\junmpProcess\utils\SpringContextHolder.class
org\modules\junmpProcess\controller\WorkspaceProcessController$2.class
org\modules\junmpProcess\utils\ExUtils$2.class
org\modules\junmpProcess\exception\WorkFlowException.class
org\modules\junmpProcess\service\Bussiness\WorkProcessService.class
org\modules\junmpProcess\vo\TaskDetailVO.class
org\modules\junmpProcess\service\Repository\impl\TemplateGroupServiceImpl.class
org\modules\junmpProcess\dto\json\LogoInfo.class
org\modules\junmpProcess\listener\TimerListener.class
org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl$1.class
org\modules\junmpProcess\service\Repository\FormGroupService.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$1.class
org\modules\junmpProcess\dto\ApplyDTO.class
org\modules\junmpProcess\dto\FlowEngineDTO.class
org\modules\junmpProcess\controller\WorkspaceProcessController$3.class
org\modules\junmpProcess\listener\CounterSignListener$3.class
org\modules\junmpProcess\service\Bussiness\impl\OrgUserAndDeptServiceImpl.class
org\modules\junmpProcess\dto\json\SettingsInfo.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl$8.class
org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl.class
org\modules\junmpProcess\entity\Process.class
org\modules\junmpProcess\utils\DateUtils$4.class
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\TemplateGroupBo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\MinioUploadUtil.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\NotifyType.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\BpmnModelUtils.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\config\minio\MyMinioClient.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\FlowDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\FlowApproverGroups.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\ProcessTemplateServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\DepartmentsService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\config\IdWorkerConfig.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\Departments.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\FormOperates.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\HttpInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\FileUtil.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\controller\SettingController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\Inout.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\impl\WorkProcessServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\WorkspaceProcessService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\Properties.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\common\R.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\FlowConditionGroup.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\config\ActivitiConfig.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\FlowChildNode.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\TaskVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\EmailInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\listener\CounterSignListener.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\OrgUserAndDeptService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\controller\OrgUserAndDeptController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\HandleDataDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\enums\AssigneeTypeEnums.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\TemplateGroupMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\ApplyDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\controller\WorkspaceProcessController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\AttachmentDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\OrgTreeVo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\job\CustomJobCmd.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\FormGroupsMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\AttachmentVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\UserInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\ChildNode.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\HistoryProcessInstanceVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\DateUtils.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\listener\ServiceListener.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\HandleDataVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\impl\SettingServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\TemplateGroupService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\enums\ModeEnums.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\ServletUtil.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\job\CustomJobHandler.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\WorkspaceProcessServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\CommentVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\SettingsInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\listener\TimerListener.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\ExUtils.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\TemplateGroup.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\FormGroupServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\TaskDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\LogoInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\ProcessTemplates.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\ProcessMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\common\WorkFlowConstants.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\UserService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\IdWorker.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\OptionVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\SpringContextHolderV2.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\SettingService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\FormGroupService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\FlowNode.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\controller\MainProcessController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\TemplateGroupVo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\ProcessTemplatesMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\job\IdWorkerIdGenerator.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\UsersMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\exception\WorkFlowException.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\listener\TaskCreatedListener.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\WorkProcessService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Bussiness\impl\OrgUserAndDeptServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\Users.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\common\CommonConstants.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\controller\BpmnController.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\FormItemProps.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\DepartmentsServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\ProcessInstanceDetailVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\GroupsInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\utils\XSSEscape.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\TemplateGroupServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\MultiVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\FormGroups.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\NotifyTypeInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\StartProcessInstanceDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\config\minio\MinioConfigurationProperties.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\PageDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\common\Result.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\listener\ProcessListener.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\vo\TaskDetailVO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\entity\Process.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\springfox\documentation\spring\web\WebMvcRequestHandler.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\ProcessTemplateService.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\exception\GlobalExceptionHandlerResolver.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\mapper\DepartmentsMapper.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\service\Repository\impl\UserServiceImpl.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\ConditionInfo.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\FlowEngineDTO.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\FormItem.java
C:\项目\JAVA\主平台\junmp-jyzb-app\jyzb-process\src\main\java\org\modules\junmpProcess\dto\json\flowJson\FlowConditionNodes.java
......@@ -2,17 +2,18 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.junmp.gold</groupId>
<artifactId>junmp-gold-app</artifactId>
<groupId>com.junmp.jyzb</groupId>
<artifactId>junmp-jyzb-app</artifactId>
<version>1.0.0</version>
<name>junmp-gold-app</name>
<name>junmp-jyzb-app</name>
<packaging>pom</packaging>
<description>金砖防伪平台</description>
<description>警用装备平台</description>
<modules>
<module>gold-api</module>
<module>gold-boot</module>
<module>gold-biz</module>
<module>jyzb-api</module>
<module>jyzb-boot</module>
<module>jyzb-biz</module>
<module>jyzb-process</module>
</modules>
<parent>
......@@ -33,6 +34,7 @@
<name>aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
......@@ -68,9 +70,10 @@
<common.codec.version>1.14</common.codec.version>
<netty.version>4.1.73.Final</netty.version>
<slf4j.version>1.7.36</slf4j.version>
<fastjson.version>1.2.76</fastjson.version>
<swagger2.version>1.5.22</swagger2.version>
<p6spy.version>3.9.1</p6spy.version>
<fastjson.version>1.2.83</fastjson.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencyManagement>
......@@ -86,11 +89,6 @@
<version>${p6spy.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
......@@ -109,7 +107,11 @@
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.junmp.v2</groupId>
<artifactId>v2-config-api</artifactId>
......@@ -207,20 +209,76 @@
</dependency>
<dependency>
<groupId>com.junmp.gold</groupId>
<artifactId>gold-api</artifactId>
<groupId>com.junmp.jyzb</groupId>
<artifactId>jyzb-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.junmp.gold</groupId>
<artifactId>gold-biz</artifactId>
<groupId>com.junmp.jyzb</groupId>
<artifactId>jyzb-biz</artifactId>
<version>1.0.0</version>
</dependency>
<!-- JSON 解析器和生成器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- flowable -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
<exclusions>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-app</artifactId>
</exclusion>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-form-spring-configurator</artifactId>
</exclusion>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-idm-spring-configurator</artifactId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-model</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-layout</artifactId>
<version>${flowable.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>gold-app</finalName>
<finalName>jyzb-app</finalName>
<pluginManagement>
<plugins>
<plugin>
......@@ -285,6 +343,7 @@
<id>dev</id>
<properties>
<spring.active>dev</spring.active>
<flowable.version>6.7.2</flowable.version>
</properties>
</profile>
<profile>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论