Explorar o código

【feat】【v3】
1.优化代码逻辑

ChenYL hai 10 meses
pai
achega
21b47e43cc

+ 3 - 1
src/main/java/com/punchsettle/server/atomic/mapper/PiTaskMapper.java

@@ -1,7 +1,9 @@
 package com.punchsettle.server.atomic.mapper;
 
 import com.punchsettle.server.atomic.entity.PiTask;
+import tk.mybatis.mapper.additional.update.batch.BatchUpdateSelectiveMapper;
 import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
 
 /**
  * @author tyuio
@@ -9,6 +11,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务表 Mapper
  * @date 2025/04/08 10:30
  */
-public interface PiTaskMapper extends Mapper<PiTask> {
+public interface PiTaskMapper extends Mapper<PiTask>, InsertListMapper<PiTask>, BatchUpdateSelectiveMapper<PiTask> {
 
 }

+ 6 - 0
src/main/java/com/punchsettle/server/atomic/service/IPiTaskHistoryService.java

@@ -45,4 +45,10 @@ public interface IPiTaskHistoryService {
      * @param piTaskHistory
      */
     void insert(PiTaskHistory piTaskHistory);
+
+    /**
+     * 批量新增
+     * @param piTaskHistories
+     */
+    void batchAdd(List<PiTaskHistory> piTaskHistories);
 }

+ 12 - 0
src/main/java/com/punchsettle/server/atomic/service/IPiTaskService.java

@@ -46,4 +46,16 @@ public interface IPiTaskService {
      * @return
      */
     List<PiTask> getActiveTask(Collection<Long> userIds);
+
+    /**
+     * 批量新增
+     * @param piTasks
+     */
+    void batchAdd(List<PiTask> piTasks);
+
+    /**
+     * 批量更新
+     * @param piTasks
+     */
+    void batchUpdate(List<PiTask> piTasks);
 }

+ 12 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java

@@ -96,4 +96,16 @@ public class PiTaskServiceImpl implements IPiTaskService {
         piTaskQuery.setUserIds(userIds);
         return queryByCondition(piTaskQuery);
     }
+
+    @Override
+    public void batchAdd(List<PiTask> piTasks) {
+        Assert.notEmpty(piTasks);
+        piTaskMapper.insertList(piTasks);
+    }
+
+    @Override
+    public void batchUpdate(List<PiTask> piTasks) {
+        Assert.notEmpty(piTasks);
+        piTaskMapper.batchUpdateSelective(piTasks);
+    }
 }

+ 41 - 10
src/main/java/com/punchsettle/server/service/controller/OpController.java

@@ -1,12 +1,7 @@
 package com.punchsettle.server.service.controller;
 
