This commit is contained in:
张良(004796)
2024-02-04 18:52:07 +08:00
parent 684216368c
commit 9e29c5f321
22 changed files with 700 additions and 11 deletions

View File

@@ -0,0 +1,37 @@
package com.ruoyi.web.controller.cai.admin;
import com.ruoyi.cai.dto.admin.vo.home.HomeStaticIndexVo;
import com.ruoyi.cai.dto.admin.vo.rank.RankNodeAdminVo;
import com.ruoyi.cai.enums.rank.RankTimeTypeEnum;
import com.ruoyi.cai.manager.AdminHomeManager;
import com.ruoyi.common.core.domain.R;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
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;
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cai/home")
public class HomeController {
@Autowired
private AdminHomeManager adminHomeManager;
@GetMapping("/static/index")
public R<HomeStaticIndexVo> staticIndex(){
HomeStaticIndexVo homeStaticIndexVo = adminHomeManager.staticIndex();
return R.ok(homeStaticIndexVo);
}
@GetMapping("/static/rank")
public R<List<RankNodeAdminVo>> staticRank(Integer rankType,String rankTime){
List<RankNodeAdminVo> rank = adminHomeManager.rank(rankType, RankTimeTypeEnum.getByCode(rankTime));
return R.ok(rank);
}
}

View File

