feat: 优化目标任务生成逻辑,增加自定义重复规则支持

- 在GoalTaskService中添加对自定义重复规则的支持,允许用户指定生成任务的星期几。
- 增加日志记录,便于调试和监控任务生成过程。
- 确保生成的任务不会与现有任务冲突,提升任务管理的灵活性和准确性。
This commit is contained in:
2025-08-24 09:46:24 +08:00
parent cba56021de
commit 475f928990
2 changed files with 44 additions and 26 deletions

View File

@@ -33,6 +33,7 @@ export class GoalsService {
*/ */
async createGoal(userId: string, createGoalDto: CreateGoalDto): Promise<Goal> { async createGoal(userId: string, createGoalDto: CreateGoalDto): Promise<Goal> {
try { try {
this.logger.log(`createGoal: ${JSON.stringify(createGoalDto, null, 2)}`);
// 验证自定义重复规则 // 验证自定义重复规则
if (createGoalDto.repeatType === GoalRepeatType.CUSTOM && !createGoalDto.customRepeatRule) { if (createGoalDto.repeatType === GoalRepeatType.CUSTOM && !createGoalDto.customRepeatRule) {
throw new BadRequestException('自定义重复类型必须提供自定义重复规则'); throw new BadRequestException('自定义重复类型必须提供自定义重复规则');

View File

@@ -153,37 +153,54 @@ export class GoalTaskService {
const generateUntil = today.add(4, 'week'); // 提前生成4周的任务 const generateUntil = today.add(4, 'week'); // 提前生成4周的任务
const actualEndDate = endDate.isBefore(generateUntil) ? endDate : generateUntil; const actualEndDate = endDate.isBefore(generateUntil) ? endDate : generateUntil;
let current = startDate.startOf('isoWeek'); // 检查是否有自定义重复规则指定星期几
const weekdays = goal.customRepeatRule?.weekdays;
while (current.isSameOrBefore(actualEndDate)) { if (weekdays && weekdays.length > 0) {
const weekStart = current.startOf('isoWeek'); // 如果有指定星期几,按指定星期几生成任务
const weekEnd = current.endOf('isoWeek'); this.logger.log(`为目标 ${goal.title} 生成每周任务,指定星期几: ${weekdays}`);
// 检查是否已存在该周的任务 // 从今天开始生成,如果开始日期晚于今天则从开始日期开始
const existingTask = existingTasks.find(task => { let current = startDate.isBefore(today) ? today : startDate;
const taskWeekStart = dayjs(task.startDate).startOf('isoWeek');
return taskWeekStart.isSame(weekStart);
});
if (!existingTask && weekStart.isSameOrAfter(startDate)) { let generatedCount = 0;
const taskTitle = `${goal.title} - 第${current.isoWeek()}周 (${weekStart.format('MM-DD')}${weekEnd.format('MM-DD')})`;
await this.goalTaskModel.create({ while (current.isSameOrBefore(actualEndDate)) {
goalId: goal.id, const dayOfWeek = current.day(); // 0=周日, 6=周六
userId: goal.userId,
title: taskTitle,
description: `每周目标:完成${goal.frequency}`,
startDate: weekStart.toDate(),
endDate: weekEnd.toDate(),
targetCount: goal.frequency,
currentCount: 0,
status: TaskStatus.PENDING,
});
this.logger.log(`为目标 ${goal.title} 生成每周任务: ${taskTitle}`); if (weekdays.includes(dayOfWeek)) {
const taskDate = current.format('YYYY-MM-DD');
// 检查是否已存在该日期的任务
const existingTask = existingTasks.find(task =>
dayjs(task.startDate).format('YYYY-MM-DD') === taskDate
);
if (!existingTask) {
const weekDayNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const taskTitle = `${goal.title} - ${current.format('YYYY年MM月DD日')} ${weekDayNames[dayOfWeek]}`;
await this.goalTaskModel.create({
goalId: goal.id,
userId: goal.userId,
title: taskTitle,
description: `每周目标:完成${goal.frequency}`,
startDate: current.toDate(),
endDate: current.toDate(),
targetCount: goal.frequency,
currentCount: 0,
status: TaskStatus.PENDING,
});
generatedCount++;
this.logger.log(`为目标 ${goal.title} 生成每周任务: ${taskTitle}`);
}
}
current = current.add(1, 'day');
} }
current = current.add(1, 'week'); this.logger.log(`为目标 ${goal.title} 生成了 ${generatedCount} 个每周任务`);
} }
} }