新疆后端项目
This commit is contained in:
@@ -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;
|
||||
|
||||
}
|
||||
+27
@@ -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;
|
||||
|
||||
}
|
||||
+34
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -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;
|
||||
}
|
||||
}
|
||||
+92
@@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
+50
@@ -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 "";
|
||||
}
|
||||
+27
@@ -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();
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+19
@@ -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";
|
||||
|
||||
/**
|
||||
* 文件上传类型(本地:local,Minio:minio,阿里云: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://";
|
||||
|
||||
/**
|
||||
* 部门表唯一key,id
|
||||
*/
|
||||
String DEPART_KEY_ID = "id";
|
||||
/**
|
||||
* 部门表唯一key,orgCode
|
||||
*/
|
||||
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";
|
||||
}
|
||||
+16
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -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
|
||||
}
|
||||
+96
@@ -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;
|
||||
}
|
||||
+94
@@ -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;
|
||||
}
|
||||
}
|
||||
+102
@@ -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;
|
||||
}
|
||||
}
|
||||
+21
@@ -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;
|
||||
}
|
||||
+21
@@ -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;
|
||||
}
|
||||
+22
@@ -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;
|
||||
}
|
||||
+82
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
+381
@@ -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 isEncode(true: 加密操作 / 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;
|
||||
}
|
||||
|
||||
}
|
||||
+551
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package org.jeecg.common.exception;
|
||||
|
||||
public class ExceptionAssertsUtil {
|
||||
public static void fail(String message) {
|
||||
throw new JeecgBootException(message);
|
||||
}
|
||||
}
|
||||
+21
@@ -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);
|
||||
}
|
||||
}
|
||||
+189
@@ -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);
|
||||
}
|
||||
}
|
||||
+19
@@ -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
Reference in New Issue
Block a user