|
|
@@ -3,7 +3,6 @@ package org.dromara.business.service.impl;
|
|
|
import cn.hutool.json.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
-import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import org.dromara.business.domain.PlayerItems;
|
|
|
import org.dromara.business.domain.PlayersItemsLog;
|
|
|
import org.dromara.business.domain.User;
|
|
|
@@ -24,6 +23,8 @@ 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.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@@ -57,6 +58,8 @@ public class UserServiceImpl implements IUserService {
|
|
|
@Autowired
|
|
|
RedisUtil redisUtil;
|
|
|
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
|
|
|
+
|
|
|
/**
|
|
|
* 查询【请填写功能名称】
|
|
|
*
|
|
|
@@ -308,54 +311,80 @@ public class UserServiceImpl implements IUserService {
|
|
|
@Override
|
|
|
public Boolean sendRewardToos(ItemsUserBo bo) {
|
|
|
try {
|
|
|
+ logger.info("开始发放/扣除道具, 请求参数: {}", bo);
|
|
|
+
|
|
|
// 1. 参数校验
|
|
|
validateParams(bo);
|
|
|
+ logger.debug("参数校验通过: userId={}, itemId={}, quantity={}, type={}",
|
|
|
+ bo.getUserId(), bo.getItemId(), bo.getQuantity(), bo.getType());
|
|
|
|
|
|
// 2. 获取分布式锁
|
|
|
boolean lockAcquired = ItemOperationLock.tryLock(bo.getUserId(), 3000);
|
|
|
if (!lockAcquired) {
|
|
|
+ logger.warn("获取道具操作锁失败,用户可能正在并发操作: userId={}", bo.getUserId());
|
|
|
throw new RuntimeException("获取道具操作锁失败,请稍后再试");
|
|
|
}
|
|
|
|
|
|
+ logger.debug("成功获取分布式锁: userId={}", bo.getUserId());
|
|
|
+
|
|
|
try {
|
|
|
- if(bo.getType()==2){
|
|
|
- //判断道具数量是否充足
|
|
|
+ // * type: 1 新增, 2 扣除, 3 其他
|
|
|
+ if (bo.getType() == 2) {
|
|
|
+ logger.debug("执行道具扣除前检查: userId={}, itemId={}, requiredQuantity={}",
|
|
|
+ bo.getUserId(), bo.getItemId(), bo.getQuantity());
|
|
|
+
|
|
|
PlayerItems playerItem = new PlayerItems();
|
|
|
playerItem.setPlayerId(bo.getUserId());
|
|
|
playerItem.setItemId(bo.getItemId().longValue());
|
|
|
|
|
|
PlayerItemsVo playerItemsVos = playerItemsMapper.selectPlayerItems(playerItem);
|
|
|
if (playerItemsVos == null || playerItemsVos.getQuantity() < bo.getQuantity()) {
|
|
|
+ logger.warn("道具数量不足: userId={}, itemId={}, available={}, required={}",
|
|
|
+ bo.getUserId(), bo.getItemId(),
|
|
|
+ playerItemsVos != null ? playerItemsVos.getQuantity() : 0,
|
|
|
+ bo.getQuantity());
|
|
|
throw new RuntimeException("道具数量不足");
|
|
|
}
|
|
|
+ logger.debug("道具数量检查通过: 当前持有={}", playerItemsVos.getQuantity());
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- // 3. 记录日志
|
|
|
+ // 3. 记录变更日志
|
|
|
+ logger.debug("开始记录道具操作日志");
|
|
|
logRewardDistribution(bo);
|
|
|
+ logger.debug("道具操作日志记录完成");
|
|
|
|
|
|
- // 4. 发放道具
|
|
|
- //根据类型 判断发放 还是 扣减 type 1 新增 2 扣除 3 其他
|
|
|
+ // 4. 发放/更新道具
|
|
|
+ logger.debug("开始构建道具变更列表");
|
|
|
List<PlayerItems> playerItemsList = buildPlayerItems(bo);
|
|
|
int updateCount = playerItemsMapper.batchInsertOrUpdatePlayerItems(playerItemsList);
|
|
|
+
|
|
|
if (updateCount <= 0) {
|
|
|
+ logger.error("道具发放/更新失败,数据库未影响任何记录: {}", bo);
|
|
|
throw new RuntimeException("道具发放失败");
|
|
|
}
|
|
|
+
|
|
|
+ logger.info("道具操作成功: userId={}, itemId={}, quantity={}, type={}, affectedRows={}",
|
|
|
+ bo.getUserId(), bo.getItemId(), bo.getQuantity(), bo.getType(), updateCount);
|
|
|
+
|
|
|
+ // 5. 发送 Redis 消息
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
jsonObject.put("channelType", "item_update");
|
|
|
jsonObject.put("value", bo.getUserId());
|
|
|
redisUtil.publish(RedisKeys.CHANNEL_ADMIN, jsonObject);
|
|
|
+ logger.debug("已发布 Redis 消息: channel={}, data={}", RedisKeys.CHANNEL_ADMIN, jsonObject);
|
|
|
+
|
|
|
return Boolean.TRUE;
|
|
|
|
|
|
} finally {
|
|
|
- // 5. 释放锁(确保释放)
|
|
|
+ // 确保释放锁
|
|
|
ItemOperationLock.releaseLock(bo.getUserId());
|
|
|
+ logger.debug("已释放分布式锁: userId={}", bo.getUserId());
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- log.error("发放道具失败,userId={}, itemId={}, quantity={}",
|
|
|
- bo.getUserId(), bo.getItemId(), bo.getQuantity(), e);
|
|
|
- throw e; // 继续抛出异常
|
|
|
+ logger.error("【严重】发放道具失败,完整请求参数: {}, 错误信息: {}",
|
|
|
+ bo, e.getMessage(), e); // 输出参数和堆栈
|
|
|
+ throw e;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -384,41 +413,65 @@ public class UserServiceImpl implements IUserService {
|
|
|
|
|
|
// 记录日志
|
|
|
private void logRewardDistribution(ItemsUserBo bo) {
|
|
|
- ItemsVo itemsVo = itemsMapper.selectVoByIdInfo(bo.getItemId().longValue());
|
|
|
- if (itemsVo == null) {
|
|
|
- throw new RuntimeException("道具信息不存在,itemId=" + bo.getItemId());
|
|
|
- }
|
|
|
+ try {
|
|
|
+ logger.info("开始记录道具发放/回收日志, 请求参数: {}", bo);
|
|
|
|
|
|
- PlayerItems playerItem = new PlayerItems();
|
|
|
- playerItem.setPlayerId(bo.getUserId());
|
|
|
- playerItem.setItemId(bo.getItemId().longValue());
|
|
|
+ // 查询道具信息
|
|
|
+ ItemsVo itemsVo = itemsMapper.selectVoByIdInfo(bo.getItemId().longValue());
|
|
|
+ if (itemsVo == null) {
|
|
|
+ logger.error("道具信息不存在,itemId={}", bo.getItemId());
|
|
|
+ throw new RuntimeException("道具信息不存在,itemId=" + bo.getItemId());
|
|
|
+ }
|
|
|
+ logger.debug("查询到道具信息: itemId={}, name={}, itemDesc={}",
|
|
|
+ itemsVo.getId(), itemsVo.getName(), itemsVo.getItemDesc());
|
|
|
+
|
|
|
+ PlayerItems playerItem = new PlayerItems();
|
|
|
+ playerItem.setPlayerId(bo.getUserId());
|
|
|
+ playerItem.setItemId(bo.getItemId().longValue());
|
|
|
+
|
|
|
+ // 查询玩家当前持有数量
|
|
|
+ PlayerItemsVo playerItemsVos = playerItemsMapper.selectPlayerItems(playerItem);
|
|
|
+ Integer beforeNum = playerItemsVos != null ? Integer.valueOf(playerItemsVos.getQuantity().toString()) : 0;
|
|
|
+ logger.debug("玩家当前持有道具数量: playerId={}, itemId={}, beforeNum={}",
|
|
|
+ bo.getUserId(), bo.getItemId(), beforeNum);
|
|
|
+
|
|
|
+ // 计算变更后数量
|
|
|
+ Integer afterNum;
|
|
|
+ if (bo.getType() == 1) {
|
|
|
+ afterNum = beforeNum + bo.getQuantity();
|
|
|
+ logger.debug("道具发放操作: quantity={}", bo.getQuantity());
|
|
|
+ } else {
|
|
|
+ afterNum = beforeNum - bo.getQuantity();
|
|
|
+ logger.debug("道具回收操作: quantity={}", bo.getQuantity());
|
|
|
+ }
|
|
|
|
|
|
- PlayerItemsVo playerItemsVos = playerItemsMapper.selectPlayerItems(playerItem);
|
|
|
- Integer beforeNum = playerItemsVos != null ? Integer.valueOf(playerItemsVos.getQuantity().toString()) : 0;
|
|
|
- Integer afterNum=0;
|
|
|
- if(bo.getType()==1){
|
|
|
- afterNum = beforeNum + bo.getQuantity();
|
|
|
- }else{
|
|
|
- afterNum = beforeNum - bo.getQuantity();
|
|
|
- }
|
|
|
+ // 构建日志实体
|
|
|
+ PlayersItemsLog logEntry = new PlayersItemsLog();
|
|
|
+ logEntry.setItemId(bo.getItemId().longValue());
|
|
|
+ logEntry.setScoreNum(bo.getQuantity().longValue());
|
|
|
+ logEntry.setBeforeNum(beforeNum.longValue());
|
|
|
+ logEntry.setAfterNum(afterNum.longValue());
|
|
|
+ logEntry.setUserId(bo.getUserId());
|
|
|
+ logEntry.setItemTypeText(itemsVo.getName());
|
|
|
+ logEntry.setRemark(itemsVo.getItemDesc());
|
|
|
+ logEntry.setType(bo.getType() == 1 ? 1L : 2L); // 简化赋值
|
|
|
+
|
|
|
+ logger.debug("准备插入日志记录: {}", logEntry);
|
|
|
+
|
|
|
+ // 插入日志
|
|
|
+ int insertResult = playersItemsLogMapper.insertPlayerItemLog(logEntry);
|
|
|
+ if (insertResult <= 0) {
|
|
|
+ logger.error("道具日志记录失败, 最终尝试写入的数据: {}", logEntry);
|
|
|
+ throw new RuntimeException("道具日志记录失败");
|
|
|
+ }
|
|
|
|
|
|
- PlayersItemsLog logEntry = new PlayersItemsLog();
|
|
|
- logEntry.setItemId(bo.getItemId().longValue());
|
|
|
- logEntry.setScoreNum(bo.getQuantity().longValue());
|
|
|
- logEntry.setAfterNum(afterNum.longValue());
|
|
|
- logEntry.setUserId(bo.getUserId());
|
|
|
+ logger.info("道具日志记录成功: userId={}, itemId={}, type={}, beforeNum={}, afterNum={}, quantity={}",
|
|
|
+ bo.getUserId(), bo.getItemId(), logEntry.getType(),
|
|
|
+ logEntry.getBeforeNum(), logEntry.getAfterNum(), logEntry.getScoreNum());
|
|
|
|
|
|
- logEntry.setBeforeNum(beforeNum.longValue());
|
|
|
- logEntry.setItemTypeText(itemsVo.getName());
|
|
|
- logEntry.setRemark(itemsVo.getItemDesc());
|
|
|
- if(bo.getType()==1){
|
|
|
- logEntry.setType(1L);
|
|
|
- }else{
|
|
|
- logEntry.setType(2L);
|
|
|
- }
|
|
|
- int insertResult = playersItemsLogMapper.insertPlayerItemLog(logEntry);
|
|
|
- if (insertResult <= 0) {
|
|
|
- throw new RuntimeException("道具日志记录失败");
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("记录道具日志时发生异常: ", e); // 输出完整堆栈
|
|
|
+ throw e; // 继续抛出异常
|
|
|
}
|
|
|
}
|
|
|
|