package com.sundot.airport.web.controller.attendance;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.sundot.airport.attendance.domain.AttendancePostRecord;
import com.sundot.airport.attendance.domain.AttendanceTeamUserRecord;
import com.sundot.airport.attendance.dto.*;
import com.sundot.airport.attendance.service.IAttendancePostRecordService;
import com.sundot.airport.attendance.service.IAttendanceTeamUserRecordService;
import com.sundot.airport.common.annotation.Log;
import com.sundot.airport.common.core.controller.BaseController;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.domain.DataPermissionResult;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysDictData;
import com.sundot.airport.common.core.domain.entity.SysRole;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.core.domain.model.LoginUser;
import com.sundot.airport.common.core.page.TableDataInfo;
import com.sundot.airport.common.dto.TreeNode;
import com.sundot.airport.common.dto.UserInfo;
import com.sundot.airport.common.enums.*;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.utils.DateUtils;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.common.utils.StringUtils;
import com.sundot.airport.common.utils.poi.ExcelUtil;
import com.sundot.airport.system.domain.BasePosition;
import com.sundot.airport.system.domain.vo.PositionInfoVO;
import com.sundot.airport.system.service.IBasePositionService;
import com.sundot.airport.system.service.ISysConfigService;
import com.sundot.airport.system.service.ISysDeptService;
import com.sundot.airport.system.service.ISysDictDataService;
import com.sundot.airport.web.core.cache.UserCache;
import com.sundot.airport.web.core.utils.DataPermissionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 上岗记录Controller
 *
 * @author wangchong
 * @date 2025-07-10
 */
@RestController
@RequestMapping("/attendance/postRecord")
public class AttendancePostRecordController extends BaseController {
    @Autowired
    private IAttendancePostRecordService attendancePostRecordService;

    @Autowired
    private IBasePositionService basePositionService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private UserCache userCache;

    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private IAttendanceTeamUserRecordService attendanceTeamUserRecordService;

    @Autowired
    private ISysConfigService configService;


