413 changed files with 11729 additions and 24255 deletions
@ -1,58 +0,0 @@ |
|||
<?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> |
|||
<groupId>org.dromara</groupId> |
|||
<artifactId>dk-common</artifactId> |
|||
<version>${revision}</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<artifactId>common-workflow</artifactId> |
|||
|
|||
<description> |
|||
工作流模块 |
|||
</description> |
|||
|
|||
<dependencies> |
|||
|
|||
<dependency> |
|||
<groupId>org.dromara</groupId> |
|||
<artifactId>common-mybatis</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>commons-io</groupId> |
|||
<artifactId>commons-io</artifactId> |
|||
<version>2.15.0</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.dromara</groupId> |
|||
<artifactId>system</artifactId> |
|||
<version>2.2.2</version> |
|||
<scope>compile</scope> |
|||
</dependency> |
|||
</dependencies> |
|||
|
|||
<build> |
|||
<finalName>${project.artifactId}</finalName> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-maven-plugin</artifactId> |
|||
<version>${spring-boot.version}</version> |
|||
<executions> |
|||
<execution> |
|||
<goals> |
|||
<goal>repackage</goal> |
|||
</goals> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
|
|||
</project> |
|||
|
@ -1,61 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.Exception; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.dromara.common.Exception.enums.abs.AbstractBaseExceptionEnum; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
|
|||
/** |
|||
* 业务异常 |
|||
* |
|||
*/ |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Data |
|||
public class ServiceException extends RuntimeException { |
|||
|
|||
private Integer code; |
|||
|
|||
private String errorMessage; |
|||
|
|||
public ServiceException(Integer code, String errorMessage) { |
|||
super(errorMessage); |
|||
this.code = code; |
|||
this.errorMessage = errorMessage; |
|||
} |
|||
|
|||
public ServiceException(AbstractBaseExceptionEnum exception) { |
|||
super(exception.getMessage()); |
|||
this.code = exception.getCode(); |
|||
this.errorMessage = exception.getMessage(); |
|||
} |
|||
|
|||
public ServiceException(WorkflowResultCode resultCode) { |
|||
super(resultCode.message()); |
|||
this.code = resultCode.code(); |
|||
this.errorMessage = resultCode.message(); |
|||
} |
|||
} |
@ -1,47 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.Exception.enums.abs; |
|||
|
|||
/** |
|||
|
|||
* @date 2017/12/17 22:22 |
|||
*/ |
|||
public interface AbstractBaseExceptionEnum { |
|||
|
|||
/** |
|||
* 获取异常的状态码 |
|||
* |
|||
* @return 状态码 |
|||
*/ |
|||
Integer getCode(); |
|||
|
|||
/** |
|||
* 获取异常的提示信息 |
|||
* |
|||
* @return 提示信息 |
|||
*/ |
|||
String getMessage(); |
|||
|
|||
} |
@ -1,27 +0,0 @@ |
|||
package org.dromara.common.consts; |
|||
|
|||
public interface ExceptionCodeConstant { |
|||
// es错误码 {10} {00} {03} {001-100}
|
|||
interface Elasticsearch { |
|||
int ES_INDEX_NOT_EXIST = 100003001; |
|||
} |
|||
|
|||
// 数据源 {10} {00} {04} {001-100}
|
|||
interface DataSource { |
|||
int TABLE_NAME_REPEAT = 100004001; |
|||
|
|||
int COLUMN_NULL = 100004002; |
|||
|
|||
int INCREMENTAL_COLUMN_NULL = 100004003; |
|||
|
|||
// Incrementalolumn is not in column config
|
|||
int INCREMENTAL_COLUMN_NOT_IN_CONFIG = 100004004; |
|||
} |
|||
|
|||
// 业务代码异常
|
|||
interface Service { |
|||
int SQL_EXCEPTION = 100008001; |
|||
int OBJECT_TARGET_NOT_EXIST = 100008051; |
|||
int VALUE_INVALID = 100010001; |
|||
} |
|||
} |
@ -1,67 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.entity; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.FieldFill; |
|||
import com.baomidou.mybatisplus.annotation.TableField; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* 通用基础字段,需要此通用字段的实体可继承此类 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class WorkflowBaseEntity implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 创建时间 |
|||
*/ |
|||
@TableField(fill = FieldFill.INSERT) |
|||
private Date createTime; |
|||
|
|||
/** |
|||
* 创建人 |
|||
*/ |
|||
@TableField(fill = FieldFill.INSERT) |
|||
private Long createUser; |
|||
|
|||
/** |
|||
* 更新时间 |
|||
*/ |
|||
@TableField(fill = FieldFill.UPDATE) |
|||
private Date updateTime; |
|||
|
|||
/** |
|||
* 更新人 |
|||
*/ |
|||
@TableField(fill = FieldFill.UPDATE) |
|||
private Long updateUser; |
|||
|
|||
} |
@ -1,153 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.page; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import org.dromara.common.util.HttpServletUtil; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
|
|||
|
|||
/** |
|||
* 默认分页参数构建 |
|||
* |
|||
*/ |
|||
public class WorkflowPageFactory { |
|||
|
|||
/** |
|||
* 每页大小(默认20) |
|||
*/ |
|||
private static final String PAGE_SIZE_PARAM_NAME = "pageSize"; |
|||
|
|||
/** |
|||
* 第几页(从1开始) |
|||
*/ |
|||
private static final String PAGE_NO_PARAM_NAME = "pageNo"; |
|||
|
|||
/** |
|||
* 默认分页,在使用时PageFactory.defaultPage会自动获取pageSize和pageNo参数 |
|||
* |
|||
* @author xuyuxiang |
|||
* @date 2020/3/30 16:42 |
|||
*/ |
|||
public static <T> Page<T> defaultPage() { |
|||
|
|||
int pageSize = 10; |
|||
int pageNo = 1; |
|||
|
|||
HttpServletRequest request = HttpServletUtil.getRequest(); |
|||
|
|||
//每页条数
|
|||
String pageSizeString = request.getParameter(PAGE_SIZE_PARAM_NAME); |
|||
if (ObjectUtil.isNotEmpty(pageSizeString)) { |
|||
pageSize = Integer.parseInt(pageSizeString); |
|||
} |
|||
|
|||
//第几页
|
|||
String pageNoString = request.getParameter(PAGE_NO_PARAM_NAME); |
|||
if (ObjectUtil.isNotEmpty(pageNoString)) { |
|||
pageNo = Integer.parseInt(pageNoString); |
|||
} |
|||
|
|||
return new Page<>(pageNo, pageSize); |
|||
} |
|||
|
|||
public static <T> Page<T> customPage(Integer pageSize,Integer pageNo) { |
|||
|
|||
if(ObjectUtil.hasEmpty(pageNo,pageSize)){ |
|||
|
|||
return defaultPage(); |
|||
} |
|||
|
|||
return new Page<>(pageNo, pageSize); |
|||
} |
|||
|
|||
public static <T> Page<T> defaultPage(Integer pageNoParam,Integer pageSizeParam) { |
|||
|
|||
int pageSize = 10; |
|||
int pageNo = 1; |
|||
|
|||
//每页条数 moren
|
|||
if (ObjectUtil.isNotEmpty(pageSizeParam)) { |
|||
pageSize = pageSizeParam; |
|||
} |
|||
|
|||
//第几页
|
|||
if (ObjectUtil.isNotEmpty(pageNoParam)) { |
|||
pageNo = pageNoParam; |
|||
} |
|||
|
|||
return new Page<>(pageNo, pageSize); |
|||
} |
|||
|
|||
|
|||
public static <T> Page<T> customPage(Boolean limited) { |
|||
|
|||
if(ObjectUtil.equal(limited,true)){ |
|||
|
|||
return defaultPage(); |
|||
} |
|||
|
|||
return new Page<>(0, -1); |
|||
} |
|||
|
|||
/** |
|||
* 得到分页后的数据 |
|||
* @return 分页后结果 |
|||
*/ |
|||
public static <T>List<T> getPagedList(List<T> data) { |
|||
int pageSize = 10; |
|||
int pageNo = 1; |
|||
|
|||
HttpServletRequest request = HttpServletUtil.getRequest(); |
|||
|
|||
//每页条数
|
|||
String pageSizeString = request.getParameter(PAGE_SIZE_PARAM_NAME); |
|||
if (ObjectUtil.isNotEmpty(pageSizeString)) { |
|||
pageSize = Integer.parseInt(pageSizeString); |
|||
} |
|||
|
|||
//第几页
|
|||
String pageNoString = request.getParameter(PAGE_NO_PARAM_NAME); |
|||
if (ObjectUtil.isNotEmpty(pageNoString)) { |
|||
pageNo = Integer.parseInt(pageNoString); |
|||
} |
|||
|
|||
int fromIndex = (pageNo - 1) * pageSize; |
|||
if (fromIndex >= data.size()) { |
|||
return Collections.emptyList(); |
|||
} |
|||
|
|||
int toIndex = pageNo * pageSize; |
|||
if (toIndex >= data.size()) { |
|||
toIndex = data.size(); |
|||
} |
|||
return data.subList(fromIndex, toIndex); |
|||
} |
|||
|
|||
} |
@ -1,119 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.page; |
|||
|
|||
import cn.hutool.core.convert.Convert; |
|||
import cn.hutool.core.util.PageUtil; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 分页结果集 |
|||
* |
|||
* @author xuyuxiang |
|||
* @date 2020/3/30 15:44 |
|||
*/ |
|||
@Data |
|||
public class WorkflowPageResult<T> implements Serializable { |
|||
|
|||
private static final long serialVersionUID = -1L; |
|||
|
|||
/** |
|||
* 默认分页彩虹展示数量 |
|||
*/ |
|||
public static final int RAINBOW_NUM = 5; |
|||
|
|||
/** |
|||
* 第几页 |
|||
*/ |
|||
private Integer pageNo = 1; |
|||
|
|||
/** |
|||
* 每页条数 |
|||
*/ |
|||
private Integer pageSize = 20; |
|||
|
|||
/** |
|||
* 总页数 |
|||
*/ |
|||
private Integer totalPage = 0; |
|||
|
|||
/** |
|||
* 总记录数 |
|||
*/ |
|||
private Integer totalRows = 0; |
|||
|
|||
/** |
|||
* 结果集 |
|||
*/ |
|||
private List<T> rows; |
|||
|
|||
/** |
|||
* 分页彩虹 |
|||
*/ |
|||
private int[] rainbow; |
|||
|
|||
public WorkflowPageResult() { |
|||
} |
|||
|
|||
/** |
|||
* 将mybatis-plus的page转成自定义的PageResult,扩展了totalPage总页数,和rainBow彩虹条 |
|||
* |
|||
* @author xuyuxiang |
|||
* @date 2020/4/8 19:20 |
|||
*/ |
|||
public WorkflowPageResult(Page<T> page) { |
|||
this.setRows(page.getRecords()); |
|||
this.setTotalRows(Convert.toInt(page.getTotal())); |
|||
this.setPageNo(Convert.toInt(page.getCurrent())); |
|||
this.setPageSize(Convert.toInt(page.getSize())); |
|||
this.setTotalPage(PageUtil.totalPage(Convert.toInt(page.getTotal()), |
|||
Convert.toInt(page.getSize()))); |
|||
// this.setRainbow(PageUtil.rainbow(Convert.toInt(page.getCurrent()),
|
|||
// Convert.toInt(this.getTotalPage()), RAINBOW_NUM));
|
|||
} |
|||
|
|||
/** |
|||
* 将mybatis-plus的page转成自定义的PageResult,扩展了totalPage总页数,和rainBow彩虹条 |
|||
* 可单独设置rows |
|||
* |
|||
* @author xuyuxiang |
|||
* @date 2020/4/14 20:55 |
|||
*/ |
|||
public WorkflowPageResult(IPage<?> page, List<T> t) { |
|||
this.setRows(t); |
|||
this.setTotalRows(Convert.toInt(page.getTotal())); |
|||
this.setPageNo(Convert.toInt(page.getCurrent())); |
|||
this.setPageSize(Convert.toInt(page.getSize())); |
|||
this.setTotalPage(PageUtil.totalPage(Convert.toInt(page.getTotal()), |
|||
Convert.toInt(page.getSize()))); |
|||
// this.setRainbow(PageUtil.rainbow(Convert.toInt(page.getCurrent()),
|
|||
// Convert.toInt(this.getTotalPage()), RAINBOW_NUM));
|
|||
} |
|||
} |
@ -1,355 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.param; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 通用基础参数,相关实体参数校验可继承此类 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class WorkflowBaseParam implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 是否禁用权限 |
|||
*/ |
|||
private boolean withoutPermission = false; |
|||
|
|||
/** |
|||
* 是否进行分页 |
|||
*/ |
|||
private Boolean showPageNation = true; |
|||
|
|||
/** |
|||
* 搜索值 |
|||
*/ |
|||
private String searchValue; |
|||
|
|||
|
|||
/** |
|||
* 数据权限 |
|||
*/ |
|||
private List<Long> dataScope; |
|||
|
|||
|
|||
/** |
|||
* 开始时间 |
|||
*/ |
|||
private String startTime; |
|||
|
|||
/** |
|||
* 结束时间 |
|||
*/ |
|||
private String endTime; |
|||
|
|||
/** |
|||
* 状态(字典 0正常 1停用 2删除) |
|||
*/ |
|||
private Integer searchStatus; |
|||
|
|||
/** |
|||
* 参数校验分组:分页 |
|||
*/ |
|||
public @interface page { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:列表 |
|||
*/ |
|||
public @interface list { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:下拉 |
|||
*/ |
|||
public @interface dropDown { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:增加 |
|||
*/ |
|||
public @interface add { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:编辑 |
|||
*/ |
|||
public @interface edit { |
|||
} |
|||
|
|||
public @interface status { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:更新信息 |
|||
*/ |
|||
public @interface updateInfo { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:修改密码 |
|||
*/ |
|||
public @interface updatePwd { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:重置密码 |
|||
*/ |
|||
public @interface resetPwd { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:修改头像 |
|||
*/ |
|||
public @interface updateAvatar { |
|||
} |
|||
|
|||
public @interface updateTask{ |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:删除 |
|||
*/ |
|||
public @interface delete { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:详情 |
|||
*/ |
|||
public @interface detail { |
|||
} |
|||
|
|||
public @interface batch { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:授权角色 |
|||
*/ |
|||
public @interface grantRole { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:授权菜单 |
|||
*/ |
|||
public @interface grantMenu { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:授权数据 |
|||
*/ |
|||
public @interface grantData { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:强退 |
|||
*/ |
|||
public @interface force { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:停用 |
|||
*/ |
|||
public @interface stop { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:启用 |
|||
*/ |
|||
public @interface start { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:部署 |
|||
*/ |
|||
public @interface deploy { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:挂起 |
|||
*/ |
|||
public @interface suspend { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:激活 |
|||
*/ |
|||
public @interface active { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:调试 |
|||
*/ |
|||
public @interface debug { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:委托 |
|||
*/ |
|||
public @interface entrust { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:转办 |
|||
*/ |
|||
public @interface turn { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:追踪 |
|||
*/ |
|||
public @interface trace { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:跳转 |
|||
*/ |
|||
public @interface jump { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:同意 |
|||
*/ |
|||
public @interface agree { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:退回 |
|||
*/ |
|||
public @interface back { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:终止 |
|||
*/ |
|||
public @interface end { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:导出 |
|||
*/ |
|||
public @interface export { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:映射 |
|||
*/ |
|||
public @interface mapping { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:切换 |
|||
*/ |
|||
public @interface change { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:历史审批记录 |
|||
*/ |
|||
public @interface commentHistory { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:修改状态 |
|||
*/ |
|||
public @interface changeStatus { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:传阅 |
|||
*/ |
|||
public @interface circulate { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:加签 |
|||
*/ |
|||
public @interface addSign { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:减签 |
|||
*/ |
|||
public @interface deleteSign { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:添加节点 |
|||
*/ |
|||
public @interface addNode { |
|||
} |
|||
|
|||
/** |
|||
* 参数校验分组:节点流转 |
|||
*/ |
|||
public @interface flow { |
|||
} |
|||
|
|||
|
|||
public @interface apply { |
|||
} |
|||
public @interface submit { |
|||
} |
|||
|
|||
public @interface reject { |
|||
} |
|||
public @interface cancel { |
|||
} |
|||
public @interface finish { |
|||
} |
|||
|
|||
public @interface rollback { |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 参数校验分组:节点转交 |
|||
*/ |
|||
public @interface forward { |
|||
} |
|||
|
|||
|
|||
public @interface valid {} |
|||
|
|||
public @interface check {} |
|||
|
|||
|
|||
public @interface todo {} |
|||
|
|||
public @interface handle {} |
|||
|
|||
public @interface cc {} |
|||
|
|||
public @interface urge {} |
|||
|
|||
public @interface install { |
|||
} |
|||
|
|||
} |
@ -1,58 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.requestno; |
|||
|
|||
/** |
|||
* 临时保存当前请求号 |
|||
* |
|||
*/ |
|||
public class RequestNoContext { |
|||
|
|||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); |
|||
|
|||
/** |
|||
* 保存请求号 |
|||
* |
|||
*/ |
|||
public static void set(String requestNo) { |
|||
CONTEXT_HOLDER.set(requestNo); |
|||
} |
|||
|
|||
/** |
|||
* 获取请求号 |
|||
* |
|||
*/ |
|||
public static String get() { |
|||
return CONTEXT_HOLDER.get(); |
|||
} |
|||
|
|||
/** |
|||
* 清除请求号 |
|||
* |
|||
*/ |
|||
public static void clear() { |
|||
CONTEXT_HOLDER.remove(); |
|||
} |
|||
} |
@ -1,58 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.response; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
/** |
|||
* 失败响应结果 |
|||
* |
|||
*/ |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@Data |
|||
public class WorkflowErrorResponseData extends WorkflowResponseData { |
|||
|
|||
/** |
|||
* 异常的具体类名称 |
|||
*/ |
|||
private String exceptionClazz; |
|||
|
|||
WorkflowErrorResponseData(String message) { |
|||
super(false, DEFAULT_ERROR_CODE, message, null); |
|||
} |
|||
|
|||
public WorkflowErrorResponseData(Integer code, String message) { |
|||
super(false, code, message, null); |
|||
} |
|||
|
|||
WorkflowErrorResponseData(Integer code, String message, Object object) { |
|||
super(false, code, message, object); |
|||
} |
|||
WorkflowErrorResponseData(){ |
|||
super(); |
|||
} |
|||
|
|||
} |
@ -1,97 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.response; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 响应结果数据 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class WorkflowResponseData { |
|||
|
|||
public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功"; |
|||
|
|||
public static final String DEFAULT_ERROR_MESSAGE = "网络异常"; |
|||
|
|||
public static final Integer DEFAULT_SUCCESS_CODE = 200; |
|||
|
|||
public static final Integer DEFAULT_ERROR_CODE = 500; |
|||
|
|||
/** |
|||
* 请求是否成功 |
|||
*/ |
|||
private Boolean success; |
|||
|
|||
/** |
|||
* 响应状态码 |
|||
*/ |
|||
private Integer code; |
|||
|
|||
/** |
|||
* 响应信息 |
|||
*/ |
|||
private String message; |
|||
|
|||
/** |
|||
* 响应对象 |
|||
*/ |
|||
private Object data; |
|||
|
|||
public WorkflowResponseData() { |
|||
} |
|||
|
|||
public WorkflowResponseData(Boolean success, Integer code, String message, Object data) { |
|||
this.success = success; |
|||
this.code = code; |
|||
this.message = message; |
|||
this.data = data; |
|||
} |
|||
|
|||
public static WorkflowSuccessResponseData success() { |
|||
return new WorkflowSuccessResponseData(); |
|||
} |
|||
|
|||
public static WorkflowSuccessResponseData success(Object object) { |
|||
return new WorkflowSuccessResponseData(object); |
|||
} |
|||
|
|||
public static WorkflowSuccessResponseData success(Integer code, String message, Object object) { |
|||
return new WorkflowSuccessResponseData(code, message, object); |
|||
} |
|||
|
|||
public static WorkflowErrorResponseData error(String message) { |
|||
return new WorkflowErrorResponseData(message); |
|||
} |
|||
|
|||
public static WorkflowErrorResponseData error(Integer code, String message) { |
|||
return new WorkflowErrorResponseData(code, message); |
|||
} |
|||
|
|||
public static WorkflowErrorResponseData error(Integer code, String message, Object object) { |
|||
return new WorkflowErrorResponseData(code, message, object); |
|||
} |
|||
} |
@ -1,54 +0,0 @@ |
|||
package org.dromara.common.response; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* API 接口返回对象 |
|||
*/ |
|||
@Data |
|||
public class WorkflowResult extends WorkflowResponseData { |
|||
|
|||
public static WorkflowSuccessResponseData success(){ |
|||
WorkflowSuccessResponseData result = new WorkflowSuccessResponseData(); |
|||
result.setSuccess(true); |
|||
result.setCode(WorkflowResultCode.SUCCESS.code()); |
|||
result.setMessage(WorkflowResultCode.SUCCESS.message()); |
|||
return result; |
|||
} |
|||
|
|||
public static WorkflowSuccessResponseData success(Object data){ |
|||
WorkflowSuccessResponseData result = new WorkflowSuccessResponseData(); |
|||
result.setSuccess(true); |
|||
result.setCode(WorkflowResultCode.SUCCESS.code()); |
|||
result.setMessage(WorkflowResultCode.SUCCESS.message()); |
|||
result.setData(data); |
|||
return result; |
|||
} |
|||
|
|||
public static WorkflowSuccessResponseData success(Object data, String message){ |
|||
WorkflowSuccessResponseData result = new WorkflowSuccessResponseData(); |
|||
result.setSuccess(true); |
|||
result.setCode(WorkflowResultCode.SUCCESS.code()); |
|||
result.setMessage(message); |
|||
result.setData(data); |
|||
return result; |
|||
} |
|||
|
|||
|
|||
public static WorkflowErrorResponseData error(WorkflowResultCode resultCode){ |
|||
WorkflowErrorResponseData result = new WorkflowErrorResponseData(); |
|||
result.setSuccess(false); |
|||
result.setCode(resultCode.code()); |
|||
result.setMessage(resultCode.message()); |
|||
return result; |
|||
} |
|||
|
|||
public static WorkflowErrorResponseData error(WorkflowResultCode resultCode, Object data){ |
|||
WorkflowErrorResponseData result = new WorkflowErrorResponseData(); |
|||
result.setSuccess(false); |
|||
result.setCode(resultCode.code()); |
|||
result.setMessage(resultCode.message()); |
|||
result.setData(data); |
|||
return result; |
|||
} |
|||
} |
@ -1,691 +0,0 @@ |
|||
package org.dromara.common.response; |
|||
|
|||
public enum WorkflowResultCode { |
|||
|
|||
/** 200~299 成功,操作被成功接收和处理 */ |
|||
SUCCESS(200,"执行成功"), |
|||
|
|||
/** 500~599 失败,服务器再处理请求过程中发生得错误 */ |
|||
FAIL(500,"糟糕,服务器竟然出岔子了,建议刷新页面再试试"), |
|||
SAVE_FAIL(501,"新增失败"), |
|||
UPDATE_FAIL(502,"修改失败"), |
|||
DELETE_FAIL(503,"删除失败"), |
|||
NOT_SUPPORT(504,"不支持该操作"), |
|||
|
|||
/** 1001~9999 业务执行错误码 */ |
|||
/** 998 Ladp服务 */ |
|||
ERROR_LADP_FAIL(998000, "认证失败!"), |
|||
ERROR_LADP_NONE_USER(998001, "无效用户!"), |
|||
ERROR_LADP_ERROR(998002, "认证异常!"), |
|||
CAS_INVALID_TICKET(9020,"CAS Ticket无效"), |
|||
|
|||
/** 角色 ****/ |
|||
ROLE_NOT_EXIST(9020,"角色不存在 "), |
|||
|
|||
ROLE_DATA_SCOPE_EMPTY(9020,"角色数据模型为空 "), |
|||
|
|||
USER_ROLE_NOT_EXIST(9020,"登录用户无角色信息,请联系管理员 "), |
|||
|
|||
ROLE_SYSTEM_FLAG(9020,"系统预设无法删除! "), |
|||
|
|||
/** |
|||
* 应用 |
|||
*/ |
|||
APP_NOT_FOUND(1921,"应用不存在"), |
|||
|
|||
/** 组织机构 */ |
|||
DEPT_PARENT_NOT_EXIST(1010,"上级部门不存在"), |
|||
DEPT_CODE_REPEAT(1011,"部门代码重复"), |
|||
DEPT_NAME_REPEAT(1012,"部门名称重复"), |
|||
DEPT_NOT_EXIST(1013,"部门不存在"), |
|||
DEPT_DEL_FAIL(1014,"删除失败"), |
|||
DEPT_ERROR_FAIL(1015,"部门信息添加失败"), |
|||
DEPT_NOT_VALID(1016,"部门不合法"), |
|||
|
|||
|
|||
/** 教师 */ |
|||
TEACHER_GH_REPEAT(1030, "工号重复"), |
|||
TEACHER_NOT_EXIST(1031, "教师不存在"), |
|||
|
|||
TEACHER_CLASS_EXIST(1032, "班级已添加辅导员,无法添加,请重新选择!"), |
|||
|
|||
|
|||
/** 学生 */ |
|||
STU_XH_REPEAT(1050,"学号重复"), |
|||
STU_NOT_EXIST(1051, "学生不存在"), |
|||
|
|||
/** 白名单 */ |
|||
ALERT_WHITE_EXIST(1056,"此学生已存在于白名单中,请勿重复添加"), |
|||
ALERT_WHITE_NOT_STU(1057,"白名单用户只能为学生,请检查后提交"), |
|||
/** 文件 */ |
|||
REPORT_NOT_EXIST(1052,"分析报告不存在"), |
|||
ASSETS_PATH_NOT_EXIST(1052,"静态资源目录不存在"), |
|||
COMPOSE_FILE_ERROR(1053,"文件压缩失败"), |
|||
FILE_SUFFIX_NOT_ALLOWED(1054,"文件类型不合法"), |
|||
|
|||
FEEDBACK_SETTING_NOT_FOUND(1029,"反馈设置不存在"), |
|||
|
|||
WATERMARK_SETTING_NOT_FOUND(1029,"水印设置不存在"), |
|||
|
|||
|
|||
/** 预警分类 **/ |
|||
ALERT_TYPE_REPEAT(2023,"预警分类名称重复"), |
|||
ALERT_TYPE_DELETE(2024,"已产生对应预警事件分类数据,如需删除,请联系管理员"), |
|||
|
|||
USER_CANNOT_DELETE_ADMIN(9020, "超级管理员不能删除"), |
|||
|
|||
|
|||
USER_PERMISSION_ERROR(100105, "用户无权限,请联系管理员"), |
|||
|
|||
/** 用户组 */ |
|||
GROUP_NAME_NOT_EXIST(1060,"用户组名称不存在"), |
|||
GROUP_NAME_REPEAT(1061,"用户组名称重复"), |
|||
GROUP_OPENED_NOT_EXIST(1062,"用户组类型不存在"), |
|||
GROUP_USER_NOT_EXIST(1063,"用户组成员存在"), |
|||
GROUP_ID_NOT_EXIST(1064,"用户组ID不存在"), |
|||
|
|||
|
|||
YEAR_IS_NOT_VALID(5001,"学年不合法,请重新配置"), |
|||
SCHOOL_CALENDAR_SERVER_ERROR(5002,"节假日API服务异常"), |
|||
SCHOOL_CALENDAR_SETTING_NOT_FOUND(5003,"校历管理设置不存在"), |
|||
SCHOOL_CALENDAR_DATE_NOT_RANGE(5003,"设置的日期不在配置的时间范围内,请重新选择!"), |
|||
SCHOOL_CALENDAR_DURATION(5003,"节假日期间不允许同步预警"), |
|||
|
|||
/** |
|||
* 自定义表单 |
|||
*/ |
|||
FORM_MAKING_NAME_REPEAT(1061,"表单名称重复"), |
|||
|
|||
FORM_NOT_VALID(4027,"表单数据格式不正确"), |
|||
|
|||
FORM_WIDGET_NOT_ALLOWED(1240, "不合法的表单字段"), |
|||
|
|||
|
|||
/** |
|||
* 文件 |
|||
*/ |
|||
FILE_UPLOAD_FAIL(1870, "上传失败!"), |
|||
|
|||
|
|||
/** 字典 */ |
|||
DICT_TYPE_NOT_EXIST(1150, "字典不存在"), |
|||
|
|||
/** |
|||
* 用户认证 |
|||
*/ |
|||
PWD_ERROR(1,"密码错误,请联系管理员"), |
|||
ACCOUNT_PWD_EMPTY(1, "账号或密码为空,请检查账号或密码"), |
|||
ACCOUNT_PWD_ERROR(2, "账号或密码错误,请检查账号或密码"), |
|||
VALID_CODE_ERROR(3, "验证码错误,请检查captcha参数"), |
|||
REQUEST_TOKEN_EMPTY(4, "请求token为空,请携带token访问本接口"), |
|||
NOT_VALID_TOKEN_TYPE(5, "token格式不正确,token请以Bearer开头,并且Bearer后边带一个空格"), |
|||
REQUEST_TOKEN_ERROR(6, "请求token错误"), |
|||
ACCOUNT_FREEZE_ERROR(7, "账号已停用,请联系管理员"), |
|||
LOGIN_EXPIRED(8, "登录已过期,请重新登录"), |
|||
NO_LOGIN_USER(9, "无登录用户"), |
|||
MODE_NOT_PERMISSION(10, "当前接口只允许在开发和测试环境调用"), |
|||
TEMP_USER_NO_PERMISSION(11, "临时用户无访问权限"), |
|||
USER_IS_NOT_ADMIN(12, "非管理员用户无法访问"), |
|||
|
|||
REFERER_ERROR(77, "REFER非法"), |
|||
PARAM_IS_INVALID(9001,"参数无效"), |
|||
PARAM_IS_BLANK(9002,"参数为空"), |
|||
PARAM_BAD_TYPE(9003,"参数类型错误"), |
|||
PARAM_MISSING(9004,"参数缺失"), |
|||
RESULT_EMPTY(9004, "查询结果为空"), |
|||
PARAM_PARSE_ERROR(9005,"参数解析异常"), |
|||
DOWNLOAD_FILE_ERROR(9006,"附件下载异常"), |
|||
ENV_NOT_ALLOWED(9001,"系统环境异常,请联系管理员"), |
|||
|
|||
FILE_UPLOAD_ERROR(1055,"文件上传失败"), |
|||
|
|||
SYSTEM_NOT_FOUND(3006, "应用不存在"), |
|||
|
|||
MODULE_NOT_FOUND(3006, "模块不存在"), |
|||
|
|||
|
|||
/** |
|||
*开放接口鉴权 |
|||
*/ |
|||
AUTH_PARAM_APPKEY_NOT_FOUND(7001,"APP_KEY参数缺失"), |
|||
AUTH_PARAM_APPKEY_ERROR(7001,"APP_KEY参数错误"), |
|||
AUTH_PARAM_SIGN_NOT_FOUND(7002,"签名参数缺失"), |
|||
AUTH_PARAM_TIMESTAMP_NOT_FOUND(7003,"时间戳参数缺失"), |
|||
AUTH_PARAM_TIMESTAMP_ERROR(7004,"时间戳参数错误"), |
|||
AUTH_PARAM_SIGN_ERROR(7005,"签名校验失败"), |
|||
AUTH_PARAM_SIGN_TYPE_ERROR(7006,"签名类型不合法"), |
|||
AUTH_DATA_ACCOUNT_EMPTY(7100, "账号为空"), |
|||
|
|||
|
|||
TAG_NOT_EXIST(2001,"未找到标签"), |
|||
|
|||
TAG_FACTORY_NOT_CONFIG(2001,"标签工厂未配置"), |
|||
|
|||
TAG_FACTORY_SERVER_ERROR(9017, "标签工厂服务异常"), |
|||
TAG_FACTORY_SERVER_EMPTY(9017, "标签工厂服务返回为空"), |
|||
|
|||
TAG_FACTORY_URL_EMPTY(9018, "标签工厂地址未设置,无法配置同步预警对象,请先设置地址!"), |
|||
|
|||
TAG_FACTORY_CONFIG_ERROR(9019, "未设置标签工厂信息,请联系管理员"), |
|||
|
|||
AUTHORIZE_SETTING_ERROR(100102, "免登认证配置不合法,请检查配置"), |
|||
|
|||
/** |
|||
* 用户 |
|||
*/ |
|||
USER_NOT_EXIST(9010,"用户不存在"), |
|||
USER_LOGIN_ERROR(9011,"账户不存在或密码错误"), |
|||
USER_ACCT_FORBIDDEN(9012,"账户已禁用"), |
|||
USER_HAS_EXIST(9013,"用户已存在"), |
|||
USER_ACCT_PWD_EMPTY(9014, "账号或密码为空"), |
|||
USER_AUTH_FAIL(9015, "认证失败"), |
|||
AUTH_WXWORK_NO_CODE(9016, "企业微信认证失败:code 参数为空"), |
|||
AUTH_CAS_NO_TICKET(9017, "CAS认证失败:ticket 参数为空"), |
|||
|
|||
AUTH_SC_CAS_NO_UID(9017, "CAS认证失败:uid 参数为空"), |
|||
|
|||
USER_PHONE_EXIST(9018,"手机号已存在"), |
|||
|
|||
SOURCE_NOT_EXIST(1136, "资源不存在"), |
|||
|
|||
|
|||
ALERT_STATUS_ERROR(2001,"预警状态异常"), |
|||
|
|||
ALERT_TAG_FLOW_NOT_EXIST(2001,"预警标签未配置流程"), |
|||
|
|||
ALERT_NOT_EXIST(2001,"未找到预警信息"), |
|||
ALERT_TAG_NOT_EXIST(2001,"预警事件不存在"), |
|||
ALERT_TEMPLATE_NOT_EXIST(2001,"预警模板不存在"), |
|||
ALERT_TEMPLATE_RULE_INSTALLED(2001,"预警模板已安装"), |
|||
ALERT_TEMPLATE_NAME_REPEAT(2001,"预警模板已重复"), |
|||
|
|||
|
|||
/** |
|||
* 机构管理 |
|||
*/ |
|||
DELETE_HAS_SUB_DEPART(3000, "本部门存在下级部门,不允许删除"), |
|||
DELETE_HAS_USERS_IN_DEPART(3001, "部门内存在成员,不允许删除"), |
|||
CONTACT_MANAGER_NOT_EXIST(3002, "管理组不存在"), |
|||
CONTACT_MANAGER_MORE_ONE(3003, "一个用户只能存在一个管理组中"), |
|||
CONTACT_MANAGER_SUPER_ADMIN_CANNOT_SET(3004, "超级管理员不能添加到任何权限组"), |
|||
CONTACT_MANAGER_SYSTEM_DELETE(3005, "系统管理组不能删除"), |
|||
CONTACT_MANAGER_SYSTEM_UPDATE(3006, "系统管理组不能编辑"), |
|||
CONTACT_MANAGER_USER_NOT_IN(3007, "当前用户不是管理员"), |
|||
|
|||
|
|||
/** |
|||
* 开放平台 |
|||
*/ |
|||
PLUGIN_CODE_REPEAT(7200,"插件已存在,请勿重复添加"), |
|||
PLUGIN_CODE_NOT_EXIST(7201,"插件不存在,请联系管理员"), |
|||
|
|||
|
|||
|
|||
INSTANCE_STAGE_ERROR(992,"流程实例状态异常"), |
|||
|
|||
INSTANCE_STAGE_FINISHED(993,"流程已结束,请勿重复操作"), |
|||
|
|||
INSTANCE_STAGE_COMPETED(994,"流程已完成,请勿重复操作"), |
|||
|
|||
HANDLER_USER_NOT_EXIST(995,"处理人不存在,请联系系统管理员"), |
|||
|
|||
DEFINITION_NOT_EXIST(996,"未找到流程配置信息"), |
|||
|
|||
DEFINITION_RUNNING_NODE_NOT_EXIST(997,"未找到正在运行的流程定义"), |
|||
|
|||
DEFINITION_NODE_NOT_EXIST(998,"未找到流程节点配置信息"), |
|||
|
|||
DEFINITION_NODE_FLOW_RULE_NOT_EXIST(998,"未找到流程节点流转规则配置"), |
|||
|
|||
NODE_TYPE_NOT_EXIST(999,"节点类型不存在"), |
|||
|
|||
NODE_START_NOT_EXIST(1000,"开始节点不存在"), |
|||
|
|||
NODE_CHECKER_TASK_NOT_EXIST(1001,"任务不存在"), |
|||
|
|||
NODE_STARTING_TRIGGER_SCENE_NOT_PERMISSION(1002,"节点不满足触发场景条件"), |
|||
|
|||
NODE_OPERATION_NOT_EXIST(1003,"节点操作类型不存在"), |
|||
|
|||
NODE_STARTING_TRIGGER_FIELD_NOT_PERMISSION(1004,"节点不满足触发字段条件"), |
|||
|
|||
NODE_STARTING_TRIGGER_DATA_NOT_PERMISSION(1005,"节点不满足触发数据条件"), |
|||
|
|||
NODE_STARTING_DATA_NOT_PERMISSION(1006,"节点数据校验不满足条件"), |
|||
|
|||
NODE_NOT_EXIST(1007,"未找到流程节点"), |
|||
|
|||
NODE_NEXT_NOT_EXIST(1008,"找不到审核节点"), |
|||
|
|||
NODE_CHECKER_NOT_PERMISSION(1009,"当前用户无审核权限"), |
|||
|
|||
NODE_CHECKER_NOT_EXIST(1010,"审核节点审核人不存在"), |
|||
|
|||
FORWARD_USER_NOT_EXIST(1011,"转交人为空"), |
|||
|
|||
FORWARD_USER_ERROR(1012,"转交人不能是当前处理人"), |
|||
|
|||
INSTANCE_NOT_EXIST(1003,"流程数据不存在"), |
|||
|
|||
NODE_TYPE_ERROR(1014,"节点类型参数异常"), |
|||
|
|||
NODE_SUGGEST_NOT_EMPTY(1015,"审核节点文本意见不能为空"), |
|||
|
|||
NODE_SIGNATURE_NOT_EMPTY(1016,"审核节点手写签名不能为空"), |
|||
|
|||
PERMISSION_SUBMIT_NO_PERMISSION(1017,"当前处理人无发起流程权限"), |
|||
|
|||
TASK_HAS_EXPIRED(1017,"待办任务已失效,请刷新页面"), |
|||
|
|||
PERMISSION_FORWARD_NO_PERMISSION(1018,"当前处理人无转交处理流程权限"), |
|||
|
|||
PERMISSION_RECALL_NOT_OPEN(1019,"系统未开启撤回功能"), |
|||
|
|||
PERMISSION_RECALL_NO_PERMISSION(1020,"当前处理人无撤回流程权限"), |
|||
|
|||
PERMISSION_RECALL_APPROVAL_NO_PERMISSION(1021,"任务节点已有人提交,发起人无法撤回"), |
|||
|
|||
PERMISSION_ROLLBACK_NOT_OPEN(1022,"系统未开启回退功能"), |
|||
|
|||
ROLLBACK_KEY_NOT_EXIST(1022,"回退节点不存在"), |
|||
|
|||
ROLLBACK_NODE_NOT_PERMISSION(1027,"回退节点不合法"), |
|||
|
|||
ROLLBACK_START_USER_NOT_EXIST(1028,"流程为匿名填报,无法回退到开始节点"), |
|||
|
|||
ROLLBACK_TASK_USER_NOT_EXIST(1029,"流程回退节点找不到负责人,请检查流程设定配置"), |
|||
|
|||
MOVING_NEXT_NODE_NOT_EXIST(1023,"找不到下一节点,流程无法流转"), |
|||
|
|||
MOVING_NEXT_NODE_CHECKER_NOT_EXIST(1024,"未找到下一个节点审核人"), |
|||
|
|||
NODE_FLOW_ERROR(1025,"提交失败,不符合流转条件"), |
|||
|
|||
INVALID_OPERATION(1026,"无效的操作类型"), |
|||
|
|||
INSTANCE_STATUS_ERROR(1028,"流程状态异常"), |
|||
|
|||
NODE_ACTIVE_NOT_EXIST(1029,"找不到激活节点"), |
|||
|
|||
SETTING_ARCHIVE_NOT_EXIST(1029,"归档设置异常,请检查流程设置"), |
|||
|
|||
ARCHIVE_USER_NOT_PERMISSION(1030,"用户无权限发起归档"), |
|||
|
|||
CC_USER_NOT_PERMISSION(1031,"用户无权限发起抄送"), |
|||
|
|||
CC_USER_NOT_EXIST(1031,"抄送用户不存在"), |
|||
|
|||
CC_TASK_NOT_EXIST(1032,"抄送任务不存在"), |
|||
|
|||
ENGINE_RESULT_EMPTY(1033,"流程引擎结果为空"), |
|||
|
|||
FLOW_RUNTIME_EXCEPTION(1034, "流程引擎发生异常,请联系管理员"), |
|||
|
|||
FLOW_STAGE_ERROR(1034, "存在未处理的预警,请检查后重新提交"), |
|||
|
|||
|
|||
NODE_CHECKER_USER_LIMIT(1035,"节点审核人数量不能超过100人"), |
|||
|
|||
NODE_CC_USER_LIMIT(1036,"节点抄送人数量不能超过100人"), |
|||
|
|||
FORM_DATA_HAS_DELETE(1037,"数据已被删除"), |
|||
|
|||
FORM_DETAIL_NOT_EXIST(1134, "表单信息不存在"), |
|||
|
|||
|
|||
TASK_NOT_EXIST(1038,"该流程已被处理或撤回"), |
|||
|
|||
TASK_PARAM_NOT_EXIST(1039,"待办参数不存在"), |
|||
|
|||
TASK_HAS_HANDLED(1040,"待办任务已处理"), |
|||
|
|||
TASK_PROCESSING_HAS_CHANGED(1040,"待办任务已在处理中状态,请勿重复更新"), |
|||
|
|||
|
|||
NODE_TRANSFER_CHECKER_NOT_CHANGE(1041,"流程负责人未改动"), |
|||
|
|||
NODE_TRANSFER_CHECKER_EMPTY(1042,"流程负责人为空"), |
|||
|
|||
USER_NOT_PERMISSION(1043,"用户无权限"), |
|||
|
|||
ROLE_NOT_PERMISSION(1043,"该角色暂无权限访问系统"), |
|||
|
|||
FLOW_INSTANCE_STARTER_NOT_FOUND(1044,"未找到流程发起人"), |
|||
|
|||
FLOW_INSTANCE_URGE_CLOSED(1045,"流程设定未开启催办"), |
|||
|
|||
FLOW_INSTANCE_URGE_LIMITED(1046,"5分钟内至多发送一次督办提醒"), |
|||
|
|||
FLOW_INSTANCE_URGE_NODE_ERROR(1046,"流程实例异常,请稍后再试"), |
|||
|
|||
FORM_PERMISSION_FAIL(1300, "用户无表单访问权限"), |
|||
FLOW_DEFINITION_NOT_EXIST(1301, "流程定义不存在"), |
|||
FLOW_DEFINITION_START_PROCESS_NOT_EXIST(1302, "流程定义开始节点不存在"), |
|||
FLOW_INSTANCE_FAIL(1303, "表单已填报,请勿重复填报"), |
|||
FLOW_INSTANCE_NOT_EXIST(1304, "流程实例不存在"), |
|||
FLOW_INSTANCE_STATUS_ERROR(1306, "流程实例状态异常"), |
|||
DATASOURCE_NOT_FOUND(1281, "找不到数据源"), |
|||
|
|||
FLOW_DRAFT_SUCCESS(1344, "草稿保存成功"), |
|||
|
|||
FLOW_URGE_SUCCESS(1344, "已提醒负责人处理"), |
|||
|
|||
FLOW_INSTANCE_PROCESS_NOT_EXIST(1305, "流程实例节点不存在"), |
|||
FLOW_INSTANCE_CC_NOT_EXIST(1306, "实例抄送不存在"), |
|||
FLOW_INSTANCE_EXIST(1305, "存在流程实例"), |
|||
|
|||
FLOW_PERMISSION_RECALL_FAIL(1320, "用户无权限撤回"), |
|||
FLOW_APPROVAL_NOT_PERMISSION(1321, "当前用户无审核权限"), |
|||
FLOW_ROLLBACK_NOT_PERMISSION(1323, "当前用户无权限退回该流程"), |
|||
FLOW_INSTANCE_NOT_SUBMIT(1322, "实例还没填报"), |
|||
FLOW_DEFINITION_NOT_APPROVER(1323, "审批节点未设置审核人"), |
|||
FLOW_DEFINITION_INSTANCE_EXIST(1325, "该流程定义存在运行实例"), |
|||
FLOW_DEFINITION_EXIST(1327, "流程定义已存在"), |
|||
FLOW_VERSION_FORM_ERROR(1326, "表单状态异常"), |
|||
FLOW_DEFINITION_PARAM_ERROR(1327, "流程参数异常"), |
|||
FLOW_USER_ROLE_NOT_PERMISSION(1328, "用户身份校验失败"), |
|||
FLOW_DEFINITION_NODE_NOT_EXIST(1329, "流程定义节点数据不存在"), |
|||
FLOW_FORM_NOT_PERMISSION(1330, "表单参数异常"), |
|||
FLOW_LINE_ELSE_CONDITION_ERROR(1331, "连接线存在多个else条件"), |
|||
FLOW_BUTTON_ROLLBACK_ERROR(1332, "未找到回退按钮"), |
|||
FLOW_DEFINITION_VERSION_NOT_EXIST(1333, "未找到流程定义"), |
|||
FLOW_INSTANCE_NOT_FINISHED(1334, "实例未结束"), |
|||
FLOW_ENDNODE_NOT_EXIST(1335, "未找到结束节点"), |
|||
FLOW_NEXT_PROCES_NOT_EXIST(1324, "提交失败,找不到下个审核节点,可联系管理员检查流程节点后重新提交。"), |
|||
FLOW_LINE_CONDITION_ERROR(1331, "提交失败,不符合流转条件,可联系管理员检查流转条件后重新提交。"), |
|||
FLOW_NEXT_NODE_CHECKER_MISSING(1336, "提交失败,找不到下个节点负责人,可联系管理员检查节点负责人后重新提交。"), |
|||
FLOW_INSTANCE_STAGE_NOT_APPROVAL(1337, "抱歉,审核任务已过期"), |
|||
FLOW_APPROVAL_PERMISSION_ERROE(1338, "抱歉,你没有审核权限"), |
|||
FLOW_DEFINITION_VERSION_STAGE_ERROR(1339, "流程版本状态异常"), |
|||
FLOW_FORM_FIELD_PERMISSION(1340, "节点未设置表单字段"), |
|||
FLOW_FORM_APPROVAL_NOT_EXIST(1341, "审核节点未设置审核人"), |
|||
FLOW_NODE_COUNT_ERROR(1342, "回退节点数量异常"), |
|||
|
|||
FLOW_INSTANCE_STAGE_FINISHED(1343, "抱歉,审核任务已结束"), |
|||
FLOW_INSTANCE_STAGE_RECALL(1344, "抱歉,审核任务已撤回"), |
|||
|
|||
CHECK_PARAM_TIME_ERROR(4000, "登记时间参数格式异常"), |
|||
|
|||
/** |
|||
* 业务异常 |
|||
*/ |
|||
MODULE_NAME_REPEAT(2, "模块已存在,请检查后提交"), |
|||
FORM_NAME_REPEAT(2, "表单已存在,请检查后提交"), |
|||
MENU_NAME_REPEAT(2, "数据中心已存在,请检查后提交"), |
|||
|
|||
MENU_NAME_DEFAULT(2, "默认的数据中心只能有一个,请检查后在提交"), |
|||
MODULE_NOT_EXIST(1001,"模块不存在"), |
|||
MODULE_FIELD_NOT_EXIST(1002,"模块字段为空"), |
|||
|
|||
SCHOOL_NOT_INIT(1004,"学校基础信息未初始化,无法同步师生数据"), |
|||
|
|||
|
|||
DATASOURCE_TYPE_NOT_SUPPORTED(1003,"数据源目前不支持此类型"), |
|||
|
|||
ES_RETURN_EMPTY(2, "数据分析平台返回数据为空!"), |
|||
|
|||
|
|||
CLASS_RETURN_EMPTY(2, "班级信息为空!"), |
|||
|
|||
FACULTY_RETURN_EMPTY(2, "学院信息为空!"), |
|||
|
|||
USER_RETURN_EMPTY(2, "用户信息为空!"), |
|||
|
|||
|
|||
DEPART_TYPE_EMPTY(9020,"部门类型为空 "), |
|||
|
|||
DEPART_NOT_FOUND(9020,"用户部门不能为空 "), |
|||
|
|||
USER_MUST_INSTRUCTOR(2005,"用户角色只能为辅导员"), |
|||
|
|||
|
|||
/***********************************通讯录相关 start***************************************/ |
|||
SYNC_TYPE_EMPTY(2, "同步通讯录类型不存在!"), |
|||
SYNC_TYPE_TASK_EMPTY(2, "同步通讯录存储过程类型不存在!"), |
|||
ES_INDEX_RETURN_EMPTY(2404, "同步索引未进行配置,请进行配置!"), |
|||
SYNC_TEACHER_INDEX_NOT_EXIST(1005,"同步教师数据索引不存在"), |
|||
SYNC_STUDENT_INDEX_NOT_EXIST(1006,"同步学生数据索引不存在"), |
|||
SYNC_FACULTY_INDEX_NOT_EXIST(1007,"同步学院数据索引不存在"), |
|||
SYNC_CLASS_INDEX_NOT_EXIST(1008,"同步班级数据索引不存在"), |
|||
SYNC_TEACHER_CLASS_INDEX_NOT_EXIST(1009,"同步带班数据索引不存在"), |
|||
ES_SERVER_ERROR(1010,"网络异常/连接ES平台异常"), |
|||
|
|||
OBJECT_FIELD_NOT_VALID(1011,"数据不合法"), |
|||
|
|||
OBJECT_FIELD_FACULTY_NOT_VALID(1012,"学院数据不合法"), |
|||
OBJECT_FIELD_CLASS_NOT_VALID(1013,"班级数据不合法"), |
|||
OBJECT_FIELD_ACCOUNT_NOT_VALID(1014,"教师工号数据不合法"), |
|||
OBJECT_FIELD_PARENT_CODE_NOT_VALID(1015,"父类编码数据不合法"), |
|||
|
|||
|
|||
|
|||
/***********************************通讯录相关 end***************************************/ |
|||
|
|||
|
|||
/***********************************预警子系统 start***************************************/ |
|||
|
|||
ALERT_RULE_NOT_EXIST(100101,"预警规则不存在"), |
|||
NOTIFY_CONFIG_NOT_FOUND(100102, "提醒配置信息未找到"), |
|||
TIMER_CRON_ERROR(100103, "定时设置不合法,请检查配置"), |
|||
FORM_NOT_EXIST(100104, "自定义表单不存在,请联系管理员"), |
|||
|
|||
OPEN_TAG_NOT_EXIST(9004, "未找到合法的预警模型"), |
|||
|
|||
SYNC_RESULT_EMPTY(9004, "预警同步结果为空"), |
|||
|
|||
|
|||
|
|||
/***********************************预警子系统 end***************************************/ |
|||
|
|||
|
|||
|
|||
COMPONENT_NOT_FOUND(3005,"组件不存在"), |
|||
|
|||
/***********************************陪伴子系统 start***************************************/ |
|||
|
|||
/** 陪伴主题 **/ |
|||
ACMP_THEME_NOT_EXIST(2002,"陪伴主题不存在"), |
|||
|
|||
ACMP_THEME_DELETE(2003,"已产生对应陪伴数据,如需删除,请联系管理员"), |
|||
|
|||
ACMP_THEME_REPEAT(2004,"主题名称重复"), |
|||
|
|||
/** 陪伴选项分类 **/ |
|||
ACMP_TYPE_REPEAT(2005,"选项分类名称重复"), |
|||
|
|||
ACMP_TYPE_DELETE(2003,"分类已有陪伴选项关联,如需删除,请联系管理员"), |
|||
|
|||
ACMP_TYPE_NOT_EXIST(2002,"选项分类不存在"), |
|||
|
|||
/** 陪伴中心**/ |
|||
|
|||
ACMP_DATA_NOT_EXIST(2006,"陪伴数据不存在"), |
|||
|
|||
ACMP_DATA_NOT_SUPPORT_UPLOAD(2007,"该陪伴数据不支持上传"), |
|||
|
|||
ACMP_SETTING_DISPOSE_NOT_EXIST(2004,"未设置陪伴方式,请联系管理员"), |
|||
|
|||
ACMP_SYSTEM_NOT_EXIST(2002,"陪伴体系不存在"), |
|||
ACMP_SYSTEM_NAME_REPEAT(2005,"选项体系名称重复"), |
|||
|
|||
|
|||
ACMP_SYSTEM_CANT_DELETE(2002,"陪伴体系存在陪伴数据,无法删除"), |
|||
|
|||
|
|||
ACMP_OPTION_NOT_EXIST(2002,"陪伴选项不存在"), |
|||
|
|||
ACMP_OPTION_CANT_DELETE(2002,"陪伴选项存在陪伴数据,无法删除"), |
|||
|
|||
ACMP_OPTION_NAME_REPEAT(2005,"选项选项名称重复"), |
|||
|
|||
|
|||
ACMP_UPLOAD_FAIL(2006,"陪伴数据上传失败"), |
|||
|
|||
ACMP_ADD_FAIL(2006,"创建陪伴记录失败"), |
|||
|
|||
|
|||
ACMP_CONFIG_MISS(2007,"缺少陪伴上报配置"), |
|||
|
|||
ACMP_ADD_NOT_STUDENT(2008,"一对多陪伴未设置陪伴学生!"), |
|||
|
|||
|
|||
/***********************************陪伴子系统 end***************************************/ |
|||
|
|||
|
|||
/***********************************关注子系统 start***************************************/ |
|||
|
|||
FOLLOW_STUDENT_NOT_FOLLOWED(100301,"您未关注该学生,无法取消关注"), |
|||
|
|||
FOLLOW_EXCEL_ERROR(100302,"批量关注Excel格式不正确"), |
|||
|
|||
/***********************************关注子系统 end***************************************/ |
|||
|
|||
|
|||
/***********************************考核子系统 start***************************************/ |
|||
CHECK_USER_MUST_INSTRUCTOR(2005,"参与考核成员必须为辅导员"), |
|||
ASSESS_FOLLOW_STUDENT_NOT_FOUND(2005,"未找到关注学生陪伴考核陪伴信息"), |
|||
|
|||
ASSESS_RECOMMEND_STUDENT_NOT_FOUND(2005,"未找到关注学生陪伴考核陪伴信息"), |
|||
|
|||
/***********************************考核子系统 end***************************************/ |
|||
MESSAGE_NOT_FOUND(1046,"消息不存在"), |
|||
|
|||
|
|||
/***********************************学生预约辅导员 start***************************************/ |
|||
RESERVATION_NOT_EXIST(1046,"未找到学生预约记录"), |
|||
RESERVATION_RULE_NOT_OPEN(1046,"辅导员未开启预约"), |
|||
RESERVATION_RULE_DAY_RULE_EMPTY(1002,"未找到当天预约内容"), |
|||
RESERVATION_RULE_DAY_RULE_PERIOD_NOT_FOUND(1002,"未找到当天预约时段,请联系辅导员"), |
|||
RESERVATION_PERIOD_OVERDUE(1002,"预约时段已过期,请刷新页面"), |
|||
RESERVATION_USER_REPEATED(1002,"请勿重复预约"), |
|||
|
|||
RESERVATION_CANCEL_USER_NO_PERMISSION(1002,"非本人无权限撤回预约"), |
|||
|
|||
RESERVATION_INSTRUCTOR_NOT_EXIST(1002,"未找到辅导员信息,请联系管理员"), |
|||
|
|||
RESERVATION_STUDENT_NOT_EXIST(1002,"未找到学生,请联系管理员"), |
|||
|
|||
|
|||
RESERVATION_FINISH_COMMENT_NOT_EXIST(1046,"预约沟通结果不能为空"), |
|||
|
|||
|
|||
/***********************************学生预约辅导员 end***************************************/ |
|||
|
|||
|
|||
/***********************************我爱记学生子系统 start***************************************/ |
|||
|
|||
ASSESS_CONFIG_NOT_EXIST(2002,"考试配置不存在"), |
|||
ASSESS_CONFIG_NAME_EXIST(2002,"存在名称重复的考试,请修改考试名称"), |
|||
|
|||
ASSESS_QUESTION_CONFIG_NOT_EXIST(2002,"考试题库配置不存在,请联系管理员"), |
|||
ASSESS_QUESTION_EMPTY_ERROR(2002,"考试未设置题目,请检查考试题目配置"), |
|||
ASSESS_QUESTION_CONFIG_ERROR(2002,"题库配置错误,请检查题库是否配置了不存在的学生属性"), |
|||
ASSESS_EXAM_RECORD_NOT_FOUND(2002,"您已提交本次考试结果,请勿重复提交"), |
|||
ASSESS_TRAIN_RECORD_NOT_FOUND(2002,"很抱歉,未找到您的本次训练成绩,请联系管理员"), |
|||
|
|||
EXAM_QUESTION_OVER_LIMIT(2002,"单场考试至多500道题目"), |
|||
|
|||
ASSESS_RECORD_DELETE_ERROR(2002,"考试记录已删除,无法再次删除"), |
|||
ASSESS_RECORD_LEVEL_EXISTS(2002,"考试成绩已存在,不能再次提交答卷"), |
|||
ASSESS_CONFIG_NOT_STU(2002,"本次考试未找到符合条件的学生信息,请联系管理员"), |
|||
ASSESS_CONFIG_NOT_START(2002,"未到考试时间,无法参加考试"), |
|||
ASSESS_CONFIG_HAS_FINISHED(2002,"考试已结束"), |
|||
ASSESS_CONFIG_NOT_TIMES(2002,"您已经参加过本次考试,请勿重复考试"), |
|||
ASSESS_CONFIG_NOT_INSTRS(2002,"无考试权限:不在考试名单中,请联系管理员"), |
|||
ASSESS_RECORD_OVER_LIMIT(2002,"您目前仍有一条正在考试的记录,请先提交该考试成绩"), |
|||
ASSESS_RECORD_PERMISSION_ERROR(2002,"您没有查看此记录的权限"), |
|||
ASSESS_QUESTION_NOT_EXIST(2002,"未找到训练题目"), |
|||
|
|||
ASSESS_EXAM_HAS_RECORD(2002,"当前考试有考生正在考试,请勿操作"), |
|||
|
|||
ASSESS_RECORD_NOT_FOUND(2002,"该数据已被删除或者您没有查看该数据的权限"), |
|||
|
|||
TEACHER_NOT_FOUND(2002,"没有教师数据权限"), |
|||
|
|||
DATASOURCE_NOT_EXIST(1003,"未配置数据源,请联系管理员"), |
|||
|
|||
DATASOURCE_DEFAULT_NOT_EXIST(1003,"未配置默认数据源,请联系管理员"), |
|||
|
|||
|
|||
/***********************************我爱记学生子系统 end***************************************/ |
|||
|
|||
|
|||
/***********************************公权力监督 start***************************************/ |
|||
|
|||
PORTRAIT_TITLE_REPEAT(2006,"画像名称重复"), |
|||
|
|||
PORTRAIT_NOT_EXIST(2007,"画像不存在"), |
|||
|
|||
PORTRAIT_DELETE(2003,"已有对应的组件配置,如需删除,请联系管理员"), |
|||
|
|||
TEMPLATE_TITLE_REPEAT(2008,"模板名称重复"), |
|||
TEMPLATE_NOT_EXIST(2009,"模板不存在"), |
|||
|
|||
PORTRAIT_DASHBOARD_NOT_EXIST(2007,"数据看板不存在"), |
|||
|
|||
DATACORRECTION_SETTING_NOT_FOUND(1029,"数据纠错表单地址不存在"), |
|||
DATACOLLECTION_SETTING_NOT_FOUND(1029,"数据采集表单地址不存在"), |
|||
|
|||
PORTRAIT_EDIT_USER_NOT_PERMISSION(1029,"用户无权限编辑画像"), |
|||
PORTRAIT_DELETE_USER_NOT_PERMISSION(1029,"用户无权限删除画像"), |
|||
PORTRAIT_VIEW_USER_NOT_PERMISSION(1029,"用户无权限查看画像"), |
|||
|
|||
DASHBOARD_EDIT_USER_NOT_PERMISSION(1029,"用户无权限编辑数据看板"), |
|||
|
|||
DASHBOARD_DELETE_USER_NOT_PERMISSION(1029,"用户无权限删除数据看板"), |
|||
DASHBOARD_VIEW_USER_NOT_PERMISSION(1029,"用户无权限查看数据看板"), |
|||
|
|||
VISIT_CODE_IS_EMPTY(1029,"公开访问码为空"), |
|||
|
|||
VISIT_CODE_IS_NOT_CORRECT(1029,"访问码不正确"), |
|||
|
|||
PORTRAIT_NOT_RELEASE(1029,"画像未发布,请联系管理员"), |
|||
|
|||
/***********************************公权力监督 end***************************************/ |
|||
|
|||
//region 进度模块错误
|
|||
TASK_RUNNING(3000,"当前任务正在运行中"), |
|||
TASK_NOT_RUNNING(3001,"任务不处于运行状态"), |
|||
|
|||
TASK_NAME_NOT_NULL(3002,"任务名称不能为空"), |
|||
//endregion
|
|||
|
|||
//region 画像模块相关错误码
|
|||
|
|||
ES_CLIENT_INIT_ERROR(10000,"es数据源链接失败"), |
|||
ES_CLIENT_ERROR(10001,"es连接错误"), |
|||
|
|||
|
|||
PROJECT_NOT_EXIST(1029,"科研项目未找到"), |
|||
|
|||
PROJECT_ALERT_EMPTY(2023,"科研项目数据为空"), |
|||
|
|||
OBJECT_SCHEMA_NOT_FOUND(2001,"数据接入未设置"), |
|||
|
|||
PROJECT_SQL_NOT_CONFIG(2002,"查询语句未配置"), |
|||
|
|||
|
|||
|
|||
ES_INDEX_NOT_EXIST(10001,"未找到数据盒,请检查数据盒配置"), |
|||
|
|||
//endregion
|
|||
; |
|||
|
|||
|
|||
private Integer code; |
|||
private String message; |
|||
|
|||
WorkflowResultCode(Integer code, String message){ |
|||
this.code = code; |
|||
this.message = message; |
|||
} |
|||
|
|||
public Integer code() { |
|||
return code; |
|||
} |
|||
|
|||
public String message() { |
|||
return message; |
|||
} |
|||
|
|||
} |
@ -1,44 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.response; |
|||
|
|||
/** |
|||
* 成功响应结果 |
|||
* |
|||
*/ |
|||
public class WorkflowSuccessResponseData extends WorkflowResponseData { |
|||
|
|||
public WorkflowSuccessResponseData() { |
|||
super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, null); |
|||
} |
|||
|
|||
public WorkflowSuccessResponseData(Object object) { |
|||
super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, object); |
|||
} |
|||
|
|||
public WorkflowSuccessResponseData(Integer code, String message, Object object) { |
|||
super(true, code, message, object); |
|||
} |
|||
} |
@ -1,68 +0,0 @@ |
|||
/* |
|||
Copyright [2020] [https://www.stylefeng.cn]
|
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: |
|||
|
|||
1.请不要删除和修改根目录下的LICENSE文件。 |
|||
2.请不要删除和修改Guns源码头部的版权声明。 |
|||
3.请保留源码和相关描述文件的项目出处,作者声明等。 |
|||
4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns-separation
|
|||
6.若您的项目无法满足以上几点,可申请商业授权,获取Guns商业授权许可,请在官网购买授权,地址为 https://www.stylefeng.cn
|
|||
*/ |
|||
package org.dromara.common.util; |
|||
|
|||
|
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
import org.springframework.web.context.request.ServletRequestAttributes; |
|||
|
|||
|
|||
/** |
|||
* HttpServlet工具类,获取当前request和response |
|||
* |
|||
|
|||
*/ |
|||
public class HttpServletUtil { |
|||
|
|||
/** |
|||
* 获取当前请求的request对象 |
|||
* |
|||
*/ |
|||
public static HttpServletRequest getRequest() { |
|||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|||
if (requestAttributes == null) { |
|||
throw new ServiceException(WorkflowResultCode.PARAM_IS_BLANK); |
|||
} else { |
|||
return requestAttributes.getRequest(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取当前请求的response对象 |
|||
* |
|||
*/ |
|||
public static HttpServletResponse getResponse() { |
|||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
|||
if (requestAttributes == null) { |
|||
throw new ServiceException(WorkflowResultCode.PARAM_IS_BLANK); |
|||
} else { |
|||
return requestAttributes.getResponse(); |
|||
} |
|||
} |
|||
} |
@ -1,128 +0,0 @@ |
|||
package org.dromara.common.util; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.fasterxml.jackson.databind.JavaType; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
import java.lang.reflect.Field; |
|||
import java.util.HashMap; |
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 定义响应结构 |
|||
*/ |
|||
public class JsonUtil { |
|||
|
|||
private static ObjectMapper MAPPER; |
|||
static{ |
|||
MAPPER=new ObjectMapper(); |
|||
} |
|||
|
|||
/** |
|||
* 将对象转换成json字符串。 |
|||
* <p>Title: pojoToJson</p> |
|||
* <p>Description: </p> |
|||
* @param data |
|||
* @return |
|||
*/ |
|||
public static String toJson(Object data){ |
|||
String string = null; |
|||
try { |
|||
string = MAPPER.writeValueAsString(data); |
|||
if(StringUtils.isEmpty(string)){ |
|||
return null; |
|||
} |
|||
return string; |
|||
} catch (JsonProcessingException e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 将json结果集转化为对象 |
|||
* |
|||
* @param jsonData json数据 |
|||
* @return |
|||
*/ |
|||
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { |
|||
try { |
|||
T t = MAPPER.readValue(jsonData, beanType); |
|||
return t; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 将json数据转换成pojo对象list |
|||
* <p>Title: jsonToList</p> |
|||
* <p>Description: </p> |
|||
* @param jsonData |
|||
* @param beanType |
|||
* @return |
|||
*/ |
|||
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { |
|||
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); |
|||
try { |
|||
List<T> list = MAPPER.readValue(jsonData, javaType); |
|||
return list; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 将Object对象里面的属性和值转化成Map对象 |
|||
* |
|||
* @param obj |
|||
* @return |
|||
* @throws IllegalAccessException |
|||
*/ |
|||
public static Map<String, Object> objectToMap(Object obj){ |
|||
try { |
|||
Map<String, Object> map = new HashMap<String,Object>(); |
|||
Class<?> clazz = obj.getClass(); |
|||
for (Field field : clazz.getDeclaredFields()) { |
|||
field.setAccessible(true); |
|||
String fieldName = field.getName(); |
|||
if(ObjectUtil.isNotEmpty(field.get(obj))){ |
|||
Object value = field.get(obj); |
|||
map.put(fieldName, value); |
|||
}else{ |
|||
map.put(fieldName, ""); |
|||
} |
|||
} |
|||
return map; |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static Map<String, Object> jsonToMap(String json){ |
|||
try { |
|||
return MAPPER.readValue(json, new TypeReference<Map<String, Object>>(){}); |
|||
} catch (JsonProcessingException e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static LinkedHashMap<String, String> jsonToStrMap(String json){ |
|||
try { |
|||
return MAPPER.readValue(json, new TypeReference<LinkedHashMap<String, String>>(){}); |
|||
} catch (JsonProcessingException e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -1,87 +0,0 @@ |
|||
package org.dromara.dataManager.controller; |
|||
|
|||
|
|||
import org.dromara.common.response.WorkflowResponseData; |
|||
import org.dromara.common.response.WorkflowResult; |
|||
import org.dromara.dataManager.param.FormDataParam; |
|||
import org.dromara.dataManager.param.UpdateDataParams; |
|||
import org.dromara.dataManager.service.FormDataService; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
|
|||
/** |
|||
* 表单数据服务API |
|||
* |
|||
*/ |
|||
@RestController |
|||
@RequestMapping("/form") |
|||
public class FormDataController { |
|||
|
|||
@Autowired |
|||
private FormDataService formDataService; |
|||
|
|||
|
|||
/** |
|||
* 列表查询表单数据 |
|||
*/ |
|||
@GetMapping("/data/page") |
|||
public WorkflowResponseData pageFormData(FormDataParam param) { |
|||
return WorkflowResult.success(formDataService.pageFormData(param)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加表单数据 |
|||
*/ |
|||
@PostMapping("/data/add") |
|||
public WorkflowResponseData addTFormData( |
|||
@RequestBody @Validated(FormDataParam.add.class) FormDataParam param) { |
|||
|
|||
return WorkflowResult.success(formDataService.addFormData(param)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 编辑表单数据 |
|||
*/ |
|||
@PostMapping("/{formId}/data/{dataId}/edit") |
|||
public WorkflowResponseData editFormData( |
|||
@PathVariable("formId")Long formId,@PathVariable("dataId")Long dataId, |
|||
@RequestBody UpdateDataParams param) { |
|||
|
|||
return WorkflowResult.success(formDataService.editFormData(param)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 查询单个表单数据 |
|||
*/ |
|||
@GetMapping("/{formId}/data/{dataId}/detail") |
|||
public WorkflowResponseData getFormDataDetail(@PathVariable("formId")Long formId, @PathVariable("dataId")Long dataId) { |
|||
|
|||
return WorkflowResult.success(formDataService.getFormDataFullInfo(formId,dataId)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 删除表单数据 |
|||
*/ |
|||
@PostMapping("/{formId}/data/{dataId}/delete") |
|||
public WorkflowResponseData deleteFormData(@PathVariable("formId")Long formId, @PathVariable("dataId")Long dataId) { |
|||
|
|||
return WorkflowResult.success(formDataService.deleteFormData(dataId)); |
|||
} |
|||
|
|||
/** |
|||
* 导出表单数据 |
|||
*/ |
|||
@GetMapping("/data/export") |
|||
public void exportFormData(FormDataParam param) { |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
|
@ -1,96 +0,0 @@ |
|||
package org.dromara.dataManager.controller; |
|||
|
|||
|
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.dromara.common.response.WorkflowResponseData; |
|||
import org.dromara.common.response.WorkflowResult; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.dataManager.param.DownloadDataParams; |
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.dataManager.service.impt.exception.ImportDataInvalidException; |
|||
import org.dromara.dataManager.service.impt.service.ImportFromExcelService; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.json.JSONUtil; |
|||
import com.fasterxml.jackson.core.type.TypeReference; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.*; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @description: 表单数据导入、导入 |
|||
*/ |
|||
@Slf4j |
|||
@RestController |
|||
@RequestMapping({"/manager/data","/data"}) |
|||
public class FormDataExcelController { |
|||
|
|||
@Autowired |
|||
private ImportFromExcelService importFromExcelService; |
|||
|
|||
/** |
|||
* 数据导出 |
|||
* |
|||
* @param params |
|||
* @param response |
|||
* @throws IOException |
|||
*/ |
|||
@PostMapping("/export") |
|||
public void export(@RequestBody @Validated DownloadDataParams params, HttpServletResponse response) throws IOException { |
|||
// exportESDataService.exportData(params, response);
|
|||
} |
|||
|
|||
/** |
|||
* 导入前预览 |
|||
* |
|||
* @param params |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("/import/preview") |
|||
public WorkflowResponseData previewExcel(@RequestParam("file") MultipartFile file, ImportDataParams params) throws Exception { |
|||
return WorkflowResult.success(importFromExcelService.previewExcel(file,params.getSheetIndex())); |
|||
} |
|||
|
|||
/** |
|||
* 数据导入 |
|||
* |
|||
* @param params |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("/import") |
|||
public WorkflowResponseData importExcelData(ImportDataParams params) { |
|||
|
|||
try { |
|||
Map<Integer, String> realMapping = new ObjectMapper().readValue(params.getMapping(), new TypeReference<Map<Integer, String>>() {}); |
|||
params.setObjMapping(realMapping); |
|||
params.setValidationConfig(JSONUtil.toBean(params.getValidationConfigStr(), ImportDataParams.ValidationConfig.class)); |
|||
return WorkflowResult.success(importFromExcelService.importV2(params)); |
|||
} catch (ImportDataInvalidException e) { |
|||
return CollectionUtil.isEmpty(e.getInvalidRows()) ? WorkflowResult.error(e.getMessage()) : WorkflowResult.error(WorkflowResultCode.FAIL, e.getInvalidRows()); |
|||
} catch (Exception e) { |
|||
log.error(e.getMessage(), e); |
|||
return WorkflowResult.error("导入数据异常" + e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 下载导入数据模板 |
|||
* |
|||
* @param params |
|||
* @param |
|||
* @throws Exception |
|||
*/ |
|||
@PostMapping("/import/template") |
|||
public void generateImportTemplate(@RequestBody ImportDataParams params, |
|||
HttpServletResponse response) throws Exception { |
|||
importFromExcelService.generateImportTemplate(response, params.getFormId(), params.getExportFields()); |
|||
} |
|||
|
|||
} |
@ -1,133 +0,0 @@ |
|||
package org.dromara.dataManager.controller; |
|||
|
|||
|
|||
import org.dromara.common.satoken.utils.LoginHelper; |
|||
import org.dromara.common.response.WorkflowResponseData; |
|||
import org.dromara.common.response.WorkflowResult; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.dataManager.param.ActiveDataParams; |
|||
import org.dromara.dataManager.param.TransferDataParams; |
|||
import org.dromara.dataManager.param.UpdateDataParams; |
|||
import org.dromara.dataManager.service.FormDataService; |
|||
import org.dromara.workflow.engine.domain.Instance; |
|||
import org.dromara.workflow.result.engine.BaseActionResult; |
|||
import org.dromara.workflow.result.engine.EngineDataResult; |
|||
import org.dromara.workflow.service.external.FlowInstanceService; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
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; |
|||
|
|||
/** |
|||
* @desc 数据管理API |
|||
*/ |
|||
@RestController |
|||
@RequestMapping({"/manager/data"}) |
|||
public class FormDataInstanceController { |
|||
@Autowired |
|||
private FlowInstanceService instanceService; |
|||
@Autowired |
|||
private FormDataService formDataService; |
|||
|
|||
/** |
|||
* 调整流程负责人 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
@PostMapping("/instance/transfer") |
|||
public WorkflowResponseData transfer(@RequestBody TransferDataParams param){ |
|||
if(ObjectUtil.hasEmpty(param.getDataId(),param.getData(),param.getFormId(),param.getTransferNodeId(), |
|||
param.getCheckers())){ |
|||
return WorkflowResult.error(WorkflowResultCode.PARAM_MISSING); |
|||
} |
|||
|
|||
Instance instance = instanceService.getInstance(param.getDataId()); |
|||
|
|||
//更新流程节点调整负责人
|
|||
BaseActionResult actionRsp = instanceService.transferInstanceUser(instance,param.getTransferNodeId(),param.getCheckers()); |
|||
|
|||
if(actionRsp.getSuccess()){ |
|||
//更新表单流程数据
|
|||
EngineDataResult result = instanceService.transformInstanceDataResult(instance); |
|||
result.setUpdatorName(LoginHelper.getLoginUser().getNickname()); |
|||
param.getData().putAll(instanceService.getInstanceData(result)); |
|||
|
|||
UpdateDataParams item = new UpdateDataParams(param.getFormCode(), param.getDataId(),param.getData()); |
|||
item.setUser(LoginHelper.getLoginUser().getUserId(),LoginHelper.getLoginUser().getUsername(),LoginHelper.getLoginUser().getNickname()); |
|||
|
|||
formDataService.editFormData(item); |
|||
|
|||
return WorkflowResult.success(item.getData()); |
|||
} |
|||
|
|||
return WorkflowResult.error(actionRsp.getCode(),actionRsp.getMessage()); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 结束流程 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
@PostMapping("/instance/finish") |
|||
public WorkflowResponseData finish(@RequestBody UpdateDataParams param){ |
|||
if(ObjectUtil.hasEmpty(param.getDataId(),param.getData(),param.getFormId())){ |
|||
return WorkflowResult.error(WorkflowResultCode.PARAM_MISSING); |
|||
} |
|||
Instance instance = instanceService.getInstance(param.getDataId()); |
|||
|
|||
//结束流程
|
|||
BaseActionResult actionRsp = instanceService.finishInstance(instance); |
|||
|
|||
if(actionRsp.getSuccess()){ |
|||
//更新表单流程数据
|
|||
EngineDataResult result = new EngineDataResult(instance); |
|||
result.setUpdatorName(LoginHelper.getLoginUser().getNickname()); |
|||
param.getData().putAll(instanceService.getInstanceData(result)); |
|||
|
|||
UpdateDataParams item = new UpdateDataParams(param.getFormCode(), param.getDataId(),param.getData()); |
|||
item.setUser(LoginHelper.getLoginUser().getUserId(),LoginHelper.getLoginUser().getUsername(),LoginHelper.getLoginUser().getNickname()); |
|||
formDataService.editFormData(item); |
|||
|
|||
return WorkflowResult.success(item.getData()); |
|||
} |
|||
|
|||
return WorkflowResult.error(actionRsp.getCode(),actionRsp.getMessage()); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 激活流程 |
|||
* feat_00141最新 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
@PostMapping("/instance/active") |
|||
public WorkflowResponseData active(@RequestBody ActiveDataParams param){ |
|||
if(ObjectUtil.hasEmpty(param.getDataId(),param.getData(),param.getFormCode())){ |
|||
return WorkflowResult.error(WorkflowResultCode.PARAM_MISSING); |
|||
} |
|||
|
|||
Instance instance = instanceService.getInstance(param.getDataId()); |
|||
|
|||
//激活流程
|
|||
BaseActionResult actionRsp = instanceService.activeInstance(instance,param.getActiveNodeId(),param.getData()); |
|||
|
|||
if(actionRsp.getSuccess()){ |
|||
//更新表单流程数据
|
|||
EngineDataResult result = instanceService.transformInstanceDataResult(instance); |
|||
result.setUpdatorName(LoginHelper.getLoginUser().getNickname()); |
|||
param.getData().putAll(instanceService.getInstanceData(result)); |
|||
|
|||
UpdateDataParams item = new UpdateDataParams(param.getFormCode(), param.getDataId(),param.getData()); |
|||
item.setUser(LoginHelper.getLoginUser().getUserId(),LoginHelper.getLoginUser().getUsername(),LoginHelper.getLoginUser().getNickname()); |
|||
formDataService.editFormData(item); |
|||
|
|||
return WorkflowResult.success(item.getData()); |
|||
} |
|||
|
|||
return WorkflowResult.error(actionRsp.getCode(),actionRsp.getMessage()); |
|||
} |
|||
} |
@ -1,97 +0,0 @@ |
|||
package org.dromara.dataManager.domain; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.*; |
|||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; |
|||
import lombok.Data; |
|||
import org.dromara.common.entity.WorkflowBaseEntity; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
|
|||
/** |
|||
* 表单数据 |
|||
* |
|||
*/ |
|||
@Data |
|||
@TableName(value = "t_form_data", autoResultMap = true) |
|||
public class FormData extends WorkflowBaseEntity { |
|||
|
|||
/** |
|||
* 主键 |
|||
*/ |
|||
@TableId(value = "id", type = IdType.AUTO) |
|||
private Long id; |
|||
|
|||
|
|||
/** |
|||
* 表单id |
|||
*/ |
|||
@TableField("form_id") |
|||
private Long formId; |
|||
|
|||
|
|||
/** |
|||
* 提交数据 |
|||
*/ |
|||
@TableField(value = "form_data", typeHandler = JacksonTypeHandler.class) |
|||
private LinkedHashMap<String,Object> formData; |
|||
|
|||
|
|||
/** |
|||
* 流程实例id |
|||
*/ |
|||
@TableField("instance_id") |
|||
private Long instanceId; |
|||
|
|||
|
|||
/** |
|||
* 流程状态 |
|||
*/ |
|||
@TableField(value = "instance_stage",updateStrategy = FieldStrategy.IGNORED) |
|||
private String instanceStage; |
|||
|
|||
|
|||
/** |
|||
* 流程当前节点负责人 |
|||
*/ |
|||
@TableField(value = "instance_checker",updateStrategy = FieldStrategy.IGNORED ) |
|||
private String instanceChecker; |
|||
|
|||
|
|||
/** |
|||
* 流程实例节点信息 |
|||
*/ |
|||
@TableField(value = "instance_node",updateStrategy = FieldStrategy.IGNORED) |
|||
private String instanceNode; |
|||
|
|||
|
|||
/** |
|||
* 是否删除 |
|||
*/ |
|||
@TableField("deleted") |
|||
private Boolean deleted; |
|||
|
|||
|
|||
|
|||
/** |
|||
* 创建人账号 |
|||
*/ |
|||
@TableField("create_account") |
|||
private String createAccount; |
|||
|
|||
|
|||
|
|||
/** |
|||
* 创建人姓名 |
|||
*/ |
|||
@TableField("create_name") |
|||
private String createName; |
|||
|
|||
|
|||
/** |
|||
* 最近一次更新人姓名 |
|||
*/ |
|||
@TableField("update_user_name") |
|||
private String updateUserName; |
|||
|
|||
|
|||
} |
@ -1,174 +0,0 @@ |
|||
package org.dromara.dataManager.domain; |
|||
|
|||
import cn.hutool.core.map.MapUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.alibaba.fastjson.JSON; |
|||
import com.alibaba.fastjson.serializer.SerializerFeature; |
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import com.baomidou.mybatisplus.annotation.TableField; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.text.SimpleDateFormat; |
|||
import java.util.Date; |
|||
import java.util.Map; |
|||
import java.util.TimeZone; |
|||
|
|||
/** |
|||
* 表单数据日志 |
|||
*/ |
|||
@Data |
|||
@TableName(value = "t_form_data_log",autoResultMap = true) |
|||
public class FormDataLog implements Serializable { |
|||
private static final long serialVersionUID = 7522827670631635795L; |
|||
|
|||
@TableId(value = "id", type = IdType.AUTO) |
|||
private Long id; |
|||
|
|||
@TableField("form_id") |
|||
private Long formId; |
|||
|
|||
@TableField("form_code") |
|||
private String formCode; |
|||
|
|||
@TableField("data_id") |
|||
private Long dataId; |
|||
|
|||
@TableField("type") |
|||
private String type; |
|||
|
|||
@TableField("new_value") |
|||
private String newValue; |
|||
|
|||
@TableField("old_value") |
|||
private String oldValue; |
|||
|
|||
@TableField("create_id") |
|||
private Long createId; |
|||
|
|||
@TableField("create_account") |
|||
private String createAccount; |
|||
|
|||
@TableField("create_name") |
|||
private String createName; |
|||
|
|||
@TableField("add_time") |
|||
private Date addTime; |
|||
|
|||
@TableField("aft") |
|||
private String aft; |
|||
|
|||
@TableField("bef") |
|||
private String bef; |
|||
|
|||
@TableField("changes") |
|||
private String changes; |
|||
|
|||
@TableField("handled") |
|||
private boolean handled; |
|||
|
|||
public FormDataLog(){ |
|||
|
|||
} |
|||
|
|||
public FormDataLog(Long formId, String formCode){ |
|||
this.formId = formId; |
|||
this.formCode = formCode; |
|||
} |
|||
|
|||
public void fillData(String type,Long dataId,Map<String, Object> before, Map<String, Object> after){ |
|||
this.dataId = dataId; |
|||
this.type = type; |
|||
this.fillOldData(before); |
|||
this.fillNewData(after); |
|||
} |
|||
|
|||
public void fillOldData(Map<String, Object> before){ |
|||
if(MapUtil.isNotEmpty(before)){ |
|||
if(before.containsKey("createTime")){ |
|||
before.put("createTime",formatTime(before.get("createTime"))); |
|||
} |
|||
if(before.containsKey("updateTime")){ |
|||
before.put("updateTime", formatTime(before.get("updateTime"))); |
|||
} |
|||
this.bef = JSON.toJSONString(before, SerializerFeature.WriteMapNullValue); |
|||
} |
|||
} |
|||
|
|||
public void fillNewData(Map<String, Object> after){ |
|||
if(MapUtil.isNotEmpty(after)){ |
|||
if(after.containsKey("createTime")){ |
|||
after.put("createTime", formatTime(after.get("createTime"))); |
|||
} |
|||
if(after.containsKey("updateTime")){ |
|||
after.put("updateTime", formatTime(after.get("updateTime"))); |
|||
} |
|||
this.aft = JSON.toJSONString(after, SerializerFeature.WriteMapNullValue); |
|||
} |
|||
} |
|||
|
|||
|
|||
private String formatTime(Object timestamp) { |
|||
TimeZone timeZone = TimeZone.getTimeZone("GMT+0:00"); |
|||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); |
|||
simpleDateFormat.setTimeZone(timeZone); |
|||
|
|||
|
|||
if (timestamp instanceof Long) { |
|||
|
|||
String wrappedTime = simpleDateFormat.format(new Date((long)timestamp)); |
|||
if(StrUtil.isNotEmpty(wrappedTime)){ |
|||
|
|||
return StrUtil.replace(wrappedTime,"Z","+00:00"); |
|||
} |
|||
} |
|||
|
|||
if (timestamp instanceof Date) { |
|||
|
|||
return StrUtil.replace(simpleDateFormat.format((Date) timestamp),"Z","+00:00"); |
|||
} |
|||
|
|||
return timestamp+""; |
|||
} |
|||
|
|||
public void setUser(Long createId,String createName,String createAccount,Date createTime){ |
|||
if(ObjectUtil.hasEmpty(createId,createAccount)){ |
|||
this.createId = 0L; |
|||
this.createAccount = "system"; |
|||
this.createName = "系统"; |
|||
}else{ |
|||
this.createId = createId; |
|||
this.createName = createName; |
|||
this.createAccount = createAccount; |
|||
} |
|||
|
|||
this.addTime = createTime; |
|||
} |
|||
|
|||
|
|||
@Data |
|||
public static class UpdateWidgetResult { |
|||
|
|||
private String model; |
|||
|
|||
private String bef; |
|||
|
|||
private String aft; |
|||
|
|||
public UpdateWidgetResult(String model){ |
|||
this.model = model; |
|||
} |
|||
|
|||
public UpdateWidgetResult(String model,String bef,String aft){ |
|||
this.model = model; |
|||
this.bef = bef; |
|||
this.aft = aft; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
} |
@ -1,11 +0,0 @@ |
|||
package org.dromara.dataManager.domain; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class FormDataLogChange extends FormDataLog { |
|||
private static final long serialVersionUID = 1040326720258635873L; |
|||
|
|||
|
|||
private String userName; |
|||
} |
@ -1,51 +0,0 @@ |
|||
package org.dromara.dataManager.enums; |
|||
|
|||
import cn.hutool.core.util.StrUtil; |
|||
import lombok.Getter; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* @Description: 数据切面枚举 |
|||
**/ |
|||
@Getter |
|||
public enum DataAspectEnum { |
|||
|
|||
SAVE("save","save","表单提交"), |
|||
|
|||
IMPORT("import","save","导入"), |
|||
|
|||
UPDATE("update","update","数据编辑"), |
|||
|
|||
UPDATE_FIELD("updateField","update","批量编辑"), |
|||
|
|||
RECOVER("recover","recover","恢复数据"), |
|||
|
|||
DELETE("delete","delete","逻辑删除"), |
|||
|
|||
SHIFT_DELETE("shift_delete","delete","物理删除"), |
|||
|
|||
CLEAR("clear","delete","清空数据"); |
|||
|
|||
|
|||
private String code; |
|||
|
|||
private String group; |
|||
|
|||
private String name; |
|||
|
|||
|
|||
DataAspectEnum(String code, String group, String name){ |
|||
this.code = code; |
|||
this.group = group; |
|||
this.name = name; |
|||
} |
|||
|
|||
public static List<String> getGroupCode(String group){ |
|||
return Arrays.stream(values()).filter(p -> StrUtil.equals(group,p.getGroup())).map(DataAspectEnum::getCode).collect(Collectors.toList()); |
|||
} |
|||
|
|||
|
|||
} |
@ -1,51 +0,0 @@ |
|||
package org.dromara.dataManager.enums; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.Optional; |
|||
|
|||
public enum WidgetType { |
|||
|
|||
GENERAL("general"), |
|||
|
|||
CHECKBOX("checkbox"), |
|||
SWITCH("switch"), |
|||
EDITOR("editor"), |
|||
TEXT("text"), |
|||
LOCATION("location"), |
|||
SINGLE_MEMBER("singlemember"), |
|||
MULTIPLE_MEMBERS("multiplemembers"), |
|||
MULTIPLE_DEPARTMENTS("multiple_departments"), |
|||
SINGLE_DEPARTMENT("singledepartment"), |
|||
TABLE("table"), |
|||
IMG_UPLOAD("imgupload"), |
|||
FILE_UPLOAD("fileupload"), |
|||
DATA_LINK("datalink"), |
|||
UNIQ_KEY("uniqkey"), |
|||
FORMAT_NUMBER("format_number"), |
|||
INPUT("input"), |
|||
TEXTAREA("textarea"), |
|||
SELECT("select"), |
|||
DATE("date"), |
|||
COORDINATES("coordinates"), |
|||
PHONE("phone"), |
|||
RADIO("radio"), |
|||
MULTIPLE_SELECT("multiple_select"), |
|||
DIVIDER("divider"), |
|||
LINK_QUERY("link_query"); |
|||
|
|||
private String code; |
|||
|
|||
public String getCode() { |
|||
return code; |
|||
} |
|||
|
|||
WidgetType(String code) { |
|||
this.code = code; |
|||
} |
|||
|
|||
public static WidgetType getByCode(String code) { |
|||
Optional<WidgetType> optional = Arrays.stream(values()).filter(type -> type.getCode().equals(code)).findFirst(); |
|||
return optional.orElse(null); |
|||
} |
|||
|
|||
} |
@ -1,17 +0,0 @@ |
|||
package org.dromara.dataManager.mapper; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.domain.FormDataLogChange; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface FormDataLogChangeMapper extends BaseMapper<FormDataLog> { |
|||
|
|||
List<String> selectDocIds(); |
|||
|
|||
List<FormDataLogChange> selectLogs(@Param("docIds")List<String> docIds); |
|||
|
|||
void updateLogs(@Param("logs")List<FormDataLogChange> logs); |
|||
} |
@ -1,21 +0,0 @@ |
|||
package org.dromara.dataManager.mapper; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface FormDataLogMapper extends BaseMapper<FormDataLog> { |
|||
|
|||
List<FormDataLog> listDataLog(@Param("formId")Long formId,@Param("dataId")Long dataId); |
|||
|
|||
|
|||
boolean batchSaveDataLog(@Param("logList")List<FormDataLog> dataLogs); |
|||
|
|||
/** |
|||
* 批量删除 |
|||
* @param docIds |
|||
*/ |
|||
void deleteByDataIds(@Param("dataIds") String[] docIds); |
|||
} |
@ -1,18 +0,0 @@ |
|||
package org.dromara.dataManager.mapper; |
|||
|
|||
import org.dromara.dataManager.result.FormDataResult; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.dromara.dataManager.domain.FormData; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
|
|||
/** |
|||
* 表单数据 Mapper 接口 |
|||
* |
|||
*/ |
|||
public interface FormDataMapper extends BaseMapper<FormData> { |
|||
|
|||
Page<FormDataResult> pageFormData(@Param("page") Page page,@Param("ew") QueryWrapper queryWrapper); |
|||
} |
@ -1,31 +0,0 @@ |
|||
<?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="org.dromara.dataManager.mapper.FormDataLogChangeMapper"> |
|||
|
|||
<select id="selectDocIds" resultType="string"> |
|||
SELECT DISTINCT data_id FROM t_form_data_log |
|||
</select> |
|||
<select id="selectLogs" resultType="org.dromara.dataManager.domain.FormDataLogChange"> |
|||
select |
|||
a.*, b.name as userName |
|||
from |
|||
t_form_data_log a |
|||
left join |
|||
sys_user b |
|||
on |
|||
a.create_id = b.id |
|||
where |
|||
a.data_id in |
|||
<foreach collection="docIds" item="docId" open="(" separator="," close=")"> |
|||
#{docId} |
|||
</foreach> |
|||
order by a.add_time asc |
|||
</select> |
|||
|
|||
<update id="updateLogs"> |
|||
<foreach collection="logs" item="log"> |
|||
UPDATE t_form_data_log SET aft = #{log.aft}, bef = #{log.bef}, changes = #{log.changes}, handled = #{log.handled} WHERE id = #{log.id}; |
|||
</foreach> |
|||
</update> |
|||
|
|||
</mapper> |
@ -1,41 +0,0 @@ |
|||
<?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="org.dromara.dataManager.mapper.FormDataLogMapper"> |
|||
|
|||
<select id="listDataLog" resultType="org.dromara.dataManager.domain.FormDataLog"> |
|||
select t.type,t.aft as 'aft',t.bef as 'bef',t.data_id as 'dataId', |
|||
t.changes as 'changes',t.add_time as 'addTime', |
|||
t.create_id as 'createId',t.create_name as 'createName',t.create_account as 'createAccount' |
|||
from t_form_data_log t |
|||
where t.form_id = #{formId} and t.data_id = #{dataId} |
|||
order by t.add_time desc |
|||
</select> |
|||
|
|||
<insert id="batchSaveDataLog" parameterType="org.dromara.dataManager.domain.FormDataLog"> |
|||
INSERT INTO t_form_data_log |
|||
( |
|||
form_id, form_code,data_id,type,aft,bef,changes,create_id,create_name,create_account,add_time |
|||
) |
|||
VALUES |
|||
<foreach collection="logList" item="model" separator=","> |
|||
( |
|||
#{model.formId}, #{model.formCode}, |
|||
#{model.dataId}, #{model.type}, #{model.aft}, #{model.bef},#{model.changes}, |
|||
#{model.createId},#{model.createName},#{model.createAccount},#{model.addTime} |
|||
) |
|||
</foreach> |
|||
</insert> |
|||
|
|||
<!-- 批量删除 --> |
|||
<delete id="deleteByDataIds"> |
|||
DELETE FROM |
|||
t_form_data_log |
|||
WHERE |
|||
data_id IN |
|||
<foreach collection="dataIds" open="(" separator="," close=")" item="dataId"> |
|||
#{dataId} |
|||
</foreach> |
|||
</delete> |
|||
|
|||
|
|||
</mapper> |
@ -1,50 +0,0 @@ |
|||
<?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="org.dromara.dataManager.mapper.FormDataMapper"> |
|||
|
|||
|
|||
<!-- 通用查询映射结果 --> |
|||
<resultMap id="BaseResultMap" type="org.dromara.dataManager.result.FormDataResult"> |
|||
<id column="id" property="id" /> |
|||
<result column="formId" property="formId" /> |
|||
<result column="formData" property="formData" javaType="java.util.LinkedHashMap" |
|||
typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> |
|||
<result column="instanceId" property="instanceId" /> |
|||
<result column="stage" property="stage" /> |
|||
<result column="checkers" property="checkerName" /> |
|||
<result column="nodes" property="nodeTitle" /> |
|||
<result column="deleted" property="deleted" /> |
|||
<result column="createUser" property="createUser" /> |
|||
<result column="createName" property="createName" /> |
|||
<result column="createAccount" property="createAccount" /> |
|||
<result column="createTime" property="createTime" /> |
|||
<result column="updateUser" property="updateUser" /> |
|||
<result column="updateTime" property="updateTime" /> |
|||
<result column="updateName" property="updateName" /> |
|||
</resultMap> |
|||
|
|||
|
|||
<select id="pageFormData" resultMap="BaseResultMap"> |
|||
select |
|||
tfd.id, |
|||
tfd.form_id formId, |
|||
tfd.form_data formData, |
|||
tfd.instance_id instanceId, |
|||
tfd.instance_stage stage, |
|||
tfd.instance_checker checkers, |
|||
tfd.instance_node nodes, |
|||
tfd.deleted, |
|||
tfd.create_user createUser, |
|||
tfd.create_account createAccount, |
|||
tfd.create_time createTime, |
|||
tfd.create_name createName, |
|||
tfd.update_user updateUser, |
|||
tfd.update_time updateTime, |
|||
tfd.update_user_name updateName |
|||
from t_form_data tfd |
|||
${ew.customSqlSegment} |
|||
</select> |
|||
|
|||
|
|||
|
|||
</mapper> |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
|
|||
/** |
|||
* 激活实例 |
|||
*/ |
|||
@Data |
|||
public class ActiveDataParams extends UpdateDataParams { |
|||
/** |
|||
* 激活的节点 id |
|||
*/ |
|||
private String activeNodeId; |
|||
|
|||
|
|||
public ActiveDataParams(){} |
|||
public ActiveDataParams(String activeNodeId){ |
|||
this.activeNodeId = activeNodeId; |
|||
} |
|||
|
|||
public ActiveDataParams(String activeNodeId, String formCode, Long docId, LinkedHashMap<String, Object> data){ |
|||
super.setFormCode(formCode); |
|||
super.setDataId(docId); |
|||
super.setData(data); |
|||
this.activeNodeId = activeNodeId; |
|||
} |
|||
|
|||
} |
@ -1,109 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import lombok.Data; |
|||
import lombok.Getter; |
|||
import org.dromara.system.domain.SysDept; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数据传参 |
|||
*/ |
|||
@Data |
|||
public class DataParams implements Serializable { |
|||
private static final long serialVersionUID = 8682927139425739121L; |
|||
|
|||
/** |
|||
* 表单id |
|||
*/ |
|||
private Long formId; |
|||
|
|||
/** |
|||
* 表单code |
|||
*/ |
|||
private String formCode; |
|||
|
|||
/** |
|||
* 权限组group id |
|||
*/ |
|||
private Long permissionGroupId; |
|||
|
|||
|
|||
/** |
|||
* 操作用户信息 |
|||
*/ |
|||
private Long userId; |
|||
private String userAccount; |
|||
private String userName; |
|||
private List<Long> userDepartIds; |
|||
private List<Long> userGroupIds; |
|||
private List<SysDept> departs; |
|||
|
|||
|
|||
/** |
|||
* 操作时间 |
|||
*/ |
|||
private Date handleTime = new Date(); |
|||
|
|||
|
|||
/** |
|||
* 外链更新方式 data |
|||
*/ |
|||
private AccessType accessType; |
|||
|
|||
/** |
|||
* 外链更新token |
|||
*/ |
|||
private String accessToken; |
|||
|
|||
@Getter |
|||
public enum AccessType{ |
|||
form("form","表单"), |
|||
|
|||
data("data","数据"); |
|||
|
|||
private String type; |
|||
|
|||
private String name; |
|||
|
|||
AccessType(String type,String name){ |
|||
this.type = type; |
|||
this.name = name; |
|||
} |
|||
} |
|||
|
|||
public void setUser(Long userId, String userAccount, String userName, List<Long> departIds, List<Long> groupIds){ |
|||
this.userId = userId; |
|||
this.userAccount = userAccount; |
|||
this.userName = userName; |
|||
this.userDepartIds = departIds; |
|||
this.userGroupIds = groupIds; |
|||
} |
|||
public void setUser(Long userId, String userAccount, String userName, List<Long> departIds, List<Long> groupIds, List<SysDept> departs){ |
|||
this.userId = userId; |
|||
this.userAccount = userAccount; |
|||
this.userName = userName; |
|||
this.userDepartIds = departIds; |
|||
this.userGroupIds = groupIds; |
|||
this.departs = departs; |
|||
} |
|||
public void setUser(Long userId, String userAccount, String userName){ |
|||
this.userId = userId; |
|||
this.userAccount = userAccount; |
|||
this.userName = userName; |
|||
} |
|||
|
|||
public void setUser(DataParams dataParams){ |
|||
if(dataParams != null){ |
|||
this.userId = dataParams.getUserId(); |
|||
this.userAccount = dataParams.getUserAccount(); |
|||
this.userName = dataParams.getUserName(); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -1,33 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import jakarta.validation.constraints.NotNull; |
|||
import lombok.Data; |
|||
import org.dromara.common.param.WorkflowBaseParam; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数据导出 |
|||
*/ |
|||
@Data |
|||
public class DownloadDataParams extends DataParams { |
|||
|
|||
@NotNull(message = "表单代码不能为空", groups = WorkflowBaseParam.export.class) |
|||
private String formCode; |
|||
|
|||
@NotNull(message = "导出字段不能为空") |
|||
private List<String> exportFields; |
|||
|
|||
private Long permissionId; |
|||
|
|||
/** |
|||
* 是否导出ID |
|||
*/ |
|||
private boolean includeId = false; |
|||
|
|||
/** |
|||
* 导出文件名,如果为空则使用表单名称作为文件名 |
|||
*/ |
|||
private String exportName; |
|||
|
|||
} |
@ -1,71 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import org.dromara.dataManager.enums.DataAspectEnum; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 表单数据更新message |
|||
*/ |
|||
@Data |
|||
public class FormDataModifyMessage implements Serializable { |
|||
private static final long serialVersionUID = -1603895080729468809L; |
|||
|
|||
/** |
|||
* 数据操作 |
|||
*/ |
|||
private DataAspectEnum action; |
|||
|
|||
|
|||
|
|||
/** |
|||
* 表单id |
|||
*/ |
|||
private Long formId; |
|||
|
|||
/** |
|||
* 表单code |
|||
*/ |
|||
private String formCode; |
|||
|
|||
/** |
|||
* 操作时间 |
|||
*/ |
|||
private Date handleTime; |
|||
|
|||
/** |
|||
* 操作人id |
|||
*/ |
|||
private Long handleUserId; |
|||
|
|||
/** |
|||
* 操作人账号 |
|||
*/ |
|||
private String handleUserAccount; |
|||
|
|||
/** |
|||
* 操作人姓名 |
|||
*/ |
|||
private String handleUserName; |
|||
|
|||
|
|||
/** |
|||
* 修改前数据 |
|||
*/ |
|||
private List<Map<String, Object>> before = null; |
|||
|
|||
/** |
|||
* 修改后数据 |
|||
*/ |
|||
private List<Map<String, Object>> after; |
|||
|
|||
|
|||
/** |
|||
* 批量修改的表单字段 |
|||
*/ |
|||
private String updateWidget; |
|||
} |
@ -1,41 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import cn.hutool.json.JSONArray; |
|||
import jakarta.validation.constraints.NotNull; |
|||
import lombok.Data; |
|||
import org.dromara.common.param.WorkflowBaseParam; |
|||
import org.dromara.workflow.engine.enums.InstanceStage; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
|
|||
/** |
|||
* 表单数据 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class FormDataParam extends WorkflowBaseParam { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@NotNull(groups = {edit.class},message = "表单数据id不能为空") |
|||
private Long dataId; |
|||
|
|||
@NotNull(groups = {add.class},message = "表单id不能为空") |
|||
private Long formId; |
|||
|
|||
@NotNull(groups = {add.class},message = "表单数据不能为空") |
|||
private LinkedHashMap<String,Object> formData; |
|||
|
|||
private Long instanceId; |
|||
|
|||
private InstanceStage instanceStage; |
|||
|
|||
private JSONArray instanceChecker; |
|||
|
|||
private JSONArray instanceNode; |
|||
|
|||
private Integer deleted; |
|||
|
|||
private String app; |
|||
|
|||
} |
@ -1,36 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import org.dromara.dataManager.service.impt.enums.ImportMode; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
public class ImportDataParams extends DataParams { |
|||
private static final long serialVersionUID = 5013388461809737003L; |
|||
private Integer sheetIndex; |
|||
private String mapping; |
|||
private Map<Integer, String> objMapping; |
|||
private List<String> exportFields = new ArrayList<>(); |
|||
private ImportMode mode; |
|||
private String primaryKey; |
|||
private MultipartFile file; |
|||
private String validationConfigStr; |
|||
private ValidationConfig validationConfig; |
|||
|
|||
@Data |
|||
public static class ValidationConfig { |
|||
|
|||
private boolean required; |
|||
private boolean memberRequired; |
|||
private boolean departRequired; |
|||
private boolean optionRequired; |
|||
private boolean numberRequired; |
|||
private boolean dateRequired; |
|||
} |
|||
} |
@ -1,38 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 调整实例节点负责人 |
|||
*/ |
|||
@Data |
|||
public class TransferDataParams extends UpdateDataParams { |
|||
/** |
|||
* 调整实例节点id |
|||
*/ |
|||
private String transferNodeId; |
|||
|
|||
/** |
|||
* 调整节点负责人 |
|||
*/ |
|||
private List<Long> checkers; |
|||
|
|||
public TransferDataParams(){} |
|||
public TransferDataParams(String transferNodeId){ |
|||
this.transferNodeId = transferNodeId; |
|||
} |
|||
|
|||
public TransferDataParams(String transferNodeId, List<Long> checkers, |
|||
String formCode, Long dataId, |
|||
LinkedHashMap<String, Object> data){ |
|||
super.setFormCode(formCode); |
|||
super.setDataId(dataId); |
|||
super.setData(data); |
|||
this.transferNodeId = transferNodeId; |
|||
this.checkers = checkers; |
|||
} |
|||
|
|||
} |
@ -1,77 +0,0 @@ |
|||
package org.dromara.dataManager.param; |
|||
|
|||
import org.dromara.workflow.engine.enums.ESDefaultFieldConst; |
|||
import lombok.Data; |
|||
|
|||
import java.util.LinkedHashMap; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 更新表单数据 |
|||
*/ |
|||
@Data |
|||
public class UpdateDataParams extends DataParams { |
|||
/** |
|||
* 数据doc id |
|||
*/ |
|||
private Long dataId; |
|||
|
|||
/** |
|||
* 表单数据 |
|||
*/ |
|||
private LinkedHashMap<String, Object> data; |
|||
|
|||
/** |
|||
* 更新之前的表单数据 |
|||
*/ |
|||
private Map<String,Object> before; |
|||
|
|||
|
|||
public UpdateDataParams(){} |
|||
public UpdateDataParams(String formCode, Long docId, LinkedHashMap<String, Object> data){ |
|||
this.setFormCode(formCode); |
|||
this.dataId = docId; |
|||
this.data = data; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 转ES数据 |
|||
* @return |
|||
*/ |
|||
public LinkedHashMap<String, Object> convertESData(){ |
|||
if(data != null){ |
|||
data.remove(ESDefaultFieldConst.OWNER); |
|||
data.remove(ESDefaultFieldConst.CREATOR); |
|||
data.remove(ESDefaultFieldConst.CREATOR_ACCOUNT); |
|||
data.remove(ESDefaultFieldConst.CREATE_TIME); |
|||
data.remove(ESDefaultFieldConst.DID); |
|||
data.remove(ESDefaultFieldConst.DELETED); |
|||
|
|||
//设置更新时间
|
|||
data.put(ESDefaultFieldConst.UPDATE_TIME, this.getHandleTime()); |
|||
data.put(ESDefaultFieldConst.UPDATOR_NAME, this.getUserName()); |
|||
} |
|||
return data; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加ES基础字段 |
|||
* @return |
|||
*/ |
|||
public LinkedHashMap<String, Object> addESData(){ |
|||
if(data == null){ |
|||
data = new LinkedHashMap<String, Object>(); |
|||
} |
|||
data.put(ESDefaultFieldConst.OWNER, this.getUserId()); |
|||
data.put(ESDefaultFieldConst.CREATOR, this.getUserName()); |
|||
data.put(ESDefaultFieldConst.CREATOR_ACCOUNT, this.getUserAccount()); |
|||
data.put(ESDefaultFieldConst.CREATE_TIME, this.getHandleTime()); |
|||
data.put(ESDefaultFieldConst.UPDATE_TIME, this.getHandleTime()); |
|||
data.put(ESDefaultFieldConst.UPDATOR_NAME, this.getUserName()); |
|||
data.put(ESDefaultFieldConst.DID, this.getFormCode()); |
|||
data.put(ESDefaultFieldConst.DELETED, false); |
|||
return data; |
|||
} |
|||
} |
@ -1,55 +0,0 @@ |
|||
package org.dromara.dataManager.result; |
|||
|
|||
import cn.hutool.json.JSONArray; |
|||
import lombok.Data; |
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 表单数据 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class FormDataResult implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
|
|||
private Long id; |
|||
|
|||
private Long formId; |
|||
|
|||
private Map<String,Object> formData; |
|||
|
|||
private Long instanceId; |
|||
|
|||
private String stage; |
|||
|
|||
private String flowStage; |
|||
|
|||
private String checkerName; |
|||
|
|||
private String nodeTitle; |
|||
|
|||
private Integer deleted; |
|||
|
|||
private Long createUser; |
|||
|
|||
private Date createTime; |
|||
|
|||
private String createName; |
|||
|
|||
private String createAccount; |
|||
|
|||
private Long updateUser; |
|||
|
|||
private Date updateTime; |
|||
|
|||
private String updateName; |
|||
|
|||
private JSONArray nodes = new JSONArray(); |
|||
|
|||
private JSONArray checkers = new JSONArray(); |
|||
|
|||
} |
@ -1,87 +0,0 @@ |
|||
package org.dromara.dataManager.service; |
|||
|
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
import org.dromara.common.page.WorkflowPageResult; |
|||
import org.dromara.dataManager.param.UpdateDataParams; |
|||
import org.dromara.formMaking.results.FormSourceResult; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
import org.dromara.dataManager.domain.FormData; |
|||
import org.dromara.dataManager.param.FormDataParam; |
|||
|
|||
|
|||
/** |
|||
* 表单数据 服务类 |
|||
* |
|||
*/ |
|||
public interface FormDataService extends IService<FormData> { |
|||
|
|||
/** |
|||
* 分页 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
WorkflowPageResult<Map<String,Object>> pageFormData(FormDataParam param); |
|||
|
|||
/** |
|||
* 查询表单数据 |
|||
* @param dataId |
|||
* @return |
|||
*/ |
|||
FormData getFormData(Long dataId); |
|||
|
|||
/** |
|||
* 查询数据全部字段数据 |
|||
* @param dataId |
|||
* @return |
|||
*/ |
|||
Map<String,Object> getFormDataById(Long formId,Long dataId); |
|||
|
|||
/** |
|||
* 查询表单中指定的字段的数据 |
|||
* @param dataId |
|||
* @param includeFields |
|||
* @return |
|||
*/ |
|||
Map<String,Object> getFormDataById(Long formId,Long dataId,String [] includeFields); |
|||
|
|||
/** |
|||
* 查询指定的data |
|||
* @param dataIds |
|||
* @return |
|||
*/ |
|||
List<Map<String, Object>> list(Long formId, String[] dataIds); |
|||
|
|||
|
|||
/** |
|||
* 查询表单数据的完整信息 |
|||
* @param formId |
|||
* @param dataId |
|||
* @return |
|||
*/ |
|||
FormSourceResult getFormDataFullInfo(Long formId,Long dataId); |
|||
|
|||
/** |
|||
* 新增表单数据 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
FormData addFormData(FormDataParam param); |
|||
|
|||
/** |
|||
* 编辑表单数据 |
|||
* @param param |
|||
* @return |
|||
*/ |
|||
FormData editFormData(UpdateDataParams param); |
|||
|
|||
/** |
|||
* 删除表单数据 |
|||
* @param id |
|||
* @return |
|||
*/ |
|||
boolean deleteFormData(Long id); |
|||
|
|||
} |
@ -1,278 +0,0 @@ |
|||
package org.dromara.dataManager.service.impl; |
|||
|
|||
|
|||
import org.dromara.common.satoken.utils.LoginHelper; |
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.consts.ExceptionCodeConstant; |
|||
import org.dromara.common.page.WorkflowPageFactory; |
|||
import org.dromara.common.page.WorkflowPageResult; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.dataManager.param.UpdateDataParams; |
|||
import org.dromara.dataManager.result.FormDataResult; |
|||
import org.dromara.formMaking.domain.FormSource; |
|||
import org.dromara.formMaking.results.FormSourceResult; |
|||
import org.dromara.formMaking.service.FormSourceService; |
|||
import org.dromara.taskCenter.param.TaskFlowParam; |
|||
import org.dromara.taskCenter.param.TaskUpdateParam; |
|||
import org.dromara.taskCenter.service.action.impl.CreateHandler; |
|||
import org.dromara.workflow.engine.enums.InstanceStage; |
|||
import org.dromara.workflow.engine.enums.OperateType; |
|||
import org.dromara.workflow.param.model.FlowUser; |
|||
import org.dromara.workflow.result.engine.ActionNodeSubmitResult; |
|||
import org.dromara.workflow.result.engine.EngineDataResult; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.BeanUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import org.dromara.dataManager.domain.FormData; |
|||
import org.dromara.dataManager.mapper.FormDataMapper; |
|||
import org.dromara.dataManager.param.FormDataParam; |
|||
import org.dromara.dataManager.service.FormDataService; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
/** |
|||
* 表单数据实现层 |
|||
* |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class FormDataServiceImpl extends ServiceImpl<FormDataMapper, FormData> implements FormDataService { |
|||
|
|||
@Autowired |
|||
private CreateHandler actionService; |
|||
@Autowired |
|||
private FormSourceService formSourceService; |
|||
|
|||
|
|||
@Override |
|||
public WorkflowPageResult<Map<String,Object>> pageFormData(FormDataParam param) { |
|||
if (ObjectUtil.isEmpty(param.getFormId())){ |
|||
throw new ServiceException(ExceptionCodeConstant.Service.VALUE_INVALID,"参数[formId]不能为空"); |
|||
} |
|||
|
|||
Page<FormDataResult> pageFormData = this.baseMapper.pageFormData(WorkflowPageFactory.defaultPage(),generateWrapper(param)); |
|||
List<Map<String,Object>> formDataList = new ArrayList<>(); |
|||
pageFormData.getRecords().forEach(p->{ |
|||
if(p.getInstanceId() != null){ |
|||
p.getFormData().put("nodeTitle",p.getNodeTitle()); |
|||
p.getFormData().put("checkerName",p.getCheckerName()); |
|||
p.getFormData().put("flowStage",p.getStage()); |
|||
} |
|||
p.getFormData().put("createName",p.getCreateName()); |
|||
p.getFormData().put("createTime",p.getCreateTime()); |
|||
p.getFormData().put("updateName",p.getUpdateName()); |
|||
p.getFormData().put("updateTime",p.getUpdateTime()); |
|||
p.getFormData().put("instanceId",p.getInstanceId()); |
|||
p.getFormData().put("dataId",p.getId()); |
|||
formDataList.add(p.getFormData()); |
|||
}); |
|||
|
|||
return new WorkflowPageResult<>(pageFormData,formDataList); |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public FormData getFormData(Long dataId) { |
|||
return this.baseMapper.selectById(dataId); |
|||
} |
|||
|
|||
@Override |
|||
public Map<String, Object> getFormDataById(Long formId,Long dataId) { |
|||
if (ObjectUtil.isEmpty(formId)){ |
|||
throw new ServiceException(ExceptionCodeConstant.Service.VALUE_INVALID,"参数[formId]不能为空"); |
|||
} |
|||
|
|||
if (ObjectUtil.isEmpty(dataId)){ |
|||
throw new ServiceException(ExceptionCodeConstant.Service.VALUE_INVALID,"参数[dataId]不能为空"); |
|||
} |
|||
|
|||
List<FormData> formDataList = this.getFormDataByFormId(formId); |
|||
|
|||
List<FormData> dataList = formDataList.stream().filter(p -> p.getId().equals(dataId)).collect(Collectors.toList()); |
|||
|
|||
if (CollUtil.isNotEmpty(dataList)){ |
|||
FormData formData = dataList.stream().findFirst().get(); |
|||
LinkedHashMap<String, Object> data = formData.getFormData(); |
|||
data.put("instanceId",formData.getInstanceId()); |
|||
data.put("instanceStage",formData.getInstanceStage()); |
|||
data.put("instanceChecker",formData.getInstanceChecker()); |
|||
data.put("instanceNode",formData.getInstanceNode()); |
|||
data.put("dataId",dataId); |
|||
return data; |
|||
} |
|||
|
|||
return new HashMap<>(); |
|||
} |
|||
|
|||
@Override |
|||
public Map<String, Object> getFormDataById(Long formId,Long dataId, String[] includeFields) { |
|||
Map<String, Object> formDataMap = this.getFormDataById(formId, dataId); |
|||
|
|||
Map<String,Object> resultMap = new HashMap<>(); |
|||
|
|||
if (ObjectUtil.isEmpty(formDataMap)){ |
|||
return resultMap; |
|||
} |
|||
|
|||
List<String> keyList = formDataMap.keySet().stream().filter(key -> Arrays.asList(includeFields).contains(key)).collect(Collectors.toList()); |
|||
|
|||
keyList.forEach(key ->{ |
|||
resultMap.put(key,formDataMap.get(key)); |
|||
}); |
|||
|
|||
return resultMap; |
|||
} |
|||
|
|||
@Override |
|||
public List<Map<String, Object>> list(Long formId, String[] dataIds) { |
|||
List<Map<String, Object>> resultList = new ArrayList<>(); |
|||
|
|||
List<FormData> formDataList = this.getFormDataByFormId(formId); |
|||
|
|||
if (CollUtil.isEmpty(formDataList)){ |
|||
return resultList; |
|||
} |
|||
|
|||
List<FormData> resultFormData = formDataList.stream(). |
|||
filter(formData -> Arrays.asList(dataIds).contains(String.valueOf(formData.getId()))).collect(Collectors.toList()); |
|||
|
|||
resultFormData.forEach(formData -> { |
|||
LinkedHashMap<String, Object> data = formData.getFormData(); |
|||
data.put("instanceId",formData.getInstanceId()); |
|||
data.put("instanceStage",formData.getInstanceStage()); |
|||
data.put("instanceChecker",formData.getInstanceChecker()); |
|||
data.put("instanceNode",formData.getInstanceNode()); |
|||
data.put("dataId",formData.getId()); |
|||
resultList.add(data); |
|||
}); |
|||
|
|||
return resultList; |
|||
} |
|||
|
|||
@Override |
|||
public FormSourceResult getFormDataFullInfo(Long formId,Long dataId) { |
|||
FormSourceResult formSourceResult =formSourceService.getFormSourceById(formId); |
|||
if (ObjectUtil.isEmpty(formSourceResult)){ |
|||
|
|||
throw new ServiceException(WorkflowResultCode.FORM_NOT_EXIST); |
|||
} |
|||
formSourceResult.setFormData(this.getFormDataById(formSourceResult.getId(), dataId)); |
|||
|
|||
return formSourceResult; |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public FormData addFormData(FormDataParam param) { |
|||
FormData item = new FormData(); |
|||
BeanUtils.copyProperties(param,item); |
|||
item.setFormData(param.getFormData()); |
|||
item.setDeleted(false); |
|||
item.setCreateAccount(LoginHelper.getUsername()); |
|||
item.setCreateName(LoginHelper.getLoginUser().getNickname()); |
|||
this.save(item); |
|||
|
|||
//应用表单提交 + 表单启用流程 => 触发流程引擎
|
|||
FormSource formSource = formSourceService.getFormSource(param.getFormId()); |
|||
TaskFlowParam wfParam = new TaskFlowParam( |
|||
new TaskUpdateParam(OperateType.create, formSource, item.getId(),false,item.getFormData(),item.getCreateTime()), |
|||
new FlowUser(LoginHelper.getUserId(), |
|||
LoginHelper.getLoginUser().getNickname(), |
|||
LoginHelper.getUsername(), |
|||
Arrays.asList(LoginHelper.getDeptId())) |
|||
); |
|||
|
|||
ActionNodeSubmitResult flowRsp = actionService.action(wfParam); |
|||
if(!flowRsp.getSuccess() || flowRsp.getData() == null){ |
|||
throw new ServiceException(flowRsp.getCode(),flowRsp.getMessage()); |
|||
} |
|||
|
|||
EngineDataResult flowData = flowRsp.getData(); |
|||
Long instanceId = flowData.getInstanceId(); |
|||
item.setInstanceId(instanceId); |
|||
item.setInstanceStage(flowData.getFlowStage()); |
|||
if(InstanceStage.processing.name().equals(flowData.getFlowStage())){ |
|||
item.setInstanceNode(flowData.getNodeTitle()); |
|||
item.setInstanceChecker(flowData.getCheckerName()); |
|||
}else{ |
|||
item.setInstanceNode("结束节点"); |
|||
item.setInstanceChecker(""); |
|||
} |
|||
this.updateById(item); |
|||
|
|||
return item; |
|||
} |
|||
|
|||
@Override |
|||
public FormData editFormData(UpdateDataParams param) { |
|||
FormData item = this.queryItem(param.getDataId()); |
|||
item.setFormData(param.getData()); |
|||
if(param.getData().containsKey("instanceStage")){ |
|||
item.setInstanceStage((String) param.getData().get("instanceStage")); |
|||
} |
|||
if(param.getData().containsKey("instanceChecker")){ |
|||
item.setInstanceChecker((String) param.getData().get("instanceChecker")); |
|||
} |
|||
if(param.getData().containsKey("instanceNode")){ |
|||
item.setInstanceNode((String) param.getData().get("instanceNode")); |
|||
} |
|||
|
|||
this.baseMapper.updateById(item); |
|||
|
|||
|
|||
|
|||
return item; |
|||
} |
|||
|
|||
@Override |
|||
public boolean deleteFormData(Long id) { |
|||
|
|||
return this.baseMapper.deleteById(id) > 0; |
|||
} |
|||
|
|||
private QueryWrapper<FormData> generateWrapper(FormDataParam param){ |
|||
QueryWrapper<FormData> wrapper = new QueryWrapper<>(); |
|||
|
|||
if (ObjectUtil.isNotEmpty(param.getFormId())){ |
|||
wrapper.eq("tfd.form_id",param.getFormId()); |
|||
} |
|||
|
|||
if (StringUtils.isNotEmpty(param.getStartTime()) && StringUtils.isNotEmpty(param.getEndTime())){ |
|||
wrapper.ge("tfd.create_time",param.getStartTime() + " 00:00:00"); |
|||
wrapper.le("tfd.create_time",param.getEndTime() + " 23:59:59"); |
|||
} |
|||
|
|||
wrapper.orderByDesc("tfd.update_time","tfd.create_time"); |
|||
|
|||
return wrapper; |
|||
} |
|||
|
|||
private FormData queryItem(Long id) { |
|||
FormData item = this.getById(id); |
|||
if (ObjectUtil.isNull(item)) { |
|||
throw new ServiceException(4004,"未找到表单数据"); |
|||
} |
|||
return item; |
|||
} |
|||
|
|||
private List<FormData> getFormDataByFormId(Long formId) { |
|||
if (ObjectUtil.isEmpty(formId)){ |
|||
throw new ServiceException(ExceptionCodeConstant.Service.VALUE_INVALID,"参数[formId]不能为空"); |
|||
} |
|||
|
|||
LambdaQueryWrapper<FormData> wrapper = new LambdaQueryWrapper<>(); |
|||
wrapper.eq(FormData::getFormId,formId); |
|||
return this.baseMapper.selectList(wrapper); |
|||
} |
|||
} |
@ -1,60 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.common; |
|||
|
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; |
|||
|
|||
import java.util.*; |
|||
|
|||
public class HeaderMergeStrategiesGenerator { |
|||
|
|||
public static List<OnceAbsoluteMergeStrategy> generate(List<FormWidget> formColumns, List<String> exportFields) { |
|||
List<OnceAbsoluteMergeStrategy> strategyList = new ArrayList<>(); |
|||
if (formColumns == null) { |
|||
return strategyList; |
|||
} |
|||
|
|||
Map<String, FormWidget> tableColumnsMap = new HashMap<>(); |
|||
List<String> allColumns = new ArrayList<>(); |
|||
|
|||
|
|||
if (exportFields == null) { |
|||
exportFields = allColumns; |
|||
} |
|||
|
|||
List<String> finalExportFields = exportFields; |
|||
formColumns.stream().filter(col -> finalExportFields.contains(col.getModel())).forEach(col -> { |
|||
if (CollectionUtil.isNotEmpty(col.getTableColumns())) { |
|||
|
|||
tableColumnsMap.put(col.getModel(), col); |
|||
} |
|||
allColumns.add(col.getModel()); |
|||
}); |
|||
|
|||
if (tableColumnsMap.size() <= 0) { |
|||
return strategyList; |
|||
} |
|||
|
|||
int colIndex = 0; |
|||
Set<String> tableColumns = tableColumnsMap.keySet(); |
|||
|
|||
for (String field : exportFields) { |
|||
if (tableColumns.contains(field)) { |
|||
int colSpan = tableColumnsMap.get(field).getTableColumns().size(); |
|||
|
|||
if (colSpan == 1) { |
|||
colIndex++; |
|||
continue; |
|||
} |
|||
|
|||
strategyList.add(new OnceAbsoluteMergeStrategy(0, 0, colIndex, colIndex + colSpan - 1)); |
|||
colIndex += colSpan; |
|||
} else { |
|||
strategyList.add(new OnceAbsoluteMergeStrategy(0, 1, colIndex, colIndex)); |
|||
colIndex++; |
|||
} |
|||
} |
|||
|
|||
return strategyList; |
|||
} |
|||
} |
@ -1,22 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.system.domain.SysDept; |
|||
import org.dromara.system.domain.SysUser; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import lombok.Data; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public abstract class BaseConverter { |
|||
private FormWidget formWidget; |
|||
|
|||
private Map<String, SysUser> accountUserMapping = new HashMap<>(); |
|||
|
|||
private Map<String, SysDept> pathDepartMapping = new HashMap<>(); |
|||
|
|||
public Object convert(String value) { |
|||
return null; |
|||
}; |
|||
} |
@ -1,14 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
public class BooleanConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
if ("是".equals(value)) { |
|||
return true; |
|||
} else if ("否".equals(value)){ |
|||
return false; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -1,11 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
public class CheckboxConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
return value.split(","); |
|||
} |
|||
} |
@ -1,13 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.dataManager.service.impt.model.StringConverter; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
|
|||
public class ConverterBuilder { |
|||
public static WidgetConverter getConverter(String type, WidgetModel widgetModel){ |
|||
|
|||
WidgetConverter converter = new StringConverter(widgetModel); |
|||
return converter; |
|||
} |
|||
|
|||
} |
@ -1,20 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
|
|||
import cn.hutool.json.JSONObject; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
public class CoordinateConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (StringUtils.isNotBlank(value)) { |
|||
JSONObject coordinate = new JSONObject(); |
|||
coordinate.set("address", value); |
|||
coordinate.set("geopoint", null); |
|||
return coordinate; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -1,70 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
|
|||
import com.alibaba.excel.util.DateUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
import java.text.ParseException; |
|||
import java.util.Date; |
|||
|
|||
@Slf4j |
|||
public class DateConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (StringUtils.isNotBlank(value)) { |
|||
try { |
|||
String format = (String) getFormWidget().getOptions().get("format"); |
|||
// 使用规定格式转换数据
|
|||
return DateUtils.parseDate(value, format); |
|||
} catch (Exception e) { |
|||
try { |
|||
// 如果转换报错,则尝试自动转换数据
|
|||
return DateUtils.parseDate(value); |
|||
} catch (Exception parseException) { |
|||
// 自动识别格式失败则尝试自动识别常用格式
|
|||
return convert2Date(value); |
|||
} |
|||
} |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
private Date convert2Date(String dateString) { |
|||
|
|||
// 自动识别格式失败则尝试自动识别常用格式
|
|||
String separator = null; |
|||
|
|||
if (dateString.contains("-")) { |
|||
separator = "-"; |
|||
|
|||
} else if (dateString.contains("/")) { |
|||
separator = "/"; |
|||
|
|||
} |
|||
|
|||
if (separator != null) { |
|||
String ymd = String.format("yyyy%sMM%sdd", separator, separator); |
|||
String[] formats = new String[]{String.format("%s HH:mm:ss", ymd), String.format("%s HH:mm", ymd), String.format("%s HH", ymd), ymd}; |
|||
|
|||
Date result = null; |
|||
|
|||
for (String format: formats) { |
|||
try { |
|||
result = DateUtils.parseDate(dateString, format); |
|||
break; |
|||
} catch (ParseException parseException) { |
|||
log.error(String.format("转换为%s格式日期失败", format)); |
|||
} |
|||
} |
|||
|
|||
if (result != null) { |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
@ -1,10 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import java.util.ArrayList; |
|||
|
|||
public class EmptyArrayValueConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
return new ArrayList<>(); |
|||
} |
|||
} |
@ -1,68 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.math.RoundingMode; |
|||
import java.text.DecimalFormat; |
|||
|
|||
public class FormatNumberConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
|
|||
String numberWithoutSymbols = value.replaceAll(",", "").replaceAll("%", ""); |
|||
|
|||
// 将字符串转为数字
|
|||
BigDecimal number = new BigDecimal(numberWithoutSymbols); |
|||
|
|||
try { |
|||
|
|||
// 开启小数位数
|
|||
boolean isFloatChecked = (boolean) getFormWidget().getOptions().get("isFloatChecked"); |
|||
// 小数位数
|
|||
int numberDigit = getFormWidget().getOptions().get("numberDigit") == null ? 0 : (int) getFormWidget().getOptions().get("numberDigit"); |
|||
|
|||
DecimalFormat df; |
|||
|
|||
// 开启了保留小数位
|
|||
if (isFloatChecked) { |
|||
|
|||
if (numberDigit > 0 ) { |
|||
|
|||
StringBuilder digitPattern = new StringBuilder(); |
|||
|
|||
for (int index = 0; index < numberDigit; index++) { |
|||
digitPattern.append("#"); |
|||
} |
|||
|
|||
df = new DecimalFormat("#." + digitPattern); |
|||
} else { |
|||
df = new DecimalFormat("#"); |
|||
} |
|||
|
|||
// 如果是百分比字符串,再除以100
|
|||
if (value.contains("%")) { |
|||
number = number.divide(new BigDecimal(100), RoundingMode.HALF_UP); |
|||
} |
|||
|
|||
} |
|||
// 没开启保留小数位,则最多保留6位
|
|||
else { |
|||
df = new DecimalFormat("###.######"); |
|||
// 如果是百分比字符串,再除以100
|
|||
if (value.contains("%")) { |
|||
number = number.divide(new BigDecimal(100), RoundingMode.HALF_UP); |
|||
} |
|||
} |
|||
df.setRoundingMode(RoundingMode.HALF_UP); |
|||
number = new BigDecimal(df.format(number)); |
|||
|
|||
} catch (Exception e) { |
|||
number = null; |
|||
} |
|||
|
|||
return number == null ? null : number.doubleValue(); |
|||
} |
|||
} |
@ -1,8 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
public class GeneralConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
return value; |
|||
} |
|||
} |
@ -1,34 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
public class InputConverter extends BaseConverter { |
|||
|
|||
private static final List<String> NUMBER_TYPES = Arrays.asList("number", "integer", "float"); |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
|
|||
Map<String, Object> options = getFormWidget().getOptions(); |
|||
String dataType = (String) options.get("dataType"); |
|||
|
|||
if (NUMBER_TYPES.contains(dataType)) { |
|||
try { |
|||
if ("integer".equals(dataType)) { |
|||
return Double.valueOf(value).intValue(); |
|||
} else { |
|||
return Float.valueOf(value); |
|||
} |
|||
} catch (Exception e) { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
@ -1,38 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class LocationConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return getDefaultValue(); |
|||
} |
|||
String[] location = value.split(",", -1); |
|||
Map<String, String> result = new HashMap<>(); |
|||
if (location.length > 0) { |
|||
result.put("province", location[0]); |
|||
} |
|||
if (location.length > 1) { |
|||
result.put("city", location[1]); |
|||
} |
|||
if (location.length > 2) { |
|||
result.put("area", location[2]); |
|||
} |
|||
if (location.length > 3) { |
|||
result.put("address", String.join(",", Arrays.asList(location).subList(3, location.length))); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
private Map<String, String> getDefaultValue() { |
|||
Map<String, String> location = new HashMap<>(); |
|||
location.put("province", null); |
|||
location.put("city", null); |
|||
location.put("area", null); |
|||
location.put("address", null); |
|||
return location; |
|||
} |
|||
} |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.system.domain.SysDept; |
|||
|
|||
import java.util.*; |
|||
|
|||
public class MultipleDepartmentsConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
List<Map<String, Object>> infoList = new ArrayList<>(); |
|||
|
|||
if (value == null) { |
|||
return infoList; |
|||
} |
|||
|
|||
String[] pathList = value.split(","); |
|||
Arrays.stream(pathList).forEach(path -> { |
|||
SysDept org = getPathDepartMapping().get(path); |
|||
Map<String, Object> info = new HashMap<>(); |
|||
info.put("key", String.valueOf(org.getDeptId())); |
|||
info.put("title", org.getDeptName()); |
|||
info.put("code", org.getDeptId()); |
|||
// info.put("path", org.getNamePath());
|
|||
infoList.add(info); |
|||
}); |
|||
|
|||
return infoList; |
|||
} |
|||
} |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
|
|||
import org.dromara.system.domain.SysUser; |
|||
|
|||
import java.util.*; |
|||
|
|||
public class MultipleMemberConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
List<Map<String, Object>> infoList = new ArrayList<>(); |
|||
|
|||
if (value == null) { |
|||
return infoList; |
|||
} |
|||
|
|||
String[] accounts = value.split(","); |
|||
Arrays.stream(accounts).forEach(account -> { |
|||
SysUser user = getAccountUserMapping().get(account); |
|||
Map<String, Object> info = new HashMap<>(); |
|||
info.put("key", String.valueOf(user.getUserId())); |
|||
info.put("title", user.getNickName()); |
|||
info.put("code", user.getUserName()); |
|||
infoList.add(info); |
|||
}); |
|||
|
|||
return infoList; |
|||
} |
|||
} |
@ -1,11 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
public class MultipleSelectConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
return value.split(","); |
|||
} |
|||
} |
@ -1,8 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
public class NullValueConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
return null; |
|||
} |
|||
} |
@ -1,17 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class PhoneConverter extends BaseConverter { |
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
Map<String, Object> result = new HashMap<>(); |
|||
result.put("phoneNumber", value); |
|||
result.put("status", 0); |
|||
return result; |
|||
} |
|||
} |
@ -1,28 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.system.domain.SysDept; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class SingleDepartmentConverter extends BaseConverter { |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
|
|||
SysDept sysDepartment = getPathDepartMapping().get(value); |
|||
if (sysDepartment != null) { |
|||
Map<String, Object> info = new HashMap<>(); |
|||
info.put("key", String.valueOf(sysDepartment.getDeptId())); |
|||
info.put("title", sysDepartment.getDeptName()); |
|||
info.put("code", sysDepartment.getDeptId()); |
|||
// info.put("path", sysDepartment.getNamePath());
|
|||
return info; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
|
|||
import org.dromara.system.domain.SysUser; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class SingleMemberConverter extends BaseConverter { |
|||
|
|||
public SingleMemberConverter() { |
|||
} |
|||
|
|||
@Override |
|||
public Object convert(String value) { |
|||
if (value == null) { |
|||
return null; |
|||
} |
|||
SysUser sysUser = getAccountUserMapping().get(value); |
|||
if (sysUser != null) { |
|||
Map<String, Object> info = new HashMap<>(); |
|||
info.put("key", String.valueOf(sysUser.getUserId())); |
|||
info.put("title", sysUser.getNickName()); |
|||
info.put("code", sysUser.getUserName()); |
|||
// info.put("type", UserDepartDataTypeEnum.USER.getCode());
|
|||
return info; |
|||
} |
|||
return null; |
|||
} |
|||
} |
@ -1,69 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 表单字段值转换 |
|||
*/ |
|||
@Data |
|||
public abstract class WidgetConverter { |
|||
protected static final String BLANK_MESSAGE = "'%s'字段不能为空值"; |
|||
protected static final String IS_NOT_NUMBER = "'%s'不是数字"; |
|||
protected static final String IS_NOT_DATE = "'%s'不是日期"; |
|||
protected static final String IS_NOT_SYSTEM_ACCOUNT = "'%s'不是系统内的账号"; |
|||
protected static final String IS_NOT_SYSTEM_DEPARTMENT = "'%s'不是系统内的部门"; |
|||
protected static final String IS_NOT_VALID_OPTION = "'%s'不是合法的选项"; |
|||
protected WidgetModel widget; |
|||
private ImportDataParams.ValidationConfig validationConfig; |
|||
|
|||
public WidgetConverter() { |
|||
} |
|||
|
|||
public WidgetConverter(WidgetModel widget){ |
|||
this.widget = widget; |
|||
} |
|||
|
|||
public void validate(String value, ConvertCallBack callback){ |
|||
if (isRequiredButEmpty(value)) { |
|||
callback.fail(String.format(BLANK_MESSAGE, this.widget.getName())); |
|||
return; |
|||
} |
|||
callback.success(this.valueOf(value)); |
|||
} |
|||
|
|||
public Object valueOf(String value){ |
|||
return value; |
|||
} |
|||
|
|||
/** |
|||
* 是否必填但是数据为空 |
|||
* @param value |
|||
* @return |
|||
*/ |
|||
protected boolean isRequiredButEmpty(Object value) { |
|||
if (!validationConfig.isRequired()) { |
|||
return false; |
|||
} |
|||
boolean required = this.widget.getOptions().getBool("required", false); |
|||
return required && ObjectUtil.isEmpty(value); |
|||
} |
|||
|
|||
/** |
|||
* 回调接口 |
|||
*/ |
|||
public interface ConvertCallBack{ |
|||
/** |
|||
* 转换成功 |
|||
* @param convertValue |
|||
*/ |
|||
void success(Object convertValue); |
|||
/** |
|||
* 转换失败 |
|||
* @param message |
|||
*/ |
|||
void fail(String message); |
|||
} |
|||
} |
@ -1,75 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.convert; |
|||
|
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.springframework.boot.CommandLineRunner; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Component |
|||
public class WidgetConverterFactory implements CommandLineRunner { |
|||
|
|||
private static final Map<WidgetType, BaseConverter> converterMap = new HashMap<>(); |
|||
|
|||
public static BaseConverter getConverter(String type) { |
|||
WidgetType widgetType = WidgetType.getByCode(type); |
|||
|
|||
if (widgetType == null) { |
|||
widgetType = WidgetType.GENERAL; |
|||
} |
|||
|
|||
BaseConverter baseConverter; |
|||
|
|||
switch (widgetType) { |
|||
case SWITCH: baseConverter = new BooleanConverter();break; |
|||
case DATE: baseConverter = new DateConverter();break; |
|||
case CHECKBOX: baseConverter = new CheckboxConverter();break; |
|||
case MULTIPLE_SELECT: baseConverter = new MultipleSelectConverter();break; |
|||
case IMG_UPLOAD: |
|||
case FILE_UPLOAD: |
|||
case UNIQ_KEY: |
|||
case DATA_LINK: |
|||
baseConverter = new NullValueConverter();break; |
|||
case SINGLE_MEMBER: baseConverter = new SingleMemberConverter();break; |
|||
case SINGLE_DEPARTMENT: baseConverter = new SingleDepartmentConverter();break; |
|||
case MULTIPLE_MEMBERS: baseConverter = new MultipleMemberConverter();break; |
|||
case LOCATION: baseConverter = new LocationConverter();break; |
|||
// case INPUT: baseConverter = new InputConverter();break;
|
|||
case PHONE: baseConverter = new PhoneConverter();break; |
|||
|
|||
case MULTIPLE_DEPARTMENTS: baseConverter = new MultipleDepartmentsConverter();break; |
|||
|
|||
case FORMAT_NUMBER: baseConverter = new FormatNumberConverter();break; |
|||
case COORDINATES: baseConverter = new CoordinateConverter();break; |
|||
default:baseConverter = new GeneralConverter(); |
|||
} |
|||
|
|||
return baseConverter; |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void run(String... args) throws Exception { |
|||
converterMap.put(WidgetType.GENERAL, new GeneralConverter()); |
|||
converterMap.put(WidgetType.SWITCH, new BooleanConverter()); |
|||
converterMap.put(WidgetType.DATE, new DateConverter()); |
|||
converterMap.put(WidgetType.CHECKBOX, new CheckboxConverter()); |
|||
converterMap.put(WidgetType.IMG_UPLOAD, new EmptyArrayValueConverter()); |
|||
converterMap.put(WidgetType.FILE_UPLOAD, new EmptyArrayValueConverter()); |
|||
converterMap.put(WidgetType.UNIQ_KEY, new NullValueConverter()); |
|||
converterMap.put(WidgetType.DATA_LINK, new NullValueConverter()); |
|||
converterMap.put(WidgetType.SINGLE_MEMBER, new SingleMemberConverter()); |
|||
converterMap.put(WidgetType.SINGLE_DEPARTMENT, new SingleDepartmentConverter()); |
|||
converterMap.put(WidgetType.MULTIPLE_MEMBERS, new MultipleMemberConverter()); |
|||
converterMap.put(WidgetType.LOCATION, new LocationConverter()); |
|||
converterMap.put(WidgetType.INPUT, new InputConverter()); |
|||
converterMap.put(WidgetType.PHONE, new PhoneConverter()); |
|||
|
|||
converterMap.put(WidgetType.MULTIPLE_DEPARTMENTS, new MultipleDepartmentsConverter()); |
|||
|
|||
converterMap.put(WidgetType.FORMAT_NUMBER, new FormatNumberConverter()); |
|||
converterMap.put(WidgetType.COORDINATES, new CoordinateConverter()); |
|||
converterMap.put(WidgetType.MULTIPLE_SELECT, new MultipleSelectConverter()); |
|||
} |
|||
} |
@ -1,17 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.enums; |
|||
|
|||
public enum ImportMode { |
|||
CREATE("create"), |
|||
UPDATE("update"), |
|||
CREATE_AND_UPDATE("createAndUpdate"); |
|||
|
|||
private final String mode; |
|||
|
|||
public String getMode() { |
|||
return mode; |
|||
} |
|||
|
|||
ImportMode(String mode) { |
|||
this.mode = mode; |
|||
} |
|||
} |
@ -1,15 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.exception; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class ImportDataInvalidException extends Exception{ |
|||
private List<String> invalidRows; |
|||
|
|||
public ImportDataInvalidException(String message, List<String> invalidRows) { |
|||
super(message); |
|||
this.invalidRows = invalidRows; |
|||
} |
|||
} |
@ -1,14 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.exception; |
|||
|
|||
import org.dromara.dataManager.service.impt.model.InvalidColumnResult; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class ImportValidationException extends Exception{ |
|||
private InvalidColumnResult result; |
|||
|
|||
public ImportValidationException(String message, InvalidColumnResult result) { |
|||
super(message); |
|||
this.result = result; |
|||
} |
|||
} |
@ -1,11 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class CellSpanInfo { |
|||
private int rowIndex; |
|||
private int columnIndex; |
|||
private int colSpan; |
|||
private int rowSpan; |
|||
} |
@ -1,44 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.util.BooleanUtil; |
|||
import lombok.Data; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class ColumnsNeedValidate { |
|||
private List<FormWidget> requiredWidgets = new ArrayList<>(); |
|||
private List<FormWidget> dateWidgets = new ArrayList<>(); |
|||
private List<FormWidget> numberWidgets = new ArrayList<>(); |
|||
|
|||
private List<FormWidget> memberWidgets = new ArrayList<>(); |
|||
private List<FormWidget> departWidgets = new ArrayList<>(); |
|||
|
|||
private List<FormWidget> widgets; |
|||
|
|||
public ColumnsNeedValidate(List<FormWidget> widgets) { |
|||
this.widgets = widgets; |
|||
analyse(); |
|||
} |
|||
|
|||
private void analyse() { |
|||
|
|||
widgets.forEach(w -> { |
|||
|
|||
Object requiredObj = w.getOptions().get("required"); |
|||
if (requiredObj != null && BooleanUtil.isTrue((Boolean) requiredObj)) { |
|||
requiredWidgets.add(w); |
|||
} |
|||
if (WidgetType.DATE.getCode().equals(w.getType())) { |
|||
dateWidgets.add(w); |
|||
} |
|||
if (WidgetType.FORMAT_NUMBER.getCode().equals(w.getType())) { |
|||
numberWidgets.add(w); |
|||
} |
|||
|
|||
}); |
|||
} |
|||
} |
@ -1,19 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public class DataAnalysisParams { |
|||
private Long formId; |
|||
private String formCode; |
|||
private int headerNumber; |
|||
private String primaryKey; |
|||
private List<WidgetModel> formWidgets; |
|||
private Map<Integer, String> mappings; |
|||
private ImportDataParams.ValidationConfig validationConfig; |
|||
} |
@ -1,11 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class DownloadTemplateParams { |
|||
private List<String> exportFields = new ArrayList<>(); |
|||
} |
@ -1,40 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import com.alibaba.excel.context.AnalysisContext; |
|||
import com.alibaba.excel.enums.CellExtraTypeEnum; |
|||
import com.alibaba.excel.event.AnalysisEventListener; |
|||
import com.alibaba.excel.metadata.CellExtra; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
public class ExtraMergeInfoListener extends AnalysisEventListener<Map<Integer, String>> { |
|||
|
|||
private final List<CellExtra> extraMergeInfoList = new ArrayList<>(); |
|||
private int rowCount = 0; |
|||
|
|||
@Override |
|||
public void invoke(Map<Integer, String> data, AnalysisContext analysisContext) { |
|||
rowCount += 1; |
|||
} |
|||
|
|||
@Override |
|||
public void doAfterAllAnalysed(AnalysisContext analysisContext) { |
|||
} |
|||
|
|||
@Override |
|||
public void extra(CellExtra extra, AnalysisContext context) { |
|||
if (CellExtraTypeEnum.MERGE.equals(extra.getType())) { |
|||
extraMergeInfoList.add(extra); |
|||
} |
|||
} |
|||
|
|||
public List<CellExtra> getExtraMergeInfoList() { |
|||
return extraMergeInfoList; |
|||
} |
|||
|
|||
public int getRowCount() { |
|||
return rowCount; |
|||
} |
|||
} |
@ -1,384 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.dataManager.service.impt.validator.ValueValidator; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.alibaba.excel.context.AnalysisContext; |
|||
import com.alibaba.excel.event.AnalysisEventListener; |
|||
import com.alibaba.excel.metadata.CellExtra; |
|||
|
|||
import java.util.*; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class ImportValidatorListener extends AnalysisEventListener<Map<Integer, Object>> { |
|||
private static final int BATCH_COUNT = 2000; |
|||
private static final List<String> NOT_IMPORTABLE_TYPES = Arrays.asList(WidgetType.FILE_UPLOAD.getCode(), WidgetType.IMG_UPLOAD.getCode()); |
|||
|
|||
private final List<CellExtra> extraMergeInfoList; |
|||
private final Map<Integer, String> mapping; |
|||
private final Map<String, FormWidget> widgetMap; |
|||
private final int headRows; |
|||
|
|||
private List<Map<String, Object>> list = new ArrayList<>(); |
|||
private final InvalidColumnResult invalidColumnResult = new InvalidColumnResult(); |
|||
|
|||
// 子表单外的必填、日期、数字字段
|
|||
private ColumnsNeedValidate widgetsOutOfTable2Validate; |
|||
// 子表单及其内的必填、日期、数字字段
|
|||
private final Map<String, ColumnsNeedValidate> widgetsInTable2Validate = new HashMap<>(); |
|||
// 用于标记字段的校验状态,初始都是true
|
|||
Map<String, Boolean> columnValidMap = new HashMap<>(); |
|||
|
|||
// 成员字段及其值的集合
|
|||
Map<String, Set<String>> memberValueMap = new HashMap<>(); |
|||
// 部门字段及其值的集合
|
|||
Map<String, Set<String>> departValueMap = new HashMap<>(); |
|||
|
|||
public ImportValidatorListener(List<CellExtra> extraMergeInfoList, Map<Integer, String> mapping, Map<String, FormWidget> widgetMap, int headRows) { |
|||
this.extraMergeInfoList = extraMergeInfoList; |
|||
this.mapping = mapping; |
|||
this.widgetMap = widgetMap; |
|||
this.headRows = headRows; |
|||
} |
|||
|
|||
@Override |
|||
public void invoke(Map<Integer, Object> data, AnalysisContext analysisContext) { |
|||
Map<String, Object> row = new HashMap<>(); |
|||
mapping.forEach((colIndex, model) -> row.put(model, data.get(colIndex))); |
|||
list.add(row); |
|||
} |
|||
|
|||
@Override |
|||
public void doAfterAllAnalysed(AnalysisContext analysisContext) { |
|||
generateWidgetsNeedValidate(); |
|||
initValidateWidgetsStatus(); |
|||
mergeRowAndValidate(); |
|||
} |
|||
|
|||
public boolean hasInvalidData() { |
|||
return columnValidMap.containsValue(false); |
|||
} |
|||
|
|||
public InvalidColumnResult getValidationResult() { |
|||
return invalidColumnResult; |
|||
} |
|||
|
|||
private Map<String, List<String>> getTableColumns() { |
|||
Map<String, List<String>> tableColumns = new HashMap<>(); |
|||
|
|||
widgetMap.forEach((model, widget) -> { |
|||
if (WidgetType.TABLE.getCode().equals(widget.getType())) { |
|||
tableColumns.put(model, widget.getTableColumns().stream().map(FormWidget::getModel).collect(Collectors.toList())); |
|||
} |
|||
}); |
|||
|
|||
return tableColumns; |
|||
} |
|||
|
|||
private void mergeRowAndValidate() { |
|||
Map<String, List<String>> tableColumns = getTableColumns(); |
|||
Set<String> tableColumnNames = new HashSet<>(); |
|||
tableColumns.forEach((tc, columns) -> tableColumnNames.addAll(columns)); |
|||
|
|||
List<Map<String, Object>> dataSave2ES = new ArrayList<>(); |
|||
|
|||
if (CollectionUtil.isNotEmpty(tableColumns)) { |
|||
// 有子表单字段,需要处理合并单元格的数据后再导入
|
|||
|
|||
AtomicInteger rowIndex = new AtomicInteger(); |
|||
while (rowIndex.get() < list.size()) { |
|||
|
|||
Map<String, Object> thisRow = list.get(rowIndex.get()); |
|||
Map<String, Object> newRow = new HashMap<>(); |
|||
|
|||
// 被合并行数,也是距离下一条数据的行数
|
|||
AtomicInteger mostMergeRows = new AtomicInteger(1); |
|||
|
|||
thisRow.forEach((field, value) -> { |
|||
// 子表单字段
|
|||
if (tableColumnNames.contains(field)) { |
|||
|
|||
// 查找这行是否有纵向合并单元格
|
|||
Optional<CellExtra> optional = extraMergeInfoList.stream().filter(info -> info.getFirstRowIndex().equals(rowIndex.get() + headRows) && info.getLastRowIndex() - info.getFirstRowIndex() > 0).findFirst(); |
|||
// 有多条数据
|
|||
if (optional.isPresent()) { |
|||
|
|||
mostMergeRows.set(optional.get().getLastRowIndex() - optional.get().getFirstRowIndex() + 1); |
|||
|
|||
// 遍历子表单字段,并收集子表单字段的数据
|
|||
tableColumns.forEach((table, columns) -> { |
|||
List<Map<String, Object>> tableData = new ArrayList<>(); |
|||
for (int index = 0; index < mostMergeRows.get(); index++) { |
|||
Map<String, Object> rowData = new HashMap<>(); |
|||
int finalIndex = index; |
|||
columns.forEach(colName -> { |
|||
rowData.put(colName, list.get(rowIndex.get() + finalIndex).get(colName)); |
|||
}); |
|||
|
|||
tableData.add(rowData); |
|||
} |
|||
|
|||
newRow.put(table, tableData); |
|||
}); |
|||
|
|||
} |
|||
// 只有一条数据
|
|||
else { |
|||
// 遍历子表单字段,并收集子表单字段的数据
|
|||
tableColumns.forEach((table, columns) -> { |
|||
List<Map<String, Object>> tableData = new ArrayList<>(); |
|||
|
|||
Map<String, Object> rowData = new HashMap<>(); |
|||
columns.forEach(colName -> { |
|||
rowData.put(colName, thisRow.get(colName)); |
|||
}); |
|||
tableData.add(rowData); |
|||
|
|||
newRow.put(table, tableData); |
|||
}); |
|||
} |
|||
} |
|||
// 非子表单字段
|
|||
else { |
|||
newRow.put(field, value); |
|||
} |
|||
|
|||
}); |
|||
|
|||
// 数据索引往后移
|
|||
rowIndex.addAndGet(mostMergeRows.get()); |
|||
|
|||
dataSave2ES.add(newRow); |
|||
|
|||
// 批量保存,以免内存中存在大量临时数据
|
|||
if (dataSave2ES.size() >= BATCH_COUNT) { |
|||
validate(dataSave2ES, null); |
|||
// validateMemberDepart();
|
|||
// 清空,使其被GC
|
|||
dataSave2ES.clear(); |
|||
} |
|||
// 如果所有需要校验的字段都不合法,那就终止,没必要后续数据的校验了
|
|||
if (validationFinished()) { |
|||
break; |
|||
} |
|||
} |
|||
|
|||
} else { |
|||
// 没有子表单字段,无需处理合并单元格的数据,直接导入
|
|||
dataSave2ES = list; |
|||
} |
|||
|
|||
validate(dataSave2ES, null); |
|||
// validateMemberDepart();
|
|||
|
|||
} |
|||
|
|||
private void generateWidgetsNeedValidate() { |
|||
// 归类子表单外的必填、日期、数字字段, 且已有不合法数据的字段就不再校验了
|
|||
List<FormWidget> notTableWidgets = widgetMap.values().stream() |
|||
.filter(widget -> !WidgetType.TABLE.getCode().equals(widget.getType())) |
|||
.collect(Collectors.toList()); |
|||
widgetsOutOfTable2Validate = new ColumnsNeedValidate(notTableWidgets); |
|||
|
|||
// 归类子表单内的必填、日期、数字字段
|
|||
widgetMap.values().stream().filter(widget -> WidgetType.TABLE.getCode().equals(widget.getType())).forEach(widget -> { |
|||
// 重命名子表单内的字段
|
|||
ColumnsNeedValidate cnv = new ColumnsNeedValidate(widget.getTableColumns().stream() |
|||
.filter(tc -> !NOT_IMPORTABLE_TYPES.contains(tc.getType()) && mapping.containsValue(tc.getModel())) |
|||
.peek(tc -> tc.setName(String.format("%s.%s", widget.getName(), tc.getName()))) |
|||
.collect(Collectors.toList())); |
|||
widgetsInTable2Validate.put(widget.getModel(), cnv); |
|||
}); |
|||
|
|||
// 初始化
|
|||
widgetMap.values().forEach(widget -> { |
|||
if (WidgetType.SINGLE_MEMBER.getCode().equals(widget.getType()) || WidgetType.MULTIPLE_MEMBERS.getCode().equals(widget.getType())) { |
|||
memberValueMap.put(widget.getModel(), new HashSet<>()); |
|||
widgetsOutOfTable2Validate.getMemberWidgets().add(widget); |
|||
|
|||
} else if (WidgetType.SINGLE_DEPARTMENT.getCode().equals(widget.getType()) || WidgetType.MULTIPLE_DEPARTMENTS.getCode().equals(widget.getType())) { |
|||
departValueMap.put(widget.getModel(), new HashSet<>()); |
|||
widgetsOutOfTable2Validate.getDepartWidgets().add(widget); |
|||
|
|||
} else if (WidgetType.TABLE.getCode().equals(widget.getType())) { |
|||
widget.getTableColumns().forEach(tc -> { |
|||
if (WidgetType.SINGLE_MEMBER.getCode().equals(tc.getType()) || WidgetType.MULTIPLE_MEMBERS.getCode().equals(tc.getType())) { |
|||
memberValueMap.put(tc.getModel(), new HashSet<>()); |
|||
widgetsInTable2Validate.get(widget.getModel()).getMemberWidgets().add(tc); |
|||
|
|||
} else if (WidgetType.SINGLE_DEPARTMENT.getCode().equals(tc.getType()) || WidgetType.MULTIPLE_DEPARTMENTS.getCode().equals(tc.getType())) { |
|||
departValueMap.put(tc.getModel(), new HashSet<>()); |
|||
widgetsInTable2Validate.get(widget.getModel()).getDepartWidgets().add(tc); |
|||
|
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
private void initValidateWidgetsStatus() { |
|||
|
|||
widgetsOutOfTable2Validate.getRequiredWidgets().forEach(widget -> columnValidMap.put(widget.getModel(), true)); |
|||
widgetsOutOfTable2Validate.getDateWidgets().forEach(widget -> columnValidMap.put(widget.getModel(), true)); |
|||
widgetsOutOfTable2Validate.getNumberWidgets().forEach(widget -> columnValidMap.put(widget.getModel(), true)); |
|||
|
|||
widgetsInTable2Validate.forEach((table, cnv) -> { |
|||
cnv.getRequiredWidgets().forEach(tc -> columnValidMap.put(tc.getModel(), true)); |
|||
cnv.getDateWidgets().forEach(tc -> columnValidMap.put(tc.getModel(), true)); |
|||
cnv.getNumberWidgets().forEach(tc -> columnValidMap.put(tc.getModel(), true)); |
|||
}); |
|||
|
|||
memberValueMap.keySet().forEach(member -> columnValidMap.put(member, true)); |
|||
departValueMap.keySet().forEach(depart -> columnValidMap.put(depart, true)); |
|||
|
|||
} |
|||
|
|||
private void validate(List<Map<String, Object>> dataSave2ES, ColumnsNeedValidate cnv) { |
|||
|
|||
Set<String> tableFields = widgetsInTable2Validate.keySet(); |
|||
|
|||
for (Map<String, Object> row: dataSave2ES) { |
|||
// 如果所有需要校验的字段都不合法,那就终止,没必要后续数据的校验了
|
|||
if (validationFinished()) { |
|||
break; |
|||
} |
|||
row.forEach((fieldName, fieldValue) -> { |
|||
|
|||
if (tableFields.contains(fieldName)) { |
|||
|
|||
if (fieldValue != null) { |
|||
|
|||
ColumnsNeedValidate tableCnv = widgetsInTable2Validate.get(fieldName); |
|||
|
|||
List<Map<String, Object>> tableData = (List<Map<String, Object>>) fieldValue; |
|||
|
|||
validate(tableData, tableCnv); |
|||
} |
|||
|
|||
|
|||
} else { |
|||
|
|||
ColumnsNeedValidate workingCnv = cnv == null ? widgetsOutOfTable2Validate : cnv; |
|||
|
|||
validateFieldValue(fieldName, fieldValue, workingCnv); |
|||
} |
|||
|
|||
|
|||
}); |
|||
|
|||
} |
|||
} |
|||
|
|||
private void validateFieldValue(String fieldName, Object fieldValue, ColumnsNeedValidate cnv) { |
|||
|
|||
List<FormWidget> requiredWidgets = cnv.getRequiredWidgets().stream().filter(w -> columnValidMap.get(w.getModel())).collect(Collectors.toList()); |
|||
List<FormWidget> dateWidgets = cnv.getDateWidgets().stream().filter(w -> columnValidMap.get(w.getModel())).collect(Collectors.toList()); |
|||
List<FormWidget> numberWidgets = cnv.getNumberWidgets().stream().filter(w -> columnValidMap.get(w.getModel())).collect(Collectors.toList()); |
|||
|
|||
List<FormWidget> memberWidgets = cnv.getMemberWidgets().stream().filter(w -> columnValidMap.get(w.getModel())).collect(Collectors.toList()); |
|||
List<FormWidget> departWidgets = cnv.getDepartWidgets().stream().filter(w -> columnValidMap.get(w.getModel())).collect(Collectors.toList()); |
|||
|
|||
List<String> requiredModels = requiredWidgets.stream().map(FormWidget::getModel).collect(Collectors.toList()); |
|||
List<String> dateModels = dateWidgets.stream().map(FormWidget::getModel).collect(Collectors.toList()); |
|||
List<String> numberModels = numberWidgets.stream().map(FormWidget::getModel).collect(Collectors.toList()); |
|||
|
|||
List<String> memberModels = memberWidgets.stream().map(FormWidget::getModel).collect(Collectors.toList()); |
|||
List<String> departModels = departWidgets.stream().map(FormWidget::getModel).collect(Collectors.toList()); |
|||
|
|||
|
|||
if (requiredModels.contains(fieldName) && ValueValidator.isEmpty(fieldValue)) { |
|||
|
|||
Optional<FormWidget> optional = requiredWidgets.stream().filter(w -> w.getModel().equals(fieldName)).findFirst(); |
|||
String name = optional.isPresent() ? optional.get().getName() : ""; |
|||
invalidColumnResult.add(fieldName, String.format("导入「%s」字段的值存在空值数据", name)); |
|||
|
|||
columnValidMap.put(fieldName, false); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (dateModels.contains(fieldName) && !ValueValidator.isEmpty(fieldValue) && !ValueValidator.isDate(fieldValue, widgetMap.get(fieldName))) { |
|||
|
|||
Optional<FormWidget> optional = dateWidgets.stream().filter(w -> w.getModel().equals(fieldName)).findFirst(); |
|||
String name = optional.isPresent() ? optional.get().getName() : ""; |
|||
invalidColumnResult.add(fieldName, String.format("导入「%s」字段的值存在不是日期的数据,请检查格式,错误数据:%s", name, fieldValue)); |
|||
|
|||
columnValidMap.put(fieldName, false); |
|||
|
|||
return; |
|||
|
|||
} |
|||
|
|||
if (numberModels.contains(fieldName) && !ValueValidator.isEmpty(fieldValue) && !ValueValidator.isNumber(fieldValue)) { |
|||
|
|||
Optional<FormWidget> optional = numberWidgets.stream().filter(w -> w.getModel().equals(fieldName)).findFirst(); |
|||
String name = optional.isPresent() ? optional.get().getName() : ""; |
|||
invalidColumnResult.add(fieldName, String.format("导入「%s」字段的值存在不是数字的数据,错误数据:%s", name, fieldValue)); |
|||
|
|||
columnValidMap.put(fieldName, false); |
|||
|
|||
} |
|||
|
|||
if (memberModels.contains(fieldName) && columnValidMap.get(fieldName)) { |
|||
|
|||
if (ObjectUtil.isNotEmpty(fieldValue)) { |
|||
memberValueMap.get(fieldName).addAll(Arrays.asList(fieldValue.toString().split(","))); |
|||
} |
|||
|
|||
} |
|||
|
|||
if (departModels.contains(fieldName) && columnValidMap.get(fieldName)) { |
|||
|
|||
if (ObjectUtil.isNotEmpty(fieldValue)) { |
|||
departValueMap.get(fieldName).addAll(Arrays.asList(fieldValue.toString().split(","))); |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
// private void validateMemberDepart() {
|
|||
// // 校验账号合法性
|
|||
// Set<String> mAccounts = new HashSet<>();
|
|||
// memberValueMap.keySet().stream().filter(key -> columnValidMap.get(key)).forEach(member -> {
|
|||
// mAccounts.addAll(memberValueMap.get(member));
|
|||
// });
|
|||
//
|
|||
// Map<String, SysUser> aNameMapping = SpringUtil.getBean(ISysUserService.class).getAccountNameMapping(mAccounts);
|
|||
// Set<String> validAccounts = aNameMapping.keySet();
|
|||
// memberValueMap.keySet().stream().filter(key -> columnValidMap.get(key)).forEach(member -> {
|
|||
//
|
|||
// List<String> iva = memberValueMap.get(member).stream().filter(acc -> !validAccounts.contains(acc)).collect(Collectors.toList());
|
|||
//
|
|||
// if (CollectionUtil.isNotEmpty(iva)) {
|
|||
// columnValidMap.put(member, false);
|
|||
// invalidColumnResult.add(member, String.format("导入数据中存在非系统内用户的账号,非法账号:%s", String.join(", ", iva)));
|
|||
// }
|
|||
// });
|
|||
//
|
|||
// // 校验部门路径合法性
|
|||
// Set<String> dPaths = new HashSet<>();
|
|||
// departValueMap.keySet().stream().filter(key -> columnValidMap.get(key)).forEach(depart -> {
|
|||
// dPaths.addAll(departValueMap.get(depart));
|
|||
// });
|
|||
// Map<String, SysDepartment> pDMapping = SpringUtil.getBean(DepartmentService.class).getPathDepartMapping(dPaths);
|
|||
// Set<String> validPaths = pDMapping.keySet();
|
|||
//
|
|||
// departValueMap.keySet().stream().filter(key -> columnValidMap.get(key)).forEach(depart -> {
|
|||
// List<String> ivp = departValueMap.get(depart).stream().filter(dp -> !validPaths.contains(dp)).collect(Collectors.toList());
|
|||
// if (CollectionUtil.isNotEmpty(ivp)) {
|
|||
// columnValidMap.put(depart, false);
|
|||
// invalidColumnResult.add(depart, String.format("导入数据中存在非系统内的部门路径,非法部门路径:%s", String.join(", ", ivp)));
|
|||
// }
|
|||
// });
|
|||
// }
|
|||
|
|||
private boolean validationFinished() { |
|||
// 如果所有需要校验的字段都不合法,那就终止,没必要后续数据的校验了
|
|||
return !columnValidMap.containsValue(true); |
|||
} |
|||
|
|||
} |
@ -1,27 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class InvalidColumnResult { |
|||
|
|||
private List<InvalidColumn> invalidColumns = new ArrayList<>(); |
|||
|
|||
public void add(String column, String message) { |
|||
invalidColumns.add(new InvalidColumn(column, message)); |
|||
} |
|||
|
|||
@Data |
|||
public static class InvalidColumn { |
|||
private String column; |
|||
private String message; |
|||
|
|||
public InvalidColumn(String column, String message) { |
|||
this.column = column; |
|||
this.message = message; |
|||
} |
|||
} |
|||
} |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class PreviewResult { |
|||
private List<PreviewTableHeader> headers; |
|||
private List<Object> data; |
|||
private List<String> sheets; |
|||
private String sheetName; |
|||
private List<CellSpanInfo> spanInfoList; |
|||
|
|||
public PreviewResult() { |
|||
} |
|||
|
|||
public PreviewResult(List<PreviewTableHeader> headers, List<Object> data, List<String> sheets) { |
|||
this.headers = headers; |
|||
this.data = data; |
|||
this.sheets = sheets; |
|||
} |
|||
|
|||
public PreviewResult(List<PreviewTableHeader> headers, List<Object> data, List<String> sheets, String sheetName) { |
|||
this.headers = headers; |
|||
this.data = data; |
|||
this.sheets = sheets; |
|||
this.sheetName = sheetName; |
|||
} |
|||
} |
@ -1,18 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import cn.hutool.core.util.StrUtil; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class PreviewTableHeader { |
|||
private String title; |
|||
private List<PreviewTableHeader> children; |
|||
private int columnIndex; |
|||
|
|||
public PreviewTableHeader(String title, int columnIndex) { |
|||
this.title = StrUtil.isBlank(title) ? "" : title; |
|||
this.columnIndex = columnIndex; |
|||
} |
|||
} |
@ -1,19 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.model; |
|||
|
|||
import org.dromara.dataManager.service.impt.convert.WidgetConverter; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
|
|||
/** |
|||
* 单行文本 |
|||
*/ |
|||
public class StringConverter extends WidgetConverter { |
|||
|
|||
public StringConverter(WidgetModel widget) { |
|||
super(widget); |
|||
} |
|||
|
|||
@Override |
|||
public Object valueOf(String value) { |
|||
return value == null ? null : value.replaceAll("\n", ""); |
|||
} |
|||
} |
@ -1,116 +0,0 @@ |
|||
//package org.dromara.dataManager.service.impt.service;
|
|||
//
|
|||
//import cn.hutool.core.collection.CollUtil;
|
|||
//import cn.hutool.core.collection.CollectionUtil;
|
|||
//import cn.hutool.json.JSONArray;
|
|||
//import cn.hutool.json.JSONObject;
|
|||
//import cn.hutool.json.JSONUtil;
|
|||
//import org.apache.commons.lang3.StringUtils;
|
|||
//import org.elasticsearch.action.search.SearchRequest;
|
|||
//import org.elasticsearch.index.query.QueryBuilders;
|
|||
//import org.elasticsearch.search.builder.SearchSourceBuilder;
|
|||
//import org.elasticsearch.search.sort.SortOrder;
|
|||
//import org.springframework.stereotype.Component;
|
|||
//
|
|||
//import java.io.IOException;
|
|||
//import java.util.List;
|
|||
//import java.util.Map;
|
|||
//
|
|||
//@Component
|
|||
//public class ImportFromExcelHelper {
|
|||
//
|
|||
// // @Autowired
|
|||
// // private ElasticsearchClient elasticsearchClient;
|
|||
//
|
|||
// public List<String> getNotExistIds(String index, String query, List<String> ids) throws IOException {
|
|||
// if(CollUtil.isNotEmpty(ids)){
|
|||
// return ids;
|
|||
// }
|
|||
// SearchRequest searchRequest = new SearchRequest(index);
|
|||
//
|
|||
// SearchSourceBuilder sb = SearchSourceBuilder.searchSource();
|
|||
//
|
|||
// JSONObject queryObj;
|
|||
// if (StringUtils.isNotBlank(query)) {
|
|||
// queryObj = JSONUtil.parseObj(query);
|
|||
// } else {
|
|||
// queryObj = new JSONObject();
|
|||
// }
|
|||
//
|
|||
// if (CollectionUtil.isNotEmpty(ids)) {
|
|||
// queryObj.getByPath("query.bool.must", JSONArray.class).add(JSONUtil.parseObj(QueryBuilders.idsQuery().addIds(ids.toArray(new String[0])).toString()));
|
|||
// }
|
|||
//
|
|||
// JSONObject query4Req = new JSONObject();
|
|||
// query4Req.putOpt("bool", queryObj.getByPath("query.bool"));
|
|||
// if (queryObj.get("query.filter") != null && !queryObj.getByPath("query.filter", JSONObject.class).isEmpty()) {
|
|||
// query4Req.putOpt("filter", queryObj.getByPath("query.filter"));
|
|||
// }
|
|||
//
|
|||
// sb.query(QueryBuilders.wrapperQuery(query4Req.toString()));
|
|||
// sb.fetchSource(new String[]{"_id"}, new String[]{});
|
|||
// // 最大只能处理3万条数据
|
|||
// sb.size(Math.min(ids.size(), 30000));
|
|||
//
|
|||
// searchRequest.source(sb);
|
|||
//
|
|||
// // try (final RestHighLevelClient client = elasticsearchClient.getHighClient()) {
|
|||
// //
|
|||
// // SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
|
|||
// //
|
|||
// // List<String> existedIds = Arrays.stream(response.getHits().getHits())
|
|||
// // .map(SearchHit::getId)
|
|||
// // .collect(Collectors.toList());
|
|||
// //
|
|||
// // return ids.stream().filter(id -> !existedIds.contains(id)).collect(Collectors.toList());
|
|||
// //
|
|||
// // }
|
|||
// return ids;
|
|||
// }
|
|||
//
|
|||
// public Map<String, String> getPKValueMapping(String index, String query, String pk, List<String> pkValues) throws IOException {
|
|||
//
|
|||
// SearchRequest searchRequest = new SearchRequest(index);
|
|||
//
|
|||
// SearchSourceBuilder sb = SearchSourceBuilder.searchSource();
|
|||
// sb.fetchSource(new String[]{pk}, new String[]{});
|
|||
// sb.sort("createTime", SortOrder.ASC);
|
|||
// // 最多处理3万条
|
|||
// sb.size(30000);
|
|||
//
|
|||
// JSONObject queryObj;
|
|||
// if (StringUtils.isNotBlank(query)) {
|
|||
// queryObj = JSONUtil.parseObj(query);
|
|||
// } else {
|
|||
// queryObj = new JSONObject();
|
|||
// }
|
|||
//
|
|||
// if (CollectionUtil.isNotEmpty(pkValues)) {
|
|||
// queryObj.getByPath("query.bool.must", JSONArray.class).add(JSONUtil.parseObj(QueryBuilders.termsQuery(pk, pkValues).toString()));
|
|||
// }
|
|||
//
|
|||
// JSONObject query4Req = new JSONObject();
|
|||
// query4Req.putOpt("bool", queryObj.getByPath("query.bool"));
|
|||
// if (queryObj.get("query.filter") != null && !queryObj.getByPath("query.filter", JSONObject.class).isEmpty()) {
|
|||
// query4Req.putOpt("filter", queryObj.getByPath("query.filter"));
|
|||
// }
|
|||
//
|
|||
// sb.query(QueryBuilders.wrapperQuery(query4Req.toString()));
|
|||
//
|
|||
// searchRequest.source(sb);
|
|||
// //
|
|||
// // try (final RestHighLevelClient client = elasticsearchClient.getHighClient()) {
|
|||
// //
|
|||
// // SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
|
|||
// //
|
|||
// // Map<String, String> map = new HashMap<>();
|
|||
// // Arrays.stream(response.getHits().getHits())
|
|||
// // .forEach(hit -> map.put(JSONUtil.parseObj(hit.getSourceAsString()).getByPath(pk, String.class), hit.getId()));
|
|||
// //
|
|||
// // return map;
|
|||
// //
|
|||
// // }
|
|||
//
|
|||
// return null;
|
|||
// }
|
|||
//}
|
@ -1,20 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service; |
|||
|
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.dataManager.service.impt.exception.ImportDataInvalidException; |
|||
import org.dromara.dataManager.service.impt.model.PreviewResult; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
public interface ImportFromExcelService{ |
|||
PreviewResult previewExcel(MultipartFile file,Integer sheetIndex) throws IOException; |
|||
|
|||
void generateImportTemplate(HttpServletResponse response, Long formId, List<String> exportFields) throws IOException; |
|||
|
|||
List<Map<String, Object>> importV2(ImportDataParams params) throws IOException, ImportDataInvalidException; |
|||
|
|||
} |
@ -1,621 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl; |
|||
|
|||
import cn.hutool.core.collection.CollUtil; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.dromara.common.util.JsonUtil; |
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.dataManager.service.FormDataService; |
|||
import org.dromara.dataManager.service.impt.common.HeaderMergeStrategiesGenerator; |
|||
import org.dromara.dataManager.service.impt.enums.ImportMode; |
|||
import org.dromara.dataManager.service.impt.exception.ImportDataInvalidException; |
|||
import org.dromara.dataManager.service.impt.model.*; |
|||
import org.dromara.dataManager.service.impt.service.ImportFromExcelService; |
|||
import org.dromara.dataManager.service.impt.service.impl.excel.listener.DataAnalysisEventListener; |
|||
import org.dromara.formMaking.results.FormSourceResult; |
|||
import org.dromara.formMaking.service.FormSourceService; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import cn.hutool.json.JSONObject; |
|||
import cn.hutool.json.JSONUtil; |
|||
import com.alibaba.excel.EasyExcel; |
|||
import com.alibaba.excel.enums.CellExtraTypeEnum; |
|||
import com.alibaba.excel.metadata.CellExtra; |
|||
import com.alibaba.excel.read.metadata.ReadSheet; |
|||
import com.alibaba.excel.util.DateUtils; |
|||
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; |
|||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.io.IOException; |
|||
import java.net.URLEncoder; |
|||
import java.util.*; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class ImportFromExcelServiceImpl implements ImportFromExcelService { |
|||
|
|||
@Resource |
|||
private FormSourceService sourceQueryService; |
|||
|
|||
@Resource |
|||
private FormDataService formDataService; |
|||
|
|||
// @Resource
|
|||
// private ImportFromExcelHelper importFromExcelHelper;
|
|||
|
|||
|
|||
@Override |
|||
public PreviewResult previewExcel(MultipartFile file, Integer sheetIndex) throws IOException { |
|||
|
|||
// FormSource form = this.sourceQueryService.getFormSourceById(formId);
|
|||
|
|||
// 是否有合并表头,有的话表头有两行,没有的话表头只有一行
|
|||
/*boolean hasMergedHeaders = false; |
|||
|
|||
List<FormColumn> formColumns = JsonUtil.jsonToList(formDetail.getColumns(), FormColumn.class); |
|||
if (formColumns != null) { |
|||
if (formColumns.stream().anyMatch(formColumn -> WidgetType.TABLE.getCode().equals(formColumn.getEleType()) && CollectionUtil.isNotEmpty(formColumn.getSubColumns()))) { |
|||
hasMergedHeaders = true; |
|||
} |
|||
}*/ |
|||
|
|||
// 获取Excel中的sheet索引
|
|||
List<String> sheets = EasyExcel.read(file.getInputStream()) |
|||
.build() |
|||
.excelExecutor() |
|||
.sheetList() |
|||
.stream() |
|||
.map(ReadSheet::getSheetName) |
|||
.collect(Collectors.toList()); |
|||
|
|||
sheetIndex = sheetIndex == null ? 0 : sheetIndex; |
|||
|
|||
// 获取Excel中所有的数据
|
|||
ExtraMergeInfoListener mergeInfoListener = new ExtraMergeInfoListener(); |
|||
List<Object> sheetData = EasyExcel.read(file.getInputStream(), mergeInfoListener) |
|||
.extraRead(CellExtraTypeEnum.MERGE) |
|||
.sheet(sheetIndex) |
|||
.headRowNumber(0) |
|||
.doReadSync() |
|||
.stream() |
|||
.limit(30000) |
|||
.collect(Collectors.toList()); |
|||
|
|||
if (CollectionUtil.isEmpty(sheetData)) { |
|||
return new PreviewResult(new ArrayList<>(), new ArrayList<>(), sheets, sheets.get(sheetIndex)); |
|||
} |
|||
|
|||
boolean hasMergedHeaders = mergeInfoListener.getExtraMergeInfoList().stream().anyMatch(em -> em.getFirstRowIndex() == 0); |
|||
int howManyHeaders = hasMergedHeaders ? 2 : 1; |
|||
|
|||
List<PreviewTableHeader> headers = generatePreviewTableHeaders(sheetData, mergeInfoListener.getExtraMergeInfoList(), howManyHeaders); |
|||
|
|||
List<Object> data = new ArrayList<>(); |
|||
|
|||
// 解析出数据
|
|||
if (sheetData.size() > howManyHeaders) { |
|||
data = sheetData.subList(howManyHeaders, sheetData.size()); |
|||
} |
|||
|
|||
PreviewResult previewResult = new PreviewResult(headers, data, sheets); |
|||
previewResult.setSheetName(sheets.get(sheetIndex)); |
|||
previewResult.setSpanInfoList(generateMergeInfo(mergeInfoListener.getExtraMergeInfoList(), headers, howManyHeaders)); |
|||
return previewResult; |
|||
} |
|||
|
|||
@Override |
|||
public void generateImportTemplate(HttpServletResponse response, Long formId, List<String> exportFields) throws IOException { |
|||
FormSourceResult formInfo = sourceQueryService.getFormSourceById(formId); |
|||
List<List<String>> headers = new ArrayList<>(); |
|||
|
|||
String widgetStr = JSONUtil.parseObj(formInfo.getFormJson()).getStr("list"); |
|||
|
|||
List<FormWidget> formColumns = JsonUtil.jsonToList(widgetStr, FormWidget.class); |
|||
List<String> exportableFields = new ArrayList<>(); |
|||
|
|||
if (formColumns != null) { |
|||
formColumns.stream() |
|||
.filter(column -> { |
|||
// 过滤掉文件、图片、流水号字段
|
|||
if (WidgetType.FILE_UPLOAD.getCode().equals(column.getType()) || WidgetType.IMG_UPLOAD.getCode().equals(column.getType()) |
|||
|| WidgetType.UNIQ_KEY.getCode().equals(column.getType()) || WidgetType.TEXT.getCode().equals(column.getType()) |
|||
|| WidgetType.COORDINATES.getCode().equals(column.getType())|| WidgetType.DATA_LINK.getCode().equals(column.getType()) |
|||
|| WidgetType.DIVIDER.getCode().equals(column.getType())) { |
|||
return false; |
|||
} else if (CollectionUtil.isNotEmpty(column.getTableColumns())){ |
|||
List<FormWidget> validCols = column.getTableColumns().stream() |
|||
.filter(col -> !WidgetType.FILE_UPLOAD.getCode().equals(col.getType()) |
|||
&& !WidgetType.IMG_UPLOAD.getCode().equals(col.getType()) |
|||
&& !WidgetType.UNIQ_KEY.getCode().equals(col.getType()) |
|||
&& !WidgetType.COORDINATES.getCode().equals(col.getType()) |
|||
&& exportFields.contains(col.getModel())) |
|||
.collect(Collectors.toList()); |
|||
column.setTableColumns(validCols); |
|||
return validCols.size() > 0; |
|||
} else { |
|||
return exportFields.contains(column.getModel()); |
|||
} |
|||
}) |
|||
.forEach(column -> { |
|||
if (CollectionUtil.isNotEmpty(column.getTableColumns())) { |
|||
column.getTableColumns().forEach(col -> { |
|||
List<String> header = new ArrayList<>(); |
|||
header.add(column.getName()); |
|||
header.add(col.getName()); |
|||
headers.add(header); |
|||
}); |
|||
} else { |
|||
List<String> header = new ArrayList<>(); |
|||
header.add(column.getName()); |
|||
headers.add(header); |
|||
|
|||
} |
|||
exportableFields.add(column.getModel()); |
|||
}); |
|||
} |
|||
|
|||
String fileName = URLEncoder.encode(String.format("%s-数据导入模版%s.xlsx", formInfo.getTitle(), DateUtils.format(new Date(), "yyyyMMddHHmmss")), "UTF-8").replaceAll("\\+", "%20"); |
|||
response.setHeader("Content-Disposition", String.format("attachment;filename=%s", fileName)); |
|||
response.setContentType("application/vnd.ms-excel"); |
|||
response.setCharacterEncoding("utf-8"); |
|||
|
|||
ExcelWriterSheetBuilder sheetBuilder = EasyExcel.write(response.getOutputStream()).sheet("sheet1"); |
|||
|
|||
HeaderMergeStrategiesGenerator.generate(formColumns, exportableFields).forEach(sheetBuilder::registerWriteHandler); |
|||
|
|||
sheetBuilder.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) |
|||
.automaticMergeHead(false) |
|||
.head(headers) |
|||
.doWrite(new ArrayList<>()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public List<Map<String, Object>> importV2(ImportDataParams params) throws IOException, ImportDataInvalidException { |
|||
MultipartFile file = params.getFile(); |
|||
Long formId = params.getFormId(); |
|||
Integer sheetIndex = params.getSheetIndex(); |
|||
Map<Integer, String> mappings = params.getObjMapping(); |
|||
|
|||
FormSourceResult form = sourceQueryService.getFormSourceById(formId); |
|||
|
|||
// 是否有合并表头
|
|||
boolean hasMergedHeaders = hasMergedHeaders(file, sheetIndex); |
|||
|
|||
// 导入数据的表单字段
|
|||
List<WidgetModel> formWidgets = new ArrayList<>(); |
|||
|
|||
if (form.getFormJson() != null) { |
|||
Map<String, Object> formJson = JsonUtil.jsonToMap(form.getFormJson()); |
|||
assert formJson != null; |
|||
formWidgets = JsonUtil.jsonToList(JsonUtil.toJson(formJson.get("list")), WidgetModel.class); |
|||
} |
|||
|
|||
int headerNumber = hasMergedHeaders ? 2 : 1; |
|||
|
|||
// 导入数据量校验
|
|||
// 获取Excel中所有的数据
|
|||
ExtraMergeInfoListener countListener = new ExtraMergeInfoListener(); |
|||
EasyExcel.read(file.getInputStream(), countListener) |
|||
.sheet(sheetIndex) |
|||
.headRowNumber(headerNumber) |
|||
.doRead(); |
|||
|
|||
int rowCount = countListener.getRowCount(); |
|||
|
|||
// 有成员部门字段限制到一万条,否则最大三万条
|
|||
boolean thereAreDMC = thereAreDMColumns(formWidgets, mappings.values()); |
|||
long maxCount = thereAreDMC ? DataAnalysisEventListener.MAX_DM_DATA_COUNT : DataAnalysisEventListener.MAX_DATA_COUNT; |
|||
|
|||
if (rowCount > maxCount) { |
|||
int dataCount = headerNumber == 1 ? rowCount - headerNumber : rowCount - headerNumber + 1; |
|||
String message = thereAreDMC ? String.format("文件有%d条数据,有成员部门字段时导入数据不能超过%d条", dataCount, maxCount) : String.format("文件有%d条数据,导入数据不能超过%d条", dataCount, maxCount); |
|||
throw new ImportDataInvalidException(message, null); |
|||
} |
|||
|
|||
// String primaryKey = params.getObjMapping().containsValue(DataAnalysisEventListener.DATA_ID) ? DataAnalysisEventListener.DATA_ID : params.getPrimaryKey();
|
|||
String primaryKey = params.getPrimaryKey(); |
|||
|
|||
// 开始导入
|
|||
DataAnalysisParams dap = new DataAnalysisParams(); |
|||
dap.setFormId(form.getId()); |
|||
dap.setFormCode(form.getCode()); |
|||
dap.setHeaderNumber(headerNumber); |
|||
dap.setPrimaryKey(primaryKey); |
|||
dap.setFormWidgets(formWidgets); |
|||
dap.setMappings(mappings); |
|||
dap.setValidationConfig(params.getValidationConfig()); |
|||
|
|||
DataAnalysisEventListener listener = new DataAnalysisEventListener(dap); |
|||
|
|||
EasyExcel.read( file.getInputStream(), listener) |
|||
.extraRead(CellExtraTypeEnum.MERGE) |
|||
.headRowNumber(headerNumber) |
|||
.autoCloseStream(true) |
|||
.sheet(sheetIndex) |
|||
.doRead(); |
|||
|
|||
if (!listener.getInvalidRows().isEmpty()) { |
|||
throw new ImportDataInvalidException("导入文件中有不合法数据", listener.getInvalidRows()); |
|||
} |
|||
|
|||
List<Map<String, Object>> convertedData = generateData4Save(listener.getConvertedData(), params, form.getFormJson()); |
|||
|
|||
if (convertedData.size() > 0) { |
|||
// formDataService.batchSave(formCode, LoginContextHolder.me().getSysLoginUserId(), convertedData);
|
|||
} |
|||
|
|||
return convertedData; |
|||
} |
|||
|
|||
private boolean hasMergedHeaders(MultipartFile file, int sheetIndex) { |
|||
ExtraMergeInfoListener mergeInfoListener = new ExtraMergeInfoListener(); |
|||
try { |
|||
List<Object> sheetData = EasyExcel.read(file.getInputStream(), mergeInfoListener) |
|||
.extraRead(CellExtraTypeEnum.MERGE) |
|||
.sheet(sheetIndex) |
|||
.headRowNumber(0) |
|||
.doReadSync() |
|||
.stream() |
|||
.limit(1) |
|||
.collect(Collectors.toList()); |
|||
|
|||
return mergeInfoListener.getExtraMergeInfoList().stream().anyMatch(em -> em.getFirstRowIndex() == 0); |
|||
|
|||
} catch (IOException e) { |
|||
return true; |
|||
} |
|||
|
|||
} |
|||
|
|||
private boolean thereAreDMColumns(List<WidgetModel> formWidgets, Collection<String> importFields) { |
|||
List<String> tc = new ArrayList<>(); |
|||
formWidgets.forEach(fc -> { |
|||
if (isDMColumn(fc)) { |
|||
tc.add(fc.getModel()); |
|||
} else if (CollectionUtil.isNotEmpty(fc.getTableColumns())) { |
|||
tc.addAll(fc.getTableColumns().stream().filter(this::isDMColumn).map(WidgetModel::getModel).collect(Collectors.toList())); |
|||
} |
|||
}); |
|||
return importFields.stream().anyMatch(tc::contains); |
|||
} |
|||
|
|||
private boolean isDMColumn(WidgetModel wm) { |
|||
return wm.getType().equals(WidgetType.SINGLE_MEMBER.getCode()) || wm.getType().equals(WidgetType.SINGLE_DEPARTMENT.getCode()) |
|||
|| wm.getType().equals(WidgetType.MULTIPLE_DEPARTMENTS.getCode()) || wm.getType().equals(WidgetType.MULTIPLE_MEMBERS.getCode()); |
|||
} |
|||
|
|||
/** |
|||
* 生成可保存数据 |
|||
* @param rawData |
|||
* @param params |
|||
* @return |
|||
*/ |
|||
private List<Map<String, Object>> generateData4Save(List<Map<String, Object>> rawData, ImportDataParams params, String formJson) { |
|||
|
|||
if (ImportMode.CREATE.equals(params.getMode())) { |
|||
return generateCreateData(rawData, params.getFormId(), formJson); |
|||
} |
|||
|
|||
if (StrUtil.isNotBlank(params.getPrimaryKey())) { |
|||
|
|||
if (DataAnalysisEventListener.DATA_ID.equals(params.getPrimaryKey())) { |
|||
return generateUpsertData4IDMode(rawData, params); |
|||
} else { |
|||
return generateUpsertData4PKMode(rawData, params); |
|||
} |
|||
|
|||
} else if (params.getObjMapping().containsValue(DataAnalysisEventListener.DATA_ID)) { |
|||
return generateUpsertData4IDMode(rawData, params); |
|||
} |
|||
|
|||
return new ArrayList<>(); |
|||
} |
|||
|
|||
/** |
|||
* 根据匹配字段生成可保存数据 |
|||
* @param rawData |
|||
* @param params |
|||
* @return |
|||
*/ |
|||
private List<Map<String, Object>> generateUpsertData4PKMode(List<Map<String, Object>> rawData, ImportDataParams params) { |
|||
// eg: singlemember_1641965976117.code, input_1641965973461
|
|||
String primaryKey = params.getPrimaryKey().contains(WidgetType.SINGLE_MEMBER.getCode()) ? String.format("%s.code", params.getPrimaryKey()) : params.getPrimaryKey(); |
|||
List<String> pks = new ArrayList<>(); |
|||
|
|||
// 收集导入的主键
|
|||
rawData.forEach(cd -> { |
|||
|
|||
if (ObjectUtil.isNotEmpty(cd.get(primaryKey))) { |
|||
JSONObject jo = JSONUtil.parseObj(JSONUtil.toJsonStr(cd)); |
|||
pks.add(jo.getByPath(primaryKey, String.class)); |
|||
} |
|||
|
|||
}); |
|||
|
|||
try { |
|||
|
|||
// Map<String, String> pkvMapping = importFromExcelHelper.getPKValueMapping(params.getFormCode(), params.toElasticsearchQuery(), params.getPrimaryKey(), pks);
|
|||
// Map<String, String> pkvMapping = importFromExcelHelper.getPKValueMapping(params.getFormCode(), null,
|
|||
// params.getPrimaryKey(), pks);
|
|||
Map<String, String> pkvMapping = new HashMap<>(); |
|||
Set<String> validPK = pkvMapping.keySet(); |
|||
|
|||
rawData = rawData.stream() |
|||
.filter(cd -> { |
|||
|
|||
JSONObject row = JSONUtil.parseObj(cd); |
|||
|
|||
// 仅更新模式仅返回有数据ID且数据ID是合法的数据
|
|||
if (ImportMode.UPDATE.equals(params.getMode())) { |
|||
return ObjectUtil.isNotEmpty(row.getByPath(primaryKey, String.class)) && validPK.contains(row.getByPath(primaryKey, String.class)); |
|||
} |
|||
// 新增和更新数据模式,返回没有匹配字段或者匹配字段是合法的数据
|
|||
else { |
|||
|
|||
String rowPK = row.getByPath(primaryKey, String.class); |
|||
// 若匹配字段是空的,这条数据是有效的
|
|||
if (StrUtil.isBlank(rowPK)) { |
|||
return true; |
|||
} else { |
|||
// 若匹配字段不是空的,则判断是否可以找到数据ID,找得到则是有效的,找不到则是无效的数据
|
|||
return StrUtil.isNotBlank(pkvMapping.get(rowPK)); |
|||
} |
|||
|
|||
} |
|||
}) |
|||
.peek(cd -> { |
|||
JSONObject row = JSONUtil.parseObj(cd); |
|||
String rowPK = row.getByPath(primaryKey, String.class); |
|||
cd.put("updateTime", new Date()); |
|||
if (StrUtil.isNotBlank(rowPK)) { |
|||
// 根据主键查找到对应的数据ID
|
|||
cd.put(DataAnalysisEventListener.DATA_ID, pkvMapping.get(rowPK)); |
|||
} else { |
|||
// 为没有ID的数据创建ID
|
|||
cd.put(DataAnalysisEventListener.DATA_ID, UUID.randomUUID().toString().replaceAll("-","")); |
|||
} |
|||
}) |
|||
.collect(Collectors.toList()); |
|||
|
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
|
|||
return rawData; |
|||
} |
|||
|
|||
/** |
|||
* 为创建模式下生成可保存的数据 |
|||
* @param rawData 原始数据 |
|||
* @return 转换后的数据 |
|||
*/ |
|||
private List<Map<String, Object>> generateCreateData(List<Map<String, Object>> rawData, Long formId, String formJson) { |
|||
AtomicInteger count = new AtomicInteger(); |
|||
|
|||
rawData.forEach(row -> { |
|||
row.put(DataAnalysisEventListener.DATA_ID, UUID.randomUUID().toString().replaceAll("-","")); |
|||
Date date = new Date(System.currentTimeMillis() + count.getAndAdd(500)); |
|||
row.put("createTime", date); |
|||
row.put("updateTime", date); |
|||
}); |
|||
|
|||
return rawData; |
|||
} |
|||
|
|||
/** |
|||
* 根据数据ID生成可保存数据 |
|||
* @param rawData 转换前的数据 |
|||
* @param params 转换参数 |
|||
* @return 转换后的数据 |
|||
*/ |
|||
private List<Map<String, Object>> generateUpsertData4IDMode(List<Map<String, Object>> rawData, ImportDataParams params) { |
|||
|
|||
List<String> ids = new ArrayList<>(); |
|||
ImportMode mode = params.getMode(); |
|||
String formCode = params.getFormCode(); |
|||
// String query = params.toElasticsearchQuery();
|
|||
String query = null; |
|||
// 收集导入的ID
|
|||
rawData.forEach(cd -> { |
|||
|
|||
if (ObjectUtil.isNotEmpty(cd.get(DataAnalysisEventListener.DATA_ID))) { |
|||
ids.add((String) cd.get(DataAnalysisEventListener.DATA_ID)); |
|||
} |
|||
|
|||
}); |
|||
|
|||
// 过滤掉非法ID
|
|||
try { |
|||
|
|||
// List<String> invalidIds = importFromExcelHelper.getNotExistIds(formCode, query, ids);
|
|||
List<String> invalidIds = CollUtil.newArrayList(); |
|||
rawData = rawData.stream() |
|||
.filter(cd -> { |
|||
|
|||
// 仅更新模式仅返回有数据ID且数据ID是合法的数据
|
|||
if (ImportMode.UPDATE.equals(mode)) { |
|||
return ObjectUtil.isNotEmpty(cd.get(DataAnalysisEventListener.DATA_ID)) && !invalidIds.contains((String) cd.get(DataAnalysisEventListener.DATA_ID)); |
|||
} |
|||
// 新增和更新数据模式,返回没有数据ID或者数据ID是合法的数据
|
|||
else { |
|||
return ObjectUtil.isEmpty(cd.get(DataAnalysisEventListener.DATA_ID)) || !invalidIds.contains((String) cd.get(DataAnalysisEventListener.DATA_ID)); |
|||
} |
|||
}) |
|||
.peek(cd -> { |
|||
|
|||
// 为没有ID的数据创建ID
|
|||
if (ObjectUtil.isEmpty(cd.get(DataAnalysisEventListener.DATA_ID))) { |
|||
|
|||
cd.put(DataAnalysisEventListener.DATA_ID, UUID.randomUUID().toString().replaceAll("-","")); |
|||
} |
|||
cd.put("updateTime", new Date()); |
|||
|
|||
}) |
|||
.collect(Collectors.toList()); |
|||
|
|||
} catch (Exception e) { |
|||
log.error(e.getMessage(), e); |
|||
} |
|||
|
|||
return rawData; |
|||
} |
|||
|
|||
/** |
|||
* 生成预览表头 |
|||
* @param sheetData |
|||
* @param extraMergeInfoList |
|||
* @param howManyHeaders |
|||
* @return |
|||
*/ |
|||
private List<PreviewTableHeader> generatePreviewTableHeaders(List<Object> sheetData, List<CellExtra> extraMergeInfoList, int howManyHeaders) { |
|||
List<PreviewTableHeader> headers = new ArrayList<>(); |
|||
|
|||
// 解析出表头
|
|||
List<Map<String, Object>> headerRows = sheetData.stream() |
|||
.limit(howManyHeaders) |
|||
.map(JsonUtil::toJson) |
|||
.map(JsonUtil::jsonToMap) |
|||
.collect(Collectors.toList()); |
|||
|
|||
Map<String, Object> firstRow = headerRows.get(0); |
|||
Map<String, Object> secondRow = headerRows.size() > 1 ? headerRows.get(1) : null; |
|||
|
|||
// 查看表头是否有合并单元格
|
|||
List<CellExtra> mergedHeaderCells = extraMergeInfoList.stream() |
|||
.filter(extra -> extra.getFirstRowIndex() == 0 && extra.getLastRowIndex() == 0) |
|||
.collect(Collectors.toList()); |
|||
|
|||
List<String> existedColumns = new ArrayList<>(); |
|||
AtomicInteger currentColumnIndex = new AtomicInteger(); |
|||
firstRow.forEach((col, value) -> { |
|||
|
|||
if (col.equals(currentColumnIndex.toString())) { |
|||
|
|||
// 判断是否是合并单元格
|
|||
Integer colIndex = Integer.parseInt(col); |
|||
Optional<CellExtra> optional = mergedHeaderCells.stream().filter(cellExtra -> colIndex.equals(cellExtra.getFirstColumnIndex())).findFirst(); |
|||
|
|||
String strValue = ObjectUtil.isEmpty(value) ? "" : String.valueOf(value); |
|||
|
|||
if (optional.isPresent() && secondRow != null) { |
|||
// 有合并单元格
|
|||
CellExtra extra = optional.get(); |
|||
|
|||
PreviewTableHeader header = new PreviewTableHeader(strValue, new Random().nextInt() * 100); |
|||
|
|||
List<PreviewTableHeader> children = new ArrayList<>(); |
|||
for (int cellColIndex = extra.getFirstColumnIndex(); cellColIndex <= extra.getLastColumnIndex(); cellColIndex++) { |
|||
PreviewTableHeader subHeader = new PreviewTableHeader((String) secondRow.get(String.valueOf(cellColIndex)), currentColumnIndex.get()); |
|||
children.add(subHeader); |
|||
currentColumnIndex.getAndIncrement(); |
|||
} |
|||
header.setChildren(children); |
|||
|
|||
headers.add(header); |
|||
|
|||
existedColumns.add(strValue); |
|||
|
|||
} else if (!existedColumns.contains(strValue)){ |
|||
// 没有合并单元格
|
|||
PreviewTableHeader header = new PreviewTableHeader(strValue, currentColumnIndex.get()); |
|||
if (secondRow != null && secondRow.get(col) != null && !strValue.equals(secondRow.get(col))) { |
|||
PreviewTableHeader subHeader = new PreviewTableHeader((String) secondRow.get(col), currentColumnIndex.get()); |
|||
List<PreviewTableHeader> children = new ArrayList<>(); |
|||
children.add(subHeader); |
|||
header.setChildren(children); |
|||
} |
|||
headers.add(header); |
|||
|
|||
currentColumnIndex.getAndIncrement(); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
}); |
|||
|
|||
return headers; |
|||
} |
|||
|
|||
/** |
|||
* 生成合并单元格信息 |
|||
* @param extraMergeInfoList |
|||
* @param howManyHeaders |
|||
* @return |
|||
*/ |
|||
private List<CellSpanInfo> generateMergeInfo(List<CellExtra> extraMergeInfoList, List<PreviewTableHeader> tableHeaders, int howManyHeaders) { |
|||
List<CellSpanInfo> spanInfoList = new ArrayList<>(); |
|||
|
|||
extraMergeInfoList.stream().filter(cellExtra -> cellExtra.getFirstRowIndex() >= howManyHeaders).forEach(cellExtra -> { |
|||
|
|||
int firstRowIndex = cellExtra.getFirstRowIndex(); |
|||
int firstColIndex = cellExtra.getFirstColumnIndex(); |
|||
|
|||
for (int rowIndex = cellExtra.getFirstRowIndex(); rowIndex <= cellExtra.getLastRowIndex(); rowIndex++) { |
|||
|
|||
for (int colIndex = cellExtra.getFirstColumnIndex(); colIndex <= cellExtra.getLastColumnIndex(); colIndex++) { |
|||
|
|||
if (rowIndex == firstRowIndex && colIndex == firstColIndex) { |
|||
// 第一个合并单元格
|
|||
CellSpanInfo firstMergeCell = new CellSpanInfo(); |
|||
firstMergeCell.setRowIndex(rowIndex - howManyHeaders); |
|||
firstMergeCell.setColumnIndex(getPreviewColumnIndex(tableHeaders, colIndex)); |
|||
firstMergeCell.setRowSpan(cellExtra.getLastRowIndex() - cellExtra.getFirstRowIndex() + 1); |
|||
firstMergeCell.setColSpan(cellExtra.getLastColumnIndex() - cellExtra.getFirstColumnIndex() + 1); |
|||
spanInfoList.add(firstMergeCell); |
|||
} else { |
|||
// 处理被合并的单元格(只处理了纵向被合并的单元格)
|
|||
CellSpanInfo noSpanCell = new CellSpanInfo(); |
|||
noSpanCell.setRowIndex(rowIndex - howManyHeaders); |
|||
noSpanCell.setColumnIndex(getPreviewColumnIndex(tableHeaders, colIndex)); |
|||
noSpanCell.setRowSpan(0); |
|||
noSpanCell.setColSpan(0); |
|||
spanInfoList.add(noSpanCell); |
|||
} |
|||
} |
|||
} |
|||
|
|||
}); |
|||
|
|||
return spanInfoList; |
|||
} |
|||
|
|||
/** |
|||
* 计算并获得列的实际索引 |
|||
* @param tableHeaders |
|||
* @param columnIndex |
|||
* @return |
|||
*/ |
|||
private int getPreviewColumnIndex(List<PreviewTableHeader> tableHeaders, int columnIndex) { |
|||
int columnCount = 0; |
|||
int mergeCellCount = 0; |
|||
|
|||
for (PreviewTableHeader header : tableHeaders) { |
|||
|
|||
if (columnCount >= columnIndex) { |
|||
break; |
|||
} |
|||
|
|||
if (CollectionUtil.isNotEmpty(header.getChildren())) { |
|||
columnCount += header.getChildren().size(); |
|||
mergeCellCount += header.getChildren().size(); |
|||
} else { |
|||
columnCount++; |
|||
} |
|||
} |
|||
|
|||
return columnIndex - mergeCellCount + (mergeCellCount > 0 ? 1 : 0); |
|||
} |
|||
|
|||
} |
File diff suppressed because one or more lines are too long
@ -1,35 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.handler; |
|||
|
|||
import org.dromara.dataManager.service.impt.service.impl.excel.model.CellModel; |
|||
import com.alibaba.excel.write.handler.RowWriteHandler; |
|||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; |
|||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.poi.ss.usermodel.Row; |
|||
|
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 插入批注 |
|||
*/ |
|||
@Slf4j |
|||
public class CommentWriteHandler implements RowWriteHandler { |
|||
private List<CellModel> errors = new LinkedList<CellModel>(); |
|||
public CommentWriteHandler(List<CellModel> errors){ |
|||
this.errors = errors; |
|||
} |
|||
|
|||
@Override |
|||
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer integer, Integer integer1, Boolean aBoolean) { |
|||
} |
|||
|
|||
@Override |
|||
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer integer, Boolean aBoolean) { |
|||
} |
|||
|
|||
@Override |
|||
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer integer, Boolean aBoolean) { |
|||
|
|||
} |
|||
} |
@ -1,433 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.listener; |
|||
|
|||
|
|||
|
|||
|
|||
import org.dromara.system.domain.SysDept; |
|||
import org.dromara.system.domain.SysUser; |
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.dataManager.param.ImportDataParams; |
|||
import org.dromara.dataManager.service.impt.convert.ConverterBuilder; |
|||
import org.dromara.dataManager.service.impt.convert.WidgetConverter; |
|||
import org.dromara.dataManager.service.impt.model.DataAnalysisParams; |
|||
import org.dromara.dataManager.service.impt.service.impl.excel.model.CellModel; |
|||
import org.dromara.dataManager.service.impt.service.impl.excel.model.RecordModel; |
|||
import org.dromara.dataManager.service.impt.service.impl.excel.model.RowModel; |
|||
|
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.alibaba.excel.context.AnalysisContext; |
|||
import com.alibaba.excel.enums.CellExtraTypeEnum; |
|||
import com.alibaba.excel.event.AnalysisEventListener; |
|||
import com.alibaba.excel.metadata.CellExtra; |
|||
import lombok.Data; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
|
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
@Data |
|||
public class DataAnalysisEventListener extends AnalysisEventListener<Map<Integer, String>> { |
|||
private static final List<String> DATE_COLUMNS = Arrays.asList("createTime", "updateTime"); |
|||
public static final String DATA_ID = "id"; |
|||
// 没有成员部门字段时的最大导入数据量
|
|||
public static final Long MAX_DATA_COUNT = 30000L; |
|||
// 有成员部门字段时的最大导入数据量
|
|||
public static final Long MAX_DM_DATA_COUNT = 10000L; |
|||
|
|||
/** |
|||
* 表单ID |
|||
*/ |
|||
private Long formId; |
|||
/** |
|||
* 表单code |
|||
*/ |
|||
private String formCode; |
|||
/** |
|||
* 主键,匹配字段 |
|||
*/ |
|||
private String primaryKey; |
|||
/** |
|||
* 表头行数 |
|||
*/ |
|||
private int headerNumber; |
|||
/** |
|||
* 要导入的表单字段 |
|||
*/ |
|||
private List<WidgetModel> importWidgets; |
|||
/** |
|||
* 表单的所有字段 |
|||
*/ |
|||
private List<WidgetModel> formWidgets; |
|||
|
|||
/** |
|||
* 字段与列的映射关系 |
|||
*/ |
|||
private Map<Integer, String> mappings; |
|||
/** |
|||
* 表单字段值converter |
|||
*/ |
|||
private Map<Integer, WidgetConverter> converts = new HashMap<Integer, WidgetConverter>(); |
|||
|
|||
/** |
|||
* excel 行信息 |
|||
*/ |
|||
private List<RowModel> rows = new LinkedList<RowModel>(); |
|||
|
|||
/** |
|||
* 合并单元格信息 |
|||
*/ |
|||
private List<CellExtra> extraList = new ArrayList<>(); |
|||
|
|||
/** |
|||
* 表单记录 |
|||
*/ |
|||
private LinkedList<RecordModel> records = new LinkedList<RecordModel>(); |
|||
|
|||
/** |
|||
* 行错误信息 |
|||
*/ |
|||
private List<String> invalidRows = new ArrayList<>(); |
|||
/** |
|||
* excel中的成员账号 |
|||
*/ |
|||
private Set<String> importMembers = new HashSet<>(); |
|||
private Map<String, SysUser> accountUserMapping = new HashMap<>(); |
|||
|
|||
|
|||
/** |
|||
* excel中的部门路径 |
|||
*/ |
|||
private Set<String> importDeparts = new HashSet<>(); |
|||
private Map<String, SysDept> pathDepartMapping = new HashMap<>(); |
|||
|
|||
public DataAnalysisEventListener(DataAnalysisParams params){ |
|||
Long formId = params.getFormId(); |
|||
String formCode = params.getFormCode(); |
|||
int headerNumber = params.getHeaderNumber(); |
|||
String primaryKey = params.getPrimaryKey(); |
|||
List<WidgetModel> formWidgets = params.getFormWidgets(); |
|||
Map<Integer, String> mappings = params.getMappings(); |
|||
ImportDataParams.ValidationConfig validationConfig = params.getValidationConfig(); |
|||
|
|||
if(mappings == null || mappings.isEmpty() || formWidgets == null || formWidgets.isEmpty()){ |
|||
throw new ServiceException(WorkflowResultCode.FAIL); |
|||
} |
|||
|
|||
List<WidgetModel> widgets = buildImportWidgets(formWidgets, mappings); |
|||
|
|||
Map<String, WidgetModel> widgetMap = new HashMap<>(); |
|||
widgets.forEach(w ->{ |
|||
if(w.getType().equalsIgnoreCase(WidgetType.TABLE.getCode())){ |
|||
w.getTableColumns().forEach(sw ->{ |
|||
widgetMap.put(sw.getModel(), sw); |
|||
}); |
|||
}else { |
|||
widgetMap.put(w.getModel(), w); |
|||
} |
|||
}); |
|||
|
|||
mappings.keySet().forEach(i ->{ |
|||
|
|||
String type = widgetMap.get(mappings.get(i)) == null ? null : widgetMap.get(mappings.get(i)).getType(); |
|||
WidgetConverter converter; |
|||
|
|||
if (DATE_COLUMNS.contains(mappings.get(i))) { |
|||
|
|||
WidgetModel widget = new WidgetModel(WidgetType.DATE.getCode(), mappings.get(i), mappings.get(i)); |
|||
converter = ConverterBuilder.getConverter(WidgetType.DATE.getCode(), widget); |
|||
widgets.add(widget); |
|||
|
|||
} else if ("creatorAccount".equals(mappings.get(i)) || DATA_ID.equals(mappings.get(i))) { |
|||
|
|||
WidgetModel widget = new WidgetModel(WidgetType.GENERAL.getCode(), mappings.get(i), mappings.get(i)); |
|||
converter = ConverterBuilder.getConverter(type, widget); |
|||
widgets.add(widget); |
|||
|
|||
} else { |
|||
|
|||
converter = ConverterBuilder.getConverter(type, widgetMap.get(mappings.get(i))); |
|||
// setAccountsDepartsMapping(type, converter);
|
|||
} |
|||
|
|||
converter.setValidationConfig(validationConfig); |
|||
|
|||
this.converts.put(i, converter); |
|||
}); |
|||
|
|||
this.importWidgets = widgets; |
|||
this.formWidgets = formWidgets; |
|||
this.mappings = mappings; |
|||
this.formId = formId; |
|||
this.formCode = formCode; |
|||
this.headerNumber = headerNumber; |
|||
this.primaryKey = primaryKey; |
|||
} |
|||
|
|||
@Override |
|||
public void invoke(Map<Integer, String> data, AnalysisContext analysisContext) { |
|||
// 封装 excel 行信息,此时不做数据校验
|
|||
RowModel row = new RowModel(analysisContext.readRowHolder().getRowIndex()); |
|||
|
|||
mappings.forEach((ci, model) -> { |
|||
|
|||
row.addCell(new CellModel(converts.get(ci), row.getRowIndex(), ci, data.get(ci))); |
|||
|
|||
// 收集成员账号与部门路径
|
|||
WidgetModel widget = getWidgetByModel(model); |
|||
collectMembersAndDeparts(widget, data.get(ci)); |
|||
|
|||
}); |
|||
|
|||
this.rows.add(row); |
|||
} |
|||
|
|||
@Override |
|||
public void doAfterAllAnalysed(AnalysisContext analysisContext) { |
|||
//
|
|||
// this.accountUserMapping.putAll(SpringUtil.getBean(UserService.class).getAccountNameMapping(importMembers));
|
|||
//
|
|||
// this.pathDepartMapping.putAll(SpringUtil.getBean(DepartmentService.class).getPathDepartMapping(importDeparts));
|
|||
//
|
|||
// // 数据从第几行开始
|
|||
// int rowIndex = headerNumber;
|
|||
//
|
|||
// // 临时的 form json
|
|||
// JSONObject fjObj = new JSONObject();
|
|||
// fjObj.putOpt("config", new JSONObject());
|
|||
// fjObj.putOpt("list", formWidgets);
|
|||
// String fj = fjObj.toString();
|
|||
//
|
|||
// // 是否有creatorAccount字段
|
|||
// boolean hasAccountField = mappings.containsValue("creatorAccount");
|
|||
// List<String> importAccounts = new ArrayList<>();
|
|||
//
|
|||
// // 是否有子表单字段
|
|||
// List<WidgetModel> tableWidgets = importWidgets.stream().filter(w -> WidgetType.TABLE.getCode().equals(w.getType())).collect(Collectors.toList());
|
|||
//
|
|||
// for (int ri = 0; ri < rows.size() && rowIndex - headerNumber < rows.size(); ri ++) {
|
|||
//
|
|||
// int finalRowIndex = rowIndex;
|
|||
// Optional<CellExtra> optional = tableWidgets.size() > 0 ? extraList.stream().filter(extra -> extra.getFirstRowIndex() == finalRowIndex).findFirst() : Optional.empty();
|
|||
//
|
|||
// RecordModel record;
|
|||
// int thisRowIndex = rowIndex;
|
|||
// // 有合并单元格的数据,且有子表单字段
|
|||
// if (tableWidgets.size() > 0 && optional.isPresent()) {
|
|||
//
|
|||
// CellExtra merge = optional.get();
|
|||
// record = new RecordModel(merge.getRowIndex());
|
|||
// for(int index = merge.getFirstRowIndex(); index <= merge.getLastRowIndex(); index ++) {
|
|||
//
|
|||
// int fri = rowIndex;
|
|||
// Optional<RowModel> rmo = this.rows.stream().filter(row -> row.getRowIndex().equals(fri)).findFirst();
|
|||
// rmo.ifPresent(rowModel -> record.addRow(this.importWidgets, rowModel));
|
|||
//
|
|||
// // 行数加1
|
|||
// rowIndex++;
|
|||
// }
|
|||
//
|
|||
// if (ObjectUtil.isNotEmpty(record.getData().get(DATA_ID))) {
|
|||
// // 移除子表单字段,更新模式不支持子表单字段
|
|||
// tableWidgets.forEach(tw -> record.getData().remove(tw.getModel()));
|
|||
// }
|
|||
//
|
|||
// }
|
|||
// // 没有合并单元格的数据
|
|||
// else {
|
|||
// record = new RecordModel(rowIndex);
|
|||
//
|
|||
// int fri = rowIndex;
|
|||
// Optional<RowModel> rmo = this.rows.stream().filter(row -> row.getRowIndex().equals(fri)).findFirst();
|
|||
// rmo.ifPresent(rowModel -> record.addRow(this.importWidgets, rowModel));
|
|||
//
|
|||
// // 行数加1
|
|||
// rowIndex++;
|
|||
//
|
|||
// }
|
|||
//
|
|||
// // 记录错误信息
|
|||
// if (record.hasError()) {
|
|||
// invalidRows.add(formatErrorMessage(thisRowIndex, record.getErrorCells()));
|
|||
// }
|
|||
//
|
|||
// // 如有流水号字段则生成流水号
|
|||
// // addSerialNumberFields(record.getData(), fj);
|
|||
// this.records.add(record);
|
|||
//
|
|||
// // 收集导入的创建人账号信息
|
|||
// if (hasAccountField && ObjectUtil.isNotEmpty(record.getData().containsKey("creatorAccount"))) {
|
|||
// importAccounts.add((String) record.getData().get("creatorAccount"));
|
|||
// }
|
|||
// }
|
|||
//
|
|||
// // 添加系统字段
|
|||
// addSystemFields(hasAccountField, importAccounts);
|
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void extra(CellExtra extra, AnalysisContext context) { |
|||
if(extra.getType() == CellExtraTypeEnum.MERGE) { |
|||
extraList.add(extra); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取处理后的数据 |
|||
* @return 处理后的数据 |
|||
*/ |
|||
public List<Map<String, Object>> getConvertedData() { |
|||
return this.records.stream().map(RecordModel::getData).collect(Collectors.toList()); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加系统字段 |
|||
* @param hasAccountField 导入字段中是否有提交人账号字段 |
|||
* @param importAccounts excel中的账号字段 |
|||
*/ |
|||
private void addSystemFields(boolean hasAccountField, List<String> importAccounts) { |
|||
//
|
|||
// Map<String, SysUser> accountNameMap = getAccountNameMapping(importAccounts);
|
|||
//
|
|||
// this.records.forEach(item -> {
|
|||
// Map<String, Object> row = item.getData();
|
|||
// if (hasAccountField) {
|
|||
//
|
|||
// if (ObjectUtil.isNotEmpty(row.get("creatorAccount"))) {
|
|||
// String account = (String) row.get("creatorAccount");
|
|||
//
|
|||
// SysUser user = accountNameMap.get(account);
|
|||
// if (ObjectUtil.isNotNull(user)) {
|
|||
// row.put("owner", user.getId());
|
|||
// row.put("creator", user.getName());
|
|||
// row.put("creatorAccount", user.getAccount());
|
|||
// } else {
|
|||
// row.put("owner", LoginContextHolder.me().getSysLoginUserId());
|
|||
// row.put("creator", LoginContextHolder.me().getSysLoginUser().getName());
|
|||
// row.put("creatorAccount", LoginContextHolder.me().getSysLoginUserAccount());
|
|||
// }
|
|||
// }
|
|||
//
|
|||
// }
|
|||
//
|
|||
// // 没有匹配字段说明这是一条新增的数据
|
|||
// if (primaryKey != null) {
|
|||
// if (ObjectUtil.isEmpty(item.getData().get(primaryKey))) {
|
|||
// row.putIfAbsent("owner", LoginContextHolder.me().getSysLoginUserId());
|
|||
// row.putIfAbsent("creator", LoginContextHolder.me().getSysLoginUser().getName());
|
|||
// row.putIfAbsent("creatorAccount", LoginContextHolder.me().getSysLoginUserAccount());
|
|||
// row.putIfAbsent("createTime", new Date());
|
|||
// }
|
|||
// } else {
|
|||
// row.putIfAbsent("owner", LoginContextHolder.me().getSysLoginUserId());
|
|||
// row.putIfAbsent("creator", LoginContextHolder.me().getSysLoginUser().getName());
|
|||
// row.putIfAbsent("creatorAccount", LoginContextHolder.me().getSysLoginUserAccount());
|
|||
// row.putIfAbsent("createTime", new Date());
|
|||
// }
|
|||
//
|
|||
// });
|
|||
|
|||
} |
|||
|
|||
private Map<String, SysUser> getAccountNameMapping(List<String> accounts) { |
|||
// if (CollUtil.isEmpty(accounts)) {
|
|||
// return new HashMap<>();
|
|||
// }
|
|||
// UserService userService = SpringUtil.getBean(UserService.class);
|
|||
// return userService.getAccountNameMapping(accounts);
|
|||
|
|||
return new HashMap<>(); |
|||
} |
|||
|
|||
/** |
|||
* 收集excel中的成员账号与部门路径 |
|||
* @param widget 字段信息 |
|||
* @param value excel中的值 |
|||
*/ |
|||
private void collectMembersAndDeparts(WidgetModel widget, String value) { |
|||
|
|||
if (StringUtils.isNotBlank(value) && widget != null) { |
|||
|
|||
if (WidgetType.SINGLE_MEMBER.getCode().equals(widget.getType()) || WidgetType.MULTIPLE_MEMBERS.getCode().equals(widget.getType())) { |
|||
importMembers.addAll(Arrays.asList(value.split(","))); |
|||
} |
|||
|
|||
if (WidgetType.SINGLE_DEPARTMENT.getCode().equals(widget.getType()) || WidgetType.MULTIPLE_DEPARTMENTS.getCode().equals(widget.getType())) { |
|||
importDeparts.addAll(Arrays.asList(value.split(","))); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 格式化错误信息 |
|||
* @param rowIndex 行索引 |
|||
* @param errorCells 有错误数据的单元格 |
|||
* @return 错误信息 |
|||
*/ |
|||
private String formatErrorMessage(int rowIndex, List<CellModel> errorCells) { |
|||
List<String> errors = new ArrayList<>(); |
|||
errors.add(String.format("第%d行", rowIndex + 1)); |
|||
errorCells.forEach(ec -> { |
|||
errors.add(String.format("%s(%d列)", ec.getValidate().getMessage(), ec.getColIndex() + 1)); |
|||
}); |
|||
|
|||
return String.join(",", errors); |
|||
} |
|||
|
|||
/** |
|||
* 根据字段唯一标识符获取字段配置信息 |
|||
* @param model 字段唯一标识符 |
|||
* @return 字段配置信息 |
|||
*/ |
|||
private WidgetModel getWidgetByModel(String model) { |
|||
|
|||
WidgetModel matched = null; |
|||
|
|||
for(WidgetModel wm: importWidgets) { |
|||
|
|||
if (WidgetType.TABLE.getCode().equals(wm.getType())) { |
|||
|
|||
Optional<WidgetModel> optional = wm.getTableColumns().stream().filter(tc -> tc.getModel().equals(model)).findFirst(); |
|||
if (optional.isPresent()) { |
|||
matched = optional.get(); |
|||
break; |
|||
} |
|||
|
|||
} else if (wm.getModel().equals(model)){ |
|||
matched = wm; |
|||
break; |
|||
} |
|||
} |
|||
return matched; |
|||
} |
|||
|
|||
private List<WidgetModel> buildImportWidgets(List<WidgetModel> formWidgets, Map<Integer, String> mappings) { |
|||
List<WidgetModel> widgets = new ArrayList<>(); |
|||
|
|||
formWidgets.forEach(fc -> { |
|||
if (mappings.containsValue(fc.getModel())) { |
|||
widgets.add(fc); |
|||
} else if (CollectionUtil.isNotEmpty(fc.getTableColumns())) { |
|||
|
|||
List<WidgetModel> tcList = fc.getTableColumns().stream() |
|||
.filter(tc -> mappings.containsValue(tc.getModel())) |
|||
.collect(Collectors.toList()); |
|||
|
|||
if (CollectionUtil.isNotEmpty(tcList)) { |
|||
fc.setTableColumns(tcList); |
|||
widgets.add(fc); |
|||
} |
|||
} |
|||
|
|||
}); |
|||
|
|||
return widgets; |
|||
} |
|||
|
|||
} |
@ -1,52 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.model; |
|||
|
|||
import org.dromara.dataManager.service.impt.convert.WidgetConverter; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* excel单元格model |
|||
*/ |
|||
@Data |
|||
public class CellModel implements Serializable { |
|||
private static final long serialVersionUID = -1027380204378668428L; |
|||
|
|||
/** |
|||
* 表单字段值converter |
|||
*/ |
|||
private WidgetConverter converter; |
|||
private Integer rowIndex; |
|||
private Integer colIndex; |
|||
private String excelValue; |
|||
private Validate validate; |
|||
|
|||
public CellModel(WidgetConverter converter, Integer rowIndex, Integer colIndex, String excelValue){ |
|||
this.converter = converter; |
|||
this.rowIndex = rowIndex; |
|||
this.colIndex = colIndex; |
|||
this.excelValue = excelValue; |
|||
} |
|||
|
|||
public void validateFail(String message){ |
|||
this.validate = new Validate(false, message); |
|||
} |
|||
|
|||
public void validateSucc(){ |
|||
this.validate = new Validate(true); |
|||
} |
|||
|
|||
@Data |
|||
static |
|||
public class Validate implements Serializable{ |
|||
private Boolean success = true; |
|||
private String message; |
|||
public Validate(Boolean success){ |
|||
this.success = success; |
|||
} |
|||
public Validate(Boolean success, String message){ |
|||
this.success = success; |
|||
this.message = message; |
|||
} |
|||
} |
|||
} |
@ -1,119 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.model; |
|||
|
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.dataManager.service.impt.convert.WidgetConverter; |
|||
import org.dromara.taskCenter.model.widget.WidgetModel; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* 数据记录 |
|||
*/ |
|||
@Data |
|||
public class RecordModel implements Serializable { |
|||
private static final long serialVersionUID = 8553281834023196024L; |
|||
|
|||
/** |
|||
* excel 合并行 |
|||
*/ |
|||
private Integer rowIndex; |
|||
/** |
|||
* 表单数据 |
|||
*/ |
|||
private Map<String, Object> data = new HashMap<>(); |
|||
|
|||
/** |
|||
* 验证错误的单元格 |
|||
*/ |
|||
public List<CellModel> errorCells = new LinkedList<CellModel>(); |
|||
|
|||
public RecordModel(Integer rowIndex){ |
|||
this.rowIndex = rowIndex; |
|||
} |
|||
|
|||
public void addRow(List<WidgetModel> widgets, RowModel row){ |
|||
if(widgets != null){ |
|||
Map<String, CellModel> cellMap = row.getCells(); |
|||
widgets.forEach(w -> { |
|||
if(!w.getType().equalsIgnoreCase(WidgetType.TABLE.getCode())){ |
|||
this.putData(w.getModel(), cellMap.get(w.getModel())); |
|||
} else if (CollectionUtil.isNotEmpty(w.getTableColumns())){ |
|||
w.getTableColumns().forEach(sw -> { |
|||
this.putTableData(w.getModel(), sw.getModel(), cellMap.get(sw.getModel())); |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public boolean hasError(){ |
|||
return errorCells.size() > 0; |
|||
} |
|||
|
|||
/** |
|||
* 设置子表单数据 |
|||
* @param tableModel |
|||
* @param model |
|||
* @param cell |
|||
*/ |
|||
private void putTableData(String tableModel, String model, CellModel cell){ |
|||
if (cell == null) { |
|||
return; |
|||
} |
|||
if(!data.containsKey(tableModel)){ |
|||
data.put(tableModel, new LinkedList<Map<String, Object>>()); |
|||
} |
|||
List<Map<String, Object>> table = (List<Map<String, Object>>) data.get(tableModel); |
|||
if(cell.getRowIndex() - this.rowIndex > table.size() -1){ |
|||
table.add(new HashMap<>()); |
|||
table.get(table.size() - 1).put("_id", UUID.randomUUID().toString()); |
|||
} |
|||
|
|||
Map<String, Object> map = table.get(cell.getRowIndex() - this.rowIndex); |
|||
cell.getConverter().validate(cell.getExcelValue(), new WidgetConverter.ConvertCallBack() { |
|||
@Override |
|||
public void success(Object convertValue) { |
|||
// 如果是空的数据则忽略掉这个字段
|
|||
if (ObjectUtil.isNotEmpty(convertValue)) { |
|||
map.put(model, convertValue); |
|||
} |
|||
cell.validateSucc(); |
|||
} |
|||
|
|||
@Override |
|||
public void fail(String message) { |
|||
cell.validateFail(message); |
|||
errorCells.add(cell); |
|||
} |
|||
}); |
|||
} |
|||
/** |
|||
* 设置数据 |
|||
* @param model |
|||
* @param cell |
|||
*/ |
|||
private void putData(String model, CellModel cell){ |
|||
if(!this.data.containsKey(model)){ |
|||
cell.getConverter().validate(cell.getExcelValue(), new WidgetConverter.ConvertCallBack() { |
|||
@Override |
|||
public void success(Object convertValue) { |
|||
// 如果是空的数据则忽略掉这个字段
|
|||
if (ObjectUtil.isNotEmpty(convertValue)) { |
|||
data.put(model, convertValue); |
|||
} |
|||
|
|||
cell.validateSucc(); |
|||
} |
|||
@Override |
|||
public void fail(String message) { |
|||
cell.validateFail(message); |
|||
errorCells.add(cell); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
@ -1,30 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* excel行合并信息 |
|||
*/ |
|||
@Data |
|||
public class RowMerge implements Serializable { |
|||
private Integer rowIndex; |
|||
private Integer firstRowIndex; |
|||
private Integer lastRowIndex; |
|||
|
|||
public RowMerge(Integer rowIndex, Integer firstRowIndex, Integer lastRowIndex){ |
|||
this.rowIndex = rowIndex; |
|||
this.firstRowIndex = firstRowIndex; |
|||
this.lastRowIndex = lastRowIndex; |
|||
} |
|||
|
|||
public void update(Integer firstRowIndex, Integer lastRowIndex) { |
|||
if (firstRowIndex != null && firstRowIndex.intValue() < this.firstRowIndex.intValue()) { |
|||
this.firstRowIndex = firstRowIndex; |
|||
} |
|||
if (lastRowIndex != null && lastRowIndex.intValue() > this.lastRowIndex.intValue()) { |
|||
this.lastRowIndex = lastRowIndex; |
|||
} |
|||
} |
|||
} |
@ -1,34 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.service.impl.excel.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* excel 行model |
|||
*/ |
|||
@Data |
|||
public class RowModel implements Serializable { |
|||
private static final long serialVersionUID = 3100643744741570508L; |
|||
|
|||
/** |
|||
* 行号 |
|||
*/ |
|||
private Integer rowIndex; |
|||
|
|||
/** |
|||
* key = 表单model |
|||
* value = CellModel |
|||
*/ |
|||
private Map<String, CellModel> cells = new HashMap<>(); |
|||
|
|||
public RowModel(Integer rowIndex){ |
|||
this.rowIndex = rowIndex; |
|||
} |
|||
|
|||
public void addCell(CellModel cell){ |
|||
this.cells.put(cell.getConverter().getWidget().getModel(), cell); |
|||
} |
|||
} |
@ -1,84 +0,0 @@ |
|||
package org.dromara.dataManager.service.impt.validator; |
|||
|
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.util.NumberUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.alibaba.excel.util.DateUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.text.ParseException; |
|||
|
|||
@Slf4j |
|||
public class ValueValidator { |
|||
|
|||
public static boolean isEmpty(Object value) { |
|||
return ObjectUtil.isEmpty(value); |
|||
} |
|||
|
|||
public static boolean isNumber(Object value) { |
|||
if (value == null) { |
|||
return false; |
|||
} else { |
|||
String numberStr = (String) value; |
|||
numberStr = numberStr.replaceAll(",", "").replaceAll("%", ""); |
|||
return NumberUtil.isNumber(numberStr); |
|||
} |
|||
} |
|||
|
|||
public static boolean isDate(Object value, FormWidget formWidget) { |
|||
if (value != null) { |
|||
String dateObj = (String) value; |
|||
try { |
|||
String format = (String) formWidget.getOptions().get("format"); |
|||
// 使用规定格式转换数据,转换不报错就说明是日期格式数据
|
|||
DateUtils.parseDate(dateObj, format); |
|||
return true; |
|||
} catch (Exception e) { |
|||
try { |
|||
// 如果转换报错,则尝试自动转换日期格式,转换不报错就说明是日期格式数据
|
|||
DateUtils.parseDate(dateObj); |
|||
return true; |
|||
} catch (Exception parseException) { |
|||
// 自动识别格式失败则尝试自动识别常用格式,转换不报错就说明是日期格式数据
|
|||
try { |
|||
if (dateObj.contains("/") || dateObj.contains("-")) { |
|||
convert2Date(dateObj); |
|||
} else { |
|||
return false; |
|||
} |
|||
} catch (ParseException exception) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
private static void convert2Date(String dateString) throws ParseException { |
|||
|
|||
// 自动识别格式失败则尝试自动识别常用格式
|
|||
String separator = null; |
|||
|
|||
if (dateString.contains("-")) { |
|||
separator = "-"; |
|||
|
|||
} else if (dateString.contains("/")) { |
|||
separator = "/"; |
|||
} |
|||
|
|||
if (separator != null) { |
|||
String ymd = String.format("yyyy%sMM%sdd", separator, separator); |
|||
String[] formats = new String[]{ymd, String.format("%s HH:mm:ss", ymd), String.format("%s HH:mm", ymd), String.format("%s HH", ymd)}; |
|||
|
|||
for (String format: formats) { |
|||
DateUtils.parseDate(dateString, format); |
|||
break; |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
} |
@ -1,20 +0,0 @@ |
|||
package org.dromara.dataManager.service.log; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @Description: server |
|||
**/ |
|||
public interface DataLogActionService { |
|||
|
|||
/** |
|||
* 封装数据日志对象集合 |
|||
* @return |
|||
*/ |
|||
List<FormDataLog> transformDataLogs(FormDataModifyMessage data); |
|||
|
|||
|
|||
} |
@ -1,37 +0,0 @@ |
|||
package org.dromara.dataManager.service.log; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数据日志service |
|||
*/ |
|||
public interface FormDataLogService extends IService<FormDataLog> { |
|||
|
|||
/** |
|||
* 添加数据日志 |
|||
* @param param |
|||
*/ |
|||
void addDataLog(FormDataModifyMessage param); |
|||
|
|||
/** |
|||
* 查询某数据的详细数据日志 |
|||
* @param dataId |
|||
* @return |
|||
*/ |
|||
List<FormDataLog> listDataLog(Long formId,Long dataId); |
|||
|
|||
/** |
|||
* 清空表单填报数据 |
|||
* @param formId |
|||
*/ |
|||
void deleteByForm(Long formId); |
|||
|
|||
/** |
|||
* 批量删除 |
|||
* @param docIds |
|||
*/ |
|||
void deleteByDataIds(String[] docIds); |
|||
} |
@ -1,53 +0,0 @@ |
|||
package org.dromara.dataManager.service.log.impl; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
import org.dromara.dataManager.service.FormDataService; |
|||
import org.dromara.dataManager.service.log.DataLogActionService; |
|||
import org.dromara.workflow.engine.enums.ESDefaultFieldConst; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @Description: 删除操作 记录数据日志 |
|||
**/ |
|||
@Slf4j |
|||
@Component("deleteDataLog") |
|||
public class DataLogDeleteService implements DataLogActionService { |
|||
|
|||
@Autowired |
|||
private FormDataService formDataService; |
|||
|
|||
@Override |
|||
public List<FormDataLog> transformDataLogs(FormDataModifyMessage data) { |
|||
List<FormDataLog> formDataLogs = new ArrayList<>(); |
|||
|
|||
data.getBefore().forEach(p -> { |
|||
Map<String, Object> afterDataMap = formDataService.getFormDataById(data.getFormId(), (Long) p.get("dataId")); |
|||
|
|||
formDataLogs.add(transformLog(data, (Long) p.get("dataId"),afterDataMap)); |
|||
}); |
|||
|
|||
return formDataLogs; |
|||
} |
|||
|
|||
private FormDataLog transformLog(FormDataModifyMessage param, Long dataId, Map<String,Object> dataMap) { |
|||
if(ObjectUtil.isNotEmpty(dataId)){ |
|||
FormDataLog formDataLog = new FormDataLog(param.getFormId(),param.getFormCode()); |
|||
formDataLog.fillData(param.getAction().getCode(),dataId,null,dataMap); |
|||
dataMap.put(ESDefaultFieldConst.DELETED,false); |
|||
formDataLog.fillOldData(dataMap); |
|||
formDataLog.setUser(param.getHandleUserId(),param.getHandleUserName(),param.getHandleUserAccount(), param.getHandleTime()); |
|||
formDataLog.setChanges(null); |
|||
return formDataLog; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
@ -1,42 +0,0 @@ |
|||
package org.dromara.dataManager.service.log.impl; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
import org.dromara.dataManager.service.log.DataLogActionService; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* @Description: 新增操作 记录数据日志 |
|||
**/ |
|||
@Slf4j |
|||
@Component("saveDataLog") |
|||
public class DataLogSaveService implements DataLogActionService { |
|||
|
|||
|
|||
@Override |
|||
public List<FormDataLog> transformDataLogs(FormDataModifyMessage data) { |
|||
|
|||
return data.getAfter().stream().map(p -> transformLog(data,(Long) p.get("dataId"),p)) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
|
|||
private FormDataLog transformLog(FormDataModifyMessage param, Long dataId,Map<String,Object> after |
|||
) { |
|||
if(ObjectUtil.isNotEmpty(dataId)){ |
|||
FormDataLog formDataLog = new FormDataLog(param.getFormId(),param.getFormCode()); |
|||
formDataLog.fillData(param.getAction().getCode(),dataId,null,after); |
|||
formDataLog.setUser(param.getHandleUserId(),param.getHandleUserName(),param.getHandleUserAccount(), param.getHandleTime()); |
|||
formDataLog.setChanges(null); |
|||
return formDataLog; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
@ -1,85 +0,0 @@ |
|||
package org.dromara.dataManager.service.log.impl; |
|||
|
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.common.util.JsonUtil; |
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
import org.dromara.dataManager.service.log.DataLogActionService; |
|||
import org.dromara.dataManager.service.validate.FormDataValidateService; |
|||
import org.dromara.formMaking.results.FormSourceResult; |
|||
import org.dromara.formMaking.service.FormSourceService; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @Description: 单条数据修改操作 记录数据日志 |
|||
**/ |
|||
@Slf4j |
|||
@Component("updateDataLog") |
|||
public class DataLogUpdateService implements DataLogActionService { |
|||
@Autowired |
|||
private FormDataValidateService dataValidateService; |
|||
@Autowired |
|||
private FormSourceService formSourceService; |
|||
@Override |
|||
public List<FormDataLog> transformDataLogs(FormDataModifyMessage data) { |
|||
|
|||
if(ObjectUtil.hasEmpty(data.getBefore(),data.getAfter())){ |
|||
|
|||
throw new ServiceException(WorkflowResultCode.PARAM_IS_BLANK); |
|||
} |
|||
List<FormWidget> configs = getFormWidgets(data); |
|||
if(CollUtil.isEmpty(configs)){ |
|||
|
|||
throw new ServiceException(WorkflowResultCode.FORM_DETAIL_NOT_EXIST); |
|||
} |
|||
List<FormDataLog.UpdateWidgetResult> updateWidgets = dataValidateService.listUpdateWidgets(configs,data.getBefore().get(0), data.getAfter().get(0)); |
|||
if(CollUtil.isNotEmpty(updateWidgets)){ |
|||
|
|||
return Arrays.asList(generateLogEntity(data, data.getBefore().get(0), data.getAfter().get(0),updateWidgets)); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
|
|||
private FormDataLog generateLogEntity(FormDataModifyMessage param,Map<String,Object> before, |
|||
Map<String,Object> after, |
|||
List<FormDataLog.UpdateWidgetResult> updateWidgetResults |
|||
) { |
|||
Long dataId = (Long)before.get("dataId"); |
|||
FormDataLog formDataLog = new FormDataLog(param.getFormId(),param.getFormCode()); |
|||
formDataLog.fillData(param.getAction().getCode(),dataId,before,after); |
|||
formDataLog.setUser(param.getHandleUserId(),param.getHandleUserName(),param.getHandleUserAccount(), param.getHandleTime()); |
|||
formDataLog.setChanges(JsonUtil.toJson(updateWidgetResults)); |
|||
return formDataLog; |
|||
} |
|||
|
|||
|
|||
private List<FormWidget> getFormWidgets(FormDataModifyMessage data){ |
|||
FormSourceResult formDetail = this.formSourceService.getFormSourceById(data.getFormId()); |
|||
|
|||
Map<String, Object> formJson = JsonUtil.jsonToMap(formDetail.getFormJson()); |
|||
|
|||
assert formJson != null; |
|||
List<FormWidget> columnWidgetList = JsonUtil.jsonToList(JsonUtil.toJson(formJson.get("list")), FormWidget.class); |
|||
if(CollUtil.isEmpty(columnWidgetList)){ |
|||
|
|||
log.error("###### 数据日志 update field widget not exist ######"); |
|||
return null; |
|||
} |
|||
|
|||
|
|||
return columnWidgetList; |
|||
} |
|||
|
|||
} |
@ -1,76 +0,0 @@ |
|||
package org.dromara.dataManager.service.log.impl; |
|||
|
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.common.util.JsonUtil; |
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.mapper.FormDataLogMapper; |
|||
import org.dromara.dataManager.param.FormDataModifyMessage; |
|||
import org.dromara.dataManager.service.log.DataLogActionService; |
|||
import org.dromara.dataManager.service.log.FormDataLogService; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class FormDataLogServiceImpl extends ServiceImpl<FormDataLogMapper, FormDataLog> implements FormDataLogService { |
|||
|
|||
@Autowired |
|||
private final Map<String, DataLogActionService> dataActionService = new ConcurrentHashMap<String, DataLogActionService>(); |
|||
|
|||
@Autowired |
|||
private FormDataLogMapper formDataLogMapper; |
|||
|
|||
@Override |
|||
public List<FormDataLog> listDataLog(Long formId,Long dataId) { |
|||
if(ObjectUtil.hasEmpty(formId,dataId)){ |
|||
|
|||
throw new ServiceException(WorkflowResultCode.PARAM_MISSING); |
|||
} |
|||
|
|||
return this.formDataLogMapper.listDataLog(formId,dataId); |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void addDataLog(FormDataModifyMessage param) { |
|||
DataLogActionService dataLogActionService = dataActionService.get(param.getAction().getCode()+"DataLog"); |
|||
if(dataLogActionService != null){ |
|||
List<FormDataLog> formDataLogList = dataLogActionService.transformDataLogs(param); |
|||
|
|||
if(CollUtil.isEmpty(formDataLogList)){ |
|||
if(log.isDebugEnabled()){ |
|||
log.error("###### data log empty {} ######", JsonUtil.toJson(param)); |
|||
} |
|||
return; |
|||
} |
|||
|
|||
this.formDataLogMapper.batchSaveDataLog(formDataLogList); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteByForm(Long formId) { |
|||
this.formDataLogMapper.delete(new LambdaQueryWrapper<FormDataLog>().eq(FormDataLog::getFormId,formId)); |
|||
} |
|||
|
|||
/** |
|||
* 删除数据日志 |
|||
* @param dataIds |
|||
*/ |
|||
@Override |
|||
public void deleteByDataIds(String... dataIds){ |
|||
if(dataIds != null && dataIds.length > 0 && dataIds[0] != null){ |
|||
this.formDataLogMapper.deleteByDataIds(dataIds); |
|||
} |
|||
} |
|||
} |
@ -1,67 +0,0 @@ |
|||
package org.dromara.dataManager.service.validate; |
|||
|
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* 表单数据校验/对比 |
|||
*/ |
|||
public interface FormDataValidateService { |
|||
|
|||
/** |
|||
* 校验字段值是否发生变化 |
|||
* @param widgetId |
|||
* @param before |
|||
* @param after |
|||
* @return |
|||
*/ |
|||
boolean checkWidgetUpdated(String widgetId,Object before, Object after); |
|||
|
|||
|
|||
/** |
|||
* 查询发生变化的表单字段的值 |
|||
*/ |
|||
List<FormDataLog.UpdateWidgetResult> listUpdateWidgets(Long formId, Map<String,Object> before, Map<String, Object> after); |
|||
|
|||
|
|||
/** |
|||
* 查询发生变化的表单字段的值 |
|||
*/ |
|||
List<FormDataLog.UpdateWidgetResult> listUpdateWidgets(List<FormWidget> configs, Map<String,Object> before, Map<String, Object> after); |
|||
|
|||
|
|||
/** |
|||
* 查询主字段值的变化 |
|||
* @param before |
|||
* @param after |
|||
* @param model |
|||
* @return |
|||
*/ |
|||
FormDataLog.UpdateWidgetResult getUpdateWidget(FormWidget model,String widgetId,Map<String,Object> before,Map<String,Object> after); |
|||
|
|||
/** |
|||
* 查询子表单子字段值的变化 |
|||
* @param before |
|||
* @param after |
|||
* @param tableId |
|||
* @return |
|||
*/ |
|||
FormDataLog.UpdateWidgetResult getTableColumnUpdateWidget(List<FormWidget> configs, |
|||
String tableId, |
|||
String subColumnId, |
|||
List<Map<String,Object>> before, |
|||
List<Map<String,Object>> after); |
|||
|
|||
|
|||
/** |
|||
* 查询数据变动情况【数据补偿,已废弃】 |
|||
* @param before |
|||
* @param after |
|||
* @return |
|||
*/ |
|||
List<FormDataLog.UpdateWidgetResult> listUpdatedData(Map<String,Object> before,Map<String, Object> after); |
|||
|
|||
} |
@ -1,265 +0,0 @@ |
|||
package org.dromara.dataManager.service.validate.impl; |
|||
|
|||
|
|||
import org.dromara.common.Exception.ServiceException; |
|||
import org.dromara.common.response.WorkflowResultCode; |
|||
import org.dromara.common.util.JsonUtil; |
|||
import org.dromara.dataManager.domain.FormDataLog; |
|||
import org.dromara.dataManager.enums.WidgetType; |
|||
import org.dromara.dataManager.service.validate.FormDataValidateService; |
|||
import org.dromara.dataManager.widget.convert.base.BaseFormFieldConverter; |
|||
import org.dromara.dataManager.widget.convert.base.FormFieldFactory; |
|||
import org.dromara.dataManager.widget.convert.column.DefaultConverter; |
|||
import org.dromara.dataManager.widget.convert.column.TableConverter; |
|||
import org.dromara.formMaking.results.FormSourceResult; |
|||
import org.dromara.formMaking.service.FormSourceService; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import org.dromara.workflow.engine.enums.ESDefaultFieldConst; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.google.common.collect.Sets; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.compress.utils.Lists; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.*; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class FormDataValidateServiceImpl implements FormDataValidateService { |
|||
|
|||
public static final List<String> flowChangedFields = Arrays.asList(ESDefaultFieldConst.FLOW_STAGE); |
|||
|
|||
@Autowired |
|||
private FormSourceService formSourceService; |
|||
|
|||
@Override |
|||
public boolean checkWidgetUpdated(String widgetId,Object before, Object after){ |
|||
BaseFormFieldConverter converter = FormFieldFactory.getConverter(widgetId.contains(WidgetType.TABLE.getCode()) ? StrUtil.subBefore(widgetId,".", true) : widgetId); |
|||
if (converter != null) { |
|||
return converter.checkChange(before, after); |
|||
} |
|||
|
|||
throw new ServiceException(WorkflowResultCode.FORM_WIDGET_NOT_ALLOWED); |
|||
} |
|||
|
|||
@Override |
|||
public List<FormDataLog.UpdateWidgetResult> listUpdateWidgets(Long formId, Map<String, Object> before, Map<String, Object> after) { |
|||
List<FormWidget> configs = getFormWidgets(formId); |
|||
if(CollUtil.isNotEmpty(configs)){ |
|||
|
|||
return listUpdateWidgets(configs,before,after); |
|||
} |
|||
|
|||
return Lists.newArrayList(); |
|||
} |
|||
|
|||
@Override |
|||
public List<FormDataLog.UpdateWidgetResult> listUpdateWidgets(List<FormWidget> configs,Map<String, Object> before,Map<String, Object> after) { |
|||
List<FormDataLog.UpdateWidgetResult> results = new ArrayList<>(); |
|||
|
|||
if(ObjectUtil.isAllNotEmpty(before,after)) { |
|||
Sets.SetView<String> unionKeys = Sets.union(after.keySet(), before.keySet()); |
|||
LinkedHashSet<String> sortKeys = new LinkedHashSet<>(); |
|||
configs.stream().map(FormWidget::getModel) |
|||
.filter(unionKeys::contains) |
|||
.forEach(sortKeys::add); |
|||
|
|||
if(CollUtil.isNotEmpty(unionKeys)){ |
|||
unionKeys.stream().filter(key -> !sortKeys.contains(key)).forEach(sortKeys::add); |
|||
sortKeys.forEach(key -> { |
|||
FormWidget config =configs.stream().filter(p -> StrUtil.equals(p.getModel(),key)).findAny().orElse(null); |
|||
if(config != null) { |
|||
|
|||
String tableId = key.contains(WidgetType.TABLE.getCode()) ? StrUtil.subBefore(key, ".", true) : null; |
|||
if (tableId != null) { |
|||
List<Map<String,Object>> tableBeforeData = (List<Map<String,Object>>)before.get(tableId); |
|||
List<Map<String,Object>> tableAfterData = (List<Map<String,Object>>)after.get(tableId); |
|||
|
|||
FormDataLog.UpdateWidgetResult tableUpdateResult = |
|||
getTableColumnUpdateWidget(config.getTableColumns(),tableId,null,tableBeforeData,tableAfterData); |
|||
if(tableUpdateResult != null) { |
|||
results.add(tableUpdateResult); |
|||
} |
|||
} else { |
|||
FormDataLog.UpdateWidgetResult updateResult = getUpdateWidget(config, key, before, after); |
|||
if(updateResult != null) { |
|||
results.add(getUpdateWidget(config, key, before, after)); |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
} |
|||
|
|||
return results; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public FormDataLog.UpdateWidgetResult getUpdateWidget(FormWidget config,String widgetId,Map<String,Object> before,Map<String,Object> after) { |
|||
if(ObjectUtil.hasEmpty(config,widgetId) || ObjectUtil.isAllEmpty(before,after)){ |
|||
return null; |
|||
} |
|||
|
|||
if (flowChangedFields.contains(widgetId)) { |
|||
FormDataLog.UpdateWidgetResult result = new FormDataLog.UpdateWidgetResult(widgetId); |
|||
|
|||
DefaultConverter converter = new DefaultConverter(); |
|||
if (converter.checkChange(before.get(widgetId), after.get(widgetId))) { |
|||
String bef = new DefaultConverter().convert(before.get(widgetId), null); |
|||
String aft = new DefaultConverter().convert(after.get(widgetId), null); |
|||
result.setBef(bef); |
|||
result.setAft(aft); |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
BaseFormFieldConverter converter = FormFieldFactory.getConverter(config.getModel()); |
|||
if(converter != null) { |
|||
FormDataLog.UpdateWidgetResult result = new FormDataLog.UpdateWidgetResult( config.getModel()); |
|||
|
|||
if(converter.checkChange(before.get(widgetId), after.get(widgetId))) { |
|||
String bData = converter.convert(before.get(widgetId), config); |
|||
String aData = converter.convert(after.get(widgetId), config); |
|||
result.setBef(bData); |
|||
result.setAft(aData); |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
public FormDataLog.UpdateWidgetResult getTableColumnUpdateWidget(List<FormWidget> config, |
|||
String tableId, |
|||
String subColumnId, |
|||
List<Map<String,Object>> before, |
|||
List<Map<String,Object>> after |
|||
) { |
|||
if(ObjectUtil.hasEmpty(config,tableId) || ObjectUtil.isAllEmpty(before,after)){ |
|||
|
|||
return null; |
|||
} |
|||
TableConverter tableConverter = new TableConverter(config); |
|||
|
|||
FormDataLog.UpdateWidgetResult result = new FormDataLog.UpdateWidgetResult(tableId); |
|||
|
|||
Map<String,List<Map<String,Object>>> updatedTableData = tableConverter.listUpdateData(subColumnId,before,after); |
|||
List<Map<String,Object>> befData = updatedTableData.get("before"); |
|||
List<Map<String,Object>> afterData = updatedTableData.get("after"); |
|||
|
|||
if(CollUtil.isEmpty(befData) && CollUtil.isEmpty(afterData)){ |
|||
|
|||
return null; |
|||
} |
|||
|
|||
if(CollUtil.isNotEmpty(befData)){ |
|||
result.setBef(JsonUtil.toJson(befData)); |
|||
} |
|||
if(CollUtil.isNotEmpty(afterData)){ |
|||
result.setAft(JsonUtil.toJson(afterData)); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
|
|||
|
|||
private List<FormWidget> getFormWidgets(Long formId){ |
|||
FormSourceResult formDetail = this.formSourceService.getFormSourceById(formId); |
|||
|
|||
Map<String, Object> formJson = JsonUtil.jsonToMap(formDetail.getFormJson()); |
|||
|
|||
assert formJson != null; |
|||
List<FormWidget> columnWidgetList = JsonUtil.jsonToList(JsonUtil.toJson(formJson.get("list")), FormWidget.class); |
|||
if(CollUtil.isEmpty(columnWidgetList)){ |
|||
|
|||
log.error("###### 数据日志 update field widget not exist ######"); |
|||
return null; |
|||
} |
|||
|
|||
return columnWidgetList; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/** |
|||
* 历史数据修复专用方法(后续会废弃) |
|||
* @param before |
|||
* @param after |
|||
* @return |
|||
*/ |
|||
@Override |
|||
public List<FormDataLog.UpdateWidgetResult> listUpdatedData(Map<String, Object> before, Map<String, Object> after) { |
|||
if(ObjectUtil.isAllNotEmpty(before,after)) { |
|||
List<FormDataLog.UpdateWidgetResult> results = new ArrayList<>(); |
|||
|
|||
after.keySet().forEach(widgetId -> { |
|||
FormDataLog.UpdateWidgetResult updateWidget = new FormDataLog.UpdateWidgetResult(widgetId); |
|||
|
|||
if(flowChangedFields.contains(widgetId)){ |
|||
DefaultConverter converter = new DefaultConverter(); |
|||
if(converter.checkChange(before.get(widgetId),after.get(widgetId))) { |
|||
String bef = new DefaultConverter().convert(before.get(widgetId), null); |
|||
String aft = new DefaultConverter().convert(after.get(widgetId), null); |
|||
updateWidget.setBef(bef); |
|||
updateWidget.setAft(aft); |
|||
|
|||
results.add(updateWidget); |
|||
} |
|||
}else{ |
|||
BaseFormFieldConverter converter = FormFieldFactory.getConverter(widgetId); |
|||
|
|||
if (converter != null) { |
|||
if(converter.checkChange(before.get(widgetId),after.get(widgetId))){ |
|||
if(!StrUtil.contains(widgetId,WidgetType.TABLE.getCode())){ |
|||
|
|||
String bData = converter.convert(before.get(widgetId), null); |
|||
|
|||
String aData = converter.convert(after.get(widgetId), null); |
|||
|
|||
updateWidget.setBef(bData); |
|||
updateWidget.setAft(aData); |
|||
}else{ |
|||
|
|||
TableConverter tableConverter = (TableConverter)converter; |
|||
tableConverter.setFormWidgets(null); |
|||
|
|||
Map<String,List<Map<String,Object>>> updatedTableData = tableConverter.listUpdateData(null,( List<Map<String,Object>>)before.get(widgetId),( List<Map<String,Object>>)after.get(widgetId)); |
|||
List<Map<String,Object>> befData = updatedTableData.get("before"); |
|||
List<Map<String,Object>> afterData = updatedTableData.get("after"); |
|||
|
|||
if(CollUtil.isNotEmpty(befData)){ |
|||
updateWidget.setBef(JsonUtil.toJson(befData)); |
|||
} |
|||
if(CollUtil.isNotEmpty(afterData)){ |
|||
updateWidget.setAft(JsonUtil.toJson(afterData)); |
|||
} |
|||
} |
|||
|
|||
results.add(updateWidget); |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
}); |
|||
|
|||
return results; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
System.out.println(" = " +JsonUtil.toJson(null) ); |
|||
} |
|||
} |
@ -1,49 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.base; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import lombok.Data; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
|
|||
import java.util.Comparator; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @Description: 表单数据转化器基类 |
|||
**/ |
|||
@Slf4j |
|||
@Data |
|||
public abstract class BaseFormFieldConverter { |
|||
|
|||
private FormWidget formWidget; |
|||
|
|||
|
|||
|
|||
public String convert(Object data, FormWidget formWidget){ |
|||
return ""; |
|||
}; |
|||
|
|||
public Boolean checkChange(Object oldValue,Object newValue) { |
|||
|
|||
return false; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 不相同时返回true |
|||
* @param oldSetData |
|||
* @param newSetData |
|||
* @return |
|||
*/ |
|||
public static boolean comparingList(List<String> oldSetData, List<String> newSetData) { |
|||
|
|||
List<String> oldData = ObjectUtil.cloneByStream(oldSetData); |
|||
List<String> newData = ObjectUtil.cloneByStream(newSetData); |
|||
|
|||
oldData.sort(Comparator.comparing(String::hashCode)); |
|||
newData.sort(Comparator.comparing(String::hashCode)); |
|||
|
|||
return !newData.toString().equals(oldData.toString()); |
|||
} |
|||
|
|||
} |
@ -1,82 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.base; |
|||
|
|||
import org.dromara.dataManager.widget.convert.column.DefaultConverter; |
|||
import org.dromara.dataManager.widget.convert.enums.FormColumnType; |
|||
import org.dromara.workflow.engine.enums.ESDefaultFieldConst; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
public class FormFieldFactory { |
|||
|
|||
private static final String packageName = "org.dromara.dataManager.convert.column.{}"; |
|||
|
|||
|
|||
public static final List<String> defaultFieldConst = Arrays.asList(ESDefaultFieldConst._ID,ESDefaultFieldConst.DID, |
|||
ESDefaultFieldConst.ID, |
|||
ESDefaultFieldConst.OWNER,ESDefaultFieldConst.CREATOR,ESDefaultFieldConst.CREATOR_ACCOUNT,ESDefaultFieldConst.CREATE_TIME, |
|||
ESDefaultFieldConst.UPDATE_TIME,ESDefaultFieldConst.UPDATOR_NAME,ESDefaultFieldConst.DELETED, |
|||
ESDefaultFieldConst.FLOW_INSTANCE_ID, ESDefaultFieldConst.FLOW_STAGE, |
|||
ESDefaultFieldConst.FLOW_TASK_ID, ESDefaultFieldConst.FLOW_NODE_TITLE, ESDefaultFieldConst.FLOW_CHECKER_NAME |
|||
); |
|||
|
|||
|
|||
public static BaseFormFieldConverter create(String columnType) throws InstantiationException, |
|||
IllegalAccessException { |
|||
FormColumnType formColumnType = FormColumnType.getByType(columnType); |
|||
|
|||
if (formColumnType == null) { |
|||
return new DefaultConverter(); |
|||
} |
|||
|
|||
String columnName = columnType.substring(0, 1).toUpperCase() + columnType.substring(1)+"Converter"; |
|||
try { |
|||
Class<?> clz = Class.forName(StrUtil.format(packageName, columnName)); |
|||
|
|||
return (BaseFormFieldConverter)clz.newInstance(); |
|||
}catch (ClassNotFoundException e){ |
|||
|
|||
return new DefaultConverter(); |
|||
} |
|||
} |
|||
|
|||
|
|||
public static BaseFormFieldConverter getConverter(String model){ |
|||
if(!model.contains("_") || defaultFieldConst.contains(model)){ |
|||
return null; |
|||
} |
|||
|
|||
String filePrefix = model.substring(0, model.lastIndexOf("_")); |
|||
|
|||
if(filePrefix.contains(".")){ |
|||
filePrefix = StrUtil.subAfter(filePrefix,".",true); |
|||
} |
|||
|
|||
FormColumnType formColumnType = FormColumnType.getByType(filePrefix); |
|||
|
|||
if (formColumnType != null) { |
|||
try{ |
|||
String columnName = filePrefix.substring(0, 1).toUpperCase() + filePrefix.substring(1)+"Converter"; |
|||
try { |
|||
Class<?> clz = Class.forName(StrUtil.format(packageName, columnName)); |
|||
|
|||
return (BaseFormFieldConverter)clz.newInstance(); |
|||
}catch (ClassNotFoundException e){ |
|||
|
|||
return new DefaultConverter(); |
|||
} |
|||
}catch (Exception e){ |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
return null; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -1,41 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.column; |
|||
|
|||
import org.dromara.dataManager.widget.convert.base.BaseFormFieldConverter; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.google.common.base.Joiner; |
|||
import java.util.List; |
|||
|
|||
public class CheckboxConverter extends BaseFormFieldConverter { |
|||
|
|||
@Override |
|||
public String convert(Object value, FormWidget widget) { |
|||
if (ObjectUtil.isEmpty(value)) { |
|||
return ""; |
|||
} |
|||
|
|||
List<String> checkBoxValue = (List<String>)value; |
|||
if(CollUtil.isNotEmpty(checkBoxValue)){ |
|||
|
|||
return Joiner.on("、").skipNulls().join(checkBoxValue); |
|||
} |
|||
|
|||
return ""; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public Boolean checkChange(Object oldValue,Object newValue) { |
|||
if(ObjectUtil.isEmpty(oldValue)){ |
|||
return ObjectUtil.isNotEmpty(newValue); |
|||
} |
|||
|
|||
if (!ObjectUtil.equal(oldValue,newValue) ) { |
|||
return true; |
|||
} |
|||
|
|||
return comparingList((List<String>)oldValue,(List<String>)newValue); |
|||
} |
|||
|
|||
} |
@ -1,96 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.column; |
|||
|
|||
|
|||
import org.dromara.dataManager.widget.convert.base.BaseFormFieldConverter; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.json.JSONObject; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public class CoordinatesConverter extends BaseFormFieldConverter { |
|||
|
|||
@Override |
|||
public String convert(Object value, FormWidget widget) { |
|||
if (ObjectUtil.isEmpty(value)) { |
|||
return ""; |
|||
} |
|||
|
|||
|
|||
if(value instanceof JSONObject) { |
|||
JSONObject data = (JSONObject)value; |
|||
|
|||
if(ObjectUtil.isNotNull(data.get("address"))){ |
|||
return (String) data.get("address"); |
|||
} |
|||
} |
|||
|
|||
if(value instanceof Map) { |
|||
Map<String, Object> data = (Map<String, Object>)value; |
|||
|
|||
if(ObjectUtil.isNotNull(data.get("address"))){ |
|||
|
|||
return (String) data.get("address"); |
|||
} |
|||
} |
|||
|
|||
return ""; |
|||
} |
|||
|
|||
@Override |
|||
public Boolean checkChange(Object oldValue,Object newValue) { |
|||
if(ObjectUtil.isAllEmpty(oldValue,newValue)){ |
|||
return false; |
|||
} |
|||
if (ObjectUtil.isEmpty(oldValue) && ObjectUtil.isNotEmpty(newValue)) { |
|||
return true; |
|||
} |
|||
if (ObjectUtil.isNotEmpty(oldValue) && ObjectUtil.isEmpty(newValue)) { |
|||
return true; |
|||
} |
|||
|
|||
if(oldValue instanceof JSONObject){ |
|||
JSONObject bef = (JSONObject)oldValue; |
|||
JSONObject aft = (JSONObject)newValue; |
|||
|
|||
JSONObject befGeoPoint = (JSONObject)bef.get("geopoint"); |
|||
JSONObject aftGeoPoint = (JSONObject)aft.get("geopoint"); |
|||
|
|||
if(!ObjectUtil.equal(befGeoPoint,aftGeoPoint) || !ObjectUtil.equal(bef.get("address"),aft.get("address"))){ |
|||
|
|||
return true; |
|||
} |
|||
|
|||
if(befGeoPoint != null && aftGeoPoint != null){ |
|||
return !(ObjectUtil.equal(bef.get("address"),aft.get("address")) |
|||
&& ObjectUtil.equal(befGeoPoint.get("lon"),aftGeoPoint.get("lon")) |
|||
&& ObjectUtil.equal(befGeoPoint.get("lat"),aftGeoPoint.get("lat"))); |
|||
} |
|||
} |
|||
|
|||
|
|||
if(oldValue instanceof Map){ |
|||
Map<String, Object> bef = (Map<String, Object>)oldValue; |
|||
Map<String, Object> aft = (Map<String, Object>)newValue; |
|||
|
|||
Map<String, Object> befGeoPoint = (Map<String, Object>)bef.get("geopoint"); |
|||
Map<String, Object> aftGeoPoint = (Map<String, Object>)aft.get("geopoint"); |
|||
|
|||
if(!ObjectUtil.equal(befGeoPoint,aftGeoPoint) || !ObjectUtil.equal(bef.get("address"),aft.get("address"))){ |
|||
|
|||
return true; |
|||
} |
|||
|
|||
if(befGeoPoint != null && aftGeoPoint != null){ |
|||
return ObjectUtil.equal(bef.get("address"),aft.get("address")) |
|||
&& ObjectUtil.equal(befGeoPoint.get("lon"),aftGeoPoint.get("lon")) |
|||
&& ObjectUtil.equal(befGeoPoint.get("lat"),aftGeoPoint.get("lat")); |
|||
} |
|||
|
|||
} |
|||
|
|||
return false; |
|||
|
|||
} |
|||
|
|||
} |
@ -1,35 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.column; |
|||
|
|||
import org.dromara.dataManager.widget.convert.base.BaseFormFieldConverter; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import java.util.HashMap; |
|||
|
|||
public class DatalinkConverter extends BaseFormFieldConverter { |
|||
|
|||
@Override |
|||
public String convert(Object value, FormWidget widget) { |
|||
if (ObjectUtil.isEmpty(value)) { |
|||
return ""; |
|||
} |
|||
|
|||
return value.toString(); |
|||
} |
|||
|
|||
@Override |
|||
public Boolean checkChange(Object oldValue,Object newValue) { |
|||
if(ObjectUtil.isAllEmpty(oldValue,newValue)){ |
|||
|
|||
return false; |
|||
} |
|||
|
|||
if(oldValue == null && ObjectUtil.isNotEmpty(newValue)){ |
|||
HashMap<String, Object> dataMap = (HashMap<String, Object>) newValue; |
|||
return StrUtil.isNotEmpty((String)dataMap.get("id")); |
|||
} |
|||
|
|||
return !ObjectUtil.equal(oldValue,newValue); |
|||
} |
|||
|
|||
} |
@ -1,150 +0,0 @@ |
|||
package org.dromara.dataManager.widget.convert.column; |
|||
|
|||
import org.dromara.dataManager.widget.convert.base.BaseFormFieldConverter; |
|||
import org.dromara.taskCenter.model.FormWidget; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.text.ParseException; |
|||
import java.text.SimpleDateFormat; |
|||
import java.util.Date; |
|||
import java.util.TimeZone; |
|||
|
|||
@Slf4j |
|||
public class DateConverter extends BaseFormFieldConverter { |
|||
|
|||
@Override |
|||
public String convert(Object value, FormWidget widget) { |
|||
if (ObjectUtil.isEmpty(value) || StrUtil.equals("null",value.toString())) { |
|||
return ""; |
|||
} |
|||
|
|||
String formatOption = "yyyy-MM-dd HH:mm:ss"; |
|||
if(widget != null){ |
|||
formatOption = (String) widget.getOptions().get("format"); |
|||
} |
|||
SimpleDateFormat defaultFormat = new SimpleDateFormat(formatOption); |
|||
|
|||
try { |
|||
String dateTime = value.toString(); |
|||
|
|||
if(StrUtil.equals("0",dateTime) || dateTime.length() == 10){ |
|||
return dateTime; |
|||
} |
|||
|
|||
return convertTime2GMT08(dateTime,defaultFormat); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
return ""; |
|||
} |
|||
|
|||
public Date converts(Object value, FormWidget widget){ |
|||
if (ObjectUtil.isEmpty(value)) { |
|||
return null; |
|||
} |
|||
String dateTime = (String)value; |
|||
dateTime = dateTime.replace("Z", " UTC"); |
|||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z"); |
|||
|
|||
try { |
|||
return format.parse(dateTime); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public Boolean checkChange(Object oldValue,Object newValue) { |
|||
if (!ObjectUtil.equal(oldValue,newValue) ) { |
|||
return true; |
|||
} |
|||
|
|||
try{ |
|||
String oldTimeValue = this.convert(oldValue,null); |
|||
String newTimeValue = this.convert(newValue,null); |
|||
|
|||
return !StrUtil.equals(oldTimeValue,newTimeValue); |
|||
|
|||
}catch (Exception e){ |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @description: 将带有0时区的字符串时间(2021-09-22T03:00:00.000Z),转换为东八区默认时间(yyyy-MM-dd HH:mm:ss) |
|||
*/ |
|||
public static String convertTime2GMT08(String time,SimpleDateFormat sdf) throws ParseException { |
|||
|
|||
//时间格式自己定义
|
|||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:sszzz"); |
|||
TimeZone tz; |
|||
|
|||
// 设置时区为"GMT+08:00"(需要输出时间的时区 )
|
|||
tz = TimeZone.getTimeZone("GMT+08:00"); |
|||
|
|||
time = time.replace("+00:00","Z"); |
|||
|
|||
String msStr = StrUtil.subBetween(time,".","Z"); |
|||
if(StrUtil.isNotEmpty(msStr)){ |
|||
time = time.replace(StrUtil.format(".{}Z",msStr), ""); |
|||
} |
|||
|
|||
// 后面的+0000为国际时间,其它时区请自行更换 (如GMT+08:00 为+0800)
|
|||
Date date = df.parse(time.replace("T"," ") + "+0000"); |
|||
|
|||
// 获取默认的DateFormat,用于格式化Date
|
|||
if(sdf == null){ |
|||
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
|||
} |
|||
|
|||
// 设置时区为tz
|
|||
sdf.setTimeZone(tz); |
|||
// 获取格式化后的字符串
|
|||
return sdf.format(date); |
|||
} |
|||
|
|||
public static String convertStr(Object date) { |
|||
String formatOption = "yyyy-MM-dd"; |
|||
SimpleDateFormat defaultFormat = new SimpleDateFormat(formatOption); |
|||
|
|||
if(date instanceof String){ |
|||
String dateTime = (String)date; |
|||
dateTime = dateTime.replace("Z", " UTC"); |
|||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z"); |
|||
try { |
|||
Date time = format.parse(dateTime); |
|||
|
|||
return defaultFormat.format(time); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
if(date instanceof Date){ |
|||
Date dateTime = (Date)date; |
|||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); |
|||
try { |
|||
return format.format(dateTime); |
|||
} catch (Exception e) { |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public static void main(String[] args) { |
|||
try{ |
|||
// "2022-02-13T16:00:00.000+00:00"
|
|||
|
|||
System.out.println(" = " + convertTime2GMT08("2022-02-13T16:00:00.123+00:00",null)); |
|||
}catch (Exception e){ |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue