|
@@ -44,6 +44,7 @@ import java.time.LocalDate;
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalTime;
|
|
import java.time.LocalTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@@ -60,6 +61,10 @@ import java.util.stream.Collectors;
|
|
@Slf4j
|
|
@Slf4j
|
|
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
|
|
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
|
|
|
|
|
|
|
|
+ // 定义午休时间段(12:00-13:00)
|
|
|
|
+ private static final LocalTime LUNCH_START = LocalTime.of(12, 0);
|
|
|
|
+ private static final LocalTime LUNCH_END = LocalTime.of(13, 0);
|
|
|
|
+
|
|
@Value(value = "${upload.path}")
|
|
@Value(value = "${upload.path}")
|
|
private String path;
|
|
private String path;
|
|
@Resource
|
|
@Resource
|
|
@@ -749,12 +754,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
task.setName(taskContentCell.getStringCellValue());
|
|
task.setName(taskContentCell.getStringCellValue());
|
|
}
|
|
}
|
|
|
|
|
|
-// XSSFCell planHoursCell = row.getCell(9);//计划工时
|
|
|
|
-// if(planHoursCell!=null){
|
|
|
|
-// planHoursCell.setCellType(CellType.STRING);
|
|
|
|
-// task.setPlanHours(Double.parseDouble(planHoursCell.getStringCellValue()));
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
XSSFCell priorityCell = row.getCell(6);//优先级
|
|
XSSFCell priorityCell = row.getCell(6);//优先级
|
|
if (priorityCell != null) {
|
|
if (priorityCell != null) {
|
|
priorityCell.setCellType(CellType.STRING);
|
|
priorityCell.setCellType(CellType.STRING);
|
|
@@ -815,6 +814,23 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
task.setEndDate(endDate);
|
|
task.setEndDate(endDate);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 每天的工作开始和结束时间
|
|
|
|
+ LocalTime workStartTime = LocalTime.of(9, 0);
|
|
|
|
+ LocalTime workEndTime = LocalTime.of(17, 30);
|
|
|
|
+ double dailyWorkHours = 7.5;
|
|
|
|
+ double totalHours = calculateTotalWorkHours(task.getStartDate(), task.getEndDate(), workStartTime, workEndTime);
|
|
|
|
+ task.setPlanHours(totalHours);
|
|
|
|
+
|
|
|
|
+ // 计算工作日数
|
|
|
|
+ int adjustedWorkDays = (int) (totalHours / dailyWorkHours);
|
|
|
|
+
|
|
|
|
+ // 检查余数并进行调整
|
|
|
|
+ if (totalHours % dailyWorkHours >= 1) {
|
|
|
|
+ adjustedWorkDays += 1; // 如果余数大于等于1,则加1
|
|
|
|
+ }
|
|
|
|
+ task.setPlannedDays(adjustedWorkDays);
|
|
|
|
+
|
|
|
|
+
|
|
XSSFCell executorCell = row.getCell(10);//执行人
|
|
XSSFCell executorCell = row.getCell(10);//执行人
|
|
if (executorCell != null) {
|
|
if (executorCell != null) {
|
|
executorCell.setCellType(CellType.STRING);
|
|
executorCell.setCellType(CellType.STRING);
|
|
@@ -861,16 +877,30 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
time2 = endDate.toLocalTime();
|
|
time2 = endDate.toLocalTime();
|
|
taskDailyAllocate.setEndTime(time2);
|
|
taskDailyAllocate.setEndTime(time2);
|
|
}
|
|
}
|
|
-
|
|
|
|
if (date1==null||date2==null|| !date1.isEqual(date2)){
|
|
if (date1==null||date2==null|| !date1.isEqual(date2)){
|
|
throw new Exception("第" + (rowIndex + 1) + "行,每日开始时间和每日截止时间日期不一致");
|
|
throw new Exception("第" + (rowIndex + 1) + "行,每日开始时间和每日截止时间日期不一致");
|
|
}else {
|
|
}else {
|
|
taskDailyAllocate.setAllocateDate(date1);
|
|
taskDailyAllocate.setAllocateDate(date1);
|
|
}
|
|
}
|
|
|
|
+ LocalDate endDateLocal = task.getEndDate().toLocalDate();
|
|
|
|
+ LocalDate startDateLocal = task.getStartDate().toLocalDate();
|
|
|
|
+ if (date1.isBefore(startDateLocal)||date1.isAfter(endDateLocal)){
|
|
|
|
+ throw new Exception("第" + (rowIndex + 1) + "行,每日分配日期不在计划的开始时间和截止时间范围内");
|
|
|
|
+ }
|
|
|
|
|
|
- double hoursDifference = Duration.between(time1, time2).getSeconds() / 3600.0;
|
|
|
|
|
|
+ if (time1.isAfter(time2)){
|
|
|
|
+ throw new Exception("第" + (rowIndex + 1) + "行,每日分配日期的开始时间不能晚于截止时间");
|
|
|
|
+ }
|
|
|
|
+ double hoursDifference = calculateEffectiveHours(time1, time2);
|
|
taskDailyAllocate.setWorkHour(hoursDifference);
|
|
taskDailyAllocate.setWorkHour(hoursDifference);
|
|
- taskDailyAllocate.setOverWorkHour(hoursDifference-7.5);
|
|
|
|
|
|
+
|
|
|
|
+ LocalTime localZao = LocalTime.of(9, 0);
|
|
|
|
+ LocalTime localWan = LocalTime.of(17, 30);
|
|
|
|
+ // 计算时间差(保持正负)
|
|
|
|
+ // 计算 time1 到 9:00 和 17:30 的时间差(小时)
|
|
|
|
+ double zao = Math.max(0.0, calculateRoundedHourDifference(time1, localZao));
|
|
|
|
+ double wan = Math.max(0.0, calculateRoundedHourDifference(localWan,time2 ));
|
|
|
|
+ taskDailyAllocate.setOverWorkHour(zao + wan);
|
|
|
|
|
|
task.setCompanyId(companyId);
|
|
task.setCompanyId(companyId);
|
|
task.setCreaterId(userId);
|
|
task.setCreaterId(userId);
|
|
@@ -879,6 +909,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
task.setCreateDate(LocalDate.now());
|
|
task.setCreateDate(LocalDate.now());
|
|
task.setIndate(LocalDateTime.now());
|
|
task.setIndate(LocalDateTime.now());
|
|
task.setTaskStatus(TaskController.STATUS_FIRST_CHECK);
|
|
task.setTaskStatus(TaskController.STATUS_FIRST_CHECK);
|
|
|
|
+ task.setIsTaskPlan(1);
|
|
taskMapper.insert(task);
|
|
taskMapper.insert(task);
|
|
initTaskId = task.getId();
|
|
initTaskId = task.getId();
|
|
initProjectId=task.getProjectId();
|
|
initProjectId=task.getProjectId();
|
|
@@ -908,10 +939,11 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
taskExecutor.setExecutorId(user.getId());
|
|
taskExecutor.setExecutorId(user.getId());
|
|
taskExecutor.setExecutorName(user.getName());
|
|
taskExecutor.setExecutorName(user.getName());
|
|
taskExecutor.setExecutorColor(user.getColor());
|
|
taskExecutor.setExecutorColor(user.getColor());
|
|
- taskExecutor.setPlanHours(task.getPlanHours());
|
|
|
|
|
|
+ taskExecutor.setPlanHours(hoursDifference);
|
|
taskExecutor.setProjectId(task.getProjectId());
|
|
taskExecutor.setProjectId(task.getProjectId());
|
|
|
|
|
|
Integer count = taskMapper.getUserConflitTaskCount(user.getId(), task.getId(), task.getStartDate(), task.getEndDate());
|
|
Integer count = taskMapper.getUserConflitTaskCount(user.getId(), task.getId(), task.getStartDate(), task.getEndDate());
|
|
|
|
+// List<Task> taskConflitList = taskMapper.getTaskConflitList(user.getId(), task.getId(), task.getStartDate(), task.getEndDate());
|
|
if (count > 0) {
|
|
if (count > 0) {
|
|
throw new Exception("第" + (rowIndex + 1) + "行,执行人" + user.getName() + "在其他任务上有时间冲突");
|
|
throw new Exception("第" + (rowIndex + 1) + "行,执行人" + user.getName() + "在其他任务上有时间冲突");
|
|
}
|
|
}
|
|
@@ -1017,16 +1049,28 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
time2 = endDate.toLocalTime();
|
|
time2 = endDate.toLocalTime();
|
|
taskDailyAllocate.setEndTime(time2);
|
|
taskDailyAllocate.setEndTime(time2);
|
|
}
|
|
}
|
|
-
|
|
|
|
if (date1==null||date2==null|| !date1.isEqual(date2)){
|
|
if (date1==null||date2==null|| !date1.isEqual(date2)){
|
|
throw new Exception("第" + (rowIndex + 1) + "行,每日开始时间和每日截止时间日期不一致");
|
|
throw new Exception("第" + (rowIndex + 1) + "行,每日开始时间和每日截止时间日期不一致");
|
|
}else {
|
|
}else {
|
|
taskDailyAllocate.setAllocateDate(date1);
|
|
taskDailyAllocate.setAllocateDate(date1);
|
|
}
|
|
}
|
|
|
|
+ LocalDate endDateLocal = initEndDate.toLocalDate();
|
|
|
|
+ LocalDate startDateLocal = initStartDate.toLocalDate();
|
|
|
|
+ if (date1.isBefore(startDateLocal)||date1.isAfter(endDateLocal)){
|
|
|
|
+ throw new Exception("第" + (rowIndex + 1) + "行,每日分配日期不在计划的开始时间和截止时间范围内");
|
|
|
|
+ }
|
|
|
|
|
|
- double hoursDifference = Duration.between(time1, time2).getSeconds() / 3600.0;
|
|
|
|
|
|
+ if (time1.isAfter(time2)){
|
|
|
|
+ throw new Exception("第" + (rowIndex + 1) + "行,每日分配日期的开始时间不能晚于截止时间");
|
|
|
|
+ }
|
|
|
|
+ double hoursDifference = calculateEffectiveHours(time1, time2);
|
|
taskDailyAllocate.setWorkHour(hoursDifference);
|
|
taskDailyAllocate.setWorkHour(hoursDifference);
|
|
- taskDailyAllocate.setOverWorkHour(hoursDifference-7.5);
|
|
|
|
|
|
+ LocalTime localZao = LocalTime.of(9, 0);
|
|
|
|
+ LocalTime localWan = LocalTime.of(17, 30);
|
|
|
|
+ double zao = Math.max(0.0, calculateRoundedHourDifference(time1, localZao));
|
|
|
|
+ double wan = Math.max(0.0, calculateRoundedHourDifference(localWan,time2 ));
|
|
|
|
+ taskDailyAllocate.setOverWorkHour(zao + wan);
|
|
|
|
+
|
|
|
|
|
|
//如果executorStr==initUserStr,taskExcutor执行人就不用保存
|
|
//如果executorStr==initUserStr,taskExcutor执行人就不用保存
|
|
if(executorStr.equals(initUserStr)){
|
|
if(executorStr.equals(initUserStr)){
|
|
@@ -1039,16 +1083,17 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
taskDailyAllocate.setUserId(first.get().getId());
|
|
taskDailyAllocate.setUserId(first.get().getId());
|
|
taskDailyAllocateService.save(taskDailyAllocate);
|
|
taskDailyAllocateService.save(taskDailyAllocate);
|
|
initUserStr=executorStr;
|
|
initUserStr=executorStr;
|
|
- initExectorIds+=first.get().getId();
|
|
|
|
- initExectorColors+=first.get().getColor();
|
|
|
|
- initExectorNames+=first.get().getName();
|
|
|
|
|
|
+ initExectorIds = getString(initExectorIds, first.get().getId());
|
|
|
|
+ initExectorColors=getString(initExectorColors, first.get().getColor());
|
|
|
|
+ initExectorNames=getString(initExectorNames, first.get().getName());
|
|
initworkHourExector+=hoursDifference;
|
|
initworkHourExector+=hoursDifference;
|
|
taskMapper.update(null,new UpdateWrapper<Task>().set("executor_id",initExectorIds)
|
|
taskMapper.update(null,new UpdateWrapper<Task>().set("executor_id",initExectorIds)
|
|
.set("executor_color",initExectorColors).set("executor_name",initExectorNames)
|
|
.set("executor_color",initExectorColors).set("executor_name",initExectorNames)
|
|
.eq("id",initTaskId));
|
|
.eq("id",initTaskId));
|
|
taskExecutorService.update(null,new UpdateWrapper<TaskExecutor>().eq("task_id",initTaskId).eq("executor_id",first.get().getId()).set("plan_hours",initworkHourExector));
|
|
taskExecutorService.update(null,new UpdateWrapper<TaskExecutor>().eq("task_id",initTaskId).eq("executor_id",first.get().getId()).set("plan_hours",initworkHourExector));
|
|
|
|
|
|
- }else {
|
|
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
|
|
initworkHourExector=hoursDifference;
|
|
initworkHourExector=hoursDifference;
|
|
String[] strings = executorStr.split(",");
|
|
String[] strings = executorStr.split(",");
|
|
@@ -1087,9 +1132,9 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
taskDailyAllocate.setUserId(first.get().getId());
|
|
taskDailyAllocate.setUserId(first.get().getId());
|
|
|
|
|
|
initUserStr=executorStr;
|
|
initUserStr=executorStr;
|
|
- initExectorIds+=first.get().getId();
|
|
|
|
- initExectorColors+=first.get().getColor();
|
|
|
|
- initExectorNames+=first.get().getName();
|
|
|
|
|
|
+ initExectorIds = getString(initExectorIds, first.get().getId());
|
|
|
|
+ initExectorColors=getString(initExectorColors, first.get().getColor());
|
|
|
|
+ initExectorNames=getString(initExectorNames, first.get().getName());
|
|
|
|
|
|
taskExecutorService.save(taskExecutor);
|
|
taskExecutorService.save(taskExecutor);
|
|
taskDailyAllocateService.save(taskDailyAllocate);
|
|
taskDailyAllocateService.save(taskDailyAllocate);
|
|
@@ -1121,6 +1166,17 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
return httpRespMsg;
|
|
return httpRespMsg;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private static String getString(String initString, String newStr) {
|
|
|
|
+ if (StringUtils.isEmpty(initString)){
|
|
|
|
+ initString = newStr;
|
|
|
|
+ }else {
|
|
|
|
+ if (!initString.contains(newStr)) {
|
|
|
|
+ initString += "," + newStr;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return initString;
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public HttpRespMsg delete(TaskGroup item) {
|
|
public HttpRespMsg delete(TaskGroup item) {
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
HttpRespMsg msg = new HttpRespMsg();
|
|
@@ -1852,4 +1908,87 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
|
|
}
|
|
}
|
|
return list;
|
|
return list;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ //任务计算得到计划工时
|
|
|
|
+ //计算时间
|
|
|
|
+ public static double calculateTotalWorkHours(LocalDateTime start, LocalDateTime end, LocalTime workStart, LocalTime workEnd) {
|
|
|
|
+ double totalHours = 0.0;
|
|
|
|
+
|
|
|
|
+ // 如果开始时间在结束时间之后,返回 0
|
|
|
|
+ if (start.isAfter(end)) {
|
|
|
|
+ return totalHours;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取开始日期和结束日期
|
|
|
|
+ LocalDateTime current = start;
|
|
|
|
+
|
|
|
|
+ while (current.toLocalDate().isBefore(end.toLocalDate()) || current.toLocalDate().isEqual(end.toLocalDate())) {
|
|
|
|
+ // 计算当天的工作开始和结束时间
|
|
|
|
+ LocalDateTime workStartDateTime = current.with(workStart);
|
|
|
|
+ LocalDateTime workEndDateTime = current.with(workEnd);
|
|
|
|
+
|
|
|
|
+ // 计算当天的有效工作时间
|
|
|
|
+ LocalDateTime actualStart = current.isBefore(workStartDateTime) ? workStartDateTime : current;
|
|
|
|
+ LocalDateTime actualEnd = end.isBefore(workEndDateTime) ? end : workEndDateTime;
|
|
|
|
+
|
|
|
|
+ // 检查是否跨越中午休息时间
|
|
|
|
+ LocalDateTime lunchStart = current.toLocalDate().atTime(12, 0);
|
|
|
|
+ LocalDateTime lunchEnd = current.toLocalDate().atTime(13, 0);
|
|
|
|
+
|
|
|
|
+ // 计算当天的工时
|
|
|
|
+ if (actualStart.isBefore(actualEnd)) {
|
|
|
|
+ // 计算工时
|
|
|
|
+ long hours = ChronoUnit.HOURS.between(actualStart, actualEnd);
|
|
|
|
+ long minutes = ChronoUnit.MINUTES.between(actualStart, actualEnd) % 60;
|
|
|
|
+ totalHours += hours + (minutes / 60.0);
|
|
|
|
+
|
|
|
|
+ // 检查是否跨越中午休息时间并减去1小时
|
|
|
|
+ if (!(actualEnd.isBefore(lunchStart) || actualStart.isAfter(lunchEnd))) {
|
|
|
|
+ totalHours -= 1; // 减去1小时
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 移动到下一天
|
|
|
|
+ current = current.toLocalDate().plusDays(1).atStartOfDay();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return totalHours;
|
|
|
|
+ }
|
|
|
|
+ //每日分配计算得到工时
|
|
|
|
+ public static double calculateEffectiveHours(LocalTime time1, LocalTime time2) {
|
|
|
|
+ if (time1.isAfter(time2)) {
|
|
|
|
+ throw new IllegalArgumentException("time1 不能晚于 time2");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 1. 如果时间范围完全不涉及午休时间,直接计算
|
|
|
|
+ if (time2.isBefore(LUNCH_START) || time1.isAfter(LUNCH_END)) {
|
|
|
|
+ return Duration.between(time1, time2).getSeconds() / 3600.0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 2. 如果时间范围完全包含午休时间,减去 1 小时
|
|
|
|
+ if (time1.isBefore(LUNCH_START) && time2.isAfter(LUNCH_END)) {
|
|
|
|
+ return (Duration.between(time1, time2).getSeconds() / 3600.0) - 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 3. 处理部分重叠的情况
|
|
|
|
+ double effectiveHours = 0;
|
|
|
|
+
|
|
|
|
+ // 3.1 计算午休前的有效时间
|
|
|
|
+ if (time1.isBefore(LUNCH_START)) {
|
|
|
|
+ effectiveHours += Duration.between(time1, LUNCH_START).getSeconds() / 3600.0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 3.2 计算午休后的有效时间
|
|
|
|
+ if (time2.isAfter(LUNCH_END)) {
|
|
|
|
+ effectiveHours += Duration.between(LUNCH_END, time2).getSeconds() / 3600.0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return effectiveHours;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 辅助方法:计算两个 LocalTime 的时间差(保留一位小数)
|
|
|
|
+ private static double calculateRoundedHourDifference(LocalTime start, LocalTime end) {
|
|
|
|
+ double hours = Duration.between(start, end).toMinutes() / 60.0;
|
|
|
|
+ return Math.round(hours * 10) / 10.0;
|
|
|
|
+ }
|
|
}
|
|
}
|