Browse Source

初始化

master
Yen 3 months ago
commit
b65c4df52a
  1. 58
      cms-api/cms-admin-svc/pom.xml
  2. 67
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/Application.java
  3. 408
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/AdminPortalController.java
  4. 21
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/CommonApi.java
  5. 120
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/CommonController.java
  6. 122
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/WxMpPortalApi.java
  7. 237
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/WxSvcLoginApi.java
  8. 27
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/dto/CounterResultVo.java
  9. 27
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/dto/SyLoginParam.java
  10. 52
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/BirTask.java
  11. 48
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/BmsTask.java
  12. 32
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/ErpDipatchTask.java
  13. 60
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/GoodsTask.java
  14. 59
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/HisTask.java
  15. 36
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/OmsTask.java
  16. 110
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/PayTask.java
  17. 47
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/SysTask.java
  18. 30
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TagTask.java
  19. 74
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TbsTask.java
  20. 51
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TzcPolicyTask.java
  21. 35
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TzcTask.java
  22. 24
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/WxUserTask.java
  23. 60
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/HistTestController.java
  24. 96
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskActivityController.java
  25. 30
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskPayController.java
  26. 45
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskPolicyController.java
  27. 65
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskSupplierController.java
  28. 106
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskUserController.java
  29. 38
      cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskWechatController.java
  30. 133
      cms-api/cms-admin-svc/src/main/resources/application-dev.yml
  31. 92
      cms-api/cms-admin-svc/src/main/resources/application-pro.yml
  32. 87
      cms-api/cms-admin-svc/src/main/resources/application.yml
  33. 4
      cms-api/cms-admin-svc/src/main/resources/banner.txt
  34. 83
      cms-api/cms-admin-svc/src/main/resources/log4j2.xml
  35. 80
      cms-api/cms-admin-svc/src/main/resources/tx-log4j2.xml
  36. 19
      cms-api/cms-policy-svc/pom.xml
  37. 27
      cms-api/pom.xml
  38. 46
      cms-common/pom.xml
  39. 8
      cms-common/src/main/java/com/qs/serve/common/TestCommon.java
  40. 199
      cms-framework/pom.xml
  41. 24
      cms-framework/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java
  42. 33
      cms-framework/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java
  43. 23
      cms-framework/src/main/java/com/qs/serve/common/config/JwtConfig.java
  44. 83
      cms-framework/src/main/java/com/qs/serve/common/config/RedisConfig.java
  45. 72
      cms-framework/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java
  46. 56
      cms-framework/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java
  47. 25
      cms-framework/src/main/java/com/qs/serve/common/config/properties/AliYunOssProperties.java
  48. 13
      cms-framework/src/main/java/com/qs/serve/common/config/properties/AuthUrlConst.java
  49. 32
      cms-framework/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java
  50. 36
      cms-framework/src/main/java/com/qs/serve/common/config/properties/ProjectApisProperties.java
  51. 31
      cms-framework/src/main/java/com/qs/serve/common/config/properties/ProjectProperties.java
  52. 22
      cms-framework/src/main/java/com/qs/serve/common/config/properties/QiShengDsProperties.java
  53. 25
      cms-framework/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java
  54. 25
      cms-framework/src/main/java/com/qs/serve/common/config/properties/SeeYonProperties.java
  55. 24
      cms-framework/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java
  56. 35
      cms-framework/src/main/java/com/qs/serve/common/framework/annotations/RedisCacheable.java
  57. 4
      cms-framework/src/main/java/com/qs/serve/common/framework/annotations/TagField.java
  58. 133
      cms-framework/src/main/java/com/qs/serve/common/framework/aop/RedisCacheAspect.java
  59. 21
      cms-framework/src/main/java/com/qs/serve/common/framework/exception/BaseException.java
  60. 25
      cms-framework/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java
  61. 153
      cms-framework/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java
  62. 66
      cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java
  63. 29
      cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/LocalDateTimeFormatSerializer.java
  64. 98
      cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java
  65. 52
      cms-framework/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java
  66. 17
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java
  67. 50
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java
  68. 74
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java
  69. 69
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/TableNameAppendHandler.java
  70. 115
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java
  71. 36
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java
  72. 14
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java
  73. 17
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java
  74. 159
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java
  75. 32
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java
  76. 23
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java
  77. 25
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java
  78. 40
      cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java
  79. 415
      cms-framework/src/main/java/com/qs/serve/common/framework/redis/RedisService.java
  80. 30
      cms-framework/src/main/java/com/qs/serve/common/framework/redis/TtlRedisCacheManager.java
  81. 22
      cms-framework/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java
  82. 22
      cms-framework/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java
  83. 97
      cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java
  84. 37
      cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java
  85. 34
      cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java
  86. 28
      cms-framework/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java
  87. 18
      cms-framework/src/main/java/com/qs/serve/common/model/AmountDTO.java
  88. 34
      cms-framework/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java
  89. 20
      cms-framework/src/main/java/com/qs/serve/common/model/annotation/BusinessDifference.java
  90. 25
      cms-framework/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java
  91. 20
      cms-framework/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java
  92. 35
      cms-framework/src/main/java/com/qs/serve/common/model/annotation/SysLog.java
  93. 19
      cms-framework/src/main/java/com/qs/serve/common/model/chart/BiCommonCounter.java
  94. 15
      cms-framework/src/main/java/com/qs/serve/common/model/chart/BiMonthCounter.java
  95. 39
      cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartAxisColumn.java
  96. 148
      cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartDataVo.java
  97. 18
      cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartGroupItem.java
  98. 26
      cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartSeriesItem.java
  99. 75
      cms-framework/src/main/java/com/qs/serve/common/model/chart/PrintChart.java
  100. 13
      cms-framework/src/main/java/com/qs/serve/common/model/consts/ApplyTypeConst.java

58
cms-api/cms-admin-svc/pom.xml

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cms-api</artifactId>
<groupId>com.qs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cms-admin-svc</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.qs</groupId>
<artifactId>cms-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.qs</groupId>
<artifactId>cms-actuator</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.qs</groupId>
<artifactId>cms-system</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<finalName>serve</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.qs.serve.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

67
cms-api/cms-admin-svc/src/main/java/com/qs/serve/Application.java

@ -0,0 +1,67 @@
package com.qs.serve;
import com.qs.serve.common.config.DevEnvironmentConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Indexed;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.TimeZone;
/**
* @author YenHex
* @since 2022/2/24
*/
@Indexed
@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@EnableCaching
@EnableFeignClients
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Value("${project.dev}")
String dev;
public static void main(String[] args) {
long start = System.currentTimeMillis();
SpringApplication.run(Application.class,args);
long end = System.currentTimeMillis();
double diff = (end-start)/1000.0;
System.out.println("启动时间:"+diff
+"\n ____ _ _ __ _ _ \n" +
" / ___| | |_ __ _ _ __ | |_ _ _ _ __ ___ _ _ ___ ___ ___ ___ ___ / _| _ _ | || |\n" +
" \\___ \\ | __|/ _` || '__|| __| | | | || '_ \\ / __|| | | | / __|/ __|/ _ \\/ __|/ __|| |_ | | | || || |\n" +
" ___) || |_| (_| || | | |_ | |_| || |_) | \\__ \\| |_| || (__| (__| __/\\__ \\\\__ \\| _|| |_| || ||_|\n" +
" |____/ \\__|\\__,_||_| \\__| \\__,_|| .__/ |___/ \\__,_| \\___|\\___|\\___||___/|___/|_| \\__,_||_|(_)\n" +
" |_| \n");
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
@PostConstruct
void started() {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
DevEnvironmentConfig.openDevEnv(dev.equals("true"));
}
}

408
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/AdminPortalController.java

@ -0,0 +1,408 @@
package com.qs.serve.controller;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.config.properties.ProjectProperties;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.framework.security.model.LoginUserType;
import com.qs.serve.common.model.annotation.LimitSubmit;
import com.qs.serve.common.model.annotation.SysLog;
import com.qs.serve.common.model.consts.GySysConst;
import com.qs.serve.common.model.consts.RedisCacheKeys;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.model.dto.SimpleKeyValue;
import com.qs.serve.common.model.enums.BizType;
import com.qs.serve.common.util.*;
import com.qs.serve.common.util.model.DateFormatString;
import com.qs.serve.controller.dto.SyLoginParam;
import com.qs.serve.modules.seeyon.SyKeyLoginUtil;
import com.qs.serve.modules.bms.service.BmsSupplierAddressService;
import com.qs.serve.modules.goods.entity.GoodsCategory;
import com.qs.serve.modules.goods.entity.GoodsSku;
import com.qs.serve.modules.goods.entity.GoodsSpu;
import com.qs.serve.modules.goods.mapper.GoodsImminentBatchMapper;
import com.qs.serve.modules.goods.service.GoodsCategoryRuleService;
import com.qs.serve.modules.goods.service.GoodsCategoryService;
import com.qs.serve.modules.goods.service.GoodsSkuService;
import com.qs.serve.modules.goods.service.GoodsSpuService;
import com.qs.serve.modules.oms.entity.OmsOrder;
import com.qs.serve.modules.oms.entity.OmsOrderItem;
import com.qs.serve.modules.oms.entity.OmsSaleOrder;
import com.qs.serve.modules.oms.entity.OmsSaleOrderItem;
import com.qs.serve.modules.oms.mapper.OmsOrderMapper;
import com.qs.serve.modules.oms.service.OmsOrderItemService;
import com.qs.serve.modules.oms.service.OmsOrderService;
import com.qs.serve.modules.oms.service.OmsSaleOrderItemService;
import com.qs.serve.modules.oms.service.OmsSaleOrderService;
import com.qs.serve.modules.seeyon.entity.SyAffairStateResult;
import com.qs.serve.modules.seeyon.enums.SyAffairState;
import com.qs.serve.modules.seeyon.service.SeeYonRequestService;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.sys.entity.SysTenant;
import com.qs.serve.modules.sys.entity.SysUser;
import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam;
import com.qs.serve.modules.sys.entity.dto.SysLoginParam;
import com.qs.serve.modules.sys.entity.dto.SysResetPwdByPhoneParam;
import com.qs.serve.modules.sys.service.SysTenantService;
import com.qs.serve.modules.sys.service.SysUserLoginService;
import com.qs.serve.modules.sys.service.SysUserService;
import com.qs.serve.modules.tbs.common.TbsSeeYonConst;
import com.qs.serve.modules.tbs.entity.TbsActivity;
import com.qs.serve.modules.tbs.entity.TbsCostApply;
import com.qs.serve.modules.tbs.service.TbsActivityService;
import com.qs.serve.modules.tbs.service.TbsCostApplyService;
import com.qs.serve.modules.tzc.entity.TzcPolicy;
import com.qs.serve.modules.tzc.service.TzcPolicyService;
import com.qs.serve.modules.vtb.entity.VtbVerification;
import com.qs.serve.modules.vtb.entity.VtbVerificationBatch;
import com.qs.serve.modules.vtb.service.VtbVerificationBatchService;
import com.qs.serve.modules.vtb.service.VtbVerificationService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 门户后台接口
* @author YenHex
* @since 2022/3/2
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("portal")
public class AdminPortalController {
private SysTenantService sysTenantService;
private SysUserLoginService sysUserLoginService;
private RedisService redisService;
private SysUserService sysUserService;
private ProjectProperties projectProperties;
private SeeYonRequestService seeYonRequestService;
private TbsCostApplyService costApplyService;
private VtbVerificationService verificationService;
private VtbVerificationBatchService verificationBatchService;
private TzcPolicyService policyService;
private TbsActivityService activityService;
private GoodsImminentBatchMapper goodsImminentBatchMapper;
private OmsOrderMapper omsOrderMapper;
private OmsOrderService omsOrderService;
private OmsOrderItemService omsOrderItemService;
private OmsSaleOrderService omsSaleOrderService;
private OmsSaleOrderItemService omsSaleOrderItemService;
private BmsSupplierAddressService bmsSupplierAddressService;
private GoodsCategoryRuleService goodsCategoryRuleService;
private GoodsSpuService goodsSpuService;
private GoodsSkuService goodsSkuService;
private GoodsCategoryService goodsCategoryService;
@GetMapping("/getSystemTime")
public R<?> getSystemTime(){
return R.ok(DateUtils.format(LocalDateTime.now(), DateFormatString.DATE_TIME));
}
/**
* 获取所有租户
* @return
*/
@GetMapping("/listTenant")
public R<List<SysTenant>> getList(){
List<SysTenant> list = sysTenantService.list2();
return R.ok(list);
}
/**
* 致远远程跳转接口
* @param param
* @param response
* @throws IOException
*/
@GetMapping("/syKeyLogin")
public void getList(SyLoginParam param, HttpServletResponse response) throws IOException {
String templateCode = param.getTemplateCode();
String syId = param.getSyId();
// dev remove
if(!StringUtils.hasText(syId)){
response.sendRedirect(projectProperties.getWebUrl()+"/#/login?");
return;
}
String key = param.getKey();
SyAffairStateResult affairStateResult = seeYonRequestService.checkAffairState(key,syId,templateCode);
// dev add
//syId = affairStateResult.getMemberId();
if(affairStateResult.getState()==SyAffairState.error){
response.sendRedirect(projectProperties.getWebUrl()+"/#/login?");
return;
}
//通过类型和key获取审批id
String targetId = affairStateResult.getTargetId();
String affairId = affairStateResult.getAffairId();
String memberId = affairStateResult.getMemberId();
//通过syId生成token
String token = sysUserLoginService.loginBySyUserId(syId);
if(token==null){
response.sendRedirect(projectProperties.getWebUrl()+"/#/login?");
return;
}else {
String jumpUrl = "404";
SyAffairState affairState = affairStateResult.getState();
if(affairState!=SyAffairState.none&&affairState!=SyAffairState.error){
//判断是否当前人员
if(syId.equals(memberId)){
//待审列表
if (affairState==SyAffairState.next){
if(templateCode.equals(TbsSeeYonConst.BatchCostCheckConf.Code())){
VtbVerificationBatch object = verificationBatchService.getById(targetId);
jumpUrl = SyKeyLoginUtil.getUnCheckedUrl4BatchVerification(object.getCostApplyId(),affairId,object.getId());
}else if(templateCode.equals(TbsSeeYonConst.CostCheckConf.Code())){
VtbVerification object = verificationService.getById(targetId);
TbsActivity activity = activityService.getById(object.getActivityId());
jumpUrl = SyKeyLoginUtil.getPreCheckUrl4Verification(activity.getCostApplyId(),activity.getId(),object.getId(),affairId);
}else{
jumpUrl = SyKeyLoginUtil.getPreCheckUrl(templateCode,targetId,affairId);
}
}else {
if(templateCode.equals(TbsSeeYonConst.BatchCostCheckConf.Code())){
VtbVerificationBatch object = verificationBatchService.getById(targetId);
jumpUrl = SyKeyLoginUtil.getCheckedUrl4BatchVerification(object.getCostApplyId(),affairId,object.getId());
}else if(templateCode.equals(TbsSeeYonConst.CostCheckConf.Code())){
VtbVerification object = verificationService.getById(targetId);
TbsActivity activity = activityService.getById(object.getActivityId());
jumpUrl = SyKeyLoginUtil.getCheckedDetailUrl4Verification(activity.getCostApplyId(),activity.getId(),object.getId());
}else{
jumpUrl = SyKeyLoginUtil.getCheckedDetailUrl(templateCode,targetId);
}
}
}else{
//判断是否创建人,创建人则跳转到详情
SysUser sysUser = sysUserService.getBySyId(syId);
String creator = null;
//非当前表单用户跳转到404页面
if(templateCode.equals(TbsSeeYonConst.CostApplyConf.Code())){
TbsCostApply object = costApplyService.getById(targetId);
creator = object.getCreateBy();
}else if(templateCode.equals(TbsSeeYonConst.CostCheckConf.Code())){
VtbVerification object = verificationService.getById(targetId);
creator = object.getCreateBy();
}else if(templateCode.equals(TbsSeeYonConst.BatchCostCheckConf.Code())){
VtbVerificationBatch object = verificationBatchService.getById(targetId);
creator = object.getCreateBy();
}else if(templateCode.equals(TbsSeeYonConst.PolicyConf.Code())){
TzcPolicy object = policyService.getById(targetId);
creator = object.getCreateBy();
}
if(creator!=null&&creator.equals(sysUser.getId())){
jumpUrl = SyKeyLoginUtil.getMyDetailUrl(templateCode,targetId);
}
}
}
String fontUrl = projectProperties.getWebUrl() + "/#/jump?code=001&token="+token+"&jumpTo="+jumpUrl;
log.warn("fontUrl:{}",fontUrl);
response.sendRedirect(fontUrl);
}
}
/**
* 登录接口
* @return
*/
@LimitSubmit
@SysLog(title = "人员",desc = "后台登录",biz = BizType.LOGIN,saveReqParam = false)
@PostMapping("/login")
public R<?> login(@RequestBody @Valid SysLoginParam param){
return R.ok(sysUserLoginService.login(param));
}
/**
* 登录接口
* @return
*/
@PostMapping("/flushToken")
public R<?> flushToken(HttpServletRequest request){
String token = request.getHeader(GySysConst.AUTHORIZATION_PROP);
String userId = JwtUtils.getUserId(token);
String client = JwtUtils.getClient(token);
String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,userId);
Map<String,Object> tokenMap = new HashMap<>(10);
String token2 = JwtUtils.generateToken(userId, LoginUserType.SYS_USER,client);
redisService.set(redisKey,token2);
tokenMap.put("token", token2);
tokenMap.put("client",client);
return R.ok(tokenMap);
}
/**
* 手机登陆
* @return
*/
@LimitSubmit
@SysLog(title = "人员",desc = "手机登陆",biz = BizType.LOGIN,saveReqParam = false)
@PostMapping("/phoneLogin")
public R<?> phoneLogin(@RequestBody @Valid SysLoginByPhoneParam param){
return R.ok(sysUserLoginService.login(param));
}
/**
* 登出接口
* @return
*/
@SysLog(title = "人员",desc = "退出登录",biz = BizType.LOGOUT,saveReqParam = false)
@GetMapping("/logout")
public R<?> login(){
return R.ok();
}
/**
* 获取用户手机验证码
*/
@LimitSubmit(interval = 10000,message = "请10秒后尝试")
@SysLog(title = "人员",desc = "获取用户手机验证码",biz = BizType.OTHER)
@GetMapping("/userPhoneCode/{phone}")
public R<?> phoneCode(@PathVariable("phone") String phone){
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getAccount,phone);
Long count = sysUserService.count(wrapper);
if(count<1L){
return R.error("无效手机号,请重新输入");
}
String key = RedisCacheKeys.PHONE_KEY+phone;
String code = redisService.getString(key);
if(code==null){
code = IdUtil.genCode(6);
}
redisService.set(key,code,1, TimeUnit.MINUTES);
// send msg
return R.ok();
}
/**
* 重置手机用户密码
*/
@LimitSubmit(interval = 10000,message = "请10秒后尝试")
@SysLog(title = "人员",desc = "重置手机用户密码",biz = BizType.RESET)
@PostMapping("/resetPwdByPhone")
public R<?> phoneCode(@RequestBody @Valid SysResetPwdByPhoneParam param){
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getAccount,param.getPhone());
List<SysUser> userList = sysUserService.list(wrapper);
if(userList.size()<1){
return R.error("无效手机号,请重新输入");
}
String key = RedisCacheKeys.PHONE_KEY+param.getPhone();
String code = redisService.getString(key);
if(!param.getCode().equals(code)){
return R.error("验证码无效或过期");
}
SysUser sysUser = new SysUser();
sysUser.setId(userList.get(0).getId());
sysUser.setPassword(SecureUtil.md5(param.getNewPwd()));
sysUserService.updateById(sysUser);
return R.ok();
}
/**
* 根据ID查询
* @param id
* @return
*/
@GetMapping("/getOrder/{id}")
public R<OmsOrder> getById(@PathVariable("id") String id,String supplierId){
AuthContextUtils.setTenant("001");
OmsOrder omsOrder = omsOrderService.getById(id);
if(omsOrder==null){return R.errorNotFound();}
omsOrder.setBrandRuleInfo(goodsCategoryRuleService.getById(omsOrder.getBrandRuleId()));
omsOrder.setAddressInfo(bmsSupplierAddressService.getById(omsOrder.getSupplierAddrId()));
// 关联折扣信息
if(StringUtils.hasText(omsOrder.getOaRateId())){
SimpleKeyValue obj = omsOrderMapper.getExpiredRateInfo(omsOrder.getOaRateId());
omsOrder.setDiscountRateInfo(obj);
}
if(omsOrder.getSupplierId().toString().equals(supplierId)){
LambdaQueryWrapper<OmsOrderItem> lqw = new LambdaQueryWrapper<>();
lqw.eq(OmsOrderItem::getOrderId,id);
List<OmsOrderItem> list = omsOrderItemService.list(lqw);
for (OmsOrderItem orderItem : list) {
GoodsSpu goodsSpu = goodsSpuService.getById(orderItem.getSpuId());
GoodsCategory goodsCategory = goodsCategoryService.getById(goodsSpu.getCategoryLast());
orderItem.setCategoryInfo(goodsCategory);
orderItem.setSpuInfo(goodsSpu);
GoodsSku goodsSku = goodsSkuService.getById(orderItem.getSkuId());
if(goodsSku!=null){
orderItem.setSkuSpecialFlag(goodsSku.getSpecialFlag());
}
//临期品添加批次对象
if(omsOrder.getOrderType().equals(3)&&orderItem.getSkuBatchId()!=null){
orderItem.setBatchInfo(goodsImminentBatchMapper.selectById(orderItem.getSkuBatchId()));
}
}
omsOrder.setOrderItems(list);
return R.ok(omsOrder);
}
return R.error();
}
/**
* 根据ID查询
* @param id
* @return
*/
@GetMapping("/getSaleOrder/{id}")
public R<OmsSaleOrder> getSaleOrderById(@PathVariable("id") String id, String supplierId){
AuthContextUtils.setTenant("001");
OmsSaleOrder omsOrder = omsSaleOrderService.getById(id);
if(omsOrder==null){return R.errorNotFound();}
omsOrder.setBrandRuleInfo(goodsCategoryRuleService.getById(omsOrder.getBrandRuleId()));
omsOrder.setAddressInfo(bmsSupplierAddressService.getById(omsOrder.getSupplierAddrId()));
// 关联折扣信息
if(StringUtils.hasText(omsOrder.getOaRateId())){
SimpleKeyValue obj = omsOrderMapper.getExpiredRateInfo(omsOrder.getOaRateId());
omsOrder.setDiscountRateInfo(obj);
}
if(omsOrder.getSupplierId().toString().equals(supplierId)){
LambdaQueryWrapper<OmsSaleOrderItem> lqw = new LambdaQueryWrapper<>();
lqw.eq(OmsSaleOrderItem::getOrderId,id);
List<OmsSaleOrderItem> list = omsSaleOrderItemService.list(lqw);
for (OmsSaleOrderItem orderItem : list) {
GoodsSpu goodsSpu = goodsSpuService.getById(orderItem.getSpuId());
GoodsCategory goodsCategory = goodsCategoryService.getById(goodsSpu.getCategoryLast());
orderItem.setCategoryInfo(goodsCategory);
orderItem.setSpuInfo(goodsSpu);
GoodsSku goodsSku = goodsSkuService.getById(orderItem.getSkuId());
if(goodsSku!=null){
orderItem.setSkuSpecialFlag(goodsSku.getSpecialFlag());
}
//临期品添加批次对象
if(omsOrder.getOrderType().equals(3)&&orderItem.getSkuBatchId()!=null){
orderItem.setBatchInfo(goodsImminentBatchMapper.selectById(orderItem.getSkuBatchId()));
}
}
omsOrder.setOrderItems(list);
return R.ok(omsOrder);
}
return R.error();
}
}