    /**
     * 查询上岗记录列表
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:list')")
    @GetMapping("/list")
    public TableDataInfo list(AttendancePostRecord attendancePostRecord) {
        // 应用数据权限过滤
        DataPermissionResult dataPermission = DataPermissionUtils.getDataPermission(getUserId(), getDeptId(), getLoginUser());
        switch (dataPermission.getPermissionType()) {
            case SELF:
                attendancePostRecord.setUserId(dataPermission.getValue());
                break;
            case STATION:
                attendancePostRecord.setAttendanceStationId(dataPermission.getValue());
                break;
            case BRIGADE:
                attendancePostRecord.setAttendanceBrigadeId(dataPermission.getValue());
                break;
            case DEPARTMENT:
                attendancePostRecord.setAttendanceDepartmentId(dataPermission.getValue());
                break;
            case TEAM:
                attendancePostRecord.setAttendanceTeamId(dataPermission.getValue());
                break;
            case ALL:
            default:
                // 不设置过滤条件，查看所有数据
                break;
        }

        startPage();
        List<AttendancePostRecord> list = attendancePostRecordService.selectAttendancePostRecordList(attendancePostRecord);
        return getDataTable(list);
    }

    /**
     * 查询当天当前用户参与的上岗记录列表，按check_in_time分组
     * 返回当前用户所在班次的所有人员记录
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:list')")
    @GetMapping("/listgroupbyTimeanduserid")
    public AjaxResult listGroupByTimeAndUserId() {
        Long currentUserId = SecurityUtils.getUserId();
        // 计算当前时间对应的班次日期
//        Date queryDate = determineShiftDate();
        Long createBy = null;
        Long userId = null;
        DataPermissionResult dataPermission = DataPermissionUtils.getDataPermission(getUserId(), getDeptId(), getLoginUser());
        switch (dataPermission.getPermissionType()) {
            case DEPARTMENT:
            case TEAM:
                createBy = currentUserId;
                break;
            default:
                userId = currentUserId;
                break;
        }
        Date queryDate = attendancePostRecordService.selectMaxDateByUserId(createBy, userId);
        if (queryDate == null) {
            queryDate = DateUtils.getNowDate();
        }
        // 先获取当前用户今天的记录，取出班次信息
        List<AttendancePostRecord> userRecords = attendancePostRecordService.selectTodayRecordsByUserId(createBy, userId, queryDate, null);

        if (userRecords.isEmpty()) {
            return AjaxResult.success(new ArrayList<>());
        }

        // 获取当前用户的所有班次代码
        List<String> shiftCodes = userRecords.stream()
                .map(AttendancePostRecord::getShiftCode)
                .filter(Objects::nonNull)
                .filter(code -> !code.isEmpty())
                .distinct()
                .collect(Collectors.toList());

        // 如果没有班次信息，返回空结果
        if (shiftCodes.isEmpty()) {
            return AjaxResult.success(new ArrayList<>());
        }

        // 根据班次代码查询当天所有相同班次的记录
        List<AttendancePostRecord> allShiftRecords = attendancePostRecordService.selectTodayRecordsByShiftCodes(queryDate, shiftCodes);

        // 按 shift_code 分组，并转换为数组格式
        Map<String, List<AttendancePostRecord>> groupedByShift = allShiftRecords.stream()
                .filter(record -> record.getShiftCode() != null && !record.getShiftCode().isEmpty())
                .collect(Collectors.groupingBy(AttendancePostRecord::getShiftCode));

        // 转换为数组格式
        List<Map<String, Object>> result = new ArrayList<>();
        groupedByShift.forEach((shiftCode, records) -> {
            Map<String, Object> shiftGroup = new HashMap<>();
            shiftGroup.put("shiftCode", shiftCode);
            shiftGroup.put("records", records);
            // 获取该班次中最早的签到时间用于排序
            Date earliestCheckInTime = records.stream()
                    .map(AttendancePostRecord::getCheckInTime)
                    .filter(Objects::nonNull)
                    .min(Date::compareTo)
                    .orElse(new Date());
            shiftGroup.put("earliestCheckInTime", earliestCheckInTime);
            result.add(shiftGroup);
        });

        // 按最早签到时间降序排列（最新的在前）
        result.sort((a, b) -> {
            Date timeA = (Date) a.get("earliestCheckInTime");
            Date timeB = (Date) b.get("earliestCheckInTime");
            return timeB.compareTo(timeA); // 降序
        });

        // 移除临时添加的排序字段
        result.forEach(item -> item.remove("earliestCheckInTime"));

        return AjaxResult.success(result);
    }

    /**
     * 根据指定时间获取当前用户的在岗位置信息
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:list')")
    @PostMapping("/getLocationsbyTime")
    public AjaxResult getLocationsByTime(@RequestBody Map<String, String> requestBody) {
        try {
            Long currentUserId = SecurityUtils.getUserId();

            // 从请求体中获取时间参数
            String searchTime = requestBody.get("searchtime");
            if (StringUtils.isEmpty(searchTime)) {
                return AjaxResult.error("请提供 searchtime 参数");
            }

            // 解析时间参数
            Date queryTime = DateUtil.parse(searchTime, "yyyy-MM-dd HH:mm:ss");

            // 打印调试信息
            System.out.println("=== 调试信息 ===");
            System.out.println("当前用户ID: " + currentUserId);
            System.out.println("查询时间参数: " + searchTime);
            System.out.println("解析后的时间: " + queryTime);
            System.out.println("时间戳: " + queryTime.getTime());

            List<AttendancePostRecord> locations = attendancePostRecordService.selectLocationsByTime(currentUserId, queryTime);

            System.out.println("查询结果数量: " + locations.size());
            System.out.println("===============");

            return AjaxResult.success(locations);

        } catch (Exception e) {
            System.out.println("接口异常: " + e.getMessage());
            return AjaxResult.error("时间格式错误，请使用 yyyy-MM-dd HH:mm:ss 格式");
        }
    }

    /**
     * 导出上岗记录列表
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:export')")
    @Log(title = "上岗记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, AttendancePostRecord attendancePostRecord) {
        // 应用数据权限过滤
        DataPermissionResult dataPermission = DataPermissionUtils.getDataPermission(getUserId(), getDeptId(), getLoginUser());
        switch (dataPermission.getPermissionType()) {
            case SELF:
                attendancePostRecord.setUserId(dataPermission.getValue());
                break;
            case STATION:
                attendancePostRecord.setAttendanceStationId(dataPermission.getValue());
                break;
            case BRIGADE:
                attendancePostRecord.setAttendanceBrigadeId(dataPermission.getValue());
                break;
            case DEPARTMENT:
                attendancePostRecord.setAttendanceDepartmentId(dataPermission.getValue());
                break;
            case TEAM:
                attendancePostRecord.setAttendanceTeamId(dataPermission.getValue());
                break;
            case ALL:
            default:
                // 不设置过滤条件，查看所有数据
                break;
        }
        List<AttendancePostRecord> list = attendancePostRecordService.selectAttendancePostRecordList(attendancePostRecord);
        ExcelUtil<AttendancePostRecord> util = new ExcelUtil<AttendancePostRecord>(AttendancePostRecord.class);
        util.exportExcel(response, list, "上岗记录数据");
    }

    /**
     * 获取上岗记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(attendancePostRecordService.selectAttendancePostRecordById(id));
    }

    /**
     * 新增上岗记录
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:add')")
    @Log(title = "上岗记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody AttendancePostRecord attendancePostRecord) {
        // 处理部门信息
        extracted(attendancePostRecord);
        attendancePostRecord.setRevision(1L);
        attendancePostRecord.setWorkDuration((attendancePostRecord.getCheckOutTime().getTime() - attendancePostRecord.getCheckInTime().getTime()) / 1000 / 60);
        attendancePostRecord.setAttendanceDate(DateUtil.date(attendancePostRecord.getCheckInTime()));
        attendancePostRecord.setOverDuration(0L);
        attendancePostRecord.setCreateBy(getUserId().toString());
        // 岗位信息
        setPositionData(attendancePostRecord);
        // 通道信息
        BasePosition positionParam = new BasePosition();
        List<BasePosition> basePositions = basePositionService.selectBasePositionList(positionParam);
        setChannel(attendancePostRecord, basePositions);
        attendancePostRecord.setLocked(false);
        attendancePostRecord.getUserIdList().forEach(userId -> {
            AttendancePostRecord item = new AttendancePostRecord();
            BeanUtil.copyProperties(attendancePostRecord, item);
            UserInfo userInfo = userCache.getUserInfo(userId);
            item.setUserId(userId);
            item.setUserName(userInfo.getNickName());
            attendancePostRecordService.insertAttendancePostRecord(item);
        });
        return success("操作成功");
    }

    private void extracted(AttendancePostRecord attendancePostRecord) {
        if (ObjUtil.isNotNull(attendancePostRecord.getAttendanceTeamId())) {
            SysDept team = sysDeptService.selectDeptById(attendancePostRecord.getAttendanceTeamId());
            attendancePostRecord.setAttendanceTeamName(team.getDeptName());
            SysDept department = sysDeptService.selectDeptById(team.getParentId());
            if (ObjUtil.isNotNull(department)) {
                attendancePostRecord.setAttendanceDepartmentId(department.getDeptId());
                attendancePostRecord.setAttendanceDepartmentName(department.getDeptName());
                SysDept brigade = sysDeptService.selectDeptById(department.getParentId());
                if (ObjUtil.isNotNull(brigade)) {
                    attendancePostRecord.setAttendanceBrigadeId(brigade.getDeptId());
                    attendancePostRecord.setAttendanceBrigadeName(brigade.getDeptName());
                    SysDept station = sysDeptService.selectDeptById(brigade.getParentId());
                    if (ObjUtil.isNotNull(station)) {
                        attendancePostRecord.setAttendanceStationId(station.getDeptId());
                        attendancePostRecord.setAttendanceStationName(station.getDeptName());
                    }
                }
            }
        }
    }

    /**
     * 修改上岗记录
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:edit')")
    @Log(title = "上岗记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody AttendancePostRecord attendancePostRecord) {
        attendancePostRecord.setUpdateBy(getUserId().toString());
        attendancePostRecord.setRevision(attendancePostRecord.getRevision() + 1);
        attendancePostRecord.setWorkDuration((attendancePostRecord.getCheckOutTime().getTime() - attendancePostRecord.getCheckInTime().getTime()) / 1000 / 60);
        attendancePostRecord.setAttendanceDate(DateUtil.date(attendancePostRecord.getCheckInTime()));
        // 处理部门信息
        extracted(attendancePostRecord);
        // 岗位信息
        setPositionData(attendancePostRecord);
        // 通道信息
        BasePosition positionParam = new BasePosition();
        List<BasePosition> basePositions = basePositionService.selectBasePositionList(positionParam);
        setChannel(attendancePostRecord, basePositions);
        return toAjax(attendancePostRecordService.updateAttendancePostRecord(attendancePostRecord));
    }

    /**
     * 删除上岗记录
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:remove')")
    @Log(title = "上岗记录", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(attendancePostRecordService.deleteAttendancePostRecordByIds(ids));
    }

    /**
     * 新增上岗记录（直接存储，不校验字段）
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:add')")
    @Log(title = "上岗记录", businessType = BusinessType.INSERT)
    @PostMapping("/direct")
    public AjaxResult addDirect(@RequestBody List<AttendancePostRecord> attendancePostRecords) {
        boolean isKeZhang;
        List<SysRole> roles = SecurityUtils.getLoginUser().getUser().getRoles();
        if (CollUtil.isNotEmpty(roles)) {
            List<String> roleKeyList = roles.stream().map(SysRole::getRoleKey).collect(Collectors.toList());
            if (roleKeyList.contains(RoleTypeEnum.kezhang.getCode())) {
                isKeZhang = true;
                if (isUserRecordLocked(SecurityUtils.getUserId())) {
                    throw new ServiceException("该用户已锁定上岗记录，无法修改");
                }
            } else {
                isKeZhang = false;
            }
        } else {
            isKeZhang = false;
        }
        // 只处理必要的基础信息，不校验和自动设置岗位、通道等信息
        AtomicInteger count = new AtomicInteger();
        attendancePostRecords.forEach(record -> {
            // 检查该用户是否已经锁定上岗记录
            if (!isKeZhang && isUserRecordLocked(record.getUserId())) {
                throw new ServiceException("该用户已锁定上岗记录，无法修改");
            }
            extracted(record);
            UserInfo userInfo = userCache.getUserInfo(record.getUserId());
            record.setUserName(userInfo.getNickName());
            record.setRevision(1L);
            record.setWorkDuration((record.getCheckOutTime().getTime() - record.getCheckInTime().getTime()) / 1000 / 60);
            // 使用班次日期逻辑设置考勤日期
//            Date shiftDate = determineShiftDate();
            Date shiftDate = DateUtils.getNowDate();
            record.setAttendanceDate(shiftDate);
            record.setOverDuration(0L);
            record.setCreateBy(getUserId().toString());

            // 设置锁定标志
            record.setLocked(true);
            record.setLockTime(new Date());

            count.addAndGet(attendancePostRecordService.insertAttendancePostRecord(record));
        });


        return toAjax(count.get());
    }

    /**
     * 修改上岗记录（直接存储，不校验字段）
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:edit')")
    @Log(title = "上岗记录", businessType = BusinessType.UPDATE)
    @PutMapping("/direct")
    public AjaxResult editDirect(@RequestBody List<AttendancePostRecord> attendancePostRecord) {
        int count = 0;
        for (AttendancePostRecord postRecord : attendancePostRecord) {
            // 只处理必要的基础信息，不校验和自动设置岗位、通道等信息
            postRecord.setUpdateBy(getUserId().toString());
            postRecord.setRevision(postRecord.getRevision() + 1);
            postRecord.setWorkDuration((postRecord.getCheckOutTime().getTime() - postRecord.getCheckInTime().getTime()) / 1000 / 60);
            // 使用班次日期逻辑设置考勤日期
//            Date shiftDate = determineShiftDate();
//            postRecord.setAttendanceDate(shiftDate);
            extracted(postRecord);
            // 判断是否已签退
            LocalDateTime baseDateTime = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
            if (postRecord.getCheckOutTime().after(Date.from(baseDateTime.atZone(ZoneId.systemDefault()).toInstant()))) {
                postRecord.setLocked(false);
            }
            count += attendancePostRecordService.updateAttendancePostRecord(postRecord);

            // 处理考勤班组成员表-暂时注释（下通道时不需要处理考勤班组成员表）
//            AttendanceTeamUserRecord queryAttendanceTeamUserRecord = new AttendanceTeamUserRecord();
//            queryAttendanceTeamUserRecord.setCreateBy(SecurityUtils.getUsername());
//            queryAttendanceTeamUserRecord.setUserId(postRecord.getUserId());
//            queryAttendanceTeamUserRecord.setCheckInType("1");
//            List<AttendanceTeamUserRecord> attendanceTeamUserRecordList = attendanceTeamUserRecordService.selectAttendanceTeamUserRecordList(queryAttendanceTeamUserRecord, true);
//            attendanceTeamUserRecordList.forEach(attendanceTeamUserRecord -> {
//                attendanceTeamUserRecord.setUpdateBy(SecurityUtils.getUsername());
//                attendanceTeamUserRecord.setCheckInType("2");
//                attendanceTeamUserRecordService.updateAttendanceTeamUserRecord(attendanceTeamUserRecord);
//            });
        }


        return toAjax(count);
    }

    private void setPositionData(AttendancePostRecord attendancePostRecord) {
        if (StrUtil.isNotBlank(attendancePostRecord.getPositionCode())) {
            String positionName = sysDictDataService.selectDictLabel("item_check_method", attendancePostRecord.getPositionCode());
            attendancePostRecord.setPositionName(positionName);
        }
        attendancePostRecord.setShiftCode("");
        attendancePostRecord.setShiftName("");
    }

    private void setChannel(AttendancePostRecord attendancePostRecord, List<BasePosition> basePositions) {
        BasePosition terminal = basePositions
                .stream().filter(x -> StrUtil.equals(BasePositionEnum.TERMINAL.getCode(), x.getPositionType())
                        && StrUtil.equals(attendancePostRecord.getTerminlCode(), x.getCode()))
                .findFirst().orElse(new BasePosition());
        attendancePostRecord.setTerminlName(terminal.getName());

        BasePosition regional = basePositions.stream()
                .filter(x -> StrUtil.equals(BasePositionEnum.REGIONAL.getCode(), x.getPositionType())
                        && ObjUtil.equals(terminal.getId(), x.getParentId())
                        && StrUtil.equals(attendancePostRecord.getRegionalCode(), x.getCode()))
                .findFirst().orElse(new BasePosition());
        attendancePostRecord.setRegionalName(regional.getName());

        BasePosition channel = basePositions.stream()
                .filter(x -> StrUtil.equals(BasePositionEnum.CHANNEL.getCode(), x.getPositionType())
                        && ObjUtil.equals(regional.getId(), x.getParentId())
                        && StrUtil.equals(attendancePostRecord.getChannelCode(), x.getCode()))
                .findFirst().orElse(new BasePosition());
        attendancePostRecord.setChannelName(channel.getName());
    }

    @PostMapping("/positionList")
    public AjaxResult list(@RequestBody BasePosition basePosition) {
        List<TreeNode> list = buildTree(basePositionService.selectBasePositionList(basePosition));
        return success(list);
    }

    private List<TreeNode> buildTree(List<BasePosition> list) {
        List<TreeNode> nodeList = list.stream().map(node -> TreeNode.builder().label(node.getName()).value(node.getCode()).parentId(node.getParentId()).id(node.getId()).build()).collect(Collectors.toList());

        // 结果列表
        List<TreeNode> result = new ArrayList<>();

        // 临时Map，用于快速查找节点
        Map<Long, TreeNode> nodeMap = new HashMap<>();

        // 第一次遍历：将所有节点存入Map
        for (TreeNode node : nodeList) {
            nodeMap.put(node.getId(), node);
        }

        // 第二次遍历：建立父子关系
        for (TreeNode node : nodeList) {
            Long parentId = node.getParentId();
            if (parentId == null || parentId == 0L) {
                // 父ID为null或0，说明是根节点
                result.add(node);
            } else {
                // 查找父节点
                TreeNode parent = nodeMap.get(parentId);
                if (parent != null) {
                    // 初始化子节点列表
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    // 将当前节点添加到父节点的子列表中
                    List<TreeNode> children = parent.getChildren();
                    children.add(node);
                }
            }
        }

        return result;
    }

    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<AttendancePostRecordImportVO> util = new ExcelUtil<AttendancePostRecordImportVO>(AttendancePostRecordImportVO.class);
        util.importTemplateExcel(response, "用户数据");
    }

    @Log(title = "上岗管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file) throws Exception {
        ExcelUtil<AttendancePostRecordImportVO> util = new ExcelUtil<AttendancePostRecordImportVO>(AttendancePostRecordImportVO.class);
        List<AttendancePostRecordImportVO> list = util.importExcel(file.getInputStream());
        if (CollectionUtil.isEmpty(list)) {
            throw new ServiceException("导入用户数据不能为空");
        }
        validateData(list);
        String message = importData(list);
        return success(message);
    }

    private void validateData(List<AttendancePostRecordImportVO> list) {
        StringBuilder failureMsg = new StringBuilder();
        int failureNum = 2;
        for (AttendancePostRecordImportVO vo : list) {
            if (StrUtil.isBlank(vo.getUserName())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行用户姓名不能为空");
            }
            UserInfo userInfo = userCache.getUserInfo(vo.getUserName());
            if (Objects.isNull(userInfo) || Objects.isNull(userInfo.getUserId())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行用户不存在");
            }
            if (ObjUtil.isNull(vo.getAttendanceDate())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行考勤日期格式错误或者不能为空");
            }
            if (ObjUtil.isNull(vo.getCheckInTime())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行签到时间格式错误或者不能为空");
            }
            if (ObjUtil.isNull(vo.getCheckOutTime())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行签退时间格式错误或者不能为空");
            }
            if (StrUtil.isBlank(vo.getAttendanceTeamName())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行班组不能为空");
            } else {
                String[] teamStr = vo.getAttendanceTeamName().split("/");
                if (teamStr.length != 3) {
                    failureMsg.append("<br/>第 ").append(failureNum).append(" 行班组格式错误");
                }
            }
            if (StrUtil.isBlank(vo.getChannelName())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行通道不能为空");
            } else {
                String[] channelStr = vo.getChannelName().split("/");
                if (channelStr.length != 3) {
                    failureMsg.append("<br/>第 ").append(failureNum).append(" 行通道格式错误");
                }
            }
            if (StrUtil.isBlank(vo.getPositionName())) {
                failureMsg.append("<br/>第 ").append(failureNum).append(" 行岗位名称不能为空");
            }
            failureNum++;
        }
        if (StrUtil.isNotBlank(failureMsg)) {
            throw new ServiceException(failureMsg.toString());
        }
    }

    private String importData(List<AttendancePostRecordImportVO> list) {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        // 岗位信息
        SysDictData dictData = new SysDictData();
        dictData.setDictType("item_check_method");
        List<SysDictData> sysDictData = sysDictDataService.selectDictDataList(dictData);

        // 通道信息
        BasePosition positionParam = new BasePosition();
        List<BasePosition> basePositions = basePositionService.selectBasePositionList(positionParam);

        // 部门信息
        SysDept sysDeptParam = new SysDept();
        List<SysDept> deptList = sysDeptService.selectDeptList(sysDeptParam);

        for (AttendancePostRecordImportVO vo : list) {
            UserInfo userInfo = userCache.getUserInfo(vo.getUserName());
            try {
                AttendancePostRecord attendancePostRecord = new AttendancePostRecord();
                attendancePostRecord.setRevision(1L);
                attendancePostRecord.setCheckInTime(vo.getCheckInTime());
                attendancePostRecord.setCheckOutTime(vo.getCheckOutTime());
                attendancePostRecord.setWorkDuration((attendancePostRecord.getCheckOutTime().getTime() - attendancePostRecord.getCheckInTime().getTime()) / 1000 / 60);
                attendancePostRecord.setAttendanceDate(vo.getAttendanceDate());

                String[] channelStr = vo.getChannelName().split("/");
                BasePosition terminal = basePositions
                        .stream().filter(x -> StrUtil.equals(BasePositionEnum.TERMINAL.getCode(), x.getPositionType())
                                && StrUtil.equals(channelStr[0], x.getName()))
                        .findFirst().orElse(new BasePosition());
                attendancePostRecord.setTerminlCode(terminal.getCode());
                attendancePostRecord.setTerminlName(terminal.getName());

                BasePosition regional = basePositions.stream()
                        .filter(x -> StrUtil.equals(BasePositionEnum.REGIONAL.getCode(), x.getPositionType())
                                && ObjUtil.equals(terminal.getId(), x.getParentId())
                                && StrUtil.equals(channelStr[1], x.getName()))
                        .findFirst().orElse(new BasePosition());
                attendancePostRecord.setRegionalCode(regional.getCode());
                attendancePostRecord.setRegionalName(regional.getName());

                BasePosition channel = basePositions.stream()
                        .filter(x -> StrUtil.equals(BasePositionEnum.CHANNEL.getCode(), x.getPositionType())
                                && ObjUtil.equals(regional.getId(), x.getParentId())
                                && StrUtil.equals(channelStr[2], x.getName()))
                        .findFirst().orElse(new BasePosition());
                attendancePostRecord.setChannelCode(channel.getCode());
                attendancePostRecord.setChannelName(channel.getName());


                String[] teamStr = vo.getAttendanceTeamName().split("/");
                SysDept station = deptList.stream().filter(x -> StrUtil.equals(teamStr[0], x.getDeptName())).findFirst().orElse(new SysDept());
                SysDept brigade = deptList.stream().filter(x -> StrUtil.equals(teamStr[1], x.getDeptName()) && ObjUtil.equals(station.getDeptId(), x.getParentId())).findFirst().orElse(new SysDept());
                SysDept department = deptList.stream().filter(x -> StrUtil.equals(teamStr[2], x.getDeptName()) && ObjUtil.equals(brigade.getDeptId(), x.getParentId())).findFirst().orElse(new SysDept());
                SysDept teams = deptList.stream().filter(x -> StrUtil.equals(teamStr[3], x.getDeptName()) && ObjUtil.equals(department.getDeptId(), x.getParentId())).findFirst().orElse(new SysDept());
                attendancePostRecord.setAttendanceTeamId(teams.getDeptId());
                attendancePostRecord.setAttendanceTeamName(teams.getDeptName());
                attendancePostRecord.setAttendanceDepartmentId(department.getDeptId());
                attendancePostRecord.setAttendanceDepartmentName(department.getDeptName());
                attendancePostRecord.setAttendanceBrigadeId(brigade.getDeptId());
                attendancePostRecord.setAttendanceBrigadeName(brigade.getDeptName());
                attendancePostRecord.setAttendanceStationId(station.getDeptId());
                attendancePostRecord.setAttendanceStationName(station.getDeptName());

                if (CollectionUtil.isNotEmpty(sysDictData)) {
                    SysDictData positionData = sysDictData.stream().filter(x -> StrUtil.equals(x.getDictLabel(), vo.getPositionName())).findFirst().orElse(new SysDictData());
                    attendancePostRecord.setPositionCode(positionData.getDictValue());
                    attendancePostRecord.setPositionName(positionData.getDictLabel());
                }

                attendancePostRecord.setShiftCode("");
                attendancePostRecord.setShiftName("");

                attendancePostRecord.setRemark(vo.getRemark());
                attendancePostRecord.setUserId(userInfo.getUserId());
                attendancePostRecord.setUserName(userInfo.getNickName());
                attendancePostRecord.setOverDuration(0L);
                attendancePostRecord.setCreateBy(getUserId().toString());
                attendancePostRecord.setCreateTime(new Date());
                attendancePostRecordService.insertAttendancePostRecord(attendancePostRecord);
                successNum++;
                successMsg.append("<br/>" + successNum + "、账号 " + userInfo.getUserName() + " 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + userInfo.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }


    /**
     *  获取通道统计
     * @param regionalStatus  区域状态 1:我的区域 2:所有区域
     * @return 统计结果
     */
    /**
     * 获取通道统计
     *
     * @param regionalStatus 区域状态 1:我的区域 2:所有区域
     * @return 统计结果
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:count')")
    @PostMapping("/count")
    public AttendanceRecordCountDTO attendanceRecordCount(String regionalStatus) {
        AttendanceRecordCountDTO dto = new AttendanceRecordCountDTO();
        List<String> regionalCodes = new ArrayList<>();
        //判断是不是科长和获取用户关联的区域编码
        boolean kezhang = isKezhang(regionalStatus, regionalCodes);
        if (kezhang && CollectionUtil.isEmpty(regionalCodes)) {
            return null;
        }
        // 查询通道详情
        List<PositionInfoVO> channels = basePositionService.selectChannelsUnderArea(regionalCodes);
        if (CollectionUtil.isEmpty(channels)) {
            return null;
        }

        // 设置基础统计数据
        dto.setChannelCount(channels.size());

        // 获取在岗记录
        List<AttendancePostRecord> onDutyRecords = getCurrentOnDutyRecords(channels);
        dto.setOnDutyCount(onDutyRecords.size());

        // 获取维护人员记录
        List<AttendanceTeamUserRecord> maintainList = getMaintainRecords();
        dto.setMaintainCount(maintainList.size());

        // 按航站楼分组统计详情
        Map<String, List<PositionInfoVO>> terminalGroup = channels.stream()
                .collect(Collectors.groupingBy(PositionInfoVO::getCode));

        List<AttendanceRecordTerminlCountDetailDTO> terminlDetail = new ArrayList<>();
        dto.setTerminlDetail(terminlDetail);

        // 构建每个航站楼的详细统计信息
        terminalGroup.forEach((terminalCode, channelList) -> {
            AttendanceRecordTerminlCountDetailDTO terminalDetail = buildTerminalDetail(
                    terminalCode, channelList, onDutyRecords, maintainList);
            terminlDetail.add(terminalDetail);
        });

        return dto;
    }

    /**
     * 查询是否是科长
     */
    private boolean isKezhang(String regionalStatus, List<String> regionalCodes) {

        if (!StringUtils.equals(regionalStatus, "1")) {
            return false;
        }

        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null || loginUser.getUser() == null) {
            return true;
        }

