Kaynağa Gözat

feat(business): 添加用户排名及申诉相关功能

- 新增用户排名查询接口和相关数据结构- 实现用户申诉状态检查和处理
- 优化奖励发放流程,增加申诉状态判断
- 添加 Redis 工具类和相关键名常量
fugui001 4 ay önce
ebeveyn
işleme
e16bc6278a
15 değiştirilmiş dosya ile 521 ekleme ve 23 silme
  1. 17 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/UserComplaintsController.java
  2. 2 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/RewardStatusEnum.java
  3. 27 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/PlayerVo.java
  4. 6 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/TournamentsVo.java
  5. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/UserComplaintsMapper.java
  6. 11 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IUserComplaintsService.java
  7. 11 2
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/RewardClaimsServiceImpl.java
  8. 9 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsServiceImpl.java
  9. 17 6
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsTemplateServiceImpl.java
  10. 129 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/UserComplaintsServiceImpl.java
  11. 4 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/UserServiceImpl.java
  12. 18 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/RedisKeys.java
  13. 242 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/RedisUtil.java
  14. 0 8
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/RewardClaimsMapper.xml
  15. 24 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/UserComplaintsMapper.xml

+ 17 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/controller/UserComplaintsController.java

@@ -7,6 +7,7 @@ import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import org.dromara.business.domain.bo.UserComplaintsBo;
+import org.dromara.business.domain.vo.PlayerVo;
 import org.dromara.business.domain.vo.UserComplaintsVo;
 import org.dromara.business.service.IUserComplaintsService;
 import org.springframework.web.bind.annotation.*;
@@ -102,4 +103,20 @@ public class UserComplaintsController extends BaseController {
                           @PathVariable Long[] ids) {
         return toAjax(userComplaintsService.deleteWithValidByIds(List.of(ids), true));
     }
+
+
+
+    /**
+     * 获取所有用户排名
+     *
+     * @param
+     */
+    @SaCheckPermission("business:complaints:getAllUserRankByTournamentId")
+    @GetMapping("/getAllUserRankByTournamentId")
+    public TableDataInfo<PlayerVo> getAllUserRankByTournamentId(UserComplaintsBo bo, PageQuery pageQuery) {
+        return userComplaintsService.getAllUserRankByTournamentId(bo, pageQuery);
+    }
+
+
+
 }

+ 2 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/enums/RewardStatusEnum.java

@@ -4,7 +4,8 @@ public enum RewardStatusEnum {
 
     NO_RECEIVE("0", "未领取"),
     RECEIVED("1", "已领取"),
-    SUBMIT_AUDIT("2", "已提交待审核");
+    SUBMIT_AUDIT("2", "已提交待审核"),
+    COMPLAINTS("3", "申诉");
 
     private final String code;
     private final String description;

+ 27 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/PlayerVo.java

@@ -0,0 +1,27 @@
+package org.dromara.business.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class PlayerVo {
+
+    private Long id;
+    private String name;
+    private Long chips;
+    private Long rank;
+
+    private String phone;
+
+    private String playerName;
+
+    private Long claimed;
+
+    private String claimedText;
+
+    private Long tournamentId;
+
+    List<RewardVo> rewardVoList;
+
+}

+ 6 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/TournamentsVo.java

@@ -194,4 +194,10 @@ public class TournamentsVo implements Serializable {
      */
     private int robotCount;
 
+    /**
+     * 是否申诉
+     */
+    private Boolean isComplaints;
+
+
 }

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/mapper/UserComplaintsMapper.java

@@ -40,4 +40,8 @@ public interface UserComplaintsMapper extends BaseMapperPlus<UserComplaints, Use
     @InterceptorIgnore(tenantLine = "true")
     int deleteUserComplaintsById(@Param("ids") Collection<Long> ids);
 
+    @InterceptorIgnore(tenantLine = "true")
+    UserComplaintsVo selectUserComplaintsPageByTournamentId(Long tournamentId,Long userId);
+
+
 }

+ 11 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/IUserComplaintsService.java

@@ -1,6 +1,7 @@
 package org.dromara.business.service;
 
 import org.dromara.business.domain.bo.UserComplaintsBo;
+import org.dromara.business.domain.vo.PlayerVo;
 import org.dromara.business.domain.vo.UserComplaintsVo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -65,4 +66,14 @@ public interface IUserComplaintsService {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 获取 tournamentId 下所有用户排名
+     * @param tournamentId
+     */
+    TableDataInfo<PlayerVo> getAllUserRankByTournamentId(UserComplaintsBo bo, PageQuery pageQuery);
+
+
+
+
 }

+ 11 - 2
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/RewardClaimsServiceImpl.java

@@ -62,6 +62,9 @@ public class RewardClaimsServiceImpl implements IRewardClaimsService {
 
     private final MessageReceiversMapper messageReceiversMapper;
 
+    private final UserComplaintsMapper userComplaintsMapper;
+
+
     /**
      * 查询用户参赛
      *
@@ -117,7 +120,7 @@ public class RewardClaimsServiceImpl implements IRewardClaimsService {
     private LambdaQueryWrapper<RewardClaims> buildQueryWrapper(RewardClaimsBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<RewardClaims> lqw = Wrappers.lambdaQuery();
-        lqw.orderByDesc(RewardClaims::getRank);
+        lqw.orderByAsc(RewardClaims::getRank);
         lqw.eq(bo.getTournamentId() != null, RewardClaims::getTournamentId, bo.getTournamentId());
         lqw.eq(bo.getPlayerId() != null, RewardClaims::getPlayerId, bo.getPlayerId());
         lqw.eq(bo.getRank() != null, RewardClaims::getRank, bo.getRank());
@@ -264,6 +267,11 @@ public class RewardClaimsServiceImpl implements IRewardClaimsService {
     @Override
     public Boolean auditSendReward(RewardClaimsBo bo) {
         try {
+            //是否有投诉
+            UserComplaintsVo complaintsVo = userComplaintsMapper.selectUserComplaintsPageByTournamentId(bo.getTournamentId(), null);
+            if(complaintsVo!=null){
+                throw new RuntimeException("本场比赛仍有选手存在异议,请处理申述后继续授作!");
+            }
             // 1. 校验领取状态,防止重复领取
             RewardClaimsVo rewardClaimsVo = baseMapper.selectInfoById(bo.getId());
             // 是否已领取奖励  0未领取  1已领取 2 已提交待审核
@@ -379,7 +387,8 @@ public class RewardClaimsServiceImpl implements IRewardClaimsService {
 
         } catch (Exception e) {
             log.error("审核并发放奖励过程中发生异常,rewardId={}", bo.getId(), e);
-            throw new RuntimeException("审核并发放奖励过程中发生异常", e);
+            //throw new RuntimeException("审核并发放奖励过程中发生异常", e);
         }
+        return Boolean.FALSE;
     }
 }

+ 9 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsServiceImpl.java

@@ -65,6 +65,8 @@ public class TournamentsServiceImpl implements ITournamentsService {
 
     private final ParticipantsMapper participantsMapper;
 
+    private final UserComplaintsMapper userComplaintsMapper;
+
     /**
      * 查询【请填写功能名称】
      *
@@ -119,6 +121,13 @@ public class TournamentsServiceImpl implements ITournamentsService {
         }
         int totalSignNum = participantsMapper.selectParticipantsTotal(tournamentId);
         tournamentsVo.setSignNum(totalSignNum);
+        //是否有投诉
+        UserComplaintsVo complaintsVo = userComplaintsMapper.selectUserComplaintsPageByTournamentId(tournamentId, null);
+        if(complaintsVo!=null){
+            tournamentsVo.setIsComplaints(true);
+        }else{
+            tournamentsVo.setIsComplaints(false);
+        }
         return tournamentsVo;
     }
 

+ 17 - 6
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsTemplateServiceImpl.java

@@ -64,6 +64,8 @@ public class TournamentsTemplateServiceImpl implements ITournamentsTemplateServi
 
     private final ScheduleConfigMapper scheduleConfigMapper;
 
+    private final UserComplaintsMapper userComplaintsMapper;
+
     /**
      * 查询【请填写功能名称】
      *
@@ -121,6 +123,13 @@ public class TournamentsTemplateServiceImpl implements ITournamentsTemplateServi
         }
         int totalSignNum = participantsMapper.selectParticipantsTotal(tournamentId);
         tournamentsVo.setSignNum(totalSignNum);
+        //是否有投诉
+        UserComplaintsVo complaintsVo = userComplaintsMapper.selectUserComplaintsPageByTournamentId(tournamentId, null);
+        if(complaintsVo!=null){
+            tournamentsVo.setIsComplaints(true);
+        }else{
+            tournamentsVo.setIsComplaints(false);
+        }
         return tournamentsVo;
     }
 
@@ -176,12 +185,14 @@ public class TournamentsTemplateServiceImpl implements ITournamentsTemplateServi
                     //奖品
                     PrizeDistributionItemsVo prizeDistributionItemsVos = prizeDistributionItemsMapper.selectByPrizeDistributionIdTemplate(id2);
                     ItemsPrizeDto itemsPrizeBo = new ItemsPrizeDto();
-                    itemsPrizeBo.setRanking(Long.valueOf(i));
-                    itemsPrizeBo.setItemId(prizeDistributionItemsVos.getItemId());
-                    itemsPrizeBo.setQuantity(prizeDistributionItemsVos.getQuantity());
-                    itemsPrizeBo.setItemsName(prizeDistributionItemsVos.getItemsName());
-                    itemsPrizeList.add(itemsPrizeBo);
-                }
+                    if(prizeDistributionItemsVos!=null){
+                        itemsPrizeBo.setRanking(Long.valueOf(i));
+                        itemsPrizeBo.setItemId(prizeDistributionItemsVos.getItemId());
+                        itemsPrizeBo.setQuantity(prizeDistributionItemsVos.getQuantity());
+                        itemsPrizeBo.setItemsName(prizeDistributionItemsVos.getItemsName());
+                        itemsPrizeList.add(itemsPrizeBo);
+                    }
+                 }
                 record.setItemsPrizeList(itemsPrizeList);
             }
 

+ 129 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/UserComplaintsServiceImpl.java

@@ -2,12 +2,24 @@ package org.dromara.business.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.dromara.business.domain.UserComplaints;
+import org.dromara.business.domain.bo.ItemsBo;
+import org.dromara.business.domain.bo.UserBo;
 import org.dromara.business.domain.bo.UserComplaintsBo;
 import org.dromara.business.domain.enums.ComplaintsStatus;
-import org.dromara.business.domain.vo.UserComplaintsVo;
+import org.dromara.business.domain.enums.RewardStatusEnum;
+import org.dromara.business.domain.vo.*;
+import org.dromara.business.mapper.RewardClaimsMapper;
 import org.dromara.business.mapper.UserComplaintsMapper;
+import org.dromara.business.service.IItemsService;
 import org.dromara.business.service.IUserComplaintsService;
+import org.dromara.business.service.IUserService;
+import org.dromara.business.utils.PageUtils;
+import org.dromara.business.utils.RedisKeys;
+import org.dromara.business.utils.RedisUtil;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -16,11 +28,12 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.satoken.utils.LoginHelper;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-
-
 import java.util.List;
 import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 用户申诉Service业务层处理
@@ -35,6 +48,17 @@ public class UserComplaintsServiceImpl implements IUserComplaintsService {
 
     private final UserComplaintsMapper baseMapper;
 
+    @Autowired
+    RedisUtil redisUtil;
+
+    @Autowired
+    IUserService iUserService;
+
+    @Autowired
+    RewardClaimsMapper rewardClaimsMapper;
+
+    private final IItemsService itemsService;
+
     /**
      * 查询用户申诉
      *
@@ -189,4 +213,106 @@ public class UserComplaintsServiceImpl implements IUserComplaintsService {
         }
         return baseMapper.deleteUserComplaintsById(ids) > 0;
     }
+
+
+    @Override
+    public TableDataInfo<PlayerVo> getAllUserRankByTournamentId(UserComplaintsBo bo, PageQuery pageQuery) {
+        Long tournamentId=bo.getTournamentId();
+        String leaderboardJson = redisUtil.get(RedisKeys.tournamentLeaderboard(tournamentId));
+        ObjectMapper objectMapper = new ObjectMapper();
+        if(StringUtils.isEmpty(leaderboardJson)){
+            return TableDataInfo.build();
+        }
+        List<PlayerVo> players = null;
+        try {
+            players = objectMapper.readValue(leaderboardJson,
+                objectMapper.getTypeFactory().constructCollectionType(List.class, PlayerVo.class));
+
+            // 查询所有用户
+            List<UserVo> userVoList = iUserService.queryList(new UserBo());
+
+            List<RewardClaimsVo> rewardClaimsVosList = rewardClaimsMapper.selectByCriteria(tournamentId);
+
+            // 构建 id -> UserVo 的映射表(提升性能:O(1) 查找)
+            Map<Long, UserVo> userMap = userVoList.stream()
+                .collect(Collectors.toMap(UserVo::getId, user -> user)); // 假设 UserVo 的 ID 是 getUserId()
+
+            //获奖信息
+            Map<Long, RewardClaimsVo> RewardClaimsMap = rewardClaimsVosList.stream()
+                .collect(Collectors.toMap(RewardClaimsVo::getPlayerId, r -> r)); // 假设 UserVo 的 ID 是 getUserId()
+
+            //奖品的基本信息
+            List<ItemsVo> itemsVoList = itemsService.queryList(new ItemsBo());
+
+            //奖品的基本信息
+            Map<Long, ItemsVo> itemsVoMap = itemsVoList.stream()
+                .collect(Collectors.toMap(ItemsVo::getId, r -> r)); // 假设 UserVo 的 ID 是 getUserId()
+
+
+
+            // 为每个 PlayerVo 补充用户信息
+            for (PlayerVo player : players) {
+                player.setTournamentId(tournamentId);
+                UserVo userVo = userMap.get(player.getId()); // 假设 PlayerVo 的 id 是用户ID
+                if (userVo != null) {
+                    player.setPlayerName(userVo.getNickName());        // 设置用户名
+                    player.setPhone(userVo.getPhone());  // 设置手机号
+                    // 其他字段也可以继续设置
+                }
+                RewardClaimsVo rewardClaimsVo = RewardClaimsMap.get(player.getId());
+                if(rewardClaimsVo!=null){
+                    player.setClaimed(rewardClaimsVo.getClaimed());
+                    player.setClaimedText(RewardStatusEnum.getDescriptionByCode(String.valueOf(rewardClaimsVo.getClaimed())));
+                    //todo 奖励奖品信息
+                    String rewardJson = rewardClaimsVo.getRewardJson();
+                    if(StringUtils.isNotBlank(rewardJson)){
+                        ObjectMapper mapper = new ObjectMapper();
+                        List<RewardVo> items = mapper.readValue(rewardJson, new TypeReference<List<RewardVo>>() {});
+                        for (RewardVo item : items) {
+                            ItemsVo itemsVo1 = itemsVoMap.get(item.getItemId());
+                            if(itemsVo1!=null){
+                                item.setItemName(itemsVo1.getName());
+                            }
+                         }
+                        player.setRewardVoList(items);
+                    }
+                }else{
+                   // 判断有没有申诉的
+                    UserComplaintsVo complaintsVo = baseMapper.selectUserComplaintsPageByTournamentId(tournamentId,player.getId());
+                    if(complaintsVo!=null){
+                        player.setClaimed(Long.valueOf(RewardStatusEnum.COMPLAINTS.getCode()));
+                        player.setClaimedText(RewardStatusEnum.COMPLAINTS.getDescription());
+                    }
+               }
+            }
+
+            // 打印结果
+            for (PlayerVo player : players) {
+                System.out.println("ID: " + player.getId());
+                System.out.println("Name: " + player.getName());
+                System.out.println("Username: " + player.getPlayerName());
+                System.out.println("Phonenumber: " + player.getPhone());
+                System.out.println("Chips: " + player.getChips());
+                System.out.println("Rank: " + player.getRank());
+                System.out.println("--------------------");
+            }
+
+            // 调用分页方法
+            TableDataInfo<PlayerVo> pageInfo = PageUtils.toTablePage(players, pageQuery.getPageNum(), pageQuery.getPageSize());
+
+           return pageInfo;
+
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+            throw new RuntimeException("解析 Redis 数据失败", e);
+        }
+   }
+
+    public static void main(String[] args) {
+        System.out.println(RedisKeys.tournamentLeaderboard(1L));
+    }
+
+
+
+
 }

+ 4 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/UserServiceImpl.java

@@ -13,6 +13,7 @@ import org.dromara.business.domain.vo.UserVo;
 import org.dromara.business.mapper.*;
 import org.dromara.business.service.IUserService;
 import org.dromara.business.utils.ItemOperationLock;
+import org.dromara.business.utils.RedisUtil;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -20,7 +21,6 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.dromara.common.redis.utils.RedisUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -51,7 +51,8 @@ public class UserServiceImpl implements IUserService {
 
     private final PlayersItemsLogMapper playersItemsLogMapper;
 
-
+    @Autowired
+    RedisUtil redisUtil;
 
 
     /**
@@ -325,7 +326,7 @@ public class UserServiceImpl implements IUserService {
                 if (updateCount <= 0) {
                     throw new RuntimeException("道具发放失败");
                 }
-                RedisUtils.publish("channel:item_updates", bo.getUserId());
+                redisUtil.publish("channel:item_updates", bo.getUserId());
                 return Boolean.TRUE;
 
             } finally {

+ 18 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/RedisKeys.java

@@ -0,0 +1,18 @@
+package org.dromara.business.utils;
+
+public class RedisKeys {
+
+    // 定义 key 模板
+    private static final String TOURNAMENT_LEADERBOARD = "game:poker:tournament:%d:leaderboard";
+
+    /**
+     * 生成排行榜 key
+     * @param tournamentId 比赛 ID
+     * @return Redis key
+     */
+    public static String tournamentLeaderboard(Long tournamentId) {
+        return String.format(TOURNAMENT_LEADERBOARD, tournamentId);
+    }
+
+
+}