@@ -1,5 +1,7 @@
package com.ruoyi.test.business; package com.ruoyi.test.business;
import com.alibaba.fastjson.JSON;
import com.ruoyi.cai.cache.RechargeTotalCache;
import com.ruoyi.cai.domain.Gift; import com.ruoyi.cai.domain.Gift;
import com.ruoyi.cai.domain.User; import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.mq.handle.dto.WindowRechargeNotifyDTO; import com.ruoyi.cai.mq.handle.dto.WindowRechargeNotifyDTO;
@@ -23,6 +25,19 @@ public class NoticeTest {
@Autowired @Autowired
private YunxinHttpService yunxinHttpService; private YunxinHttpService yunxinHttpService;
@Autowired
private RechargeTotalCache rechargeTotalCache;
@Test
public void test(){
System.out.println(JSON.toJSONString(rechargeTotalCache.getToday()));
rechargeTotalCache.add(BigDecimal.valueOf(8123.12D));
System.out.println(JSON.toJSONString(rechargeTotalCache.getToday()));
rechargeTotalCache.add(BigDecimal.valueOf(123));
System.out.println(JSON.toJSONString(rechargeTotalCache.getToday()));
}
/** /**
* 注册赠送消息 * 注册赠送消息
*/ */

View File

@@ -11,6 +11,9 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* 用户每日发送统计
*/
@Component @Component
public class DynamicTotalCache { public class DynamicTotalCache {

View File

@@ -0,0 +1,60 @@
package com.ruoyi.cai.cache;
import com.ruoyi.cai.cache.bean.RechargeTotalCacheBean;
import com.ruoyi.cai.constant.RedisHttpConstant;
import com.ruoyi.common.utils.MapGetUtil;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/**
* 每日充值统计
*/
@Component
public class RechargeTotalCache {
@Autowired
private RedissonClient redissonClient;
public String getKey(LocalDate date){
String now = date.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return String.format(RedisHttpConstant.RECHARGE_TOTAL_CACHE_REDIS,now);
}
public void add(BigDecimal amount){
String key = getKey(LocalDate.now());
RMap<String, Object> map = redissonClient.getMap(key);
map.addAndGet("amount",amount.doubleValue());
map.addAndGet("num",1);
map.expireAsync(Duration.ofDays(3));
}
public RechargeTotalCacheBean get(LocalDate date){
String key = getKey(date);
RMap<String, Object> map = redissonClient.getMap(key);
Map<String, Object> allMap = map.readAllMap();
Object amountObj = allMap.getOrDefault("amount", 0.0D);
BigDecimal amount = MapGetUtil.getBigDecimal(amountObj);
Object numObj = allMap.getOrDefault("num", 0);
Long num = MapGetUtil.getLong(numObj);
RechargeTotalCacheBean rechargeTotalCacheBean = new RechargeTotalCacheBean();
rechargeTotalCacheBean.setAmount(amount);
rechargeTotalCacheBean.setNum(num);
return rechargeTotalCacheBean;
}
public RechargeTotalCacheBean getToday(){
return get(LocalDate.now());
}
public RechargeTotalCacheBean getLastToday(){
return get(LocalDate.now().plusDays(-1));
}
}

View File

@@ -0,0 +1,60 @@
package com.ruoyi.cai.cache;
import com.ruoyi.cai.cache.bean.WithdrawTotalCacheBean;
import com.ruoyi.cai.constant.RedisHttpConstant;
import com.ruoyi.common.utils.MapGetUtil;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/**
* 每日充值统计
*/
@Component
public class WithdrawTotalCache {
@Autowired
private RedissonClient redissonClient;
public String getKey(LocalDate date){
String now = date.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return String.format(RedisHttpConstant.WITHDRAW_TOTAL_CACHE_REDIS,now);
}
public void add(BigDecimal amount){
String key = getKey(LocalDate.now());
RMap<String, Object> map = redissonClient.getMap(key);
map.addAndGet("amount",amount.doubleValue());
map.addAndGet("num",1);
map.expireAsync(Duration.ofDays(3));
}
public WithdrawTotalCacheBean get(LocalDate date){
String key = getKey(date);
RMap<String, Object> map = redissonClient.getMap(key);
Map<String, Object> allMap = map.readAllMap();
Object amountObj = allMap.getOrDefault("amount", 0.0D);
BigDecimal amount = MapGetUtil.getBigDecimal(amountObj);
Object numObj = allMap.getOrDefault("num", 0);
Long num = MapGetUtil.getLong(numObj);
WithdrawTotalCacheBean bean = new WithdrawTotalCacheBean();
bean.setAmount(amount);
bean.setNum(num);
return bean;
}
public WithdrawTotalCacheBean getToday(){
return get(LocalDate.now());
}
public WithdrawTotalCacheBean getLastToday(){
return get(LocalDate.now().plusDays(-1));
}
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.cai.cache.bean;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class RechargeTotalCacheBean {
private BigDecimal amount;
private Long num;
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.cai.cache.bean;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class WithdrawTotalCacheBean {
private BigDecimal amount;
private Long num;
}

View File

@@ -6,12 +6,16 @@ public class RedisHttpConstant {
public static final String CITY_CACHE_REDIS = REDIS_P + "city"; public static final String CITY_CACHE_REDIS = REDIS_P + "city";
public static final String CITY_CACHE_ALL_REDIS = REDIS_P + "cityAll"; public static final String CITY_CACHE_ALL_REDIS = REDIS_P + "cityAll";
public static final String DYNAMIC_TOTAL_CACHE_REDIS = REDIS_P + "synamicTotal:%s:%s"; public static final String DYNAMIC_TOTAL_CACHE_REDIS = REDIS_P + "synamicTotal:%s:%s";
public static final String RECHARGE_TOTAL_CACHE_REDIS = REDIS_P + "rechargeTotal:%s";
public static final String WITHDRAW_TOTAL_CACHE_REDIS = REDIS_P + "withdrawTotal:%s";
public static final String CODE_REDIS = REDIS_P + "code:%s:%s"; public static final String CODE_REDIS = REDIS_P + "code:%s:%s";
public static final String USER_GREET_TOTAL_REDIS = REDIS_P + "userGreetTotal:%s:%s"; public static final String USER_GREET_TOTAL_REDIS = REDIS_P + "userGreetTotal:%s:%s";
public static final String USER_GREET_SEND_TIME_REDIS = REDIS_P + "userGreetSendTime:%s"; public static final String USER_GREET_SEND_TIME_REDIS = REDIS_P + "userGreetSendTime:%s";
public static final String FORBID_CACHE_REDIS = REDIS_P + "forbid:%s"; public static final String FORBID_CACHE_REDIS = REDIS_P + "forbid:%s";
public static final String LOVE_RANK_REDIS = REDIS_P + "loveRank:%s:%s"; public static final String LOVE_RANK_REDIS = REDIS_P + "loveRank:%s:%s";
public static final String INVITE_RANK_REDIS = REDIS_P + "inviteRank:%s:%s"; public static final String INVITE_RANK_REDIS = REDIS_P + "inviteRank:%s:%s";
public static final String WITHDRAW_RANK_REDIS = REDIS_P + "withdrawRank:%s:%s";
public static final String RECHARGE_RANK_REDIS = REDIS_P + "rechargeRank:%s:%s";
public static final String HOME_RECOMMEND_REDIS = REDIS_P + "homeRecommendAnchor"; public static final String HOME_RECOMMEND_REDIS = REDIS_P + "homeRecommendAnchor";
public static final String HOME_NEW_REDIS = REDIS_P + "homeNewAnchor"; public static final String HOME_NEW_REDIS = REDIS_P + "homeNewAnchor";
public static final String HOME_ACTIVE_REDIS = REDIS_P + "homeActiveAnchor"; public static final String HOME_ACTIVE_REDIS = REDIS_P + "homeActiveAnchor";

View File

@@ -77,6 +77,11 @@ public class DayIncomeStatistics implements Serializable {
*/ */
private Long modifyIncomeSub; private Long modifyIncomeSub;
/**
* 登陆用户
*/
private Long loginNum;
private LocalDateTime createTime; private LocalDateTime createTime;
private LocalDateTime updateTime; private LocalDateTime updateTime;

View File

@@ -0,0 +1,21 @@
package com.ruoyi.cai.dto.admin.vo.home;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class HomeStaticIndexVo {
private Long todayLoginNum;
private BigDecimal todayLoginDiffLast;
private Long anchorNum;
private BigDecimal todayRechargeAmountNum;
private Long todayRechargeNum;
private BigDecimal todayRechargeAmountDiffLast;
private BigDecimal todayWithdrawAmount;
private Long todayWithdrawNum;
private BigDecimal todayWithdrawAmountDiffLast;
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.cai.dto.admin.vo.rank;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class RankNodeAdminVo {
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "头像")
private String avatar;
@Schema(description = "昵称")
private String nickname;
@Schema(description = "蜜瓜号")
private String usercode;
@Schema(description = "数值")
private Number value;
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.cai.enums.rank;
import lombok.Getter;
@Getter
public enum RankTimeTypeEnum {
DAY("Day"),
WEEK("Week"),
MONTH("Month"),
TOTAL("Total"),
;
private final String code;
RankTimeTypeEnum(String code) {
this.code = code;
}
public static RankTimeTypeEnum getByCode(String code){
RankTimeTypeEnum[] values = RankTimeTypeEnum.values();
for (RankTimeTypeEnum value : values) {
if(value.getCode().equals(code)){
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,146 @@
package com.ruoyi.cai.manager;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.cache.RechargeTotalCache;
import com.ruoyi.cai.cache.WithdrawTotalCache;
import com.ruoyi.cai.cache.bean.RechargeTotalCacheBean;
import com.ruoyi.cai.cache.bean.WithdrawTotalCacheBean;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.dto.admin.vo.home.HomeStaticIndexVo;
import com.ruoyi.cai.dto.admin.vo.rank.RankNodeAdminVo;
import com.ruoyi.cai.enums.rank.RankTimeTypeEnum;
import com.ruoyi.cai.rank.RankAdminManager;
import com.ruoyi.cai.rank.RankManager;
import com.ruoyi.cai.rank.RankNode;
import com.ruoyi.cai.rank.bean.RankAdminNode;
import com.ruoyi.cai.service.AnchorService;
import com.ruoyi.cai.service.UserService;
import com.ruoyi.cai.util.CaiNumUtil;
import com.ruoyi.framework.OnlineUserTodayCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
public class AdminHomeManager {
@Autowired
private OnlineUserTodayCache onlineUserTodayCache;
@Autowired
private AnchorService anchorService;
@Autowired
private RechargeTotalCache rechargeTotalCache;
@Autowired
private WithdrawTotalCache withdrawTotalCache;
@Autowired
private RankAdminManager rankAdminManager;
@Autowired
private RankManager rankManager;
@Autowired
private UserService userService;
/**
* @param rankType 1-魅力榜 2-邀请榜 3-充值榜 4-提现榜
* @param rankTimeType
*/
public List<RankNodeAdminVo> rank(Integer rankType, RankTimeTypeEnum rankTimeType){
if(rankType == null || rankTimeType == null){
return Collections.emptyList();
}
List<RankNodeAdminVo> res = new ArrayList<>();
List<RankNode> rankNodeList;
if(rankType == 1){
if(rankTimeType == RankTimeTypeEnum.DAY){
rankNodeList = rankManager.getInviteRankToday(30);
}else if(rankTimeType == RankTimeTypeEnum.WEEK){
rankNodeList = rankManager.getInviteRankWeek(30);
}else if(rankTimeType == RankTimeTypeEnum.MONTH){
rankNodeList = rankManager.getInviteRankMonth(30);
}else if(rankTimeType == RankTimeTypeEnum.TOTAL){
rankNodeList = rankManager.getInviteRankTotal(30);
}else{
rankNodeList = Collections.emptyList();
}
res = rankNodeList.stream().map(i -> {
RankNodeAdminVo vo = new RankNodeAdminVo();
vo.setUserId(i.getUserId());
vo.setValue(i.getScore());
return vo;
}).collect(Collectors.toList());
}else if(rankType == 2){
if(rankTimeType == RankTimeTypeEnum.DAY){
rankNodeList = rankManager.getLoveRankToday(30);
}else if(rankTimeType == RankTimeTypeEnum.WEEK){
rankNodeList = rankManager.getLoveRankWeek(30);
}else if(rankTimeType == RankTimeTypeEnum.MONTH){
rankNodeList = rankManager.getLoveRankMonth(30);
}else if(rankTimeType == RankTimeTypeEnum.TOTAL){
rankNodeList = rankManager.getLoveRankTotal(30);
}else{
rankNodeList = Collections.emptyList();
}
res = rankNodeList.stream().map(i -> {
RankNodeAdminVo vo = new RankNodeAdminVo();
vo.setUserId(i.getUserId());
vo.setValue(i.getScore());
return vo;
}).collect(Collectors.toList());
}else if(rankType == 3){
List<RankAdminNode> rank = rankAdminManager.getRechargeRank(LocalDate.now(), rankTimeType, 30);
res = rank.stream().map(i -> {
RankNodeAdminVo vo = new RankNodeAdminVo();
vo.setUserId(i.getUserId());
vo.setValue(i.getScore());
return vo;
}).collect(Collectors.toList());
}else if(rankType == 4){
List<RankAdminNode> rank = rankAdminManager.getWithdrawRank(LocalDate.now(), rankTimeType, 30);
res = rank.stream().map(i -> {
RankNodeAdminVo vo = new RankNodeAdminVo();
vo.setUserId(i.getUserId());
vo.setValue(i.getScore());
return vo;
}).collect(Collectors.toList());
}
if(CollectionUtils.isEmpty(res)){
return res;
}
Set<Long> userIds = res.stream().map(RankNodeAdminVo::getUserId).collect(Collectors.toSet());
List<User> userList = userService.listByIds(userIds);
Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
for (RankNodeAdminVo re : res) {
User user = userMap.get(re.getUserId());
if(user != null){
re.setUsercode(user.getUsercode());
re.setNickname(user.getNickname());
re.setAvatar(user.getAvatar());
}
}
return res;
}
public HomeStaticIndexVo staticIndex(){
Long onlineTodayNum = onlineUserTodayCache.getOnlineTodayNum();
Long onlineLastNum = onlineUserTodayCache.getOnlineLastNum();
HomeStaticIndexVo vo = new HomeStaticIndexVo();
vo.setTodayLoginNum(onlineTodayNum);
vo.setTodayLoginDiffLast(CaiNumUtil.diffRate(onlineTodayNum,onlineLastNum));
vo.setAnchorNum(anchorService.count(Wrappers.emptyWrapper()));
RechargeTotalCacheBean todayRecharge = rechargeTotalCache.getToday();
RechargeTotalCacheBean lastTodayRecharge = rechargeTotalCache.getLastToday();
vo.setTodayRechargeAmountNum(todayRecharge.getAmount());
vo.setTodayRechargeNum(todayRecharge.getNum());
vo.setTodayRechargeAmountDiffLast(CaiNumUtil.diffRate(todayRecharge.getAmount(),lastTodayRecharge.getAmount()));
WithdrawTotalCacheBean todayWithdraw = withdrawTotalCache.getToday();
WithdrawTotalCacheBean lastTodayWithdraw = withdrawTotalCache.getLastToday();
vo.setTodayWithdrawAmount(todayWithdraw.getAmount());
vo.setTodayWithdrawNum(todayWithdraw.getNum());
vo.setTodayWithdrawAmountDiffLast(CaiNumUtil.diffRate(todayWithdraw.getAmount(),lastTodayWithdraw.getAmount()));
return vo;
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.cai.manager; package com.ruoyi.cai.manager;
import com.ruoyi.cai.cache.RechargeTotalCache;
import com.ruoyi.cai.domain.Account; import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.domain.ConsumeLog; import com.ruoyi.cai.domain.ConsumeLog;
import com.ruoyi.cai.domain.Gift; import com.ruoyi.cai.domain.Gift;
@@ -16,7 +17,9 @@ import com.ruoyi.cai.mq.handle.dto.WindowGiftNotifyDTO;
import com.ruoyi.cai.mq.handle.dto.WindowRechargeNotifyDTO; import com.ruoyi.cai.mq.handle.dto.WindowRechargeNotifyDTO;
import com.ruoyi.cai.notice.YunxinHttpService; import com.ruoyi.cai.notice.YunxinHttpService;
import com.ruoyi.cai.pay.PayTypeEnum; import com.ruoyi.cai.pay.PayTypeEnum;
import com.ruoyi.cai.rank.RankAdminManager;
import com.ruoyi.cai.rank.RankManager; import com.ruoyi.cai.rank.RankManager;
import com.ruoyi.cai.rank.bean.RankAdminBean;
import com.ruoyi.cai.service.*; import com.ruoyi.cai.service.*;
import com.ruoyi.cai.ws.bean.Room; import com.ruoyi.cai.ws.bean.Room;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -123,10 +126,24 @@ public class ConsumerManager {
rankManager.sendLoveRankMq(consumeLog.getSourceUserId(),consumeLog.getAnchorAmount(),consumeLog.getTraceId()); rankManager.sendLoveRankMq(consumeLog.getSourceUserId(),consumeLog.getAnchorAmount(),consumeLog.getTraceId());
return resp; return resp;
} }
@Autowired
private RechargeTotalCache rechargeTotalCache;
@Autowired
private RankAdminManager rankAdminManager;
public RechargeConsumerResp rechargeOrderSuccess(String tradeNo, Map<String,String> params, String appId, PayTypeEnum payTypeEnum){ public RechargeConsumerResp rechargeOrderSuccess(String tradeNo, Map<String,String> params, String appId, PayTypeEnum payTypeEnum){
RechargeConsumerResp resp = rechargeOrderService.orderSuccess(tradeNo,params,appId,payTypeEnum); RechargeConsumerResp resp = rechargeOrderService.orderSuccess(tradeNo,params,appId,payTypeEnum);
if(resp.isSuccess()){ if(resp.isSuccess()){
try {
rechargeTotalCache.add(resp.getPrice());
RankAdminBean rankAdminBean = new RankAdminBean();
rankAdminBean.setRankType(3); // 充值榜单
rankAdminBean.setUserId(resp.getUserId());
rankAdminBean.setPrice(resp.getPrice());
rankAdminManager.addRank(rankAdminBean);
}catch (Exception e){
log.error("充值每日实时统计失败",e);
}
try { try {
amqpProducer.sendCalculateSales(resp.getConsumeLogId()+""); amqpProducer.sendCalculateSales(resp.getConsumeLogId()+"");
}catch (Exception e){ }catch (Exception e){

View File

@@ -44,7 +44,7 @@ public class LoginNotifyHandle implements IHandle {
@Override @Override
public void run(String message) { public void run(String message) {
LoginNotifyDTO loginNotify = JSON.parseObject(message, LoginNotifyDTO.class); LoginNotifyDTO loginNotify = JSON.parseObject(message, LoginNotifyDTO.class);
boolean todayFirstLogin = onlineUserTodayCache.addOnlineUserId(loginNotify.getUserId(),loginNotify.getHappenTime()); boolean todayFirstLogin = onlineUserTodayCache.addOnlineUserId(loginNotify.getUserId(),loginNotify.getHappenTime().toLocalDate());
if(todayFirstLogin){ if(todayFirstLogin){
this.updateUserInfoSB(loginNotify.getUserId(),loginNotify.getClientIP(),loginNotify.getImei()); this.updateUserInfoSB(loginNotify.getUserId(),loginNotify.getClientIP(),loginNotify.getImei());
} }

View File

@@ -0,0 +1,148 @@
package com.ruoyi.cai.rank;
import com.ruoyi.cai.constant.RedisHttpConstant;
import com.ruoyi.cai.enums.rank.RankTimeTypeEnum;
import com.ruoyi.cai.rank.bean.RankAdminBean;
import com.ruoyi.cai.rank.bean.RankAdminNode;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.client.protocol.ScoredEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 充值和提现
* 排行榜 后台管理专用, 暂时没有做持久化
*/
@Component
public class RankAdminManager {
@Autowired
private RedissonClient redissonClient;
public static final String WITHDRAW_RANK_REDIS = RedisHttpConstant.WITHDRAW_RANK_REDIS;
public static final String RECHARGE_RANK_REDIS = RedisHttpConstant.RECHARGE_RANK_REDIS;
private String dateString(LocalDate time){
return time.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
}
/**
* 获取key
* @param time 时间
* @return
*/
private String getWithdrawKey(LocalDate time, RankTimeTypeEnum rankTimeTypeEnum){
String typeStr;
if(rankTimeTypeEnum == RankTimeTypeEnum.DAY){
typeStr = dateString(time);
}else if(rankTimeTypeEnum == RankTimeTypeEnum.WEEK){
LocalDate monday = time.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate sunday = time.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
String mondayStr = dateString(monday);
String sundayStr = dateString(sunday);
typeStr = mondayStr+"-"+sundayStr;
}else if(rankTimeTypeEnum == RankTimeTypeEnum.MONTH){
typeStr = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
}else if(rankTimeTypeEnum == RankTimeTypeEnum.TOTAL){
typeStr = RankTimeTypeEnum.TOTAL.getCode();
}else {
return null;
}
return String.format(WITHDRAW_RANK_REDIS,rankTimeTypeEnum.getCode(),typeStr);
}
private String getRechargeKey(LocalDate time,RankTimeTypeEnum rankTimeTypeEnum){
String typeStr;
if(rankTimeTypeEnum == RankTimeTypeEnum.DAY){
typeStr = dateString(time);
}else if(rankTimeTypeEnum == RankTimeTypeEnum.WEEK){
LocalDate monday = time.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate sunday = time.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
String mondayStr = dateString(monday);
String sundayStr = dateString(sunday);
typeStr = mondayStr+"-"+sundayStr;
}else if(rankTimeTypeEnum == RankTimeTypeEnum.MONTH){
typeStr = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
}else if(rankTimeTypeEnum == RankTimeTypeEnum.TOTAL){
typeStr = RankTimeTypeEnum.TOTAL.getCode();
}else {
return null;
}
return String.format(RECHARGE_RANK_REDIS,rankTimeTypeEnum.getCode(),typeStr);
}
public void addRank(RankAdminBean dto){
if(dto.getRankType() == null){
return;
}
if(dto.getRankType() == 3){ // 3-充值榜
LocalDate localDate = dto.getHappenTime().toLocalDate();
String dayKey = getRechargeKey(localDate,RankTimeTypeEnum.DAY);
RScoredSortedSet<String> daySet = redissonClient.getScoredSortedSet(dayKey);
daySet.addScore(dto.getUserId()+"",dto.getPrice());
String weekKey = getRechargeKey(localDate,RankTimeTypeEnum.WEEK);
RScoredSortedSet<String> weekSet = redissonClient.getScoredSortedSet(weekKey);
weekSet.addScore(dto.getUserId()+"",dto.getPrice());
String monthKey = getRechargeKey(localDate,RankTimeTypeEnum.MONTH);
RScoredSortedSet<String> monthSet = redissonClient.getScoredSortedSet(monthKey);
monthSet.addScore(dto.getUserId()+"",dto.getPrice());
String totalKey = getRechargeKey(localDate,RankTimeTypeEnum.TOTAL);
RScoredSortedSet<String> totalSet = redissonClient.getScoredSortedSet(totalKey);
totalSet.addScore(dto.getUserId()+"",dto.getPrice());
}else if(dto.getRankType() == 4){ // 4=提现榜
LocalDate localDate = dto.getHappenTime().toLocalDate();
String dayKey = getWithdrawKey(localDate,RankTimeTypeEnum.DAY);
RScoredSortedSet<String> daySet = redissonClient.getScoredSortedSet(dayKey);
daySet.addScore(dto.getUserId()+"",dto.getPrice());
String weekKey = getWithdrawKey(localDate,RankTimeTypeEnum.WEEK);
RScoredSortedSet<String> weekSet = redissonClient.getScoredSortedSet(weekKey);
weekSet.addScore(dto.getUserId()+"",dto.getPrice());
String monthKey = getWithdrawKey(localDate,RankTimeTypeEnum.MONTH);
RScoredSortedSet<String> monthSet = redissonClient.getScoredSortedSet(monthKey);
monthSet.addScore(dto.getUserId()+"",dto.getPrice());
String totalKey = getWithdrawKey(localDate,RankTimeTypeEnum.TOTAL);
RScoredSortedSet<String> totalSet = redissonClient.getScoredSortedSet(totalKey);
totalSet.addScore(dto.getUserId()+"",dto.getPrice());
}
}
public List<RankAdminNode> getRechargeRank(LocalDate date, RankTimeTypeEnum rankTimeType, int limit){
List<RankAdminNode> res = new ArrayList<>();
String key = getRechargeKey(date,rankTimeType);
RScoredSortedSet<String> daySet = redissonClient.getScoredSortedSet(key);
Collection<ScoredEntry<String>> entries = daySet.entryRangeReversed(0, limit-1);
for (ScoredEntry<String> entry : entries) {
res.add(RankAdminNode.getNode(entry));
}
return res;
}
public List<RankAdminNode> getWithdrawRank(LocalDate date, RankTimeTypeEnum rankTimeType, int limit){
List<RankAdminNode> res = new ArrayList<>();
String key = getWithdrawKey(date,rankTimeType);
RScoredSortedSet<String> daySet = redissonClient.getScoredSortedSet(key);
Collection<ScoredEntry<String>> entries = daySet.entryRangeReversed(0, limit-1);
for (ScoredEntry<String> entry : entries) {
res.add(RankAdminNode.getNode(entry));
}
return res;
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.cai.rank.bean;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class RankAdminBean {
/**
* // 1-魅力榜
* // 2-邀请榜
* 3-充值榜
* 4-提现榜
*/
private Integer rankType;
// 受益人ID
private Long userId;
private Number price;
private LocalDateTime happenTime = LocalDateTime.now();
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.cai.rank.bean;
import lombok.Data;
import org.redisson.client.protocol.ScoredEntry;
import java.math.BigDecimal;
@Data
public class RankAdminNode {
private BigDecimal score;
private Long userId;
public RankAdminNode() {
}
public static RankAdminNode getNode(ScoredEntry<String> entry){
RankAdminNode rankNode = new RankAdminNode();
rankNode.setScore(BigDecimal.valueOf(entry.getScore()));
rankNode.setUserId(Long.valueOf(entry.getValue()));
return rankNode;
}
}

View File

@@ -3,6 +3,7 @@ package com.ruoyi.cai.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.cache.WithdrawTotalCache;
import com.ruoyi.cai.domain.AccountBankcard; import com.ruoyi.cai.domain.AccountBankcard;
import com.ruoyi.cai.domain.AccountCash; import com.ruoyi.cai.domain.AccountCash;
import com.ruoyi.cai.domain.WithdrawExchange; import com.ruoyi.cai.domain.WithdrawExchange;
@@ -17,6 +18,8 @@ import com.ruoyi.cai.notice.YunxinHttpService;
import com.ruoyi.cai.notice.dto.CashSuccessSendMesDTO; import com.ruoyi.cai.notice.dto.CashSuccessSendMesDTO;
import com.ruoyi.cai.pay.OrderNoUtil; import com.ruoyi.cai.pay.OrderNoUtil;
import com.ruoyi.cai.pay.OrderTypeEnum; import com.ruoyi.cai.pay.OrderTypeEnum;
import com.ruoyi.cai.rank.RankAdminManager;
import com.ruoyi.cai.rank.bean.RankAdminBean;
import com.ruoyi.cai.service.AccountCashService; import com.ruoyi.cai.service.AccountCashService;
import com.ruoyi.cai.service.AccountBankcardService; import com.ruoyi.cai.service.AccountBankcardService;
import com.ruoyi.cai.service.AccountService; import com.ruoyi.cai.service.AccountService;
@@ -43,6 +46,10 @@ public class AccountCashServiceImpl extends ServiceImpl<AccountCashMapper, Accou
private WithdrawExchangeService withdrawExchangeService; private WithdrawExchangeService withdrawExchangeService;
@Autowired @Autowired
private YunxinHttpService yunxinHttpService; private YunxinHttpService yunxinHttpService;
@Autowired
private WithdrawTotalCache withdrawTotalCache;
@Autowired
private RankAdminManager rankAdminManager;
@Override @Override
public void withdraw(WithdrawReq res) { public void withdraw(WithdrawReq res) {
AccountBankcard one = accountBankcardService.getOne(Wrappers.lambdaQuery(AccountBankcard.class) AccountBankcard one = accountBankcardService.getOne(Wrappers.lambdaQuery(AccountBankcard.class)
@@ -113,11 +120,21 @@ public class AccountCashServiceImpl extends ServiceImpl<AccountCashMapper, Accou
if(accountCash == null){ if(accountCash == null){
return; return;
} }
// 发送通知 try {
yunxinHttpService.cashSuccessSendMessage(accountCash.getUserId(), withdrawTotalCache.add(accountCash.getCashMoney());
accountCash.getCreateTime(), RankAdminBean rankAdminBean = new RankAdminBean();
accountCash.getCashMoney(),accountCash.getRealCashMoney(), rankAdminBean.setRankType(3); // 充值榜单
accountCash.getCardAccount(),accountCash.getVerifyTime()); rankAdminBean.setUserId(accountCash.getUserId());
rankAdminBean.setPrice(accountCash.getCashMoney());
rankAdminManager.addRank(rankAdminBean);
// 发送通知
yunxinHttpService.cashSuccessSendMessage(accountCash.getUserId(),
accountCash.getCreateTime(),
accountCash.getCashMoney(),accountCash.getRealCashMoney(),
accountCash.getCardAccount(),accountCash.getVerifyTime());
}catch (Exception e){
log.error("提现后续统计和通知操作失败!需要开发检查问题",e);
}
} }
@@ -153,6 +170,12 @@ public class AccountCashServiceImpl extends ServiceImpl<AccountCashMapper, Accou
dto.setCardAccount(cash.getCardAccount()); dto.setCardAccount(cash.getCardAccount());
dto.setVerifyTime(now); dto.setVerifyTime(now);
dtoList.add(dto); dtoList.add(dto);
withdrawTotalCache.add(cash.getCashMoney());
RankAdminBean rankAdminBean = new RankAdminBean();
rankAdminBean.setRankType(3); // 充值榜单
rankAdminBean.setUserId(cash.getUserId());
rankAdminBean.setPrice(cash.getCashMoney());
rankAdminManager.addRank(rankAdminBean);
}else{ }else{
ignoreNum++; ignoreNum++;
} }

View File

@@ -2,15 +2,17 @@ package com.ruoyi.cai.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.DayIncomeStatistics;
import com.ruoyi.cai.dto.admin.incomeStatis.AccountCashCountDTO; import com.ruoyi.cai.dto.admin.incomeStatis.AccountCashCountDTO;
import com.ruoyi.cai.dto.admin.incomeStatis.RechargeOrderCountDTO; import com.ruoyi.cai.dto.admin.incomeStatis.RechargeOrderCountDTO;
import com.ruoyi.cai.dto.admin.incomeStatis.VipOrderCountDTO; import com.ruoyi.cai.dto.admin.incomeStatis.VipOrderCountDTO;
import com.ruoyi.cai.domain.DayIncomeStatistics;
import com.ruoyi.cai.mapper.AccountCashMapper; import com.ruoyi.cai.mapper.AccountCashMapper;
import com.ruoyi.cai.mapper.DayIncomeStatisticsMapper; import com.ruoyi.cai.mapper.DayIncomeStatisticsMapper;
import com.ruoyi.cai.mapper.RechargeOrderMapper; import com.ruoyi.cai.mapper.RechargeOrderMapper;
import com.ruoyi.cai.mapper.VipOrderMapper; import com.ruoyi.cai.mapper.VipOrderMapper;
import com.ruoyi.cai.service.DayIncomeStatisticsService; import com.ruoyi.cai.service.DayIncomeStatisticsService;
import com.ruoyi.framework.OnlineUserTodayCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@@ -35,6 +37,8 @@ public class DayIncomeStatisticsServiceImpl extends ServiceImpl<DayIncomeStatist
private VipOrderMapper vipOrderMapper; private VipOrderMapper vipOrderMapper;
@Resource @Resource
private AccountCashMapper accountCashMapper; private AccountCashMapper accountCashMapper;
@Autowired
private OnlineUserTodayCache onlineUserTodayCache;
@Override @Override
public void refreshByDate(LocalDate date){ public void refreshByDate(LocalDate date){
@@ -58,8 +62,12 @@ public class DayIncomeStatisticsServiceImpl extends ServiceImpl<DayIncomeStatist
RechargeOrderCountDTO recharge = rechargeOrderMapper.incomeStatistics(startTime,endTime); RechargeOrderCountDTO recharge = rechargeOrderMapper.incomeStatistics(startTime,endTime);
VipOrderCountDTO vip = vipOrderMapper.incomeStatistics(startTime,endTime); VipOrderCountDTO vip = vipOrderMapper.incomeStatistics(startTime,endTime);
AccountCashCountDTO cash = accountCashMapper.incomeStatistics(startTime,endTime); AccountCashCountDTO cash = accountCashMapper.incomeStatistics(startTime,endTime);
Long loginNum = onlineUserTodayCache.getOnlineNum(date);
DayIncomeStatistics update = new DayIncomeStatistics(); DayIncomeStatistics update = new DayIncomeStatistics();
update.setId(one.getId()); update.setId(one.getId());
if(loginNum != null && loginNum != 0){
update.setLoginNum(loginNum);
}
if(recharge != null){ if(recharge != null){
update.setExpInMoney(recharge.getExpInMoney()==null? BigDecimal.ZERO:recharge.getExpInMoney()); update.setExpInMoney(recharge.getExpInMoney()==null? BigDecimal.ZERO:recharge.getExpInMoney());
update.setOrderCount(recharge.getOrderCount()==null?0:recharge.getOrderCount()); update.setOrderCount(recharge.getOrderCount()==null?0:recharge.getOrderCount());

View File

@@ -39,4 +39,21 @@ public class CaiNumUtil {
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(memberDay(BigDecimal.valueOf(20), 3220)); System.out.println(memberDay(BigDecimal.valueOf(20), 3220));
} }
public static BigDecimal diffRate(Long onlineTodayNum, Long onlineLastNum) {
Long diff = onlineTodayNum - onlineLastNum;
if(onlineLastNum == 0){
return BigDecimal.ZERO;
}
return NumberUtil.div(diff,onlineLastNum,3);
}
public static BigDecimal diffRate(BigDecimal onlineTodayNum, BigDecimal onlineLastNum) {
BigDecimal diff = NumberUtil.sub(onlineTodayNum, onlineLastNum);
if(onlineLastNum.compareTo(BigDecimal.ZERO) == 0){
return BigDecimal.ZERO;
}
return NumberUtil.div(diff,onlineLastNum,3);
}
} }

View File

@@ -18,20 +18,35 @@ public class OnlineUserTodayCache {
@Autowired @Autowired
private RedissonClient redissonClient; private RedissonClient redissonClient;
private String getKey(LocalDateTime dateTime){ private String getKey(LocalDate dateTime){
String today = dateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd")); String today = dateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return String.format(CacheConstants.ONLINE_TODAY_TOKEN_KEY,today); return String.format(CacheConstants.ONLINE_TODAY_TOKEN_KEY,today);
} }
public boolean addOnlineUserId(Long userId, LocalDateTime dateTime){ public boolean addOnlineUserId(Long userId, LocalDate dateTime){
RSet<Long> set = redissonClient.getSet(getKey(dateTime)); RSet<Long> set = redissonClient.getSet(getKey(dateTime));
boolean res = set.add(userId); boolean res = set.add(userId);
set.expire(Duration.ofDays(1)); set.expire(Duration.ofDays(3));
return res; return res;
} }
public Set<Long> getAllOnlineToday(){ public Set<Long> getAllOnlineToday(){
RSet<Long> set = redissonClient.getSet(getKey(LocalDateTime.now())); RSet<Long> set = redissonClient.getSet(getKey(LocalDate.now()));
return set.readAll(); return set.readAll();
} }
public Long getOnlineNum(LocalDate time){
RSet<Long> set = redissonClient.getSet(getKey(time));
return (long) set.size();
}
public Long getOnlineTodayNum(){
RSet<Long> set = redissonClient.getSet(getKey(LocalDate.now()));
return (long) set.size();
}
public Long getOnlineLastNum(){
RSet<Long> set = redissonClient.getSet(getKey(LocalDate.now().plusDays(-1)));
return (long) set.size();
}
} }