21
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/CommonApi.java

@ -0,0 +1,21 @@
package com.qs.serve.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 门户API通用接口
* @author YenHex
* @since 2022/3/14
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/api/common")
public class CommonApi {
}

120
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/CommonController.java

@ -0,0 +1,120 @@
package com.qs.serve.controller;
import com.qs.serve.common.config.properties.UploadProperties;
import com.qs.serve.common.model.annotation.SysLog;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.model.enums.BizType;
import com.qs.serve.common.util.IdUtil;
import com.qs.serve.common.util.JwtUtils;
import com.qs.serve.common.util.UploadUtil;
import com.qs.serve.modules.oss.service.OssService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
/**
* 门户后台通用接口
* @author YenHex
* @since 2022/3/14
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/common")
public class CommonController {
private UploadProperties uploadProperties;
private OssService ossService;
/**
* 获取签名
* @param request
* @return
*/
@GetMapping("/getSign")
public R getSign(HttpServletRequest request) {
return R.ok(ossService.getPolicySign());
}
/**
* 单图上传
* @apiNote file不能为空
* @param request
* @return
*/
@SysLog(title = "文件",biz = BizType.UPLOAD)
@PostMapping("/upload")
public R upload(HttpServletRequest request) {
String relativePath = UploadUtil.put(uploadProperties.getLogicalPath(),IdUtil.timeStampId(),request);
if(relativePath!=null){
return R.ok(uploadProperties.getProxyUrl()+relativePath,"上传成功");
}
return R.error("上传失败");
}
/**
* 验证token
* @param token
* @return
*/
@PostMapping("/validToken")
public R validToken(String token) {
return R.isOk(JwtUtils.verify(token),"无效token");
}
/**
* 多图上传
* @apiNote files不能为空
* @param request
* @return
*/
@SysLog(title = "文件",biz = BizType.UPLOAD)
@PostMapping( "/uploadMulti")
public R<?> multiUpload(HttpServletRequest request) {
String contentType = request.getContentType();
List<MultipartFile> files = null;
if (contentType != null && contentType.toLowerCase().startsWith("multipart")) {
MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
files = multipartHttpServletRequest.getFiles("files");
}
if (files==null||files.isEmpty()) {
return R.error("请选择文件");
}
List<String> list = new ArrayList<>();
for (int i = 0; i < files.size(); i++) {
MultipartFile file = files.get(i);
if (file.isEmpty()) {
return R.error("上传第" + (i++) + "个文件失败");
}
String fileOrgName = file.getOriginalFilename();
String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf("."));
String filePath = LocalDate.now().toString().replace("-","")+"/"+ IdUtil.timeStampId()+mimeType;
String uploadPath = uploadProperties.getLogicalPath();
File dest = new File(uploadPath + filePath);
try {
file.transferTo(dest);
list.add(uploadProperties.getProxyUrl()+filePath);
} catch (IOException e) {
log.error(e.toString(), e);
return R.error("上传第" + (i++) + "个文件失败");
}
}
return R.ok(list);
}
}

122
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/WxMpPortalApi.java

@ -0,0 +1,122 @@
package com.qs.serve.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
/**
* 门户微信公众号回调
* @author YenHex
* @since 2022-03-07
*/
@Slf4j
@AllArgsConstructor
//@RestController
//@RequestMapping("/api/wx/mp/portal/{appid}")
public class WxMpPortalApi {
private final WxMpService wxService;
private final WxMpMessageRouter messageRouter;
/**
* 校验身份
* @param appid
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @return
*/
@GetMapping(produces = "text/plain;charset=utf-8")
public String authGet(@PathVariable String appid,
@RequestParam(name = "signature", required = false) String signature,
@RequestParam(name = "timestamp", required = false) String timestamp,
@RequestParam(name = "nonce", required = false) String nonce,
@RequestParam(name = "echostr", required = false) String echostr) {
log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature,
timestamp, nonce, echostr);
if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
throw new IllegalArgumentException("请求参数非法,请核实!");
}
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (wxService.checkSignature(timestamp, nonce, signature)) {
return echostr;
}
return "非法请求";
}
/**
* 身份校验2
* @param appid
* @param requestBody
* @param signature
* @param timestamp
* @param nonce
* @param openid
* @param encType
* @param msgSignature
* @return
*/
@PostMapping(produces = "application/xml; charset=UTF-8")
public String post(@PathVariable String appid,
@RequestBody String requestBody,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
log.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
if (!this.wxService.switchover(appid)) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
if (!wxService.checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
String out = null;
if (encType == null) {
// 明文传输的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toXml();
} else if ("aes".equalsIgnoreCase(encType)) {
// aes加密的消息
WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
timestamp, nonce, msgSignature);
log.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
WxMpXmlOutMessage outMessage = this.route(inMessage);
if (outMessage == null) {
return "";
}
out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
}
log.debug("\n组装回复信息:{}", out);
return out;
}
private WxMpXmlOutMessage route(WxMpXmlMessage message) {
try {
return this.messageRouter.route(message);
} catch (Exception e) {
log.error("路由消息时出现异常!", e);
}
return null;
}
}

237
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/WxSvcLoginApi.java

@ -0,0 +1,237 @@
package com.qs.serve.controller;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.framework.security.model.LoginUser;
import com.qs.serve.common.framework.security.model.LoginUserType;
import com.qs.serve.common.model.annotation.SysLog;
import com.qs.serve.common.model.consts.RedisCacheKeys;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.model.enums.BizType;
import com.qs.serve.common.model.enums.HttpCode;
import com.qs.serve.common.model.enums.InterType;
import com.qs.serve.common.util.*;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.sys.mapper.SysTenantMapper;
import com.qs.serve.modules.sys.service.SysUserService;
import com.qs.serve.modules.sys.service.impl.SysUserDetailsServiceImpl;
import com.qs.serve.modules.wx.common.conf.WxCpConfig;
import com.qs.serve.modules.wx.entity.WxApp;
import com.qs.serve.modules.wx.entity.WxUser;
import com.qs.serve.modules.wx.entity.dto.WxLoginUser;
import com.qs.serve.modules.wx.service.WxAppService;
import com.qs.serve.modules.wx.service.WxUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.WxCpAgentJsapiSignature;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* 门户微信登录
* @author YenHex
* @since 2022/3/7
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/api/wx/login")
public class WxSvcLoginApi {
private final WxUserService wxUserService;
private final RedisService redisService;
private final SysUserDetailsServiceImpl userDetailsService;
private final SysTenantMapper sysTenantMapper;
private final WxAppService wxAppService;
private SysUserService sysUserService;
/**
* 企业微信登录
* @param wxLoginUser
* @param request
* @return
*/
@SysLog(title = "企业微信登录",biz = BizType.LOGIN,inter = InterType.API)
@PostMapping("/cp")
public R<?> loginCompanyApp(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){
WxUser wxUser = null;
try {
wxUser = wxUserService.login(wxLoginUser,request);
} catch (Exception e) {
Assert.throwEx(e.getMessage());
}
if(wxUser==null){
Assert.throwEx(HttpCode.WX_ERR);
}
Map<String, Object> objectMap = genTokenInfo(request, wxUser);
return R.ok(objectMap);
}
/**
* 获取签名授权
* @param url
* @param request
* @return
*/
@GetMapping("/getCpSignature")
public R<WxCpAgentJsapiSignature> getCpSignature(String url, HttpServletRequest request) {
AuthContextUtils.setTenant("001");
String agentIdStr = request.getHeader("agentId");
String appId = AuthContextUtils.getAppId();
WxApp wxApp = wxAppService.getById(appId);
Integer agentId = Integer.parseInt(agentIdStr);
// 企业微信登录
WxCpService wxCpService = new WxCpServiceImpl();
WxCpDefaultConfigImpl config =new WxCpDefaultConfigImpl();
config.setAgentId(agentId);
config.setCorpSecret(WxCpConfig.getSecret(agentId));
config.setCorpId(wxApp.getId());
wxCpService.setWxCpConfigStorage(config);
WxCpAgentJsapiSignature signature = null;
try {
signature = wxCpService.createAgentJsapiSignature(url);
} catch (WxErrorException e) {
log.warn("企业微信签名授权失败:appid{},agentId:{},{}",appId,agentId,e.getMessage());
}
return R.ok(signature);
}
/**
* 企业微信登录
* @param wxLoginUser
* @param request
* @return
*/
@SysLog(title = "企业微信登录",biz = BizType.LOGIN,inter = InterType.API)
@PostMapping("/cp4Pc")
public R<?> loginCompanyPc(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){
WxUser wxUser = null;
try {
wxUser = wxUserService.login(wxLoginUser,request);
} catch (Exception e) {
Assert.throwEx(e.getMessage());
}
if(wxUser==null){
Assert.throwEx(HttpCode.WX_ERR);
}
Map<String, Object> objectMap = genTokenInfo(request, wxUser);
return R.ok(objectMap.get("adminTokenInfo"));
}
/**
* 小程序登陆(暂测试)
* @param wxLoginUser
* @param request
* @return
*/
@SysLog(title = "小程序登录",biz = BizType.LOGIN,inter = InterType.API)
@PostMapping("/ma")
public R<?> loginMicroApp(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){
WxUser wxUser = null;
try {
wxUser = wxUserService.login(wxLoginUser,request);
} catch (Exception e) {
log.warn(e.getMessage());
}
if(wxUser==null){
Assert.throwEx(HttpCode.WX_ERR);
}
Map<String, Object> objectMap = genTokenInfo(request, wxUser);
return R.ok(objectMap);
}
/**
* 公众号登录
* @param wxLoginUser
* @return
* @throws Exception
*/
@SysLog(title = "公众号登录",biz = BizType.LOGIN,inter = InterType.API)
@PostMapping("/mp")
public R<?> login(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){
WxUser wxUser = null;
try {
wxUser = wxUserService.login(wxLoginUser,request);
} catch (Exception e) {
log.warn(e.getMessage());
}
if(wxUser==null){
Assert.throwEx(HttpCode.WX_ERR);
}
Map<String, Object> objectMap = genTokenInfo(request, wxUser);
return R.ok(objectMap);
}
@NotNull
private Map<String, Object> genTokenInfo(HttpServletRequest request, WxUser wxUser) {
Map<String,Object> objectMap = new HashMap<>();
String token = IdUtil.fastSimpleUUID();
LoginUser loginUser = new LoginUser(wxUser.getId(), wxUser.getEmpName(),"",
ServletUtils.getIp(request), LoginUserType.APP_USER,new ArrayList<>(),null,AuthContextUtils.getTenant());
objectMap.put("token",token);
//微信登录ID
String wxUserKey = StringUtils.format(RedisCacheKeys.WX_KEY_USER,token);
redisService.set(wxUserKey, wxUser.getId());
//后台管理员信息
Map<String,Object> tokenMap = new HashMap<>(10);
String client = "wx_app";
String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client, wxUser.getSysUserId());
String pctoken = JwtUtils.generateToken(wxUser.getSysUserId(),loginUser.getTypeFlag(),client);
redisService.set(redisKey,pctoken);
tokenMap.put("token", pctoken);
tokenMap.put("userId", wxUser.getSysUserId());
tokenMap.put("IP", loginUser.getLoginIp());
tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant()));
tokenMap.put("loginType",client);
tokenMap.put("client",client);
//关联
objectMap.put("adminTokenInfo",tokenMap);
return objectMap;
}
/**
* 公众号测试登录
*/
@PostMapping("/mptest")
public R<?> login(HttpServletRequest request){
Map<String,Object> objectMap = new HashMap<>();
String token = IdUtil.fastSimpleUUID();
//微信登录ID
String wxUserKey = StringUtils.format(RedisCacheKeys.WX_KEY_USER,token);
redisService.set(wxUserKey,"1");
LoginUser loginUser = new LoginUser("1","微信测试用户","",
ServletUtils.getIp(request), LoginUserType.APP_USER,new ArrayList<>(),null,AuthContextUtils.getTenant());
objectMap.put("token",token);
String sysUserId = "1";
Map<String,Object> tokenMap = new HashMap<>(10);
String client = "wx_app";
String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,sysUserId);
String pctoken = JwtUtils.generateToken(sysUserId,loginUser.getTypeFlag(),client);
redisService.set(redisKey,pctoken);
tokenMap.put("token", pctoken);
tokenMap.put("userId", sysUserId);
tokenMap.put("IP", loginUser.getLoginIp());
tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant()));
tokenMap.put("loginType",client);
tokenMap.put("client",client);
//关联
objectMap.put("adminTokenInfo",tokenMap);
return R.ok(objectMap);
}
}

27
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/dto/CounterResultVo.java

@ -0,0 +1,27 @@
package com.qs.serve.controller.dto;
import lombok.Data;
/**
* @author YenHex
* @since 2022/5/13
*/
@Data
public class CounterResultVo {
/**
* 待处理审批数
*/
private Long apprCounter;
/**
* 公告未读数
*/
private Integer noticeCounter;
/**
* 维修任务数
*/
private Long repairCounter;
}

27
cms-api/cms-admin-svc/src/main/java/com/qs/serve/controller/dto/SyLoginParam.java

@ -0,0 +1,27 @@
package com.qs.serve.controller.dto;
import lombok.Data;
/**
* @author YenHex
* @since 2023/6/8
*/
@Data
public class SyLoginParam {
/**
* 模板编码
*/
private String templateCode;
/**
* 表单data的exsp5字段值
*/
private String key;
/**
* 致远员工id
*/
private String syId;
}

52
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/BirTask.java

@ -0,0 +1,52 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.bir.controller.BirActivityCenterGoodsController;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author YenHex
* @since 2023/11/7
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.bir-service-sync", havingValue = "true")
public class BirTask {
private final BirActivityCenterGoodsController birActivityCenterGoodsController;
/**
* 同步bir实时
* 15分钟执行一次
*/
@Scheduled(cron="0 0/15 * * * ?")
public void toSyncBirEcro(){
AuthContextUtils.setTenant("001");
birActivityCenterGoodsController.toSyncBirEcro();
log.warn("bir更新完成");
}
/**
* 移除因作废的费用申请导致的bir数据
* 每天中午13点触发
*/
@Scheduled(cron="0 0 13 * * ?")
public void toSyncRm(){
AuthContextUtils.setTenant("001");
birActivityCenterGoodsController.toSyncRm();
log.warn("bir更新完成 - 作废的费用");
}
@PostConstruct
void started() {
log.warn("bir同步开启");
}
}

48
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/BmsTask.java

@ -0,0 +1,48 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.bms.controller.BmsRegion2Controller;
import com.qs.serve.modules.bms.controller.BmsRegionController;
import com.qs.serve.modules.tbs.service.TbsActivityTemplateService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2024/5/9
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class BmsTask {
private final BmsRegion2Controller bmsRegion2Controller;
private final BmsRegionController bmsRegionController;
private final TbsActivityTemplateService tbsActivityTemplateService;
/**
* 更新树路径
*/
@Scheduled(cron="0 0 7,13 * * ?")
public void levelTask(){
AuthContextUtils.setTenant("001");
bmsRegionController.updateLevel();
bmsRegion2Controller.updateLevel();
//更新客户的关联区域的列
tbsActivityTemplateService.updateState();
}
/**
* 5分钟执行一次
*/
@Scheduled(cron="0 0/5 * * * ?")
public void updateActTmpState(){
AuthContextUtils.setTenant("001");
tbsActivityTemplateService.updateState();
}
}

32
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/ErpDipatchTask.java

@ -0,0 +1,32 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.bir.mapper.BirReportAccountBookMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/7/14
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class ErpDipatchTask {
private final BirReportAccountBookMapper birReportAccountBookMapper;
@Scheduled(cron="0 0 1 * * ?")
public void buildTempTable(){
AuthContextUtils.setTenant("001");
birReportAccountBookMapper.buildAllDispatch();
birReportAccountBookMapper.buildRegionDispatch();
birReportAccountBookMapper.buildBizRegionDispatch();
birReportAccountBookMapper.buildCustomerDispatch();
}
}

60
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/GoodsTask.java

@ -0,0 +1,60 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.goods.service.GoodsApplicationService;
import com.qs.serve.modules.goods.service.GoodsCustomerPriceService;
import com.qs.serve.modules.goods.service.GoodsSpuService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/12/20
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class GoodsTask {
private GoodsSpuService goodsSpuService;
private GoodsApplicationService goodsApplicationService;
private GoodsCustomerPriceService goodsCustomerPriceService;
@Scheduled(cron="0 0 1 * * ?")
public void buildTempTable(){
AuthContextUtils.setTenant("001");
goodsSpuService.initSkuNum();
}
/**
* 每15分钟同步一次
*/
@Scheduled(cron="0/15 0 0 * * ?")
public void syncCusPriceGoods(){
AuthContextUtils.setTenant("001");
goodsCustomerPriceService.syncCustomerPrice();
}
/**
* 每两个小时同步一次
*/
//@Scheduled(cron="0 0/2 0 * * ?")
public void syncStandGoods(){
AuthContextUtils.setTenant("001");
goodsApplicationService.syncStandGoods(false);
}
/**
* 同步价格
*/
//@Scheduled(cron="0 0 1 * * ?")
public void syncInvPrice(){
AuthContextUtils.setTenant("001");
goodsApplicationService.syncSkuPrice();
}
}

59
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/HisTask.java

@ -0,0 +1,59 @@
package com.qs.serve.task;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.model.consts.RedisCacheKeys;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.his.service.HisUserSupplierTempService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
/**
* @author YenHex
* @since 2023/5/31
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class HisTask {
RedisService redisService;
HisUserSupplierTempService tempService;
/**
* 数据处理10-15分钟每隔20分钟执行一次,串行
*/
@Scheduled(cron="0 0/20 * * * ?")
public void buildTempTable(){
AuthContextUtils.setTenant("001");
Integer opt = redisService.getInteger(RedisCacheKeys.HIS_UPDATE);
//设置默认值
if (opt==null){
redisService.set(RedisCacheKeys.HIS_UPDATE,0);
return;
}
//忽略状态
if (opt==1){
//执行同步
log.warn("======================执行同步======================");
LocalDateTime s1 = LocalDateTime.now();
//防卡死,加入超时
redisService.set(RedisCacheKeys.HIS_UPDATE,2,1, TimeUnit.HOURS);
tempService.reloadHis();
LocalDateTime s2 = LocalDateTime.now();
long diff = Duration.between(s1, s2).getSeconds();
tempService.selectInfoHis();
redisService.set(RedisCacheKeys.HIS_UPDATE,0);
log.warn("======================执行同步完成,耗时[ {} 秒]======================",diff);
}
}
}

36
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/OmsTask.java

@ -0,0 +1,36 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.oms.mapper.OmsSaleOrderItemMapper;
import com.qs.serve.modules.oms.service.OmsOrderOptionsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2024/9/26
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class OmsTask {
OmsOrderOptionsService omsOrderOptionsService;
OmsSaleOrderItemMapper omsSaleOrderItemMapper;
/**
* 同步临期品到调度系统的订单中间表
* 每10分钟执行一次
*/
@Scheduled(cron="0 0/10 * * * ?")
public void saveToErpOrder(){
AuthContextUtils.setTenant("001");
omsSaleOrderItemMapper.updateItemSkuBelong();
omsOrderOptionsService.syncToErp();
}
}

110
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/PayTask.java

@ -0,0 +1,110 @@
package com.qs.serve.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.config.properties.ProjectApisProperties;
import com.qs.serve.common.model.AmountDTO;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.common.util.HttpUtil;
import com.qs.serve.modules.pay.mapper.PayPaymentItemMapper;
import com.qs.serve.modules.pay.mapper.PayPaymentMapper;
import com.qs.serve.modules.tbs.entity.TbsCostApply;
import com.qs.serve.modules.tbs.service.TbsCostApplyService;
import com.qs.serve.modules.vtb.mapper.VtbVerificationMapper;
import com.qs.serve.modules.vtb.service.VtbVerificationService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author YenHex
* @since 2023/11/7
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class PayTask {
private VtbVerificationService vtbVerificationService;
private VtbVerificationMapper vtbVerificationMapper;
private final TbsCostApplyService costApplyService;
private final PayPaymentItemMapper payPaymentItemMapper;
private final PayPaymentMapper payPaymentMapper;
private ProjectApisProperties projectApisProperties;
/**
* 将未支付的重新发起请求
*/
@Scheduled(cron="0 0 2 * * ?")
public void checkToPay(){
AuthContextUtils.setTenant("001");
//预先调用伟成同步状态接口,减少查询记录数
String url = projectApisProperties.getCheckPayStatus();
HttpUtil.doGet(url,null);
List<Long> vids = vtbVerificationMapper.listNotPayVerifyIds();
for (Long vid : vids) {
vtbVerificationService.toPayRequest(vid);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
HttpUtil.doGet(url,null);
}
/**
* 同步支付
*/
@Scheduled(cron="0 0 2 * * ?")
public void syncCostPayStatus(){
AuthContextUtils.setTenant("001");
List<Long> costIds4State = payPaymentMapper.selectCostApplyIds4State();
LambdaQueryWrapper<TbsCostApply> costLqw = new LambdaQueryWrapper<>();
costLqw.select(
TbsCostApply::getId,
TbsCostApply::getTotalActivityAmount
);
costLqw.in(TbsCostApply::getId,costIds4State);
List<TbsCostApply> costApplyList = costApplyService.list(costLqw);
List<String> costIds = costApplyList.stream().map(TbsCostApply::toString).collect(Collectors.toList());
List<AmountDTO> amountDTOList = payPaymentItemMapper.selectCostTotal(costIds);
List<TbsCostApply> updatePayStateList = new ArrayList<>();
for (TbsCostApply costApply : costApplyList) {
String costId = costApply.getId().toString();
for (AmountDTO dto : amountDTOList) {
if(costId.equals(dto.getId())){
BigDecimal totalPay = dto.getAmount();
if(totalPay.compareTo(BigDecimal.ZERO)==0){
//未支付忽略
continue;
}
BigDecimal totalCost = costApply.getTotalActivityAmount();
TbsCostApply updParam = new TbsCostApply();
updParam.setId(costApply.getId());
if(totalPay.compareTo(totalCost)<0){
updParam.setPayStatus(1);
}else {
updParam.setPayStatus(2);
}
updatePayStateList.add(updParam);
}
}
}
costApplyService.updateBatchById(updatePayStateList);
//更新支付表记录,用于实现增量更新
List<Long> costIds4Update = updatePayStateList.stream().map(TbsCostApply::getId).collect(Collectors.toList());
if(costIds4Update.size()>0){
payPaymentItemMapper.updateSyncCostState(costIds4Update);
}
}
}

47
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/SysTask.java

@ -0,0 +1,47 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.sys.service.SysPostService;
import com.qs.serve.task.controller.TaskUserController;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class SysTask {
TaskUserController taskUserController;
SysPostService sysPostService;
/**
* 同步用户
*/
@Scheduled(cron="0 0 1 * * ?")
public void task1(){
AuthContextUtils.setTenant("001");
taskUserController.test();
//更新下属数据
sysPostService.flushPathIds();
}
/**
* 同步离职
*/
@Scheduled(cron="0 0 2 * * ?")
public void task2(){
AuthContextUtils.setTenant("001");
taskUserController.doLeave();
}
}

30
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TagTask.java

@ -0,0 +1,30 @@
package com.qs.serve.task;
import com.qs.serve.modules.tag.mapper.TagDataMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/5/31
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TagTask {
private TagDataMapper tagDataMapper;
/**
* 数据处理10-15分钟清理过期数据
*/
//@Scheduled(cron="0 0/1 * * * ?")
public void buildTempTable(){
//tagDataMapper.deleteExpireData();
}
}

74
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TbsTask.java

@ -0,0 +1,74 @@
package com.qs.serve.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.bir.mapper.BirTbsVtbPayJoinMapper;
import com.qs.serve.modules.tbs.common.TbsCostApplyState;
import com.qs.serve.modules.tbs.entity.TbsCostApply;
import com.qs.serve.modules.tbs.service.TbsActivityService;
import com.qs.serve.modules.tbs.service.TbsActivityTemplateService;
import com.qs.serve.modules.tbs.service.TbsCostApplyService;
import com.qs.serve.modules.vtb.service.VtbVerificationService;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author YenHex
* @since 2022/12/9
*/
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TbsTask {
private final BirTbsVtbPayJoinMapper birTbsVtbPayJoinMapper;
private final TbsActivityService activityService;
private final TbsCostApplyService tbsCostApplyService;
private final TbsActivityTemplateService activityTemplateService;
private final VtbVerificationService vtbVerificationService;
//每日更新过期的活动,过期则进行冻结
@Scheduled(cron="0 0 1 * * ?")
public void task1(){
AuthContextUtils.setTenant("001");
activityService.initReopenState();
LambdaQueryWrapper<TbsCostApply> lqwApply = new LambdaQueryWrapper<>();
lqwApply.select(TbsCostApply::getId);
lqwApply.eq(TbsCostApply::getChargeState, TbsCostApplyState.State_2_actioning.getCode());
List<TbsCostApply> costApplyList = tbsCostApplyService.list(lqwApply);
List<Long> costApplyIds = costApplyList.stream().map(TbsCostApply::getId).collect(Collectors.toList());
// 更新费用申请的活动的冻结状态
activityService.flushBandingState(costApplyIds);
}
/**
* 每半小时执行一次
*/
@Scheduled(cron="0 0/30 * * * ?")
public void updateCheckState(){
AuthContextUtils.setTenant("001");
tbsCostApplyService.updateCheckState();
//间隔几个月换一次即可
Long maxCostId = 313000L;
birTbsVtbPayJoinMapper.updateActivityAllCenters(maxCostId);
}
/**
* 每半小时执行一次
*/
@Scheduled(cron="0 0/30 * * * ?")
public void syncPayToErp(){
AuthContextUtils.setTenant("001");
vtbVerificationService.toPayRequest();
}
}

51
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TzcPolicyTask.java

@ -0,0 +1,51 @@
package com.qs.serve.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.seeyon.service.XiaoLuTonService;
import com.qs.serve.modules.third.service.PortalOfCostApplication;
import com.qs.serve.modules.tzc.common.TzPolicyItemStatus;
import com.qs.serve.modules.tzc.entity.TzcPolicyItem;
import com.qs.serve.modules.tzc.service.TzcPolicyApplicationService;
import com.qs.serve.modules.tzc.service.TzcPolicyItemService;
import com.qs.serve.modules.tzc.service.TzcPolicyService;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 政策同步方法
* @author YenHex
* @since 2023/3/11
*/
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TzcPolicyTask {
private TzcPolicyService policyService;
private TzcPolicyItemService policyItemService;
private TzcPolicyApplicationService policyApplicationService;
private PortalOfCostApplication portalOfCostApplication;
private XiaoLuTonService xiaoLuTonService;
/**
* 同步政策到销路通
*/
@Scheduled(cron="0 20 * * * ?")
public void syncPolicyToXlt(){
AuthContextUtils.setTenant("001");
LambdaQueryWrapper<TzcPolicyItem> itemLqw = new LambdaQueryWrapper<>();
itemLqw.select(TzcPolicyItem::getId);
itemLqw.eq(TzcPolicyItem::getPolicyItemStatus,TzPolicyItemStatus.Status_1_PassSuccess);
List<TzcPolicyItem> policyItemList = policyItemService.list(itemLqw);
for (TzcPolicyItem policyItem : policyItemList) {
policyApplicationService.syncPolicyItem(policyItem.getId());
}
}
}

35
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/TzcTask.java

@ -0,0 +1,35 @@
package com.qs.serve.task;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/11/7
*/
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TzcTask {
/**
* 同步未同步的政策项排查数据并无异常
* 流程如下
* 1.查询CMS未同步的政策项编码发送到中间服务 SELECT * FROM `tzc_policy` LEFT JOIN tzc_policy_item
* ON tzc_policy.id = tzc_policy_item.policy_id WHERE tzc_policy.del_flag = 0 AND tzc_policy_item.del_flag = 0
* AND tzc_policy.policy_status = 2 AND tzc_policy_item.sync_status = 0
* 2.中间服务返回已有的政策项编码 SELECT * FROM [dbo].[XLT_BI_GhDbf] where cGhMemo = '数据自动导入' and cGhCode like 'P%'
* 3.更新已有的政策项编码 update tzc_policy_item set sync_status = 1 where policy_item_code in (...)
* 4.重新请求未同步的政策编码
*
*/
//@Scheduled(cron="0 0 3 * * ?")
public void checkToPay(){
}
}

24
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/WxUserTask.java

@ -0,0 +1,24 @@
package com.qs.serve.task;
import com.qs.serve.modules.sys.common.AuthContextUtils;
import com.qs.serve.modules.wx.service.WxUserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2022/9/26
*/
@Component
@AllArgsConstructor
public class WxUserTask {
private WxUserService wxUserService;
//@Scheduled(cron = "0 0/30 * * * ?")
public void syncSubscribe(){
AuthContextUtils.setTenant("001");
wxUserService.syncSubscribe();
}
}

60
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/HistTestController.java

@ -0,0 +1,60 @@
package com.qs.serve.task.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.config.DevEnvironmentConfig;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.model.consts.RedisCacheKeys;
import com.qs.serve.common.model.dto.PageVo;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.util.PageUtil;
import com.qs.serve.modules.his.service.HisUserChannelPointService;
import com.qs.serve.modules.oms.entity.OmsOrder;
import com.qs.serve.task.HisTask;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author YenHex
* @since 2023/4/17
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("his/dev")
@ConditionalOnBean(HisTask.class)
public class HistTestController {
HisUserChannelPointService hisUserChannelPointService;
RedisService redisService;
HisTask hisTask;
@GetMapping("/initSupplier")
public R<?> initSupplier(){
if(DevEnvironmentConfig.isDev()){
redisService.set(RedisCacheKeys.HIS_UPDATE,1);
hisTask.buildTempTable();
}
return R.ok();
}
/**
*
* @return
*/
@GetMapping("/initPoint")
public R<?> initPoint(){
if(DevEnvironmentConfig.isDev()){
hisUserChannelPointService.initSetup();
}
return R.ok();
}
}

96
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskActivityController.java

@ -0,0 +1,96 @@
package com.qs.serve.task.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.util.CollectionUtil;
import com.qs.serve.modules.seeyon.service.impl.SeeYonRequestBaseService;
import com.qs.serve.modules.tbs.common.TbsActivityState;
import com.qs.serve.modules.tbs.common.TbsSeeYonConst;
import com.qs.serve.modules.tbs.entity.TbsActivity;
import com.qs.serve.modules.tbs.entity.TbsActivityTemplate;
import com.qs.serve.modules.tbs.service.TbsActivityService;
import com.qs.serve.modules.tbs.service.TbsActivityTemplateService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 同步 活动相关
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/activity")
//@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskActivityController {
private final TbsActivityService activityService;
private final TbsActivityTemplateService activityTemplateService;
private final SeeYonRequestBaseService seeYonRequestBaseService;
/**
* 同步ERP的发货单用于计算活动费率
* @return
*/
@GetMapping("syncDispatch")
public R task0(){
seeYonRequestBaseService.getBase(TbsSeeYonConst.TASK_SYNC_DISPATCH,"同步ERP的发货单");
return R.ok();
}
/**
* 每日更新过期的活动过期则进行冻结
* @return
*/
@GetMapping("lockActivity")
public R task2(){
LambdaQueryWrapper<TbsActivity> lqw = new LambdaQueryWrapper<>();
lqw.le(TbsActivity::getPreEndDate, LocalDate.now());
lqw.eq(TbsActivity::getReopenFlag,0);
TbsActivity param = new TbsActivity();
param.setActivityState(TbsActivityState.STATE_1_Baning);
activityService.update(param,lqw);
return R.ok();
}
/**
* 启用和停用模板规则
* @return
*/
@GetMapping("startAndStopActivityTemplates")
public R task3(){
LocalDateTime nowTime = LocalDateTime.now();
LambdaQueryWrapper<TbsActivityTemplate> lqw = new LambdaQueryWrapper<>();
lqw.select(TbsActivityTemplate::getId);
lqw.ge(TbsActivityTemplate::getStartTime,nowTime.with(LocalDateTime.MIN));
lqw.le(TbsActivityTemplate::getStartTime,nowTime.with(LocalDateTime.MAX));
lqw.eq(TbsActivityTemplate::getTemplateState,0);
List<TbsActivityTemplate> preStartList = activityTemplateService.list(lqw);
if(CollectionUtil.isNotEmpty(preStartList)){
preStartList.forEach(a->a.setTemplateState(1));
activityTemplateService.updateBatchById(preStartList);
}
LambdaQueryWrapper<TbsActivityTemplate> lqw2 = new LambdaQueryWrapper<>();
lqw2.select(TbsActivityTemplate::getId);
lqw2.ge(TbsActivityTemplate::getEndTime,nowTime.with(LocalDateTime.MIN));
lqw2.le(TbsActivityTemplate::getEndTime,nowTime.with(LocalDateTime.MAX));
lqw2.eq(TbsActivityTemplate::getTemplateState,1);
List<TbsActivityTemplate> preCloseList = activityTemplateService.list(lqw2);
if(CollectionUtil.isNotEmpty(preCloseList)){
preCloseList.forEach(a->a.setTemplateState(0));
activityTemplateService.updateBatchById(preCloseList);
}
return R.ok();
}
}

30
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskPayController.java

@ -0,0 +1,30 @@
package com.qs.serve.task.controller;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.modules.pay.service.impl.PayApplicationService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author YenHex
* @since 2023/11/2
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/pay")
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskPayController {
PayApplicationService applicationService;
@RequestMapping("test")
public R<?> task(){
applicationService.syncTotalPayToActivity();
return R.ok();
}
}

45
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskPolicyController.java

@ -0,0 +1,45 @@
package com.qs.serve.task.controller;
import com.qs.serve.common.model.dto.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 同步 政策相关
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/policy")
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskPolicyController {
//TzcPolicyTask policyTask;
/**
* 根据销路通支付数据和本系统政策匹对并生成本系统核销及支付信息
* @return
*/
@GetMapping("loadXltPayment")
public R syncFromXltPolicyPayment(){
//policyTask.syncFromXltPolicyPayment();
return R.ok();
}
/**
* 同步政策到销路通
* @return
*/
@GetMapping("syncPolicyToXlt")
public R syncPolicyToXlt(){
//policyTask.syncPolicyToXlt();
return R.ok();
}
}

65
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskSupplierController.java

@ -0,0 +1,65 @@
package com.qs.serve.task.controller;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.model.consts.RedisCacheKeys;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.modules.his.service.HisUserSupplierTempService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
/**
* 同步 客户相关
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/supplier")
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskSupplierController {
RedisService redisService;
HisUserSupplierTempService tempService;
/**
* 通过客户底表
* @return
*/
@GetMapping("syncToTemp")
public R test(){
Integer opt = redisService.getInteger(RedisCacheKeys.HIS_UPDATE);
log.warn("======================执行状态:"+opt+"======================");
//设置默认值
if (opt==null){
redisService.set(RedisCacheKeys.HIS_UPDATE,0);
return R.ok();
}
//忽略状态
if (opt==1){
//执行同步
log.warn("======================执行同步======================");
LocalDateTime s1 = LocalDateTime.now();
//防卡死,加入超时
redisService.set(RedisCacheKeys.HIS_UPDATE,2,1, TimeUnit.HOURS);
tempService.reloadHis();
LocalDateTime s2 = LocalDateTime.now();
long diff = Duration.between(s1, s2).getSeconds();
tempService.selectInfoHis();
redisService.set(RedisCacheKeys.HIS_UPDATE,0);
log.warn("======================执行同步完成,耗时[ {} 秒]======================",diff);
}
return R.ok();
}
}

106
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskUserController.java

@ -0,0 +1,106 @@
package com.qs.serve.task.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.util.JsonUtil;
import com.qs.serve.modules.bms.mapper.BmsSupplierMapper;
import com.qs.serve.modules.his.service.HisUserSupplierService;
import com.qs.serve.modules.seeyon.service.impl.SeeYonRequestBaseService;
import com.qs.serve.modules.sys.entity.SysUser;
import com.qs.serve.modules.sys.entity.SysUserLeave;
import com.qs.serve.modules.sys.entity.dto.SyUser;
import com.qs.serve.modules.sys.service.SysUserLeaveService;
import com.qs.serve.modules.sys.service.SysUserService;
import com.qs.serve.modules.tbs.common.TbsSeeYonConst;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
/**
* 同步 用户相关
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/user")
//@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskUserController {
SeeYonRequestBaseService seeYonRequestBaseService;
SysUserService sysUserService;
SysUserLeaveService sysUserLeaveService;
private final BmsSupplierMapper supplierMapper;
private final HisUserSupplierService hisUserSupplierService;
@Transactional
public R<?> doLeave(){
LambdaQueryWrapper<SysUserLeave> lqw = new LambdaQueryWrapper<>();
lqw.select(SysUserLeave::getUserId,SysUserLeave::getId);
lqw.le(SysUserLeave::getLeaveEffectDate, LocalDate.now());
lqw.eq(SysUserLeave::getLeaveStatus,0);
List<SysUserLeave> sysUserLeaves = sysUserLeaveService.list(lqw);
if(sysUserLeaves.size()<1){
return null;
}
for (SysUserLeave userLeaf : sysUserLeaves) {
userLeaf.setLeaveStatus(1);
}
sysUserLeaveService.updateBatchById(sysUserLeaves);
List<String> userIds = sysUserLeaves.stream().map(a->a.getUserId()).collect(Collectors.toList());
sysUserService.leaveNow(userIds,false);
return R.ok();
}
/**
* 同步致远的用户到CRM
* @return
*/
@GetMapping("syncFromSeeYon")
public R test(){
R<String> rs = seeYonRequestBaseService.getBase(TbsSeeYonConst.OA_USER_LIST_1,null);
String listJson = rs.getData();
List<SyUser> userList = JsonUtil.jsonToList(listJson, SyUser.class);
assert userList != null;
if(userList.size()<1){
return R.ok();
}
List<String> codes = userList.stream().map(SyUser::getCode).collect(Collectors.toList());
LambdaQueryWrapper<SysUser> userLqw = new LambdaQueryWrapper<>();
userLqw.in(SysUser::getAccount,codes).or()
.in(SysUser::getCode,codes);
List<SysUser> existUserList = sysUserService.list(userLqw);
for (SyUser oaUser : userList) {
boolean exist = existUserList.stream().anyMatch(
a->a.getAccount().equals(oaUser.getCode())
||a.getCode().equals(oaUser.getCode())
);
if(!exist){
SysUser sysUser = new SysUser();
sysUser.setCode(oaUser.getCode());
sysUser.setMobile(oaUser.getMobile());
sysUser.setAccount(oaUser.getCode());
sysUser.setId(oaUser.getId());
sysUser.setSyUserId(oaUser.getId());
sysUser.setSyAccount(oaUser.getCode());
sysUser.setServingState(1);
sysUser.setServingDate(LocalDate.now());
sysUser.setSuperFlag(1);
sysUser.setTenantId("001");
sysUserService.save(sysUser);
}
}
return R.ok();
}
}

38
cms-api/cms-admin-svc/src/main/java/com/qs/serve/task/controller/TaskWechatController.java

@ -0,0 +1,38 @@
package com.qs.serve.task.controller;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.modules.wx.service.WxUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 同步 微信相关
* @author YenHex
* @since 2023/6/27
*/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/task/wechat")
@ConditionalOnProperty(value = "project.task", havingValue = "true")
public class TaskWechatController {
private WxUserService wxUserService;
/**
* 同步订阅用户流程
* @return
*/
@GetMapping("syncSubscribe")
public R test(){
wxUserService.syncSubscribe();
return R.ok();
}
}

133
cms-api/cms-admin-svc/src/main/resources/application-dev.yml

@ -0,0 +1,133 @@
feign:
client:
config:
default:
connectTimeout: 5000 # 连接超时时间
readTimeout: 5000 # 读取超时时间
httpclient:
enabled: true
# 服务列表
service-list:
policy-svc: http://localhost:8081
#项目配置
project:
bir-service: 'false'
bir-service-sync: 'false'
bir-service-url: 'http://192.168.0.9:7401'
web_url: 'http://192.168.0.9:6031'
host_url: 'http://192.168.0.9:7400'
pc-web-local: 'D:\Software\Nginx1.8\html\jslcrm3\'
apis:
#支付接口
#cost-to-pay: 'http://59.37.164.96:2506/action/cms/api/add'
#支付接口(新)
#cost-to-pay: 'http://59.37.164.96:2505/api/cms/api/add'
cost-to-pay: 'http://0.0.0.0:2505/api/cms/api/add'
# 同步核销的支付状态
#check-pay-status: 'http://59.37.164.96:2506/action/cms/cost/match'
check-pay-status: 'http://0.0.0.0:2506/action/cms/cost/match'
# 核销生成报价单接口
diaodu-plan-order: ''
# 嘉士利接口,spu转换sku
#spu-to-sku: 'http://59.37.164.96:2505/api/cms/order/matchInvCode'
spu-to-sku: 'http://0.0.0.0:2505/api/cms/order/matchInvCode'
# 政策同步
#policy-sync-cate: 'http://192.168.10.18:9003/api/cms/saleCost/costPolicy/syncCate'
policy-sync-cate: 'http://0.0.0.0:9003/api/cms/saleCost/costPolicy/syncCate'
# 政策同步旧的
#policy-sync-inv: 'http://192.168.10.18:9003/api/cms/saleCost/costPolicy/syncInv'
policy-sync-inv: 'http://0.0.0.0:9003/api/cms/saleCost/costPolicy/syncInv'
task: false
dev: true
seeyon:
enable: true
url: 'http://192.168.0.9:7444'
#请求致远OA的拓展服务(用于修改密码)
extApi: 'http://192.168.10.244:9003/'
upload:
#上传映射地址
proxy-url: https://qsjslservice.oss-cn-guangzhou.aliyuncs.com/jsl/
#物理存储地址
logical-path: D:\\WebMapPath\\
#腾讯云配置
tencent:
sms:
secret-id: AKIDR3A5mVkSaXFUT3TABanPxc2MtkMu45wb
secret-key: iLkjeKzHwegQ4eE55xX9byXmBLxgwypV
sdkAppId: 1400174031
signName: 柒胜软件
templateId: 689207
#天翼云配置
tianyi:
sms:
appid: 'WIgWyCFn4DnHLtjKBIXBVyZbGevFg3J4'
appKey: 'bjfsZlF01OZPUzyiCLSFOrOOnfsZhYZJ'
aliyun:
oss:
bucket: qsjslservice
accessKeyId: LTAI5tHvNJT7M9YZJ9BSmURK
accessKeySecret: OzH0ea3w8fgjrll9P0XTQlqmEg3Cky
endpoint: oss-cn-guangzhou.aliyuncs.com
prefix: jsl
#服务配置
server:
port: 7400
servlet:
context-path: /
#SpringBoot相关
spring:
datasource:
# 旧的
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.0.9:3306/jsl_mall_qs_dev?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
# username: kpjsl
# password: '123456'
# 新的
dynamic:
primary: crm_db #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
crm_db:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.0.9:3306/jsl_mall_qs_dev?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
username: kpjsl
password: 123456
qisheng:
url: jdbc:sqlserver://192.168.10.11:1433;DatabaseName=JSL_COST_QS_TEST
username: sa
password: JSL2282125
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
#SpringBoot相关
hikari:
#连接池名
pool-name: DateHikariCP
#最小空闲连接数
minimum-idle: 10
# 空闲连接存活最大时间,默认600000(10分钟)
idle-timeout: 180000
# 连接池最大连接数,默认是10
maximum-pool-size: 30
# 此属性控制从池返回的连接的默认自动提交行为,默认值:true
auto-commit: true
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
max-lifetime: 1800000
# 数据库连接超时时间,默认30秒,即30000
connection-timeout: 30000
connection-test-query: SELECT 1
validation-timeout: 1
login-timeout: 5
redis:
database: 1
host: 127.0.0.1
port: 6379
password:
#工作流配置
flowable:
database-schema-update: true

