package com.designhub.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.designhub.common.ResultCode; import com.designhub.entity.RewardRecord; import com.designhub.entity.RewardRule; import com.designhub.entity.Task; import com.designhub.entity.User; import com.designhub.exception.BusinessException; import com.designhub.mapper.RewardRecordMapper; import com.designhub.mapper.RewardRuleMapper; import com.designhub.mapper.TaskMapper; import com.designhub.mapper.UserMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Map; /** * 自动奖励规则 Service */ @Slf4j @Service @RequiredArgsConstructor public class RewardRuleService { private final RewardRuleMapper rewardRuleMapper; private final RewardRecordMapper rewardRecordMapper; private final UserMapper userMapper; private final TaskMapper taskMapper; private final NotificationService notificationService; private final ObjectMapper objectMapper; /** * 创建奖励规则 */ @Transactional public RewardRule createRule(RewardRule rule) { rule.setEnabled(1); rule.setDeleted(0); rewardRuleMapper.insert(rule); log.info("创建奖励规则成功: id={}, name={}", rule.getId(), rule.getName()); return rule; } /** * 更新奖励规则 */ @Transactional public RewardRule updateRule(Long id, RewardRule rule) { RewardRule existing = rewardRuleMapper.selectById(id); if (existing == null) { throw new BusinessException(ResultCode.NOT_FOUND, "规则不存在"); } rule.setId(id); rewardRuleMapper.updateById(rule); return rewardRuleMapper.selectById(id); } /** * 启用/禁用规则 */ @Transactional public void toggleRule(Long id, boolean enabled) { RewardRule rule = rewardRuleMapper.selectById(id); if (rule == null) { throw new BusinessException(ResultCode.NOT_FOUND, "规则不存在"); } rule.setEnabled(enabled ? 1 : 0); rewardRuleMapper.updateById(rule); } /** * 删除规则 */ @Transactional public void deleteRule(Long id) { rewardRuleMapper.deleteById(id); } /** * 获取规则列表 */ public IPage getRuleList(Integer page, Integer pageSize, String ruleType) { Page pageParam = new Page<>(page, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (ruleType != null && !ruleType.isEmpty()) { wrapper.eq(RewardRule::getRuleType, ruleType); } wrapper.orderByDesc(RewardRule::getPriority) .orderByDesc(RewardRule::getCreateTime); return rewardRuleMapper.selectPage(pageParam, wrapper); } /** * 获取规则详情 */ public RewardRule getRuleById(Long id) { RewardRule rule = rewardRuleMapper.selectById(id); if (rule == null) { throw new BusinessException(ResultCode.NOT_FOUND, "规则不存在"); } return rule; } /** * 获取所有启用的规则 */ public List getEnabledRules() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RewardRule::getEnabled, 1); return rewardRuleMapper.selectList(wrapper); } /** * 任务完成时触发检查 */ @Transactional public void onTaskCompleted(Task task, User user) { // 获取任务相关的奖励规则 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RewardRule::getEnabled, 1) .eq(RewardRule::getRuleType, "task"); List rules = rewardRuleMapper.selectList(wrapper); for (RewardRule rule : rules) { if (checkRuleCondition(rule, user, task)) { applyReward(rule, user); } } } /** * 好评时触发检查 */ @Transactional public void onTaskRated(Task task, User user, Integer rating) { if (rating == null || rating < 5) return; // 获取好评相关的奖励规则 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RewardRule::getEnabled, 1) .eq(RewardRule::getRuleType, "rating"); List rules = rewardRuleMapper.selectList(wrapper); for (RewardRule rule : rules) { if (checkRuleCondition(rule, user, task)) { applyReward(rule, user); } } } /** * 检查规则条件是否满足 */ private boolean checkRuleCondition(RewardRule rule, User user, Task task) { try { Map condition = objectMapper.readValue( rule.getTriggerCondition(), new TypeReference>() {}); String type = (String) condition.get("type"); String operator = (String) condition.get("operator"); int targetValue = ((Number) condition.get("value")).intValue(); int actualValue = 0; switch (type) { case "task_count": // 统计用户完成任务数 actualValue = countUserTasks(user.getId(), "completed"); break; case "rating": // 任务评分 actualValue = task.getRating() != null ? task.getRating() : 0; break; case "five_star_count": // 统计五星好评数 actualValue = countUserFiveStarTasks(user.getId()); break; default: return false; } return compareValue(actualValue, operator, targetValue); } catch (JsonProcessingException e) { log.error("解析规则条件失败", e); return false; } } /** * 值比较 */ private boolean compareValue(int actual, String operator, int target) { switch (operator) { case ">=": return actual >= target; case ">": return actual > target; case "<=": return actual <= target; case "<": return actual < target; case "==": return actual == target; default: return false; } } /** * 统计用户任务数 */ private int countUserTasks(Long userId, String status) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Task::getReceiverId, userId) .eq(Task::getStatus, status); Long count = taskMapper.selectCount(wrapper); return count != null ? count.intValue() : 0; } /** * 统计用户五星好评数 */ private int countUserFiveStarTasks(Long userId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Task::getReceiverId, userId) .eq(Task::getStatus, "completed") .ge(Task::getRating, 5); Long count = taskMapper.selectCount(wrapper); return count != null ? count.intValue() : 0; } /** * 应用奖励 */ @Transactional public void applyReward(RewardRule rule, User user) { applyReward(rule, user, null); } /** * 应用奖励(带触发数据) */ @Transactional public void applyReward(RewardRule rule, User user, Object triggerData) { if (rule.getRewardScore() != null && rule.getRewardScore() > 0) { int currentScore = user.getScore() != null ? user.getScore() : 0; user.setScore(currentScore + rule.getRewardScore()); userMapper.updateById(user); // 记录奖励发放 try { Map rewardValue = new java.util.HashMap<>(); rewardValue.put("score", rule.getRewardScore()); RewardRecord record = new RewardRecord(); record.setUserId(user.getId()); record.setRuleId(rule.getId()); record.setRuleName(rule.getName()); record.setRewardType("score"); record.setRewardValue(objectMapper.writeValueAsString(rewardValue)); if (triggerData != null) { record.setTriggerData(objectMapper.writeValueAsString(triggerData)); } record.setCreateTime(LocalDateTime.now()); rewardRecordMapper.insert(record); } catch (Exception e) { log.error("记录奖励发放失败", e); } // 更新规则触发次数 rule.setTriggerCount(rule.getTriggerCount() != null ? rule.getTriggerCount() + 1 : 1); rewardRuleMapper.updateById(rule); // 发送通知 notificationService.sendNotification( user.getId(), "获得奖励", String.format("恭喜!根据「%s」规则,您获得 %d 积分奖励!", rule.getName(), rule.getRewardScore()), "reward", rule.getId() ); log.info("用户获得自动奖励: userId={}, ruleId={}, score={}", user.getId(), rule.getId(), rule.getRewardScore()); } } /** * 定时任务:执行每日奖励规则 */ @Scheduled(cron = "0 0 23 * * ?") // 每天23点执行 @Transactional public void executeDailyRewards() { log.info("开始执行每日自动奖励规则"); executePeriodicRewards("daily"); } /** * 定时任务:执行每周奖励规则 */ @Scheduled(cron = "0 0 22 ? * SUN") // 每周日22点执行 @Transactional public void executeWeeklyRewards() { log.info("开始执行每周自动奖励规则"); executePeriodicRewards("weekly"); } /** * 定时任务:执行每月奖励规则 */ @Scheduled(cron = "0 0 21 L * ?") // 每月最后一天21点执行 @Transactional public void executeMonthlyRewards() { log.info("开始执行每月自动奖励规则"); executePeriodicRewards("monthly"); } /** * 执行周期性奖励 */ private void executePeriodicRewards(String ruleType) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RewardRule::getEnabled, 1) .eq(RewardRule::getRuleType, ruleType); List rules = rewardRuleMapper.selectList(wrapper); for (RewardRule rule : rules) { try { executePeriodicRule(rule); rule.setLastExecuteTime(LocalDateTime.now()); rewardRuleMapper.updateById(rule); } catch (Exception e) { log.error("执行奖励规则失败: ruleId={}", rule.getId(), e); } } } /** * 执行单个周期性规则 */ private void executePeriodicRule(RewardRule rule) { // 获取符合范围的用户 List users = getUsersByScope(rule); LocalDateTime startTime = getStartTimeByRuleType(rule.getRuleType()); LocalDateTime endTime = LocalDateTime.now(); for (User user : users) { // 检查用户在该周期内是否满足条件 if (checkPeriodicCondition(rule, user, startTime, endTime)) { applyReward(rule, user); } } } /** * 根据范围获取用户列表 */ private List getUsersByScope(RewardRule rule) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getDeleted, 0); if ("designer".equals(rule.getScope())) { // 获取设计师角色的用户 // 简化处理,获取所有用户 } else if ("department".equals(rule.getScope()) && rule.getScopeDeptIds() != null) { try { List deptIds = objectMapper.readValue( rule.getScopeDeptIds(), new TypeReference>() {}); wrapper.in(User::getDeptId, deptIds); } catch (JsonProcessingException e) { log.error("解析部门ID失败", e); } } return userMapper.selectList(wrapper); } /** * 获取周期开始时间 */ private LocalDateTime getStartTimeByRuleType(String ruleType) { LocalDateTime now = LocalDateTime.now(); switch (ruleType) { case "daily": return now.toLocalDate().atStartOfDay(); case "weekly": return now.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY)) .toLocalDate().atStartOfDay(); case "monthly": return now.with(TemporalAdjusters.firstDayOfMonth()) .toLocalDate().atStartOfDay(); default: return now.minusDays(1); } } /** * 检查周期性条件 */ private boolean checkPeriodicCondition(RewardRule rule, User user, LocalDateTime startTime, LocalDateTime endTime) { try { Map condition = objectMapper.readValue( rule.getTriggerCondition(), new TypeReference>() {}); String type = (String) condition.get("type"); String operator = (String) condition.get("operator"); int targetValue = ((Number) condition.get("value")).intValue(); int actualValue = 0; switch (type) { case "task_count": // 统计周期内完成任务数 LambdaQueryWrapper taskWrapper = new LambdaQueryWrapper<>(); taskWrapper.eq(Task::getReceiverId, user.getId()) .eq(Task::getStatus, "completed") .ge(Task::getCompleteTime, startTime) .le(Task::getCompleteTime, endTime); Long taskCount = taskMapper.selectCount(taskWrapper); actualValue = taskCount != null ? taskCount.intValue() : 0; break; case "five_star_count": // 统计周期内五星好评数 LambdaQueryWrapper fiveStarWrapper = new LambdaQueryWrapper<>(); fiveStarWrapper.eq(Task::getReceiverId, user.getId()) .eq(Task::getStatus, "completed") .ge(Task::getRating, 5) .ge(Task::getCompleteTime, startTime) .le(Task::getCompleteTime, endTime); Long fiveStarCount = taskMapper.selectCount(fiveStarWrapper); actualValue = fiveStarCount != null ? fiveStarCount.intValue() : 0; break; default: return false; } return compareValue(actualValue, operator, targetValue); } catch (JsonProcessingException e) { log.error("解析规则条件失败", e); return false; } } /** * 初始化默认奖励规则 */ @Transactional public void initDefaultRules() { // 检查是否已有规则 if (rewardRuleMapper.selectCount(null) > 0) { return; } // 每日完成5个任务奖励 RewardRule dailyRule = new RewardRule(); dailyRule.setName("每日任务达人"); dailyRule.setDescription("每天完成5个任务,额外奖励20积分"); dailyRule.setRuleType("daily"); dailyRule.setTriggerCondition("{\"type\":\"task_count\",\"operator\":\">=\",\"value\":5}"); dailyRule.setRewardType("score"); dailyRule.setRewardScore(20); dailyRule.setScope("all"); dailyRule.setEnabled(1); dailyRule.setPriority(100); rewardRuleMapper.insert(dailyRule); // 每周完成20个任务奖励 RewardRule weeklyRule = new RewardRule(); weeklyRule.setName("每周效率之星"); weeklyRule.setDescription("每周完成20个任务,额外奖励100积分"); weeklyRule.setRuleType("weekly"); weeklyRule.setTriggerCondition("{\"type\":\"task_count\",\"operator\":\">=\",\"value\":20}"); weeklyRule.setRewardType("score"); weeklyRule.setRewardScore(100); weeklyRule.setScope("all"); weeklyRule.setEnabled(1); weeklyRule.setPriority(90); rewardRuleMapper.insert(weeklyRule); // 五星好评奖励 RewardRule ratingRule = new RewardRule(); ratingRule.setName("五星好评奖励"); ratingRule.setDescription("获得五星好评,奖励10积分"); ratingRule.setRuleType("rating"); ratingRule.setTriggerCondition("{\"type\":\"rating\",\"operator\":\">=\",\"value\":5}"); ratingRule.setRewardType("score"); ratingRule.setRewardScore(10); ratingRule.setScope("all"); ratingRule.setEnabled(1); ratingRule.setPriority(80); rewardRuleMapper.insert(ratingRule); log.info("初始化默认奖励规则完成"); } }