This commit is contained in:
张良(004796)
2024-03-28 18:20:50 +08:00
parent e955c21991
commit c25e43359c
14 changed files with 180 additions and 29 deletions

View File

@@ -18,7 +18,7 @@ public class Clear2HoursJob {
// 每隔小时执行一次 // 每隔小时执行一次
@Scheduled(cron = "0 0 0/2 * * ? *") @Scheduled(cron = "0 0 0/1 * * ?")
public void clearRun() { public void clearRun() {
try { try {
log.info("定时删除动态== 开始"); log.info("定时删除动态== 开始");

View File

@@ -32,6 +32,11 @@ public class HomeRecommendJob {
}catch (Exception e){ }catch (Exception e){
log.error("刷新首页推荐用户失败",e); log.error("刷新首页推荐用户失败",e);
} }
try {
homeManager.refreshHomeAnchorTopCache();
}catch (Exception e){
log.error("刷新首页推荐置顶用户失败",e);
}
} }

View File

@@ -1,4 +1,4 @@
package com.ruoyi.cai.controller; package com.ruoyi.web.controller.cai.admin;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -59,26 +59,21 @@ public class AnchorTopController extends BaseController {
return R.ok(anchorTopService.getById(id)); return R.ok(anchorTopService.getById(id));
} }
/** @GetMapping("/getAnchorTopByUserCode")
* 新增主播限时置顶 public R<AnchorTopAdminVo> getAnchorTopByUserCode(String usercode) {
*/ AnchorTopAdminVo anchorTop = anchorTopService.getAnchorTopByUserCode(usercode);
return R.ok(anchorTop);
}
@SaCheckPermission("cai:anchorTop:add") @SaCheckPermission("cai:anchorTop:add")
@Log(title = "主播限时置顶", businessType = BusinessType.INSERT) @Log(title = "主播限时置顶", businessType = BusinessType.INSERT)
@RepeatSubmit() @RepeatSubmit()
@PostMapping() @PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody AnchorTop bo) { public R<Void> add(@RequestBody AnchorTopAdminVo bo) {
return toAjax(anchorTopService.save(bo)); boolean save = anchorTopService.saveOrUpdateAnchorTop(bo);
} return R.ok();
/**
* 修改主播限时置顶
*/
@SaCheckPermission("cai:anchorTop:edit")
@Log(title = "主播限时置顶", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AnchorTop bo) {
return toAjax(anchorTopService.updateById(bo));
} }
/** /**

View File

@@ -17,6 +17,8 @@ public class RedisHttpConstant {
public static final String WITHDRAW_RANK_REDIS = REDIS_P + "withdrawRank:%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 RECHARGE_RANK_REDIS = REDIS_P + "rechargeRank:%s:%s";
public static final String ANCHOR_COUNT_REDIS = REDIS_P + "anchorCount:%s"; public static final String ANCHOR_COUNT_REDIS = REDIS_P + "anchorCount:%s";
public static final String HOME_RECOMMEND_TOP_REDIS = REDIS_P + "homeRecommendAnchorTop";
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

@@ -43,6 +43,5 @@ public class AnchorTop implements Serializable {
private Long sortBy; private Long sortBy;
private LocalDateTime createTime; private LocalDateTime createTime;
private LocalDateTime updateTime;
} }

View File

@@ -30,7 +30,9 @@ public class AnchorTopAdminVo extends AnchorTop {
* 性别 * 性别
*/ */
private Integer gender; private Integer gender;
private Integer age; private Long age;
private Integer status; private Integer status;
private Integer onlineStatus; private Integer onlineStatus;
// 1-生效 2-过期 3-待生效
private Integer topStatus;
} }

View File