92
cms-api/cms-admin-svc/src/main/resources/application-pro.yml

@ -0,0 +1,92 @@
#项目配置
project:
#关闭权限
close-auth: 'false'
#true-请求端;false-接收端
bir-service: 'false'
#对应233服务的的cms
bir-service-url: 'http://59.37.164.96:7400'
#bir-service-url: 'http://127.0.0.1:7401'
web_url: 'http://192.168.0.9:6031'
host_url: 'http://192.168.0.9:7400'
pc-web-local: 'D:\Software\Nginx1.8\html\jslcrm3\'
apis:
#支付接口
cost-to-pay: 'http://59.37.164.96:2505/api/cms/api/add'
check-pay-status: 'http://59.37.164.96:2506/action/cms/cost/match'
# 核销生成报价单接口
diaodu-plan-order: ''
# 嘉士利接口,spu转换sku
spu-to-sku: 'http://59.37.164.96:2505/api/cms/order/matchInvCode'
# 政策同步
policy-sync-cate: 'http://59.37.164.96:2505/api/cms/saleCost/costPolicy/syncCate'
# 政策同步旧的
policy-sync-inv: 'http://59.37.164.96:2505/api/cms/saleCost/costPolicy/syncInv'
task: false
dev: false
seeyon:
enable: true
url: 'http://192.168.0.9:7444'
#请求致远OA的拓展服务(用于修改密码)
extApi: 'http://192.168.10.244:9003/'
upload:
#上传映射地址
proxy-url: https://qsjslservice.oss-cn-guangzhou.aliyuncs.com/jsl/
#物理存储地址
logical-path: D:\\WebMapPath\\
#腾讯云配置
tencent:
sms:
secret-id: AKIDR3A5mVkSaXFUT3TABanPxc2MtkMu45wb
secret-key: iLkjeKzHwegQ4eE55xX9byXmBLxgwypV
sdkAppId: 1400174031
signName: 柒胜软件
templateId: 689207
#天翼云配置
tianyi:
sms:
appid: 'WIgWyCFn4DnHLtjKBIXBVyZbGevFg3J4'
appKey: 'bjfsZlF01OZPUzyiCLSFOrOOnfsZhYZJ'
aliyun:
oss:
bucket: qsjslservice
accessKeyId: LTAI5tHvNJT7M9YZJ9BSmURK
accessKeySecret: OzH0ea3w8fgjrll9P0XTQlqmEg3Cky
endpoint: oss-cn-guangzhou.aliyuncs.com
prefix: jsl
#服务配置
server:
port: 7401
servlet:
context-path: /
#SpringBoot相关
spring:
datasource:
dynamic:
primary: crm_db #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
crm_db:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://183.56.249.148:3306/jsl_cost_base?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: '@Jsl2282125'
qisheng:
url: jdbc:sqlserver://192.168.10.11:1433;DatabaseName=JSL_COST_QS
username: sa
password: JSL2282125
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# erp:
# username: sa
# password: 'JSL2282125'
# url: jdbc:sqlserver://192.168.10.11:1433;DatabaseName=UFDATA_001_2020
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
redis:
database: 2
host: 127.0.0.1
port: 6379
password:
#工作流配置
flowable:
database-schema-update: true

87
cms-api/cms-admin-svc/src/main/resources/application.yml

@ -0,0 +1,87 @@
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 160MB
profiles:
active: dev
main:
#easypoi启用覆盖
allow-bean-definition-overriding: true
jmx:
enabled: false
devtools:
restart:
enabled: false
#项目配置
project:
ignore-url:
tenants: #忽略租户拦截
- /callback
- /favicon.ico
- /error
- /portal/syKeyLogin
- /bir/roiRate/test
- /static/*
- /api/wx/login/getCpSignature
- /web/*
permits: #忽略登录
- /thirty/** #第三方接口
- /portal/flushToken #第三方接口
- /common/upload #支持API上传调整
- /common/validToken #验证token
- /sys/attach/listByIds/**
- /api/**
- /static/**
- /web/**
- /portal/**
- /favicon.ico
- /error
- /callback
- /bir/roiRate/test
#mybatis plus
mybatis-plus:
mapper-locations: classpath:mapper/*/*.xml
type-aliases-package: com.qs.serve.modules.*.entity.*
configuration:
map-underscore-to-camel-case: true
#log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
global-config:
banner: false
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
select-strategy: not_empty
logic-delete-field: delFlag
# 日志配置
logging:
level:
ROOT: debug
com.qs.serve: debug
com.qs.serve.modules.his: debug
com.qs.serve.modules.sys: debug
com.qs.serve.modules.tag: info
org.xnio.nio: info
org.springframework: info
com.baomidou: info
org.mybatis: info
org.hibernate.validator: info
druid.sql.ResultSet: info
druid.sql.Connection: info
com.zaxxer.hikari.pool: info
com.zaxxer.hikari.HikariConfig: info
com.qs.serve.modules.sys.mapper.SysOperationLogMapper: info
java.io: warn
io.netty: info
io.undertow: info
io.lettuce.core: info
config: classpath:log4j2.xml
# PageHelper分页插件
pagehelper:
reasonable: false
#helper-dialect: sqlserver
autoRuntimeDialect: true
supportMethodsArguments: true
params: count=countSql

4
cms-api/cms-admin-svc/src/main/resources/banner.txt

@ -0,0 +1,4 @@
${AnsiBackground.BLACK}
-- ----------------------------
-- 嘉士利CRM系统 by.柒胜
-- ----------------------------

83
cms-api/cms-admin-svc/src/main/resources/log4j2.xml

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<property name="LOG_PATTERN" value="%d %highlight{%-5level}{ERROR=Bright RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} %style{[%t]}{bright,magenta} %style{%c{1.}.%M(%L)}{cyan}: %msg%n" />
<property name="FILE_PATH" value="home/logs" />
</Properties>
<appenders>
<!-- console -->
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
<ThresholdFilter level="all" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<File name="FileLog" fileName="${FILE_PATH}/test.log" append="false" filePattern="${FILE_PATH}/test-%d{yyyy-MM-dd}_%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</File>
<!-- debug -->
<RollingFile name="RollingFileDebug" fileName="${FILE_PATH}/debug.log" filePattern="${FILE_PATH}/debug-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="all" onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- info -->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/info-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- warn -->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/warn-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- error -->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/error-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<loggers>
<root level="debug">
<appender-ref ref="Console"/>
<appender-ref ref="FileLog"/>
<appender-ref ref="RollingFileDebug"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>

80
cms-api/cms-admin-svc/src/main/resources/tx-log4j2.xml

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<property name="LOG_PATTERN" value="%d %highlight{%-5level}{ERROR=Bright RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} %style{[%t]}{bright,magenta} %style{%c{1.}.%M(%L)}{cyan}: %msg%n" />
<!--<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />-->
<property name="FILE_PATH" value="logs" />
<property name="FILE_NAME" value="api" />
</Properties>
<appenders>
<!-- console -->
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="20MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</File>
<!-- info -->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- warn -->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- error -->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<loggers>
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="Filelog"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>

19
cms-api/cms-policy-svc/pom.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cms-api</artifactId>
<groupId>com.qs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cms-policy-svc</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

27
cms-api/pom.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jsl-cms</artifactId>
<groupId>com.qs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>cms-admin-svc</module>
<module>cms-policy-svc</module>
</modules>
<artifactId>cms-api</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

46
cms-common/pom.xml

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jsl-cms</artifactId>
<groupId>com.qs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cms-common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>

8
cms-common/src/main/java/com/qs/serve/common/TestCommon.java

@ -0,0 +1,8 @@
package com.qs.serve.common;
/**
* @author YenHex
* @since 2025/4/14
*/
public class TestCommon {
}

199
cms-framework/pom.xml

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jsl-cms</artifactId>
<groupId>com.qs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>cms-framework</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.qs</groupId>
<artifactId>cms-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.4</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>8.4.1.jre8</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.598</version>
</dependency>
<dependency>
<groupId>com.github.shalousun</groupId>
<artifactId>smart-doc</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.16.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10</version>
</dependency>
</dependencies>
</project>

24
cms-framework/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java

@ -0,0 +1,24 @@
package com.qs.serve.common.config;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;
import java.util.Collections;
/**
* 禁用jsessionid
* @author YenHex
* @since 2022/3/11
*/
@Configuration
public class CustomServletContextInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
}
}

33
cms-framework/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java

@ -0,0 +1,33 @@
package com.qs.serve.common.config;
import com.qs.serve.common.util.Assert;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
/**
* @author YenHex
* @since 2022/3/11
*/
@Slf4j
@UtilityClass
public class DevEnvironmentConfig {
private static Boolean devEnv = null;
public static void openDevEnv(Boolean open){
log.warn("环境变量:devEnv=>>> "+open);
devEnv = open;
}
public static Boolean isDev(){
if(devEnv==null){
Assert.throwEx("资源加载中...");
}
return devEnv;
}
/**
* 开启账套
*/
public final static boolean OPEN_TENANT_BOOK = true;
}

23
cms-framework/src/main/java/com/qs/serve/common/config/JwtConfig.java

@ -0,0 +1,23 @@
package com.qs.serve.common.config;
import lombok.Getter;
/**
* @Author: YenHex
* @Date: 2021/3/3
* @Version: 1.0
**/
@Getter
public class JwtConfig {
/**
* 单位分钟
*/
private final Integer expire = 7;
private final String iss = "KP_ISS";
private final String secret = "QiShenAa18n9VUcCxaSeSqLtFvsSCaRoVPKtBLaYxB0123456";
}

83
cms-framework/src/main/java/com/qs/serve/common/config/RedisConfig.java

@ -0,0 +1,83 @@
package com.qs.serve.common.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.*;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* @author YenHex
* @since 2022/2/24
*/
@EnableCaching
@Configuration(proxyBeanMethods = false)
public class RedisConfig extends CachingConfigurerSupport{
private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
private static final GenericJackson2JsonRedisSerializer JACKSON__SERIALIZER = new GenericJackson2JsonRedisSerializer();
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
//设置缓存过期时间
RedisCacheConfiguration redisCacheCfg=RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON__SERIALIZER));
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheCfg)
.build();
}
// @Bean
// public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
// JavaTimeModule module = new JavaTimeModule();
// DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// .appendPattern("yyyy-MM-dd HH:mm:ss").toFormatter();
// module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
// module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
// ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// objectMapper.registerModule(new JavaTimeModule());
// objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// return objectMapper;
// }
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
// 配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
// key序列化
redisTemplate.setKeySerializer(STRING_SERIALIZER);
// value序列化
redisTemplate.setValueSerializer(JACKSON__SERIALIZER);
// Hash key序列化
redisTemplate.setHashKeySerializer(STRING_SERIALIZER);
// Hash value序列化
redisTemplate.setHashValueSerializer(JACKSON__SERIALIZER);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

72
cms-framework/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java

@ -0,0 +1,72 @@
package com.qs.serve.common.config;
import com.qs.serve.common.config.properties.ProjectProperties;
import com.qs.serve.common.framework.interceptor.LimitSubmitInterceptor;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author YenHex
* @since 2022/2/24
*/
@Slf4j
@AllArgsConstructor
@Configuration(proxyBeanMethods = false)
public class SpringMvcConfig implements WebMvcConfigurer {
private final LimitSubmitInterceptor limitSubmitInterceptor;
//private final ApiAuthInterceptor apiAuthInterceptor;
private final ProjectProperties projectProperties;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(limitSubmitInterceptor)
.addPathPatterns("/**");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
log.warn("PcWebLocal==>{}",projectProperties.getPcWebLocal());
registry.addResourceHandler("/web/**")
.addResourceLocations("file:"+projectProperties.getPcWebLocal());
registry.addResourceHandler("/static/**")
.addResourceLocations("file:"+projectProperties.getPcWebLocal()+"static/");
}
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
/*是否允许请求带有验证信息*/
corsConfiguration.setAllowCredentials(true);
/*允许访问的客户端域名*/
corsConfiguration.addAllowedOrigin("*");
/*允许服务端访问的客户端请求头*/
corsConfiguration.addAllowedHeader("*");
/*允许访问的方法名,GET POST等*/
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
//@Bean
public MultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxInMemorySize(5120);
resolver.setMaxInMemorySize(300 * 1024 * 1024);
resolver.setDefaultEncoding("UTF-8");
return resolver;
}
}

56
cms-framework/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java

@ -0,0 +1,56 @@
package com.qs.serve.common.config;
import com.qs.serve.common.util.ThreadsUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
* @author YenHex
* @since 2022/2/24
*/
@Configuration
public class ThreadPoolConfig {
/** 核心线程池大小 */
private final int corePoolSize = 50;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
// 最大可创建的线程数
int maxPoolSize = 200;
// 队列最大长度
int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
int keepAliveSeconds = 300;
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/** 执行周期性或定时任务 */
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
ThreadsUtils.printException(r, t);
}
};
}
}

25
cms-framework/src/main/java/com/qs/serve/common/config/properties/AliYunOssProperties.java

@ -0,0 +1,25 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: YenHex
* @Date: 2021/3/3
* @Version: 1.0
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliYunOssProperties {
private String bucket;
private String accessKeyId;
private String accessKeySecret;
private String endpoint;
private String prefix;
}

13
cms-framework/src/main/java/com/qs/serve/common/config/properties/AuthUrlConst.java

@ -0,0 +1,13 @@
package com.qs.serve.common.config.properties;
/**
* @author YenHex
* @since 2024/3/27
*/
public class AuthUrlConst {
public final static String[] AUTH_ALLOW_URL = new String[]{
"bir/"
};
}

32
cms-framework/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java

@ -0,0 +1,32 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: YenHex
* @Date: 2021/3/3
* @Version: 1.0
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "project.ignore-url")
public class PermitProperties {
/**
* 可通过路径适用于回调场景无拦截场景等
*/
private List<String> permits = new ArrayList<>();
/**
* 默认租户拦截(适用于无需登录接口但有租户拦截)
*/
private List<String> tenants = new ArrayList<>();
}

36
cms-framework/src/main/java/com/qs/serve/common/config/properties/ProjectApisProperties.java

@ -0,0 +1,36 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2023/9/7
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "project.apis")
public class ProjectApisProperties {
/** 支付接口 */
private String costToPay;
/** 同步核销的支付状态 */
private String checkPayStatus;
/** 调度系统-发货单 */
private String diaoduPlanOrder;
/** 嘉士利接口,spu转换sku */
private String spuToSku;
/**
* 原是生成销路通apt的中间表替换伟成的接口直接生成
*/
private String policySyncCate;
private String policySyncInv;
}

31
cms-framework/src/main/java/com/qs/serve/common/config/properties/ProjectProperties.java

@ -0,0 +1,31 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: YenHex
* @Date: 2021/3/3
* @Version: 1.0
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "project")
public class ProjectProperties {
private String closeAuth;
private String birService;
private String birServiceUrl;
private String hostUrl;
private String webUrl;
private String pcWebLocal;
}

22
cms-framework/src/main/java/com/qs/serve/common/config/properties/QiShengDsProperties.java

@ -0,0 +1,22 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2024/6/18
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.qisheng")
public class QiShengDsProperties {
private String url;
private String username;
private String password;
}

25
cms-framework/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java

@ -0,0 +1,25 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2022/3/7
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
private String host;
private Integer port;
private String password;
private Integer database;
}

25
cms-framework/src/main/java/com/qs/serve/common/config/properties/SeeYonProperties.java

@ -0,0 +1,25 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: YenHex
* @Date: 2021/3/3
* @Version: 1.0
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "project.seeyon")
public class SeeYonProperties {
private Boolean enable;
private String url;
private String extApi;
}

24
cms-framework/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java

