commit
b65c4df52a
1780 changed files with 159921 additions and 0 deletions
@ -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> |
@ -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")); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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 { |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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同步开启"); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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();
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(){ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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 |
@ -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 |
@ -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 |
||||
|
|
@ -0,0 +1,4 @@ |
|||||
|
${AnsiBackground.BLACK} |
||||
|
-- ---------------------------- |
||||
|
-- 嘉士利CRM系统 by.柒胜 |
||||
|
-- ---------------------------- |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -0,0 +1,8 @@ |
|||||
|
package com.qs.serve.common; |
||||
|
|
||||
|
/** |
||||
|
* @author YenHex |
||||
|
* @since 2025/4/14 |
||||
|
*/ |
||||
|
public class TestCommon { |
||||
|
} |
@ -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> |
@ -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)); |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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"; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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/" |
||||
|
}; |
||||
|
|
||||
|
} |
@ -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<>(); |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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"; |
||||
|
|
||||
|
} |
@ -0,0 +1,4 @@ |
|||||
|
package com.qs.serve.common.framework.annotations; |
||||
|
|
||||
|
public @interface TagField { |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
|
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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&¶meter.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&¶meter.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; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package com.qs.serve.common.framework.mybatis.join.enums; |
||||
|
|
||||
|
/** |
||||
|
* @author YenHex |
||||
|
* @since 2022/5/24 |
||||
|
*/ |
||||
|
public enum JoinType { |
||||
|
|
||||
|
/** |
||||
|
* 返回类型 |
||||
|
*/ |
||||
|
Object,List |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
@ -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); } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
||||
|
|
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
package com.qs.serve.common.framework.mybatis.query.model; |
||||
|
|
||||
|
/** |
||||
|
* @author JcYen |
||||
|
*/ |
||||
|
public enum QueryType { |
||||
|
|
||||
|
/** |
||||
|
* 无 |
||||
|
*/ |
||||
|
NONE, |
||||
|
|
||||
|
/** |
||||
|
* 通用的equals(Integer,Long,String) |
||||
|
*/ |
||||
|
EQ, |
||||
|
NE, |
||||
|
|
||||
|
/** |
||||
|
* 比较修饰符,修饰日期,数值类型(Integer,Long,Double,BigDecimal) |
||||
|
*/ |
||||
|
LT, |
||||
|
LE, |
||||
|
GT, |
||||
|
GE, |
||||
|
|
||||
|
/** |
||||
|
* 修饰List<Long> |
||||
|
*/ |
||||
|
In, |
||||
|
NotIn, |
||||
|
|
||||
|
/** |
||||
|
* 修饰字符串 |
||||
|
*/ |
||||
|
Like, |
||||
|
RightLike, |
||||
|
NotLike, |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
@ -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,"权限不足"); |
||||
|
} |
||||
|
} |
@ -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,"登录信息已过期或失效"); |
||||
|
} |
||||
|
} |
@ -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"); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -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 ""; |
||||
|
|
||||
|
} |
@ -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 ""; |
||||
|
|
||||
|
} |
@ -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 "不允许重复提交,请稍后再试"; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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; |
||||
|
|
||||
|
} |
@ -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); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -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…
Reference in new issue