新疆后端项目

This commit is contained in:
DESKTOP-BLB5287\FP
2025-06-30 14:31:09 +08:00
commit 0e52aff1f1
2596 changed files with 261030 additions and 0 deletions
@@ -0,0 +1,18 @@
package org.jeecg.annotation;
import org.jeecg.enums.RoleEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Junqiang Zhu
* @date 2023-08-15 13:15
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckRole {
RoleEnum[] value() default {RoleEnum.SECOND_MANAGER, RoleEnum.THIRD_MANAGER, RoleEnum.ADMIN_MANAGER};
}
@@ -0,0 +1,41 @@
package org.jeecg.annotation;
import org.jeecg.enums.DbColumnEnum;
import org.jeecg.enums.DbColumnNameEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 字段对应db
*
* @author Junqiang Zhu
* @since 2023-10-25
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBColumnInfo {
/**
* 开发者自定义字段释义 PS:该字段有值时 不会再取值 commonName()
*/
String diyName() default "";
/**
*常用通用的释义
* @see DbColumnNameEnum
*/
DbColumnNameEnum commonName() default DbColumnNameEnum.DEFAULT_NAME;
/**
* 字段类型
* @see DbColumnEnum
*/
DbColumnEnum columnType() default DbColumnEnum.VARCHAR;
/**
*字段长度
*/
int len() default 0;
}
@@ -0,0 +1,49 @@
package org.jeecg.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.jeecg.enums.DesensitizationTypeEnum;
import org.jeecg.enums.PrivacyTypeEnum;
import org.jeecg.filter.DesensitizationSerializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerializer.class)
public @interface Desensitization {
/**
* 脱敏的隐私数据类型
*/
PrivacyTypeEnum dataType();
/**
* 脱敏方式,默认方式不需要定义下面脱敏长度等信息,根据脱敏的隐私数据类型自动脱敏
*/
DesensitizationTypeEnum mode() default DesensitizationTypeEnum.DEFAULT;
/**
* 尾部不脱敏的长度,当mode为HEAD或MIDDLE时使用
*/
int tailNoMaskLen() default 1;
/**
* 头部不脱敏的长度,当mode为TAIL或MIDDLE时使用
*/
int headNoMaskLen() default 1;
/**
* 中间不脱敏的长度,当mode为HEAD_TAIL时使用
*/
int middleNoMaskLen() default 1;
/**
* 打码
*/
char maskCode() default '*';
}
@@ -0,0 +1,15 @@
package org.jeecg.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Junqiang Zhu
* @date 2023-08-03 13:49
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeStat {
}
@@ -0,0 +1,85 @@
package org.jeecg.annotation.aspect;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.annotation.CheckRole;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.enums.RoleEnum;
import org.jeecg.global.GlobalUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 方法耗时统计切面
*
* @author Junqiang Zhu
* @date 2023-08-15 13:51
*/
@Component
@Aspect
@Slf4j
public class CheckRoleAspect {
@Pointcut("@annotation(org.jeecg.annotation.CheckRole)")
public void checkRolePointcut() {
}
@Around("checkRolePointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
LoginUser loginUser = GlobalUtils.getLoginUser();
if (StrUtil.isBlank(loginUser.getRoleCodes())) {
return GlobalUtils.getResult(false, "不是(二级/三级)管理员", null);
}
// 获取方法签名
Signature signature = point.getSignature();
// 获取方法对象
Method method = ((MethodSignature) signature).getMethod();
// 获取方法上的CheckRole注解
CheckRole checkRoleAnnotation = method.getAnnotation(CheckRole.class);
if (checkRoleAnnotation == null) {
return GlobalUtils.getResult(false, "不是(二级/三级)管理员", null);
}
boolean havaRole = checkRole(checkRoleAnnotation.value(), loginUser.getRoleCodes());
if (!havaRole) {
return GlobalUtils.getResult(false, "不是(二级/三级)管理员", null);
}
return point.proceed();
}
private boolean checkRole(RoleEnum[] roles, String roleCodes) {
if (isEmpty(roles)) {
return true;
}
String[] loginUserRoles = roleCodes.split(",");
if (isEmpty(loginUserRoles)) {
return false;
}
for (String str : loginUserRoles) {
for (RoleEnum role : roles) {
if (str.equals(role.get())) {
return true;
}
}
}
return false;
}
private <T> boolean isEmpty(T[] ts) {
return ts == null || ts.length == 0;
}
}
@@ -0,0 +1,37 @@
package org.jeecg.annotation.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
* 方法耗时统计切面
*
* @author Junqiang Zhu
* @date 2023-08-15 13:51
*/
@Component
@Aspect
@Slf4j
public class TimeStatAspect {
@Pointcut("@annotation(org.jeecg.annotation.TimeStat)")
public void timeStatPointcut() {
}
@Around("timeStatPointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = point.proceed();
long end = System.currentTimeMillis();
String methodName = point.getSignature().getName();
log.info("{{}}--总共耗时:{}秒", methodName, BigDecimal.valueOf(end - start).movePointLeft(3));
return proceed;
}
}
@@ -0,0 +1,41 @@
package org.jeecg.base;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Shunzhi Jiang
* @since 2024/10/5
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Criteria {
Mode value() default Mode.EQ;
String property() default "";
Class<?>[] groups() default {ListGroup.Default.class};
enum Mode {
/**
* 匹配模式
*/
EQ,
NE,
IN,
NOT_IN,
GT,
LT,
GE,
LE,
LIKE,
LIKE_LEFT,
LIKE_RIGHT,
IS_NULL,
IS_NOT_NULL;
}
}
@@ -0,0 +1,61 @@
package org.jeecg.base;
import cn.hutool.core.util.StrUtil;
/**
* @author Junqiang Zhu
* @since 2024-08-19 09:46
*/
public interface FillBase {
// 部门信息
default String getOrgCode() {
return "";
}
default void setSecondDepart(String departName) {
}
default void setThirdDepart(String departName) {
}
// 用户基本信息
default String getUserId() {
return "";
}
default void setRealName(String realName) {
}
default void setSex(String sex) {
}
default void setWorkNo(String workNo) {
}
default void setIdCard(String idCard) {
}
default void setUserName(String userName) {
}
default void setMobile(String mobile) {
}
default void setAge(Integer age) {
}
default void setOrgCode(String orgCode) {
}
default String getRealName() {
return StrUtil.EMPTY;
}
default String getWorkNo() {
return StrUtil.EMPTY;
}
}
@@ -0,0 +1,21 @@
package org.jeecg.base;
/**
* @author Shunzhi Jiang
* @since 2024/10/5
*/
public interface ListFilter<T> {
default String getColumn() {
return "createTime";
}
;
default String getOrder() {
return "DESC";
}
;
}
@@ -0,0 +1,14 @@
package org.jeecg.base;
/**
* @author Shunzhi Jiang
* @since 2024/10/5
*/
public @interface ListGroup {
Class<?>[] value() default {Default.class};
interface Default {
}
}
@@ -0,0 +1,49 @@
package org.jeecg.base;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
/**
* @author Shunzhi Jiang
* @since 2024/8/25
*/
@Data
public abstract class PageInfo<T> implements ListFilter<T>, Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "分页大小", defaultValue = "10")
private Integer pageSize = 10;
@Schema(description = "查询页码", defaultValue = "1")
private Integer pageNo = 1;
@Schema(description = "排序字段", defaultValue = "createTime")
private String column = "createTime";
@Schema(description = "排序规则", defaultValue = "desc")
private String order = "desc";
public Integer getPageSize() {
if (Objects.isNull(pageSize)) {
setPageSize(10);
}
return pageSize;
}
public Integer getPageNo() {
if (Objects.isNull(pageNo)) {
setPageNo(1);
}
return pageNo;
}
public Page<T> getPage() {
return Page.of(getPageNo(), getPageSize());
}
}
@@ -0,0 +1,65 @@
package org.jeecg.base;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author Junqiang Zhu
* @since 2024-08-21 17:13
*/
@Data
public class UserBase implements FillBase {
private String userId;
private String userName;
@Excel(name = "姓名", orderNum = "0")
private String realName;
@Dict(dicCode = "sex2")
@Excel(name = "性别", dicCode = "sex2", orderNum = "1")
private String sex;
@Excel(name = "工号", orderNum = "3")
private String workNo;
private String idCard;
@Excel(name = "年龄", orderNum = "2")
private Integer age;
private String mobile;
private String orgCode;
@Dict(dicCode = "user_status")
private String status;
// 部门信息
@Excel(name = "单位", orderNum = "4")
private String secondDepart;
@Excel(name = "部门", orderNum = "5")
private String thirdDepart;
private String depart;
// 身高
private String heightNew;
// 体重
private String weightNew;
// 腰围
private BigDecimal waistNew;
// 体脂率
private BigDecimal fatRateNew;
// bmi
private Double bmiNew;
// 生日
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
// 昵称
private String nickname;
// 体力活动水平
@Dict(dicCode = "physical_activity")
private String physicalActivity;
// 基础代谢率
private BigDecimal basalMetabolicRate;
}
@@ -0,0 +1,130 @@
package org.jeecg.cloud;
import org.jeecg.common.constant.ServiceNameConstants;
import org.jeecg.modules.exports.entity.CommonExportsInfo;
import org.jeecg.modules.imports.entity.CommonImports;
import org.jeecg.modules.imports.entity.CommonImportsDetail;
import org.jeecg.modules.imports.entity.CommonImportsInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* @author Jiang Shunzhi
*/
@Component
@FeignClient(
contextId = "SysImportExportApi",
url = "${renkang.service-url.system:}",
value = ServiceNameConstants.SERVICE_SYSTEM,
fallback = ImportExportApiFallback.class
)
public interface ImportExportApi {
/**
* 修改导出信息
*
* @param info 通用导入导出主表实体
* @return 用户信息
*/
@PostMapping("/sys/common/commonExportsInfo/editInfo")
CommonExportsInfo updateExportsInfo(@RequestBody CommonExportsInfo info);
/**
* @param id 通用导出信息id
* @return 通用导出信息
*/
@GetMapping("/sys/common/commonExportsInfo/query")
CommonExportsInfo getExportsInfoById(@RequestParam String id);
/**
* 通过code与exportStatus 判断是否已完成
*
* @param code
* @param exportStatus
* @return
*/
@GetMapping("/sys/common/commonExportsInfo/getFinishFlagByCode")
Boolean getFinishFlagByCode(@RequestParam String code, @RequestParam String exportStatus);
//增加接口,查询所有中执行中的任务,而不只查自己启动的任务,本接口适用于大批量的公共的数据任务,比如病种勾选
@GetMapping("/sys/common/commonExportsInfo/getFinishFlagByCodeInAll")
Boolean getFinishFlagByCodeInAll(@RequestParam String code, @RequestParam String exportStatus);
/**
* 保存导入信息子表实体list
*
* @param list 导入信息子表实体list
* @return
*/
@PostMapping(value = "/saveInfoList")
Boolean saveInfoList(List<CommonImportsInfo> list);
//通用导入相关功能======================================start
/**
* 通用文件导入信息
*
* @param info
* @return
*/
@PostMapping("/sys/common/commonImports/editInfo")
CommonImports updateImportsInfo(@RequestBody CommonImports info);
/**
* 根据ID查询通用文件导入信息
*
* @param id
* @return
*/
@GetMapping("/sys/common/commonImports/query")
CommonImports getImportsInfoById(@RequestParam String id);
/**
* 根据code和状态查询是否已完成
*
* @param code
* @param importStatus
* @return
*/
@GetMapping("/sys/common/commonImports/getImportsFinishFlagByCode")
Boolean getImportsFinishFlagByCode(@RequestParam String code, @RequestParam String importStatus);
/**
* 保存/修改导入通用详细信息
*
* @param detail
*/
@PostMapping("/sys/common/commonImportsDetail/editDetail")
void editImportsDetail(@RequestBody CommonImportsDetail detail);
@PostMapping("/sys/common/commonImportsDetail/saveDetailList")
void saveImportsDetailList(@RequestBody List<CommonImportsDetail> detailList);
/**
* 根据ID查询导入详细信息
*
* @param id
* @return
*/
@GetMapping("/sys/common/commonImportsDetail/query")
CommonImportsDetail getImportsDetailById(@RequestParam String id);
/**
* 根据ID查询导入详细信息
*
* @param infoId
* @return
*/
@GetMapping("/sys/common/commonImportsDetail/queryByInfoId")
List<CommonImportsDetail> getImportsDetailListByInfoId(@RequestParam String infoId);
}
@@ -0,0 +1,77 @@
package org.jeecg.cloud;
import org.jeecg.modules.exports.entity.CommonExportsInfo;
import org.jeecg.modules.imports.entity.CommonImports;
import org.jeecg.modules.imports.entity.CommonImportsDetail;
import org.jeecg.modules.imports.entity.CommonImportsInfo;
import java.util.Collections;
import java.util.List;
/**
* @author Jiang Shunzhi
*/
public class ImportExportApiFallback implements ImportExportApi {
@Override
public CommonExportsInfo updateExportsInfo(CommonExportsInfo info) {
return null;
}
@Override
public CommonExportsInfo getExportsInfoById(String id) {
return null;
}
@Override
public Boolean getFinishFlagByCode(String code, String exportStatus) {
return null;
}
@Override
public Boolean getFinishFlagByCodeInAll(String code, String exportStatus) {
return false;
}
@Override
public Boolean saveInfoList(List<CommonImportsInfo> list) {
return false;
}
@Override
public CommonImports updateImportsInfo(CommonImports info) {
return null;
}
@Override
public CommonImports getImportsInfoById(String id) {
return null;
}
@Override
public Boolean getImportsFinishFlagByCode(String code, String importStatus) {
return false;
}
@Override
public void editImportsDetail(CommonImportsDetail detail) {
}
@Override
public void saveImportsDetailList(List<CommonImportsDetail> detailList) {
}
@Override
public CommonImportsDetail getImportsDetailById(String id) {
return null;
}
@Override
public List<CommonImportsDetail> getImportsDetailListByInfoId(String infoId) {
return Collections.emptyList();
}
}
@@ -0,0 +1,26 @@
package org.jeecg.cloud;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author Jiang Shunzhi
*/
@Component
@ConfigurationProperties("renkang")
public class ServiceUrlProperties {
private Map<String, String> serviceUrl = new HashMap<>();
public Map<String, String> getServiceUrl() {
return serviceUrl;
}
public void setServiceUrl(Map<String, String> serviceUrl) {
this.serviceUrl = serviceUrl;
}
}
@@ -0,0 +1,146 @@
package org.jeecg.common.api;
import org.jeecg.common.system.vo.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 通用api 强制全部重新打包
*
* @author: jeecg-boot
*/
public interface CommonAPI {
/**
* 1查询用户角色信息
* 发一版
*
* @param userId
* @return 则好烦好烦
*/
Set<String> queryUserRoles(String userId);
/**
* 2查询用户权限信息
*
* @param userId
* @return 啊啊啊
*/
Set<String> queryUserAuths(String userId);
/**
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel
*
* @param dbSourceId
* @return
*/
DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId);
/**
* 4根据 code 查询数据库中存储的 DynamicDataSourceModel
*
* @param dbSourceCode
* @return
*/
DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode);
/**
* 5根据用户账号查询用户信息
*
* @param username
* @return
*/
public LoginUser getUserByName(String username);
public LoginUser getUserById(String id);
/**
* 6字典表的 翻译
*
* @param table
* @param text
* @param code
* @param key
* @return
*/
String translateDictFromTable(String table, String text, String code, String key);
/**
* 7普通字典的翻译
*
* @param code
* @param key
* @return
*/
String translateDict(String code, String key);
/**
* 8查询数据权限
*
* @param component 组件
* @param userId 用户
* @param requestPath 前段请求地址
* @return
*/
List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String userId);
/**
* 9查询用户信息
*
* @param userId
* @return
*/
SysUserCacheInfo getCacheUser(String userId);
/**
* 10获取数据字典
*
* @param code
* @return
*/
public List<DictModel> queryDictItemsByCode(String code);
/**
* 获取有效的数据字典项
*
* @param code
* @return
*/
public List<DictModel> queryEnableDictItemsByCode(String code);
/**
* 13获取表数据字典
*
* @param table
* @param text
* @param code
* @return
*/
List<DictModel> queryTableDictItemsByCode(String table, String text, String code);
/**
* 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
*
* @param dictCodes 例如:user_status,sex
* @param keys 例如:1,2,0
* @return
*/
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
/**
* 15 字典表的 翻译,可批量
*
* @param table
* @param text
* @param code
* @param keys 多个用逗号分割
* @return
*/
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys);
}
@@ -0,0 +1,30 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 大病dto
*
* @author Junqiang Zhu
* @date 2024-04-12 14:40
*/
@Data
public class BigIllFakerData {
@NotNull(message = "高危不能为空")
private Integer highRisk;
@NotNull(message = "中危不能为空")
private Integer centerRisk;
@NotNull(message = "低危不能为空")
private Integer lowRisk;
public int getTotal() {
if (highRisk == null || centerRisk == null || lowRisk == null) {
return 0;
}
return highRisk + centerRisk + lowRisk;
}
}
@@ -0,0 +1,36 @@
package org.jeecg.common.api.dto;
import lombok.Data;
/**
* @Author taoYan
* @Date 2022/7/26 14:44
**/
@Data
public class DataLogDTO {
private String tableName;
private String dataId;
private String content;
private String type;
public DataLogDTO() {
}
public DataLogDTO(String tableName, String dataId, String content, String type) {
this.tableName = tableName;
this.dataId = dataId;
this.content = content;
this.type = type;
}
public DataLogDTO(String tableName, String dataId, String type) {
this.tableName = tableName;
this.dataId = dataId;
this.type = type;
}
}
@@ -0,0 +1,33 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
/**
* 文件下载
* cloud api 用到的接口传输对象
*
* @author: jeecg-boot
*/
@Data
public class FileDownDTO implements Serializable {
private static final long serialVersionUID = 6749126258686446019L;
private String filePath;
private String uploadpath;
private String uploadType;
private HttpServletResponse response;
public FileDownDTO() {
}
public FileDownDTO(String filePath, String uploadpath, String uploadType, HttpServletResponse response) {
this.filePath = filePath;
this.uploadpath = uploadpath;
this.uploadType = uploadType;
this.response = response;
}
}
@@ -0,0 +1,59 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
/**
* 文件上传
* cloud api 用到的接口传输对象
*
* @author: jeecg-boot
*/
@Data
public class FileUploadDTO implements Serializable {
private static final long serialVersionUID = -4111953058578954386L;
private MultipartFile file;
private String bizPath;
private String uploadType;
private String customBucket;
public FileUploadDTO() {
}
/**
* 简单上传 构造器1
*
* @param file
* @param bizPath
* @param uploadType
*/
public FileUploadDTO(MultipartFile file, String bizPath, String uploadType) {
this.file = file;
this.bizPath = bizPath;
this.uploadType = uploadType;
}
/**
* 申明桶 文件上传 构造器2
*
* @param file
* @param bizPath
* @param uploadType
* @param customBucket
*/
public FileUploadDTO(MultipartFile file, String bizPath, String uploadType, String customBucket) {
this.file = file;
this.bizPath = bizPath;
this.uploadType = uploadType;
this.customBucket = customBucket;
}
}
@@ -0,0 +1,29 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* 服务详情dto
* 正常 警戒 危险 心率
*
* @author Junqiang Zhu
* @since 2024-04-12 14:40
*/
@Data
public class HouseWatchFakerData {
@NotNull(message = "血氧正常值不能为空")
private BigDecimal bloodOxygenNormal;
@NotNull(message = "血氧告警值不能为空")
private BigDecimal bloodOxygenWarn;
@NotNull(message = "血氧异常不能为空")
private BigDecimal bloodOxygenDanger;
@NotNull(message = "心率正常值不能为空")
private BigDecimal heartRateNormal;
@NotNull(message = "心率告警值不能为空")
private BigDecimal heartRateWarn;
@NotNull(message = "心率异常不能为空")
private BigDecimal heartRateDanger;
}
@@ -0,0 +1,97 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import org.jeecg.common.system.vo.LoginUser;
import java.io.Serializable;
import java.util.Date;
/**
* 日志对象
* cloud api 用到的接口传输对象
*
* @author: jeecg-boot
*/
@Data
public class LogDTO implements Serializable {
private static final long serialVersionUID = 8482720462943906924L;
/**
* 内容
*/
private String logContent;
/**
* 日志类型(0:操作日志;1:登录日志;2:定时任务)
*/
private Integer logType;
/**
* 操作类型(1:添加;2:修改;3:删除;)
*/
private Integer operateType;
/**
* 登录用户
*/
private LoginUser loginUser;
private String id;
private String createBy;
private Date createTime;
private Long costTime;
private String ip;
/**
* 请求参数
*/
private String requestParam;
/**
* 请求类型
*/
private String requestType;
/**
* 请求路径
*/
private String requestUrl;
/**
* 请求方法
*/
private String method;
/**
* 操作人用户名称
*/
private String username;
/**
* 操作人用户账户
*/
private String userid;
/**
* 租户ID
*/
private Integer tenantId;
public LogDTO() {
}
public LogDTO(String logContent, Integer logType, Integer operatetype) {
this.logContent = logContent;
this.logType = logType;
this.operateType = operatetype;
}
public LogDTO(String logContent, Integer logType, Integer operatetype, LoginUser loginUser) {
this.logContent = logContent;
this.logType = logType;
this.operateType = operatetype;
this.loginUser = loginUser;
}
}
@@ -0,0 +1,29 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 体检dto
*
* @author Junqiang Zhu
* @date 2024-04-12 14:40
*/
@Data
public class MedicalFakerData {
@NotNull(message = "兴隆医院数据不能为空")
private Integer xl;
@NotNull(message = "泾河医院数据不能为空")
private Integer jh;
@NotNull(message = "宁夏宝石花医院数据不能为空")
private Integer nx;
@NotNull(message = "庆阳医院数据不能为空")
private Integer qy;
@NotNull(message = "延安市人民医院数据不能为空")
private Integer ya;
@NotNull(message = "西京医院数据不能为空")
private Integer xj;
private String centerId;
}
@@ -0,0 +1,43 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* online 拦截器权限判断
* cloud api 用到的接口传输对象
*
* @author: jeecg-boot
*/
@Data
public class OnlineAuthDTO implements Serializable {
private static final long serialVersionUID = 1771827545416418203L;
/**
* 用户名
*/
private String username;
/**
* 可能的请求地址
*/
private List<String> possibleUrl;
/**
* online开发的菜单地址
*/
private String onlineFormUrl;
public OnlineAuthDTO() {
}
public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl) {
this.username = username;
this.possibleUrl = possibleUrl;
this.onlineFormUrl = onlineFormUrl;
}
}
@@ -0,0 +1,40 @@
package org.jeecg.common.api.dto;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Getter;
import lombok.Setter;
/**
* @author Jiang Shunzhi
*/
@Setter
@Getter
public class PageExtra<T, U> extends Page<T> {
protected U extra;
public PageExtra() {
}
public PageExtra(long current, long size) {
super(current, size);
}
public PageExtra(long current, long size, long total) {
super(current, size, total);
}
public PageExtra(long current, long size, boolean searchCount) {
super(current, size, searchCount);
}
public PageExtra(long current, long size, long total, boolean searchCount) {
super(current, size, total, searchCount);
}
public PageExtra<T, U> extra(U extra) {
this.extra = extra;
return this;
}
}
@@ -0,0 +1,29 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 服务详情dto
*
* @author Junqiang Zhu
* @date 2024-04-12 14:40
*/
@Data
public class ServiceFakerData {
@NotNull(message = "最新呼入电话不能为空")
private Integer latestCall;
@NotNull(message = "最新受理电话不能为空")
private Integer latestAcceptCall;
@NotNull(message = "突发重大伤病应急不能为空")
private Integer illNum;
@NotNull(message = "重大伤病应急就医不能为空")
private Integer emergencyNum;
@NotNull(message = "累计受理不能为空")
private Integer totalAccept;
@NotNull(message = "累计处置不能为空")
private Integer totalDisposal;
private String centerId;
}
@@ -0,0 +1,27 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 银川一线医疗点dto
*
* @author Junqiang Zhu
* @date 2024-04-12 14:40
*/
@Data
public class YcMedicalCenterFakerData {
@NotBlank(message = "医疗点名称不能为空")
private String name;
@NotNull(message = "高风险干预人数不能为空")
private Integer high;
@NotNull(message = "慢病管理人数不能为空")
private Integer slow;
@NotNull(message = "巡诊人数不能为空")
private Integer tour;
@NotNull(message = "排序不能为空")
private Integer order;
}
@@ -0,0 +1,34 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 银川用户健康dto
*
* @author Junqiang Zhu
* @date 2024-04-12 14:40
*/
@Data
public class YcUserHealthFakerData {
@NotNull(message = "重大疾病人数不能为空")
private Integer bigIll;
@NotNull(message = "健康高风险人数不能为空")
private Integer highRisk;
@NotNull(message = "慢病人数不能为空")
private Integer slowIll;
@NotNull(message = "重点指标异常不能为空")
private Integer focusErr;
@NotNull(message = "健康人数不能为空")
private Integer health;
private String centerId;
public Integer getTotal() {
if (bigIll == null || highRisk == null || slowIll == null || focusErr == null || health == null) {
return null;
}
return bigIll + highRisk + slowIll + focusErr + health;
}
}
@@ -0,0 +1,47 @@
package org.jeecg.common.api.dto.message;
import lombok.Data;
import java.io.Serializable;
/**
* 带业务参数的消息
*
* @author: taoyan
* @date: 2022/8/17
*/
@Data
public class BusMessageDTO extends MessageDTO implements Serializable {
private static final long serialVersionUID = 9104793287983367669L;
/**
* 业务类型
*/
private String busType;
/**
* 业务id
*/
private String busId;
public BusMessageDTO() {
}
/**
* 构造 带业务参数的消息
*
* @param fromUser
* @param toUser
* @param title
* @param msgContent
* @param msgCategory
* @param busType
* @param busId
*/
public BusMessageDTO(String fromUser, String toUser, String title, String msgContent, String msgCategory, String busType, String busId) {
super(fromUser, toUser, title, msgContent, msgCategory);
this.busId = busId;
this.busType = busType;
}
}
@@ -0,0 +1,92 @@
package org.jeecg.common.api.dto.message;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 带业务参数的模板消息
*
* @author: jeecg-boot
*/
@Data
public class BusTemplateMessageDTO extends TemplateMessageDTO implements Serializable {
private static final long serialVersionUID = -4277810906346929459L;
/**
* 业务类型
*/
private String busType;
/**
* 业务id
*/
private String busId;
private boolean isMultipart = false;//默认单发,群发和单发只在发送时区分处理,保存时不影响
private List<String> phones;//定义群发手机号组
private boolean isAllowRepet = true;//是否允许重复,默认允许,该字段需和busTyp和busId一起判断,如业务类型和业务ID不全,则允许重复
public BusTemplateMessageDTO() {
}
/**
* 构造 带业务参数的模板消息
*
* @param fromUser
* @param toUser
* @param title
* @param templateParam
* @param templateCode
* @param busType
* @param busId
*/
public BusTemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode, String busType, String busId) {
super(fromUser, toUser, title, templateParam, templateCode);
this.busId = busId;
this.busType = busType;
}
public BusTemplateMessageDTO(String fromUser, String toUser, Map<String, String> templateParam, String templateCode, String busId) {
super(fromUser, toUser, "", templateParam, templateCode);
this.busId = busId;
}
public BusTemplateMessageDTO(String fromUser, String toUser, Map<String, String> templateParam, String templateCode,String busType, String busId) {
super(fromUser, toUser, "", templateParam, templateCode);
this.busId = busId;
this.busType = busType;
}
public BusTemplateMessageDTO(String fromUser, String toUser, Map<String, String> templateParam, String templateCode,String busType, String busId, boolean isAllowRepet) {
super(fromUser, toUser, "", templateParam, templateCode);
this.busId = busId;
this.busType = busType;
this.isAllowRepet = isAllowRepet;
}
/**
* 群发对象处理
* @param fromUser
* @param phones
* @param templateParam
* @param templateCode
* @param busType
* @param busId
*/
public BusTemplateMessageDTO(String fromUser, List<String> phones, Map<String, String> templateParam, String templateCode, String busType, String busId) {
this.isMultipart = true;
this.phones = phones;
this.fromUser = fromUser;
this.title = "";
this.templateParam = templateParam;
this.templateCode = templateCode;
this.busId = busId;
this.busType = busType;
this.isAllowRepet = false;
}
}
@@ -0,0 +1,115 @@
package org.jeecg.common.api.dto.message;
import lombok.Data;
import org.jeecg.common.constant.CommonConstant;
import java.io.Serializable;
import java.util.Map;
/**
* 普通消息
*
* @author: jeecg-boot
*/
@Data
public class MessageDTO implements Serializable {
private static final long serialVersionUID = -5690444483968058442L;
/**
* 发送人(用户登录账户)
*/
protected String fromUser;
/**
* 发送给(用户登录账户)
*/
protected String toUser;
/**
* 发送给所有人
*/
protected Boolean toAll;
/**
* 消息主题
*/
protected String title;
/**
* 消息内容
*/
protected String content;
/**
* 消息类型 1:消息 2:系统消息
*/
protected String category;
//-----------------------------------------------------------------------
//update-begin---author:taoyan ---date:20220705 for:支持自定义推送类型,邮件、钉钉、企业微信、系统消息-----------
/**
* 模板消息对应的模板编码
*/
protected String templateCode;
/**
* 消息类型:org.jeecg.common.constant.enums.MessageTypeEnum
* XT("system", "系统消息")
* YJ("email", "邮件消息")
* DD("dingtalk", "钉钉消息")
* QYWX("wechat_enterprise", "企业微信")
*/
protected String type;
/**
* 是否发送Markdown格式的消息
*/
protected boolean isMarkdown;
/**
* 解析模板内容 对应的数据
*/
protected Map<String, Object> data;
//update-end---author:taoyan ---date::20220705 for:支持自定义推送类型,邮件、钉钉、企业微信、系统消息-----------
//-----------------------------------------------------------------------
/**
* 抄送人
*/
private String copyToUser;
public MessageDTO() {
}
/**
* 构造器1 系统消息
*/
public MessageDTO(String fromUser, String toUser, String title, String content) {
this.fromUser = fromUser;
this.toUser = toUser;
this.title = title;
this.content = content;
//默认 都是2系统消息
this.category = CommonConstant.MSG_CATEGORY_2;
}
/**
* 构造器2 支持设置category 1:消息 2:系统消息
*/
public MessageDTO(String fromUser, String toUser, String title, String content, String category) {
this.fromUser = fromUser;
this.toUser = toUser;
this.title = title;
this.content = content;
this.category = category;
}
public boolean isMarkdown() {
return this.isMarkdown;
}
public void setIsMarkdown(boolean isMarkdown) {
this.isMarkdown = isMarkdown;
}
}
@@ -0,0 +1,39 @@
package org.jeecg.common.api.dto.message;
import lombok.Data;
import java.io.Serializable;
import java.util.Map;
/**
* 消息模板dto
*
* @author: jeecg-boot
*/
@Data
public class TemplateDTO implements Serializable {
private static final long serialVersionUID = 5848247133907528650L;
/**
* 模板编码
*/
protected String templateCode;
/**
* 模板参数
*/
protected Map<String, String> templateParam;
/**
* 构造器 通过设置模板参数和模板编码 作为参数获取消息内容
*/
public TemplateDTO(String templateCode, Map<String, String> templateParam) {
this.templateCode = templateCode;
this.templateParam = templateParam;
}
public TemplateDTO() {
}
}
@@ -0,0 +1,50 @@
package org.jeecg.common.api.dto.message;
import lombok.Data;
import java.io.Serializable;
import java.util.Map;
/**
* 模板消息
*
* @author: jeecg-boot
*/
@Data
public class TemplateMessageDTO extends TemplateDTO implements Serializable {
private static final long serialVersionUID = 411137565170647585L;
/**
* 发送人(用户登录账户)
*/
protected String fromUser;
/**
* 发送给(用户登录账户)
*/
protected String toUser;
/**
* 消息主题
*/
protected String title;
public TemplateMessageDTO() {
}
/**
* 构造器1 发模板消息用
*/
public TemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode) {
super(templateCode, templateParam);
this.fromUser = fromUser;
this.toUser = toUser;
this.title = title;
}
}
@@ -0,0 +1,178 @@
package org.jeecg.common.api.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.Data;
import org.jeecg.common.constant.CommonConstant;
import java.io.Serializable;
/**
* 接口返回数据格式
*
* @author scott
* @email jeecgos@163.com
* @date 2019年1月19日
*/
@Data
@Schema(title = "接口返回对象", description = "接口返回对象")
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标志
*/
@Schema(title = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@Schema(title = "返回处理消息")
private String message = "";
/**
* 返回代码
*/
@Schema(title = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@Schema(title = "返回数据对象")
private T result;
/**
* 时间戳
*/
@Schema(title = "时间戳")
private long timestamp = System.currentTimeMillis();
@JsonIgnore
private String onlTable;
public Result() {
}
/**
* 兼容VUE3版token失效不跳转登录页面
*
* @param code
* @param message
*/
public Result(Integer code, String message) {
this.code = code;
this.message = message;
}
public static <T> Result<T> ok() {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
return r;
}
public static <T> Result<T> ok(String msg) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
//Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D
r.setResult((T) msg);
r.setMessage(msg);
return r;
}
public static <T> Result<T> ok(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setResult(data);
return r;
}
public static <T> Result<T> OK() {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
return r;
}
/**
* 此方法是为了兼容升级所创建
*
* @param msg
* @param <T>
* @return
*/
public static <T> Result<T> OK(String msg) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage(msg);
//Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D
r.setResult((T) msg);
return r;
}
public static <T> Result<T> OK(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setResult(data);
return r;
}
public static <T> Result<T> OK(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static <T> Result<T> error(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(false);
r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static <T> Result<T> error(String msg) {
return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
}
public static <T> Result<T> error(int code, String msg) {
Result<T> r = new Result<T>();
r.setCode(code);
r.setMessage(msg);
r.setSuccess(false);
return r;
}
/**
* 无权限访问返回结果
*/
public static <T> Result<T> noauth(String msg) {
return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
}
public Result<T> success(String message) {
this.message = message;
this.code = CommonConstant.SC_OK_200;
this.success = true;
return this;
}
public Result<T> error500(String message) {
this.message = message;
this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
this.success = false;
return this;
}
}
@@ -0,0 +1,258 @@
package org.jeecg.common.aspect;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.PropertyFilter;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ModuleType;
import org.jeecg.common.constant.enums.OperateTypeEnum;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IpUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 系统日志,切面处理类
*
* @Author scott
* @email jeecgos@163.com
* @Date 2018年1月14日
*/
@Aspect
@Component
public class AutoLogAspect {
@Resource
private BaseCommonService baseCommonService;
@Pointcut("@annotation(org.jeecg.common.aspect.annotation.AutoLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time, result);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogDTO dto = new LogDTO();
AutoLog syslog = method.getAnnotation(AutoLog.class);
if (syslog != null) {
//update-begin-author:taoyan date:
String content = syslog.value();
if (syslog.module() == ModuleType.ONLINE) {
content = getOnlineLogContent(obj, content);
}
//注解上的描述,操作日志内容
dto.setLogType(syslog.logType());
dto.setLogContent(content);
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
dto.setMethod(className + "." + methodName + "()");
//设置操作类型
if (CommonConstant.LOG_TYPE_2 == dto.getLogType()) {
dto.setOperateType(getOperateType(methodName, syslog.operateType()));
}
//获取request
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
//请求的参数
dto.setRequestParam(getReqestParams(request, joinPoint));
//设置IP地址
dto.setIp(IpUtils.getIpAddr(request));
//获取登录用户信息
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if (sysUser != null) {
dto.setUserid(sysUser.getUsername());
dto.setUsername(sysUser.getRealname());
}
//耗时
dto.setCostTime(time);
dto.setCreateTime(new Date());
//保存系统日志
baseCommonService.addLog(dto);
}
/**
* 获取操作类型
*/
private int getOperateType(String methodName, int operateType) {
if (operateType > 0) {
return operateType;
}
//update-begin---author:wangshuai ---date:20220331 for:阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
return OperateTypeEnum.getTypeByMethodName(methodName);
//update-end---author:wangshuai ---date:20220331 for:阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
}
/**
* @param request: request
* @param joinPoint: joinPoint
* @Description: 获取请求参数
* @author: scott
* @date: 2020/4/16 0:10
* @Return: java.lang.String
*/
private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
String httpMethod = request.getMethod();
String params = "";
if (CommonConstant.HTTP_POST.equals(httpMethod) || CommonConstant.HTTP_PUT.equals(httpMethod) || CommonConstant.HTTP_PATCH.equals(httpMethod)) {
Object[] paramsArray = joinPoint.getArgs();
// java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
// https://my.oschina.net/mengzhang6/blog/2395893
Object[] arguments = new Object[paramsArray.length];
for (int i = 0; i < paramsArray.length; i++) {
if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile) {
//ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
//ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
continue;
}
arguments[i] = paramsArray[i];
}
//update-begin-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
PropertyFilter profilter = new PropertyFilter() {
@Override
public boolean apply(Object o, String name, Object value) {
int length = 500;
if (value != null && value.toString().length() > length) {
return false;
}
return true;
}
};
params = JSONObject.toJSONString(arguments, profilter);
//update-end-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
} else {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 请求的方法参数值
Object[] args = joinPoint.getArgs();
// 请求的方法参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
for (int i = 0; i < args.length; i++) {
params += " " + paramNames[i] + ": " + args[i];
}
}
}
return params;
}
/**
* online日志内容拼接
*
* @param obj
* @param content
* @return
*/
private String getOnlineLogContent(Object obj, String content) {
if (Result.class.isInstance(obj)) {
Result res = (Result) obj;
String msg = res.getMessage();
String tableName = res.getOnlTable();
if (oConvertUtils.isNotEmpty(tableName)) {
content += ",表名:" + tableName;
}
if (res.isSuccess()) {
content += "," + (oConvertUtils.isEmpty(msg) ? "操作成功" : msg);
} else {
content += "," + (oConvertUtils.isEmpty(msg) ? "操作失败" : msg);
}
}
return content;
}
/* private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
AutoLog syslog = method.getAnnotation(AutoLog.class);
if(syslog != null){
//update-begin-author:taoyan date:
String content = syslog.value();
if(syslog.module()== ModuleType.ONLINE){
content = getOnlineLogContent(obj, content);
}
//注解上的描述,操作日志内容
sysLog.setLogContent(content);
sysLog.setLogType(syslog.logType());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//设置操作类型
if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {
sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
}
//获取request
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
//请求的参数
sysLog.setRequestParam(getReqestParams(request,joinPoint));
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//获取登录用户信息
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
if(sysUser!=null){
sysLog.setUserid(sysUser.getUsername());
sysLog.setUsername(sysUser.getRealname());
}
//耗时
sysLog.setCostTime(time);
sysLog.setCreateTime(new Date());
//保存系统日志
sysLogService.save(sysLog);
}*/
}
@@ -0,0 +1,437 @@
package org.jeecg.common.aspect;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @Description: 字典aop类
* @Author: dangzhenghui
* @Date: 2019-3-17 21:50
* @Version: 1.0
*/
@Aspect
//@Component
@Slf4j
public class DictAspect {
private static final String JAVA_UTIL_DATE = "java.util.Date";
@Autowired
public RedisTemplate redisTemplate;
@Lazy
@Autowired
private CommonAPI commonApi;
@Autowired
private ObjectMapper objectMapper;
/**
* 定义切点Pointcut
*/
@Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..)) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)")
public void excudeService() {
}
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time1 = System.currentTimeMillis();
Object result = pjp.proceed();
long time2 = System.currentTimeMillis();
log.debug("获取JSON数据 耗时:" + (time2 - time1) + "ms");
long start = System.currentTimeMillis();
result = this.parseDictText(result);
long end = System.currentTimeMillis();
log.debug("注入字典到JSON数据 耗时" + (end - start) + "ms");
return result;
}
/**
* 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
* 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 table字典 code table text配合使用与原来jeecg的用法相同
* 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端
* 例输入当前返回值的就会多出一个sex_dictText字段
* {
* sex:1,
* sex_dictText:"男"
* }
* 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
* customRender:function (text) {
* if(text==1){
* return "男";
* }else if(text==2){
* return "女";
* }else{
* return text;
* }
* }
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
*
* @param result
*/
@SuppressWarnings("rawtypes")
private Object parseDictText(Object result) {
if (!(result instanceof Result) || !(((Result) result).getResult() instanceof IPage)) {
return result;
}
List records = ((IPage) ((Result) result).getResult()).getRecords();
if (CollectionUtils.isEmpty(records)) {
return result;
}
//step.1 筛选出加了 Dict 注解的字段列表
List<Field> dictFieldList = getDictAnnotations(records.get(0));
if (CollectionUtils.isEmpty(dictFieldList)) {
return result;
}
List<JSONObject> items = new ArrayList<>();
// 字典数据列表, key = 字典code,value=数据列表
Map<String, List<String>> dataListMap = new HashMap<>(5);
//取出结果集
log.debug(" __ 进入字典翻译切面 DictAspect —— ");
for (Object record : records) {
String json = "{}";
try {
//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = objectMapper.writeValueAsString(record);
//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
} catch (JsonProcessingException e) {
log.error("json解析失败" + e.getMessage(), e);
}
//update-begin--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----
JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);
//update-end--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----
//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
//for (Field field : record.getClass().getDeclaredFields()) {
// 遍历所有字段,把字典Code取出来,放到 map 里
for (Field field : oConvertUtils.getAllFields(record)) {
String value = item.getString(field.getName());
if (oConvertUtils.isEmpty(value)) {
continue;
}
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
if (field.getAnnotation(Dict.class) != null) {
if (!dictFieldList.contains(field)) {
dictFieldList.add(field);
}
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
List<String> dataList;
String dictCode = code;
if (!StringUtils.isEmpty(table)) {
dictCode = String.format("%s,%s,%s", table, text, code);
}
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
}
//date类型默认转换string格式化日期
//update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
//if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
//SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
//}
//update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错-----
}
items.add(item);
}
//step.2 调用翻译方法,一次性翻译
Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
//step.3 将翻译结果填充到返回结果里
for (JSONObject record : items) {
for (Field field : dictFieldList) {
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
String fieldDictCode = code;
if (!StringUtils.isEmpty(table)) {
fieldDictCode = String.format("%s,%s,%s", table, text, code);
}
String value = record.getString(field.getName());
if (oConvertUtils.isNotEmpty(value)) {
List<DictModel> dictModels = translText.get(fieldDictCode);
if (dictModels == null || dictModels.size() == 0) {
continue;
}
String textValue = this.translDictText(dictModels, value);
log.debug(" 字典Val : " + textValue);
log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + " " + textValue);
// TODO-sun 测试输出,待删
log.debug(" ---- dictCode: " + fieldDictCode);
log.debug(" ---- value: " + value);
log.debug(" ----- text: " + textValue);
log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
}
}
}
((IPage) ((Result) result).getResult()).setRecords(items);
return result;
}
/**
* list 去重添加
*/
private void listAddAllDeduplicate(List<String> dataList, List<String> addList) {
// 筛选出dataList中没有的数据
List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList());
dataList.addAll(filterList);
}
/**
* 一次性把所有的字典都翻译了
* 1. 所有的普通数据字典的所有数据只执行一次SQL
* 2. 表字典相同的所有数据只执行一次SQL
*
* @param dataListMap
* @return
*/
private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) {
// 翻译后的字典文本,key=dictCode
Map<String, List<DictModel>> translText = new HashMap<>(5);
// 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询)
List<String> needTranslData = new ArrayList<>();
//step.1 先通过redis中获取缓存字典数据
for (String dictCode : dataListMap.keySet()) {
List<String> dataList = dataListMap.get(dictCode);
if (dataList.size() == 0) {
continue;
}
// 表字典需要翻译的数据
List<String> needTranslDataTable = new ArrayList<>();
for (String s : dataList) {
String data = s.trim();
if (data.length() == 0) {
continue; //跳过循环
}
if (dictCode.contains(",")) {
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data);
if (redisTemplate.hasKey(keyString)) {
try {
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.add(new DictModel(data, text));
} catch (Exception e) {
log.warn(e.getMessage());
}
} else if (!needTranslDataTable.contains(data)) {
// 去重添加
needTranslDataTable.add(data);
}
} else {
String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data);
if (redisTemplate.hasKey(keyString)) {
try {
String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.add(new DictModel(data, text));
} catch (Exception e) {
log.warn(e.getMessage());
}
} else if (!needTranslData.contains(data)) {
// 去重添加
needTranslData.add(data);
}
}
}
//step.2 调用数据库翻译表字典
if (needTranslDataTable.size() > 0) {
String[] arr = dictCode.split(",");
String table = arr[0], text = arr[1], code = arr[2];
String values = String.join(",", needTranslDataTable);
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
log.debug("translateDictFromTableByKeys.values:" + values);
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values);
log.debug("translateDictFromTableByKeys.result:" + texts);
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.addAll(texts);
// 做 redis 缓存
for (DictModel dict : texts) {
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
try {
// update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
// 保留5分钟
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
// update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
}
}
//step.3 调用数据库进行翻译普通字典
if (needTranslData.size() > 0) {
List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{}));
// 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典
List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList());
String dictCodes = String.join(",", filterDictCodes);
String values = String.join(",", needTranslData);
log.debug("translateManyDict.dictCodes:" + dictCodes);
log.debug("translateManyDict.values:" + values);
Map<String, List<DictModel>> manyDict = commonApi.translateManyDict(dictCodes, values);
log.debug("translateManyDict.result:" + manyDict);
for (String dictCode : manyDict.keySet()) {
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
List<DictModel> newList = manyDict.get(dictCode);
list.addAll(newList);
// 做 redis 缓存
for (DictModel dict : newList) {
String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue());
try {
redisTemplate.opsForValue().set(redisKey, dict.getText());
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
}
}
return translText;
}
/**
* 字典值替换文本
*
* @param dictModels
* @param values
* @return
*/
private String translDictText(List<DictModel> dictModels, String values) {
List<String> result = new ArrayList<>();
// 允许多个逗号分隔,允许传数组对象
String[] splitVal = values.split(",");
for (String val : splitVal) {
String dictText = val;
for (DictModel dict : dictModels) {
if (val.equals(dict.getValue())) {
dictText = dict.getText();
break;
}
}
result.add(dictText);
}
return String.join(",", result);
}
/**
* 翻译字典文本
*
* @param code
* @param text
* @param table
* @param key
* @return
*/
// @Deprecated
// private String translateDictValue(String code, String text, String table, String key) {
// if (oConvertUtils.isEmpty(key)) {
// return null;
// }
// StringBuffer textValue = new StringBuffer();
// String[] keys = key.split(",");
// for (String k : keys) {
// String tmpValue = null;
// log.debug(" 字典 key : " + k);
// if (k.trim().length() == 0) {
// continue; //跳过循环
// }
// //update-begin--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
// if (!StringUtils.isEmpty(table)) {
// log.debug("--DictAspect------dicTable=" + table + " ,dicText= " + text + " ,dicCode=" + code);
// String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]", table, text, code, k.trim());
// if (redisTemplate.hasKey(keyString)) {
// try {
// tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
// } catch (Exception e) {
// log.warn(e.getMessage());
// }
// } else {
// tmpValue = commonApi.translateDictFromTable(table, text, code, k.trim());
// }
// } else {
// String keyString = String.format("sys:cache:dict::%s:%s", code, k.trim());
// if (redisTemplate.hasKey(keyString)) {
// try {
// tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
// } catch (Exception e) {
// log.warn(e.getMessage());
// }
// } else {
// tmpValue = commonApi.translateDict(code, k.trim());
// }
// }
// //update-end--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
//
// if (tmpValue != null) {
// if (!"".equals(textValue.toString())) {
// textValue.append(",");
// }
// textValue.append(tmpValue);
// }
//
// }
// return textValue.toString();
// }
/**
* 检测返回结果集中是否包含Dict注解
*
* @param records
* @return
*/
private Boolean checkHasDict(List<Object> records) {
if (oConvertUtils.isNotEmpty(records) && records.size() > 0) {
for (Field field : oConvertUtils.getAllFields(records.get(0))) {
if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) {
return true;
}
}
}
return false;
}
private List<Field> getDictAnnotations(Object object) {
return Arrays.stream(oConvertUtils.getAllFields(object))
.filter(field -> oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class)))
.collect(Collectors.toList());
}
}
@@ -0,0 +1,84 @@
package org.jeecg.common.aspect;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.aspect.annotation.LimitSubmit;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
@Aspect
@Slf4j
public class LimitSubmitAspect {
@Autowired
private RedisUtil redisUtil;
@Pointcut("@annotation(org.jeecg.common.aspect.annotation.LimitSubmit)")
private void pointcut() {
}
@Around("pointcut()")
public Object handleSubmit(ProceedingJoinPoint joinPoint) throws Throwable {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
//获取注解信息
LimitSubmit limitSubmit = method.getAnnotation(LimitSubmit.class);
int submitTimeLimiter = limitSubmit.limit();
String redisKey = limitSubmit.key();
boolean needAllWait = limitSubmit.needAllWait();
String key = getRedisKey(sysUser, joinPoint, redisKey);
Object result = redisUtil.get(key);
if (result != null) {
throw new JeecgBootException("请勿重复访问!");
}
redisUtil.set(key, sysUser.getId(), submitTimeLimiter);
try {
Object proceed = joinPoint.proceed();
return proceed;
} catch (Throwable e) {
log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e);
throw e;
} finally {
if (!needAllWait) {
redisUtil.del(redisKey);
}
}
}
/**
* 支持多参数,从请求参数进行处理
*/
private String getRedisKey(LoginUser sysUser, ProceedingJoinPoint joinPoint, String key) {
if (key.contains("%s")) {
key = String.format(key, sysUser.getId());
}
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = discoverer.getParameterNames(method);
if (parameterNames != null) {
for (int i = 0; i < parameterNames.length; i++) {
String item = parameterNames[i];
if (key.contains("#" + item)) {
key = key.replace("#" + item, joinPoint.getArgs()[i].toString());
}
}
}
return key.toString();
}
}
@@ -0,0 +1,145 @@
package org.jeecg.common.aspect;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JeecgDataAutorUtils;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
/**
* 数据权限切面处理类
* 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
*
* @Date 2019年4月10日
* @Version: 1.0
* @author: jeecg-boot
*/
@Aspect
@Component
@Slf4j
public class PermissionDataAspect {
private static final String SPOT_DO = ".do";
@Lazy
@Autowired
private CommonAPI commonApi;
@Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)")
public void pointCut() {
}
@Around("pointCut()")
public Object arround(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
PermissionData pd = method.getAnnotation(PermissionData.class);
String component = pd.pageComponent();
String requestMethod = request.getMethod();
String requestPath = request.getRequestURI().substring(request.getContextPath().length());
requestPath = filterUrl(requestPath);
//update-begin-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效
//先判断是否online报表请求
// TODO 参数顺序调整有隐患
if (requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl()) >= 0) {
// 获取地址栏参数
String urlParamString = request.getParameter(CommonConstant.ONL_REP_URL_PARAM_STR);
if (oConvertUtils.isNotEmpty(urlParamString)) {
requestPath += "?" + urlParamString;
}
}
//update-end-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效
log.info("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod);
// String userId = JwtUtil.getUserIdByToken(request);
LoginUser loginUser =(LoginUser) SecurityUtils.getSubject().getPrincipal();
String userId = loginUser.getId();
//查询数据权限信息
//TODO 微服务情况下也得支持缓存机制
List<SysPermissionDataRuleModel> dataRules = commonApi.queryPermissionDataRule(component, requestPath, userId);
if (dataRules != null && dataRules.size() > 0) {
//临时存储
JeecgDataAutorUtils.installDataSearchConditon(request, dataRules);
//TODO 微服务情况下也得支持缓存机制
SysUserCacheInfo userinfo = commonApi.getCacheUser(userId);
JeecgDataAutorUtils.installUserInfo(request, userinfo);
}
return point.proceed();
}
private String filterUrl(String requestPath) {
String url = "";
if (oConvertUtils.isNotEmpty(requestPath)) {
url = requestPath.replace("\\", "/");
url = url.replace("//", "/");
if (url.indexOf(SymbolConstant.DOUBLE_SLASH) >= 0) {
url = filterUrl(url);
}
/*if(url.startsWith("/")){
url=url.substring(1);
}*/
}
return url;
}
/**
* 获取请求地址
*
* @param request
* @return
*/
@Deprecated
private String getJgAuthRequsetPath(HttpServletRequest request) {
String queryString = request.getQueryString();
String requestPath = request.getRequestURI();
if (oConvertUtils.isNotEmpty(queryString)) {
requestPath += "?" + queryString;
}
// 去掉其他参数(保留一个参数) 例如:loginController.do?login
if (requestPath.indexOf(SymbolConstant.AND) > -1) {
requestPath = requestPath.substring(0, requestPath.indexOf("&"));
}
if (requestPath.indexOf(QueryRuleEnum.EQ.getValue()) != -1) {
if (requestPath.indexOf(SPOT_DO) != -1) {
requestPath = requestPath.substring(0, requestPath.indexOf(".do") + 3);
} else {
requestPath = requestPath.substring(0, requestPath.indexOf("?"));
}
}
// 去掉项目路径
requestPath = requestPath.substring(request.getContextPath().length() + 1);
return filterUrl(requestPath);
}
@Deprecated
private boolean moHuContain(List<String> list, String key) {
for (String str : list) {
if (key.contains(str)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,78 @@
package org.jeecg.common.aspect;
/**
* @Author scott
* @Date 2020/1/14 13:36
* @Description: 请求URL与菜单路由URL转换规则(方便于采用菜单路由URL来配置数据权限规则)
*/
public enum UrlMatchEnum {
/**
* 求URL与菜单路由URL转换规则 /online/cgform/api/getData/
*/
CGFORM_DATA("/online/cgform/api/getData/", "/online/cgformList/"),
/**
* 求URL与菜单路由URL转换规则 /online/cgform/api/exportXls/
*/
CGFORM_EXCEL_DATA("/online/cgform/api/exportXls/", "/online/cgformList/"),
/**
* 求URL与菜单路由URL转换规则 /online/cgform/api/getTreeData/
*/
CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"),
/**
* 求URL与菜单路由URL转换规则 /online/cgreport/api/getColumnsAndData/
*/
CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"),
/**
* 求URL与菜单路由URL转换规则 /online/cgreport/api/exportXls/
*/
CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/"),
/**
* 求URL与菜单路由URL转换规则 /online/cgreport/api/exportManySheetXls/
*/
CGREPORT_EXCEL_DATA2("/online/cgreport/api/exportManySheetXls/", "/online/cgreport/");
/**
* Request 请求 URL前缀
*/
private String url;
/**
* 菜单路由 URL前缀 (对应菜单路径)
*/
private String matchUrl;
UrlMatchEnum(String url, String matchUrl) {
this.url = url;
this.matchUrl = matchUrl;
}
/**
* 根据req url 获取到菜单配置路径(前端页面路由URL)
*
* @param url
* @return
*/
public static String getMatchResultByUrl(String url) {
//获取到枚举
UrlMatchEnum[] values = UrlMatchEnum.values();
//加强for循环进行遍历操作
for (UrlMatchEnum lr : values) {
//如果遍历获取的type和参数type一致
if (url.indexOf(lr.url) != -1) {
//返回type对象的desc
return url.replace(lr.url, lr.matchUrl);
}
}
return null;
}
public String getMatchUrl() {
return matchUrl;
}
// public static void main(String[] args) {
// /**
// * 比如request真实请求URL: /online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a
// * 转换匹配路由URL后(对应配置的菜单路径):/online/cgformList/81fcf7d8922d45069b0d5ba983612d3a
// */
// System.out.println(UrlMatchEnum.getMatchResultByUrl("/online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a"));
// }
}
@@ -0,0 +1,24 @@
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.*;
/**
* 通过此注解声明的接口,自动实现字典翻译
*
* @Author scott
* @email jeecgos@163.com
* @Date 2022年01月05日
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoDict {
/**
* 暂时无用
*
* @return
*/
String value() default "";
}
@@ -0,0 +1,47 @@
package org.jeecg.common.aspect.annotation;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ModuleType;
import java.lang.annotation.*;
/**
* 系统日志注解
*
* @Author scott
* @email jeecgos@163.com
* @Date 2019年1月14日
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoLog {
/**
* 日志内容
*
* @return
*/
String value() default "";
/**
* 日志类型
*
* @return 0:操作日志;1:登录日志;2:定时任务;
*/
int logType() default CommonConstant.LOG_TYPE_2;
/**
* 操作日志类型
*
* @return (1查询,2添加,3修改,4删除)
*/
int operateType() default 0;
/**
* 模块类型 默认为common
*
* @return
*/
ModuleType module() default ModuleType.COMMON;
}
@@ -0,0 +1,33 @@
package org.jeecg.common.aspect.annotation;
import org.jeecg.common.constant.enums.LowAppAopEnum;
import java.lang.annotation.*;
/**
* 自动注入low_app_id
*
* @Author scott
* @email jeecgos@163.com
* @Date 2022年01月05日
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoLowApp {
/**
* 切面类型(add、delete、db_import等其他操作)
*
* @return
*/
LowAppAopEnum action();
/**
* 业务类型(cgform等)
*
* @return
*/
String bizType();
}
@@ -0,0 +1,43 @@
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 字典注解
*
* @author: dangzhenghui
* @date: 2019年03月17日-下午9:37:16
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {
/**
* 方法描述: 数据code
* 作 者: dangzhenghui
* 日 期: 2019年03月17日-下午9:37:16
*
* @return 返回类型: String
*/
String dicCode();
/**
* 方法描述: 数据Text
* 作 者: dangzhenghui
* 日 期: 2019年03月17日-下午9:37:16
*
* @return 返回类型: String
*/
String dicText() default "";
/**
* 方法描述: 数据字典表
* 作 者: dangzhenghui
* 日 期: 2019年03月17日-下午9:37:16
*
* @return 返回类型: String
*/
String dictTable() default "";
}
@@ -0,0 +1,27 @@
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LimitSubmit {
String key();
/**
* 默认 10s
*/
int limit() default 10;
/**
* 请求完成后 是否一直等待
* true则等待
*
* @return
*/
boolean needAllWait() default true;
}
@@ -0,0 +1,21 @@
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.*;
/**
* online请求拦截专用注解
*
* @author: jeecg-boot
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface OnlineAuth {
/**
* 请求关键字,在xxx/code之前的字符串
*
* @return
*/
String value();
}
@@ -0,0 +1,27 @@
package org.jeecg.common.aspect.annotation;
import java.lang.annotation.*;
/**
* 数据权限注解
*
* @Author taoyan
* @Date 2019年4月11日
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface PermissionData {
/**
* 暂时没用
*
* @return
*/
String value() default "";
/**
* 配置菜单的组件路径,用于数据权限
*/
String pageComponent() default "";
}
@@ -0,0 +1,26 @@
package org.jeecg.common.bean;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
/**
* 推荐范围
* @author stan
* @since 2025-03-31 10:45
*/
@Getter
@Setter
public class Recommended {
private BigDecimal max;
private BigDecimal min;
private BigDecimal data;
public String toStr(){
if(null != max && null != min){
return min + "~" + max;
}
return null;
}
}
@@ -0,0 +1,19 @@
package org.jeecg.common.bean.request;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 综合分析
* @author stan
* @since 2024-11-16 10:06
*/
@Getter
@Setter
public class DataUserGroupReq {
private List<String> orgCodes;
private List<String> params;
private String userGroup;
}
@@ -0,0 +1,17 @@
package org.jeecg.common.bean.request;
import lombok.Getter;
import lombok.Setter;
import java.util.Set;
/**
* @author stan
* @since 2025-03-06 13:04
*/
@Getter
@Setter
public class SendSmsReq {
private String param;
private Set<String> userIds;
}
@@ -0,0 +1,19 @@
package org.jeecg.common.bean.request;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 综合分析
* @author stan
* @since 2024-11-16 10:06
*/
@Getter
@Setter
public class StatAllReq {
private List<String> userGroups;
private List<String> params;
private List<String> orgCodes;
}
@@ -0,0 +1,18 @@
package org.jeecg.common.bean.request;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author stan
* @since 2024-11-16 10:06
*/
@Getter
@Setter
public class StatReq {
private List<String> orgCodes;
private List<String> params;
private String userGroup;
}
@@ -0,0 +1,18 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
* @author stan
* @since 2025-01-09 13:38
*/
@Getter
@Setter
public class BaseUserGroup {
private String id;
private String userGroup;
private Date userGroupUpdateTime;
}
@@ -0,0 +1,44 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import org.jeecg.annotation.DBColumnInfo;
import org.jeecg.enums.DbColumnNameEnum;
/**
* 部门统计数据
*
* @author stan
* @since 2024-11-21 09:52
*/
@Getter
@Setter
public class DepartDataShow {
private String id;
private String orgCode;
private String departName;
private String address;
private String mobile;
private String fax;
@DBColumnInfo(commonName = DbColumnNameEnum.USER_DEPT)
private String thirdDepartName;
// 健康管理员
private String healthManageUserName;
private String healthManageUserMobile;
private String healthManageUserAddress;
// 职业体检员
private String medialManageUserName;
private String medialManageUserMobile;
private String medialManageUserAddress;
// 健康监测员
private String monitorManageUserName;
private String monitorManageUserMobile;
private String memo;
// 是否有下级
private boolean haveChild;
}
@@ -0,0 +1,27 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
/**
* 部门统计数据
*
* @author stan
* @since 2024-11-21 09:52
*/
@Getter
@Setter
public class DepartStat {
private String id;
private String name;
private String orgCode;
private String address;
private String mobile;
private int childNum;
private int userNum;
private BigDecimal longitude;
private BigDecimal latitude ;
}
@@ -0,0 +1,18 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 未签到人员类型
* @author stan
* @since 2025-03-17 14:59
*/
@Getter
@Setter
public class NotSignType {
private String userId;
private List<String> notSigns;
}
@@ -0,0 +1,19 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
/**
* 饼图
* @author stan
* @since 2024-11-15 11:17
*/
@Getter
@Setter
public class PieChart {
private String name;
private Object value;
private BigDecimal ratio;
}
@@ -0,0 +1,19 @@
package org.jeecg.common.bean.response;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 柱状图
* @author stan
* @since 2024-11-15 11:18
*/
@Getter
@Setter
public class PillarChart {
private String name;
private List<Object> data;
private List<PieChart> charts;
}
@@ -0,0 +1,26 @@
package org.jeecg.common.bean.response;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.math.BigDecimal;
import java.util.List;
/**
* @author stan
* @since 2024-11-15 14:15
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class TotalPieChart {
// 总计数据
private BigDecimal total;
// 图表数据
private List<PieChart> chart;
}
@@ -0,0 +1,20 @@
package org.jeecg.common.bean.transfer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @author stan
* @since 2024-11-15 14:31
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class GroupCount {
private String code;
private String name;
private Integer count;
}
@@ -0,0 +1,25 @@
package org.jeecg.common.bean.transfer;
import lombok.Getter;
import lombok.Setter;
/**
* @author stan
* @since 2025-04-18 14:40
*/
@Getter
@Setter
public class UserEatFlag {
private String idCard;
private Integer breakfast;
private Integer lunch;
private Integer dinner;
private Boolean sign;
public Boolean getSign() {
int breakfastFlag = breakfast == null ? 0 : breakfast;
int lunchFlag = lunch == null ? 0 : lunch;
int dinnerFlag = dinner == null ? 0 : dinner;
return breakfastFlag == 1 || lunchFlag == 1 || dinnerFlag == 1;
}
}
@@ -0,0 +1,17 @@
package org.jeecg.common.bean.transfer;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author stan
* @since 2025-04-18 14:40
*/
@Getter
@Setter
public class UserEatParam {
private List<String> idCards;
private String day;
}
@@ -0,0 +1,22 @@
package org.jeecg.common.bean.transfer;
import lombok.Getter;
import lombok.Setter;
/**
* @author stan
* @since 2025-04-18 10:37
*/
@Getter
@Setter
public class UserWeightSign {
private String userId;
private String idCard;
private String mobile;
// 体重打卡
private Boolean weightSign = false;
// 吃打卡
private Boolean eatSign = false;
// 运动打卡
private Boolean playSign = false;
}
@@ -0,0 +1,724 @@
package org.jeecg.common.constant;
/**
* @Description: 通用常量
* @author: jeecg-boot
*/
public interface CommonConstant {
// 用户总数
String TOTAL_USER_NUM = "total:user:";
// 表结构信息
String TABLE_INFO_PREFIX = "tableInfo:";
// 医护人员类型
String MEDICAL_STAFF_PERSON_TYPE = "15";
String CANCER_DATE_KEY = "cancerDate";
String ASSESS_DATE_KEY = "assessDate";
String MAN = "2";
String WOMAN = "1";
Integer FOUR = 4;
// 体重管理已经设置目标人员
String SELF_TARGET = "intervene:weight:self:user";
// 审核状态(0:待处理 2:拒绝转入 1:同意转入)
String APPLY_STATUS_0 = "0";
String APPLY_STATUS_1 = "1";
String APPLY_STATUS_2 = "2";
// rest
String REST = "/rest";
// 二级部门管理员code
String SECOND_MANAGER = "second_manager";
// 身份证号码正则表达式
String ID_CORD_REGULAR = "^[1-9]\\d{5}(18|19|20)\\d{2}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}[0-9Xx]$";
// 字典翻译字段后缀
String DICT_TR_SUFFIX = "_dictText";
// 人员类型 医生
String PERSON_TYPE_DOCTOR_10 = "10";
// 人员类型 医院管理员
String PERSON_TYPE_DOCTOR_9 = "9";
// 人员类型 大屏分中心管理员
String PERSON_TYPE_DOCTOR_16 = "16";
// 人员类型 大屏分中心登录账号
String PERSON_TYPE_DOCTOR_17 = "17";
// 操作人员
String PERSON_TYPE_DOCTOR_5 = "5";
// 专业人员
String PERSON_TYPE_DOCTOR_6 = "6";
// 员工
String PERSON_TYPE_DOCTOR_1 = "1";
// 员工家属
String PERSON_TYPE_FAMILY_MEMBERS = "22";
/**
* 部门code查询
*/
String DEPART_FIND_TYPE_CODE = "code";
/**
* 部门id查询
*/
String DEPART_FIND_TYPE_ID = "id";
/**
* 否
*/
String NO = "0";
/**
* 是
*/
String YES = "1";
/**
* 系统配置redis key
*/
String SYS_CACHE_CONFIG_KEY = "sys:config:";
/**
* 系统字典
*/
String SYS_CACHE_DICT_KEY = "sys:dict";
/**
* 默认密码
*/
String DEFAULT_PWD = "Aa123456";
/**
* 分类相关 category
*/
String TOP_CATEGORY = "0";
/**
* 科室
*/
String OFFICE = "科室";
String CATEGORY_REDIS_KEY = "sys:category:";
String DEPART_REDIS_KEY = "sys:depart:code:";
String CONSULT_DEPARTMENT = "consult:department:";
String DEPART_REDIS_ID_KEY = "sys:depart:id:";
/**
* 节假日
*/
String CONSULT_HOLIDAY_KEY = "consult:holiday:";
String INTERVENE_EXERCISE_MATCH = "intervene:exercise:match:";
/**
* 正常状态
*/
Integer STATUS_NORMAL = 0;
/**
* 禁用状态
*/
Integer STATUS_DISABLE = -1;
/**
* 删除标志
*/
Integer DEL_FLAG_1 = 1;
/**
* 未删除
*/
Integer DEL_FLAG_0 = 0;
/**
* 系统日志类型: 登录
*/
int LOG_TYPE_1 = 1;
/**
* 系统日志类型: 操作
*/
int LOG_TYPE_2 = 2;
/**
* 操作日志类型: 查询
*/
int OPERATE_TYPE_1 = 1;
/**
* 操作日志类型: 添加
*/
int OPERATE_TYPE_2 = 2;
/**
* 操作日志类型: 更新
*/
int OPERATE_TYPE_3 = 3;
/**
* 操作日志类型: 删除
*/
int OPERATE_TYPE_4 = 4;
/**
* 操作日志类型: 倒入
*/
int OPERATE_TYPE_5 = 5;
/**
* 操作日志类型: 导出
*/
int OPERATE_TYPE_6 = 6;
/**
* {@code 500 Server Error} (HTTP/1.0 - RFC 1945)
*/
Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
/**
* {@code 200 OK} (HTTP/1.0 - RFC 1945)
*/
Integer SC_OK_200 = 200;
/**
* 访问权限认证未通过 510
*/
Integer SC_JEECG_NO_AUTHZ = 510;
/**
* 登录用户Shiro权限缓存KEY前缀
*/
public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:";
/**
* 登录用户Token令牌缓存KEY前缀
*/
String PREFIX_USER_TOKEN = "prefix_user_token:";
// /** Token缓存时间:3600秒即一小时 */
// int TOKEN_EXPIRE_TIME = 3600;
/**
* 登录二维码
*/
String LOGIN_QRCODE_PRE = "QRCODELOGIN:";
String LOGIN_QRCODE = "LQ:";
/**
* 登录二维码token
*/
String LOGIN_QRCODE_TOKEN = "LQT:";
String FAKE_TOKEN_KEY_PREFIX = "test:fake:token:";
String FAKE_USER_KEY_PREFIX = "test:fake:user:";
/**
* 0:一级菜单
*/
Integer MENU_TYPE_0 = 0;
/**
* 1:子菜单
*/
Integer MENU_TYPE_1 = 1;
/**
* 2:按钮权限
*/
Integer MENU_TYPE_2 = 2;
/**
* 通告对象类型(USER:指定用户,ALL:全体用户,ALL_DOC:全体专家,DOC:指定专家)
*/
String MSG_TYPE_USER = "USER";
String MSG_TYPE_ALL = "ALL";
String MSG_TYPE_ALL_DOC = "ALL_DOC";
String MSG_TYPE_DOC = "DOC";
Integer MSG_BATCH_NUM = 10;//批量发送短信最大条数
String ES_TYPE_1 = "1";//短信单发
String ES_TYPE_2 = "2";//短信群发
/**
* 发布状态(0未发布,1已发布,2已撤销)
*/
String NO_SEND = "0";
String HAS_SEND = "1";
String HAS_CANCLE = "2";
/**
* 阅读状态(0未读,1已读)
*/
String HAS_READ_FLAG = "1";
String NO_READ_FLAG = "0";
/**
* 优先级(L低,M中,H高)
*/
String PRIORITY_L = "L";
String PRIORITY_M = "M";
String PRIORITY_H = "H";
/**
* 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板
*/
String SMS_TPL_TYPE_0 = "0";
String SMS_TPL_TYPE_1 = "1";
String SMS_TPL_TYPE_2 = "2";
/**
* 状态(0无效1有效 2:冻结 3:封存 4:注销)
*/
String STATUS_0 = "0";
String STATUS_1 = "1";
String STATUS_2 = "2";
String STATUS_3 = "3";
String STATUS_4 = "4";
/**
* 同步工作流引擎1同步0不同步
*/
Integer ACT_SYNC_1 = 1;
Integer ACT_SYNC_0 = 0;
/**
* 消息类型1:通知公告2:系统消息
*/
String MSG_CATEGORY_1 = "1";
String MSG_CATEGORY_2 = "2";
/**
* 是否配置菜单的数据权限 1是0否
*/
Integer RULE_FLAG_0 = 0;
Integer RULE_FLAG_1 = 1;
/**
* 是否用户已被冻结 1正常(解冻) 2冻结 3离职
*/
Integer USER_UNFREEZE = 1;
Integer USER_FREEZE = 2;
Integer USER_QUIT = 3;
/**
* 字典翻译文本后缀
*/
String DICT_TEXT_SUFFIX = "_dictText";
/**
* 表单设计器主表类型
*/
Integer DESIGN_FORM_TYPE_MAIN = 1;
/**
* 表单设计器子表表类型
*/
Integer DESIGN_FORM_TYPE_SUB = 2;
/**
* 表单设计器URL授权通过
*/
Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
/**
* 表单设计器URL授权未通过
*/
Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
/**
* 表单设计器新增 Flag
*/
String DESIGN_FORM_URL_TYPE_ADD = "add";
/**
* 表单设计器修改 Flag
*/
String DESIGN_FORM_URL_TYPE_EDIT = "edit";
/**
* 表单设计器详情 Flag
*/
String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
/**
* 表单设计器复用数据 Flag
*/
String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
/**
* 表单设计器编辑 Flag (已弃用)
*/
String DESIGN_FORM_URL_TYPE_VIEW = "view";
/**
* online参数值设置(是:Y, 否:N)
*/
String ONLINE_PARAM_VAL_IS_TURE = "Y";
String ONLINE_PARAM_VAL_IS_FALSE = "N";
/**
* 文件上传类型(本地:localMiniominio,阿里云:alioss
*/
String UPLOAD_TYPE_LOCAL = "local";
String UPLOAD_TYPE_MINIO = "minio";
String UPLOAD_TYPE_OSS = "alioss";
String UPLOAD_TYPE_MY_UPLOAD = "myupload";
/**
* 文档上传自定义桶名称
*/
String UPLOAD_CUSTOM_BUCKET = "eoafile";
/**
* 文档上传自定义路径
*/
String UPLOAD_CUSTOM_PATH = "eoafile";
/**
* 文件外链接有效天数
*/
Integer UPLOAD_EFFECTIVE_DAYS = 1;
/**
* 员工身份 (1:普通员工 2:上级)
*/
Integer USER_IDENTITY_1 = 1;
Integer USER_IDENTITY_2 = 2;
/**
* sys_user 表 username 唯一键索引
*/
String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
/**
* sys_user 表 work_no 唯一键索引
*/
String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
/**
* sys_user 表 phone 唯一键索引
*/
String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
/**
* 达梦数据库升提示。违反表[SYS_USER]唯一性约束
*/
String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束";
/**
* sys_user 表 email 唯一键索引
*/
String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
/**
* sys_quartz_job 表 job_class_name 唯一键索引
*/
String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
/**
* sys_position 表 code 唯一键索引
*/
String SQL_INDEX_UNIQ_CODE = "uniq_code";
/**
* sys_role 表 code 唯一键索引
*/
String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
/**
* sys_depart 表 code 唯一键索引
*/
String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
/**
* sys_category 表 code 唯一键索引
*/
String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code";
/**
* 在线聊天 是否为默认分组
*/
String IM_DEFAULT_GROUP = "1";
/**
* 在线聊天 图片文件保存路径
*/
String IM_UPLOAD_CUSTOM_PATH = "biz/user_imgs";
/**
* 在线聊天 用户状态
*/
String IM_STATUS_ONLINE = "online";
/**
* 在线聊天 SOCKET消息类型
*/
String IM_SOCKET_TYPE = "chatMessage";
/**
* 在线聊天 是否开启默认添加好友 1是 0否
*/
String IM_DEFAULT_ADD_FRIEND = "1";
/**
* 在线聊天 用户好友缓存前缀
*/
String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
/**
* 考勤补卡业务状态 (1:同意 2:不同意)
*/
String SIGN_PATCH_BIZ_STATUS_1 = "1";
String SIGN_PATCH_BIZ_STATUS_2 = "2";
/**
* 公文文档上传自定义路径
*/
String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
/**
* 公文文档下载自定义路径
*/
String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
/**
* WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板))
*/
String WPS_TYPE_1 = "1";
String WPS_TYPE_2 = "2";
/**===============================================================================================*/
/**
* ::非常重要::
* 注意:这四个常量值如果修改,需要与 jeecg-boot-starter/jeecg-boot-common/org.jeecg.config.FeignConfig 类中的值保持一致。
*/
String X_ACCESS_TOKEN = "X-Access-Token";
String X_SIGN = "X-Sign";
String X_TIMESTAMP = "X-TIMESTAMP";
/**
* 租户请求头 更名为:X-Tenant-Id
*/
String TENANT_ID = "X-Tenant-Id";
/**
* ===============================================================================================
*/
String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!";
String X_FORWARDED_SCHEME = "X-Forwarded-Scheme";
/**
* 微服务读取配置文件属性 服务地址
*/
String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
/**
* 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
*/
String THIRD_LOGIN_CODE = "third_login_code";
/**
* 第三方APP同步方向:本地 --> 第三方APP
*/
String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
/**
* 第三方APP同步方向:第三方APP --> 本地
*/
String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
/**
* 系统通告消息状态:0=未发布
*/
String ANNOUNCEMENT_SEND_STATUS_0 = "0";
/**
* 系统通告消息状态:1=已发布
*/
String ANNOUNCEMENT_SEND_STATUS_1 = "1";
/**
* 系统通告消息状态:2=已撤销
*/
String ANNOUNCEMENT_SEND_STATUS_2 = "2";
/**
* ONLINE 报表权限用 从request中获取地址栏后的参数
*/
String ONL_REP_URL_PARAM_STR = "onlRepUrlParamStr";
/**
* POST请求
*/
String HTTP_POST = "POST";
/**
* PUT请求
*/
String HTTP_PUT = "PUT";
/**
* PATCH请求
*/
String HTTP_PATCH = "PATCH";
/**
* 未知的
*/
String UNKNOWN = "unknown";
/**
* 字符串http
*/
String STR_HTTP = "http";
/**
* String 类型的空值
*/
String STRING_NULL = "null";
/**
* 前端vue3版本Header参数名
*/
String VERSION = "X-Version";
/**
* 存储在线程变量里的动态表名
*/
String DYNAMIC_TABLE_NAME = "DYNAMIC_TABLE_NAME";
/**
* http:// http协议
*/
String HTTP_PROTOCOL = "http://";
/**
* https:// https协议
*/
String HTTPS_PROTOCOL = "https://";
/**
* 部门表唯一keyid
*/
String DEPART_KEY_ID = "id";
/**
* 部门表唯一keyorgCode
*/
String DEPART_KEY_ORG_CODE = "orgCode";
/**
* 发消息 会传递一些信息到map
*/
String NOTICE_MSG_SUMMARY = "NOTICE_MSG_SUMMARY";
/**
* 发消息 会传递一个业务ID到map
*/
String NOTICE_MSG_BUS_ID = "NOTICE_MSG_BUS_ID";
/**
* 邮箱消息中地址登录时地址后携带的token,需要替换成真实的token值
*/
String LOGIN_TOKEN = "{LOGIN_TOKEN}";
/**
* 模板消息中 跳转地址的对应的key
*/
String MSG_HREF_URL = "url";
/**
* sys_data_log表的类型 用于区别评论区域的日志数据
*/
String DATA_LOG_TYPE_COMMENT = "comment";
/**
* sys_data_log表的类型 老的数据比较 类型都设置为json
*/
String DATA_LOG_TYPE_JSON = "json";
/**
* 消息模板:markdown
*/
String MSG_TEMPLATE_TYPE_MD = "5";
/**
* 短信验证码redis-key的前缀
*/
String PHONE_REDIS_KEY_PRE = "phone_msg";
//校验验证码过期
String PHONE_REDIS_KEY_RESEND_PRE = "phone_msg_resend";
/**
* 是文件夹
*/
String IT_IS_FOLDER = "1";
/**
* 文件拥有者
*/
String FILE_OWNER = "owner";
/**
* 文件管理员
*/
String FILE_ADMIN = "admin";
/**
* 只允许编辑
*/
String FILE_EDITABLE = "editable";
/**
* 登录失败,用于记录失败次数的key
*/
String LOGIN_FAIL = "LOGIN_FAIL_";
/**
* 入职事件
*/
Integer BPM_USER_EVENT_ADD = 1;
/**
* 离职事件
*/
Integer BPM_USER_EVENT_LEVEL = 2;
/**
* 用户租户状态(正常/已通过审核的)
*/
String USER_TENANT_NORMAL = "1";
/**
* 用户租户状态(离职)
*/
String USER_TENANT_QUIT = "2";
/**
* 用户租户状态(审核中)
*/
String USER_TENANT_UNDER_REVIEW = "3";
/**
* 用户租户状态(拒绝)
*/
String USER_TENANT_REFUSE = "4";
/**
* 不是叶子节点
*/
Integer NOT_LEAF = 0;
/**
* 是叶子节点
*/
Integer IS_LEAF = 1;
/**
* 缩略图通用前缀
*/
String THUMBNAIL_PREFIX = "small_";
/**
* 缩略图缩略比例
*/
Double THUMBNAIL_SCALE = 0.25;
// 请求头客户端标识
String X_CLIENT_SIGN = "X-ClientSign";
/**
* 上午下午
*/
String AM_PM = "0";
String PM_PM = "1";
String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKZl9H9sD1fe+nzrLVoSm/DNclgpFEXV8tq7b7Tn9m1ohMulXxuGSZJ/ed5LL9D2AB28bvkWvvcT4ZYT4rlvQGm8hLWMMajfX34+llHf1JplMpnbtcVeuiyYlNm603v23zX0dLVWx6V66ccAWAxW58T1TmM/osbOX/BuRLLTUaHPAgMBAAECgYAzhsLNamLd7PhYEmM6zyRmztenoSDb90J6pSwUMvhGLOViQlVPKqhBqyPLyDCIXoTusFkU3QxJamiilonQrjidhB5rnel0e83fbhpYu+A+64N8CX7FWPZnrIJazSep6P9akQKAAAYvrM+80YOX7/oUDVTXd1RiJjyKFw9SvaLysQJBAPDj+sffy3jIaqfhMYw3YqBmHFTXJplJIo+wZuBX+NaFod79/1EQJ1zWZxiyvGIedMky6FQXCZmC6KwR9cy6yKUCQQCw1dcYUbvUgkwgo1RFRYlc3/kPwLAU8RGq6ds7iHdv2y+d6iWUNWPKeUeeYApA5whgrG/KuYLk51HWHIOXlcJjAkEA5elRs26/rrnqQezG84LxGRIcPEVUy7xnxiihJ8IO+AB3LHPUOTRnvU3M/F+rOSLEaDu0Tn3mZaPyGjjSFuK3GQJBAIyucuKsE4wq5LmKdr5tZax3msNHfk4Kww1/4qPoG2znqWguIRtZpjwsZCfBLCcaJfYS+RUEpPfKd7apFJ+ByxUCQH14bKDj8rvT9O+ABrrY5i7XzRatJP7uwT8NhIlciUuc7WFiduUJwvmxfkV4EoRccjk9+aV+8xKjAplPBxL9lIc=";
String MYSTIQUE = "Mystique";
// 长庆油田
String COYOTE = "Coyote";
// 青海油田
String QUARRY = "Quarry";
/**
* 单选
*/
String DG = "DG";
/**
* 多选
*/
String DX = "DX";
/**
* 多选
*/
String PD = "PD";
}
@@ -0,0 +1,52 @@
package org.jeecg.common.constant;
/**
* 系统通告 - 发布状态
*
* @Author LeeShaoQing
*/
public interface CommonSendStatus {
/**
* 未发布
*/
public static final String UNPUBLISHED_STATUS_0 = "0";
/**
* 已发布
*/
public static final String PUBLISHED_STATUS_1 = "1";
/**
* 发布中
*/
public static final String PUBLISHED_STATUS_3 = "3";
/**
* 撤销
*/
public static final String REVOKE_STATUS_2 = "2";
/**
* app端推送会话标识后缀
*/
public static final String APP_SESSION_SUFFIX = "_app";
/**
* 流程催办——系统通知消息模板
*/
public static final String TZMB_BPM_CUIBAN = "bpm_cuiban";
/**
* 流程催办——邮件通知消息模板
*/
public static final String TZMB_BPM_CUIBAN_EMAIL = "bpm_cuiban_email";
/**
* 标准模板—系统消息通知
*/
public static final String TZMB_SYS_TS_NOTE = "sys_ts_note";
/**
* 流程超时提醒——系统通知消息模板
*/
public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip";
}
@@ -0,0 +1,206 @@
package org.jeecg.common.constant;
/**
* 数据库上下文常量
*
* @author: jeecg-boot
*/
public interface DataBaseConstant {
//*********数据库类型****************************************
/**
* MYSQL数据库
*/
public static final String DB_TYPE_MYSQL = "MYSQL";
/**
* ORACLE
*/
public static final String DB_TYPE_ORACLE = "ORACLE";
/**
* 达梦数据库
*/
public static final String DB_TYPE_DM = "DM";
/**
* postgreSQL达梦数据库
*/
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
/**
* sqlserver数据库
*/
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
/**
* mariadb 数据库
*/
public static final String DB_TYPE_MARIADB = "MARIADB";
/**
* DB2 数据库
*/
public static final String DB_TYPE_DB2 = "DB2";
/**
* HSQL 数据库
*/
public static final String DB_TYPE_HSQL = "HSQL";
// // 数据库类型,对应 database_type 字典
// public static final String DB_TYPE_MYSQL_NUM = "1";
// public static final String DB_TYPE_MYSQL7_NUM = "6";
// public static final String DB_TYPE_ORACLE_NUM = "2";
// public static final String DB_TYPE_SQLSERVER_NUM = "3";
// public static final String DB_TYPE_POSTGRESQL_NUM = "4";
// public static final String DB_TYPE_MARIADB_NUM = "5";
//*********系统上下文变量****************************************
/**
* 数据-所属机构编码
*/
public static final String SYS_ORG_CODE = "sysOrgCode";
/**
* 数据-所属机构编码
*/
public static final String SYS_ORG_CODE_TABLE = "sys_org_code";
/**
* 数据-所属机构编码
*/
public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode";
/**
* 数据-所属机构编码
*/
public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code";
/**
* 数据-系统用户编码(对应登录用户账号)
*/
public static final String SYS_USER_CODE = "sysUserCode";
/**
* 数据-系统用户编码(对应登录用户账号)
*/
public static final String SYS_USER_CODE_TABLE = "sys_user_code";
/**
* 数据-系统用户编码(对应登录用户ID)
*/
public static final String SYS_USER_ID = "sysUserId";
/**
* 数据-系统用户编码(对应登录用户ID)
*/
public static final String SYS_USER_ID_TABLE = "sys_user_id";
/**
* 数据-系统用户编码(对应登录用户管理医院ID)
*/
public static final String SYS_MANAGER_HOS_ID = "sysManagerHosId";
/**
* 数据-系统用户编码(对应登录用户管理医院ID)
*/
public static final String SYS_MANAGER_HOS_ID_TABLE = "sys_manager_hos_id";
/**
* 数据-系统用户编码(对应登录用户管理部门ID)
*/
public static final String SYS_MANAGER_DEPART_IDS = "sysManagerDepartIds";
/**
* 数据-系统用户编码(对应登录用户管理部门ID)
*/
public static final String SYS_MANAGER_DEPART_IDS_TABLE = "sys_manager_depart_ids";
/**
* 数据-系统用户编码(对应登录用户管理部门CODE)
*/
public static final String SYS_MANAGER_DEPART_CODES = "sysManagerDepartCodes";
/**
* 数据-系统用户编码(对应登录用户管理部门CODE)
*/
public static final String SYS_MANAGER_DEPART_CODES_TABLE = "sys_manager_depart_codes";
/**
* 登录用户真实姓名
*/
public static final String SYS_USER_NAME = "sysUserName";
/**
* 登录用户真实姓名
*/
public static final String SYS_USER_NAME_TABLE = "sys_user_name";
/**
* 系统日期"yyyy-MM-dd"
*/
public static final String SYS_DATE = "sysDate";
/**
* 系统日期"yyyy-MM-dd"
*/
public static final String SYS_DATE_TABLE = "sys_date";
/**
* 系统时间"yyyy-MM-dd HH:mm"
*/
public static final String SYS_TIME = "sysTime";
/**
* 系统时间"yyyy-MM-dd HH:mm"
*/
public static final String SYS_TIME_TABLE = "sys_time";
/**
* 数据-所属机构编码
*/
public static final String SYS_BASE_PATH = "sys_base_path";
//*********系统上下文变量****************************************
//*********系统建表标准字段****************************************
/**
* 创建者登录名称
*/
public static final String CREATE_BY_TABLE = "create_by";
/**
* 创建者登录名称
*/
public static final String CREATE_BY = "createBy";
/**
* 创建日期时间
*/
public static final String CREATE_TIME_TABLE = "create_time";
/**
* 创建日期时间
*/
public static final String CREATE_TIME = "createTime";
/**
* 更新用户登录名称
*/
public static final String UPDATE_BY_TABLE = "update_by";
/**
* 更新用户登录名称
*/
public static final String UPDATE_BY = "updateBy";
/**
* 更新日期时间
*/
public static final String UPDATE_TIME = "updateTime";
/**
* 更新日期时间
*/
public static final String UPDATE_TIME_TABLE = "update_time";
/**
* 业务流程状态
*/
public static final String BPM_STATUS = "bpmStatus";
/**
* 业务流程状态
*/
public static final String BPM_STATUS_TABLE = "bpm_status";
//*********系统建表标准字段****************************************
/**
* sql语句 where
*/
String SQL_WHERE = "where";
/**
* sql语句 asc
*/
String SQL_ASC = "asc";
/**
* sqlserver数据库,中间有空格
*/
String DB_TYPE_SQL_SERVER_BLANK = "sql server";
}
@@ -0,0 +1,16 @@
package org.jeecg.common.constant;
/**
* 动态切换表配置常量
*
* @author: scott
* @date: 2022年04月25日 22:30
*/
public class DynamicTableConstant {
/**
* 角色首页配置表
* vue2表名: sys_role_index
* vue3表名: sys_role_index_vue3
*/
public static final String SYS_ROLE_INDEX = "sys_role_index";
}
@@ -0,0 +1,13 @@
package org.jeecg.common.constant;
/**
* @Description: 导入常量定义
* @author: jeecg-boot
*/
public interface ExportConstant {
//数据导出中
public static final String EXPORTING = "7";
//数据导出完成
public static final String EXPORT_SUCCESS = "8";
}
@@ -0,0 +1,82 @@
package org.jeecg.common.constant;
/**
* 假数据常量
*
* @author Junqiang Zhu
* @since 2024-05-13 09:37
*/
public interface FakerDataConstant {
String BASE = "house:fakerData:";
String ENABLE = "enable:";
// 五类人群
String BASE_GROUP_USER = "groupUser";
String GROUP_USER = BASE + BASE_GROUP_USER;
String GROUP_USER_ENABLE = BASE + ENABLE + BASE_GROUP_USER;
// 一线医疗点
String BASE_MEDICAL_CENTER = "medicalCenter";
String MEDICAL_CENTER = BASE + BASE_MEDICAL_CENTER;
String MEDICAL_CENTER_ENABLE = BASE + ENABLE + BASE_MEDICAL_CENTER;
// 员工营养监测
String BASE_NUTRITION = "nutrition";
String NUTRITION = BASE + BASE_NUTRITION;
String NUTRITION_ENABLE = BASE + ENABLE + BASE_NUTRITION;
// 员工手表数据监测
String BASE_WATCH = "watch";
String WATCH = BASE + BASE_WATCH;
String WATCH_ENABLE = BASE + ENABLE + BASE_WATCH;
// 健康水平分布
String BASE_HEALTH = "health";
String HEALTH = BASE + BASE_HEALTH;
String HEALTH_ENABLE = BASE + ENABLE + BASE_HEALTH;
// 心理干预
String BASE_INTERVENE = "intervene";
String INTERVENE = BASE + BASE_INTERVENE;
String INTERVENE_ENABLE = BASE + ENABLE + BASE_INTERVENE;
//服务详情
String BASE_SERVICE = "service";
String SERVICE = BASE + BASE_SERVICE;
String SERVICE_ENABLE = BASE + ENABLE + BASE_SERVICE;
// 体检数据
String BASE_MEDICAL = "medical";
String MEDICAL = BASE + BASE_MEDICAL;
String MEDICAL_ENABLE = BASE + ENABLE + BASE_MEDICAL;
// 大病
String BASE_BIG_ILL = "bigIll";
String BIG_ILL = BASE + BASE_BIG_ILL;
String BIG_ILL_ENABLE = BASE + ENABLE + BASE_BIG_ILL;
// 银川服务详情数据
String BASE_YC_SERVICE = "ycService";
String YC_SERVICE = BASE + BASE_YC_SERVICE;
String YC_SERVICE_ENABLE = BASE + ENABLE + BASE_YC_SERVICE;
// 银川体检数据
String BASE_YC_MEDICAL = "ycMedical";
String YC_MEDICAL = BASE + BASE_YC_MEDICAL;
String YC_MEDICAL_ENABLE = BASE + ENABLE + BASE_YC_MEDICAL;
// 银川一线医疗点
String BASE_YC_MEDICAL_CENTER = "ycMedicalCenter";
String YC_MEDICAL_CENTER = BASE + BASE_YC_MEDICAL_CENTER;
String YC_MEDICAL_CENTER_ENABLE = BASE + ENABLE + BASE_YC_MEDICAL_CENTER;
// 银川员工队伍健康状况
String BASE_YC_USER_HEALTH = "ycUserHealth";
String YC_USER_HEALTH = BASE + BASE_YC_USER_HEALTH;
String YC_USER_HEALTH_ENABLE = BASE + ENABLE + BASE_YC_USER_HEALTH;
}
@@ -0,0 +1,26 @@
package org.jeecg.common.constant;
/**
* 规则值生成 编码常量类
*
* @author: taoyan
* @date: 2020年04月02日
*/
public class FillRuleConstant {
/**
* 公文发文编码
*/
public static final String DOC_SEND = "doc_send_code";
/**
* 部门编码
*/
public static final String DEPART = "org_num_role";
/**
* 分类字典编码
*/
public static final String CATEGORY = "category_code_rule";
}
@@ -0,0 +1,31 @@
package org.jeecg.common.constant;
/**
* @Description: 导入常量定义
* @author: jeecg-boot
*/
public interface ImportConstant {
//上传中
// public static final String UPLOADING = "-1";
//数据导入中
public static final String IMPORTING = "9";
//数据导入成功
public static final String IMPORT_SUCCEED = "10";
//数据导入失败
public static final String IMPORT_FAILED = "11";
//已保存待校验
public static final String SAVE = "0";
//数据校验中
public static final String CHECKING = "1";
//数据校验有误
public static final String CHECK_FAILED = "2";
//数据校验完成
public static final String CHECK_SUCCEED = "3";
//数据更新中
public static final String UPDATING = "4";
//数据更新有误
public static final String UPDATE_FAILED = "5";
//数据更新完成
public static final String UPDATE_SUCCEED = "6";
}
@@ -0,0 +1,13 @@
package org.jeecg.common.constant;
/**
* @author Shunzhi Jiang
* @since 2023/6/25
*/
public interface JwtClaimConstant {
String CLAIM_USERNAME = "username";
String CLAIM_IDENTIFIER = "identifier";
}
@@ -0,0 +1,31 @@
package org.jeecg.common.constant;
/**
* @author Shunzhi Jiang
* @since 2023/6/14
*/
public interface NewCacheConstant {
String SYS_RESET_USER_PASSWORD = "sys:cache:reset:user";
String SYS_DEPART_ID_CACHE = "sys:cache:depart:id";
String SYS_DEPART_CODE_CACHE = "sys:cache:depart:code";
//青海部门
String SYS_DEPART_QH_ID_CACHE = "sys:cache:depart_qh:id";
String SYS_DEPART_QH_CODE_CACHE = "sys:cache:depart_qh:code";
String SYS_USER_CODE_CACHE = "sys:cache:user:code";
String SYS_USER_QH_CODE_CACHE = "sys:cache:user_qh:code";
String SYS_CATEGORY_CACHE = "sys:cache:category";
String SYS_CONFIG_CACHE = "sys:cache:config";
String SYS_HOS_MANAGE_ID_CACHE = "sys:cache:hos:manager:id";//管理医院id
String QUESTION_CATEGORY = "sys:cache:dict::question_category";
String SYS_CACHE_DICT_WATCH_EVENT_TYPE= "sys:cache:dict::watch_event_type";
}
@@ -0,0 +1,219 @@
package org.jeecg.common.constant;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* @Description: 省市区
* @author: jeecg-boot
*/
@Component("pca")
public class ProvinceCityArea {
List<Area> areaList;
public String getText(String code) {
this.initAreaList();
if (this.areaList != null || this.areaList.size() > 0) {
List<String> ls = new ArrayList<String>();
getAreaByCode(code, ls);
return String.join("/", ls);
}
return "";
}
public String getCode(String text) {
this.initAreaList();
if (areaList != null && areaList.size() > 0) {
for (int i = areaList.size() - 1; i >= 0; i--) {
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
String areaText = areaList.get(i).getText();
String cityText = areaList.get(i).getAheadText();
if (text.indexOf(areaText) >= 0 && (cityText != null && text.indexOf(cityText) >= 0)) {
return areaList.get(i).getId();
}
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
}
}
return null;
}
// update-begin-author:sunjianlei date:20220121 for:【JTC-704】数据导入错误 省市区组件,文件中为北京市,导入后,导为了山西省
/**
* 获取省市区code,精准匹配
*
* @param texts 文本数组,省,市,区
* @return 返回 省市区的code
*/
public String[] getCode(String[] texts) {
if (texts == null || texts.length == 0) {
return null;
}
this.initAreaList();
if (areaList == null || areaList.size() == 0) {
return null;
}
String[] codes = new String[texts.length];
String code = null;
for (int i = 0; i < texts.length; i++) {
String text = texts[i];
Area area;
if (code == null) {
area = getAreaByText(text);
} else {
area = getAreaByPidAndText(code, text);
}
if (area != null) {
code = area.id;
codes[i] = code;
} else {
return null;
}
}
return codes;
}
/**
* 根据text获取area
*
* @param text
* @return
*/
public Area getAreaByText(String text) {
for (Area area : areaList) {
if (text.equals(area.getText())) {
return area;
}
}
return null;
}
/**
* 通过pid获取 area 对象
*
* @param pCode 父级编码
* @param text
* @return
*/
public Area getAreaByPidAndText(String pCode, String text) {
this.initAreaList();
if (this.areaList != null && this.areaList.size() > 0) {
for (Area area : this.areaList) {
if (area.getPid().equals(pCode) && area.getText().equals(text)) {
return area;
}
}
}
return null;
}
// update-end-author:sunjianlei date:20220121 for:【JTC-704】数据导入错误 省市区组件,文件中为北京市,导入后,导为了山西省
public void getAreaByCode(String code, List<String> ls) {
for (Area area : areaList) {
if (area.getId().equals(code)) {
String pid = area.getPid();
ls.add(0, area.getText());
getAreaByCode(pid, ls);
}
}
}
private void initAreaList() {
//System.out.println("=====================");
if (this.areaList == null || this.areaList.size() == 0) {
this.areaList = new ArrayList<Area>();
try {
String jsonData = oConvertUtils.readStatic("classpath:static/pca.json");
JSONObject baseJson = JSONObject.parseObject(jsonData);
//第一层 省
JSONObject provinceJson = baseJson.getJSONObject("86");
for (String provinceKey : provinceJson.keySet()) {
//System.out.println("===="+provinceKey);
Area province = new Area(provinceKey, provinceJson.getString(provinceKey), "86");
this.areaList.add(province);
//第二层 市
JSONObject cityJson = baseJson.getJSONObject(provinceKey);
for (String cityKey : cityJson.keySet()) {
//System.out.println("-----"+cityKey);
Area city = new Area(cityKey, cityJson.getString(cityKey), provinceKey);
this.areaList.add(city);
//第三层 区
JSONObject areaJson = baseJson.getJSONObject(cityKey);
if (areaJson != null) {
for (String areaKey : areaJson.keySet()) {
//System.out.println("········"+areaKey);
Area area = new Area(areaKey, areaJson.getString(areaKey), cityKey);
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
area.setAheadText(cityJson.getString(cityKey));
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
this.areaList.add(area);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private String jsonRead(File file) {
Scanner scanner = null;
StringBuilder buffer = new StringBuilder();
try {
scanner = new Scanner(file, "utf-8");
while (scanner.hasNextLine()) {
buffer.append(scanner.nextLine());
}
} catch (Exception e) {
} finally {
if (scanner != null) {
scanner.close();
}
}
return buffer.toString();
}
class Area {
String id;
String text;
String pid;
// 用于存储上级文本数据,区的上级文本 是市的数据
String aheadText;
public Area(String id, String text, String pid) {
this.id = id;
this.text = text;
this.pid = pid;
}
public String getId() {
return id;
}
public String getText() {
return text;
}
public String getPid() {
return pid;
}
public String getAheadText() {
return aheadText;
}
public void setAheadText(String aheadText) {
this.aheadText = aheadText;
}
}
}
@@ -0,0 +1,54 @@
/*
*
* * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
* * <p>
* * Licensed under the GNU Lesser General Public License 3.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* * <p>
* * https://www.gnu.org/licenses/lgpl.html
* * <p>
* * 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.
*
*/
package org.jeecg.common.constant;
/**
* @author scott
* @date 2019年05月18日
* 服务名称
*/
public interface ServiceNameConstants {
/**
* 微服务名:系统管理模块
*/
String SERVICE_SYSTEM = "health-system";
/**
* 微服务名: demo模块
*/
String SERVICE_DEMO = "jeecg-demo";
/**
* 微服务名:online在线模块
*/
String SERVICE_ONLINE = "jeecg-online";
/**
* 微服务名:OA模块
*/
String SERVICE_EOA = "jeecg-eoa";
/**
* 微服务名:表单设计模块
*/
String SERVICE_FORM = "jeecg-desform";
/**
* gateway通过header传递根路径 basePath
*/
String X_GATEWAY_BASE_PATH = "X_GATEWAY_BASE_PATH";
}
@@ -0,0 +1,153 @@
package org.jeecg.common.constant;
/**
* @Description: 符号和特殊符号常用类
* @author: wangshuai
* @date: 2022年03月30日 17:44
*/
public class SymbolConstant {
/**
* 符号:点
*/
public static final String SPOT = ".";
/**
* 符号:双斜杠
*/
public static final String DOUBLE_BACKSLASH = "\\";
/**
* 符号:冒号
*/
public static final String COLON = ":";
/**
* 符号:逗号
*/
public static final String COMMA = ",";
/**
* 符号:左花括号 }
*/
public static final String LEFT_CURLY_BRACKET = "{";
/**
* 符号:右花括号 }
*/
public static final String RIGHT_CURLY_BRACKET = "}";
/**
* 符号:井号 #
*/
public static final String WELL_NUMBER = "#";
/**
* 符号:单斜杠
*/
public static final String SINGLE_SLASH = "/";
/**
* 符号:双斜杠
*/
public static final String DOUBLE_SLASH = "//";
/**
* 符号:感叹号
*/
public static final String EXCLAMATORY_MARK = "!";
/**
* 符号:下划线
*/
public static final String UNDERLINE = "_";
/**
* 符号:单引号
*/
public static final String SINGLE_QUOTATION_MARK = "'";
/**
* 符号:星号
*/
public static final String ASTERISK = "*";
/**
* 符号:百分号
*/
public static final String PERCENT_SIGN = "%";
/**
* 符号:美元 $
*/
public static final String DOLLAR = "$";
/**
* 符号:和 &
*/
public static final String AND = "&";
/**
* 符号:../
*/
public static final String SPOT_SINGLE_SLASH = "../";
/**
* 符号:..\\
*/
public static final String SPOT_DOUBLE_BACKSLASH = "..\\";
/**
* 系统变量前缀 #{
*/
public static final String SYS_VAR_PREFIX = "#{";
/**
* 符号 {{
*/
public static final String DOUBLE_LEFT_CURLY_BRACKET = "{{";
/**
* 符号:[
*/
public static final String SQUARE_BRACKETS_LEFT = "[";
/**
* 符号:]
*/
public static final String SQUARE_BRACKETS_RIGHT = "]";
/**
* 符号: 大于
*/
public static final String GREATER_THAN = ">";
/**
*符号: 小于
*/
public static final String LESS_THAN = "<";
/**
*符号: 大于等于
*/
public static final String GREATER_THAN_AND_EQUAL = ">=";
/**
*符号: 小于等于
*/
public static final String LESS_THAN_AND_EQUAL = "<=";
/**
*符号: 等号
*/
public static final String EQUAL = "=";
/**
*符号: 不等号
*/
public static final String NOT_EQUAL = "!=";
/**
* 符号: <> 代表区间
*/
public static final String RANGE = "<>";
}
@@ -0,0 +1,50 @@
package org.jeecg.common.constant;
/**
* @Description: TenantConstant
* @author: scott
* @date: 2022年08月29日 15:29
*/
public interface TenantConstant {
/*------【低代码应用参数】----------------------------------------------*/
/**
* header的lowAppId标识
*/
String X_LOW_APP_ID = "X-Low-App-ID";
/**
* 应用ID——实体字段
*/
String FIELD_LOW_APP_ID = "lowAppId";
/**
* 应用ID——表字段
*/
String DB_FIELD_LOW_APP_ID = "low_app_id";
/*------【低代码应用参数】---------------------------------------------*/
/*--------【租户参数】-----------------------------------------------*/
/**
* 租户ID(实体字段名 和 url参数名)
*/
String TENANT_ID = "tenantId";
/**
* 租户ID 数据库字段名
*/
String TENANT_ID_TABLE = "tenant_id";
/*-------【租户参数】-----------------------------------------------*/
/**
* 超级管理员
*/
String SUPER_ADMIN = "superAdmin";
/**
* 组织账户管理员
*/
String ACCOUNT_ADMIN = "accountAdmin";
/**
* 组织应用管理员
*/
String APP_ADMIN = "appAdmin";
}
@@ -0,0 +1,32 @@
package org.jeecg.common.constant;
/**
* VXESocket 常量
*
* @author: jeecg-boot
*/
public class VxeSocketConst {
/**
* 消息类型
*/
public static final String TYPE = "type";
/**
* 消息数据
*/
public static final String DATA = "data";
/**
* 消息类型:心跳检测
*/
public static final String TYPE_HB = "heart_beat";
/**
* 消息类型:通用数据传递
*/
public static final String TYPE_CSD = "common_send_date";
/**
* 消息类型:更新vxe table数据
*/
public static final String TYPE_UVT = "update_vxe_table";
}
@@ -0,0 +1,66 @@
package org.jeecg.common.constant;
/**
* @Description: Websocket常量类
* @author: taoyan
* @date: 2020年03月23日
*/
public class WebsocketConst {
/**
* 消息json key:cmd
*/
public static final String MSG_CMD = "cmd";
/**
* 消息json key:msgId
*/
public static final String MSG_ID = "msgId";
/**
* 消息json key:msgTxt
*/
public static final String MSG_TXT = "msgTxt";
/**
* 消息json key:userId
*/
public static final String MSG_USER_ID = "userId";
/**
* 消息json key:chat
*/
public static final String MSG_CHAT = "chat";
/**
* 消息类型 heartcheck
*/
public static final String CMD_CHECK = "heartcheck";
/**
* 消息类型 user 用户消息
*/
public static final String CMD_USER = "user";
/**
* 消息类型 topic 系统通知
*/
public static final String CMD_TOPIC = "topic";
/**
* 消息类型 email
*/
public static final String CMD_EMAIL = "email";
/**
* 消息类型 meetingsign 会议签到
*/
public static final String CMD_SIGN = "sign";
/**
* 消息类型 新闻发布/取消
*/
public static final String NEWS_PUBLISH = "publish";
}
@@ -0,0 +1,167 @@
package org.jeecg.common.constant.enums;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* online表单枚举 代码生成器用到
*
* @author: jeecg-boot
*/
public enum CgformEnum {
/**
* 单表
*/
ONE(1, "one", "/jeecg/code-template-online", "default.one", "经典风格", new String[]{"vue3", "vue", "vue3Native"}),
/**
* 多表
*/
MANY(2, "many", "/jeecg/code-template-online", "default.onetomany", "经典风格", new String[]{"vue"}),
/**
* 多表(jvxe风格)
*/
JVXE_TABLE(2, "jvxe", "/jeecg/code-template-online", "jvxe.onetomany", "JVXE风格", new String[]{"vue3", "vue", "vue3Native"}),
/**
* 多表 (erp风格)
*/
ERP(2, "erp", "/jeecg/code-template-online", "erp.onetomany", "ERP风格", new String[]{"vue3", "vue"}),
/**
* 多表(内嵌子表风格)
*/
INNER_TABLE(2, "innerTable", "/jeecg/code-template-online", "inner-table.onetomany", "内嵌子表风格", new String[]{"vue3", "vue"}),
/**
* 多表(tab风格)
*/
TAB(2, "tab", "/jeecg/code-template-online", "tab.onetomany", "Tab风格", new String[]{"vue3", "vue"}),
/**
* 树形列表
*/
TREE(3, "tree", "/jeecg/code-template-online", "default.tree", "树形列表", new String[]{"vue3", "vue", "vue3Native"});
/**
* 类型 1/单表 2/一对多 3/树
*/
int type;
/**
* 编码标识
*/
String code;
/**
* 代码生成器模板路径
*/
String templatePath;
/**
* 代码生成器模板路径
*/
String stylePath;
/**
* 模板风格名称
*/
String note;
/**
* 支持代码风格 vue3:vue3包装代码 vue3Native:vue3原生代码 vue:vue2代码
*/
String[] vueStyle;
/**
* 构造器
*
* @param type 类型 1/单表 2/一对多 3/树
* @param code 模板编码
* @param templatePath 模板路径
* @param stylePath 模板子路径
* @param note
* @param vueStyle 支持代码风格
*/
CgformEnum(int type, String code, String templatePath, String stylePath, String note, String[] vueStyle) {
this.type = type;
this.code = code;
this.templatePath = templatePath;
this.stylePath = stylePath;
this.note = note;
this.vueStyle = vueStyle;
}
/**
* 根据code获取模板路径
*
* @param code
* @return
*/
public static String getTemplatePathByConfig(String code) {
return getCgformEnumByConfig(code).templatePath;
}
/**
* 根据code找枚举
*
* @param code
* @return
*/
public static CgformEnum getCgformEnumByConfig(String code) {
for (CgformEnum e : CgformEnum.values()) {
if (e.code.equals(code)) {
return e;
}
}
return null;
}
/**
* 根据类型找所有
*
* @param type
* @return
*/
public static List<Map<String, Object>> getJspModelList(int type) {
List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>();
for (CgformEnum e : CgformEnum.values()) {
if (e.type == type) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", e.code);
map.put("note", e.note);
ls.add(map);
}
}
return ls;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getTemplatePath() {
return templatePath;
}
public void setTemplatePath(String templatePath) {
this.templatePath = templatePath;
}
public String getStylePath() {
return stylePath;
}
public void setStylePath(String stylePath) {
this.stylePath = stylePath;
}
public String[] getVueStyle() {
return vueStyle;
}
public void setVueStyle(String[] vueStyle) {
this.vueStyle = vueStyle;
}
}
@@ -0,0 +1,77 @@
package org.jeecg.common.constant.enums;
import org.jeecg.common.util.oConvertUtils;
/**
* 文件类型
*/
public enum FileTypeEnum {
// 文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频)
// FOLDER
xls(".xls", "excel", "excel"),
xlsx(".xlsx", "excel", "excel"),
doc(".doc", "doc", "word"),
docx(".docx", "doc", "word"),
ppt(".ppt", "pp", "ppt"),
pptx(".pptx", "pp", "ppt"),
gif(".gif", "image", "图片"),
jpg(".jpg", "image", "图片"),
jpeg(".jpeg", "image", "图片"),
png(".png", "image", "图片"),
txt(".txt", "text", "文本"),
avi(".avi", "video", "视频"),
mov(".mov", "video", "视频"),
rmvb(".rmvb", "video", "视频"),
rm(".rm", "video", "视频"),
flv(".flv", "video", "视频"),
mp4(".mp4", "video", "视频"),
zip(".zip", "zip", "压缩包"),
pdf(".pdf", "pdf", "pdf");
private String type;
private String value;
private String text;
private FileTypeEnum(String type, String value, String text) {
this.type = type;
this.value = value;
this.text = text;
}
public static FileTypeEnum getByType(String type) {
if (oConvertUtils.isEmpty(type)) {
return null;
}
for (FileTypeEnum val : values()) {
if (val.getType().equals(type)) {
return val;
}
}
return null;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
@@ -0,0 +1,33 @@
package org.jeecg.common.constant.enums;
/**
* LowApp 切面注解枚举
*
* @date 2022-1-5
* @author: jeecg-boot
*/
public enum LowAppAopEnum {
/**
* 新增方法
*/
ADD,
/**
* 删除方法(包含单个和批量删除)
*/
DELETE,
/**
* 复制表单操作
*/
COPY,
/**
* Online表单专用:数据库表转Online表单
*/
CGFORM_DB_IMPORT,
/**
* 表单设计器专用:子表转工作表
*/
DESFORM_SUB2WORK
}
@@ -0,0 +1,96 @@
package org.jeecg.common.constant.enums;
import org.jeecg.common.system.annotation.EnumDict;
import org.jeecg.common.system.vo.DictModel;
import java.util.ArrayList;
import java.util.List;
/**
* 消息类型
*
* @author: jeecg-boot
*/
@EnumDict("messageType")
public enum MessageTypeEnum {
/**
* 系统消息
*/
XT("system", "系统消息"),
/**
* 邮件消息
*/
YJ("email", "邮件消息"),
/**
* 钉钉消息
*/
DD("dingtalk", "钉钉消息"),
/**
* 企业微信
*/
QYWX("wechat_enterprise", "企业微信");
/**
* 消息类型
*/
String type;
/**
* 类型说明
*/
String note;
MessageTypeEnum(String type, String note) {
this.type = type;
this.note = note;
}
/**
* 获取字典数据
*
* @return
*/
public static List<DictModel> getDictList() {
List<DictModel> list = new ArrayList<>();
DictModel dictModel = null;
for (MessageTypeEnum e : MessageTypeEnum.values()) {
dictModel = new DictModel();
dictModel.setValue(e.getType());
dictModel.setText(e.getNote());
list.add(dictModel);
}
return list;
}
/**
* 根据type获取枚举
*
* @param type
* @return
*/
public static MessageTypeEnum valueOfType(String type) {
for (MessageTypeEnum e : MessageTypeEnum.values()) {
if (e.getType().equals(type)) {
return e;
}
}
return null;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
@@ -0,0 +1,19 @@
package org.jeecg.common.constant.enums;
/**
* 日志按模块分类
*
* @author: jeecg-boot
*/
public enum ModuleType {
/**
* 普通
*/
COMMON,
/**
* online
*/
ONLINE;
}
@@ -0,0 +1,94 @@
package org.jeecg.common.constant.enums;
import org.jeecg.common.constant.CommonConstant;
/**
* @Description: 操作类型
* @author: jeecg-boot
* @date: 2022/3/31 10:05
*/
public enum OperateTypeEnum {
/**
* 列表
*/
LIST(CommonConstant.OPERATE_TYPE_1, "list"),
/**
* 新增
*/
ADD(CommonConstant.OPERATE_TYPE_2, "add"),
/**
* 编辑
*/
EDIT(CommonConstant.OPERATE_TYPE_3, "edit"),
/**
* 删除
*/
DELETE(CommonConstant.OPERATE_TYPE_4, "delete"),
/**
* 导入
*/
IMPORT(CommonConstant.OPERATE_TYPE_5, "import"),
/**
* 导出
*/
EXPORT(CommonConstant.OPERATE_TYPE_6, "export");
/**
* 类型 1列表,2新增,3编辑,4删除,5导入,6导出
*/
int type;
/**
* 编码(请求方式)
*/
String code;
/**
* 构造器
*
* @param type 类型
* @param code 编码(请求方式)
*/
OperateTypeEnum(int type, String code) {
this.type = type;
this.code = code;
}
/**
* 根据请求名称匹配
*
* @param methodName 请求名称
* @return Integer 类型
*/
public static Integer getTypeByMethodName(String methodName) {
for (OperateTypeEnum e : OperateTypeEnum.values()) {
if (methodName.startsWith(e.getCode())) {
return e.getType();
}
}
return CommonConstant.OPERATE_TYPE_1;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
@@ -0,0 +1,102 @@
package org.jeecg.common.constant.enums;
import org.jeecg.common.util.oConvertUtils;
import java.util.List;
/**
* 首页自定义
* 通过角色编码与首页组件路径配置
* 枚举的顺序有权限高低权重作用(也就是配置多个角色,在前面的角色首页,会优先生效)
*
* @author: jeecg-boot
*/
public enum RoleIndexConfigEnum {
/**
* 首页自定义 admin
*/
ADMIN("admin", "dashboard/Analysis"),
//TEST("test", "dashboard/IndexChart"),
/**
* 首页自定义 hr
*/
HR("hr", "dashboard/IndexBdc");
//DM("dm", "dashboard/IndexTask"),
/**
* 角色编码
*/
String roleCode;
/**
* 路由index
*/
String componentUrl;
/**
* 构造器
*
* @param roleCode 角色编码
* @param componentUrl 首页组件路径(规则跟菜单配置一样)
*/
RoleIndexConfigEnum(String roleCode, String componentUrl) {
this.roleCode = roleCode;
this.componentUrl = componentUrl;
}
/**
* 根据code找枚举
*
* @param roleCode 角色编码
* @return
*/
private static RoleIndexConfigEnum getEnumByCode(String roleCode) {
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
if (e.roleCode.equals(roleCode)) {
return e;
}
}
return null;
}
/**
* 根据code找index
*
* @param roleCode 角色编码
* @return
*/
private static String getIndexByCode(String roleCode) {
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
if (e.roleCode.equals(roleCode)) {
return e.componentUrl;
}
}
return null;
}
public static String getIndexByRoles(List<String> roles) {
String[] rolesArray = roles.toArray(new String[roles.size()]);
for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) {
if (oConvertUtils.isIn(e.roleCode, rolesArray)) {
return e.componentUrl;
}
}
return null;
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getComponentUrl() {
return componentUrl;
}
public void setComponentUrl(String componentUrl) {
this.componentUrl = componentUrl;
}
}
@@ -0,0 +1,21 @@
package org.jeecg.common.desensitization.annotation;
import java.lang.annotation.*;
/**
* 解密注解
* <p>
* 在方法上定义 将方法返回对象中的敏感字段 解密,需要注意的是,如果没有加密过,解密会出问题,返回原字符串
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface SensitiveDecode {
/**
* 指明需要脱敏的实体类class
*
* @return
*/
Class entity() default Object.class;
}
@@ -0,0 +1,21 @@
package org.jeecg.common.desensitization.annotation;
import java.lang.annotation.*;
/**
* 加密注解
* <p>
* 在方法上声明 将方法返回对象中的敏感字段 加密/格式化
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface SensitiveEncode {
/**
* 指明需要脱敏的实体类class
*
* @return
*/
Class entity() default Object.class;
}
@@ -0,0 +1,22 @@
package org.jeecg.common.desensitization.annotation;
import org.jeecg.common.desensitization.enums.SensitiveEnum;
import java.lang.annotation.*;
/**
* 在字段上定义 标识字段存储的信息是敏感的
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SensitiveField {
/**
* 不同类型处理不同
*
* @return
*/
SensitiveEnum type() default SensitiveEnum.ENCODE;
}
@@ -0,0 +1,82 @@
package org.jeecg.common.desensitization.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.desensitization.annotation.SensitiveDecode;
import org.jeecg.common.desensitization.annotation.SensitiveEncode;
import org.jeecg.common.desensitization.util.SensitiveInfoUtil;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
/**
* 敏感数据切面处理类
*
* @Author taoYan
* @Date 2022/4/20 17:45
**/
@Slf4j
@Aspect
@Component
public class SensitiveDataAspect {
/**
* 定义切点Pointcut
*/
@Pointcut("@annotation(org.jeecg.common.desensitization.annotation.SensitiveEncode) || @annotation(org.jeecg.common.desensitization.annotation.SensitiveDecode)")
public void sensitivePointCut() {
}
@Around("sensitivePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
// 处理结果
Object result = point.proceed();
if (result == null) {
return result;
}
Class resultClass = result.getClass();
log.debug(" resultClass = {}", resultClass);
if (resultClass.isPrimitive()) {
//是基本类型 直接返回 不需要处理
return result;
}
// 获取方法注解信息:是哪个实体、是加密还是解密
boolean isEncode = true;
Class entity = null;
MethodSignature methodSignature = (MethodSignature) point.getSignature();
Method method = methodSignature.getMethod();
SensitiveEncode encode = method.getAnnotation(SensitiveEncode.class);
if (encode == null) {
SensitiveDecode decode = method.getAnnotation(SensitiveDecode.class);
if (decode != null) {
entity = decode.entity();
isEncode = false;
}
} else {
entity = encode.entity();
}
long startTime = System.currentTimeMillis();
if (resultClass.equals(entity) || entity.equals(Object.class)) {
// 方法返回实体和注解的entity一样,如果注解没有申明entity属性则认为是(方法返回实体和注解的entity一样)
SensitiveInfoUtil.handlerObject(result, isEncode);
} else if (result instanceof List) {
// 方法返回List<实体>
SensitiveInfoUtil.handleList(result, entity, isEncode);
} else {
// 方法返回一个对象
SensitiveInfoUtil.handleNestedObject(result, entity, isEncode);
}
long endTime = System.currentTimeMillis();
log.info((isEncode ? "加密操作," : "解密操作,") + "Aspect程序耗时:" + (endTime - startTime) + "ms");
return result;
}
}
@@ -0,0 +1,55 @@
package org.jeecg.common.desensitization.enums;
/**
* 敏感字段信息类型
*/
public enum SensitiveEnum {
/**
* 加密
*/
ENCODE,
/**
* 中文名
*/
CHINESE_NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 座机号
*/
FIXED_PHONE,
/**
* 手机号
*/
MOBILE_PHONE,
/**
* 地址
*/
ADDRESS,
/**
* 电子邮件
*/
EMAIL,
/**
* 银行卡
*/
BANK_CARD,
/**
* 公司开户银行联号
*/
CNAPS_CODE;
}
@@ -0,0 +1,381 @@
package org.jeecg.common.desensitization.util;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.desensitization.annotation.SensitiveField;
import org.jeecg.common.desensitization.enums.SensitiveEnum;
import org.jeecg.common.util.encryption.AesEncryptUtil;
import org.jeecg.common.util.oConvertUtils;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.List;
/**
* 敏感信息处理工具类
*
* @author taoYan
* @date 2022/4/20 18:01
**/
@Slf4j
public class SensitiveInfoUtil {
/**
* 处理嵌套对象
*
* @param obj 方法返回值
* @param entity 实体class
* @param isEncode 是否加密(true: 加密操作 / false:解密操作)
* @throws IllegalAccessException
*/
public static void handleNestedObject(Object obj, Class entity, boolean isEncode) throws IllegalAccessException {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.getType().isPrimitive()) {
continue;
}
if (field.getType().equals(entity)) {
// 对象里面是实体
field.setAccessible(true);
Object nestedObject = field.get(obj);
handlerObject(nestedObject, isEncode);
break;
} else {
// 对象里面是List<实体>
if (field.getGenericType() instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) field.getGenericType();
if (pt.getRawType().equals(List.class)) {
if (pt.getActualTypeArguments()[0].equals(entity)) {
field.setAccessible(true);
Object nestedObject = field.get(obj);
handleList(nestedObject, entity, isEncode);
break;
}
}
}
}
}
}
/**
* 处理Object
*
* @param obj 方法返回值
* @param isEncode 是否加密(true: 加密操作 / false:解密操作)
* @return
* @throws IllegalAccessException
*/
public static Object handlerObject(Object obj, boolean isEncode) throws IllegalAccessException {
if (oConvertUtils.isEmpty(obj)) {
return obj;
}
long startTime = System.currentTimeMillis();
log.debug(" obj --> " + obj.toString());
// 判断是不是一个对象
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
boolean isSensitiveField = field.isAnnotationPresent(SensitiveField.class);
if (isSensitiveField) {
// 必须有SensitiveField注解 才作处理
if (field.getType().isAssignableFrom(String.class)) {
//必须是字符串类型 才作处理
field.setAccessible(true);
String realValue = (String) field.get(obj);
if (realValue == null || "".equals(realValue)) {
continue;
}
SensitiveField sf = field.getAnnotation(SensitiveField.class);
if (isEncode == true) {
//加密
String value = SensitiveInfoUtil.getEncodeData(realValue, sf.type());
field.set(obj, value);
} else {
//解密只处理 encode类型的
if (sf.type().equals(SensitiveEnum.ENCODE)) {
String value = SensitiveInfoUtil.getDecodeData(realValue);
field.set(obj, value);
}
}
}
}
}
//long endTime=System.currentTimeMillis();
//log.info((isEncode ? "加密操作," : "解密操作,") + "当前程序耗时:" + (endTime - startTime) + "ms");
return obj;
}
/**
* 处理 List<实体>
*
* @param obj
* @param entity
* @param isEncodetrue: 加密操作 / false:解密操作)
*/
public static void handleList(Object obj, Class entity, boolean isEncode) {
List list = (List) obj;
if (list.size() > 0) {
Object first = list.get(0);
if (first.getClass().equals(entity)) {
for (int i = 0; i < list.size(); i++) {
Object temp = list.get(i);
try {
handlerObject(temp, isEncode);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 处理数据 获取解密后的数据
*
* @param data
* @return
*/
public static String getDecodeData(String data) {
String result = null;
try {
result = AesEncryptUtil.desEncrypt(data);
} catch (Exception exception) {
log.debug("数据解密错误,原数据:" + data);
}
//解决debug模式下,加解密失效导致中文被解密变成空的问题
if (oConvertUtils.isEmpty(result) && oConvertUtils.isNotEmpty(data)) {
result = data;
}
return result;
}
/**
* 处理数据 获取加密后的数据 或是格式化后的数据
*
* @param data 字符串
* @param sensitiveEnum 类型
* @return 处理后的字符串
*/
public static String getEncodeData(String data, SensitiveEnum sensitiveEnum) {
String result;
switch (sensitiveEnum) {
case ENCODE:
try {
result = AesEncryptUtil.encrypt(data);
} catch (Exception exception) {
log.error("数据加密错误", exception.getMessage());
result = data;
}
break;
case CHINESE_NAME:
result = chineseName(data);
break;
case ID_CARD:
result = idCardNum(data);
break;
case FIXED_PHONE:
result = fixedPhone(data);
break;
case MOBILE_PHONE:
result = mobilePhone(data);
break;
case ADDRESS:
result = address(data, 3);
break;
case EMAIL:
result = email(data);
break;
case BANK_CARD:
result = bankCard(data);
break;
case CNAPS_CODE:
result = cnapsCode(data);
break;
default:
result = data;
}
return result;
}
/**
* [中文姓名] 只显示第一个汉字,其他隐藏为2个星号
*
* @param fullName 全名
* @return <例子:李**>
*/
private static String chineseName(String fullName) {
if (oConvertUtils.isEmpty(fullName)) {
return "";
}
return formatRight(fullName, 1);
}
/**
* [中文姓名] 只显示第一个汉字,其他隐藏为2个星号
*
* @param familyName 姓
* @param firstName 名
* @return <例子:李**>
*/
private static String chineseName(String familyName, String firstName) {
if (oConvertUtils.isEmpty(familyName) || oConvertUtils.isEmpty(firstName)) {
return "";
}
return chineseName(familyName + firstName);
}
/**
* [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。
*
* @param id 身份证号
* @return <例子:*************5762>
*/
private static String idCardNum(String id) {
if (oConvertUtils.isEmpty(id)) {
return "";
}
return formatLeft(id, 4);
}
/**
* [固定电话] 后四位,其他隐藏
*
* @param num 固定电话
* @return <例子:****1234>
*/
private static String fixedPhone(String num) {
if (oConvertUtils.isEmpty(num)) {
return "";
}
return formatLeft(num, 4);
}
/**
* [手机号码] 前三位,后四位,其他隐藏
*
* @param num 手机号码
* @return <例子:138******1234>
*/
private static String mobilePhone(String num) {
if (oConvertUtils.isEmpty(num)) {
return "";
}
int len = num.length();
if (len < 11) {
return num;
}
return formatBetween(num, 3, 4);
}
/**
* [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护
*
* @param address 地址
* @param sensitiveSize 敏感信息长度
* @return <例子:北京市海淀区****>
*/
private static String address(String address, int sensitiveSize) {
if (oConvertUtils.isEmpty(address)) {
return "";
}
int len = address.length();
if (len < sensitiveSize) {
return address;
}
return formatRight(address, sensitiveSize);
}
/**
* [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示
*
* @param email 电子邮箱
* @return <例子:g**@163.com>
*/
private static String email(String email) {
if (oConvertUtils.isEmpty(email)) {
return "";
}
int index = email.indexOf("@");
if (index <= 1) {
return email;
}
String begin = email.substring(0, 1);
String end = email.substring(index);
String stars = "**";
return begin + stars + end;
}
/**
* [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号
*
* @param cardNum 银行卡号
* @return <例子:6222600**********1234>
*/
private static String bankCard(String cardNum) {
if (oConvertUtils.isEmpty(cardNum)) {
return "";
}
return formatBetween(cardNum, 6, 4);
}
/**
* [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号
*
* @param code 公司开户银行联号
* @return <例子:12********>
*/
private static String cnapsCode(String code) {
if (oConvertUtils.isEmpty(code)) {
return "";
}
return formatRight(code, 2);
}
/**
* 将右边的格式化成*
*
* @param str 字符串
* @param reservedLength 保留长度
* @return 格式化后的字符串
*/
private static String formatRight(String str, int reservedLength) {
String name = str.substring(0, reservedLength);
String stars = String.join("", Collections.nCopies(str.length() - reservedLength, "*"));
return name + stars;
}
/**
* 将左边的格式化成*
*
* @param str 字符串
* @param reservedLength 保留长度
* @return 格式化后的字符串
*/
private static String formatLeft(String str, int reservedLength) {
int len = str.length();
String show = str.substring(len - reservedLength);
String stars = String.join("", Collections.nCopies(len - reservedLength, "*"));
return stars + show;
}
/**
* 将中间的格式化成*
*
* @param str 字符串
* @param beginLen 开始保留长度
* @param endLen 结尾保留长度
* @return 格式化后的字符串
*/
private static String formatBetween(String str, int beginLen, int endLen) {
int len = str.length();
String begin = str.substring(0, beginLen);
String end = str.substring(len - endLen);
String stars = String.join("", Collections.nCopies(len - beginLen - endLen, "*"));
return begin + stars + end;
}
}
@@ -0,0 +1,551 @@
package org.jeecg.common.es;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.util.RestUtil;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* 关于 ElasticSearch 的一些方法(创建索引、添加数据、查询等)
*
* @author sunjianlei
*/
@Slf4j
@Component
public class JeecgElasticsearchTemplate {
/**
* ElasticSearch 最大可返回条目数
*/
public static final int ES_MAX_SIZE = 10000;
/**
* es7
*/
public static final String IE_SEVEN = "7";
/**
* url not found 404
*/
public static final String URL_NOT_FOUND = "404 Not Found";
private final String FORMAT_JSON = "format=json";
/**
* es服务地址
*/
private String baseUrl;
/**
* Elasticsearch 的版本号
*/
private String version = null;
public JeecgElasticsearchTemplate(@Value("${jeecg.elasticsearch.cluster-nodes}") String baseUrl, @Value("${jeecg.elasticsearch.check-enabled}") boolean checkEnabled) {
log.debug("JeecgElasticsearchTemplate BaseURL" + baseUrl);
if (StringUtils.isNotEmpty(baseUrl)) {
this.baseUrl = baseUrl;
// 验证配置的ES地址是否有效
if (checkEnabled) {
try {
this.getElasticsearchVersion();
log.info("ElasticSearch 服务连接成功");
log.info("ElasticSearch version: " + this.version);
} catch (Exception e) {
this.version = "";
log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!");
}
}
}
}
/**
* 获取 Elasticsearch 的版本号信息,失败返回null
*/
private void getElasticsearchVersion() {
if (this.version == null) {
String url = this.getBaseUrl().toString();
JSONObject result = RestUtil.get(url);
if (result != null) {
JSONObject v = result.getJSONObject("version");
this.version = v.getString("number");
}
}
}
public StringBuilder getBaseUrl(String indexName, String typeName) {
typeName = typeName.trim().toLowerCase();
return this.getBaseUrl(indexName).append("/").append(typeName);
}
public StringBuilder getBaseUrl(String indexName) {
indexName = indexName.trim().toLowerCase();
return this.getBaseUrl().append("/").append(indexName);
}
public StringBuilder getBaseUrl() {
return new StringBuilder("http://").append(this.baseUrl);
}
/**
* cat 查询ElasticSearch系统数据,返回json
*/
private <T> ResponseEntity<T> cat(String urlAfter, Class<T> responseType) {
String url = this.getBaseUrl().append("/_cat").append(urlAfter).append("?").append(FORMAT_JSON).toString();
return RestUtil.request(url, HttpMethod.GET, null, null, null, responseType);
}
/**
* 查询所有索引
* <p>
* 查询地址:GET http://{baseUrl}/_cat/indices
*/
public JSONArray getIndices() {
return getIndices(null);
}
/**
* 查询单个索引
* <p>
* 查询地址:GET http://{baseUrl}/_cat/indices/{indexName}
*/
public JSONArray getIndices(String indexName) {
StringBuilder urlAfter = new StringBuilder("/indices");
if (!StringUtils.isEmpty(indexName)) {
urlAfter.append("/").append(indexName.trim().toLowerCase());
}
return cat(urlAfter.toString(), JSONArray.class).getBody();
}
/**
* 索引是否存在
*/
public boolean indexExists(String indexName) {
try {
JSONArray array = getIndices(indexName);
return array != null;
} catch (org.springframework.web.client.HttpClientErrorException ex) {
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
return false;
} else {
throw ex;
}
}
}
/**
* 根据ID获取索引数据,未查询到返回null
* <p>
* 查询地址:GET http://{baseUrl}/{indexName}/{typeName}/{dataId}
*
* @param indexName 索引名称
* @param typeName type,一个任意字符串,用于分类
* @param dataId 数据id
* @return
*/
public JSONObject getDataById(String indexName, String typeName, String dataId) {
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
log.info("url:" + url);
JSONObject result = RestUtil.get(url);
boolean found = result.getBoolean("found");
if (found) {
return result.getJSONObject("_source");
} else {
return null;
}
}
/**
* 创建索引
* <p>
* 查询地址:PUT http://{baseUrl}/{indexName}
*/
public boolean createIndex(String indexName) {
String url = this.getBaseUrl(indexName).toString();
/* 返回结果 (仅供参考)
"createIndex": {
"shards_acknowledged": true,
"acknowledged": true,
"index": "hello_world"
}
*/
try {
return RestUtil.put(url).getBoolean("acknowledged");
} catch (org.springframework.web.client.HttpClientErrorException ex) {
if (HttpStatus.BAD_REQUEST == ex.getStatusCode()) {
log.warn("索引创建失败:" + indexName + " 已存在,无需再创建");
} else {
ex.printStackTrace();
}
}
return false;
}
/**
* 删除索引
* <p>
* 查询地址:DELETE http://{baseUrl}/{indexName}
*/
public boolean removeIndex(String indexName) {
String url = this.getBaseUrl(indexName).toString();
try {
return RestUtil.delete(url).getBoolean("acknowledged");
} catch (org.springframework.web.client.HttpClientErrorException ex) {
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
log.warn("索引删除失败:" + indexName + " 不存在,无需删除");
} else {
ex.printStackTrace();
}
}
return false;
}
/**
* 获取索引字段映射(可获取字段类型)
* <p>
*
* @param indexName 索引名称
* @param typeName 分类名称
* @return
*/
public JSONObject getIndexMapping(String indexName, String typeName) {
String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString();
// 针对 es 7.x 版本做兼容
this.getElasticsearchVersion();
if (oConvertUtils.isNotEmpty(this.version) && this.version.startsWith(IE_SEVEN)) {
url += "&include_type_name=true";
}
log.info("getIndexMapping-url:" + url);
/*
* 参考返回JSON结构:
*
*{
* // 索引名称
* "[indexName]": {
* "mappings": {
* // 分类名称
* "[typeName]": {
* "properties": {
* // 字段名
* "input_number": {
* // 字段类型
* "type": "long"
* },
* "input_string": {
* "type": "text",
* "fields": {
* "keyword": {
* "type": "keyword",
* "ignore_above": 256
* }
* }
* }
* }
* }
* }
* }
* }
*/
try {
return RestUtil.get(url);
} catch (org.springframework.web.client.HttpClientErrorException e) {
String message = e.getMessage();
if (message != null && message.contains(URL_NOT_FOUND)) {
return null;
}
throw e;
}
}
/**
* 获取索引字段映射,返回Java实体类
*
* @param indexName
* @param typeName
* @return
*/
public <T> Map<String, T> getIndexMappingFormat(String indexName, String typeName, Class<T> clazz) {
JSONObject mapping = this.getIndexMapping(indexName, typeName);
Map<String, T> map = new HashMap<>(5);
if (mapping == null) {
return map;
}
// 获取字段属性
JSONObject properties = mapping.getJSONObject(indexName)
.getJSONObject("mappings")
.getJSONObject(typeName)
.getJSONObject("properties");
// 封装成 java类型
for (String key : properties.keySet()) {
T entity = properties.getJSONObject(key).toJavaObject(clazz);
map.put(key, entity);
}
return map;
}
/**
* 保存数据,详见:saveOrUpdate
*/
public boolean save(String indexName, String typeName, String dataId, JSONObject data) {
return this.saveOrUpdate(indexName, typeName, dataId, data);
}
/**
* 更新数据,详见:saveOrUpdate
*/
public boolean update(String indexName, String typeName, String dataId, JSONObject data) {
return this.saveOrUpdate(indexName, typeName, dataId, data);
}
/**
* 保存或修改索引数据
* <p>
* 查询地址:PUT http://{baseUrl}/{indexName}/{typeName}/{dataId}
*
* @param indexName 索引名称
* @param typeName type,一个任意字符串,用于分类
* @param dataId 数据id
* @param data 要存储的数据
* @return
*/
public boolean saveOrUpdate(String indexName, String typeName, String dataId, JSONObject data) {
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).append("?refresh=wait_for").toString();
/* 返回结果(仅供参考)
"createIndexA2": {
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_index": "test_index_1",
"_type": "test_type_1",
"_id": "a2",
"_version": 1,
"_primary_term": 1
}
*/
try {
// 去掉 data 中为空的值
Set<String> keys = data.keySet();
List<String> emptyKeys = new ArrayList<>(keys.size());
for (String key : keys) {
String value = data.getString(key);
//1、剔除空值
if (oConvertUtils.isEmpty(value) || "[]".equals(value)) {
emptyKeys.add(key);
}
//2、剔除上传控件值(会导致ES同步失败,报异常failed to parse field [ge_pic] of type [text] )
if (oConvertUtils.isNotEmpty(value) && value.indexOf("[{") != -1) {
emptyKeys.add(key);
log.info("-------剔除上传控件字段------------key: " + key);
}
}
for (String key : emptyKeys) {
data.remove(key);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
String result = RestUtil.put(url, data).getString("result");
return "created".equals(result) || "updated".equals(result);
} catch (Exception e) {
log.error(e.getMessage() + "\n-- url: " + url + "\n-- data: " + data.toJSONString());
//TODO 打印接口返回异常json
return false;
}
}
/**
* 批量保存数据
*
* @param indexName 索引名称
* @param typeName type,一个任意字符串,用于分类
* @param dataList 要存储的数据数组,每行数据必须包含id
* @return
*/
public boolean saveBatch(String indexName, String typeName, JSONArray dataList) {
String url = this.getBaseUrl().append("/_bulk").append("?refresh=wait_for").toString();
StringBuilder bodySb = new StringBuilder();
for (int i = 0; i < dataList.size(); i++) {
JSONObject data = dataList.getJSONObject(i);
String id = data.getString("id");
// 该行的操作
// {"create": {"_id":"${id}", "_index": "${indexName}", "_type": "${typeName}"}}
JSONObject action = new JSONObject();
JSONObject actionInfo = new JSONObject();
actionInfo.put("_id", id);
actionInfo.put("_index", indexName);
actionInfo.put("_type", typeName);
action.put("create", actionInfo);
bodySb.append(action.toJSONString()).append("\n");
// 该行的数据
data.remove("id");
bodySb.append(data.toJSONString()).append("\n");
}
System.out.println("+-+-+-: bodySb.toString(): " + bodySb.toString());
HttpHeaders headers = RestUtil.getHeaderApplicationJson();
RestUtil.request(url, HttpMethod.PUT, headers, null, bodySb, JSONObject.class);
return true;
}
/**
* 删除索引数据
* <p>
* 请求地址:DELETE http://{baseUrl}/{indexName}/{typeName}/{dataId}
*/
public boolean delete(String indexName, String typeName, String dataId) {
String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
/* 返回结果(仅供参考)
{
"_index": "es_demo",
"_type": "docs",
"_id": "001",
"_version": 3,
"result": "deleted",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 28,
"_primary_term": 18
}
*/
try {
return "deleted".equals(RestUtil.delete(url).getString("result"));
} catch (org.springframework.web.client.HttpClientErrorException ex) {
if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
return false;
} else {
throw ex;
}
}
}
/* = = = 以下关于查询和查询条件的方法 = = =*/
/**
* 查询数据
* <p>
* 请求地址:POST http://{baseUrl}/{indexName}/{typeName}/_search
*/
public JSONObject search(String indexName, String typeName, JSONObject queryObject) {
String url = this.getBaseUrl(indexName, typeName).append("/_search").toString();
log.info("url:" + url + " ,search: " + queryObject.toJSONString());
JSONObject res = RestUtil.post(url, queryObject);
log.info("url:" + url + " ,return res: \n" + res.toJSONString());
return res;
}
/**
* @param source (源滤波器)指定返回的字段,传null返回所有字段
* @param query
* @param from 从第几条数据开始
* @param size 返回条目数
* @return { "query": query }
*/
public JSONObject buildQuery(List<String> source, JSONObject query, int from, int size) {
JSONObject json = new JSONObject();
if (source != null) {
json.put("_source", source);
}
json.put("query", query);
json.put("from", from);
json.put("size", size);
return json;
}
/**
* @return { "bool" : { "must": must, "must_not": mustNot, "should": should } }
*/
public JSONObject buildBoolQuery(JSONArray must, JSONArray mustNot, JSONArray should) {
JSONObject bool = new JSONObject();
if (must != null) {
bool.put("must", must);
}
if (mustNot != null) {
bool.put("must_not", mustNot);
}
if (should != null) {
bool.put("should", should);
}
JSONObject json = new JSONObject();
json.put("bool", bool);
return json;
}
/**
* @param field 要查询的字段
* @param args 查询参数,参考: *哈哈* OR *哒* NOT *呵* OR *啊*
* @return
*/
public JSONObject buildQueryString(String field, String... args) {
if (field == null) {
return null;
}
StringBuilder sb = new StringBuilder(field).append(":(");
if (args != null) {
for (String arg : args) {
sb.append(arg).append(" ");
}
}
sb.append(")");
return this.buildQueryString(sb.toString());
}
/**
* @return { "query_string": { "query": query } }
*/
public JSONObject buildQueryString(String query) {
JSONObject queryString = new JSONObject();
queryString.put("query", query);
JSONObject json = new JSONObject();
json.put("query_string", queryString);
return json;
}
/**
* @param field 查询字段
* @param min 最小值
* @param max 最大值
* @param containMin 范围内是否包含最小值
* @param containMax 范围内是否包含最大值
* @return { "range" : { field : { 『 "gt『e』?containMin" : min 』?min!=null , 『 "lt『e』?containMax" : max 』}} }
*/
public JSONObject buildRangeQuery(String field, Object min, Object max, boolean containMin, boolean containMax) {
JSONObject inner = new JSONObject();
if (min != null) {
if (containMin) {
inner.put("gte", min);
} else {
inner.put("gt", min);
}
}
if (max != null) {
if (containMax) {
inner.put("lte", max);
} else {
inner.put("lt", max);
}
}
JSONObject range = new JSONObject();
range.put(field, inner);
JSONObject json = new JSONObject();
json.put("range", range);
return json;
}
}
@@ -0,0 +1,99 @@
package org.jeecg.common.es;
/**
* 用于创建 ElasticSearch 的 queryString
*
* @author sunjianlei
*/
public class QueryStringBuilder {
StringBuilder builder;
public QueryStringBuilder(String field, String str, boolean not, boolean addQuot) {
builder = this.createBuilder(field, str, not, addQuot);
}
public QueryStringBuilder(String field, String str, boolean not) {
builder = this.createBuilder(field, str, not, true);
}
/**
* 创建 StringBuilder
*
* @param field
* @param str
* @param not 是否是不匹配
* @param addQuot 是否添加双引号
* @return
*/
public StringBuilder createBuilder(String field, String str, boolean not, boolean addQuot) {
StringBuilder sb = new StringBuilder(field).append(":(");
if (not) {
sb.append(" NOT ");
}
this.addQuotEffect(sb, str, addQuot);
return sb;
}
public QueryStringBuilder and(String str) {
return this.and(str, true);
}
public QueryStringBuilder and(String str, boolean addQuot) {
builder.append(" AND ");
this.addQuot(str, addQuot);
return this;
}
public QueryStringBuilder or(String str) {
return this.or(str, true);
}
public QueryStringBuilder or(String str, boolean addQuot) {
builder.append(" OR ");
this.addQuot(str, addQuot);
return this;
}
public QueryStringBuilder not(String str) {
return this.not(str, true);
}
public QueryStringBuilder not(String str, boolean addQuot) {
builder.append(" NOT ");
this.addQuot(str, addQuot);
return this;
}
/**
* 添加双引号(模糊查询,不能加双引号)
*/
private QueryStringBuilder addQuot(String str, boolean addQuot) {
return this.addQuotEffect(this.builder, str, addQuot);
}
/**
* 是否在两边加上双引号
*
* @param builder
* @param str
* @param addQuot
* @return
*/
private QueryStringBuilder addQuotEffect(StringBuilder builder, String str, boolean addQuot) {
if (addQuot) {
builder.append('"');
}
builder.append(str);
if (addQuot) {
builder.append('"');
}
return this;
}
@Override
public String toString() {
return builder.append(")").toString();
}
}
@@ -0,0 +1,7 @@
package org.jeecg.common.exception;
public class ExceptionAssertsUtil {
public static void fail(String message) {
throw new JeecgBootException(message);
}
}
@@ -0,0 +1,21 @@
package org.jeecg.common.exception;
/**
* @Description: jeecg-boot自定义401异常
* @author: jeecg-boot
*/
public class JeecgBoot401Exception extends RuntimeException {
private static final long serialVersionUID = 1L;
public JeecgBoot401Exception(String message) {
super(message);
}
public JeecgBoot401Exception(Throwable cause) {
super(cause);
}
public JeecgBoot401Exception(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,21 @@
package org.jeecg.common.exception;
/**
* @Description: jeecg-boot自定义异常
* @author: jeecg-boot
*/
public class JeecgBootException extends RuntimeException {
private static final long serialVersionUID = 1L;
public JeecgBootException(String message) {
super(message);
}
public JeecgBootException(Throwable cause) {
super(cause);
}
public JeecgBootException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,189 @@
package org.jeecg.common.exception;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.enums.SentinelErrorInfoEnum;
import org.jeecg.config.feign.FeignResponseException;
import org.jeecg.util.XssUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.connection.PoolException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.validation.ConstraintViolationException;
/**
* 异常处理器
*
* @Author scott
* @Date 2019
*/
@RestControllerAdvice
@Slf4j
public class JeecgBootExceptionHandler implements ResponseBodyAdvice<String> {
@Value("${spring.servlet.multipart.maxFileSize:'10MB'}")
private String maxUploadSize;
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBootException.class)
public Result<?> handleJeecgBootException(JeecgBootException e) {
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
/**
* 处理自定义微服务异常
*/
@ExceptionHandler(JeecgCloudException.class)
public Result<?> handleJeecgCloudException(JeecgCloudException e) {
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBoot401Exception.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleJeecgBoot401Exception(JeecgBoot401Exception e) {
log.error(e.getMessage(), e);
return new Result<>(401, e.getMessage());
}
@ExceptionHandler(FeignResponseException.class)
public Result<?> handleJeecgCloudException(FeignResponseException e) {
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public Result<?> handlerNoFoundException(Exception e) {
log.error(e.getMessage(), e);
return Result.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public Result<?> handleDuplicateKeyException(DuplicateKeyException e) {
log.error(e.getMessage(), e);
return Result.error("数据库中已存在该记录");
}
@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
public Result<?> handleAuthorizationException(AuthorizationException e) {
log.error(e.getMessage(), e);
return Result.noauth("没有权限,请联系管理员授权");
}
@ExceptionHandler(Exception.class)
public Result<?> handleException(Exception e) {
log.error(e.getMessage(), e);
//update-begin---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常
Throwable throwable = e.getCause();
SentinelErrorInfoEnum errorInfoEnum = SentinelErrorInfoEnum.getErrorByException(throwable);
if (ObjectUtil.isNotEmpty(errorInfoEnum)) {
return Result.error(errorInfoEnum.getError());
}
//update-end---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常
return Result.error("系统异常,请稍后再试", e.getMessage());
}
/**
* @param e
* @return
* @Author 政辉
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Result<?> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
StringBuffer sb = new StringBuffer();
sb.append("不支持");
sb.append(e.getMethod());
sb.append("请求方法,");
sb.append("支持以下");
String[] methods = e.getSupportedMethods();
if (methods != null) {
for (String str : methods) {
sb.append(str);
sb.append("");
}
}
log.error(sb.toString(), e);
//return Result.error("没有权限,请联系管理员授权");
Result<Object> result = Result.error(405, "请求方法不支持");
result.setResult(sb.toString());
return result;
}
/**
* spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
log.error(e.getMessage(), e);
return Result.error("文件大小超出限制", "文件大小超出" + maxUploadSize + "限制, 请压缩或降低文件质量! ");
}
@ExceptionHandler(DataIntegrityViolationException.class)
public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
log.error(e.getMessage(), e);
//【issues/3624】数据库执行异常handleDataIntegrityViolationException提示有误 #3624
return Result.error("系统异常,请稍后再试", "执行数据库异常,违反了完整性例如:违反惟一约束、违反非空限制、字段内容超出长度等");
}
@ExceptionHandler(PoolException.class)
public Result<?> handlePoolException(PoolException e) {
log.error(e.getMessage(), e);
return Result.error("系统异常,请稍后再试", "Redis 连接异常!");
}
/**
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
// @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Object handleMethodArgumentNotValidException(BindException e) {
StringBuilder sb = new StringBuilder("参数校验失败:");
for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
sb.append(fieldError.getDefaultMessage()).append(",");
}
log.warn("参数校验失败: {}", sb);
return Result.error(sb.substring(0, sb.length() - 1));
}
@ExceptionHandler(ConstraintViolationException.class)
// @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<?> handleValidationException(ConstraintViolationException e) {
log.error(e.getMessage(), e);
return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),e.getMessage());
}
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return returnType.getParameterType().equals(String.class);
}
@Override
public String beforeBodyWrite(String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
return XssUtils.scriptXss(body);
}
}
@@ -0,0 +1,19 @@
package org.jeecg.common.export;
import com.alibaba.excel.EasyExcel;
import java.io.OutputStream;
import java.util.List;
/**
* @author Jiang Shunzhi
*/
public interface EasyExcelExportHandler<T, U> extends ExportWriter<T, U> {
default void doWrite(OutputStream outputStream, List<T> data) {
EasyExcel.write(outputStream, getExportClass())
.sheet(getSheetName())
.doWrite(data);
}
}
@@ -0,0 +1,174 @@
package org.jeecg.common.export;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import org.jeecg.common.util.MyUploadUtil;
import org.slf4j.Logger;
import org.springframework.core.task.AsyncTaskExecutor;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Future;
/**
* 导出统一处理接口,泛型T为导出数据POJO类,泛型U为参数类
*
* @author Jiang Shunzhi
*/
public interface ExportHandler<T, U> {
/**
* 辅助方法,
*
* @return 获取数据POJO类
*/
Class<T> getExportClass();
/**
* 获取导出任务Code
*
* @return 导出任务Code
*/
String getCode();
/**
* 获取导出标题,使用于表头上标题、导出文件名前缀
*
* @return 导出标题
*/
String getTitle();
/**
* 获取Sheet名称,默认逻辑取{@link #getTitle()}
*
* @return Sheet名称
*/
default String getSheetName() {
return getTitle();
}
/**
* 获取AsyncTaskExecutor对象
*
* @return AsyncTaskExecutor对象
*/
AsyncTaskExecutor getAsyncTaskExecutor();
/**
* 获取导出数据
*
* @return 导出数据
*/
List<T> getData(U params);
/**
* 获取导出文件输入流
*
* @param data 导出数据,默认逻辑为{@link #getData(U)}中返回的数据
* @return 导出文件输入流
* @throws Exception 操作流时产生的可能异常
*/
InputStream getExportInputStream(List<T> data) throws Exception;
/**
* 获取日志类
*
* @return 日志类
*/
Logger getLogger();
/**
* 获取导出文件扩展名,默认为xlsx
*
* @return 导出文件扩展名
*/
default String getExportExtName() {
return "xlsx";
}
/**
* 获取文件保存业务路径
*
* @return 文件保存业务路径
*/
default String getBizPath() {
return "";
}
/**
* 获取需要传递的ThreadLocal对象,默认为null
*
* @return 需要传递的ThreadLocal对象
*/
default ThreadLocal<?> getThreadLocal() {
return null;
}
/**
* 执行导出
*
* @param params 参数对象
*/
default void export(U params) {
List<T> exportList;
try {
exportList = getData(params);
} catch (Exception e) {
getLogger().error("查询导出数据出错:{} PARAMS: {}", getTitle(), JSON.toJSONString(params), e);
ExportUtils.exportErrorUpdate("查询导出数据出错");
doFinally();
return;
}
int dataSize = exportList.size();
ExportUtils.exportStartUpdate(dataSize, getTitle());
InputStream inputStream;
try {
inputStream = getExportInputStream(exportList);
} catch (Exception e) {
getLogger().error("生成导出文件有误:{} PARAMS: {}", getTitle(), JSON.toJSONString(params), e);
ExportUtils.exportErrorUpdate("生成导出文件有误");
doFinally();
return;
}
try {
String filename = ExportUtils.filename(getTitle(), getExportExtName());
String bizPath = MyUploadUtil.EXPORT_BIZ + getBizPath();
String filePath = MyUploadUtil.upload(inputStream, bizPath, filename);
if (StrUtil.isEmpty(filePath)) {
getLogger().error("上传导出文件有误:{} PARAMS: {}", getTitle(), JSON.toJSONString(params));
ExportUtils.exportErrorUpdate("生成导出文件有误");
doFinally();
return;
}
ExportUtils.exportFinishUpdate(dataSize, filePath);
} catch (Exception e) {
getLogger().error("上传导出文件有误:{} PARAMS: {}", getTitle(), JSON.toJSONString(params), e);
ExportUtils.exportErrorUpdate("生成导出文件有误");
}
doFinally();
}
/**
* 异步执行导出
*
* @param params 参数对象
* @return 线程池返回Future对象
*/
default Future<?> exportAsync(U params) {
return ExportUtils.exportTaskExecute(getCode(), getAsyncTaskExecutor(), () -> {
try {
export(params);
} catch (Exception e) {
getLogger().error("{}异步导出出错", getTitle(), e);
}
}, getThreadLocal()
);
}
/**
* 最终执行,默认为空方法
*/
default void doFinally() {
}
}
@@ -0,0 +1,225 @@
package org.jeecg.common.export;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.jeecg.cloud.ImportExportApi;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.global.GlobalUtils;
import org.jeecg.modules.exports.entity.CommonExportsInfo;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.springframework.core.task.AsyncTaskExecutor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Future;
/**
* @author Jiang Shunzhi
*/
@Slf4j
public class ExportUtils {
public static final ThreadLocal<CommonExportsInfo> EXPORT_LOCAL = new ThreadLocal<>();
private static ImportExportApi importExportApi;
public static CommonExportsInfo newExportsInfo(String taskCode, String title) {
CommonExportsInfo info = new CommonExportsInfo();
Date now = new Date();
info.setBatchNo(String.valueOf(System.currentTimeMillis()));
info.setExportMsg(title);
info.setHandleMsg("0/0");
info.setCreateBy(getLoginUserId());
info.setCreateDate(now);
info.setTaskCode(taskCode);
info.setExportStatus(Status.DOING);
info.setHandleStartTime(now);
return updateExportInfo(info);
}
public static CommonExportsInfo getExportsInfo() {
return EXPORT_LOCAL.get();
}
public static CommonExportsInfo getUpdateExportsInfo() {
return new CommonExportsInfo().setId(EXPORT_LOCAL.get().getId());
}
public static ImportExportApi getImportExportApi() {
if (Objects.isNull(importExportApi)) {
importExportApi = SpringContextUtils.getBean(ImportExportApi.class);
}
return importExportApi;
}
private static String getLoginUserId() {
try {
LoginUser loginUser = GlobalUtils.getLoginUser();
return loginUser.getId();
} catch (Exception e) {
log.error("Login User Fetch Error.", e);
return "";
}
}
public static CommonExportsInfo getExportsInfoUpdated() {
return Optional.ofNullable(getExportsInfo())
.map(info -> getImportExportApi().getExportsInfoById(info.getId()))
.orElse(null);
}
public static CommonExportsInfo getExportsInfoById(String id) {
return getImportExportApi().getExportsInfoById(id);
}
public static CommonExportsInfo newExportsInfo(String taskCode) {
return newExportsInfo(taskCode, null);
}
public static <T> Future<?> exportTaskExecute(String taskCode, AsyncTaskExecutor executor, Runnable runnable, ThreadLocal<T> threadLocal) {
Boolean flag = getImportExportApi().getFinishFlagByCode(taskCode, Status.DOING);
if (!flag) {
throw new RuntimeException("已存在执行中的导出任务,请稍后导出或点击【查看导出任务】查看任务导出进度!");
}
CommonExportsInfo info = newExportsInfo(taskCode);
Subject subject = null;
try {
subject = SecurityUtils.getSubject();
} catch (Exception e) {
log.warn("Shiro Subject Fetch Error.");
}
Subject finalSubject = subject;
String token = GlobalUtils.getToken();
if (ObjectUtil.isNotNull(threadLocal)) {
T o = threadLocal.get();
return executor.submit(() -> {
UserTokenContext.setToken(token);
threadLocal.set(o);
EXPORT_LOCAL.set(info);
try {
if (finalSubject != null) {
finalSubject.associateWith(runnable).run();
} else {
runnable.run();
}
} finally {
UserTokenContext.remove();
threadLocal.remove();
EXPORT_LOCAL.remove();
}
});
} else {
return executor.submit(() -> {
UserTokenContext.setToken(token);
EXPORT_LOCAL.set(info);
try {
if (finalSubject != null) {
finalSubject.associateWith(runnable).run();
} else {
runnable.run();
}
} finally {
UserTokenContext.remove();
EXPORT_LOCAL.remove();
}
});
}
}
public static CommonExportsInfo updateExportInfo(CommonExportsInfo info) {
return getImportExportApi().updateExportsInfo(info);
}
public static Future<?> exportTaskExecute(String taskCode, AsyncTaskExecutor executor, Runnable runnable) {
return exportTaskExecute(taskCode, executor, runnable, null);
}
public static void exportFinishUpdate(Integer dataSize, String fileUrl) {
CommonExportsInfo info = getUpdateExportsInfo();
info.setHandleMsg(Optional.ofNullable(dataSize).orElse(0) + "/" + Optional.ofNullable(dataSize).orElse(0));
info.setExportUrl(fileUrl);
info.setExportStatus(Status.FINISH);
info.setHandleEndTime(new Date());
updateExportInfo(info);
}
public static void exportStartUpdate(Integer dataSize, String title) {
CommonExportsInfo info = getUpdateExportsInfo();
info.setExportMsg(title);
info.setHandleMsg("0/" + Optional.ofNullable(dataSize).orElse(0));
updateExportInfo(info);
}
public static void exportStartUpdate(Integer dataSize) {
exportStartUpdate(dataSize, null);
}
public static void exportProcessUpdate(Integer currentSize, Integer dataSize) {
CommonExportsInfo info = getUpdateExportsInfo();
info.setHandleMsg(Optional.ofNullable(currentSize).orElse(0) + "/" + Optional.ofNullable(dataSize).orElse(0));
updateExportInfo(info);
}
public static void exportFinishUpdate(String fileUrl) {
exportFinishUpdate(null, fileUrl);
}
public static void exportErrorUpdate(String errorMsg) {
CommonExportsInfo updatedInfo = getExportsInfoUpdated();
CommonExportsInfo info = getUpdateExportsInfo();
info.setExportMsg(errorMsg + "" + updatedInfo.getExportMsg());
info.setExportStatus(Status.DATA_CHECK_ERROR);
info.setHandleEndTime(new Date());
updateExportInfo(info);
}
public static InputStream workbookToInputStream(Workbook workbook) throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
workbook.write(os);
return new ByteArrayInputStream(os.toByteArray());
}
public static String filename(String prefix, String extName) {
return prefix + "_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_FORMAT) + "." + extName;
}
public static <T> Workbook listToExcelAutoPoi(String title, String sheetName, List<T> data, Class<T> clz) {
return ExcelExportUtil.exportExcel(new ExportParams(title, sheetName, ExcelType.XSSF), clz, data);
}
private static String getExtName(Workbook workbook) {
if (workbook instanceof HSSFWorkbook) {
return ".xls";
} else {
return ".xlsx";
}
}
public interface Status {
String DATA_CHECK_ERROR = "2";
String DOING = "7";
String FINISH = "8";
}
}

Some files were not shown because too many files have changed in this diff Show More