崔向南 | 03d21b9 | 2025-06-05 17:42:23 +0800 | [diff] [blame^] | 1 | package bounty.service; |
| 2 | |
| 3 | import bounty.domain.Bounty; |
| 4 | import bounty.domain.BountySubmission; |
| 5 | import bounty.mapper.BountyMapper; |
| 6 | import bounty.mapper.BountySubmissionMapper; |
| 7 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 8 | import com.baomidou.mybatisplus.core.metadata.IPage; |
| 9 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| 10 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| 11 | import com.ruoyi.common.utils.SecurityUtils; |
| 12 | import org.mybatis.spring.MyBatisSystemException; |
| 13 | import org.springframework.beans.factory.annotation.Autowired; |
| 14 | import org.springframework.stereotype.Service; |
| 15 | import org.springframework.util.StringUtils; |
| 16 | |
| 17 | import org.slf4j.Logger; |
| 18 | import org.slf4j.LoggerFactory; |
| 19 | |
| 20 | import java.util.Date; |
| 21 | |
| 22 | @Service |
| 23 | public class BountySubmissionServiceImpl extends ServiceImpl<BountySubmissionMapper, BountySubmission> implements BountySubmissionService { |
| 24 | |
| 25 | @Autowired |
| 26 | private BountyMapper bountyMapper; // 注入 BountyMapper 校验悬赏存在性 |
| 27 | |
| 28 | @Override |
| 29 | public boolean saveBountySubmission(BountySubmission bountySubmission) { |
| 30 | // 校验 1:悬赏 ID 不能为空 |
| 31 | Long bountyId = bountySubmission.getBountyId(); |
| 32 | if (bountyId == null) { |
| 33 | throw new IllegalArgumentException("悬赏 ID 不能为空"); |
| 34 | } |
| 35 | |
| 36 | // 校验 2:目标悬赏是否存在 |
| 37 | Bounty targetBounty = bountyMapper.selectById(bountyId); |
| 38 | if (targetBounty == null) { |
| 39 | throw new IllegalArgumentException("无效的悬赏 ID,未找到对应悬赏"); |
| 40 | } |
| 41 | |
| 42 | // 校验 3:提交内容不能为空 |
| 43 | String content = bountySubmission.getContent(); |
| 44 | if (!StringUtils.hasText(content)) { |
| 45 | throw new IllegalArgumentException("提交内容不能为空"); |
| 46 | } |
| 47 | |
| 48 | // 自动填充当前用户 ID(需用户已登录) |
| 49 | Long currentUserId = SecurityUtils.getUserId(); |
| 50 | bountySubmission.setUserId(currentUserId); |
| 51 | |
| 52 | |
| 53 | // 调用 MyBatis-Plus 保存方法 |
| 54 | boolean saveResult = this.save(bountySubmission); |
| 55 | |
| 56 | // 新增:保存成功后,更新对应悬赏的状态为1(已回复) |
| 57 | if (saveResult) { |
| 58 | targetBounty.setStatus(1); // 将悬赏状态改为1 |
| 59 | bountyMapper.updateById(targetBounty); // 执行更新 |
| 60 | } |
| 61 | |
| 62 | return saveResult; |
| 63 | } |
| 64 | |
| 65 | @Override |
| 66 | public IPage<BountySubmission> getBountySubmissionsByPage(Page<BountySubmission> page, Long bountyId) { |
| 67 | QueryWrapper<BountySubmission> wrapper = new QueryWrapper<>(); |
| 68 | wrapper.eq("bounty_id", bountyId); |
| 69 | return this.page(page, wrapper); |
| 70 | } |
| 71 | |
| 72 | private static final Logger log = LoggerFactory.getLogger(BountySubmissionServiceImpl.class); |
| 73 | |
| 74 | @Override |
| 75 | public boolean adoptSubmission(Long submissionId) { |
| 76 | log.info("【采纳流程开始】submissionId={}, 当前时间={}", submissionId, new Date()); |
| 77 | |
| 78 | try { |
| 79 | // 参数校验 |
| 80 | if (submissionId == null || submissionId <= 0) { |
| 81 | log.warn("【参数校验失败】submissionId为空或无效"); |
| 82 | throw new IllegalArgumentException("无效的回复ID"); |
| 83 | } |
| 84 | |
| 85 | // 获取回复详情 |
| 86 | BountySubmission submission = this.getById(submissionId); |
| 87 | if (submission == null) { |
| 88 | log.warn("【回复不存在】submissionId={}", submissionId); |
| 89 | throw new IllegalArgumentException("无效的回复ID"); |
| 90 | } |
| 91 | |
| 92 | if (submission.getId() == null || submission.getBountyId() == null) { |
| 93 | log.warn("【无效提交数据】submissionId={}", submissionId); |
| 94 | throw new IllegalArgumentException("提交数据不完整"); |
| 95 | } |
| 96 | |
| 97 | |
| 98 | log.debug("【原始回复数据】{}", submission); |
| 99 | |
| 100 | // 获取关联悬赏 |
| 101 | Bounty bounty = bountyMapper.selectById(submission.getBountyId()); |
| 102 | |
| 103 | if (bounty == null) { |
| 104 | log.warn("【关联悬赏不存在】bountyId={}", submission.getBountyId()); |
| 105 | throw new IllegalArgumentException("关联悬赏不存在"); |
| 106 | } |
| 107 | |
| 108 | // 用户权限校验 |
| 109 | Long currentUserId = SecurityUtils.getUserId(); |
| 110 | if (currentUserId == null) { |
| 111 | log.warn("【用户未登录】"); |
| 112 | throw new IllegalArgumentException("用户未登录"); |
| 113 | } |
| 114 | |
| 115 | |
| 116 | if (!bounty.getCreator_id().equals(currentUserId)) { |
| 117 | log.warn("【权限不足】用户ID={} 试图访问悬赏ID={}", currentUserId, bounty.getId()); |
| 118 | throw new IllegalArgumentException("无权操作"); |
| 119 | } |
| 120 | |
| 121 | // 状态校验 |
| 122 | if (submission.getStatus() == 1) { |
| 123 | log.warn("【重复采纳】submissionId={}", submissionId); |
| 124 | throw new IllegalArgumentException("该回复已被采纳"); |
| 125 | } |
| 126 | |
| 127 | log.info("【更新前对象】{}", submission); |
| 128 | |
| 129 | // 执行更新 |
| 130 | submission.setStatus(1); |
| 131 | boolean submissionResult = this.updateById(submission); |
| 132 | log.info("【更新后对象】{}", this.getById(submissionId)); |
| 133 | |
| 134 | |
| 135 | log.info("【操作结果】submissionResult={}, 新状态={}", submissionResult, submission.getStatus()); |
| 136 | |
| 137 | return submissionResult; |
| 138 | } catch (MyBatisSystemException e) { |
| 139 | // 显式捕获 MyBatis 异常 |
| 140 | log.error("【MyBatis 异常】submissionId={}, rootCause={}", submissionId, e.getRootCause()); |
| 141 | log.error("【异常详情】", e); // 打印完整堆栈 |
| 142 | throw new RuntimeException("MyBatis 错误: " + e.getRootCause(), e); |
| 143 | |
| 144 | } catch (IllegalArgumentException e) { |
| 145 | log.warn("【参数异常】submissionId={}, message={}", submissionId, e.getMessage()); |
| 146 | throw e; |
| 147 | } catch (Exception e) { |
| 148 | log.error("【采纳异常】submissionId={}, 错误={}", submissionId, e.getMessage(), e); |
| 149 | log.error("【未分类异常】submissionId={}, exceptionClass={}", submissionId, e.getClass().getName()); |
| 150 | log.error("【异常详情】", e); // 打印完整堆栈 |
| 151 | throw e; |
| 152 | } |
| 153 | } |
| 154 | } |