feat: improve schedule auto-arrange functionality
- Add ScheduleConfig for configurable schedule parameters - Add updateParticipantCheckInStatus API for exception status persistence - Use configurable thresholds for group splitting and capacity warning - Add @Slf4j to MartialScheduleServiceImpl
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package org.springblade.modules.martial.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 赛程编排配置
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "martial.schedule")
|
||||
public class ScheduleConfig {
|
||||
|
||||
/**
|
||||
* 个人项目每组最大人数(超过此数量将自动拆分)
|
||||
*/
|
||||
private int maxPeoplePerGroup = 35;
|
||||
|
||||
/**
|
||||
* 拆分后每组目标人数
|
||||
*/
|
||||
private int targetPeoplePerGroup = 33;
|
||||
|
||||
/**
|
||||
* 默认每人比赛时长(分钟)
|
||||
*/
|
||||
private int defaultDurationPerPerson = 5;
|
||||
|
||||
/**
|
||||
* 容量利用率警告阈值(百分比)
|
||||
*/
|
||||
private int capacityWarningThreshold = 90;
|
||||
|
||||
/**
|
||||
* 是否允许容量超载(超载时仍继续编排)
|
||||
*/
|
||||
private boolean allowOverload = false;
|
||||
|
||||
/**
|
||||
* 上午时段开始时间
|
||||
*/
|
||||
private String morningStartTime = "08:00";
|
||||
|
||||
/**
|
||||
* 上午时段结束时间
|
||||
*/
|
||||
private String morningEndTime = "12:00";
|
||||
|
||||
/**
|
||||
* 下午时段开始时间
|
||||
*/
|
||||
private String afternoonStartTime = "14:00";
|
||||
|
||||
/**
|
||||
* 下午时段结束时间
|
||||
*/
|
||||
private String afternoonEndTime = "18:00";
|
||||
}
|
||||
@@ -167,4 +167,22 @@ public class MartialScheduleArrangeController extends BladeController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新参赛者签到状态
|
||||
*/
|
||||
@PostMapping("/update-check-in-status")
|
||||
@Operation(summary = "更新签到状态", description = "更新参赛者签到状态:未签到/已签到/异常")
|
||||
public R updateCheckInStatus(@RequestBody java.util.Map<String, Object> params) {
|
||||
try {
|
||||
Long participantId = Long.valueOf(String.valueOf(params.get("participantId")));
|
||||
String status = String.valueOf(params.get("status"));
|
||||
boolean success = scheduleService.updateParticipantCheckInStatus(participantId, status);
|
||||
return success ? R.success("状态更新成功") : R.fail("状态更新失败");
|
||||
} catch (Exception e) {
|
||||
log.error("更新签到状态失败", e);
|
||||
return R.fail("更新签到状态失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,4 +72,12 @@ public interface IMartialScheduleService extends IService<MartialSchedule> {
|
||||
*/
|
||||
boolean saveDispatch(org.springblade.modules.martial.pojo.dto.SaveDispatchDTO dto);
|
||||
|
||||
/**
|
||||
* 更新参赛者签到状态
|
||||
* @param participantId 参赛者ID
|
||||
* @param status 状态:未签到/已签到/异常
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean updateParticipantCheckInStatus(Long participantId, String status);
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.joda.time.DateTime;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.modules.martial.mapper.*;
|
||||
import org.springblade.modules.martial.pojo.entity.*;
|
||||
import org.springblade.modules.martial.config.ScheduleConfig;
|
||||
import org.springblade.modules.martial.service.IMartialScheduleArrangeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -50,6 +51,7 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
private final MartialCompetitionMapper competitionMapper;
|
||||
private final MartialVenueMapper venueMapper;
|
||||
private final MartialProjectMapper projectMapper;
|
||||
private final ScheduleConfig scheduleConfig;
|
||||
|
||||
@Override
|
||||
public List<Long> getUnlockedCompetitions() {
|
||||
@@ -450,7 +452,7 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
String categoryName = first.getCategory() != null ? first.getCategory() : "未分组";
|
||||
|
||||
// 计算单人时长
|
||||
int durationPerPerson = 5; // 默认5分钟/人
|
||||
int durationPerPerson = scheduleConfig.getDefaultDurationPerPerson();
|
||||
if (project.getEstimatedDuration() != null && project.getEstimatedDuration() > 0) {
|
||||
durationPerPerson = project.getEstimatedDuration();
|
||||
}
|
||||
@@ -459,12 +461,12 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
// 改进策略:根据人数动态拆分,确保能充分利用所有时间槽
|
||||
// 目标:让分组数量接近可用时间槽数量,实现均匀分配
|
||||
int maxPeoplePerGroup;
|
||||
if (members.size() <= 35) {
|
||||
if (members.size() <= scheduleConfig.getMaxPeoplePerGroup()) {
|
||||
// 35人以内不拆分
|
||||
maxPeoplePerGroup = members.size();
|
||||
} else {
|
||||
// 超过35人,按每组30-35人拆分
|
||||
maxPeoplePerGroup = 33; // 每组33人左右
|
||||
maxPeoplePerGroup = scheduleConfig.getTargetPeoplePerGroup();
|
||||
}
|
||||
|
||||
if (members.size() <= maxPeoplePerGroup) {
|
||||
@@ -551,7 +553,7 @@ public class MartialScheduleArrangeServiceImpl implements IMartialScheduleArrang
|
||||
double utilizationRate = totalCapacity > 0 ? (totalDuration * 100.0 / totalCapacity) : 0;
|
||||
log.info("预计容量利用率: {}%", (int)utilizationRate);
|
||||
|
||||
if (utilizationRate > 90) {
|
||||
if (utilizationRate > scheduleConfig.getCapacityWarningThreshold()) {
|
||||
log.warn("⚠️ 容量利用率超过90%,可能导致分配困难,建议增加场地或延长比赛时间");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.springblade.modules.martial.pojo.vo.ScheduleGroupDetailVO;
|
||||
import org.springblade.modules.martial.mapper.MartialScheduleMapper;
|
||||
import org.springblade.modules.martial.service.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -28,6 +29,7 @@ import java.util.stream.Collectors;
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MartialScheduleServiceImpl extends ServiceImpl<MartialScheduleMapper, MartialSchedule> implements IMartialScheduleService {
|
||||
|
||||
@@ -598,4 +600,25 @@ public class MartialScheduleServiceImpl extends ServiceImpl<MartialScheduleMappe
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateParticipantCheckInStatus(Long participantId, String status) {
|
||||
if (participantId == null || status == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MartialScheduleParticipant participant = scheduleParticipantMapper.selectById(participantId);
|
||||
if (participant == null) {
|
||||
log.warn("参赛者不存在, participantId: {}", participantId);
|
||||
return false;
|
||||
}
|
||||
|
||||
participant.setCheckInStatus(status);
|
||||
int result = scheduleParticipantMapper.updateById(participant);
|
||||
|
||||
log.info("更新参赛者签到状态: participantId={}, status={}, result={}", participantId, status, result);
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -332,3 +332,12 @@ blade:
|
||||
#分库分表配置
|
||||
sharding:
|
||||
enabled: false
|
||||
|
||||
# 赛程编排配置
|
||||
martial:
|
||||
schedule:
|
||||
max-people-per-group: 35
|
||||
target-people-per-group: 33
|
||||
default-duration-per-person: 5
|
||||
capacity-warning-threshold: 90
|
||||
allow-overload: false
|
||||
|
||||
Reference in New Issue
Block a user