@ -0,0 +1,24 @@
package com.qs.serve.common.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author YenHex
* @since 2022/3/14
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "project.upload")
public class UploadProperties {
private String tempPath;
private String proxyUrl;
private String logicalPath;
}

35
cms-framework/src/main/java/com/qs/serve/common/framework/annotations/RedisCacheable.java

@ -0,0 +1,35 @@
package com.qs.serve.common.framework.annotations;
import java.lang.annotation.*;
/**
* 解决原有@CacheAble不支持独立失效策略场景
* @author YenHex
* @since 2024/10/17
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisCacheable {
/**
* redis缓存前缀默认类与方法名
* @return
*/
String prefix() default "";
/**
* 过期时间
* @return
*/
int expire() default 350;
/**
* 缓存读取主键表达式
* @return
*/
String expression() default "";
String SIMPLE_KEY = "#key";
}

4
cms-framework/src/main/java/com/qs/serve/common/framework/annotations/TagField.java

@ -0,0 +1,4 @@
package com.qs.serve.common.framework.annotations;
public @interface TagField {
}

133
cms-framework/src/main/java/com/qs/serve/common/framework/aop/RedisCacheAspect.java

@ -0,0 +1,133 @@
package com.qs.serve.common.framework.aop;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.qs.serve.common.framework.annotations.RedisCacheable;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.util.JsonUtil;
import com.qs.serve.common.util.StringUtils;
import lombok.AllArgsConstructor;
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.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotatedElementUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author YenHex
* @since 2024/10/18
*/
@Slf4j
//@Aspect
//@Component
@AllArgsConstructor
public class RedisCacheAspect {
private final RedisService redisService;
@Pointcut("@annotation(com.qs.serve.common.framework.annotations.RedisCacheable)")
public void PointCut() {}
@Around("PointCut()")
public Object redisCacheAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = ((MethodSignature) signature);
Method method = methodSignature.getMethod();
RedisCacheable redisCacheable = AnnotatedElementUtils.findMergedAnnotation(method, RedisCacheable.class);
if(redisCacheable!=null){
String prefix = StringUtils.hasText(redisCacheable.prefix()) ? redisCacheable.prefix()
: methodSignature.getDeclaringType().getName() +"."+ methodSignature.getMethod().getName()+"()";
//构建表达式key
String pk = this.getPrimaryKey(methodSignature,redisCacheable,args);
String redisCacheKey = "RCache:" + prefix + (pk==null?"":pk);
Object result = redisService.get(redisCacheKey);
if(result!=null){
return JsonUtil.jsonToMap(result.toString());
}
result = joinPoint.proceed(args);
if(result!=null){
redisService.set(redisCacheKey,JsonUtil.objectToJson(result),redisCacheable.expire(), TimeUnit.MILLISECONDS);
}
return result;
}
// 返回默认对象
return joinPoint.proceed(args);
}
public String getPrimaryKey(MethodSignature methodSignature,RedisCacheable annotation,Object[] args){
String method = methodSignature.getDeclaringType().getName()
+"."+ methodSignature.getMethod().getName()+"()";
final String expression = annotation.expression();
//适配表达式读取key,key读取不到log.error,放行请求
String primaryKey = null;
if(StringUtils.isNotEmpty(expression)){
//
if(expression.equals(RedisCacheable.SIMPLE_KEY)&&args.length==1){
return args[0].toString();
}
List<String> keys = new ArrayList<>();
// 指定表名
String tableName = null;
if(expression.contains(StringPool.DOT)){
String[] keyArr = expression.split(StringPool.BACK_SLASH + StringPool.DOT);
for (String key : keyArr) {
if(key.contains(StringPool.DOLLAR)){
tableName = key.replace(StringPool.DOLLAR,"");
continue;
}
keys.add(key);
}
}else {
keys.add(expression);
}
for (Object arg : args) {
// 跳过非指定的表名
if(tableName!=null){
String clazzName = arg.getClass().getSimpleName();
if(!clazzName.equals(tableName)){
continue;
}
}
// 读取key
primaryKey = getPrimaryKeyRecursion(keys, arg, 0);
}
if(primaryKey==null){
log.error("LockSubmitAspect失效,方法:{} 无法读取主键:{}",method,expression);
}
}
return primaryKey;
}
/**
* 递归读取主键
* @param keys
* @param arg
* @param startIndex
* @return
*/
private String getPrimaryKeyRecursion(List<String> keys, Object arg, int startIndex) {
String key = keys.get(startIndex);
Map<String,Object> param = JsonUtil.jsonToMap(JsonUtil.objectToJson(arg));
Object val = param.get(key);
if(val!=null){
boolean isLast = startIndex + 1== keys.size();
if(isLast){
return val.toString();
}else {
// 自调支持无限层级
return getPrimaryKeyRecursion(keys, val, startIndex + 1 );
}
}
return null;
}
}

21
cms-framework/src/main/java/com/qs/serve/common/framework/exception/BaseException.java

@ -0,0 +1,21 @@
package com.qs.serve.common.framework.exception;
/**
* @author JcYen
* @date 2020/6/11
* @version 1.0
*/
public abstract class BaseException extends RuntimeException {
public BaseException(String message){
super(message);
}
/**
* 错误代码
* @return
*/
public abstract int getCode();
}

25
cms-framework/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java

@ -0,0 +1,25 @@
package com.qs.serve.common.framework.exception;
import java.io.Serializable;
/**
* @author JcYen
* @Date 2020/6/11
* @Version 1.0
*/
public class BusinessException extends BaseException implements Serializable {
private static final long serialVersionUID = 1L;
private Integer status;
public BusinessException(String message,Integer status) {
super(message);
this.status = status;
}
@Override
public int getCode() {
return status;
}
}

153
cms-framework/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java

@ -0,0 +1,153 @@
package com.qs.serve.common.framework.exception;
import com.qs.serve.common.config.DevEnvironmentConfig;
import com.qs.serve.common.model.dto.R;
import com.qs.serve.common.model.enums.HttpCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLIntegrityConstraintViolationException;
/**
* @Author JcYen
* @Date 2019/6/7
* @Version 1.0
*/
@Slf4j
@Component
@ControllerAdvice
public class UnifiedExceptionHandler {
@ExceptionHandler(value = BusinessException.class)
@ResponseBody
public R handleBindException(BusinessException e,HttpServletRequest request) {
log.warn("自定义异常触发【{},{}】,请求地址:{}",e.getCode(),e.getMessage(),request.getRequestURI());
return new R(e.getCode(),e.getMessage());
}
@ExceptionHandler(value = NullPointerException.class)
@ResponseBody
public R handleBindException(NullPointerException e,HttpServletRequest request) {
StringBuilder stringBuilder = new StringBuilder();
for (StackTraceElement element : e.getStackTrace()) {
if (element.getClassName().contains("qs")){
stringBuilder.append(element.getClassName()+":"+element.getLineNumber()+"\n");
}
}
log.error("\n空指针:{} \n{}",request.getRequestURI(),stringBuilder);
e.printStackTrace();
return R.error("数据不存在或被移除");
}
@ExceptionHandler({
AccessDeniedException.class
})
@ResponseBody
public R handleAccessException(AccessDeniedException e,HttpServletRequest request) {
HttpCode hc = HttpCode.FORBIDDEN_403;
log.error("访问拦截【{}】,请求地址:{}",e.getMessage(),request.getRequestURI());
return new R(hc.getCode(),hc.getMsg());
}
@ExceptionHandler({
UsernameNotFoundException.class,
})
@ResponseBody
public R handlePrintMsgException(UsernameNotFoundException e) {
return R.error();
}
@ExceptionHandler({
BadCredentialsException.class,
})
@ResponseBody
public R handlePrintMsgException(Exception e) {
log.warn(e.getMessage());
HttpCode hc = HttpCode.LOGIN_ERR_1;
return new R(hc.getCode(),hc.getMsg());
}
@ExceptionHandler({
BindException.class,
HttpRequestMethodNotSupportedException.class
})
@ResponseBody
public R handleDevPrintMsgException(Exception e,HttpServletRequest request) {
log.error("参数校验异常:{}",e.getMessage());
if(DevEnvironmentConfig.isDev()){
return R.error(e.getMessage());
}
return R.error();
}
@ExceptionHandler({
MethodArgumentNotValidException.class,
})
@ResponseBody
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e,HttpServletRequest request) {
log.error("参数校验异常【{}】,请求地址:{}",e.getMessage(),request.getRequestURI());
return R.error(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
}
@ExceptionHandler(value = DuplicateKeyException.class)
@ResponseBody
public R handleDuplicateKeyException(DuplicateKeyException e,HttpServletRequest request) {
log.error("限制重复数据【{}】,请求地址:{}",e.getMessage(),request.getRequestURI());
e.printStackTrace();
return R.error("限制重复数据,请联系管理员");
}
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public R handleHttpMessageNotReadableException(HttpMessageNotReadableException e,HttpServletRequest request) {
log.error("请求参数无法解析【{}】,请求地址:{}",e.getMessage(),request.getRequestURI());
return R.error("请求参数无法解析");
}
@ExceptionHandler({
SQLIntegrityConstraintViolationException.class,
})
@ResponseBody
public R handleSqlIntegrityException(Exception e,HttpServletRequest request) {
log.warn("数据库拦截【{}】,请求地址:{}",e.getMessage(),request.getRequestURI());
e.printStackTrace();
return new R(500,"数据库拦截,请联系管理员");
}
/**
* 强制运行写入成功
* @param e
* @return
*/
@ExceptionHandler(value = HttpMessageNotWritableException.class)
@ResponseBody
public R handleMsgException(HttpMessageNotWritableException e) {
return R.ok();
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public R handleException(Exception e,HttpServletRequest request) {
log.error("Servlet异常\n请求地址:{},异常类型:{}\n异常信息:{}\n异常体:",request.getRequestURI(),e.getClass().getSimpleName(),e.getMessage(),e);
e.printStackTrace();
if(DevEnvironmentConfig.isDev()){return R.error(e.getMessage());}
return R.error();
}
}

66
cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java

@ -0,0 +1,66 @@
package com.qs.serve.common.framework.interceptor;
import com.qs.serve.common.framework.redis.RedisService;
import com.qs.serve.common.model.HttpResponsePrintUtil;
import com.qs.serve.common.model.annotation.LimitSubmit;
import com.qs.serve.common.util.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
/**
* 防止重复提交拦截器
* @author YenHex
*/
@Configuration(proxyBeanMethods = false)
public class LimitSubmitInterceptor implements HandlerInterceptor {
public final String REPEAT_Limit_KEY = "repeatLimitKey";
@Resource
public RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
LimitSubmit annotation = method.getAnnotation(LimitSubmit.class);
if (annotation != null) {
if (this.LimitSubmit(request, annotation)) {
if(StringUtils.isNotEmpty(annotation.message())){
HttpResponsePrintUtil.print(response,406,annotation.message());
}else {
HttpResponsePrintUtil.print(response,406,"系统处理中,请勿频繁操作");
}
return false;
}
}
return true;
} else {
return true;
}
}
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
* @param request 请求对象
* @param annotation 防复注解
* @return
*/
public boolean LimitSubmit(HttpServletRequest request, LimitSubmit annotation) throws Exception {
String key = REPEAT_Limit_KEY+"_"+request.getRequestURI()+"_"+request.getRemoteHost();
Object cache = redisService.get(key);
if(cache!=null){return true;}
redisService.set(key,"true",annotation.interval(), TimeUnit.MILLISECONDS);
return false;
}
}

29
cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/LocalDateTimeFormatSerializer.java

@ -0,0 +1,29 @@
package com.qs.serve.common.framework.interceptor;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author YenHex
* @since 2024/7/18
*/
public class LocalDateTimeFormatSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if (object == null) {
serializer.out.writeNull();
return;
}
LocalDateTime date = (LocalDateTime) object;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timeString = formatter.format(date);
serializer.write(timeString);
}
}

98
cms-framework/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java

@ -0,0 +1,98 @@
package com.qs.serve.common.framework.interceptor;
import com.qs.serve.common.model.HttpResponsePrintUtil;
import com.qs.serve.common.model.annotation.RepeatSubmit;
import com.qs.serve.common.util.JsonUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 防止重复提交拦截器
* @author YenHex
*/
@Configuration(proxyBeanMethods = false)
public class RepeatSubmitInterceptor implements HandlerInterceptor {
public final String REPEAT_PARAMS = "repeatParams";
public final String REPEAT_TIME = "repeatTime";
public final String SESSION_REPEAT_KEY = "repeatData";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
if (annotation != null) {
if (this.isRepeatSubmit(request, annotation)) {
HttpResponsePrintUtil.print(response,406,"系统正常处理,请勿重复提交");
return false;
}
}
return true;
} else {
return true;
}
}
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
* @param request 请求对象
* @param annotation 防复注解
* @return
*/
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception {
// 本次参数及系统时间
String nowParams = JsonUtil.objectToJson(request.getParameterMap());
Map<String, Object> nowDataMap = new HashMap<String, Object>();
nowDataMap.put(REPEAT_PARAMS, nowParams);
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
// 请求地址(作为存放session的key值)
String url = request.getRequestURI();
HttpSession session = request.getSession();
Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
if (sessionObj != null) {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
if (sessionMap.containsKey(url)) {
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) {
return true;
}
}
}
Map<String, Object> sessionMap = new HashMap<>();
sessionMap.put(url, nowDataMap);
session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
return false;
}
/**
* 判断参数是否相同
*/
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
String preParams = (String) preMap.get(REPEAT_PARAMS);
return nowParams.equals(preParams);
}
/**
* 判断两次间隔时间
*/
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
long time1 = (Long) nowMap.get(REPEAT_TIME);
long time2 = (Long) preMap.get(REPEAT_TIME);
if ((time1 - time2) < interval) {
return true;
}
return false;
}
}

52
cms-framework/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java

@ -0,0 +1,52 @@
package com.qs.serve.common.framework.manager;
import com.qs.serve.common.util.SpringUtils;
import com.qs.serve.common.util.ThreadsUtils;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 异步任务管理器
* @author YenHex
* @since 2022/2/24
*/
public class AsyncManager {
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager() {
}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me() {
return me;
}
/**
* 执行任务
* @param task 任务
*/
public void execute(TimerTask task) {
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/** 停止任务线程池 */
public void shutdown() {
ThreadsUtils.shutdownAndAwaitTermination(executor);
}
}

17
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java

@ -0,0 +1,17 @@
package com.qs.serve.common.framework.mybatis.handler;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.qs.serve.common.util.NanoIdUtils;
/**
* @author YenHex
* @since 2022/4/11
*/
public class IdGeneratorHandler extends DefaultIdentifierGenerator {
@Override
public String nextUUID(Object entity) {
return NanoIdUtils.randomNanoId();
}
}

50
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java

@ -0,0 +1,50 @@
package com.qs.serve.common.framework.mybatis.handler.meta;
import cn.hutool.json.JSONUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 存储到数据库, 将String数组转换成字符串;
* 从数据库获取数据, 将字符串转为LONG数组.
* @author YenHex
* @since 2022/3/1
*/
@MappedTypes({String[].class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class JsonStringTypeHandler extends BaseTypeHandler<String[]> {
private static String[] l = new String[]{};
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
String[] parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, JSONUtil.toJsonStr(parameter));
}
@Override
public String[] getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return JSONUtil.parseArray(rs.getString(columnName)).toArray(l);
}
@Override
public String[] getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l);
}
@Override
public String[] getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l);
}
}

74
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java