+ 242 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/RedisUtil.java

@@ -0,0 +1,242 @@
+package org.dromara.business.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisUtil {
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 设置缓存值 + 过期时间(分钟)
+     */
+    public boolean set(String key, Object value, long time) {
+        try {
+            if (time > 0) {
+                if (value instanceof String) {
+                    redisTemplate.opsForValue().set(key, (String) value, time, TimeUnit.SECONDS);
+                } else {
+                    String jsonValue = objectMapper.writeValueAsString(value);
+                    redisTemplate.opsForValue().set(key, jsonValue, time, TimeUnit.SECONDS);
+                }
+            } else {
+                set(key, value);
+            }
+            return true;
+        } catch (JsonProcessingException e) {
+            return false;
+        }
+    }
+
+    /**
+     * 设置缓存值(无过期时间)
+     */
+    public boolean set(String key, Object value) {
+        try {
+            String jsonValue = objectMapper.writeValueAsString(value);
+            redisTemplate.opsForValue().set(key, jsonValue);
+            return true;
+        } catch (JsonProcessingException e) {
+            return false;
+        }
+    }
+
+    /**
+     * 获取缓存值(字符串或对象)
+     */
+    public <T> T get(String key, Class<T> clazz) {
+        String value = redisTemplate.opsForValue().get(key);
+        if (value == null) {
+            return null;
+        }
+        try {
+            return objectMapper.readValue(value, clazz);
+        } catch (JsonProcessingException e) {
+            return null;
+        }
+    }
+
+    /**
+     * 获取缓存值(字符串)
+     */
+    public String get(String key) {
+        String value = redisTemplate.opsForValue().get(key);
+        if (value != null && value.startsWith("\"") && value.endsWith("\"")) {
+            return value.substring(1, value.length() - 1);
+        }
+        return value;
+    }
+
+    /**
+     * 删除单个 key
+     */
+    public void delete(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 判断 key 是否存在
+     */
+    public boolean hasKey(String key) {
+        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
+    }
+
+    /**
+     * 指定缓存失效时间
+     */
+    public boolean expire(String key, long time) {
+        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 增加数值(原子操作)
+     *
+     * @param key 键
+     * @param delta 增加的数量
+     * @return 增加后的值(Long),失败返回 null
+     */
+    public Long increment(String key, long delta) {
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 减少数值(原子操作)
+     *
+     * @param key 键
+     * @param delta 减少的数量
+     * @return 减少后的值(Long),失败返回 null
+     */
+    public Long decrement(String key, long delta) {
+        return redisTemplate.opsForValue().decrement(key, delta);
+    }
+
+    // 下面是针对不同类型的操作
+
+    /**
+     * Hash 类型操作 - 存储对象
+     */
+    public <HK, HV> void hSetAll(String key, Map<HK, HV> map) throws JsonProcessingException {
+        for (Map.Entry<HK, HV> entry : map.entrySet()) {
+            redisTemplate.opsForHash().put(key, objectMapper.writeValueAsString(entry.getKey()), objectMapper.writeValueAsString(entry.getValue()));
+        }
+    }
+
+    /**
+     * Hash 类型操作 - 获取所有键值对
+     */
+    public <HK, HV> Map<HK, HV> hGetAll(String key, Class<HK> hkClass, Class<HV> hvClass) throws JsonProcessingException {
+        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
+        Map<HK, HV> resultMap = new HashMap<>();
+        for (Map.Entry<Object, Object> entry : entries.entrySet()) {
+            HK hk = objectMapper.readValue((String) entry.getKey(), hkClass);
+            HV hv = objectMapper.readValue((String) entry.getValue(), hvClass);
+            resultMap.put(hk, hv);
+        }
+        return resultMap;
+    }
+
+    /**
+     * List 类型操作 - 在右边添加元素
+     */
+    public void rPush(String key, Object... values) throws JsonProcessingException {
+        for (Object value : values) {
+            redisTemplate.opsForList().rightPush(key, objectMapper.writeValueAsString(value));
+        }
+    }
+
+    /**
+     * List 类型操作 - 获取所有元素
+     */
+    public <T> List<T> lRange(String key, Class<T> clazz) throws JsonProcessingException {
+        List<String> range = redisTemplate.opsForList().range(key, 0, -1);
+        return range.stream()
+                .map(s -> {
+                    try {
+                        return objectMapper.readValue(s, clazz);
+                    } catch (JsonProcessingException e) {
+                        return null;
+                    }
+                })
+                .toList();
+    }
+
+    /**
+     * 安全获取 Long 类型的值,如果为空或不是 Long 类型则返回默认值
+     */
+    public Long getLongValue(String key, Long defaultValue) {
+        String value = get(key);
+        if (value != null && !value.isEmpty()) {
+            try {
+                return Long.parseLong(value);
+            } catch (NumberFormatException e) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    public Long getLongValue(String key) {
+        String value = get(key);
+        if (value != null && !value.isEmpty()) {
+            try {
+                return Long.parseLong(value);
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+        return null;
+    }
+
+    public <T> T getObject(String key, Class<T> clazz) {
+        String json = redisTemplate.opsForValue().get(key);
+        if (json == null) {
+            return null;
+        }
+
+        try {
+            return objectMapper.readValue(json, clazz);
+        } catch (Exception e) {
+            throw new RuntimeException("Redis 反序列化失败: " + key, e);
+        }
+    }
+
+
+    public void setObject(String key, Object value, long expireSeconds) {
+        try {
+            String json = objectMapper.writeValueAsString(value);
+            redisTemplate.opsForValue().set(key, json, expireSeconds, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            throw new RuntimeException("Redis 序列化失败", e);
+        }
+    }
+
+
+    /**
+     * 发布消息到指定频道(支持对象自动序列化为 JSON)
+     *
+     * @param channel 频道名
+     * @param message 消息内容(支持 POJO)
+     * @return 发送的消息数量(成功一般 >= 1)
+     */
+    public Long publish(String channel, Object message) {
+        try {
+            String msg = (message instanceof String) ? (String) message : objectMapper.writeValueAsString(message);
+            return redisTemplate.convertAndSend(channel, msg);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("消息序列化失败: " + channel, e);
+        }
+    }
+
+}

+ 0 - 8
ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/RewardClaimsMapper.xml

@@ -89,15 +89,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         SELECT *
         FROM reward_claims
         <where>
-            <if test="id != null">AND id = #{id}</if>
             <if test="tournamentId != null">AND tournament_id = #{tournamentId}</if>
-            <if test="playerId != null">AND player_id = #{playerId}</if>
-            <if test="rank != null">AND rank = #{rank}</if>
-            <if test="playerName != null and playerName != ''">
-                AND player_name LIKE CONCAT('%', #{playerName}, '%')
-            </if>
-            <if test="phone != null and phone != ''">AND phone = #{phone}</if>
-            <if test="claimed != null">AND claimed = #{claimed}</if>
         </where>
     </select>
 

+ 24 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/business/UserComplaintsMapper.xml

@@ -139,4 +139,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </delete>
 
 
+    <select id="selectUserComplaintsPageByTournamentId" resultType="org.dromara.business.domain.vo.UserComplaintsVo" >
+        SELECT
+            a.id,
+            a.user_id,
+            a.tournament_id,
+            a.final_rank,
+            a.complaint_reason,
+            a.create_at,
+            a.update_at,
+            a.status,
+            a.status_text,
+            b.nick_name,
+            b.phone,
+            c.name  tournamentName,
+            c.start_time,
+            a.advice,
+            a.operate_name
+        FROM
+            user_complaints a left join user b  on a.user_id=b.id
+                              left join  tournaments c  on a.tournament_id=c.id
+        WHERE a.tournament_id =  #{tournamentId}  and a.status not in (2,3)
+        <if test="userId != null">and a.user_id = #{userId}</if>
+    </select>
+
 </mapper>