V13
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package com.ruoyi.cai.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 魅力榜单实时数据
|
||||
*/
|
||||
@Data
|
||||
@TableName("cai_love_rank_today")
|
||||
public class LoveRankToday implements Serializable {
|
||||
@TableId(value = "id",type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 日期类型 1-日榜 2-周榜 3-月榜
|
||||
*/
|
||||
private Integer dataType;
|
||||
|
||||
/**
|
||||
* 榜单期数
|
||||
*/
|
||||
private LocalDate rankTime;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDate beginRankTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDate endRankTime;
|
||||
|
||||
/**
|
||||
* 数值
|
||||
*/
|
||||
private Long num;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.cai.dto.app.vo.rank;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class RankNodeRecharge {
|
||||
|
||||
@Schema(description = "用户ID,只有当前用户才有数据,其他用户因为保密问题没有")
|
||||
private Long userId;
|
||||
@Schema(description = "头像")
|
||||
private String avatar;
|
||||
@Schema(description = "昵称")
|
||||
private String nickname;
|
||||
private BigDecimal money;
|
||||
@Schema(description = "数值")
|
||||
private Long value;
|
||||
@Schema(description = "距离上一名差距")
|
||||
private Long diffLastValue;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import lombok.Getter;
|
||||
public enum RankTypeEnum {
|
||||
LOVE(1,"魅力榜"),
|
||||
INVITE(2,"邀请榜"),
|
||||
PAY(3,"土豪榜"),
|
||||
;
|
||||
private final Integer code;
|
||||
private final String text;
|
||||
|
||||
@@ -183,7 +183,7 @@ public class ConsumerManager {
|
||||
accountTotalManager.incsTrdPayIncomeCoin(resp.getUserId(), resp.getPrice());
|
||||
}
|
||||
}catch (Exception e){
|
||||
log.error("主播消费记录失败-充值",e);
|
||||
log.error("用户充值记录失败-充值",e);
|
||||
}
|
||||
try {
|
||||
Account account = accountService.getByUserId(resp.getUserId());
|
||||
|
||||
@@ -4,9 +4,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.cai.domain.Account;
|
||||
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
|
||||
import com.ruoyi.cai.dto.app.vo.rank.RankNodeRecharge;
|
||||
import com.ruoyi.cai.rank.RankNode;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户账户Mapper接口
|
||||
@@ -38,4 +41,6 @@ public interface AccountMapper extends BaseMapper<Account> {
|
||||
void incsPayTotal(@Param("userId") Long userId, @Param("rechargeCoin") Long rechargeCoin, @Param("price") BigDecimal price);
|
||||
|
||||
void incsTrdPayTotal(@Param("userId") Long userId, @Param("price") BigDecimal price);
|
||||
|
||||
List<RankNodeRecharge> rankTotalPay(@Param("limit") int limit);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.cai.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.cai.domain.LoveRankToday;
|
||||
import com.ruoyi.cai.dto.app.query.index.AnchorListQuery;
|
||||
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public interface LoveRankTodayMapper extends BaseMapper<LoveRankToday> {
|
||||
|
||||
void insRank(@Param("id") Long id, @Param("value") Long value);
|
||||
|
||||
Page<AnchorListVo> homePage(Page<Object> build, @Param("query") AnchorListQuery query, @Param("monday") LocalDate monday);
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.ruoyi.cai.mq.handle;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.cai.enums.rank.RankDataTypeEnum;
|
||||
import com.ruoyi.cai.enums.rank.RankTypeEnum;
|
||||
import com.ruoyi.cai.mq.CommonConsumerEnum;
|
||||
import com.ruoyi.cai.mq.handle.dto.RankNotifyDTO;
|
||||
import com.ruoyi.cai.rank.RankManager;
|
||||
import com.ruoyi.cai.service.LoveRankTodayService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,10 +17,15 @@ public class RankNotifyHandle implements IHandle {
|
||||
|
||||
@Autowired
|
||||
private RankManager rankManager;
|
||||
@Autowired
|
||||
private LoveRankTodayService loveRankTodayService;
|
||||
@Override
|
||||
public void run(String message) {
|
||||
RankNotifyDTO rank = JSON.parseObject(message, RankNotifyDTO.class);
|
||||
rankManager.addRank(rank);
|
||||
if(RankTypeEnum.LOVE.getCode().equals(rank.getRankType())){
|
||||
loveRankTodayService.addRank(rank);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,12 +14,14 @@ import com.ruoyi.cai.service.AccountService;
|
||||
import com.ruoyi.cai.service.UserService;
|
||||
import com.ruoyi.cai.util.CaiDateUtil;
|
||||
import com.ruoyi.cai.util.CaiNumUtil;
|
||||
import com.ruoyi.cai.ws.constant.RedisConstant;
|
||||
import com.ruoyi.yunxin.YunExecutor;
|
||||
import com.ruoyi.yunxin.Yunxin;
|
||||
import com.ruoyi.yunxin.resp.SendMsgResp;
|
||||
import com.ruoyi.yunxin.resp.YxCommonR;
|
||||
import com.ruoyi.yunxin.resp.YxDataR;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -43,6 +45,8 @@ public class YunxinHttpService {
|
||||
private CaiProperties caiProperties;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 注册赠送消息
|
||||
@@ -247,14 +251,34 @@ public class YunxinHttpService {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private boolean checkFollowedSendMessage(Long toUid,
|
||||
User followUser){
|
||||
String key = String.format(RedisConstant.START_SEND_MESSAGE_CACHE, toUid);
|
||||
Object o = redissonClient.getMap(key).get(followUser.getId());
|
||||
return o != null;
|
||||
}
|
||||
|
||||
private void setFollowedSendMessage(Long toUid,User followUser){
|
||||
String key = String.format(RedisConstant.START_SEND_MESSAGE_CACHE, toUid);
|
||||
redissonClient.getMap(key).put(followUser.getId(),1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关注发送消息
|
||||
* @param toUid
|
||||
* @param toUid 接收消息的用户
|
||||
*/
|
||||
public void followedSendMessage(Long toUid,
|
||||
User followUser,
|
||||
LocalDateTime followTime){
|
||||
YunExecutor.YUN_EXECUTOR.execute(() -> {
|
||||
// 检测是否发送过通知
|
||||
boolean checked = checkFollowedSendMessage(toUid, followUser);
|
||||
if(checked){
|
||||
log.error("用户已经发送过关注通知,无需再次发送 被关注人id:{}, 关注人id:{} 昵称:{} 编号:{}",
|
||||
toUid, followUser.getId(), followUser.getNickname(),followUser.getUsercode());
|
||||
return;
|
||||
}
|
||||
SendFollowNoticeData data = new SendFollowNoticeData();
|
||||
data.setUserid(followUser.getId());
|
||||
data.setNickname(followUser.getNickname());
|
||||
@@ -268,6 +292,7 @@ public class YunxinHttpService {
|
||||
if(r == null || !r.isSuccess()){
|
||||
log.error("云信发送失败【sendCallAsync】r={}", JSON.toJSONString(r));
|
||||
}
|
||||
this.setFollowedSendMessage(toUid, followUser);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ruoyi.cai.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.cai.domain.LoveRankToday;
|
||||
import com.ruoyi.cai.dto.app.query.index.AnchorListQuery;
|
||||
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
|
||||
import com.ruoyi.cai.mq.handle.dto.RankNotifyDTO;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LoveRankTodayService extends IService<LoveRankToday> {
|
||||
List<AnchorListVo> homePage(PageQuery pageQuery, AnchorListQuery query);
|
||||
|
||||
void addRank(RankNotifyDTO rank);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.ruoyi.cai.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.cai.domain.Anchor;
|
||||
import com.ruoyi.cai.domain.LoveRankToday;
|
||||
import com.ruoyi.cai.dto.app.query.index.AnchorListQuery;
|
||||
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
|
||||
import com.ruoyi.cai.enums.rank.RankDataTypeEnum;
|
||||
import com.ruoyi.cai.mapper.LoveRankTodayMapper;
|
||||
import com.ruoyi.cai.mq.handle.dto.RankNotifyDTO;
|
||||
import com.ruoyi.cai.service.AnchorService;
|
||||
import com.ruoyi.cai.service.LoveRankTodayService;
|
||||
import com.ruoyi.cai.util.IdLockManager;
|
||||
import com.ruoyi.common.core.domain.PageQuery;
|
||||
import com.ruoyi.common.helper.LoginHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Service
|
||||
public class LoveRankTodayServiceImpl extends ServiceImpl<LoveRankTodayMapper, LoveRankToday> implements LoveRankTodayService {
|
||||
|
||||
@Resource
|
||||
private LoveRankTodayMapper loveRankTodayMapper;
|
||||
@Autowired
|
||||
private AnchorService anchorService;
|
||||
|
||||
@Override
|
||||
public List<AnchorListVo> homePage(PageQuery pageQuery, AnchorListQuery query){
|
||||
if(pageQuery.checkPageNum(20)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
pageQuery.resetPageSize();
|
||||
Anchor anchor = anchorService.getByUserId(LoginHelper.getUserId());
|
||||
if(anchor != null && anchor.getHiddenStatus() == 1){
|
||||
query.setHiddenStatusUser(true);
|
||||
}
|
||||
// 获取当前日期
|
||||
LocalDate today = LocalDate.now();
|
||||
// 获取本周的周一(如果今天是周一,则返回今天)
|
||||
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
||||
Page<AnchorListVo> page = baseMapper.homePage(pageQuery.build(), query,monday);
|
||||
return page.getRecords();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRank(RankNotifyDTO rank) {
|
||||
// 获取当前日期
|
||||
LocalDate today = LocalDate.now();
|
||||
// 获取本周的周一(如果今天是周一,则返回今天)
|
||||
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
||||
// 获取本周的周日(如果今天是周日,则返回今天)
|
||||
LocalDate sunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
|
||||
LoveRankToday one = this.getOne(Wrappers.lambdaQuery(LoveRankToday.class)
|
||||
.eq(LoveRankToday::getUserId, rank.getUserId())
|
||||
.eq(LoveRankToday::getDataType, RankDataTypeEnum.WEEK.getCode())
|
||||
.eq(LoveRankToday::getBeginRankTime, monday)
|
||||
.last("limit 1"));
|
||||
if(one == null){
|
||||
AtomicReference<LoveRankToday> atomicReference = new AtomicReference<>();
|
||||
IdLockManager.executeWithLock(String.valueOf(rank.getUserId()), () -> {
|
||||
LoveRankToday rankData = this.getOne(Wrappers.lambdaQuery(LoveRankToday.class)
|
||||
.eq(LoveRankToday::getUserId, rank.getUserId())
|
||||
.eq(LoveRankToday::getDataType, RankDataTypeEnum.WEEK.getCode())
|
||||
.eq(LoveRankToday::getBeginRankTime, monday)
|
||||
.last("limit 1"));
|
||||
if(rankData == null){
|
||||
LoveRankToday saveData = new LoveRankToday();
|
||||
saveData.setDataType(RankDataTypeEnum.WEEK.getCode());
|
||||
saveData.setRankTime(monday);
|
||||
saveData.setBeginRankTime(monday);
|
||||
saveData.setEndRankTime(sunday);
|
||||
saveData.setNum(0L);
|
||||
saveData.setUserId(rank.getUserId());
|
||||
this.save(saveData);
|
||||
atomicReference.set(saveData);
|
||||
}
|
||||
});
|
||||
one = atomicReference.get();
|
||||
}
|
||||
loveRankTodayMapper.insRank(one.getId(), rank.getPrice());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.cai.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class IdLockManager {
|
||||
// 存储ID对应的锁对象
|
||||
private static final ConcurrentHashMap<String, Lock> idLocks = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 获取指定ID的锁
|
||||
*/
|
||||
public static Lock getLock(String id) {
|
||||
// 不存在则创建,存在则返回已有的锁
|
||||
return idLocks.computeIfAbsent(id, k -> new ReentrantLock());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行带ID锁的任务
|
||||
*/
|
||||
public static void executeWithLock(String id, Runnable task) {
|
||||
Lock lock = getLock(id);
|
||||
try {
|
||||
lock.lock(); // 获取锁
|
||||
task.run(); // 执行任务
|
||||
} finally {
|
||||
lock.unlock(); // 确保释放锁
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理不再使用的锁(可选)
|
||||
*/
|
||||
public static void cleanUpLock(String id) {
|
||||
idLocks.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,5 @@ public class RedisConstant {
|
||||
public static final String USER_ROOM_DATA = REDIS_P + "room:%s:%s";
|
||||
public static final String INIT_ROOM_LOCK = REDIS_P + "lock:initRoom:%s-%s";
|
||||
public static final String Y4X_REDIS_CACHE = REDIS_P + "shareUrl:y4x:%s";
|
||||
public static final String START_SEND_MESSAGE_CACHE = REDIS_P + "starSendMessage:%s";
|
||||
}
|
||||
|
||||
@@ -87,5 +87,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
order by t1.create_time desc
|
||||
</select>
|
||||
|
||||
|
||||
<select id="rankTotalPay" resultType="com.ruoyi.cai.dto.app.vo.rank.RankNodeRecharge">
|
||||
select
|
||||
t2.id as user_id,
|
||||
t2.avatar as avatar,
|
||||
t2.nickname as nickname,
|
||||
t1.total_buy_money as money
|
||||
from cai_account t1
|
||||
join cai_user t2 on t1.user_id = t2.id
|
||||
order by t1.total_buy_coin desc
|
||||
limit #{limit}
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="com.ruoyi.cai.mapper.LoveRankTodayMapper">
|
||||
|
||||
<delete id="insRank">
|
||||
update cai_love_rank_today
|
||||
set num = num + #{value}
|
||||
where id = #{id}
|
||||
</delete>
|
||||
|
||||
<select id="homePage" resultType="com.ruoyi.cai.dto.app.vo.AnchorListVo">
|
||||
select
|
||||
t1.id as user_id,t1.avatar,t1.gender,t1.nickname,t1.usercode,t2.service_time,
|
||||
t1.city_id,t1.city,t2.give_score,
|
||||
t2.price,t3.status as online
|
||||
from cai_love_rank_today w
|
||||
join cai_user t1 on t1.id = w.user_id
|
||||
join cai_anchor t2 on t2.user_id = w.user_id
|
||||
join cai_user_online t3 on t3.user_id = w.user_id
|
||||
where t1.status = 0 and t1.is_anchor = 1 and t2.index_display = 1 and t1.usercode > 100
|
||||
and w.rank_time = #{monday}
|
||||
and t3.status = 1
|
||||
and t2.open_video_status = 1
|
||||
<if test="!query.hiddenStatusUser">
|
||||
and t2.hidden_status = 0
|
||||
</if>
|
||||
<if test="query.price != null and query.price != 0">
|
||||
and t2.price = #{query.price}
|
||||
</if>
|
||||
order by w.num desc
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user