-import com.punchsettle.server.pojo.op.SettleRequest;
-import com.punchsettle.server.service.manager.IOpManager;
-import com.punchsettle.server.service.manager.ISettleManager;
-import com.punchsettle.server.service.manager.IStatManager;
-import com.punchsettle.server.task.SettlePointsTask;
-import com.punchsettle.server.utiis.SpringUtils;
-import jakarta.validation.constraints.NotBlank;
+import java.time.LocalDate;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -16,7 +11,19 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.time.LocalDate;
+import com.punchsettle.server.pojo.op.SettleRequest;
+import com.punchsettle.server.service.manager.ICalendarManager;
+import com.punchsettle.server.service.manager.IOpManager;
+import com.punchsettle.server.service.manager.ISettleManager;
+import com.punchsettle.server.service.manager.IStatManager;
+import com.punchsettle.server.task.CalendarTask;
+import com.punchsettle.server.task.PiTaskAutoArchiveTask;
+import com.punchsettle.server.task.PiTaskAutoPunchInTask;
+import com.punchsettle.server.task.RewardAutoExchangeTask;
+import com.punchsettle.server.task.SettlePointsTask;
+import com.punchsettle.server.utiis.SpringUtils;
+
+import jakarta.validation.constraints.NotBlank;
 
 /**
  * @author tyuio
@@ -53,7 +60,7 @@ public class OpController {
      */
     @GetMapping("invokeCalendarTask")
     public void invokeCalendarTask() {
-        opManager.invokeCalendarTask();
+        SpringUtils.getBean(CalendarTask.class).execute();
     }
 
     /**
@@ -61,7 +68,7 @@ public class OpController {
      */
     @GetMapping("refreshCalendar")
     public void refreshCalendar(String gregorianDate) {
-        opManager.refreshCalendar(gregorianDate);
+        SpringUtils.getBean(ICalendarManager.class).refreshCalendar(gregorianDate);
     }
 
     /**
@@ -89,4 +96,28 @@ public class OpController {
     public void distributePoints(@NotBlank(message = "结算日期不能为空") String settleDate) {
         SpringUtils.getBean(ISettleManager.class).distributePoints(LocalDate.parse(settleDate));
     }
+
+    /**
+     * 任务自动归档
+     */
+    @GetMapping("/taskAutoArchive")
+    public void taskAutoArchive() {
+        SpringUtils.getBean(PiTaskAutoArchiveTask.class).execute();
+    }
+
+    /**
+     * 任务自动归档
+     */
+    @GetMapping("/taskAutoPunchIn")
+    public void taskAutoPunchIn() {
+        SpringUtils.getBean(PiTaskAutoPunchInTask.class).execute();
+    }
+
+    /**
+     * 任务自动归档
+     */
+    @GetMapping("/rewardAutoExchange")
+    public void rewardAutoExchange() {
+        SpringUtils.getBean(RewardAutoExchangeTask.class).execute();
+    }
 }

+ 14 - 75
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -43,7 +43,6 @@ import com.punchsettle.server.constant.PunchInMethodEnum;
 import com.punchsettle.server.constant.PunchInResultEnum;
 import com.punchsettle.server.constant.PunchInResultViewEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
-import com.punchsettle.server.constant.SettleResultEnum;
 import com.punchsettle.server.constant.StatPeriodEnum;
 import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
@@ -63,7 +62,6 @@ import com.punchsettle.server.pojo.ucharts.LineVO;
 import com.punchsettle.server.service.manager.ICalendarManager;
 import com.punchsettle.server.service.manager.IPunchInCoreManager;
 import com.punchsettle.server.service.manager.IPunchInManager;
-import com.punchsettle.server.service.manager.ISettleManager;
 import com.punchsettle.server.utiis.DateUtils;
 import com.punchsettle.server.utiis.UserUtils;
 
