新增spins task
This commit is contained in:
parent
da9819085f
commit
83f79ce3d8
@ -34,7 +34,7 @@ public interface LotteryTicketClientApi {
|
||||
* 增加用户抽奖券.
|
||||
*/
|
||||
@PostMapping("/addTicket")
|
||||
ResultResponse<Boolean> addTicket(
|
||||
ResultResponse<Long> addTicket(
|
||||
@RequestParam("userId") Long userId,
|
||||
@RequestParam("count") Integer count,
|
||||
@RequestParam(value = "source", required = false) String source,
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
package com.red.circle.other.adapter.app.task;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskCO;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd;
|
||||
import com.red.circle.other.app.service.SpinsTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spins任务接口
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/spins/task")
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskRestController {
|
||||
|
||||
private final SpinsTaskService spinsTaskService;
|
||||
|
||||
/**
|
||||
* 获取用户任务列表
|
||||
*
|
||||
* @param cmd 用户ID
|
||||
* @return 任务列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public List<SpinsTaskCO> getTaskList(AppExtCommand cmd) {
|
||||
Long userId = cmd.getReqUserId();
|
||||
log.info("获取用户任务列表, userId={}", userId);
|
||||
List<SpinsTaskCO> taskList = spinsTaskService.getUserTaskList(userId);
|
||||
return taskList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取任务奖励
|
||||
*
|
||||
* @param cmd 领取奖励命令
|
||||
* @return 奖励信息
|
||||
*/
|
||||
@PostMapping("/receive/reward")
|
||||
public SpinsTaskRewardCO receiveReward(@Validated @RequestBody SpinsTaskReceiveRewardCmd cmd) {
|
||||
log.info("领取任务奖励, userId={}, taskCode={}", cmd.getUserId(), cmd.getTaskCode());
|
||||
SpinsTaskRewardCO reward = spinsTaskService.receiveTaskReward(cmd);
|
||||
return reward;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 增加任务进度执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskProgressIncrementExe {
|
||||
|
||||
private final SpinsTaskConfigDAO spinsTaskConfigDAO;
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
|
||||
/**
|
||||
* 执行增加任务进度
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param taskCode 任务编码
|
||||
* @param incrementValue 增加值
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execute(Long userId, String taskCode, Integer incrementValue) {
|
||||
// 1. 查询任务配置
|
||||
List<SpinsTaskConfig> taskConfigs = spinsTaskConfigDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsTaskConfig>()
|
||||
.eq(SpinsTaskConfig::getTaskCode, taskCode)
|
||||
.eq(SpinsTaskConfig::getStatus, 1)
|
||||
);
|
||||
|
||||
if (taskConfigs.isEmpty()) {
|
||||
log.warn("任务配置不存在或已下线, taskCode={}", taskCode);
|
||||
return;
|
||||
}
|
||||
|
||||
SpinsTaskConfig taskConfig = taskConfigs.get(0);
|
||||
|
||||
// 2. 获取或创建用户任务进度
|
||||
String cycleKey = getCurrentCycleKey(taskConfig.getCycleType());
|
||||
SpinsUserTaskProgress progress = getOrCreateProgress(userId, taskConfig, cycleKey);
|
||||
|
||||
// 3. 增加进度值
|
||||
int newValue = progress.getCurrentValue() + incrementValue;
|
||||
progress.setCurrentValue(newValue);
|
||||
|
||||
// 4. 计算进度百分比
|
||||
BigDecimal progressRate = calculateProgressRate(newValue, taskConfig.getTargetValue());
|
||||
progress.setProgressRate(progressRate);
|
||||
|
||||
// 5. 检查是否完成
|
||||
if (newValue >= taskConfig.getTargetValue() && progress.getTaskStatus() == 0) {
|
||||
progress.setTaskStatus(1);
|
||||
progress.setCompleteTime(new Timestamp(System.currentTimeMillis()));
|
||||
progress.setCompleteTimes(progress.getCompleteTimes() + 1);
|
||||
log.info("任务完成, userId={}, taskCode={}, newValue={}", userId, taskCode, newValue);
|
||||
}
|
||||
|
||||
progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
|
||||
spinsUserTaskProgressDAO.updateById(progress);
|
||||
|
||||
log.info("任务进度增加成功, userId={}, taskCode={}, incrementValue={}, newValue={}",
|
||||
userId, taskCode, incrementValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或创建用户任务进度
|
||||
*/
|
||||
private SpinsUserTaskProgress getOrCreateProgress(Long userId, SpinsTaskConfig taskConfig, String cycleKey) {
|
||||
List<SpinsUserTaskProgress> progressList = spinsUserTaskProgressDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.eq(SpinsUserTaskProgress::getTaskCode, taskConfig.getTaskCode())
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
|
||||
);
|
||||
SpinsUserTaskProgress progress = null;
|
||||
if (!progressList.isEmpty()) {
|
||||
progress = progressList.get(0);
|
||||
}
|
||||
|
||||
if (progress == null) {
|
||||
progress = new SpinsUserTaskProgress();
|
||||
progress.setUserId(userId);
|
||||
progress.setTaskId(taskConfig.getId());
|
||||
progress.setTaskCode(taskConfig.getTaskCode());
|
||||
progress.setCurrentValue(0);
|
||||
progress.setTargetValue(taskConfig.getTargetValue());
|
||||
progress.setProgressRate(BigDecimal.ZERO);
|
||||
progress.setTaskStatus(0);
|
||||
progress.setCycleType(taskConfig.getCycleType());
|
||||
progress.setCycleDate(LocalDate.now());
|
||||
progress.setCycleKey(cycleKey);
|
||||
progress.setCompleteTimes(0);
|
||||
progress.setRewardType(taskConfig.getRewardType());
|
||||
progress.setRewardValue(taskConfig.getRewardValue());
|
||||
progress.setCreateTime(new Timestamp(System.currentTimeMillis()));
|
||||
progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
|
||||
spinsUserTaskProgressDAO.insert(progress);
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算进度百分比
|
||||
*/
|
||||
private BigDecimal calculateProgressRate(Integer currentValue, Integer targetValue) {
|
||||
if (targetValue == null || targetValue == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return BigDecimal.valueOf(currentValue)
|
||||
.divide(BigDecimal.valueOf(targetValue), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100))
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期key
|
||||
*/
|
||||
private String getCurrentCycleKey(Integer cycleType) {
|
||||
LocalDate now = LocalDate.now();
|
||||
if (cycleType == 1) {
|
||||
// 每日任务:格式 yyyyMMdd
|
||||
return now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
} else if (cycleType == 2) {
|
||||
// 每周任务:格式 yyyyWw(例如:2025W03)
|
||||
int weekOfYear = now.getDayOfYear() / 7 + 1;
|
||||
return now.getYear() + "W" + String.format("%02d", weekOfYear);
|
||||
} else {
|
||||
// 一次性任务:固定标识
|
||||
return "ONCE";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 初始化任务进度执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskProgressInitExe {
|
||||
|
||||
private final SpinsTaskConfigDAO spinsTaskConfigDAO;
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
|
||||
/**
|
||||
* 执行初始化用户任务进度
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param taskCode 任务编码
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execute(Long userId, String taskCode) {
|
||||
// 1. 查询任务配置
|
||||
List<SpinsTaskConfig> taskConfigs = spinsTaskConfigDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsTaskConfig>()
|
||||
.eq(SpinsTaskConfig::getTaskCode, taskCode)
|
||||
.eq(SpinsTaskConfig::getStatus, 1)
|
||||
);
|
||||
|
||||
if (taskConfigs.isEmpty()) {
|
||||
log.warn("任务配置不存在或已下线, taskCode={}", taskCode);
|
||||
return;
|
||||
}
|
||||
SpinsTaskConfig taskConfig = taskConfigs.get(0);
|
||||
|
||||
// 2. 获取当前周期key
|
||||
String cycleKey = getCurrentCycleKey(taskConfig.getCycleType());
|
||||
|
||||
// 3. 检查是否已存在
|
||||
List<SpinsUserTaskProgress> existProgressList = spinsUserTaskProgressDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.eq(SpinsUserTaskProgress::getTaskCode, taskCode)
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
|
||||
);
|
||||
|
||||
if (!existProgressList.isEmpty()) {
|
||||
log.info("任务进度已存在, userId={}, taskCode={}", userId, taskCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 创建新的任务进度
|
||||
SpinsUserTaskProgress progress = new SpinsUserTaskProgress();
|
||||
progress.setUserId(userId);
|
||||
progress.setTaskId(taskConfig.getId());
|
||||
progress.setTaskCode(taskConfig.getTaskCode());
|
||||
progress.setCurrentValue(0);
|
||||
progress.setTargetValue(taskConfig.getTargetValue());
|
||||
progress.setProgressRate(BigDecimal.ZERO);
|
||||
progress.setTaskStatus(0);
|
||||
progress.setCycleType(taskConfig.getCycleType());
|
||||
progress.setCycleDate(LocalDate.now());
|
||||
progress.setCycleKey(cycleKey);
|
||||
progress.setCompleteTimes(0);
|
||||
progress.setRewardType(taskConfig.getRewardType());
|
||||
progress.setRewardValue(taskConfig.getRewardValue());
|
||||
progress.setCreateTime(new Timestamp(System.currentTimeMillis()));
|
||||
progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
|
||||
|
||||
spinsUserTaskProgressDAO.insert(progress);
|
||||
|
||||
log.info("初始化用户任务进度成功, userId={}, taskCode={}", userId, taskCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期key
|
||||
*/
|
||||
private String getCurrentCycleKey(Integer cycleType) {
|
||||
LocalDate now = LocalDate.now();
|
||||
if (cycleType == 1) {
|
||||
// 每日任务:格式 yyyyMMdd
|
||||
return now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
} else if (cycleType == 2) {
|
||||
// 每周任务:格式 yyyyWw(例如:2025W03)
|
||||
int weekOfYear = now.getDayOfYear() / 7 + 1;
|
||||
return now.getYear() + "W" + String.format("%02d", weekOfYear);
|
||||
} else {
|
||||
// 一次性任务:固定标识
|
||||
return "ONCE";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 重置任务进度执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskProgressResetExe {
|
||||
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
|
||||
/**
|
||||
* 执行重置用户每日任务
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execute(Long userId) {
|
||||
// 获取昨天的周期key
|
||||
String yesterdayCycleKey = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
|
||||
// 查询昨天的每日任务进度
|
||||
List<SpinsUserTaskProgress> progressList = spinsUserTaskProgressDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.eq(SpinsUserTaskProgress::getCycleType, 1) // 每日任务
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, yesterdayCycleKey)
|
||||
);
|
||||
|
||||
if (progressList.isEmpty()) {
|
||||
log.info("没有需要重置的每日任务, userId={}", userId);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("重置用户每日任务成功, userId={}, 重置任务数={}", userId, progressList.size());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskProgressUpdateCmd;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 更新任务进度执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskProgressUpdateExe {
|
||||
|
||||
private final SpinsTaskConfigDAO spinsTaskConfigDAO;
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
|
||||
/**
|
||||
* 执行更新任务进度
|
||||
*
|
||||
* @param cmd 更新命令
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execute(SpinsTaskProgressUpdateCmd cmd) {
|
||||
Long userId = cmd.getUserId();
|
||||
String taskCode = cmd.getTaskCode();
|
||||
Integer progressValue = cmd.getProgressValue();
|
||||
|
||||
// 1. 查询任务配置
|
||||
List<SpinsTaskConfig> taskConfigs = spinsTaskConfigDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsTaskConfig>()
|
||||
.eq(SpinsTaskConfig::getTaskCode, taskCode)
|
||||
.eq(SpinsTaskConfig::getStatus, 1)
|
||||
);
|
||||
|
||||
if (taskConfigs.isEmpty()) {
|
||||
log.warn("任务配置不存在或已下线, taskCode={}", taskCode);
|
||||
return;
|
||||
}
|
||||
SpinsTaskConfig taskConfig = taskConfigs.get(0);
|
||||
|
||||
// 2. 获取或创建用户任务进度
|
||||
String cycleKey = getCurrentCycleKey(taskConfig.getCycleType());
|
||||
SpinsUserTaskProgress progress = getOrCreateProgress(userId, taskConfig, cycleKey);
|
||||
|
||||
// 3. 更新进度值
|
||||
progress.setCurrentValue(progressValue);
|
||||
|
||||
// 4. 计算进度百分比
|
||||
BigDecimal progressRate = calculateProgressRate(progressValue, taskConfig.getTargetValue());
|
||||
progress.setProgressRate(progressRate);
|
||||
|
||||
// 5. 检查是否完成
|
||||
if (progressValue >= taskConfig.getTargetValue() && progress.getTaskStatus() == 0) {
|
||||
progress.setTaskStatus(1);
|
||||
progress.setCompleteTime(new Timestamp(System.currentTimeMillis()));
|
||||
progress.setCompleteTimes(progress.getCompleteTimes() + 1);
|
||||
log.info("任务完成, userId={}, taskCode={}, progressValue={}", userId, taskCode, progressValue);
|
||||
}
|
||||
|
||||
progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
|
||||
spinsUserTaskProgressDAO.updateById(progress);
|
||||
|
||||
log.info("任务进度更新成功, userId={}, taskCode={}, progressValue={}, progressRate={}",
|
||||
userId, taskCode, progressValue, progressRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或创建用户任务进度
|
||||
*/
|
||||
private SpinsUserTaskProgress getOrCreateProgress(Long userId, SpinsTaskConfig taskConfig, String cycleKey) {
|
||||
List<SpinsUserTaskProgress> progressList = spinsUserTaskProgressDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.eq(SpinsUserTaskProgress::getTaskCode, taskConfig.getTaskCode())
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
|
||||
);
|
||||
|
||||
SpinsUserTaskProgress progress = null;
|
||||
if (!progressList.isEmpty()) {
|
||||
progress = progressList.get(0);
|
||||
}
|
||||
|
||||
if (progress == null) {
|
||||
progress = new SpinsUserTaskProgress();
|
||||
progress.setUserId(userId);
|
||||
progress.setTaskId(taskConfig.getId());
|
||||
progress.setTaskCode(taskConfig.getTaskCode());
|
||||
progress.setCurrentValue(0);
|
||||
progress.setTargetValue(taskConfig.getTargetValue());
|
||||
progress.setProgressRate(BigDecimal.ZERO);
|
||||
progress.setTaskStatus(0);
|
||||
progress.setCycleType(taskConfig.getCycleType());
|
||||
progress.setCycleDate(LocalDate.now());
|
||||
progress.setCycleKey(cycleKey);
|
||||
progress.setCompleteTimes(0);
|
||||
progress.setRewardType(taskConfig.getRewardType());
|
||||
progress.setRewardValue(taskConfig.getRewardValue());
|
||||
progress.setCreateTime(new Timestamp(System.currentTimeMillis()));
|
||||
progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
|
||||
spinsUserTaskProgressDAO.insert(progress);
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算进度百分比
|
||||
*/
|
||||
private BigDecimal calculateProgressRate(Integer currentValue, Integer targetValue) {
|
||||
if (targetValue == null || targetValue == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return BigDecimal.valueOf(currentValue)
|
||||
.divide(BigDecimal.valueOf(targetValue), 4, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(100))
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期key
|
||||
*/
|
||||
private String getCurrentCycleKey(Integer cycleType) {
|
||||
LocalDate now = LocalDate.now();
|
||||
if (cycleType == 1) {
|
||||
// 每日任务:格式 yyyyMMdd
|
||||
return now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
} else if (cycleType == 2) {
|
||||
// 每周任务:格式 yyyyWw(例如:2025W03)
|
||||
int weekOfYear = now.getDayOfYear() / 7 + 1;
|
||||
return now.getYear() + "W" + String.format("%02d", weekOfYear);
|
||||
} else {
|
||||
// 一次性任务:固定标识
|
||||
return "ONCE";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskCO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 查询用户任务列表执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskQueryExe {
|
||||
|
||||
private final SpinsTaskConfigDAO spinsTaskConfigDAO;
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
|
||||
/**
|
||||
* 执行查询用户任务列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 任务列表
|
||||
*/
|
||||
public List<SpinsTaskCO> execute(Long userId) {
|
||||
// 1. 查询所有启用的任务配置
|
||||
List<SpinsTaskConfig> taskConfigs = spinsTaskConfigDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsTaskConfig>()
|
||||
.eq(SpinsTaskConfig::getStatus, 1)
|
||||
.orderByAsc(SpinsTaskConfig::getSortOrder)
|
||||
);
|
||||
|
||||
if (CollectionUtils.isEmpty(taskConfigs)) {
|
||||
log.warn("未查询到启用的任务配置");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 2. 获取当前周期key
|
||||
String cycleKey = getCurrentCycleKey();
|
||||
|
||||
// 3. 查询用户任务进度
|
||||
List<String> taskCodes = taskConfigs.stream()
|
||||
.map(SpinsTaskConfig::getTaskCode)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<SpinsUserTaskProgress> progressList = spinsUserTaskProgressDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.in(SpinsUserTaskProgress::getTaskCode, taskCodes)
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
|
||||
);
|
||||
|
||||
Map<String, SpinsUserTaskProgress> progressMap = progressList.stream()
|
||||
.collect(Collectors.toMap(SpinsUserTaskProgress::getTaskCode, p -> p, (p1, p2) -> p1));
|
||||
|
||||
// 4. 组装返回数据
|
||||
List<SpinsTaskCO> result = new ArrayList<>();
|
||||
for (SpinsTaskConfig config : taskConfigs) {
|
||||
SpinsTaskCO taskCO = buildTaskCO(config, progressMap.get(config.getTaskCode()));
|
||||
result.add(taskCO);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建任务CO对象
|
||||
*/
|
||||
private SpinsTaskCO buildTaskCO(SpinsTaskConfig config, SpinsUserTaskProgress progress) {
|
||||
SpinsTaskCO taskCO = new SpinsTaskCO();
|
||||
taskCO.setTaskId(config.getId());
|
||||
taskCO.setTaskCode(config.getTaskCode());
|
||||
taskCO.setTaskName(config.getTaskName());
|
||||
taskCO.setTaskType(config.getTaskType());
|
||||
taskCO.setTaskDesc(config.getTaskDesc());
|
||||
taskCO.setIconUrl(config.getIconUrl());
|
||||
taskCO.setTargetType(config.getTargetType());
|
||||
taskCO.setTargetValue(config.getTargetValue());
|
||||
taskCO.setTargetUnit(config.getTargetUnit());
|
||||
taskCO.setRewardType(config.getRewardType());
|
||||
taskCO.setRewardValue(config.getRewardValue());
|
||||
|
||||
if (progress != null) {
|
||||
taskCO.setCurrentValue(progress.getCurrentValue());
|
||||
taskCO.setTaskStatus(progress.getTaskStatus());
|
||||
taskCO.setProgressRate(progress.getProgressRate());
|
||||
taskCO.setCompleteTime(progress.getCompleteTime());
|
||||
} else {
|
||||
// 未开始的任务
|
||||
taskCO.setCurrentValue(0);
|
||||
taskCO.setTaskStatus(0);
|
||||
taskCO.setProgressRate(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
return taskCO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期key(每日任务格式:yyyyMMdd)
|
||||
*/
|
||||
private String getCurrentCycleKey() {
|
||||
return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
package com.red.circle.other.app.command;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskRecord;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskRecordDAO;
|
||||
import com.red.circle.other.inner.endpoint.activity.LotteryTicketClient;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 领取任务奖励执行器
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskReceiveRewardExe {
|
||||
|
||||
private final SpinsTaskConfigDAO spinsTaskConfigDAO;
|
||||
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
|
||||
private final SpinsUserTaskRecordDAO spinsUserTaskRecordDAO;
|
||||
private final LotteryTicketClient lotteryTicketClient;
|
||||
|
||||
/**
|
||||
* 执行领取任务奖励
|
||||
*
|
||||
* @param cmd 领取奖励命令
|
||||
* @return 奖励信息
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SpinsTaskRewardCO execute(SpinsTaskReceiveRewardCmd cmd) {
|
||||
Long userId = cmd.getUserId();
|
||||
String taskCode = cmd.getTaskCode();
|
||||
|
||||
// 1. 查询任务配置
|
||||
List<SpinsTaskConfig> spinsTaskConfigs = spinsTaskConfigDAO.selectList(
|
||||
new LambdaQueryWrapper<SpinsTaskConfig>()
|
||||
.eq(SpinsTaskConfig::getTaskCode, taskCode)
|
||||
.eq(SpinsTaskConfig::getStatus, 1)
|
||||
);
|
||||
|
||||
if (spinsTaskConfigs.isEmpty()) {
|
||||
throw new RuntimeException("任务不存在或已下线");
|
||||
}
|
||||
SpinsTaskConfig taskConfig = spinsTaskConfigs.get(0);
|
||||
|
||||
// 2. 查询用户任务进度
|
||||
String cycleKey = getCurrentCycleKey();
|
||||
SpinsUserTaskProgress progress = spinsUserTaskProgressDAO.selectById(
|
||||
new LambdaQueryWrapper<SpinsUserTaskProgress>()
|
||||
.eq(SpinsUserTaskProgress::getUserId, userId)
|
||||
.eq(SpinsUserTaskProgress::getTaskCode, taskCode)
|
||||
.eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
|
||||
);
|
||||
|
||||
if (progress == null) {
|
||||
throw new RuntimeException("任务未开始");
|
||||
}
|
||||
|
||||
// 3. 校验任务状态
|
||||
if (progress.getTaskStatus() == 0) {
|
||||
throw new RuntimeException("任务未完成,无法领取奖励");
|
||||
}
|
||||
|
||||
if (progress.getTaskStatus() == 2) {
|
||||
throw new RuntimeException("奖励已领取,请勿重复领取");
|
||||
}
|
||||
|
||||
// 4. 发放抽奖券
|
||||
List<Long> ticketIds = new ArrayList<>();
|
||||
try {
|
||||
for (int i = 0; i < taskConfig.getRewardValue(); i++) {
|
||||
Long ticketId = lotteryTicketClient.addTicket(
|
||||
userId,
|
||||
1,
|
||||
"SPINS_TASK",
|
||||
taskCode
|
||||
).getBody();
|
||||
ticketIds.add(ticketId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发放抽奖券失败, userId={}, taskCode={}", userId, taskCode, e);
|
||||
throw new RuntimeException("发放奖励失败,请稍后重试");
|
||||
}
|
||||
|
||||
// 5. 更新任务进度状态
|
||||
progress.setTaskStatus(2);
|
||||
progress.setReceiveTime(TimestampUtils.now());
|
||||
progress.setLotteryTicketIds(String.join(",", ticketIds.stream().map(String::valueOf).toArray(String[]::new)));
|
||||
progress.setUpdateTime(TimestampUtils.now());
|
||||
spinsUserTaskProgressDAO.updateById(progress);
|
||||
|
||||
// 6. 记录任务完成记录
|
||||
SpinsUserTaskRecord record = new SpinsUserTaskRecord();
|
||||
record.setUserId(userId);
|
||||
record.setTaskId(taskConfig.getId());
|
||||
record.setTaskCode(taskCode);
|
||||
record.setTaskName(taskConfig.getTaskName());
|
||||
record.setCompleteValue(progress.getCurrentValue());
|
||||
record.setCompleteTime(progress.getCompleteTime());
|
||||
record.setCycleKey(cycleKey);
|
||||
record.setRewardType(taskConfig.getRewardType());
|
||||
record.setRewardValue(taskConfig.getRewardValue());
|
||||
record.setLotteryActivityId(taskConfig.getLotteryActivityId());
|
||||
record.setLotteryTicketIds(progress.getLotteryTicketIds());
|
||||
record.setReceiveStatus(1);
|
||||
record.setCreateTime(TimestampUtils.now());
|
||||
spinsUserTaskRecordDAO.insert(record);
|
||||
|
||||
// 7. 组装返回结果
|
||||
SpinsTaskRewardCO rewardCO = new SpinsTaskRewardCO();
|
||||
rewardCO.setTaskCode(taskCode);
|
||||
rewardCO.setTaskName(taskConfig.getTaskName());
|
||||
rewardCO.setRewardType(taskConfig.getRewardType());
|
||||
rewardCO.setRewardValue(taskConfig.getRewardValue());
|
||||
rewardCO.setLotteryTicketIds(ticketIds);
|
||||
rewardCO.setReceiveTime(TimestampUtils.now());
|
||||
|
||||
log.info("任务奖励领取成功, userId={}, taskCode={}, ticketIds={}", userId, taskCode, ticketIds);
|
||||
return rewardCO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期key(每日任务格式:yyyyMMdd)
|
||||
*/
|
||||
private String getCurrentCycleKey() {
|
||||
return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
}
|
||||
}
|
||||
@ -184,15 +184,11 @@ public class TaskListener implements MessageListener {
|
||||
if ("10".equals(inc) || Integer.parseInt(inc) >= 10) {
|
||||
// 更新任务状态的逻辑 直接更新
|
||||
updateTaskStatus(eventBody);
|
||||
//判断一下是否有工会裂变任务
|
||||
// checkMemberActive(eventBody.getUserId(), MemberActiveEnum.TASK_2);
|
||||
} else {
|
||||
redisService.increment(redisKey, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("处理任务-1上麦10分钟: " + eventBody);
|
||||
// task list 接口单独处理
|
||||
}
|
||||
|
||||
private void handleTask99(TaskApprovalEvent eventBody) {
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.red.circle.other.app.service.task;
|
||||
|
||||
import com.red.circle.other.app.command.SpinsTaskQueryExe;
|
||||
import com.red.circle.other.app.command.SpinsTaskReceiveRewardExe;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskCO;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd;
|
||||
import com.red.circle.other.app.service.SpinsTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spins任务服务实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsTaskServiceImpl implements SpinsTaskService {
|
||||
|
||||
private final SpinsTaskQueryExe spinsTaskQueryExe;
|
||||
|
||||
private final SpinsTaskReceiveRewardExe spinsTaskReceiveRewardExe;
|
||||
|
||||
@Override
|
||||
public List<SpinsTaskCO> getUserTaskList(Long userId) {
|
||||
log.info("执行获取用户任务列表, userId={}", userId);
|
||||
return spinsTaskQueryExe.execute(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpinsTaskRewardCO receiveTaskReward(SpinsTaskReceiveRewardCmd cmd) {
|
||||
log.info("执行领取任务奖励, userId={}, taskCode={}", cmd.getUserId(), cmd.getTaskCode());
|
||||
return spinsTaskReceiveRewardExe.execute(cmd);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.red.circle.other.app.service.task;
|
||||
|
||||
import com.red.circle.other.app.command.SpinsTaskProgressInitExe;
|
||||
import com.red.circle.other.app.command.SpinsTaskProgressIncrementExe;
|
||||
import com.red.circle.other.app.command.SpinsTaskProgressResetExe;
|
||||
import com.red.circle.other.app.command.SpinsTaskProgressUpdateExe;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskProgressUpdateCmd;
|
||||
import com.red.circle.other.app.service.SpinsUserTaskProgressService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Spins用户任务进度服务实现
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SpinsUserTaskProgressServiceImpl implements SpinsUserTaskProgressService {
|
||||
|
||||
private final SpinsTaskProgressUpdateExe spinsTaskProgressUpdateExe;
|
||||
private final SpinsTaskProgressIncrementExe spinsTaskProgressIncrementExe;
|
||||
private final SpinsTaskProgressResetExe spinsTaskProgressResetExe;
|
||||
private final SpinsTaskProgressInitExe spinsTaskProgressInitExe;
|
||||
|
||||
@Override
|
||||
public void updateTaskProgress(SpinsTaskProgressUpdateCmd cmd) {
|
||||
log.info("更新用户任务进度, userId={}, taskCode={}, progressValue={}",
|
||||
cmd.getUserId(), cmd.getTaskCode(), cmd.getProgressValue());
|
||||
spinsTaskProgressUpdateExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementTaskProgress(Long userId, String taskCode, Integer incrementValue) {
|
||||
log.info("增加用户任务进度, userId={}, taskCode={}, incrementValue={}",
|
||||
userId, taskCode, incrementValue);
|
||||
spinsTaskProgressIncrementExe.execute(userId, taskCode, incrementValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDailyTasks(Long userId) {
|
||||
log.info("重置用户每日任务, userId={}", userId);
|
||||
spinsTaskProgressResetExe.execute(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initUserTaskProgress(Long userId, String taskCode) {
|
||||
log.info("初始化用户任务进度, userId={}, taskCode={}", userId, taskCode);
|
||||
spinsTaskProgressInitExe.execute(userId, taskCode);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package com.red.circle.other.app.dto.clientobject;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Spins任务客户端对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
public class SpinsTaskCO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
*/
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 任务编码
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 任务类型:1-开麦任务,2-送礼任务,3-邀请任务
|
||||
*/
|
||||
private Integer taskType;
|
||||
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
private String taskDesc;
|
||||
|
||||
/**
|
||||
* 任务图标
|
||||
*/
|
||||
private String iconUrl;
|
||||
|
||||
/**
|
||||
* 目标类型:MIC_TIME-开麦时长,SEND_GIFT-送礼,INVITE_USER-邀请用户
|
||||
*/
|
||||
private String targetType;
|
||||
|
||||
/**
|
||||
* 目标值
|
||||
*/
|
||||
private Integer targetValue;
|
||||
|
||||
/**
|
||||
* 目标单位:MINUTES-分钟,COUNT-次数,HOURS-小时
|
||||
*/
|
||||
private String targetUnit;
|
||||
|
||||
/**
|
||||
* 当前进度值
|
||||
*/
|
||||
private Integer currentValue;
|
||||
|
||||
/**
|
||||
* 进度百分比
|
||||
*/
|
||||
private BigDecimal progressRate;
|
||||
|
||||
/**
|
||||
* 任务状态:0-进行中,1-已完成,2-已领取奖励
|
||||
*/
|
||||
private Integer taskStatus;
|
||||
|
||||
/**
|
||||
* 奖励类型:1-抽奖券
|
||||
*/
|
||||
private Integer rewardType;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Integer rewardValue;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private Timestamp completeTime;
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.red.circle.other.app.dto.clientobject;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spins任务奖励客户端对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
public class SpinsTaskRewardCO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务编码
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 奖励类型:1-抽奖券
|
||||
*/
|
||||
private Integer rewardType;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Integer rewardValue;
|
||||
|
||||
/**
|
||||
* 抽奖券ID列表
|
||||
*/
|
||||
private List<Long> lotteryTicketIds;
|
||||
|
||||
/**
|
||||
* 领取时间
|
||||
*/
|
||||
private Timestamp receiveTime;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.red.circle.other.app.dto.cmd;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 更新任务进度命令
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
public class SpinsTaskProgressUpdateCmd implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
@NotBlank(message = "任务编码不能为空")
|
||||
private String taskCode;
|
||||
|
||||
@NotNull(message = "进度值不能为空")
|
||||
private Integer progressValue;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private String bizType;
|
||||
|
||||
/**
|
||||
* 业务ID
|
||||
*/
|
||||
private String bizId;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.red.circle.other.app.dto.cmd;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 领取任务奖励命令
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
public class SpinsTaskReceiveRewardCmd implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
@NotBlank(message = "任务编码不能为空")
|
||||
private String taskCode;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.red.circle.other.app.service;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskCO;
|
||||
import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO;
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Spins任务服务接口
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
public interface SpinsTaskService {
|
||||
|
||||
/**
|
||||
* 获取用户任务列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 任务列表
|
||||
*/
|
||||
List<SpinsTaskCO> getUserTaskList(Long userId);
|
||||
|
||||
/**
|
||||
* 领取任务奖励
|
||||
*
|
||||
* @param cmd 领取奖励命令
|
||||
* @return 奖励信息
|
||||
*/
|
||||
SpinsTaskRewardCO receiveTaskReward(SpinsTaskReceiveRewardCmd cmd);
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.red.circle.other.app.service;
|
||||
|
||||
import com.red.circle.other.app.dto.cmd.SpinsTaskProgressUpdateCmd;
|
||||
|
||||
/**
|
||||
* Spins用户任务进度服务接口
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
public interface SpinsUserTaskProgressService {
|
||||
|
||||
/**
|
||||
* 更新用户任务进度
|
||||
*
|
||||
* @param cmd 更新进度命令
|
||||
*/
|
||||
void updateTaskProgress(SpinsTaskProgressUpdateCmd cmd);
|
||||
|
||||
/**
|
||||
* 增加用户任务进度
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param taskCode 任务编码
|
||||
* @param incrementValue 增加值
|
||||
*/
|
||||
void incrementTaskProgress(Long userId, String taskCode, Integer incrementValue);
|
||||
|
||||
/**
|
||||
* 重置用户每日任务
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void resetDailyTasks(Long userId);
|
||||
|
||||
/**
|
||||
* 初始化用户任务进度
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param taskCode 任务编码
|
||||
*/
|
||||
void initUserTaskProgress(Long userId, String taskCode);
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.red.circle.other.infra.database.rds.dao.task;
|
||||
|
||||
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
|
||||
|
||||
/**
|
||||
* Spins任务配置DAO
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
public interface SpinsTaskConfigDAO extends BaseDAO<SpinsTaskConfig> {
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.red.circle.other.infra.database.rds.dao.task;
|
||||
|
||||
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
|
||||
|
||||
/**
|
||||
* Spins用户任务进度DAO
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
public interface SpinsUserTaskProgressDAO extends BaseDAO<SpinsUserTaskProgress> {
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.red.circle.other.infra.database.rds.dao.task;
|
||||
|
||||
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskRecord;
|
||||
|
||||
/**
|
||||
* Spins用户任务完成记录DAO
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
public interface SpinsUserTaskRecordDAO extends BaseDAO<SpinsUserTaskRecord> {
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
package com.red.circle.other.infra.database.rds.entity.task;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Spins任务配置实体
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
@TableName("spins_task_config")
|
||||
public class SpinsTaskConfig {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 任务编码(唯一标识)
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 任务类型:1-开麦任务,2-送礼任务,3-邀请任务
|
||||
*/
|
||||
private Integer taskType;
|
||||
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
private String taskDesc;
|
||||
|
||||
/**
|
||||
* 任务图标
|
||||
*/
|
||||
private String iconUrl;
|
||||
|
||||
/**
|
||||
* 目标类型:MIC_TIME-开麦时长,SEND_GIFT-送礼,INVITE_USER-邀请用户
|
||||
*/
|
||||
private String targetType;
|
||||
|
||||
/**
|
||||
* 目标值(如:15分钟=15,送3个礼物=3)
|
||||
*/
|
||||
private Integer targetValue;
|
||||
|
||||
/**
|
||||
* 目标单位:MINUTES-分钟,COUNT-次数,HOURS-小时
|
||||
*/
|
||||
private String targetUnit;
|
||||
|
||||
/**
|
||||
* 奖励类型:1-抽奖券
|
||||
*/
|
||||
private Integer rewardType;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Integer rewardValue;
|
||||
|
||||
/**
|
||||
* 关联的抽奖活动ID
|
||||
*/
|
||||
private Long lotteryActivityId;
|
||||
|
||||
/**
|
||||
* 周期类型:1-每日,2-每周,3-一次性
|
||||
*/
|
||||
private Integer cycleType;
|
||||
|
||||
/**
|
||||
* 重置时间(每日任务)
|
||||
*/
|
||||
private String resetTime;
|
||||
|
||||
/**
|
||||
* 每周期最大完成次数
|
||||
*/
|
||||
private Integer maxTimes;
|
||||
|
||||
/**
|
||||
* 状态:0-禁用,1-启用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortOrder;
|
||||
|
||||
/**
|
||||
* 任务开始时间
|
||||
*/
|
||||
private Timestamp startTime;
|
||||
|
||||
/**
|
||||
* 任务结束时间
|
||||
*/
|
||||
private Timestamp endTime;
|
||||
|
||||
/**
|
||||
* 扩展配置(JSON格式)
|
||||
*/
|
||||
private String extraConfig;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Timestamp createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Timestamp updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updatedBy;
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package com.red.circle.other.infra.database.rds.entity.task;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* Spins用户任务进度实体
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
@TableName("spins_user_task_progress")
|
||||
public class SpinsUserTaskProgress {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 任务配置ID
|
||||
*/
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 任务编码
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 当前进度值
|
||||
*/
|
||||
private Integer currentValue;
|
||||
|
||||
/**
|
||||
* 目标值(冗余,方便查询)
|
||||
*/
|
||||
private Integer targetValue;
|
||||
|
||||
/**
|
||||
* 进度百分比
|
||||
*/
|
||||
private BigDecimal progressRate;
|
||||
|
||||
/**
|
||||
* 任务状态:0-进行中,1-已完成,2-已领取奖励
|
||||
*/
|
||||
private Integer taskStatus;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private Timestamp completeTime;
|
||||
|
||||
/**
|
||||
* 领取奖励时间
|
||||
*/
|
||||
private Timestamp receiveTime;
|
||||
|
||||
/**
|
||||
* 周期类型:1-每日,2-每周,3-一次性
|
||||
*/
|
||||
private Integer cycleType;
|
||||
|
||||
/**
|
||||
* 周期日期(用于每日任务)
|
||||
*/
|
||||
private LocalDate cycleDate;
|
||||
|
||||
/**
|
||||
* 周期标识:如20250121,202503W1
|
||||
*/
|
||||
private String cycleKey;
|
||||
|
||||
/**
|
||||
* 当前周期完成次数
|
||||
*/
|
||||
private Integer completeTimes;
|
||||
|
||||
/**
|
||||
* 奖励类型
|
||||
*/
|
||||
private Integer rewardType;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Integer rewardValue;
|
||||
|
||||
/**
|
||||
* 已发放的抽奖券ID列表(逗号分隔)
|
||||
*/
|
||||
private String lotteryTicketIds;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Timestamp createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Timestamp updateTime;
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
package com.red.circle.other.infra.database.rds.entity.task;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Spins用户任务完成记录实体
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-21
|
||||
*/
|
||||
@Data
|
||||
@TableName("spins_user_task_record")
|
||||
public class SpinsUserTaskRecord {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 任务配置ID
|
||||
*/
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 任务编码
|
||||
*/
|
||||
private String taskCode;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 完成值
|
||||
*/
|
||||
private Integer completeValue;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private Timestamp completeTime;
|
||||
|
||||
/**
|
||||
* 周期标识
|
||||
*/
|
||||
private String cycleKey;
|
||||
|
||||
/**
|
||||
* 奖励类型
|
||||
*/
|
||||
private Integer rewardType;
|
||||
|
||||
/**
|
||||
* 奖励数量
|
||||
*/
|
||||
private Integer rewardValue;
|
||||
|
||||
/**
|
||||
* 抽奖活动ID
|
||||
*/
|
||||
private Long lotteryActivityId;
|
||||
|
||||
/**
|
||||
* 抽奖券ID列表
|
||||
*/
|
||||
private String lotteryTicketIds;
|
||||
|
||||
/**
|
||||
* 领取状态:1-已发放,2-发放失败
|
||||
*/
|
||||
private Integer receiveStatus;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private String bizType;
|
||||
|
||||
/**
|
||||
* 业务ID
|
||||
*/
|
||||
private String bizId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Timestamp createTime;
|
||||
}
|
||||
@ -36,8 +36,8 @@ public class LotteryTicketClientEndpoint implements LotteryTicketClientApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultResponse<Boolean> addTicket(Long userId, Integer count, String source, String sourceId) {
|
||||
Boolean result = lotteryTicketClientService.addTicket(userId, count, source, sourceId);
|
||||
public ResultResponse<Long> addTicket(Long userId, Integer count, String source, String sourceId) {
|
||||
Long result = lotteryTicketClientService.addTicket(userId, count, source, sourceId);
|
||||
return ResultResponse.success(result);
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,6 @@ public interface LotteryTicketClientService {
|
||||
* @param sourceId 来源ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean addTicket(Long userId, Integer count, String source, String sourceId);
|
||||
Long addTicket(Long userId, Integer count, String source, String sourceId);
|
||||
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ public class LotteryTicketClientServiceImpl implements LotteryTicketClientServic
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean addTicket(Long userId, Integer count, String source, String sourceId) {
|
||||
public Long addTicket(Long userId, Integer count, String source, String sourceId) {
|
||||
LotteryTicket ticket = new LotteryTicket();
|
||||
ticket.setUserId(userId);
|
||||
ticket.setTicketSource(source != null ? source : "SYSTEM");
|
||||
@ -107,7 +107,7 @@ public class LotteryTicketClientServiceImpl implements LotteryTicketClientServic
|
||||
ticketRecord.setRemark("系统发放");
|
||||
lotteryTicketRecordService.save(ticketRecord);
|
||||
|
||||
return true;
|
||||
return ticket.getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user