@ -0,0 +1,74 @@
package com.qs.serve.common.framework.mybatis.handler.meta;
import com.qs.serve.common.util.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
/**
* 存储到数据库, 将String数组转换成字符串;
* 从数据库获取数据, 将字符串转为LONG数组.
* @author YenHex
* @since 2022/3/1
*/
@MappedTypes({String[].class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class SplitStringTypeHandler extends BaseTypeHandler<String[]> {
private static String[] l = new String[]{};
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException {
if(parameter!=null&&parameter.length>1){
StringBuffer buffer = new StringBuffer();
for (int i1 = 0; i1 < parameter.length; i1++) {
buffer.append(parameter[i1]);
if(i1+1<parameter.length){
buffer.append(",");
}
}
ps.setString(i, buffer.toString());
}else if (parameter!=null&&parameter.length==1){
ps.setString(i, parameter[0]);
}else {
ps.setString(i, "");
}
}
@Override
public String[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
String valueString = rs.getString(columnName);
return initValues(valueString);
}
@Override
public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String valueString = rs.getString(columnIndex);
return initValues(valueString);
}
@Override
public String[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String valueString = cs.getString(columnIndex);
return initValues(valueString);
}
private String[] initValues(String valueString){
if(StringUtils.isNotEmpty(valueString)){
String[] vals = valueString.split(",");
return Arrays.stream(vals)
.filter(val -> val != null && val.trim().length() > 0)
.toArray(String[]::new);
}
return null;
}
}

69
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/TableNameAppendHandler.java

@ -0,0 +1,69 @@
package com.qs.serve.common.framework.mybatis.handler.meta;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
/**
* 拓展表格名称
* @author YenHex
* @since 2024/12/26
*/
@Slf4j
public class TableNameAppendHandler implements TableNameHandler {
/**
* 用于记录哪些表可以使用该月份动态表名处理器即哪些表按月分表
*/
private List<String> tableNames;
/**
* 构造函数构造动态表名处理器的时候传递tableNames参数
* @param tableNames
*/
public TableNameAppendHandler(String ...tableNames) {
this.tableNames = Arrays.asList(tableNames);
}
/**
* 每个请求线程维护一个month数据避免多线程数据冲突所以使用ThreadLocal
*/
private static final ThreadLocal<String> APPEND_DATA = new ThreadLocal<>();
/**
* 设置请求线程的month数据
* @param name
*/
public static void setAppend(String name) {
APPEND_DATA.set(name);
}
/**
* 删除当前请求线程的month数据
*/
public static void removeCache() {
APPEND_DATA.remove();
}
/**
* 动态表名接口实现方法
* @param sql
* @param tableName
* @return
*/
@Override
public String dynamicTableName(String sql, String tableName) {
if (this.tableNames.contains(tableName) && APPEND_DATA.get() != null){
//表名增加月份后缀
return tableName + "_" + APPEND_DATA.get();
}else{
if(this.tableNames.contains(tableName)){
log.warn("APPEND_DATA is null, table is {}",tableName);
}
//表名原样返回
return tableName;
}
}
}

115
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java

@ -0,0 +1,115 @@
package com.qs.serve.common.framework.mybatis.join;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity;
import com.qs.serve.common.framework.mybatis.join.enums.JoinType;
import com.qs.serve.common.framework.mybatis.join.model.JoinFieldData;
import com.qs.serve.common.util.CollectionUtil;
import com.qs.serve.common.util.SpringUtils;
import com.qs.serve.common.util.WordUtil;
import lombok.extern.slf4j.Slf4j;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author YenHex
* @since 2022/5/24
*/
@Slf4j
public class JoinUtil {
private static Map<String, List<JoinFieldData>> CACHE_MAP = new ConcurrentHashMap<>();
private static List<JoinFieldData> getJoinFields(List<?> list) {
if(CollectionUtil.isEmpty(list)){
return new ArrayList<>();
}
String className = list.get(0).getClass().getName();
List<JoinFieldData> joinFieldDataList = new ArrayList<>();
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(clazz==null){return null;}
Field[] fields = clazz.getDeclaredFields();
Field fieldJoinVal = null;
Field fieldSetVal = null;
BindEntity bindEntity = null;
for (Field field : fields) {
for (Annotation annotation : field.getAnnotations()) {
if(annotation instanceof BindEntity){
fieldSetVal = field;
bindEntity = (BindEntity) annotation;
break;
}
}
}
if(fieldSetVal!=null){
for (Field field :fields){
if(field.getName().equals(bindEntity.joinField())){
fieldJoinVal = field;
break;
}
}
}
if(bindEntity!=null&&fieldJoinVal!=null){
JoinFieldData fieldData = new JoinFieldData();
fieldData.setFieldJoinVal(fieldJoinVal);
fieldData.setBindEntity(bindEntity);
fieldData.setFieldSetVal(fieldSetVal);
joinFieldDataList.add(fieldData);
}
CACHE_MAP.put(className,joinFieldDataList);
return joinFieldDataList;
}
public static void relate(List<?> list) {
List<JoinFieldData> joinFieldData = getJoinFields(list);
HashMap<String,Object> tempCache = new HashMap<>(list.size()+1);
for (JoinFieldData fieldData : joinFieldData) {
for (Object object : list) {
try {
Field fieldJoinVal = fieldData.getFieldJoinVal();
Field fieldSetVal = fieldData.getFieldSetVal();
BindEntity bindEntity = fieldData.getBindEntity();
fieldSetVal.setAccessible(true);
fieldJoinVal.setAccessible(true);
IService<?> iService = SpringUtils.getBean(bindEntity.service());
Object identity = fieldJoinVal.get(object);
if(identity==null){
continue;
}
Object result = tempCache.get(identity.toString());
if(result!=null){
fieldSetVal.set(object,result);
continue;
}
if(bindEntity.joinType()== JoinType.List){
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq(WordUtil.toLine(bindEntity.joinField()),identity);
result = iService.list(wrapper);
}else {
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq(WordUtil.toLine(bindEntity.selfField()),identity);
result = iService.getOne(wrapper,false);
}
fieldSetVal.set(object,result);
tempCache.put(identity.toString(),result);
} catch (IllegalAccessException e) {
log.warn("join 工具失败:",e);
}
}
}
tempCache = null;
}
}

36
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java

@ -0,0 +1,36 @@
package com.qs.serve.common.framework.mybatis.join.annotations;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qs.serve.common.framework.mybatis.join.enums.JoinType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 实现left join
* @author YenHex
* @since 2022/5/24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface BindEntity {
Class<? extends IService> service();
/**
* 关联的表
* @return
*/
String joinField() default "";
/**
* 主表
* @return
*/
String selfField() default "id";
JoinType joinType() default JoinType.Object;
}

14
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java

@ -0,0 +1,14 @@
package com.qs.serve.common.framework.mybatis.join.enums;
/**
* @author YenHex
* @since 2022/5/24
*/
public enum JoinType {
/**
* 返回类型
*/
Object,List
}

17
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java

@ -0,0 +1,17 @@
package com.qs.serve.common.framework.mybatis.join.model;
import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity;
import lombok.Data;
import java.lang.reflect.Field;
/**
* @author YenHex
* @since 2022/5/24
*/
@Data
public class JoinFieldData {
Field fieldJoinVal;
Field fieldSetVal;
BindEntity bindEntity;
}

159
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java

@ -0,0 +1,159 @@
package com.qs.serve.common.framework.mybatis.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.serve.common.framework.mybatis.query.annotations.QueryWrap;
import com.qs.serve.common.framework.mybatis.query.model.QueryFieldData;
import com.qs.serve.common.framework.mybatis.query.model.QueryFieldDataValue;
import com.qs.serve.common.framework.mybatis.query.model.QueryType;
import com.qs.serve.common.util.WordUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author JcYen
* @Date 2017/10/28
* @Version 1.0
*/
@Slf4j
public class AnnotationQueryStorage {
private static final Map<String, List<QueryFieldData>> BEAN_QUERY_FIELD = new ConcurrentHashMap<>();
protected static List<QueryFieldData> getQueryFieldList(String className){
List<QueryFieldData> queryFieldList = BEAN_QUERY_FIELD.get(className);
if(queryFieldList==null){
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
queryFieldList = new ArrayList<>();
if(clazz==null){return queryFieldList;}
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
boolean isExist = false;
boolean isIgnore = false;
for (Annotation annotation : annotations) {
if(annotation instanceof QueryWrap){
QueryWrap queryWrap = (QueryWrap)annotation;
QueryFieldData queryField= handleQueryField(queryWrap.type(),field);
if(queryField!=null){
isExist = true;
queryFieldList.add(queryField);
break;
}
}
if(annotation instanceof TableField){
TableField tableField = (TableField) annotation;
isIgnore = tableField.exist();
}
}
//不存在,添加默认
if( !isExist && !isIgnore ){
QueryFieldData queryField = new QueryFieldData();
//系统默认使用格式。示例: userInfo -> user_info
queryField.setColumnName(WordUtil.toLine(field.getName()));
queryField.setField(field);
queryField.setFieldName(field.getName());
queryField.setType(QueryType.NONE);
queryFieldList.add(queryField);
}
}
BEAN_QUERY_FIELD.put(className,queryFieldList);
if(queryFieldList.size()==0){
log.warn("无匹配的注解字段,类名:"+className);
}
}
return queryFieldList;
}
/**
* 处理查询列
* @param queryType
* @param field
* @return
*/
private static QueryFieldData handleQueryField(QueryType queryType, Field field){
String columnName = null;
if(queryType!=null){
QueryFieldData queryField = new QueryFieldData();
if(StringUtils.isEmpty(columnName)){
columnName = WordUtil.toLine(field.getName());
}
queryField.setFieldName(field.getName());
queryField.setColumnName(columnName);
queryField.setField(field);
queryField.setType(queryType);
return queryField;
}
return null;
}
/**
* 加载查询对象生成配置值
* @param query
* @return
*/
protected static List<QueryFieldDataValue> loadQueryFieldDataValues(Object query){
String className = query.getClass().getName();
List<QueryFieldData> dataList = AnnotationQueryStorage.getQueryFieldList(className);
if(!CollectionUtils.isEmpty(dataList)){
List<QueryFieldDataValue> valueList = new ArrayList<>();
for (QueryFieldData fieldData : dataList) {
Field field = fieldData.getField();
field.setAccessible(true);
Object value = null;
try {
value = field.get(query);
} catch (IllegalAccessException e) {
log.warn("查询类字段参数异常。查询类:{},字段:{}",className,field.getName());
}
if(value!=null){
QueryFieldDataValue dataValue = new QueryFieldDataValue(fieldData);
//通过列条件,重新赋值(赋值查询条件和格式)
dataValue.setValue(value);
valueList.add(dataValue);
}
}
return valueList;
}
return null;
}
/**
* 初始化封装包参数
* @param fieldValues
* @param queryWrapper
* @param <T>
* @return 判断是否排序
*/
protected static <T> void initWrap(List<QueryFieldDataValue> fieldValues, QueryWrapper<T> queryWrapper){
for (QueryFieldDataValue fieldValue : fieldValues) {
QueryType queryType = fieldValue.getType();
Object value = fieldValue.getValue();
String column = fieldValue.getColumnName();
if(queryType.equals(QueryType.EQ)){ queryWrapper.eq(column,value); }
if(queryType.equals(QueryType.GE)){ queryWrapper.ge(column,value); }
if(queryType.equals(QueryType.GT)){ queryWrapper.gt(column,value); }
if(queryType.equals(QueryType.In)){ queryWrapper.in(column,value); }
if(queryType.equals(QueryType.LE)){ queryWrapper.le(column,value); }
if(queryType.equals(QueryType.Like)){ queryWrapper.like(column,value); }
if(queryType.equals(QueryType.LT)){ queryWrapper.lt(column,value); }
if(queryType.equals(QueryType.NE)){ queryWrapper.ne(column,value); }
if(queryType.equals(QueryType.RightLike)){ queryWrapper.likeRight(column,value); }
}
}
}

32
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java

@ -0,0 +1,32 @@
package com.qs.serve.common.framework.mybatis.query.annotations;
import com.qs.serve.common.framework.mybatis.query.model.QueryType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author JcYen
* @date 2020/5/26
* SQL In条件注解
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryWrap {
/**
* 列名默认为空字符串
* 空字符串采用字段转列策略 示例 userInfo -> user_info
* 非空时采用列的值
*/
String value() default "";
/**
* 查询类型默认采用值相对
*/
QueryType type() default QueryType.EQ;
}

23
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java

@ -0,0 +1,23 @@
package com.qs.serve.common.framework.mybatis.query.model;
import lombok.Getter;
import lombok.Setter;
import java.lang.reflect.Field;
/**
* 存储DTO
* @author JcYen
* @Date 2017/10/28
* @Version 1.0
*/
@Getter
@Setter
public class QueryFieldData {
private Field field;
private QueryType type;
private String columnName;
private String fieldName;
}

25
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java

@ -0,0 +1,25 @@
package com.qs.serve.common.framework.mybatis.query.model;
import com.qs.serve.common.util.CopierUtil;
import lombok.Getter;
import lombok.Setter;
/**
* 存储DTO
* @author JcYen
* @Date 2017/10/28
* @Version 1.0
*/
@Getter
@Setter
public class QueryFieldDataValue{
public QueryFieldDataValue(QueryFieldData data){
CopierUtil.copy(data,this);
}
private QueryType type;
private String columnName;
private String fieldName;
private Object value;
}

40
cms-framework/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java

@ -0,0 +1,40 @@
package com.qs.serve.common.framework.mybatis.query.model;
/**
* @author JcYen
*/
public enum QueryType {
/**
*
*/
NONE,
/**
* 通用的equalsIntegerLongString
*/
EQ,
NE,
/**
* 比较修饰符修饰日期数值类型Integer,Long,Double,BigDecimal)
*/
LT,
LE,
GT,
GE,
/**
* 修饰List<Long>
*/
In,
NotIn,
/**
* 修饰字符串
*/
Like,
RightLike,
NotLike,
}

415
cms-framework/src/main/java/com/qs/serve/common/framework/redis/RedisService.java

@ -0,0 +1,415 @@
package com.qs.serve.common.framework.redis;
import com.qs.serve.common.util.Assert;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author JcYen
* @since 2022/3/4
*/
@Service
@AllArgsConstructor
public class RedisService {
private final static ThreadLocal<String> RES_THEME_LOCK = new ThreadLocal<>();
public static void setLockTheme(String value){RES_THEME_LOCK.set(value);}
public static String getLockTheme(){return RES_THEME_LOCK.get();}
public static void removeThreadLocal(){
RES_THEME_LOCK.remove();
}
@Bean
@Primary
public RedisCacheManager selfCacheManager(RedisTemplate<String, Object> redisTemplate) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
return new TtlRedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
private RedisTemplate redisTemplate;
private StringRedisTemplate stringRedisTemplate;
public long nextId(String key) {
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
// 如果键不存在,则设置初始值为 "0"
if (!redisTemplate.hasKey(key)) {
valueOps.set(key, "0");
}
// 使用 INCR 命令递增计数器
return valueOps.increment(key);
}
/**
* 加锁
* @param theme
* @param id
* @return 是否在锁
*/
public void throwResLock(String theme,String id){
String key = "LOCK_RES:"+theme+":"+id;
String value = this.getString(key);
System.out.println("throwResLock:"+value);
String newVal = "lock";
if(newVal.equals(value)){
Assert.throwEx("服务正在处理,请稍后再试");
}
this.set(key,newVal,10,TimeUnit.MINUTES);
String value2 = this.getString(key);
if(!newVal.equals(value2)){
Assert.throwEx("锁失效");
}
RedisService.setLockTheme(key);
}
/**
* 释放锁
* @param theme
* @param id
* @return 是否在锁
*/
public void removeResLock(String theme,String id){
String key = "LOCK_RES:"+theme+":"+id;
this.remove(key);
}
/**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存设置时效时间
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, int expireTime) {
return set(key, value, expireTime,TimeUnit.SECONDS);
}
/**
* 写入缓存设置时效时间
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, int expireTime,TimeUnit unit) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, unit);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 批量删除对应的value
*
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除key
*
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/**
* 删除对应的value
*
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
*
* @param text
* @return
*/
public Set<String> list(final String text) {
Set<String> keySet = redisTemplate.keys("*" + text + "*");
for (String key : keySet) {
System.out.println(key);
}
return keySet;
}
/**
* 获取所有数据
*
* @return
*/
public Set<String> list() {
Set<String> keySet = redisTemplate.keys("*" + "#" +"*");
for (String key : keySet) {
System.out.println(key);
}
return keySet;
}
/**
* 判断缓存中是否有对应的value
*
* @param text
* @return
*/
public void removeForLike(final String text) {
Set<String> keySet = redisTemplate.keys("*" + text + "*");
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
redisTemplate.delete(it.next());
}
}
public Map<String, Object> cleanRedis() {
Map<String, Object> map = new HashMap<>();
try {
// 获取所有key
Set<String> keys = redisTemplate.keys("*");
assert keys != null;
// 迭代
Iterator<String> it1 = keys.iterator();
while (it1.hasNext()) {
// 循环删除
stringRedisTemplate.delete(it1.next());
}
map.put("code", 1);
map.put("msg", "清理全局缓存成功");
return map;
} catch (Exception e) {
map.put("code", -1);
map.put("msg", "清理全局缓存失败");
return map;
}
}
/**
* 判断缓存中是否有对应的value
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
public String getString(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
if(result!=null){
return result.toString();
}
return null;
}
public Integer getInteger(final String key) {
String result = getString(key);
if(result!=null){
return Integer.parseInt(result);
}
return null;
}
public Long getLong(final String key) {
String result = getString(key);
if(result!=null){
return Long.parseLong(result);
}
return null;
}
/**
* 哈希 添加
*
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key, hashKey, value);
}
/**
* 哈希获取数据
*
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key, hashKey);
}
/**
* 列表添加
*
* @param k
* @param v
*/
public void lPush(String k, Object v) {
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k, v);
}
/**
* 列表获取
*
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1) {
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k, l, l1);
}
/**
* 集合添加
*
* @param key
* @param value
*/
public void add(String key, Object value) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key, value);
}
/**
* 集合获取
*
* @param key
* @return
*/
public Set<Object> setMembers(String key) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/**
* 有序集合添加
*
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key, Object value, double scoure) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key, value, scoure);
}
/**
* 有序集合获取
*
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
/**
* 移除业务锁
* @param code
* @param targetId
*/
public void removeLock(String code,String targetId){
String key = "lock_commit:"+code+":"+targetId;
this.remove(key);
}
/**
*
* @param code
* @param targetId
* @return true--新建锁成功false反之
*/
public boolean tryToLock(String code,String targetId){
String key = "lock_commit:"+code+":"+targetId;
Integer existState = getInteger(key);
if(existState==null){
this.set(key,1,20,TimeUnit.SECONDS);
return true;
}else {
return false;
}
}
}