@@ -79,9 +77,6 @@ import lombok.extern.slf4j.Slf4j;
 @Service
 public class PunchInManagerImpl implements IPunchInManager {
 
-    @Autowired
-    private ISettleManager settleManager;
-
     @Autowired
     private IPiTaskService piTaskService;
 
@@ -107,9 +102,9 @@ public class PunchInManagerImpl implements IPunchInManager {
     private IPiStatusService piStatusService;
 
     /**
-     * 默认显示时间00:00:00.000
+     * 默认时间00:00:00.000
      */
-    private static final LocalTime DEFAULT_DISPLAY_TIME = LocalTime.parse("00:00:00.000");
+    private static final LocalTime ZERO_TIME = LocalTime.parse("00:00:00.000");
 
     @Override
     public List<PiTaskToDoVO> queryToDoList(Long currentUserId) {
@@ -138,7 +133,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 3.根据displayOrder进行排序,按自然顺序排列
         return piTasks.stream().filter(piTask -> punchInCoreManager.judgeRepeat(piTask, today))
                 .filter(piTask -> {
-                    LocalTime displayTime = Optional.ofNullable(piTask.getDisplayTime()).orElse(DEFAULT_DISPLAY_TIME);
+                    LocalTime displayTime = Optional.ofNullable(piTask.getDisplayTime()).orElse(ZERO_TIME);
                     return nowTime.compareTo(displayTime) > -1;
                 })
                 .sorted(Comparator.comparing(piTask -> Optional.ofNullable(piTask.getDisplayOrder()).orElse(0)))
@@ -163,11 +158,7 @@ public class PunchInManagerImpl implements IPunchInManager {
     public List<PiTaskSimpleVO> queryTaskList() {
         Long currentUserId = UserUtils.getCurrentUserId();
         // 查询打卡任务
-        PiTaskQuery piTaskQuery = new PiTaskQuery();
-        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
-        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
-        piTaskQuery.setUserIds(Arrays.asList(currentUserId));
-        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+        List<PiTask> piTasks = piTaskService.getActiveTask(Arrays.asList(currentUserId));
 
         if (CollectionUtils.isEmpty(piTasks)) {
             return List.of();
@@ -288,6 +279,11 @@ public class PunchInManagerImpl implements IPunchInManager {
     public void saveTask(PiTaskRequest request) {
         Assert.isNullInBusiness(request, "请传入任务信息");
 
+        // 今天
+        LocalDate today = LocalDate.now();
+        // 当前用户ID
+        Long currentUserId = UserUtils.getCurrentUserId();
+
         // 数据校验
         if (PunchInMethodEnum.TIMING.equals(request.getPunchInMethod())) {
             if (Objects.isNull(request.getCompareRule()) || Objects.isNull(request.getTimeTrack())) {
@@ -328,6 +324,9 @@ public class PunchInManagerImpl implements IPunchInManager {
         if (CommonEnableStatusEnum.ENABLED.equals(request.getTaskPointsStatus()) && CollectionUtils.isEmpty(request.getContinueTaskExtList())) {
             throw BusinessException.fail("启用了任务积分计算,连续任务积分区间信息不能为空");
         }
+        if (Objects.nonNull(request.getEndDate()) && request.getEndDate().isBefore(today)) {
+            throw BusinessException.fail("任务自动归档时间无效,必需大于等于当前时间");
+        }
 
         // 新增打卡任务
         PiTask addPiTask = new PiTask();
@@ -350,11 +349,6 @@ public class PunchInManagerImpl implements IPunchInManager {
             piTaskService.update(updatePiTask);
         }
 
-        // 今天
-        LocalDate today = LocalDate.now();
-        // 当前用户ID
-        Long currentUserId = UserUtils.getCurrentUserId();
-
         // 保存数据
         piTaskService.insert(addPiTask);
         // 如果首次保存,需要设置唯一ID
@@ -494,54 +488,6 @@ public class PunchInManagerImpl implements IPunchInManager {
         cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 4)));
     }
 
-    @Override
-    public void autoPunchIn(PiTask piTask, String punchInDate) {
-        // 当前用户ID
-        Long currentUserId = piTask.getCreatedBy();
-        // 是否节假日
-        boolean holidayFlag = calendarManager.judgeHoliday(punchInDate);
-
-        // 查询今天的打卡记录
-        PiTaskHistory oldPiTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(piTask.getUniqueId(), punchInDate);
-
-        // 新增的打卡记录
-        PiTaskHistory tempPiTaskHistory = new PiTaskHistory();
-        tempPiTaskHistory.setTaskId(piTask.getId());
-        tempPiTaskHistory.setTaskUniqueId(piTask.getUniqueId());
-        tempPiTaskHistory.setPunchInDate(punchInDate);
-        tempPiTaskHistory.setUserId(currentUserId);
-
-        // 打卡类型:单次打卡,
-        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
-            // 默认打卡次数是1,是计数打卡的特例
-            tempPiTaskHistory.setCountTrack(1);
-        }
-
-        // 打卡类型:计数,需要累加打卡次数
-        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
-            tempPiTaskHistory.setCountTrack(holidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack());
-        }
-
-        // 打卡类型:计时,需要记录最新打卡时长
-        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
-            tempPiTaskHistory.setTimeTrack(holidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack());
-        }
-
-        // 设置打卡结果
-        PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(piTask, tempPiTaskHistory);
-        tempPiTaskHistory.setPunchInResult(punchInResult);
-
-        // 新增或更新
-        piTaskHistoryService.insert(tempPiTaskHistory);
-
-        // 清楚缓存
-        cacheManager.getCache(CacheNameConstant.TASK_LIST_VO).evict(currentUserId);
-        cacheManager.getCache(CacheNameConstant.TASK_PUNCH_IN_HISTORY).evict(String.format("%s_%s", currentUserId, punchInDate));
-        cacheManager.getCache(CacheNameConstant.TASK_HISTORY_LIST_FOR_USER).evict(String.format("%s_%s", currentUserId, punchInDate));
-        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 7)));
-        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 4)));
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void archiveTask(Long id) {
@@ -580,7 +526,7 @@ public class PunchInManagerImpl implements IPunchInManager {
 
         // 计时打卡 时间置为00:00:00.000
         if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
-            updatePiTaskHistory.setTimeTrack(DEFAULT_DISPLAY_TIME);
+            updatePiTaskHistory.setTimeTrack(ZERO_TIME);
         }
 
         // 计数打卡,当前打卡次数减1
@@ -729,14 +675,7 @@ public class PunchInManagerImpl implements IPunchInManager {
     @Cacheable(cacheNames = CacheNameConstant.TASK_LIST_FOR_USER, key = "#userId", condition = "#userId != null")
     public List<PiTask> getTaskListInCache(Long userId) {
         Assert.isNullInBusiness(userId, "用户ID不能为空");
-
-        PiTaskQuery piTaskQuery = new PiTaskQuery();
-        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
-        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
-        piTaskQuery.setUserIds(Arrays.asList(userId));
-        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
-
-        return piTasks;
+        return piTaskService.getActiveTask(Arrays.asList(userId));
     }
 
     @Override

+ 18 - 6
src/main/java/com/punchsettle/server/service/manager/impl/SettleManagerImpl.java

@@ -574,14 +574,20 @@ public class SettleManagerImpl implements ISettleManager {
         List<SettleUserHistory> settleUserHistories = settleUserHistoryService.querySettleUserHistory(settleUserHistoryQuery);
 
         if (CollectionUtils.isEmpty(settleUserHistories)) {
-            log.info("========== 积分分发定时任务,没有可分发的积分 结束执行 ==========");
+            log.info("========== 积分分发,没有可分发的积分 结束执行 ==========");
             return;
         }
 
+        // 零结算积分,直接修改结算状态节课
+        List<SettleUserHistory> zeroSettleUserHistories = settleUserHistories.stream().filter(settleUserHistory -> Optional.ofNullable(settleUserHistory.getSettlePoints()).orElse(0).equals(0)).toList();
+        zeroSettleUserHistories.forEach(v -> v.setDistributeStatus(PointsDistributeStatusEnum.DISTRIBUTE));
+
+        // 非零结算积分,下发积分
+        List<SettleUserHistory> nonZeroSettleUserHistories = settleUserHistories.stream().filter(settleUserHistory -> !Optional.ofNullable(settleUserHistory.getSettlePoints()).orElse(0).equals(0)).toList();
         // 用户ID-用户结算记录关联
-        Map<Long, SettleUserHistory> settleUserHistoryMap = settleUserHistories.stream().collect(Collectors.toMap(SettleUserHistory::getUserId, Function.identity(), (key1, key2) -> key1));
+        Map<Long, SettleUserHistory> settleUserHistoryMap = nonZeroSettleUserHistories.stream().collect(Collectors.toMap(SettleUserHistory::getUserId, Function.identity(), (key1, key2) -> key1));
         // 用户ID列表
-        Set<Long> userIds = settleUserHistories.stream().map(SettleUserHistory::getUserId).collect(Collectors.toSet());
+        Set<Long> userIds = nonZeroSettleUserHistories.stream().map(SettleUserHistory::getUserId).collect(Collectors.toSet());
 
         // 用户信息, 用户ID-用户信息关联
         List<User> users = userService.listByIds(userIds);
@@ -620,12 +626,14 @@ public class SettleManagerImpl implements ISettleManager {
             updateUser.setId(user.getId());
             updateUser.setTotalPoints(beforeTotalPoints + settlePoints);
             updateUser.setUnusedPoints(beforeUnusedPoints + settlePoints);
-            updateUserList.add(user);
+            updateUserList.add(updateUser);
 
             // 更新账户信息
             Integer beforeAccountPoints = Optional.ofNullable(account.getPoints()).orElse(0);
-            account.setPoints(beforeAccountPoints + settlePoints);
-            updateAccountList.add(account);
+            Account updateAccount = new Account();
+            updateAccount.setId(account.getId());
+            updateAccount.setPoints(beforeAccountPoints + settlePoints);
+            updateAccountList.add(updateAccount);
 
             // 增加账户转账记录
             AccountTransferHistory accountTransferHistory = new AccountTransferHistory();
@@ -661,5 +669,9 @@ public class SettleManagerImpl implements ISettleManager {
         if (!CollectionUtils.isEmpty(updateSettleUserHistories)) {
             settleUserHistoryService.batchUpdate(updateSettleUserHistories);
         }
+
+        if (!CollectionUtils.isEmpty(zeroSettleUserHistories)) {
+            settleUserHistoryService.batchUpdate(zeroSettleUserHistories);
+        }
     }
 }

+ 41 - 12
src/main/java/com/punchsettle/server/task/PiTaskAutoArchiveTask.java

@@ -1,18 +1,24 @@
 package com.punchsettle.server.task;
 
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
 import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.atomic.service.IPiTaskService;
 import com.punchsettle.server.constant.ArchiveStatusEnum;
 import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
 import com.punchsettle.server.service.manager.IPunchInManager;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
 
-import java.time.LocalDate;
-import java.util.List;
+import lombok.extern.slf4j.Slf4j;
 
 /**
  * @author tyuio
@@ -30,6 +36,7 @@ public class PiTaskAutoArchiveTask {
     @Autowired
     private IPunchInManager punchInManager;
 
+    @Transactional(rollbackFor = Exception.class)
     public void execute() {
         log.info("========== 打卡任务自动归档定时任务 开始执行 ==========");
 
@@ -44,12 +51,34 @@ public class PiTaskAutoArchiveTask {
             return;
         }
 
-        for (PiTask piTask : piTasks) {
-            try {
-                punchInManager.archiveTask(piTask.getId());
-            } catch (Exception e) {
-                log.error("自动归档发生异常", e);
-            }
+        // 更新
+        List<PiTask> updatePiTaskList = new ArrayList<>(piTasks.size());
+        // 新增
+        List<PiTask> addPiTaskList = new ArrayList<>(piTasks.size());
+
+        for (PiTask oldPiTask : piTasks) {
+            // 旧的打卡任务信息归档
+            PiTask updatePiTask = new PiTask();
+            updatePiTask.setId(oldPiTask.getId());
+            updatePiTask.setTaskStatus(VersionStatusEnum.ARCHIVE);
+            updatePiTaskList.add(updatePiTask);
+
+            // 新的打卡任务信息
+            PiTask addPiTask = new PiTask();
+            BeanUtils.copyProperties(oldPiTask, addPiTask);
+            addPiTask.setId(null);
+            addPiTask.setArchiveStatus(ArchiveStatusEnum.ARCHIVE);
+            addPiTask.setTaskStatus(VersionStatusEnum.ACTIVE);
+            addPiTask.setTaskVersion(Optional.ofNullable(oldPiTask.getTaskVersion()).orElse(0) + 1);
+            addPiTaskList.add(addPiTask);
+        }
+
+        if (!CollectionUtils.isEmpty(updatePiTaskList)) {
+            piTaskService.batchUpdate(updatePiTaskList);
+        }
+
+        if (!CollectionUtils.isEmpty(addPiTaskList)) {
+            piTaskService.batchAdd(addPiTaskList);
         }
 
         log.info("========== 打卡任务自动归档任务 结束执行 ==========");

+ 89 - 6
src/main/java/com/punchsettle/server/task/PiTaskAutoPunchInTask.java

@@ -1,10 +1,24 @@
 package com.punchsettle.server.task;
 
 import java.time.LocalDate;
+import java.time.LocalTime;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
+import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
+import com.punchsettle.server.constant.PunchInMethodEnum;
+import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
+import com.punchsettle.server.service.manager.ICalendarManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import com.punchsettle.server.atomic.entity.PiTask;
@@ -27,12 +41,21 @@ import lombok.extern.slf4j.Slf4j;
 @Component
 public class PiTaskAutoPunchInTask {
 
+    /**
+     * 默认时间:00:00
+     */
+    private static final LocalTime ZERO_TIME = LocalTime.parse("00:00:00.000");
+
     @Autowired
     private IPiTaskService piTaskService;
 
     @Autowired
-    private IPunchInManager punchInManager;
+    private IPiTaskHistoryService piTaskHistoryService;
+
+    @Autowired
+    private ICalendarManager calendarManager;
 
+    @Transactional(rollbackFor = Exception.class)
     public void execute() {
         log.info("========== 打卡任务自动打卡定时任务 开始执行 ==========");
 
@@ -47,14 +70,74 @@ public class PiTaskAutoPunchInTask {
             return;
         }
 
+        // 打卡日期
         LocalDate punchInDate = LocalDate.now();
+        // 是否节假日
+        boolean holidayFlag = calendarManager.judgeHoliday(punchInDate.toString());
+
+        // 查询已打卡数据
+        Set<Long> taskUniqueIds = piTasks.stream().map(PiTask::getUniqueId).collect(Collectors.toSet());
+        PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
+        piTaskHistoryQuery.setPunchInDate(punchInDate.toString());
+        piTaskHistoryQuery.setTaskUniqueIds(taskUniqueIds);
+        List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+        // 任务唯一ID-打卡记录
+        Map<Long, PiTaskHistory> piTaskHistoryMap = piTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        List<PiTaskHistory> addPiTaskHistories = piTasks.stream().filter(piTask -> {
+            PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId());
+            // 没有打卡记录
+            if (Objects.isNull(piTaskHistory)) {
+                return true;
+            }
+
+            // 判断是否有效的打卡记录
+            // 单次打卡,次数置为0,即为无效打卡
+            if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod()) && Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0).equals(0)) {
+                return true;
+            }
+
+            // 计时打卡 时间为00:00:00.000,即为无效打卡
+            if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod()) && ZERO_TIME.equals(Optional.ofNullable(piTaskHistory.getTimeTrack()).orElse(ZERO_TIME))) {
+                return true;
+            }
 
