507 lines
18 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<RewardRule> getRuleList(Integer page, Integer pageSize, String ruleType) {
Page<RewardRule> pageParam = new Page<>(page, pageSize);
LambdaQueryWrapper<RewardRule> 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<RewardRule> getEnabledRules() {
LambdaQueryWrapper<RewardRule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RewardRule::getEnabled, 1);
return rewardRuleMapper.selectList(wrapper);
}
/**
* 任务完成时触发检查
*/
@Transactional
public void onTaskCompleted(Task task, User user) {
// 获取任务相关的奖励规则
LambdaQueryWrapper<RewardRule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RewardRule::getEnabled, 1)
.eq(RewardRule::getRuleType, "task");
List<RewardRule> 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<RewardRule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RewardRule::getEnabled, 1)
.eq(RewardRule::getRuleType, "rating");
List<RewardRule> 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<String, Object> condition = objectMapper.readValue(
rule.getTriggerCondition(), new TypeReference<Map<String, Object>>() {});
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<Task> 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<Task> 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<String, Object> 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<RewardRule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RewardRule::getEnabled, 1)
.eq(RewardRule::getRuleType, ruleType);
List<RewardRule> 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<User> 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<User> getUsersByScope(RewardRule rule) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getDeleted, 0);
if ("designer".equals(rule.getScope())) {
// 获取设计师角色的用户
// 简化处理,获取所有用户
} else if ("department".equals(rule.getScope()) && rule.getScopeDeptIds() != null) {
try {
List<Long> deptIds = objectMapper.readValue(
rule.getScopeDeptIds(), new TypeReference<List<Long>>() {});
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<String, Object> condition = objectMapper.readValue(
rule.getTriggerCondition(), new TypeReference<Map<String, Object>>() {});
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<Task> 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<Task> 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("初始化默认奖励规则完成");
}
}