30
cms-framework/src/main/java/com/qs/serve/common/framework/redis/TtlRedisCacheManager.java

@ -0,0 +1,30 @@
package com.qs.serve.common.framework.redis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.util.StringUtils;
import java.time.Duration;
@Slf4j
public class TtlRedisCacheManager extends RedisCacheManager {
public TtlRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
super(cacheWriter, defaultCacheConfiguration);
}
@Override
protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
log.debug("TtlRedisCacheManager keyName:{}",name);
String[] cells = StringUtils.delimitedListToStringArray(name, "=");
name = cells[0];
if (cells.length > 1) {
long ttl = Long.parseLong(cells[1]);
// 根据传参设置缓存失效时间,默认单位是秒
cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
}
return super.createRedisCache(name, cacheConfig);
}
}

22
cms-framework/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java

@ -0,0 +1,22 @@
package com.qs.serve.common.framework.security.handler;
import com.qs.serve.common.model.HttpResponsePrintUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author YenHex
* @since 2022/3/3
*/
public class SecurityAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
HttpResponsePrintUtil.print(response,403,"权限不足");
}
}

22
cms-framework/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java

@ -0,0 +1,22 @@
package com.qs.serve.common.framework.security.handler;
import com.qs.serve.common.model.HttpResponsePrintUtil;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author YenHex
* @since 2022/3/3
*/
public class SecurityAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
HttpResponsePrintUtil.print(response,401,"登录信息已过期或失效");
}
}

97
cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java

@ -0,0 +1,97 @@
package com.qs.serve.common.framework.security.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户登录信息
* @author YenHex
* @since 2022/3/1
*/
@Data
@AllArgsConstructor
public class LoginUser implements UserDetails {
private String userId;
private String nick;
private String password;
private String loginIp;
/** 用户类型 */
private LoginUserType typeFlag;
private List<String> authorList;
private List<String> authorIds;
private String tenant;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if(authorList!=null&&authorList.size()>0){
return authorList
.stream()
.filter(n->n.length()>0)
.map(auth->new SimpleGrantedAuthority("ROLE_"+auth))
.collect(Collectors.toList());
}
return Collections.singletonList(new SimpleGrantedAuthority("NOT_ROLE"));
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return userId;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public LoginUserDTO loginUserDTO(){
return new LoginUserDTO(userId,nick,password,loginIp,typeFlag.getCode(),authorList,authorIds,tenant);
}
public boolean verifyRole(String permitCode){
return authorList.contains(permitCode);
}
/**
* 是否拥有招生超管权限
* @return
*/
public boolean hasRegSuperRole(){
return verifyRole("edu:reg:admin");
}
}

37
cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java

@ -0,0 +1,37 @@
package com.qs.serve.common.framework.security.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 用户登录信息
* @author YenHex
* @since 2022/3/1
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUserDTO {
private String userId;
private String nick;
private String password;
private String loginIp;
private String typeFlagCode;
private List<String> authorList;
private List<String> authorIds;
private String tenant;
public LoginUser loginUser(){
return new LoginUser(userId,nick,password,loginIp,LoginUserType.getByCode(typeFlagCode),authorList,authorIds,tenant);
}
}

34
cms-framework/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java

@ -0,0 +1,34 @@
package com.qs.serve.common.framework.security.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author YenHex
* @since 2022/3/7
*/
@Getter
@AllArgsConstructor
public enum LoginUserType {
/**
* 人员分类
*/
APP_USER("00","微信用户"),
SYS_USER("01","系统人员"),
SYS_SUP_USER("02","超级管理员")
;
private String code;
private String name;
public static LoginUserType getByCode(String code){
for (LoginUserType value : LoginUserType.values()) {
if(value.getCode().equals(code)){
return value;
}
}
return null;
}
}

28
cms-framework/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java

@ -0,0 +1,28 @@
package com.qs.serve.common.framework.security.util;
/**
* @Author JcYen
* @Date 2021/9/24
* @Version 1.0
*/
public class SecurityPermitUtil {
public static boolean verify(String reg, String input){
if ("/*".equals(reg)) return true;
String[] reg_split = reg.split("\\*");
int index = 0, reg_len = reg_split.length;
boolean b = reg.charAt(reg.length() - 1) == '*' ? true : false;
while (input.length() > 0) {
if (index == reg_len) {
if (b) return true;
else return false;
}
String r = reg_split[index++];
int indexOf = input.indexOf(r);
if (indexOf != 0) return false;
input = input.substring(indexOf + r.length());
}
return true;
}
}

18
cms-framework/src/main/java/com/qs/serve/common/model/AmountDTO.java

@ -0,0 +1,18 @@
package com.qs.serve.common.model;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author YenHex
* @since 2023/7/31
*/
@Data
public class AmountDTO {
private String id;
private BigDecimal amount;
}

34
cms-framework/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java

@ -0,0 +1,34 @@
package com.qs.serve.common.model;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author YenHex
* @since 2022/3/30
*/
public class HttpResponsePrintUtil {
public static void print(HttpServletResponse response,Integer code ,String msg) throws IOException,SecurityException{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setStatus(200);
response.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}");
response.getWriter().flush();
}
public static void print2(HttpServletResponse response,Integer code ,String msg)throws IOException,SecurityException{
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}");
response.getWriter().flush();
}
}

20
cms-framework/src/main/java/com/qs/serve/common/model/annotation/BusinessDifference.java

@ -0,0 +1,20 @@
package com.qs.serve.common.model.annotation;
import java.lang.annotation.*;
/**
* @author YenHex
* @since 2023/4/25
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BusinessDifference {
/**
* 字段备注
* @return
*/
String value() default "";
}

25
cms-framework/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java

@ -0,0 +1,25 @@
package com.qs.serve.common.model.annotation;
import java.lang.annotation.*;
/**
* 防止表单重复提交
* @author YenHex
* @since 2022-03-01
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LimitSubmit {
/**
* 间隔时间(ms)在世界间隔内超过执行次数视为被限制
*/
int interval() default 1000;
/**
* 提示消息
*/
String message() default "";
}

20
cms-framework/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java

@ -0,0 +1,20 @@
package com.qs.serve.common.model.annotation;
/**
* 防止表单重复提交
* @author YenHex
* @since 2022-03-01
*/
public @interface RepeatSubmit {
/**
* 间隔时间(ms)小于此时间视为重复提交
*/
int interval() default 5000;
/**
* 提示消息
*/
String message() default "不允许重复提交,请稍后再试";
}

35
cms-framework/src/main/java/com/qs/serve/common/model/annotation/SysLog.java

@ -0,0 +1,35 @@
package com.qs.serve.common.model.annotation;
import com.qs.serve.common.model.enums.BizType;
import com.qs.serve.common.model.enums.InterType;
import com.qs.serve.common.model.enums.SystemModule;
import java.lang.annotation.*;
/**
* 记录用户登录操作
* @author YenHex
* @since 2022-03-01
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
SystemModule module() default SystemModule.SYSTEM;
/** 业务标题 */
String title() default "";
/** 操作描述 */
String desc() default "";
/** 操作类型 */
BizType biz() default BizType.OTHER;
/** 接口类型 */
InterType inter() default InterType.ADMIN;
boolean saveReqParam() default true;
}

19
cms-framework/src/main/java/com/qs/serve/common/model/chart/BiCommonCounter.java

@ -0,0 +1,19 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class BiCommonCounter {
/**
* 横轴下标的ID
*/
private String label;
private Long counts;
}

15
cms-framework/src/main/java/com/qs/serve/common/model/chart/BiMonthCounter.java

@ -0,0 +1,15 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class BiMonthCounter {
private String months;
private Long counts;
}

39
cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartAxisColumn.java

@ -0,0 +1,39 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class ChartAxisColumn {
/** 列Id */
String columnId;
/** 列名 */
String columnName;
/** 系列坐标值合计 */
Double total;
public static List<ChartAxisColumn> buildMonthsOfYear(){
List<ChartAxisColumn> axisColumnList = new ArrayList<>();
for (long i = 1; i < 13; i++) {
ChartAxisColumn axisColumn = new ChartAxisColumn();
if(i>9){
axisColumn.setColumnId(i+"");
}else {
axisColumn.setColumnId("0"+i);
}
axisColumn.setColumnName(i+"月");
axisColumnList.add(axisColumn);
}
return axisColumnList;
}
}

148
cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartDataVo.java

@ -0,0 +1,148 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class ChartDataVo {
/**
* 饼状图的主要参数
*/
List<ChartAxisColumn> axisColumnList;
/**
* 系列
*/
List<ChartSeriesItem> seriesItemList;
/**
* 分组
*/
List<ChartGroupItem> groupItemList;
public void initAxisColumnTotal(){
for (int i = 0; i < axisColumnList.size(); i++) {
ChartAxisColumn axisColumn = axisColumnList.get(i);
BigDecimal total = BigDecimal.ZERO;
if(seriesItemList!=null&&seriesItemList.size()>0){
for (ChartSeriesItem seriesItem : seriesItemList) {
double value = seriesItem.getValues().get(i);
total = total.add(new BigDecimal(value+""));
}
}
axisColumn.setTotal(total.doubleValue());
}
}
public static ChartDataVo buildStateChartData(List<BiCommonCounter> stateCounterList, Map<String,String> stateMap){
ChartDataVo chartDataVo = new ChartDataVo();
List<ChartAxisColumn> axisColumnList = new ArrayList<>();
List<ChartSeriesItem> seriesItemList = new ArrayList<>();
List<ChartGroupItem> groupItemList = new ArrayList<>();
ChartGroupItem groupItem = new ChartGroupItem();
groupItem.setGroupId(100L);
groupItem.setGroupName("默认");
groupItemList.add(groupItem);
for (String stateNum : stateMap.keySet()) {
String label = stateMap.get(stateNum);
ChartAxisColumn axisColumn = new ChartAxisColumn();
axisColumn.setColumnId(stateNum);
axisColumn.setColumnName(label);
axisColumnList.add(axisColumn);
}
List<Double> values = new ArrayList<>();
for (ChartAxisColumn chartAxisColumn : axisColumnList) {
Double currVal = 0.0;
for (BiCommonCounter counter : stateCounterList) {
if(chartAxisColumn.getColumnId().equals(counter.getLabel())){
currVal = counter.getCounts().doubleValue();
break;
}
}
values.add(currVal);
}
ChartSeriesItem seriesItem = new ChartSeriesItem();
seriesItem.setGroupId(groupItem.getGroupId());
seriesItem.setGroupName(groupItem.getGroupName());
seriesItem.setValues(values);
seriesItemList.add(seriesItem);
//更新total
chartDataVo.setAxisColumnList(axisColumnList);
chartDataVo.setGroupItemList(groupItemList);
chartDataVo.setSeriesItemList(seriesItemList);
chartDataVo.initAxisColumnTotal();
return chartDataVo;
}
public void tes(){
}
public void buildStateMap(Map<String,String> stateMap){
init();
for (String stateNum : stateMap.keySet()) {
String label = stateMap.get(stateNum);
ChartAxisColumn axisColumn = new ChartAxisColumn();
axisColumn.setColumnId(stateNum);
axisColumn.setColumnName(label);
this.axisColumnList.add(axisColumn);
}
}
public void buildStateMapOfMonths(){
init();
this.axisColumnList = ChartAxisColumn.buildMonthsOfYear();
}
/**
* 先调用buildStateMap
* @param groupId
* @param groupName
* @param stateCounterList
*/
public void addData(Long groupId,String groupName,List<BiCommonCounter> stateCounterList){
ChartGroupItem groupItem = new ChartGroupItem();
groupItem.setGroupId(groupId);
groupItem.setGroupName(groupName);
groupItemList.add(groupItem);
List<Double> values = new ArrayList<>();
for (ChartAxisColumn chartAxisColumn : axisColumnList) {
Double currVal = 0.0;
for (BiCommonCounter counter : stateCounterList) {
if(chartAxisColumn.getColumnId().equals(counter.getLabel())){
currVal = counter.getCounts().doubleValue();
break;
}
}
values.add(currVal);
}
ChartSeriesItem seriesItem = new ChartSeriesItem();
seriesItem.setGroupId(groupItem.getGroupId());
seriesItem.setGroupName(groupItem.getGroupName());
seriesItem.setValues(values);
seriesItemList.add(seriesItem);
this.initAxisColumnTotal();
}
private void init(){
if(axisColumnList==null){
axisColumnList = new ArrayList<>();
}
if(seriesItemList==null){
seriesItemList = new ArrayList<>();
}
if(groupItemList==null){
groupItemList = new ArrayList<>();
}
}
}

18
cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartGroupItem.java

@ -0,0 +1,18 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class ChartGroupItem {
/** 组id */
private Long groupId;
/** 组名 */
private String groupName;
}

26
cms-framework/src/main/java/com/qs/serve/common/model/chart/ChartSeriesItem.java

@ -0,0 +1,26 @@
package com.qs.serve.common.model.chart;
import lombok.Data;
import java.util.List;
/**
* @author YenHex
* @since 2023/6/7
*/
@Data
public class ChartSeriesItem {
/** 组id */
Long groupId;
/** 组名 */
String groupName;
/**
* 值列表(列对应axisColumns)
*/
List<Double> values;
}

75
cms-framework/src/main/java/com/qs/serve/common/model/chart/PrintChart.java

@ -0,0 +1,75 @@
package com.qs.serve.common.model.chart;
import com.qs.serve.common.util.JsonUtil;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author YenHex
* @since 2023/2/17
*/
public class PrintChart {
public static void main(String[] args) {
//eg. 统计最近5年入学人数,并区分男女数量
ChartDataVo chartDataVo = new ChartDataVo();
List<ChartAxisColumn> axisColumnList = new ArrayList<>();
List<ChartSeriesItem> seriesItemList = new ArrayList<>();
List<ChartGroupItem> groupItemList = new ArrayList<>();
ChartGroupItem groupItem = new ChartGroupItem();
groupItem.setGroupId(100L);
groupItem.setGroupName("男学生");
groupItemList.add(groupItem);
ChartGroupItem groupItem2 = new ChartGroupItem();
groupItem2.setGroupId(200L);
groupItem2.setGroupName("女学生");
groupItemList.add(groupItem2);
for (long i = 1; i <= 5; i++) {
ChartAxisColumn axisColumn = new ChartAxisColumn();
axisColumn.setColumnId(i+"");
axisColumn.setColumnName("202"+i+"年");
axisColumnList.add(axisColumn);
}
Random random = new Random();
for (ChartGroupItem chartGroupItem : groupItemList) {
ChartSeriesItem seriesItem = new ChartSeriesItem();
seriesItem.setGroupId(chartGroupItem.getGroupId());
seriesItem.setGroupName(chartGroupItem.getGroupName());
List<Double> values = new ArrayList<>();
for (int i = 0; i < axisColumnList.size(); i++) {
double result = random.nextInt(1000)+3000;
values.add(result);
}
seriesItem.setValues(values);
seriesItemList.add(seriesItem);
}
//更新total
for (int i = 0; i < axisColumnList.size(); i++) {
ChartAxisColumn axisColumn = axisColumnList.get(i);
BigDecimal total = BigDecimal.ZERO;
for (ChartSeriesItem seriesItem : seriesItemList) {
double value = seriesItem.getValues().get(i);
total = total.add(new BigDecimal(value+""));
}
axisColumn.setTotal(total.doubleValue());
}
chartDataVo.setAxisColumnList(axisColumnList);
chartDataVo.setGroupItemList(groupItemList);
chartDataVo.setSeriesItemList(seriesItemList);
String v = JsonUtil.objectToJson(chartDataVo);
System.out.println(v);
}
}

13
cms-framework/src/main/java/com/qs/serve/common/model/consts/ApplyTypeConst.java

@ -0,0 +1,13 @@
package com.qs.serve.common.model.consts;
/**
* @author YenHex
* @since 2023/9/19
*/
public interface ApplyTypeConst {
String CostBill = "CostBill";
String CheckCost = "CheckCost";
String ReleasePolicy = "ReleasePolicy";
}

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

Loading…
Cancel
Save