-        for (PiTask piTask : piTasks) {
-            try {
-                punchInManager.autoPunchIn(piTask, punchInDate.toString());
-            } catch (Exception e) {
-                log.error("自动打卡发生异常", e);
+            // 计数打卡,,次数置为0,即为无效打卡
+            if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod()) && Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0).equals(0)) {
+                return true;
             }
+
+            return false;
+        }).map(piTask -> {
+            // 新增的打卡记录
+            PiTaskHistory addPiTaskHistory = new PiTaskHistory();
+            addPiTaskHistory.setTaskId(piTask.getId());
+            addPiTaskHistory.setTaskUniqueId(piTask.getUniqueId());
+            addPiTaskHistory.setPunchInDate(punchInDate.toString());
+            addPiTaskHistory.setUserId(piTask.getCreatedBy());
+            addPiTaskHistory.setPunchInResult(PunchInResultEnum.DONE);
+
+            // 打卡类型:单次打卡,
+            if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
+                // 默认打卡次数是1,是计数打卡的特例
+                addPiTaskHistory.setCountTrack(1);
+            }
+
+            // 打卡类型:计数,需要累加打卡次数
+            if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
+                addPiTaskHistory.setCountTrack(holidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack());
+            }
+
+            // 打卡类型:计时,需要记录最新打卡时长
+            if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
+                addPiTaskHistory.setTimeTrack(holidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack());
+            }
+
+            return addPiTaskHistory;
+        }).toList();
+
+        if (!CollectionUtils.isEmpty(addPiTaskHistories)) {
+            piTaskHistoryService.batchAdd(addPiTaskHistories);
         }
 
         log.info("========== 打卡任务自动打卡定时任务 结束执行 ==========");