新增admin 任务
This commit is contained in:
parent
323505ca48
commit
79ef0e68f6
@ -0,0 +1,31 @@
|
||||
package com.red.circle.other.adapter.app;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskSummaryCO;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
|
||||
import com.red.circle.other.app.service.AdminTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 管理员任务控制器
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/task")
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskRestController {
|
||||
|
||||
private final AdminTaskService adminTaskService;
|
||||
|
||||
/**
|
||||
* 查询任务进度
|
||||
*/
|
||||
@PostMapping("/query")
|
||||
public AdminTaskSummaryCO queryTaskSummary(@Validated @RequestBody AdminTaskQueryCmd cmd) {
|
||||
AdminTaskSummaryCO summary = adminTaskService.queryTaskSummary(cmd);
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.red.circle.other.app.command.admintask;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskStatus;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskType;
|
||||
import com.red.circle.other.domain.gateway.AdminTaskGateway;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskInitCmd;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理员任务初始化执行器
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskInitCmdExe {
|
||||
|
||||
private final AdminTaskGateway adminTaskGateway;
|
||||
|
||||
public void execute(AdminTaskInitCmd cmd) {
|
||||
// 检查是否已初始化
|
||||
boolean exists = adminTaskGateway.existsByUserIdAndCycle(cmd.getUserId(), cmd.getCycleStartDate());
|
||||
if (exists) {
|
||||
throw new RuntimeException("该周期任务已初始化");
|
||||
}
|
||||
|
||||
// 批量创建5个任务记录
|
||||
List<AdminTaskRecord> tasks = new ArrayList<>();
|
||||
for (AdminTaskType taskType : AdminTaskType.values()) {
|
||||
AdminTaskRecord record = new AdminTaskRecord();
|
||||
record.setUserId(cmd.getUserId());
|
||||
record.setUserRole("ADMIN");
|
||||
record.setCycleStartDate(cmd.getCycleStartDate());
|
||||
record.setCycleEndDate(cmd.getCycleEndDate());
|
||||
record.setTaskType(taskType.getCode());
|
||||
record.setTargetCount(taskType.getDefaultTarget());
|
||||
record.setCompletedCount(0);
|
||||
record.setStatus(AdminTaskStatus.IN_PROGRESS.getCode());
|
||||
record.setCreateTime(LocalDateTime.now());
|
||||
record.setUpdateTime(LocalDateTime.now());
|
||||
tasks.add(record);
|
||||
}
|
||||
|
||||
adminTaskGateway.batchInsert(tasks);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package com.red.circle.other.app.command.admintask;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskType;
|
||||
import com.red.circle.other.domain.gateway.AdminTaskGateway;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 管理员任务进度更新执行器
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskProgressUpdateCmdExe {
|
||||
|
||||
private final AdminTaskGateway adminTaskGateway;
|
||||
|
||||
private static final int HOURS_PER_WORKING_DAY = 2;
|
||||
|
||||
public AdminTaskRecord execute(AdminTaskProgressUpdateCmd cmd) {
|
||||
LocalDate cycleStartDate = cmd.getCycleStartDate() != null ? cmd.getCycleStartDate() : getCurrentCycleStartDate();
|
||||
|
||||
// 校验任务类型
|
||||
AdminTaskType taskType = AdminTaskType.fromCode(cmd.getTaskType());
|
||||
if (taskType == null) {
|
||||
throw new RuntimeException("无效的任务类型: " + cmd.getTaskType());
|
||||
}
|
||||
|
||||
// 增量更新任务进度
|
||||
AdminTaskRecord updatedRecord = adminTaskGateway.incrementCompletedCount(
|
||||
cmd.getUserId(),
|
||||
cmd.getTaskType(),
|
||||
cycleStartDate,
|
||||
cmd.getIncrementValue()
|
||||
);
|
||||
|
||||
if (updatedRecord == null) {
|
||||
throw new RuntimeException("任务记录不存在");
|
||||
}
|
||||
|
||||
// 检查是否达到目标,更新状态
|
||||
if (updatedRecord.reachedTarget() && !updatedRecord.isCompleted()) {
|
||||
adminTaskGateway.markAsCompleted(cmd.getUserId(), cmd.getTaskType(), cycleStartDate);
|
||||
updatedRecord.setStatus("COMPLETED");
|
||||
}
|
||||
|
||||
// 特殊处理:麦克风使用时长影响工作天数
|
||||
if (AdminTaskType.MIC_USAGE.getCode().equals(cmd.getTaskType())) {
|
||||
int workingDays = updatedRecord.getCompletedCount() / HOURS_PER_WORKING_DAY;
|
||||
AdminTaskRecord workingDaysRecord = adminTaskGateway.updateCompletedCountAbsolute(
|
||||
cmd.getUserId(),
|
||||
AdminTaskType.WORKING_DAYS.getCode(),
|
||||
cycleStartDate,
|
||||
workingDays
|
||||
);
|
||||
|
||||
// 检查工作天数是否达到目标
|
||||
if (workingDaysRecord != null && workingDaysRecord.reachedTarget() && !workingDaysRecord.isCompleted()) {
|
||||
adminTaskGateway.markAsCompleted(cmd.getUserId(), AdminTaskType.WORKING_DAYS.getCode(), cycleStartDate);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期开始日期
|
||||
*/
|
||||
private LocalDate getCurrentCycleStartDate() {
|
||||
LocalDate now = LocalDate.now();
|
||||
int dayOfMonth = now.getDayOfMonth();
|
||||
|
||||
if (dayOfMonth <= 15) {
|
||||
return LocalDate.of(now.getYear(), now.getMonth(), 1);
|
||||
} else {
|
||||
return LocalDate.of(now.getYear(), now.getMonth(), 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.red.circle.other.app.command.admintask;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import com.red.circle.other.domain.gateway.AdminTaskGateway;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理员任务查询执行器
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskQueryCmdExe {
|
||||
|
||||
private final AdminTaskGateway adminTaskGateway;
|
||||
|
||||
public List<AdminTaskRecord> execute(AdminTaskQueryCmd cmd) {
|
||||
LocalDate cycleStartDate = cmd.getCycleStartDate() != null ? cmd.getCycleStartDate() : getCurrentCycleStartDate();
|
||||
return adminTaskGateway.findByUserIdAndCycle(cmd.getUserId(), cycleStartDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前周期开始日期
|
||||
*/
|
||||
private LocalDate getCurrentCycleStartDate() {
|
||||
LocalDate now = LocalDate.now();
|
||||
int dayOfMonth = now.getDayOfMonth();
|
||||
|
||||
if (dayOfMonth <= 15) {
|
||||
return LocalDate.of(now.getYear(), now.getMonth(), 1);
|
||||
} else {
|
||||
return LocalDate.of(now.getYear(), now.getMonth(), 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.red.circle.other.app.convertor;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskStatus;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskType;
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskRecordCO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 管理员任务转换器
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Component
|
||||
public class AdminTaskConvertor {
|
||||
|
||||
public AdminTaskRecordCO toRecordCO(AdminTaskRecord record) {
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AdminTaskRecordCO co = new AdminTaskRecordCO();
|
||||
co.setTaskType(record.getTaskType());
|
||||
co.setTargetCount(record.getTargetCount());
|
||||
co.setCompletedCount(record.getCompletedCount());
|
||||
co.setStatus(record.getStatus());
|
||||
co.setCompletionRate(record.getCompletionRate());
|
||||
|
||||
// 设置任务名称和单位
|
||||
AdminTaskType taskType = AdminTaskType.fromCode(record.getTaskType());
|
||||
if (taskType != null) {
|
||||
co.setTaskName(taskType.getName());
|
||||
co.setUnit(taskType.getUnit());
|
||||
}
|
||||
|
||||
// 设置状态名称
|
||||
AdminTaskStatus status = AdminTaskStatus.fromCode(record.getStatus());
|
||||
if (status != null) {
|
||||
co.setStatusName(status.getName());
|
||||
}
|
||||
|
||||
return co;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.red.circle.other.app.service;
|
||||
|
||||
import com.red.circle.other.app.command.admintask.AdminTaskInitCmdExe;
|
||||
import com.red.circle.other.app.command.admintask.AdminTaskProgressUpdateCmdExe;
|
||||
import com.red.circle.other.app.command.admintask.AdminTaskQueryCmdExe;
|
||||
import com.red.circle.other.app.convertor.AdminTaskConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskRecordCO;
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskSummaryCO;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskInitCmd;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 管理员任务服务实现
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskServiceImpl implements AdminTaskService {
|
||||
|
||||
private final AdminTaskInitCmdExe adminTaskInitCmdExe;
|
||||
private final AdminTaskProgressUpdateCmdExe adminTaskProgressUpdateCmdExe;
|
||||
private final AdminTaskQueryCmdExe adminTaskQueryCmdExe;
|
||||
private final AdminTaskConvertor adminTaskConvertor;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void initTasks(AdminTaskInitCmd cmd) {
|
||||
adminTaskInitCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AdminTaskRecordCO updateTaskProgress(AdminTaskProgressUpdateCmd cmd) {
|
||||
AdminTaskRecord record = adminTaskProgressUpdateCmdExe.execute(cmd);
|
||||
return adminTaskConvertor.toRecordCO(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminTaskSummaryCO queryTaskSummary(AdminTaskQueryCmd cmd) {
|
||||
List<AdminTaskRecord> records = adminTaskQueryCmdExe.execute(cmd);
|
||||
|
||||
// 转换为 CO
|
||||
List<AdminTaskRecordCO> taskCOList = records.stream()
|
||||
.map(adminTaskConvertor::toRecordCO)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 统计已完成任务数
|
||||
long completedCount = records.stream()
|
||||
.filter(AdminTaskRecord::isCompleted)
|
||||
.count();
|
||||
|
||||
// 构建汇总对象
|
||||
AdminTaskSummaryCO summary = new AdminTaskSummaryCO();
|
||||
summary.setUserId(cmd.getUserId());
|
||||
summary.setCompletedTaskCount((int) completedCount);
|
||||
summary.setTotalTaskCount(records.size());
|
||||
summary.setTasks(taskCOList);
|
||||
|
||||
// 设置周期信息
|
||||
if (!records.isEmpty()) {
|
||||
summary.setCycleStartDate(records.get(0).getCycleStartDate());
|
||||
summary.setCycleEndDate(records.get(0).getCycleEndDate());
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.red.circle.other.app.dto.clientobject;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 管理员任务记录客户端对象
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
public class AdminTaskRecordCO {
|
||||
|
||||
/**
|
||||
* 任务类型编码
|
||||
*/
|
||||
private String taskType;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 目标数量
|
||||
*/
|
||||
private Integer targetCount;
|
||||
|
||||
/**
|
||||
* 已完成数量
|
||||
*/
|
||||
private Integer completedCount;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 任务状态名称
|
||||
*/
|
||||
private String statusName;
|
||||
|
||||
/**
|
||||
* 完成率(百分比)
|
||||
*/
|
||||
private Double completionRate;
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.red.circle.other.app.dto.clientobject;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理员任务汇总客户端对象
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
public class AdminTaskSummaryCO {
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 周期开始日期
|
||||
*/
|
||||
private LocalDate cycleStartDate;
|
||||
|
||||
/**
|
||||
* 周期结束日期
|
||||
*/
|
||||
private LocalDate cycleEndDate;
|
||||
|
||||
/**
|
||||
* 已完成任务数
|
||||
*/
|
||||
private Integer completedTaskCount;
|
||||
|
||||
/**
|
||||
* 总任务数
|
||||
*/
|
||||
private Integer totalTaskCount;
|
||||
|
||||
/**
|
||||
* 任务列表
|
||||
*/
|
||||
private List<AdminTaskRecordCO> tasks;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.red.circle.other.app.dto.cmd;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 管理员任务初始化命令
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AdminTaskInitCmd extends AppExtCommand {
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 周期开始日期
|
||||
*/
|
||||
@NotNull(message = "周期开始日期不能为空")
|
||||
private LocalDate cycleStartDate;
|
||||
|
||||
/**
|
||||
* 周期结束日期
|
||||
*/
|
||||
@NotNull(message = "周期结束日期不能为空")
|
||||
private LocalDate cycleEndDate;
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.red.circle.other.app.dto.cmd;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 管理员任务进度更新命令
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AdminTaskProgressUpdateCmd extends AppExtCommand {
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
@NotBlank(message = "任务类型不能为空")
|
||||
private String taskType;
|
||||
|
||||
/**
|
||||
* 增量值
|
||||
*/
|
||||
@NotNull(message = "增量值不能为空")
|
||||
private Integer incrementValue;
|
||||
|
||||
/**
|
||||
* 周期开始日期(可选,默认当前周期)
|
||||
*/
|
||||
private LocalDate cycleStartDate;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.red.circle.other.app.dto.cmd;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 管理员任务查询命令
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
public class AdminTaskQueryCmd {
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 周期开始日期(可选,默认当前周期)
|
||||
*/
|
||||
private LocalDate cycleStartDate;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.red.circle.other.app.service;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskRecordCO;
|
||||
import com.red.circle.other.app.dto.clientobject.AdminTaskSummaryCO;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskInitCmd;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskProgressUpdateCmd;
|
||||
import com.red.circle.other.app.dto.cmd.AdminTaskQueryCmd;
|
||||
|
||||
/**
|
||||
* 管理员任务服务接口
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
public interface AdminTaskService {
|
||||
|
||||
/**
|
||||
* 初始化任务(批量创建5个任务)
|
||||
*/
|
||||
void initTasks(AdminTaskInitCmd cmd);
|
||||
|
||||
/**
|
||||
* 更新任务进度
|
||||
*/
|
||||
AdminTaskRecordCO updateTaskProgress(AdminTaskProgressUpdateCmd cmd);
|
||||
|
||||
/**
|
||||
* 查询任务汇总
|
||||
*/
|
||||
AdminTaskSummaryCO queryTaskSummary(AdminTaskQueryCmd cmd);
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
package com.red.circle.other.domain.admintask;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 管理员任务记录领域对象
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
public class AdminTaskRecord {
|
||||
|
||||
/**
|
||||
* 主键 ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户角色
|
||||
*/
|
||||
private String userRole;
|
||||
|
||||
/**
|
||||
* 任务周期开始日期
|
||||
*/
|
||||
private LocalDate cycleStartDate;
|
||||
|
||||
/**
|
||||
* 任务周期结束日期
|
||||
*/
|
||||
private LocalDate cycleEndDate;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
private String taskType;
|
||||
|
||||
/**
|
||||
* 目标数量
|
||||
*/
|
||||
private Integer targetCount;
|
||||
|
||||
/**
|
||||
* 已完成数量
|
||||
*/
|
||||
private Integer completedCount;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
private LocalDateTime completedAt;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 判断任务是否完成
|
||||
*/
|
||||
public boolean isCompleted() {
|
||||
return AdminTaskStatus.COMPLETED.getCode().equals(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断任务是否已达到目标
|
||||
*/
|
||||
public boolean reachedTarget() {
|
||||
return completedCount != null && targetCount != null && completedCount >= targetCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算完成率
|
||||
*/
|
||||
public double getCompletionRate() {
|
||||
if (targetCount == null || targetCount == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
if (completedCount == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return Math.min(100.0, (completedCount * 100.0) / targetCount);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.red.circle.other.domain.admintask;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 管理员任务状态枚举
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Getter
|
||||
public enum AdminTaskStatus {
|
||||
|
||||
/**
|
||||
* 进行中
|
||||
*/
|
||||
IN_PROGRESS("IN_PROGRESS", "进行中"),
|
||||
|
||||
/**
|
||||
* 已完成
|
||||
*/
|
||||
COMPLETED("COMPLETED", "已完成"),
|
||||
|
||||
/**
|
||||
* 已过期
|
||||
*/
|
||||
EXPIRED("EXPIRED", "已过期");
|
||||
|
||||
/**
|
||||
* 状态编码
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 状态名称
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
AdminTaskStatus(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 code 获取枚举
|
||||
*/
|
||||
public static AdminTaskStatus fromCode(String code) {
|
||||
for (AdminTaskStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.red.circle.other.domain.admintask;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 管理员任务类型枚举
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Getter
|
||||
public enum AdminTaskType {
|
||||
|
||||
/**
|
||||
* 麦克风使用时长
|
||||
*/
|
||||
MIC_USAGE("MIC_USAGE", "麦克风使用时长", 20, "小时"),
|
||||
|
||||
/**
|
||||
* 工作天数(2小时算1天)
|
||||
*/
|
||||
WORKING_DAYS("WORKING_DAYS", "工作天数", 10, "天"),
|
||||
|
||||
/**
|
||||
* 新绑定 BD Leader
|
||||
*/
|
||||
NEW_BD_LEADERS("NEW_BD_LEADERS", "新绑定 BD Leader", 1, "个"),
|
||||
|
||||
/**
|
||||
* 新绑定 BD
|
||||
*/
|
||||
NEW_BDS("NEW_BDS", "新绑定 BD", 3, "个"),
|
||||
|
||||
/**
|
||||
* 新绑定代理
|
||||
*/
|
||||
NEW_AGENCIES("NEW_AGENCIES", "新绑定代理", 5, "个");
|
||||
|
||||
/**
|
||||
* 任务类型编码
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* 默认目标值
|
||||
*/
|
||||
private final int defaultTarget;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private final String unit;
|
||||
|
||||
AdminTaskType(String code, String name, int defaultTarget, String unit) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.defaultTarget = defaultTarget;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 code 获取枚举
|
||||
*/
|
||||
public static AdminTaskType fromCode(String code) {
|
||||
for (AdminTaskType type : values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.red.circle.other.domain.gateway;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理员任务网关接口
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
public interface AdminTaskGateway {
|
||||
|
||||
/**
|
||||
* 批量创建任务记录
|
||||
*
|
||||
* @param records 任务记录列表
|
||||
*/
|
||||
void batchInsert(List<AdminTaskRecord> records);
|
||||
|
||||
/**
|
||||
* 查询用户指定周期的所有任务
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param cycleStartDate 周期开始日期
|
||||
* @return 任务记录列表
|
||||
*/
|
||||
List<AdminTaskRecord> findByUserIdAndCycle(Long userId, LocalDate cycleStartDate);
|
||||
|
||||
/**
|
||||
* 查询用户指定周期的特定任务类型
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param taskType 任务类型
|
||||
* @param cycleStartDate 周期开始日期
|
||||
* @return 任务记录
|
||||
*/
|
||||
AdminTaskRecord findByUserIdAndTaskTypeAndCycle(Long userId, String taskType, LocalDate cycleStartDate);
|
||||
|
||||
/**
|
||||
* 增量更新任务完成数量(原子操作)
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param taskType 任务类型
|
||||
* @param cycleStartDate 周期开始日期
|
||||
* @param incrementValue 增量值
|
||||
* @return 更新后的记录
|
||||
*/
|
||||
AdminTaskRecord incrementCompletedCount(Long userId, String taskType, LocalDate cycleStartDate, int incrementValue);
|
||||
|
||||
/**
|
||||
* 绝对值更新任务完成数量(用于工作天数计算)
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param taskType 任务类型
|
||||
* @param cycleStartDate 周期开始日期
|
||||
* @param absoluteValue 绝对值
|
||||
* @return 更新后的记录
|
||||
*/
|
||||
AdminTaskRecord updateCompletedCountAbsolute(Long userId, String taskType, LocalDate cycleStartDate, int absoluteValue);
|
||||
|
||||
/**
|
||||
* 更新任务状态为已完成
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param taskType 任务类型
|
||||
* @param cycleStartDate 周期开始日期
|
||||
*/
|
||||
void markAsCompleted(Long userId, String taskType, LocalDate cycleStartDate);
|
||||
|
||||
/**
|
||||
* 检查用户指定周期是否已初始化任务
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @param cycleStartDate 周期开始日期
|
||||
* @return 是否存在
|
||||
*/
|
||||
boolean existsByUserIdAndCycle(Long userId, LocalDate cycleStartDate);
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.red.circle.other.infra.database.mongo.document;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndexes;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 管理员任务记录 MongoDB 文档
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Data
|
||||
@Document(collection = "admin_task_record")
|
||||
@CompoundIndexes({
|
||||
@CompoundIndex(name = "uk_user_cycle_type", def = "{'user_id': 1, 'cycle_start_date': 1, 'task_type': 1}", unique = true),
|
||||
@CompoundIndex(name = "idx_user_role", def = "{'user_id': 1, 'user_role': 1}"),
|
||||
@CompoundIndex(name = "idx_cycle", def = "{'cycle_start_date': 1, 'cycle_end_date': 1}")
|
||||
})
|
||||
public class AdminTaskRecordDO {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Field("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Field("user_role")
|
||||
private String userRole;
|
||||
|
||||
@Field("cycle_start_date")
|
||||
private LocalDate cycleStartDate;
|
||||
|
||||
@Field("cycle_end_date")
|
||||
private LocalDate cycleEndDate;
|
||||
|
||||
@Field("task_type")
|
||||
@Indexed
|
||||
private String taskType;
|
||||
|
||||
@Field("target_count")
|
||||
private Integer targetCount;
|
||||
|
||||
@Field("completed_count")
|
||||
private Integer completedCount;
|
||||
|
||||
@Field("status")
|
||||
@Indexed
|
||||
private String status;
|
||||
|
||||
@Field("completed_at")
|
||||
private LocalDateTime completedAt;
|
||||
|
||||
@Field("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Field("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.red.circle.other.infra.database.mongo.repository;
|
||||
|
||||
import com.red.circle.other.infra.database.mongo.document.AdminTaskRecordDO;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 管理员任务记录 Repository
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Repository
|
||||
public interface AdminTaskRecordRepository extends MongoRepository<AdminTaskRecordDO, String> {
|
||||
|
||||
/**
|
||||
* 查询用户指定周期的所有任务
|
||||
*/
|
||||
List<AdminTaskRecordDO> findByUserIdAndCycleStartDate(Long userId, LocalDate cycleStartDate);
|
||||
|
||||
/**
|
||||
* 查询用户指定周期的特定任务类型
|
||||
*/
|
||||
Optional<AdminTaskRecordDO> findByUserIdAndTaskTypeAndCycleStartDate(Long userId, String taskType, LocalDate cycleStartDate);
|
||||
|
||||
/**
|
||||
* 检查是否存在
|
||||
*/
|
||||
boolean existsByUserIdAndCycleStartDate(Long userId, LocalDate cycleStartDate);
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
package com.red.circle.other.infra.gateway;
|
||||
|
||||
import com.red.circle.other.domain.admintask.AdminTaskRecord;
|
||||
import com.red.circle.other.domain.admintask.AdminTaskStatus;
|
||||
import com.red.circle.other.domain.gateway.AdminTaskGateway;
|
||||
import com.red.circle.other.infra.database.mongo.document.AdminTaskRecordDO;
|
||||
import com.red.circle.other.infra.database.mongo.repository.AdminTaskRecordRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 管理员任务网关实现
|
||||
*
|
||||
* @author tf
|
||||
* @date 2025-11-25
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AdminTaskGatewayImpl implements AdminTaskGateway {
|
||||
|
||||
private final AdminTaskRecordRepository adminTaskRecordRepository;
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
@Override
|
||||
public void batchInsert(List<AdminTaskRecord> records) {
|
||||
List<AdminTaskRecordDO> doList = records.stream()
|
||||
.map(this::toDO)
|
||||
.collect(Collectors.toList());
|
||||
adminTaskRecordRepository.saveAll(doList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminTaskRecord> findByUserIdAndCycle(Long userId, LocalDate cycleStartDate) {
|
||||
List<AdminTaskRecordDO> doList = adminTaskRecordRepository.findByUserIdAndCycleStartDate(userId, cycleStartDate);
|
||||
return doList.stream()
|
||||
.map(this::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminTaskRecord findByUserIdAndTaskTypeAndCycle(Long userId, String taskType, LocalDate cycleStartDate) {
|
||||
return adminTaskRecordRepository.findByUserIdAndTaskTypeAndCycleStartDate(userId, taskType, cycleStartDate)
|
||||
.map(this::toDomain)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminTaskRecord incrementCompletedCount(Long userId, String taskType, LocalDate cycleStartDate, int incrementValue) {
|
||||
Query query = Query.query(Criteria.where("user_id").is(userId)
|
||||
.and("task_type").is(taskType)
|
||||
.and("cycle_start_date").is(cycleStartDate));
|
||||
|
||||
Update update = new Update()
|
||||
.inc("completed_count", incrementValue)
|
||||
.set("update_time", LocalDateTime.now());
|
||||
|
||||
mongoTemplate.updateFirst(query, update, AdminTaskRecordDO.class);
|
||||
|
||||
return findByUserIdAndTaskTypeAndCycle(userId, taskType, cycleStartDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminTaskRecord updateCompletedCountAbsolute(Long userId, String taskType, LocalDate cycleStartDate, int absoluteValue) {
|
||||
Query query = Query.query(Criteria.where("user_id").is(userId)
|
||||
.and("task_type").is(taskType)
|
||||
.and("cycle_start_date").is(cycleStartDate));
|
||||
|
||||
Update update = new Update()
|
||||
.set("completed_count", absoluteValue)
|
||||
.set("update_time", LocalDateTime.now());
|
||||
|
||||
mongoTemplate.updateFirst(query, update, AdminTaskRecordDO.class);
|
||||
|
||||
return findByUserIdAndTaskTypeAndCycle(userId, taskType, cycleStartDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsCompleted(Long userId, String taskType, LocalDate cycleStartDate) {
|
||||
Query query = Query.query(Criteria.where("user_id").is(userId)
|
||||
.and("task_type").is(taskType)
|
||||
.and("cycle_start_date").is(cycleStartDate));
|
||||
|
||||
Update update = new Update()
|
||||
.set("status", AdminTaskStatus.COMPLETED.getCode())
|
||||
.set("completed_at", LocalDateTime.now())
|
||||
.set("update_time", LocalDateTime.now());
|
||||
|
||||
mongoTemplate.updateFirst(query, update, AdminTaskRecordDO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByUserIdAndCycle(Long userId, LocalDate cycleStartDate) {
|
||||
return adminTaskRecordRepository.existsByUserIdAndCycleStartDate(userId, cycleStartDate);
|
||||
}
|
||||
|
||||
private AdminTaskRecordDO toDO(AdminTaskRecord record) {
|
||||
AdminTaskRecordDO dobj = new AdminTaskRecordDO();
|
||||
dobj.setUserId(record.getUserId());
|
||||
dobj.setUserRole(record.getUserRole());
|
||||
dobj.setCycleStartDate(record.getCycleStartDate());
|
||||
dobj.setCycleEndDate(record.getCycleEndDate());
|
||||
dobj.setTaskType(record.getTaskType());
|
||||
dobj.setTargetCount(record.getTargetCount());
|
||||
dobj.setCompletedCount(record.getCompletedCount());
|
||||
dobj.setStatus(record.getStatus());
|
||||
dobj.setCompletedAt(record.getCompletedAt());
|
||||
dobj.setCreateTime(record.getCreateTime() != null ? record.getCreateTime() : LocalDateTime.now());
|
||||
dobj.setUpdateTime(record.getUpdateTime() != null ? record.getUpdateTime() : LocalDateTime.now());
|
||||
return dobj;
|
||||
}
|
||||
|
||||
private AdminTaskRecord toDomain(AdminTaskRecordDO dobj) {
|
||||
AdminTaskRecord record = new AdminTaskRecord();
|
||||
record.setId(dobj.getId() != null ? Long.parseLong(dobj.getId()) : null);
|
||||
record.setUserId(dobj.getUserId());
|
||||
record.setUserRole(dobj.getUserRole());
|
||||
record.setCycleStartDate(dobj.getCycleStartDate());
|
||||
record.setCycleEndDate(dobj.getCycleEndDate());
|
||||
record.setTaskType(dobj.getTaskType());
|
||||
record.setTargetCount(dobj.getTargetCount());
|
||||
record.setCompletedCount(dobj.getCompletedCount());
|
||||
record.setStatus(dobj.getStatus());
|
||||
record.setCompletedAt(dobj.getCompletedAt());
|
||||
record.setCreateTime(dobj.getCreateTime());
|
||||
record.setUpdateTime(dobj.getUpdateTime());
|
||||
return record;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user