        SysUser user = loginUser.getUser();
        List<SysRole> roles = user.getRoles();
        if (CollUtil.isEmpty(roles)) {
            return true;
        }
        List<String> roleKeyList = roles.stream()
                .map(SysRole::getRoleKey)
                .collect(Collectors.toList());
        if (roleKeyList.contains(RoleTypeEnum.kezhang.getCode())) {
            Map<String, Date> shiftTime = attendancePostRecordService.getShiftTimeNew();
            Date shiftStartTime = shiftTime.get("start");
            Date shiftEndTime = shiftTime.get("end");
            List<AttendancePostRecord> regionalList = attendancePostRecordService
                    .selectKezhangRecordCount(user.getUserId(), shiftStartTime, shiftEndTime);
            regionalCodes.addAll(regionalList.stream()
                    .map(AttendancePostRecord::getRegionalCode)
                    .collect(Collectors.toList()));
            return true;
        }
        return false;

    }

    /**
     * 获取当前在岗记录
     */
    private List<AttendancePostRecord> getCurrentOnDutyRecords(List<PositionInfoVO> channels) {
        List<String> channelCodeList = channels.stream()
                .map(PositionInfoVO::getChannelCode)
                .collect(Collectors.toList());
        Map<String, Date> shiftTime = attendancePostRecordService.getShiftTimeNew();
        Date shiftStartTime = shiftTime.get("start");
        Date shiftEndTime = shiftTime.get("end");
        return attendancePostRecordService
                .selectLocationsByTimeAndChannelName(channelCodeList, DateUtils.getNowDate(), shiftStartTime, shiftEndTime);
    }

    /**
     * 获取维护人员记录
     */
    private List<AttendanceTeamUserRecord> getMaintainRecords() {
        AttendanceTeamUserRecord queryRecord = new AttendanceTeamUserRecord();
//        try {
//            queryRecord.setAttendanceDate(DateUtils.parseDate(DateUtils.getDate()));
//        } catch (Exception e) {
//            // 处理日期解析异常，使用当前日期作为默认值
//            queryRecord.setAttendanceDate(new Date());
//        }
        queryRecord.setCheckInType("1");
        return attendanceTeamUserRecordService
                .selectAttendanceTeamUserRecordList(queryRecord, false);
    }


    /**
     * 构建航站楼详细统计信息
     *
     * @param terminalCode  航站楼编码
     * @param channelList   通道列表
     * @param onDutyRecords 在岗记录
     * @param maintainList  维护人员记录
     * @return 航站楼详细统计信息
     */
    private AttendanceRecordTerminlCountDetailDTO buildTerminalDetail(
            String terminalCode,
            List<PositionInfoVO> channelList,
            List<AttendancePostRecord> onDutyRecords,
            List<AttendanceTeamUserRecord> maintainList) {

        AttendanceRecordTerminlCountDetailDTO detailDTO = new AttendanceRecordTerminlCountDetailDTO();
        detailDTO.setTerminlCode(terminalCode);
        detailDTO.setTerminlName(channelList.get(0).getName());
        //总通道数
        detailDTO.setChannelCount(channelList.size());

        // 计算在岗人数
        List<AttendancePostRecord> terminalOnDutyRecords = calculateOnDutyRecords(channelList, onDutyRecords);
        detailDTO.setOnDutyCount(terminalOnDutyRecords.size());

        // 设置总人数
        Map<String, List<AttendanceTeamUserRecord>> userRecord = maintainList.stream()
                .collect(Collectors.groupingBy(AttendanceTeamUserRecord::getTerminlCode));
        detailDTO.setOpenChannelCount(
                userRecord.getOrDefault(terminalCode, Collections.emptyList()).size());

        // 设置在岗通道数
        Set<String> onDutyChannelCodes = terminalOnDutyRecords.stream()
                .map(AttendancePostRecord::getChannelCode)
                .collect(Collectors.toSet());
        detailDTO.setOnDutyChannelCount(onDutyChannelCodes.size());

        // 构建区域详情
        List<AttendanceRecordCountRegionDTO> regionList = buildRegionDetails(terminalOnDutyRecords);
        detailDTO.setRegion(regionList);

        // 构建空闲班组列表
        List<AttendanceRecordCountWaitDTO> waitList = buildWaitTeamList(
                terminalCode, maintainList, regionList);
        detailDTO.setWaitList(waitList);

        // 设置最后一次离岗时间
        updateLastCheckOutTime(waitList);

        return detailDTO;
    }

    /**
     * 计算指定航站楼下的在岗记录
     */
    private List<AttendancePostRecord> calculateOnDutyRecords(
            List<PositionInfoVO> channelList,
            List<AttendancePostRecord> allOnDutyRecords) {

        List<AttendancePostRecord> result = new ArrayList<>();

        for (PositionInfoVO channel : channelList) {
            List<AttendancePostRecord> matchedRecords = allOnDutyRecords.stream()
                    .filter(record -> record != null &&
                            StrUtil.equals(record.getChannelCode(), channel.getChannelCode()))
                    .peek(record -> {
                        record.setRegionalCode(channel.getSmallAreaCode());
                        record.setRegionalName(channel.getSmallAreaName());
                        record.setTerminlCode(channel.getCode());
                        record.setTerminlName(channel.getName());
                    })
                    .collect(Collectors.toList());
            result.addAll(matchedRecords);
        }

        return result;
    }

    /**
     * 构建区域详情列表
     *
     * @param terminalOnDutyRecords 航站楼下的在岗记录
     */
    private List<AttendanceRecordCountRegionDTO> buildRegionDetails(
            List<AttendancePostRecord> terminalOnDutyRecords) {

        // 按区域和通道分组
        Map<String, Map<String, List<AttendancePostRecord>>> regionChannelGroup =
                terminalOnDutyRecords.stream()
                        .collect(Collectors.groupingBy(AttendancePostRecord::getRegionalName,
                                Collectors.groupingBy(AttendancePostRecord::getChannelName)));

        List<AttendanceRecordCountRegionDTO> regionList = new ArrayList<>();

        regionChannelGroup.forEach((regionName, channelGroup) -> {
            AttendanceRecordCountRegionDTO regionDTO = new AttendanceRecordCountRegionDTO();
            regionDTO.setRegionalName(regionName);

            List<AttendanceRecordCountDetailDTO> detailList = new ArrayList<>();
            int totalChannelCount = 0;

            for (Map.Entry<String, List<AttendancePostRecord>> entry : channelGroup.entrySet()) {
                String channelName = entry.getKey();
                List<AttendancePostRecord> channelRecords = entry.getValue();

                totalChannelCount += channelRecords.size();

                if (!channelRecords.isEmpty()) {
                    AttendancePostRecord firstRecord = channelRecords.get(0);
                    AttendanceRecordCountDetailDTO detail = new AttendanceRecordCountDetailDTO();
                    detail.setChannelName(channelName);
                    detail.setOnDutyTeamName(firstRecord.getAttendanceTeamName());
                    detail.setOnDutyCount(channelRecords.size());
                    detail.setRegionalCode(firstRecord.getRegionalCode());
                    detail.setRegionalName(firstRecord.getRegionalName());
                    detail.setTerminlCode(firstRecord.getTerminlCode());
                    detail.setTerminlName(firstRecord.getTerminlName());
                    detail.setAttendanceTeamName(firstRecord.getAttendanceTeamName());
                    detail.setOnDutyTime(firstRecord.getCheckInTime());
                    detailList.add(detail);
                }
            }

            regionDTO.setOpenUserCount(totalChannelCount);
            if (!detailList.isEmpty()) {
                AttendanceRecordCountDetailDTO firstDetail = detailList.get(0);
                regionDTO.setRegionalCode(firstDetail.getRegionalCode());
                regionDTO.setTerminlCode(firstDetail.getTerminlCode());
                regionDTO.setTerminlName(firstDetail.getTerminlName());
                regionDTO.setOpenChannelCount(detailList.size());
            } else {
                regionDTO.setOpenChannelCount(0);
            }

            regionDTO.setDetailList(detailList);
            regionList.add(regionDTO);
        });

        return regionList;
    }

    /**
     * 构建空闲班组列表
     */
    private List<AttendanceRecordCountWaitDTO> buildWaitTeamList(
            String terminalCode,
            List<AttendanceTeamUserRecord> maintainList,
            List<AttendanceRecordCountRegionDTO> regionList) {

        // 按班组分组维护人员
        Map<String, List<AttendanceTeamUserRecord>> teamGroup = maintainList.stream()
                .filter(record -> StringUtils.equals(record.getTerminlCode(), terminalCode))
                .collect(Collectors.groupingBy(AttendanceTeamUserRecord::getAttendanceTeamName));

//        Date date = determineShiftDate();
        Date date = DateUtils.getNowDate();

        List<AttendanceRecordCountWaitDTO> waitList = new ArrayList<>();

        teamGroup.forEach((teamName, teamMembers) -> {
            // 查找该班组是否在岗
            Optional<AttendanceRecordCountDetailDTO> onDutyDetail = findTeamOnDutyDetail(
                    teamName, regionList);

            AttendanceRecordCountWaitDTO waitDTO = new AttendanceRecordCountWaitDTO();
            waitDTO.setWaitTeamName(teamName);
            waitDTO.setTerminlCode(terminalCode);
            waitDTO.setTerminlName(teamMembers.get(0).getTerminlName());
            waitDTO.setWaitTeamCode(teamMembers.get(0).getAttendanceTeamId());
            List<AttendancePostRecord> attendancePostRecords = attendancePostRecordService.selectTeamOnList(date, teamMembers.get(0).getAttendanceTeamId());
            int onDutyCount = onDutyDetail.map(AttendanceRecordCountDetailDTO::getOnDutyCount).orElse(0);
            waitDTO.setWaitCount(teamMembers.size() - onDutyCount);


            // 只添加有空闲人员的班组
            if (waitDTO.getWaitCount() > 0 && CollectionUtil.isEmpty(attendancePostRecords)) {
                waitList.add(waitDTO);
            }
        });

        return waitList;
    }

    /**
     * 查找班组在岗详情
     */
    private Optional<AttendanceRecordCountDetailDTO> findTeamOnDutyDetail(
            String teamName,
            List<AttendanceRecordCountRegionDTO> regionList) {

        return regionList.stream()
                .flatMap(region -> region.getDetailList().stream())
                .filter(detail -> StrUtil.equals(detail.getAttendanceTeamName(), teamName))
                .findFirst();
    }

    /**
     * 更新空闲班组的最后离岗时间
     */
    private void updateLastCheckOutTime(List<AttendanceRecordCountWaitDTO> waitList) {
        if (waitList.isEmpty()) {
            return;
        }

        List<Long> terminalCodes = waitList.stream()
                .map(AttendanceRecordCountWaitDTO::getWaitTeamCode)
                .distinct()
                .collect(Collectors.toList());

        if (terminalCodes.isEmpty()) {
            return;
        }

        List<AttendancePostRecord> checkoutRecords = attendancePostRecordService
                .selectCheckOutTimeByShiftCodes(DateUtil.beginOfDay(new Date()), terminalCodes);

        Map<Long, List<AttendancePostRecord>> checkoutGroup = checkoutRecords.stream()
                .collect(Collectors.groupingBy(AttendancePostRecord::getAttendanceTeamId));

        if (checkoutGroup.isEmpty()) {
            return;
        }

        waitList.forEach(waitDTO -> {
            List<AttendancePostRecord> records = checkoutGroup.get(waitDTO.getWaitTeamCode());
            if (records != null && !records.isEmpty()) {
                waitDTO.setCheckOutTime(records.get(0).getCheckOutTime());
            }
        });
    }

    /**
     * 查询科长最后一次上岗记录
     *
     * @param userId 用户ID
     */
    @PreAuthorize("@ss.hasPermi('attendance:postRecord:query:last:time')")
    @GetMapping("/query-last-time")
    public AjaxResult queryLastTime(@RequestParam("userId") Long userId) {
        return AjaxResult.success(attendancePostRecordService.queryLastTime(userId));
    }

    /**
     * 查询当前班次下所有科长上岗记录
     *
     * @return
     */
    @GetMapping("/queryKeIds")
    public AjaxResult queryKeIds() {
        return AjaxResult.success(attendancePostRecordService.queryKeIds());
    }


    /**
     * 根据当前时间确定所属班次日期
     * 班次周期：每日9:00到次日10:00
     *
     * @return 所属班次日期
     */
    private Date determineShiftDate() {
        try {
            Date now = DateUtils.getNowDate();
            String todayStr = DateUtils.getDate();
            String startTime = configService.selectConfigByKey("attendance.post.record.start.time");
            String endTime = configService.selectConfigByKey("attendance.post.record.end.time");

            // 参数校验
            if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
                throw new RuntimeException("班次时间配置缺失");
            }

            // 构造昨天的班次开始时间
            Date yesterday = DateUtils.addDays(now, -1);
            String yesterdayStr = DateUtils.parseDateToStr("yyyy-MM-dd", yesterday);
            Date shiftStartTime = DateUtils.parseDate(yesterdayStr + " " + startTime);

            // 构造今天的班次结束时间
            Date shiftEndTime = DateUtils.parseDate(todayStr + " " + endTime);

            // 如果当前时间在昨天班次时间段内，则属于昨天班次
            // 否则属于今天班次（需要重新计算今天的班次时间段）
            if (now.compareTo(shiftStartTime) >= 0 && now.compareTo(shiftEndTime) < 0) {
                // 属于昨天班次，直接返回已计算的时间段
                return DateUtils.addDays(now, -1);
            } else {
                // 属于今天班次，重新计算时间段
                return now;
            }
        } catch (Exception e) {
            throw new RuntimeException("班次时间计算错误: " + e.getMessage(), e);
        }
    }


    /**
     * 判断用户记录是否已锁定
     *
     * @param userId 用户ID
     * @return 是否已锁定
     */
    private boolean isUserRecordLocked(Long userId) {
        try {
            // 获取当前班次日期
//            Date shiftDate = determineShiftDate();
            Date shiftDate = attendancePostRecordService.selectMaxDateByUserId(null, userId);
            if (shiftDate == null) {
                shiftDate = DateUtils.getNowDate();
            }
            List<AttendancePostRecord> userRecords = attendancePostRecordService.selectTodayRecordsByUserId(null, userId, shiftDate, null);

            // 检查是否有已锁定且在当前班次周期内的记录
//            return userRecords.stream()
//                    .anyMatch(record -> record.getLocked() != null && record.getLocked()
//                            && isWithinCurrentShiftPeriod(record.getLockTime()));
            return userRecords.stream()
                    .anyMatch(record -> record.getLocked() != null && record.getLocked());
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断当前时间是否在班次周期内（当日9:00 - 次日9:00）
     *
     * @param lockTime 锁定时间
     * @return 是否在班次周期内
     */
    private boolean isWithinCurrentShiftPeriod(Date lockTime) {
        if (lockTime == null) {
            return false;
        }

        try {
            Map<String, Date> shiftTime = attendancePostRecordService.getShiftTime();
            Date shiftStartTime = shiftTime.get("start");
            Date shiftEndTime = shiftTime.get("end");
            // 判断锁定时间是否在当前班次周期内
            return !lockTime.before(shiftStartTime) && lockTime.before(shiftEndTime);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据角色标识查询今日上岗用户列表
     */
    @PostMapping("/selectUserListByRoleKey")
    public AjaxResult selectUserListByRoleKey(@RequestBody List<String> roleTypeList) {
        // 计算当前时间对应的班次日期
        Date queryDate = DateUtils.getNowDate();
        List<SysUser> result = attendancePostRecordService.selectUserListByRoleKey(null, roleTypeList);
        return AjaxResult.success(result);
    }
}