@@ -3,6 +3,8 @@ package com.ruoyi.cai.dto.app.query.index;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.List;
@Data @Data
@Schema(description = "主播查询条件") @Schema(description = "主播查询条件")
public class AnchorListQuery { public class AnchorListQuery {
@@ -21,4 +23,6 @@ public class AnchorListQuery {
@Schema(hidden = true) @Schema(hidden = true)
private Integer onlineStatus; private Integer onlineStatus;
@Schema(hidden = true)
private List<Long> ignoreUserIds;
} }

View File

@@ -17,7 +17,7 @@ public class AnchorListVo {
private Integer online; private Integer online;
@Schema(description = "用户ID") @Schema(description = "用户ID")
private String userId; private Long userId;
/** /**
* 头像 * 头像
*/ */

View File

@@ -2,6 +2,7 @@ package com.ruoyi.cai.manager;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cai.constant.RedisHttpConstant; import com.ruoyi.cai.constant.RedisHttpConstant;
import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo;
import com.ruoyi.cai.dto.app.query.index.AnchorListQuery; import com.ruoyi.cai.dto.app.query.index.AnchorListQuery;
import com.ruoyi.cai.dto.app.vo.AnchorListVo; import com.ruoyi.cai.dto.app.vo.AnchorListVo;
import com.ruoyi.cai.dto.app.vo.setting.AppHomeConfig; import com.ruoyi.cai.dto.app.vo.setting.AppHomeConfig;
@@ -10,9 +11,11 @@ import com.ruoyi.cai.enums.home.AnchorListQueryTypeEnum;
import com.ruoyi.cai.mq.AmqpProducer; import com.ruoyi.cai.mq.AmqpProducer;
import com.ruoyi.cai.mq.handle.dto.LoginNotifyDTO; import com.ruoyi.cai.mq.handle.dto.LoginNotifyDTO;
import com.ruoyi.cai.service.AnchorService; import com.ruoyi.cai.service.AnchorService;
import com.ruoyi.cai.service.AnchorTopService;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RBucket; import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient; import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -21,6 +24,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* 首页主播随机推荐 * 首页主播随机推荐
@@ -31,8 +35,16 @@ public class HomeManager {
@Autowired @Autowired
private AnchorService anchorService; private AnchorService anchorService;
@Autowired @Autowired
private AnchorTopService anchorTopService;
@Autowired
private RedissonClient redissonClient; private RedissonClient redissonClient;
public void refreshHomeAnchorTopCache(){
List<AnchorListVo> anchorTop = anchorTopService.anchorTop(4);
RBucket<List<AnchorListVo>> bucket = redissonClient.getBucket(RedisHttpConstant.HOME_RECOMMEND_TOP_REDIS);
bucket.set(anchorTop);
}
public void refreshHomeRecommendCache(){ public void refreshHomeRecommendCache(){
PageQuery pageQuery = new PageQuery(); PageQuery pageQuery = new PageQuery();
pageQuery.setPageSize(200); pageQuery.setPageSize(200);
@@ -86,7 +98,7 @@ public class HomeManager {
}else if(anchorListQueryTypeEnum == AnchorListQueryTypeEnum.NEW){ }else if(anchorListQueryTypeEnum == AnchorListQueryTypeEnum.NEW){
RBucket<List<AnchorListVo>> bucket = redissonClient.getBucket(RedisHttpConstant.HOME_NEW_REDIS); RBucket<List<AnchorListVo>> bucket = redissonClient.getBucket(RedisHttpConstant.HOME_NEW_REDIS);
vos = bucket.get(); vos = bucket.get();
} else { } else { // 同城查询
if(query.getCityId() == null){ if(query.getCityId() == null){
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -95,11 +107,22 @@ public class HomeManager {
Collections.shuffle(vos); Collections.shuffle(vos);
Integer pageNum = pageQuery.getPageNum(); Integer pageNum = pageQuery.getPageNum();
int startIndex = (pageNum - 1) * pageQuery.getPageSize(); int startIndex = (pageNum - 1) * pageQuery.getPageSize();
if(startIndex > vos.size()){ if(startIndex > vos.size()){ // 超出范围
return Collections.emptyList(); return Collections.emptyList();
} }
int endIndex = Math.min(startIndex+pageQuery.getPageSize(), vos.size()); int endIndex = Math.min(startIndex+pageQuery.getPageSize(), vos.size());
return vos.subList(startIndex, endIndex); List<AnchorListVo> result = vos.subList(startIndex, endIndex);
if(anchorListQueryTypeEnum == AnchorListQueryTypeEnum.DEFAULT && pageNum == 1){
List<AnchorListVo> list = getAnchorTopList();
result.addAll(0, list);
}
return result;
}
public List<AnchorListVo> getAnchorTopList(){
RBucket<List<AnchorListVo>> bucketTop = redissonClient.getBucket(RedisHttpConstant.HOME_RECOMMEND_TOP_REDIS);
List<AnchorListVo> anchorListVos = bucketTop.get();
return anchorListVos == null ? Collections.emptyList() : anchorListVos;
} }
public List<AnchorListVo> recommendFollows(Integer limit) { public List<AnchorListVo> recommendFollows(Integer limit) {

View File

@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cai.domain.AnchorTop; import com.ruoyi.cai.domain.AnchorTop;
import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo; import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo;
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* 主播限时置顶Mapper接口 * 主播限时置顶Mapper接口
* *
@@ -15,4 +18,6 @@ import org.apache.ibatis.annotations.Param;
public interface AnchorTopMapper extends BaseMapper<AnchorTop> { public interface AnchorTopMapper extends BaseMapper<AnchorTop> {
Page<AnchorTopAdminVo> pageAdmin(@Param("build") Page<Object> build, @Param("bo") AnchorTopAdminVo bo); Page<AnchorTopAdminVo> pageAdmin(@Param("build") Page<Object> build, @Param("bo") AnchorTopAdminVo bo);
List<AnchorListVo> anchorTop(@Param("limit") int limit);
} }

View File

@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cai.domain.AnchorTop; import com.ruoyi.cai.domain.AnchorTop;
import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo; import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo;
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import java.util.List;
/** /**
* 主播限时置顶Service接口 * 主播限时置顶Service接口
* *
@@ -15,4 +18,10 @@ import com.ruoyi.common.core.domain.PageQuery;
public interface AnchorTopService extends IService<AnchorTop> { public interface AnchorTopService extends IService<AnchorTop> {
Page<AnchorTopAdminVo> pageAdmin(PageQuery pageQuery, AnchorTopAdminVo bo); Page<AnchorTopAdminVo> pageAdmin(PageQuery pageQuery, AnchorTopAdminVo bo);
boolean saveOrUpdateAnchorTop(AnchorTopAdminVo bo);
AnchorTopAdminVo getAnchorTopByUserCode(String usercode);
List<AnchorListVo> anchorTop(int limit);
} }

View File

@@ -1,13 +1,22 @@
package com.ruoyi.cai.service.impl; 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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.AnchorTop; import com.ruoyi.cai.domain.AnchorTop;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo; import com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo;
import com.ruoyi.cai.dto.app.vo.AnchorListVo;
import com.ruoyi.cai.mapper.AnchorTopMapper; import com.ruoyi.cai.mapper.AnchorTopMapper;
import com.ruoyi.cai.service.AnchorTopService; import com.ruoyi.cai.service.AnchorTopService;
import com.ruoyi.cai.service.UserService;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/** /**
* 主播限时置顶Service业务层处理 * 主播限时置顶Service业务层处理
@@ -18,8 +27,68 @@ import org.springframework.stereotype.Service;
@Service @Service
public class AnchorTopServiceImpl extends ServiceImpl<AnchorTopMapper,AnchorTop> implements AnchorTopService { public class AnchorTopServiceImpl extends ServiceImpl<AnchorTopMapper,AnchorTop> implements AnchorTopService {
@Autowired
private UserService userService;
@Override @Override
public Page<AnchorTopAdminVo> pageAdmin(PageQuery pageQuery, AnchorTopAdminVo bo) { public Page<AnchorTopAdminVo> pageAdmin(PageQuery pageQuery, AnchorTopAdminVo bo) {
return baseMapper.pageAdmin(pageQuery.build(), bo); return baseMapper.pageAdmin(pageQuery.build(), bo);
} }
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveOrUpdateAnchorTop(AnchorTopAdminVo bo) {
if(bo.getBeginTime() == null || bo.getEndTime() == null){
throw new ServiceException("请填写开始时间和结束时间");
}
if(bo.getBeginTime().isAfter(bo.getEndTime())){
throw new ServiceException("开始时间不能大于结束时间");
}
User user = userService.getByUserCode(bo.getUsercode());
if(user == null || user.getIsAnchor() != 1){
throw new ServiceException("用户不存在或不是主播");
}
if(bo.getSortBy() == null){
bo.setSortBy(0L);
}
AnchorTop one = this.getOne(Wrappers.lambdaQuery(AnchorTop.class).eq(AnchorTop::getUserId, user.getId()).last("limit 1"));
AnchorTop anchorTop = new AnchorTop();
if(one != null){
anchorTop.setId(one.getId());
}
anchorTop.setUserId(user.getId());
anchorTop.setBeginTime(bo.getBeginTime());
anchorTop.setEndTime(bo.getEndTime());
anchorTop.setSortBy(bo.getSortBy());
return this.saveOrUpdate(anchorTop);
}
@Override
public AnchorTopAdminVo getAnchorTopByUserCode(String usercode) {
User user = userService.getByUserCode(usercode);
if(user == null){
return null;
}
AnchorTop one = this.getOne(Wrappers.lambdaQuery(AnchorTop.class).eq(AnchorTop::getUserId, user.getId()).last("limit 1"));
if(one != null){
AnchorTopAdminVo vo = new AnchorTopAdminVo();
vo.setId(one.getId());
vo.setUsercode(user.getUsercode());
vo.setNickname(user.getNickname());
vo.setMobile(user.getMobile());
vo.setAge(user.getAge());
vo.setGender(user.getGender());
vo.setUserId(one.getUserId());
vo.setBeginTime(one.getBeginTime());
vo.setEndTime(one.getEndTime());
vo.setSortBy(one.getSortBy());
return vo;
}
return null;
}
@Override
public List<AnchorListVo> anchorTop(int limit) {
return baseMapper.anchorTop(limit);
}
} }

View File

@@ -50,7 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if> </if>
<if test="query.type != null"> <if test="query.type != null">
<if test="query.type == 0"> <if test="query.type == 0">
order by t2.recommend_status desc order by t2.recommend_status desc,t2.update_time desc
</if> </if>
<if test="query.type == 1"> <if test="query.type == 1">
order by t3.last_live_time desc,t2.recommend_status desc order by t3.last_live_time desc,t2.recommend_status desc
@@ -59,7 +59,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by t1.create_time desc, t2.recommend_status desc order by t1.create_time desc, t2.recommend_status desc
</if> </if>
</if> </if>
order by t2.update_time desc
</select> </select>

View File

@@ -3,11 +3,16 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.cai.mapper.AnchorTopMapper"> <mapper namespace="com.ruoyi.cai.mapper.AnchorTopMapper">
<!--// 1-生效 2-过期 3-待生效-->
<select id="pageAdmin" resultType="com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo"> <select id="pageAdmin" resultType="com.ruoyi.cai.dto.admin.vo.AnchorTopAdminVo">
select t1.*, select t1.*,
t3.usercode,t3.nickname,t3.mobile,t3.avatar,t3.gender,t3.age,t3.status, t3.usercode,t3.nickname,t3.mobile,t3.avatar,t3.gender,t3.age,t3.status,
t4.status as online_status t4.status as online_status,
<![CDATA[
case when t1.begin_time > now() then 3
when t1.end_time < now() then 2
else 1 end as top_status
]]>
from cai_anchor_top t1 from cai_anchor_top t1
left join cai_anchor t2 on t1.user_id = t2.user_id left join cai_anchor t2 on t1.user_id = t2.user_id
left join cai_user t3 on t1.user_id = t3.id left join cai_user t3 on t1.user_id = t3.id
@@ -25,9 +30,43 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="bo.onlineStatus != null"> <if test="bo.onlineStatus != null">
and t4.status = #{bo.onlineStatus} and t4.status = #{bo.onlineStatus}
</if> </if>
<if test="bo.topStatus != null">
<if test="bo.topStatus == 1">
<![CDATA[
and t1.begin_time <= now() and t1.end_time >= now()
]]>
</if>
<if test="bo.topStatus == 2">
<![CDATA[
and t1.end_time < now()
]]>
</if>
<if test="bo.topStatus == 3">
<![CDATA[
and t1.begin_time > now()
]]>
</if>
</if>
</where> </where>
order by t1.sort_by desc order by t1.sort_by desc
</select> </select>
<select id="anchorTop" resultType="com.ruoyi.cai.dto.app.vo.AnchorListVo">
select
t1.id as user_id,t1.avatar,t1.gender,t1.city,t1.nickname,t1.usercode,
t1.city_id,t1.city,
t2.give_score,t2.price,t3.status as online
from cai_user t1
join cai_anchor t2 on t1.id = t2.user_id
join cai_user_online t3 on t1.id = t3.user_id
join cai_anchor_top t4 on t1.id = t4.user_id
where t1.status = 0 and t1.is_anchor = 1 and t2.index_display = 1 and t1.usercode > 100
and t3.status = 1
<![CDATA[
and t4.begin_time <= now() and t4.end_time >= now()
]]>
order by t4.sort_by desc
limit #{limit}
</select>
</mapper> </mapper>