package cn.wisenergy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.DateUtils;
import cn.wisenergy.common.utils.ExcelUtils;
import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.mapper.*;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.dto.*;
import cn.wisenergy.model.enums.*;
import cn.wisenergy.service.StatisticsService;
import cn.wisenergy.service.WorkUserService;
import cn.wisenergy.service.utils.UserRoleLevelUtils;
import com.alibaba.excel.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: nh
 * @create: 2021-01-19 17:19
 **/

@Service
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {
    @Autowired
    private WorkUserService workUserService;

    @Autowired
    private WorkTimeOrderMapper workTimeOrderMapper;

    @Autowired
    private WorkUserDeptMapper workUserDeptMapper;

    @Autowired
    private WorkHolidayMapper workHolidayMapper;

    @Autowired
    private WorkUserMapper workUserMapper;

    @Autowired
    private WorkTypeMapper workTypeMapper;

    @Autowired
    private WorkProjectTimeCostMapper workProjectTimeCostMapper;

    @Autowired
    private WorkProjectMapper workProjectMapper;

    @Autowired
    private WorkDeptMapper workDeptMapper;

    private final static Integer EXCEL_WIDTH = 1000 * 6;


    @Override
    public PageInfo getDayWorkTimeOfMonth(GetMonthlyCollectParam param) {
        log.info("StatisticsServiceImpl[]getMonthlyCollect[]input.param" + param);
        if (param == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 用户权限和对应级别
        List<UserRoleLevelDto> roleUserLevel = UserRoleLevelUtils.getRoleUserLevel(param.getUserId());
        // 用户权限名
        List<String> userAuthority = this.getUserAuthority(roleUserLevel);
        if (CollectionUtil.isEmpty(userAuthority) || !userAuthority.contains(LevelEnum.TIMEEXPORT.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }
        //默认时间为当月
        Integer year = param.getYear();
        Integer month = param.getMonth();
        if (StringUtils.isEmpty(param.getYear()) || StringUtils.isEmpty(param.getMonth())) {
            Date now = new Date();
            year = DateUtil.getYear(now);
            month = DateUtil.getMonth(now) + 1;
        }
        Integer deptId = param.getDeptId();
        if (param.getDeptId() == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        //默认当前页码为1，每页数量为10
        if (param.getCurrentPage() == null) {
            param.setCurrentPage(1);
        }
        if (param.getSize() == null) {
            param.setSize(10);
        }

        // 分页获取部门下所有员工主键
        PageHelper.startPage(param.getCurrentPage(), param.getSize());
        List<Integer> userIds = workUserDeptMapper.listByDeptIdAndStatus(deptId);
        PageInfo pageInfo = new PageInfo(userIds);
        // 获取用户姓名、部门名称
        List<StatisticsTableDto> statisticsTableDtos = workUserMapper.getStatisticsTableDtos(userIds);
        // 获取用户当月每天工时信息
        List<DayWorkTimeAndType> dayWorkTimeAndTypes = workTimeOrderMapper.listByDateAndUserId(year, month, userIds);

        // 将工单集合与对应用户信息封装在一起
        Iterator<StatisticsTableDto> statisticsTableDtoIterator = statisticsTableDtos.iterator();
        while (statisticsTableDtoIterator.hasNext()) {
            StatisticsTableDto statisticsTableDto = statisticsTableDtoIterator.next();
            // 存放一位用户一个月中每天的工时信息
            ArrayList<DayWorkTimeAndType> dayWorkTimeAndTypes1 = new ArrayList<>();
            // 查询出的工时信息遍历
            Iterator<DayWorkTimeAndType> workTimeAndTypeIterator = dayWorkTimeAndTypes.iterator();
            while (workTimeAndTypeIterator.hasNext()) {
                DayWorkTimeAndType dayWorkTimeAndType = workTimeAndTypeIterator.next();
                if (dayWorkTimeAndType.getUserId().equals(statisticsTableDto.getUserId())) {
                    dayWorkTimeAndTypes1.add(dayWorkTimeAndType);
                }
            }
            statisticsTableDto.setDayWorkTimeAndTypeList(dayWorkTimeAndTypes1);
        }
        pageInfo.setList(statisticsTableDtos);
        return pageInfo;
    }

    @Override
    public Map<String, Object> getMonthlyStatistics(Integer userId) {
        log.info("WorkTimeOrderServiceImpl[]getMonthlyStatistics[]input.param" + userId);
        WorkUser user = workUserService.getById(userId);
        // 用户权限与权限对应级别
        List<UserRoleLevelDto> roleUserLevel = UserRoleLevelUtils.getRoleUserLevel(user.getId());
        List<String> userAuthority = this.getUserAuthority(roleUserLevel);
        // 本月第一天
        Date firstDayOfMonth = DateUtil.getCurrentFirstDayOfMonth();
        // 返回数据对象
        Map<String, Object> objects = new HashMap<>();
        // 存放查询条件
        Map<String, Object> map = new HashMap<>();
        // 用户有审批权限
        if (CollectionUtil.isNotEmpty(userAuthority) && userAuthority.contains(LevelEnum.EXAMINE.getLevelName())) {
            // 以审批人、审核状态、开始时间查询本月审批数量
            map.put("reviewerId", userId);
            map.put("startModifyTime", firstDayOfMonth);
            Integer completedCount = workTimeOrderMapper.getCountByCondition(map);
            // 本月驳回未重报数量
            map.put("status", WorkOrderStatus.TURN_DOWN.getCode());
            Integer rejectAndNotResubmit = workTimeOrderMapper.getCountByCondition(map);
            // 移除查询审批人和状态条件
            map.remove("reviewerId");
            map.remove("status");
            map.remove("startModifyTime");

            //待审核包括：新提交和重新提交的
            List<Integer> statusArray = new ArrayList<>();
            statusArray.add(WorkOrderStatus.WAIT_AUDIT.getCode());
            statusArray.add(WorkOrderStatus.RE_SUBMIT.getCode());
            //本月未审批数量查询
            map.put("startWorkDay", firstDayOfMonth);
            map.put("statusArray", statusArray);

            // 查询用户负责的项目和商机id
            List<Integer> projectIdList = workProjectMapper.getProjectIdByManager(userId);

            // 项目和商机的未审批的数
            Integer notCompletedCount1 = 0;
            if (CollectionUtil.isNotEmpty(projectIdList)) {
                map.put("projectIdList", projectIdList);
                notCompletedCount1 = workTimeOrderMapper.getCountByCondition(map);
            }
            // 用户在该权限对应的级别
            List<Integer> rank = this.getUserRank(roleUserLevel, LevelEnum.EXAMINE.getLevelName());
            // 查询用户负责审批的除项目合商机的其余类型
            Integer notCompletedCount2 = 0;
            if (rank.contains(LevelRankEnum.DEPARTMENT_LEVEL.getRank())) {
                map.remove("projectIdList");
                List<WorkType> allType = workTypeMapper.getAll();
                List<Integer> type = new ArrayList<>();
                for (int i = 4; i < allType.size(); i++) {
                    type.add(allType.get(i).getId());
                }
                map.put("typeList", type);
                map.put("deptId", user.getDeptId());
                // 其余类型为审批的条数
                notCompletedCount2 = workTimeOrderMapper.getCountByCondition(map);
            }
            //所有查询结果封装进对象
            ApprovalStatistics approvalStatistics = new ApprovalStatistics();
            approvalStatistics.setApprovalCount(completedCount);
            approvalStatistics.setRejectNotSubmit(rejectAndNotResubmit);
            approvalStatistics.setNotApprovalCount(notCompletedCount1 + notCompletedCount2);
            objects.put("manager", approvalStatistics);
        }

        // 填报情况
        // 本月应填报日期
        List<Date> currentMonthWorkDays = this.currentMonthWorkDays(firstDayOfMonth, true);
        // 本月已填报日期
        List<Date> currentMonthFilledDays = this.currentMonthFilledDays(userId, firstDayOfMonth);
        // 本月未填报日期
        currentMonthWorkDays.removeAll(currentMonthFilledDays);
        int notFilledCount = currentMonthWorkDays.size();
        //本月被现存驳回数
        map.clear();
        map.put("status", StatusEnum.REJECTED.getCode());
        map.put("userId", userId);
        map.put("startWorkDay", firstDayOfMonth);
        Integer countByCondition = workTimeOrderMapper.getCountByCondition(map);

        List<MonthlyWorkingHoursStatistics> monthlyWorkingHoursStatistics = workTimeOrderMapper.statisticsByProjectType(userId, firstDayOfMonth);
        Integer[] status = {StatusEnum.APPROVED.getCode(), StatusEnum.AUTOMATIC_AUDIT.getCode()};
        // 已审批的类型和统计条数
        List<MonthlyWorkingHoursStatistics> monthlyWorkingHoursStatistics1 = workTimeOrderMapper.selectCountByTypeAndStatus(userId, firstDayOfMonth, status);
        for (MonthlyWorkingHoursStatistics workingHoursStatistics : monthlyWorkingHoursStatistics1) {
            for (MonthlyWorkingHoursStatistics monthlyWorkingHoursStatistic : monthlyWorkingHoursStatistics) {
                if (workingHoursStatistics.getProjectType().equals(monthlyWorkingHoursStatistic.getProjectType())) {
                    monthlyWorkingHoursStatistic.setApproved(workingHoursStatistics.getApproved());
                }
            }
        }

        List<Integer> types = monthlyWorkingHoursStatistics.stream().map(MonthlyWorkingHoursStatistics::getProjectType).collect(Collectors.toList());
        // 如果没填写填报类型其中某项，造对象传前端
        List<WorkType> workTypes = workTypeMapper.getAll();
        if (monthlyWorkingHoursStatistics.size() < workTypes.size()) {
            for (WorkType workType : workTypes) {
                if (!types.contains(workType.getId())) {
                    MonthlyWorkingHoursStatistics workingHoursStatistics = new MonthlyWorkingHoursStatistics();
                    workingHoursStatistics.setTypeName(workType.getName());
                    workingHoursStatistics.setProjectType(workType.getId());
                    workingHoursStatistics.setCount(0);
                    workingHoursStatistics.setWorkTime(0);
                    monthlyWorkingHoursStatistics.add(workingHoursStatistics);
                }
            }
        }

        // 赋值未填报天数、被驳回未重报天
        for (MonthlyWorkingHoursStatistics monthlyWorkingHoursStatistic : monthlyWorkingHoursStatistics) {
            if (monthlyWorkingHoursStatistic.getApproved() == null) {
                monthlyWorkingHoursStatistic.setApproved(0);
            }
        }
        objects.put("notFilledCount", notFilledCount);
        objects.put("countByCondition", countByCondition);
        objects.put("user", monthlyWorkingHoursStatistics);
        return objects;
    }

    @Override
    public List<WorkTimeAndCostCollect> getCurrentMonthWorkTimeCollect(Integer userId, String startTime) {
        log.info("StatisticsServiceImpl[]getCurrentMonthWorkTimeCollect[]input.param" + userId + startTime);
        if (userId == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }
        // 用户对象
        WorkUser user = workUserService.getById(userId);
        // 用户权限和对应级别
        List<UserRoleLevelDto> roleUserLevel = UserRoleLevelUtils.getRoleUserLevel(user.getId());
        // 用户权限名
        List<String> userAuthority = this.getUserAuthority(roleUserLevel);
        // 按照人员统计报表权限验证
        if (CollectionUtil.isEmpty(userAuthority) || !userAuthority.contains(LevelEnum.PROJECT_STATISTICS.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.THE_USER_NOT_MANAGER_PLASE_MANAGER_LOGIN);
        }

        // 时间不为空，赋值当月第一天
        if (StringUtil.isNotEmpty(startTime)) {
            Date currentFirstDayOfMonth = DateUtil.getCurrentFirstDayOfMonth();
            startTime = DateUtil.convertDateToYMDStr(currentFirstDayOfMonth);
        }

        // 用户该权限的级别
        List<Integer> rank = this.getUserRank(roleUserLevel, LevelEnum.PROJECT_STATISTICS.getLevelName());

        // 获取所有的类型
        List<WorkType> workTypes = workTypeMapper.getAll();
        // 存储查询的类型
        List<Integer> types = new ArrayList<>();
        // 只存储项目和商机之外的类型
        for (WorkType workType : workTypes) {
            if (workType.getId() != 1 && workType.getId() != 2) {
                types.add(workType.getId());
            }
        }

        List<WorkTimeAndCostCollect> workTimeAndCostCollects = null;
        Map<String, Object> map = new HashMap<>();
        map.put("firstDayOfMonth", startTime);

        // 中心级用户，
        if (rank.contains(LevelRankEnum.CENTRAL_LEVEL.getRank())) {
            // 获取用户所在中心
            WorkDept userDept = workDeptMapper.getById(user.getDeptId());
            // 获取中心下的所有项目和商机工单统计
            map.put("centreId", userDept.getCentreId());
            workTimeAndCostCollects = workProjectTimeCostMapper.selectList(map);

            // 除项目和项目的类型
            map.put("types", types);
            // 获取这些类型的所有工单
            List<WorkTimeAndCostCollect> workTimeAndCostCollect = workTimeOrderMapper.getWorkTimeAndCostCollect(map);
            workTimeAndCostCollects.addAll(workTimeAndCostCollect);

        } else if (rank.contains(LevelRankEnum.DEPARTMENT_LEVEL.getRank())) { // 如果用户的审批权限的级别最高为部门级别
            // 获取部门下的所有项目和商机的工时统计
            map.put("deptId", user.getDeptId());
            map.put("managerId", user.getId());
            workTimeAndCostCollects = workProjectTimeCostMapper.selectList(map);

            // 除项目和项目的类型
            map.put("types", types);
            // 获取这些类型的所有工单
            List<WorkTimeAndCostCollect> workTimeAndCostCollect = workTimeOrderMapper.getWorkTimeAndCostCollect(map);
            workTimeAndCostCollects.addAll(workTimeAndCostCollect);
        } else if (rank.contains(LevelRankEnum.PROJECT_LEVEL.getRank())) { // 如果用户的审批权限的级别最高为项目/商机级别,与其他两种级别不同的是只汇总项目和商机类型的工单
            map.put("managerId", user.getId());
            workTimeAndCostCollects = workProjectTimeCostMapper.selectList(map);
        }

        // 获取查询结果中的类型
        List<Integer> typeList = workTimeAndCostCollects.stream().map(WorkTimeAndCostCollect::getType).collect(Collectors.toList());
        // 如果查询结果不包含查询条件中的类型，造对象传前端
        for (WorkType workType : workTypes) {
            if (!typeList.contains(workType.getId())) {
                // 权限级别为项目级别的用户只返回项目和商机类型的汇总
                if (rank.contains(LevelRankEnum.PROJECT_LEVEL.getRank()) && rank.size() == 1 && types.contains(workType.getId())) {
                    continue;
                }
                WorkTimeAndCostCollect workTimeAndCostCollect1 = new WorkTimeAndCostCollect();
                workTimeAndCostCollect1.setType(workType.getId());
                workTimeAndCostCollect1.setTypeName(workType.getName());
                workTimeAndCostCollects.add(workTimeAndCostCollect1);
            }
        }

        // 给类型赋值类型名称
        for (WorkTimeAndCostCollect timeAndCostCollect : workTimeAndCostCollects) {
            for (WorkType workType : workTypes) {
                if (timeAndCostCollect.getType().equals(workType.getId())) {
                    timeAndCostCollect.setTypeName(workType.getName());
                }
            }
        }
        // 类型总工时
        for (WorkTimeAndCostCollect workTimeAndCostCollect1 : workTimeAndCostCollects) {
            // 类型的总工时
            BigDecimal typeTotalTime = new BigDecimal("0.000");
            List<DeptProjectWorkTimeAndCost> deptProjectWorkTimeAndCosts = workTimeAndCostCollect1.getDeptProjectWorkTimeAndCosts();
            if (CollectionUtil.isNotEmpty(deptProjectWorkTimeAndCosts)) {
                for (DeptProjectWorkTimeAndCost deptProjectWorkTimeAndCost : deptProjectWorkTimeAndCosts) {
                    List<ProjectWorkTimeAndCostStatistics> projectWorkTimeAndCostStatistics = deptProjectWorkTimeAndCost.getProjectWorkTimeAndCostStatistics();
                    for (ProjectWorkTimeAndCostStatistics projectWorkTimeAndCostStatistic : projectWorkTimeAndCostStatistics) {
                        typeTotalTime = typeTotalTime.add(projectWorkTimeAndCostStatistic.getTotalTime());
                    }
                }
            }
            workTimeAndCostCollect1.setWorkTime(typeTotalTime);
        }

        // 排序
        Collections.sort(workTimeAndCostCollects);
        return workTimeAndCostCollects;
    }

    @Override
    public HSSFWorkbook exportWorkTimeExcel(GetMonthlyCollectParam param) {
        log.info("StatisticsServiceImpl[]exportWorkTimeExcel[]input.param{}" + param);
        PageInfo dayWorkTimeOfMonth = this.getDayWorkTimeOfMonth(param);
        Date date = DateUtil.convertStrToDate(param.getYear() + "-" + param.getMonth(), "yyyy-MM");
        // 传参的时间当月总天数
        int dayCount = DateUtil.getMonthDaysArray(date).length;
        // 需要导出的信息
        List<StatisticsTableDto> list = dayWorkTimeOfMonth.getList();
        // 创建工作簿
        HSSFWorkbook sheets = new HSSFWorkbook();
        // 创建表
        HSSFSheet sheet = sheets.createSheet("Sheet1");
        // 普通样式对象
        HSSFCellStyle cellStyle = this.createOrdinaryCellStyle(sheets);
        cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());

        // 节假日样式，底色为绿色,其余样式与普通相同
        HSSFCellStyle cellStyle1 = this.createOrdinaryCellStyle(sheets);
        cellStyle1.setFillForegroundColor(HSSFColor.HSSFColorPredefined.LIGHT_GREEN.getIndex());

        // 当日工时小于8，底色为红色，其余样式与普通相同
        HSSFCellStyle cellStyle2 = this.createOrdinaryCellStyle(sheets);
        cellStyle2.setFillForegroundColor(HSSFColor.HSSFColorPredefined.RED.getIndex());

        // 第一列列宽
        sheet.setColumnWidth(1, EXCEL_WIDTH);
        // 获取本月应上班日期集合
        List<Date> dates = this.currentMonthWorkDays(date, false);
        List<Integer> days = new ArrayList<>();
        for (Date date1 : dates) {
            days.add(DateUtil.getDay(date1));
        }
        // 创建一行
        HSSFRow row1 = sheet.createRow(0);
        // 给第一行赋值
        row1.createCell(0).setCellValue("序号");
        row1.createCell(1).setCellValue("部门名称");
        row1.createCell(2).setCellValue("姓名");
        row1.getCell(0).setCellStyle(cellStyle);
        row1.getCell(1).setCellStyle(cellStyle);
        row1.getCell(2).setCellStyle(cellStyle);

        for (int i = 1; i <= dayCount; i++) {
            HSSFCell cell = row1.createCell(2 + i);
            cell.setCellValue(i + "日");
            // 如果为节假日
            if (!days.contains(i)) {
                cell.setCellStyle(cellStyle1);
            } else {
                cell.setCellStyle(cellStyle);
            }
        }
        Iterator<StatisticsTableDto> iterator = list.iterator();
        int i = 1;
        while (iterator.hasNext()) {
            StatisticsTableDto next = iterator.next();
            // 创建对应的行
            HSSFRow row_i = sheet.createRow(i);
            // 序号
            row_i.createCell(0).setCellValue(i);
            row_i.getCell(0).setCellStyle(cellStyle);
            // 部门名称
            row_i.createCell(1).setCellValue(next.getDeptName());
            row_i.getCell(1).setCellStyle(cellStyle);
            // 姓名
            row_i.createCell(2).setCellValue(next.getUserName());
            row_i.getCell(2).setCellStyle(cellStyle);
            // 日期与工时集合
            List<DayWorkTimeAndType> timeAndTypes = next.getDayWorkTimeAndTypeList();
            // 在excel中对应日期单元格添加工时
            for (DayWorkTimeAndType timeAndType : timeAndTypes) {
                HSSFCell cell = row_i.getCell(timeAndType.getDay() + 2);
                String cellValue = ExcelUtils.getCellValue(cell, true);
                // 单元格为空则直接写入，否则追加
                if (!StringUtils.isEmpty(cellValue)) {
                    cell.setCellValue(timeAndType.getType() + timeAndType.getWorkTime().toString() + "\n" + cellValue);
                } else {
                    HSSFCell emptyCell = row_i.createCell(timeAndType.getDay() + 2);
                    emptyCell.setCellValue(timeAndType.getType() + timeAndType.getWorkTime().toString());
                }
            }
            // 换行
            i++;
        }
        // 给节假日单元格设置单元格格式
        for (int j = 0; j < list.size(); j++) {
            HSSFRow row = sheet.getRow(j + 1);
            for (int r = 0; r < dayCount; r++) {
                HSSFCell cell = null;
                if (row.getCell(r + 3) == null) {
                    cell = row.createCell(r + 3);
                } else {
                    cell = row.getCell(r + 3);
                }
                // 节假日单元格标绿色
                if (!days.contains(r + 1)) {
                    cell.setCellStyle(cellStyle1);
                } else {
                    cell.setCellStyle(cellStyle);
                }
                // 获取单元格中的工时，当日总工时小于8,则单元格底色为红色
                String cellValue = ExcelUtils.getCellValue(cell, true);
                if (StringUtil.isNotEmpty(cellValue)) {
                    Integer numberOfString = this.getNumberOfString(cellValue);
                    if (numberOfString != null && numberOfString < 8) {
                        cell.setCellStyle(cellStyle2);
                    }
                }
            }
        }
        this.closeSheets(sheets);
        return sheets;
    }

    // 将字符串中的1到9的数字相加
    Integer getNumberOfString(String value) {
        value = value.trim();
        if (StringUtil.isEmpty(value)) {
            return null;
        }
        Integer sum = 0;
        for (int i = 0; i < value.length(); i++) {
            if (value.charAt(i) >= 48 && value.charAt(i) <= 57) {
                sum += value.charAt(i) - 48;
            }
        }
        return sum;
    }

    @SneakyThrows
    @Override
    public List<UserWorkTimeStatisticsByProject> getUserWorkTimeStatisticsReport(Integer userId, Integer deptId, String startDate, String endDate) {
        log.info("StatisticsServiceImpl[]getUserWorkTimeStatisticsReport[]" + userId + deptId + startDate + endDate);

        // 获取用户信息
        WorkUser user = workUserService.getById(userId);
        // 获取用户权限和级别
        List<UserRoleLevelDto> workLevels = UserRoleLevelUtils.getRoleUserLevel(user.getId());
        // 用户在该权限下的级别
        List<Integer> rank = this.getUserRank(workLevels, LevelEnum.USER_STATISTICS.getLevelName());
        // 获取用户的权限名
        List<String> userAuthority = this.getUserAuthority(workLevels);
        // 判断是否有该权限
        if (CollectionUtil.isEmpty(userAuthority) || !userAuthority.contains(LevelEnum.USER_STATISTICS.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_AUTHORITY);
        }


        // 不是中心级不能选择部门,只能查看自己部门的信息
        if (!rank.contains(LevelRankEnum.CENTRAL_LEVEL.getRank()) && deptId != user.getDeptId()) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_AUTHORITY);
        }


        // 默认统计截至时间为当天
        if (StringUtil.isEmpty(endDate)) {
            Date date = new Date();
            endDate = DateUtil.convertDateToYMDStr(date);
        }

        // 查询条件
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", startDate);
        map.put("endDate", endDate);
        map.put("deptId", deptId);
        // 存所有项目的加班工时和正常工时
        List<UserWorkTimeStatisticsByProject> userProjectWorkTimeStatistics;
        // 存各个项目下所有人的加班工时和平常工时
        List<UserWorkTimeStatisticsByProject> userProjectWorkTimeStatistics1;

        // 所有项目的统计
        map.put("isAll", false);
        userProjectWorkTimeStatistics = workTimeOrderMapper.getUserProjectWorkTimeStatistics(map);
        if (CollectionUtil.isEmpty(userProjectWorkTimeStatistics)) {
            return null;
        }
        UserWorkTimeStatisticsByProject userWorkTimeStatisticsByProject = new UserWorkTimeStatisticsByProject();
        // 拷贝属性
        BeanUtils.copyProperties(userWorkTimeStatisticsByProject, userProjectWorkTimeStatistics.get(0));
        // 总计
        userWorkTimeStatisticsByProject.setUserName("总计");
        // 将合计和总计
        userProjectWorkTimeStatistics.add(userWorkTimeStatisticsByProject);
        // 所有项目下所有人员的统计
        map.replace("isAll", true);
        userProjectWorkTimeStatistics1 = workTimeOrderMapper.getUserProjectWorkTimeStatistics(map);

        // 合并两个查询结果
        userProjectWorkTimeStatistics.addAll(0, userProjectWorkTimeStatistics1);

        // 查询所有工单类型
        List<WorkType> types = workTypeMapper.getAll();
        for (UserWorkTimeStatisticsByProject userProjectWorkTimeStatistic : userProjectWorkTimeStatistics) {
            // 获取单人的统计，包括合计，为了给除了项目和商机类型的统计将项目名称赋值为类型名称
            List<ProjectWorkTimeAndType> projectWorkTimeAndType = userProjectWorkTimeStatistic.getProjectWorkTimeAndType();
            for (ProjectWorkTimeAndType workTimeAndType : projectWorkTimeAndType) {
                if (StringUtils.isEmpty(workTimeAndType.getProjectName())) {
                    workTimeAndType.setProjectName(types.get(workTimeAndType.getWorkTimeType() - 1).getName());
                }
            }
        }

        // 取出单人的项目工时统计
        for (UserWorkTimeStatisticsByProject userProjectWorkTimeStatistic : userProjectWorkTimeStatistics) {
            int totalTime = 0;
            List<ProjectWorkTimeAndType> projectWorkTimeAndType1 = userProjectWorkTimeStatistic.getProjectWorkTimeAndType();
            // 将相同项目的加班工时和平常工时放在前一个对象，将后一个对象删除
            for (int i = 1; i < projectWorkTimeAndType1.size(); i++) {
                ProjectWorkTimeAndType projectWorkTimeAndType2 = projectWorkTimeAndType1.get(i);
                String projectName = projectWorkTimeAndType2.getProjectName();

                ProjectWorkTimeAndType projectWorkTimeAndType3 = projectWorkTimeAndType1.get(i - 1);
                String projectName1 = projectWorkTimeAndType3.getProjectName();

                if (projectName.equals(projectName1)) {
                    Integer overTime = 0;
                    Integer normalTime = 0;
                    if (projectWorkTimeAndType2.getOverTime() != null) {
                        overTime += projectWorkTimeAndType2.getOverTime();
                    }
                    if (projectWorkTimeAndType3.getOverTime() != null) {
                        overTime += projectWorkTimeAndType3.getOverTime();
                    }
                    if (projectWorkTimeAndType2.getNormalTime() != null) {
                        normalTime += projectWorkTimeAndType2.getNormalTime();
                    }
                    if (projectWorkTimeAndType3.getNormalTime() != null) {
                        normalTime += projectWorkTimeAndType3.getNormalTime();
                    }
                    projectWorkTimeAndType1.get(i - 1).setOverTime(overTime);
                    projectWorkTimeAndType1.get(i - 1).setNormalTime(normalTime);
                    projectWorkTimeAndType1.remove(i);
                }
            }
            for (ProjectWorkTimeAndType projectWorkTimeAndType : projectWorkTimeAndType1) {
                if (projectWorkTimeAndType.getNormalTime() != null) {
                    totalTime += projectWorkTimeAndType.getNormalTime();
                }
                if (projectWorkTimeAndType.getOverTime() != null) {
                    totalTime += projectWorkTimeAndType.getOverTime();
                }
            }

            userProjectWorkTimeStatistic.setTotalTime(totalTime);
        }
        // 计算合计中的每个项目的正常工时加上加班工时的和
        List<ProjectWorkTimeAndType> userProjectWorkTimeStatisticsCollect = userProjectWorkTimeStatistics.get(userProjectWorkTimeStatistics.size() - 1).getProjectWorkTimeAndType();
        for (ProjectWorkTimeAndType projectWorkTimeAndType : userProjectWorkTimeStatisticsCollect) {
            projectWorkTimeAndType.setTotalTime(projectWorkTimeAndType.getNormalTime() + projectWorkTimeAndType.getOverTime());
        }

        return userProjectWorkTimeStatistics;
    }

    @Override
    public List<ProjectStatisticsByMonth> getProjectStatistics(Integer userId, Integer deptId, Integer year, Integer projectId) {
        log.info("StatisticsServiceImpl[]getProjectStatistics[]input.param" + userId + deptId + year + projectId);
        // 获取权限
        if (!UserRoleLevelUtils.isManagerLevel(userId, LevelEnum.PROJECT_STATISTICS.getLevelName())) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.NO_AUTHORITY);
        }
        // 获取在改权限下用户对应的级别
        List<UserRoleLevelDto> roleUserLevel = UserRoleLevelUtils.getRoleUserLevel(userId);
        List<Integer> rank = this.getUserRank(roleUserLevel, LevelEnum.PROJECT_STATISTICS.getLevelName());

        // 默认查询时间为当前
        if (year == null) {
            year = DateUtil.getYear(new Date());
        }
        // 部门主键和项目主键不能同时为空
        if (deptId == null && projectId == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.INPUT_PARAM_IS_NULL);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("year", year);
        if (projectId == null) {
            if (rank.contains(LevelRankEnum.CENTRAL_LEVEL.getRank())) {
                // 查询部门下所有项目，部门主键为空时是默认部门
                map.put("deptId", deptId);
            } else if (rank.contains(LevelRankEnum.DEPARTMENT_LEVEL.getRank())) {
                // 查询部门下所有项目，部门主键是用户的部门主键,当前权限最高级别为部门级别
                map.put("deptId", deptId);
                map.put("managerId", userId);
            } else {
                // 项目/商机级别，以项目管理查询
                map.put("managerId", userId);
            }
        } else {
            map.put("projectId", projectId);
        }

        // 查询所管理项目的项目统计总计
        List<ProjectStatisticsByMonth> projectStatisticsByMonths = workProjectTimeCostMapper.selectListByMonth(map);
        // 合计统计为空，造合计对象
        if (CollectionUtil.isEmpty(projectStatisticsByMonths)) {
            ProjectStatisticsByMonth projectStatisticsByMonth = new ProjectStatisticsByMonth();
            projectStatisticsByMonth.setProjectName("合计");
            List<ProjectStatisticsByMonth.StatisticsDateAndWorkTime> statisticsDateAndWorkTimes = new ArrayList<>();
            projectStatisticsByMonth.setStatisticsDateAndWorkTimes(statisticsDateAndWorkTimes);
            projectStatisticsByMonths.add(projectStatisticsByMonth);
        }

        // 查询每个项目单独统计的集合
        List<ProjectStatisticsByMonth> projectStatisticsByMonths1 = workProjectTimeCostMapper.selectListStatistics(map);

        // 将在查询时间端内未存在填报信息的项目补齐
        if (projectId == null) {
            // 查询项目
            List<WorkProject> projects = workProjectMapper.getListByCriteria(map);
            // 查询统计结果中的项目主键
            List<Integer> queryProjectId = projectStatisticsByMonths1.stream().map(ProjectStatisticsByMonth::getProjectId).collect(Collectors.toList());
            for (WorkProject project : projects) {
                // 如果在查询结果中未存在所管理的项目，新建对象加入统计
                if (!queryProjectId.contains(project.getId())) {
                    ProjectStatisticsByMonth projectStatisticsByMonth = new ProjectStatisticsByMonth();
                    projectStatisticsByMonth.setProjectName(project.getProjectName());
                    projectStatisticsByMonth.setProjectId(project.getId());
                    List<ProjectStatisticsByMonth.StatisticsDateAndWorkTime> statisticsDateAndWorkTimes = new ArrayList<>();
                    projectStatisticsByMonth.setStatisticsDateAndWorkTimes(statisticsDateAndWorkTimes);
                    projectStatisticsByMonths1.add(projectStatisticsByMonth);
                }
            }
        }


        String startDate = "";
        String endDate = "";
        if (projectId != null) {
            // 整个项目所占时间，未结项目截止时间为当月，已结项目截止时间为最后一次统计的时间
            startDate = projectStatisticsByMonths.get(0).getStatisticsDateAndWorkTimes().get(0).getDate();
            endDate = workProjectMapper.getLastDate(projectId);
        } else {
            if (year < DateUtil.getYear(new Date())) {
                startDate = year + "年1月";
                endDate = year + "年12月";
            } else if (year == DateUtil.getYear(new Date())) {
                startDate = DateUtil.convertDateToStr(DateUtil.getFirstDayOfYear(new Date()), "yyyy年M月");
                endDate = DateUtil.convertDateToStr(new Date(), "yyyy年M月");
            }
        }
        // 项目的周期年月集合
        List<String> yearMonthList = this.getYearMonthList(startDate, endDate);

        // 部门主键不为空时，日期格式只有某月。为空时，日期格式为某年统计的第一个月为某年某月，其余为某月
        this.conversionDateFormat(projectStatisticsByMonths, yearMonthList, projectId, true);
        this.conversionDateFormat(projectStatisticsByMonths1, yearMonthList, projectId, false);
        // 将查询结果封装在一起
        projectStatisticsByMonths.addAll(0, projectStatisticsByMonths1);


        // 计算项目工时和成本合计
        this.addProjectStatisticsTotalTime(projectStatisticsByMonths, "项目合计");
        return projectStatisticsByMonths;
    }

    @Override
    public HSSFWorkbook exportUserStatistics(Integer userId, Integer deptId, String startDate, String endDate) {
        log.info("StatisticsServiceImpl[]exportUserStatistics[]param{}" + userId + deptId + startDate + endDate);
        List<UserWorkTimeStatisticsByProject> userWorkTimeStatisticsReport = this.getUserWorkTimeStatisticsReport(userId, deptId, startDate, endDate);
        if (CollectionUtil.isEmpty(userWorkTimeStatisticsReport)) {
            HSSFWorkbook sheets = new HSSFWorkbook();
            HSSFSheet sheet = sheets.createSheet();
            sheet.createRow(0).createCell(0).setCellValue("暂无数据");
            return sheets;
        }
        // 部门信息
        WorkDept dept = workDeptMapper.getById(deptId);
        String statisticsStart = this.simpleDateToYearMonthDay(startDate);
        String statisticsEnd = this.simpleDateToYearMonthDay(endDate);
        // 创建工作簿
        HSSFWorkbook sheets = new HSSFWorkbook();

        HSSFSheet sheet1 = sheets.createSheet("sheet1");

        // 第0行，存部门名称和时间
        HSSFRow row0 = sheet1.createRow(0);
        HSSFCell row0Cell0 = row0.createCell(0);
        row0Cell0.setCellValue("部门：" + dept.getDeptName() + "    时间：" + statisticsStart + "-" + statisticsEnd);


        // 获取合计,写入项目名称和正常工时加班工时表头，除开请假和调休，这两种类型没有正常和加班之分
        UserWorkTimeStatisticsByProject userWorkTimeStatisticsByProject = userWorkTimeStatisticsReport.get(userWorkTimeStatisticsReport.size() - 1);
        List<ProjectWorkTimeAndType> projectWorkTimeAndType = userWorkTimeStatisticsByProject.getProjectWorkTimeAndType();
        // 第1行，序号和人员的表头
        HSSFRow row_1 = sheet1.createRow(1);
        HSSFCell row_1Cell1 = row_1.createCell(0);
        row_1Cell1.setCellValue("序号");
        HSSFCell row_1Cell2 = row_1.createCell(1);
        row_1Cell2.setCellValue("人员");

        // 合计行
        HSSFRow totalRow1 = sheet1.createRow(userWorkTimeStatisticsReport.size() + 1);
        totalRow1.createCell(0).setCellValue("合计");
        // 总计
        HSSFRow totalRow2 = sheet1.createRow(userWorkTimeStatisticsReport.size() + 2);
        totalRow2.createCell(0).setCellValue("总计");
        // 项目行
        HSSFRow row_2 = sheet1.createRow(2);
        for (int i = 0; i < projectWorkTimeAndType.size(); i++) {
            // 项目名称单元格
            HSSFCell row_1Cell;
            // 总计行单元格
            HSSFCell totalRow2Cell;
            if (!"请假".equals(projectWorkTimeAndType.get(i).getProjectName()) && !"调休".equals(projectWorkTimeAndType.get(i).getProjectName())) {
                // 项目名称或类型名称
                row_1Cell = row_1.createCell((i + 1) * 2);
                totalRow2Cell = totalRow2.createCell((i + 1) * 2);
                // 正常工时
                HSSFCell row2Cell = row_2.createCell((i + 1) * 2);
                row2Cell.setCellValue("正常工时");
                // 该项目正常工时合计
                HSSFCell cell1 = totalRow1.createCell((i + 1) * 2);
                cell1.setCellValue(projectWorkTimeAndType.get(i).getNormalTime());
                // 加班工时
                HSSFCell row2Cell1 = row_2.createCell((i + 1) * 2 + 1);
                row2Cell1.setCellValue("加班工时");
                // 该项目加班工时合计
                HSSFCell cell2 = totalRow1.createCell((i + 1) * 2 + 1);
                cell2.setCellValue(projectWorkTimeAndType.get(i).getOverTime());
            } else {
                // 加班工时和正常工时行最后的
                short lastCellNum = row_2.getLastCellNum();
                // 调休和请假的类型名单元格
                row_1Cell = row_1.createCell(lastCellNum);
                // 请假或调休的总计单元格
                totalRow2Cell = totalRow2.createCell(lastCellNum);
                // 类型名称
                row_1Cell.setCellValue(projectWorkTimeAndType.get(i).getProjectName());
                // 请假或调休合计
                HSSFCell cell1 = totalRow1.createCell(lastCellNum);
                cell1.setCellValue(projectWorkTimeAndType.get(i).getNormalTime());
            }
            row_1Cell.setCellValue(projectWorkTimeAndType.get(i).getProjectName());
            totalRow2Cell.setCellValue(projectWorkTimeAndType.get(i).getTotalTime());
        }
        // 所有项目的合计
        String lastProjectName = projectWorkTimeAndType.get(projectWorkTimeAndType.size() - 1).getProjectName();
        short row1_lastCellNum = row_1.getLastCellNum();
        if (lastProjectName.equals("请假") || lastProjectName.equals("调休")) {
            row_1.createCell(row1_lastCellNum).setCellValue("合计");
            totalRow1.createCell(row1_lastCellNum).setCellValue(userWorkTimeStatisticsByProject.getTotalTime());
            totalRow2.createCell(row1_lastCellNum).setCellValue(userWorkTimeStatisticsByProject.getTotalTime());
        } else {
            row_1.createCell(row1_lastCellNum + 1).setCellValue("合计");
            totalRow1.createCell(row1_lastCellNum + 1).setCellValue(userWorkTimeStatisticsByProject.getTotalTime());
            totalRow2.createCell(row1_lastCellNum + 1).setCellValue(userWorkTimeStatisticsByProject.getTotalTime());
        }

        for (int i = 0; i < userWorkTimeStatisticsReport.size() - 2; i++) {
            UserWorkTimeStatisticsByProject userWorkTimeStatisticsByProject1 = userWorkTimeStatisticsReport.get(i);
            List<ProjectWorkTimeAndType> projectWorkTimeAndType1 = userWorkTimeStatisticsByProject1.getProjectWorkTimeAndType();
            HSSFRow row_i = sheet1.createRow(i + 3);
            // 第一列：序号
            HSSFCell cell_0 = row_i.createCell(0);
            cell_0.setCellValue(i + 1);
            // 第二列：姓名
            HSSFCell cell_1 = row_i.createCell(1);
            cell_1.setCellValue(userWorkTimeStatisticsByProject1.getUserName());
            // 项目的工时
            for (int j = 0; j < projectWorkTimeAndType1.size(); j++) {
                for (int k = 2; k < row1_lastCellNum; k++) {
                    // 除开请假和调休
                    if (row_1.getCell(k) != null && !projectWorkTimeAndType1.get(j).getProjectName().equals("请假") && !projectWorkTimeAndType1.get(j).getProjectName().equals("调休") && projectWorkTimeAndType1.get(j).getProjectName().equals(row_1.getCell(k).getStringCellValue())) {
                        if (projectWorkTimeAndType1.get(j).getNormalTime() != null) {
                            HSSFCell cell_k_1 = row_i.createCell(k);
                            cell_k_1.setCellValue(projectWorkTimeAndType1.get(j).getNormalTime());
                        }
                        if (projectWorkTimeAndType1.get(j).getOverTime() != null) {
                            HSSFCell cell_k_2 = row_i.createCell(k + 1);
                            cell_k_2.setCellValue(projectWorkTimeAndType1.get(j).getOverTime());
                        }
                        break;
                    }
                    if (row_1.getCell(k) != null && projectWorkTimeAndType1.get(j).getProjectName().equals(row_1.getCell(k).getStringCellValue())) {
                        if (projectWorkTimeAndType1.get(j).getNormalTime() != null) {
                            HSSFCell cell_k_1 = row_i.createCell(k);
                            cell_k_1.setCellValue(projectWorkTimeAndType1.get(j).getNormalTime());
                        }
                    }

                }
            }
            // 个人合计
            row_i.createCell(row1_lastCellNum).setCellValue(userWorkTimeStatisticsByProject1.getTotalTime());
        }

        // 合并单元格,第一行
        CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 0, row1_lastCellNum + 1);
        sheet1.addMergedRegion(cellRangeAddress);
        setBorderStyle(BorderStyle.THIN, cellRangeAddress, sheet1);
        // 序号
        CellRangeAddress cellRangeAddress1 = new CellRangeAddress(1, 2, 0, 0);
        sheet1.addMergedRegion(cellRangeAddress1);
        setBorderStyle(BorderStyle.THIN, cellRangeAddress1, sheet1);
        // 人员
        CellRangeAddress cellRangeAddress2 = new CellRangeAddress(1, 2, 1, 1);
        sheet1.addMergedRegion(cellRangeAddress2);
        setBorderStyle(BorderStyle.THIN, cellRangeAddress2, sheet1);
        // 合计行
        CellRangeAddress cellRangeAddress3 = new CellRangeAddress(userWorkTimeStatisticsReport.size() + 1, userWorkTimeStatisticsReport.size() + 1, 0, 1);
        sheet1.addMergedRegion(cellRangeAddress3);
        setBorderStyle(BorderStyle.THIN, cellRangeAddress3, sheet1);
        // 项目行和总计行
        for (int i = 0; i < row1_lastCellNum / 2 - 1; i++) {
            // 总计行
            CellRangeAddress cellRangeAddress4 = new CellRangeAddress(userWorkTimeStatisticsReport.size() + 2, userWorkTimeStatisticsReport.size() + 2, i * 2, i * 2 + 1);
            sheet1.addMergedRegion(cellRangeAddress4);
            setBorderStyle(BorderStyle.THIN, cellRangeAddress4, sheet1);
            if (i > 0) {
                CellRangeAddress cellRangeAddress5 = new CellRangeAddress(1, 1, i * 2, i * 2 + 1);
                sheet1.addMergedRegion(cellRangeAddress5);
                setBorderStyle(BorderStyle.THIN, cellRangeAddress5, sheet1);
            }
        }
        // 样式
        HSSFCellStyle ordinaryCellStyle = this.createOrdinaryCellStyle(sheets);
        // 第一行的样式,水平左对齐
        HSSFCellStyle ordinaryCellStyle1 = this.createOrdinaryCellStyle(sheets);
        ordinaryCellStyle1.setAlignment(HorizontalAlignment.LEFT);

        for (Row cells : sheet1) {
            for (Cell cell : cells) {
                cell.setCellStyle(ordinaryCellStyle);
            }
        }
        sheet1.getRow(0).getCell(0).setCellStyle(ordinaryCellStyle1);

        this.closeSheets(sheets);
        return sheets;
    }

    @Override
    public HSSFWorkbook exportProjectStatistics(Integer userId, Integer year, String projectIds) {
        log.info("StatisticsServiceImpl[]exportProjectStatistics[]param{}" + userId + year + projectIds);
        // 将项目主键解析出来
        List<Integer> projectIdList = Arrays.asList(projectIds.split(",")).stream().map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
        // year为空，为今年
        if (year == null) {
            year = DateUtil.getYear(new Date());
        }
        // 查询条件
        Map<String, Object> map = new HashMap<>();
        map.put("year", year);
        map.put("projectIds", projectIdList);
        List<ProjectStatisticsByMonth> projectStatisticsByMonths = workProjectTimeCostMapper.selectListByMonth(map);
        map.put("isAll", false);
        List<ProjectStatisticsByMonth> projectStatisticsByMonths1 = workProjectTimeCostMapper.selectListStatistics(map);
        map.replace("isAll", true);
        List<ProjectStatisticsByMonth> projectStatisticsByMonths2 = workProjectTimeCostMapper.selectListStatistics(map);
        // 计算项目合计
        this.addProjectStatisticsTotalTime(projectStatisticsByMonths, "合计");
        this.addProjectStatisticsTotalTime(projectStatisticsByMonths1, "合计");
        this.addProjectStatisticsTotalTime(projectStatisticsByMonths2, "合计");

        List<String> yearMonthList = this.getYearMonthList(year + "年1月", year + "年12月");
        // 转换日期格式，由yyyy年M月>M月
        this.conversionDateFormat(projectStatisticsByMonths, yearMonthList, null, true);
        this.conversionDateFormat(projectStatisticsByMonths1, yearMonthList, null, true);
        this.conversionDateFormat(projectStatisticsByMonths2, yearMonthList, null, false);

        HSSFWorkbook sheets = new HSSFWorkbook();
        for (ProjectStatisticsByMonth projectStatisticsByMonth : projectStatisticsByMonths) {
            // 项目名作为sheet名
            String projectName = projectStatisticsByMonth.getProjectName();
            HSSFSheet sheet = sheets.createSheet(projectName);
            // 普通样式
            HSSFCellStyle ordinaryCellStyle = this.createOrdinaryCellStyle(sheets);
            // 将人员所在部门列宽加宽
            sheet.setColumnWidth(0, EXCEL_WIDTH);
            // 第一行，部门、项目、时间
            String deptName = projectStatisticsByMonth.getDeptName();
            String date = year + "年";
            HSSFRow row_0 = sheet.createRow(0);
            row_0.createCell(0).setCellValue("部门：" + deptName + "   项目：" + projectName + "    时间：" + date);
            // 合并第一行的前五个单元格
            CellRangeAddress cellRangeAddress2 = new CellRangeAddress(0, 0, 0, 4);
            sheet.addMergedRegion(cellRangeAddress2);
            setBorderStyle(BorderStyle.THIN, cellRangeAddress2, sheet);

            // 人员所在部门、序号，一个部门重复一次
            for (ProjectStatisticsByMonth statisticsByMonth : projectStatisticsByMonths1) {
                if (!statisticsByMonth.getProjectName().equals(projectName)) {
                    continue;
                }
                // 参与项目的其中一个部门
                String deptName1 = statisticsByMonth.getDeptName();
                int lastRowNum = sheet.getLastRowNum();
                HSSFRow row_last = sheet.createRow(lastRowNum + 1);
                // 部门的表头
                row_last.createCell(0).setCellValue("人员所在部门");
                row_last.createCell(1).setCellValue("序号");
                row_last.createCell(2).setCellValue("人员");
                for (int i = 0; i < 12; i++) {
                    row_last.createCell(i + 3).setCellValue(i + 1 + "月");
                }
                row_last.createCell(15).setCellValue("合计");

                //  部门下的人员的统计
                for (int i = 0, k = 0; i < projectStatisticsByMonths2.size(); i++) {
                    ProjectStatisticsByMonth projectStatisticsByMonth1 = projectStatisticsByMonths2.get(i);
                    if (projectStatisticsByMonth1.getDeptName().equals(deptName1) && projectStatisticsByMonth1.getProjectName().equals(projectName)) {
                        k++;
                        int lastRowNum1 = sheet.getLastRowNum();
                        HSSFRow row = sheet.createRow(lastRowNum1 + 1);
                        // 写入人员所在部门、序号、姓名内容
                        row.createCell(0).setCellValue(projectStatisticsByMonth1.getDeptName());
                        row.createCell(1).setCellValue(k);
                        row.createCell(2).setCellValue(projectStatisticsByMonth1.getUserName());
                        // 一个人的统计月份与工时
                        this.writeWorkTimeToExcel(projectStatisticsByMonth1, row, row_last);
                    }
                }
                // 一个部门的合计
                int lastRowNum1 = sheet.getLastRowNum();
                HSSFRow row_total = sheet.createRow(lastRowNum1 + 1);
                row_total.createCell(0).setCellValue("合计");
                // 合并合计单元格
                CellRangeAddress cellRangeAddress1 = new CellRangeAddress(lastRowNum1 + 1, lastRowNum1 + 1, 0, 2);
                sheet.addMergedRegion(cellRangeAddress1);
                setBorderStyle(BorderStyle.THIN, cellRangeAddress1, sheet);
                // 写入部门的工时
                this.writeWorkTimeToExcel(statisticsByMonth, row_total, row_last);
            }
            // 一个项目的总计
            int lastRowNum1 = sheet.getLastRowNum();
            HSSFRow row = sheet.createRow(lastRowNum1 + 1);
            row.createCell(0).setCellValue("总合计");
            // 合并单元格
            CellRangeAddress cellRangeAddress = new CellRangeAddress(lastRowNum1 + 1, lastRowNum1 + 1, 0, 2);
            sheet.addMergedRegion(cellRangeAddress);
            setBorderStyle(BorderStyle.THIN, cellRangeAddress, sheet);


            // 写入项目的总合计工时
            HSSFRow row1 = sheet.getRow(1);
            this.writeWorkTimeToExcel(projectStatisticsByMonth, row, row1);

            for (Row cells : sheet) {
                for (Cell cell : cells) {
                    cell.setCellStyle(ordinaryCellStyle);
                }
            }

        }
        // 释放资源
        this.closeSheets(sheets);
        return sheets;
    }

    //获取一个月应上班日期，如果是当月，时间截至到当天
    public List<Date> currentMonthWorkDays(Date date, boolean toToday) {
        log.info("StatisticsServiceImpl[]currentMonthWorkDays[]input.method");
        // 时间为本月,起始时间为参数时间当月第一天，截至时间为当天。否则，截至时间为当月最后一天
        Date startDate = DateUtil.getFirstDayOfMonth(date);
        Date endDate = null;
        // 当前时间
        Date now = new Date();
        if (DateUtil.getYear(date) == DateUtil.getYear(now) && DateUtil.getMonth(date) == DateUtil.getMonth(now) && toToday) {
            endDate = DateUtil.getStartOfDay(now);
            System.out.println("endDate1 = " + DateUtils.dateToStringWithPattern(endDate, "yyyy-MM-dd"));
        } else {
            endDate = DateUtil.getLastDayByMonth2(date);
            System.out.println("endDate2 = " + DateUtils.dateToStringWithPattern(endDate, "yyyy-MM-dd"));
        }
        // 当月月第一天到截止时间的日期集合
        List<Date> workDays = DateUtil.getDatesBetweenTwoDate(startDate, endDate);

        //除去周末
        Iterator<Date> iterator = workDays.iterator();
        while (iterator.hasNext()) {
            Date next = iterator.next();
            int week = DateUtil.getWeek(next);
            // week为7是星期六，1是星期天
            if (week == 7 || week == 1) {
                iterator.remove();
            }
        }
        //获取当月的节日和周末上班日期
        List<WorkHoliday> specialDates = workHolidayMapper.getByDate(startDate, endDate);
        if (CollectionUtil.isEmpty(specialDates)) {
            return workDays;
        }
        for (WorkHoliday specialDate : specialDates) {
            List<Date> isWorkDays = DateUtil.getDatesBetweenTwoDate(specialDate.getDayStart(), specialDate.getDayEnd());
            //获取的是工作日
            if (specialDate.getDayType().equals(HolidayTypeEnum.WORKING_DAY.getCode())) {
                //在本月应上班集合中加上这天，一般都是放假前后的周末调整上班
                for (Date isWorkDay : isWorkDays) {
                    if (isWorkDay.compareTo(endDate) != 1 && isWorkDay.compareTo(startDate) != -1 && !workDays.contains(isWorkDay)) {
                        workDays.add(isWorkDay);
                    }
                }
            } else {
                //否则就除去假日
                for (Date isWorkDay : isWorkDays) {
                    if (isWorkDay.compareTo(endDate) != 1 && isWorkDay.compareTo(startDate) != -1) {
                        workDays.remove(isWorkDay);
                    }
                }
            }
        }
        Collections.sort(workDays);
        return workDays;
    }

    //获取用户某月已填报的日期,如果一天中只有被驳回则不为已填报
    public List<Date> currentMonthFilledDays(Integer userId, Date date) {
        log.info("StatisticsServiceImpl[]currentMonthFilledDays[]input.method");
        List<Date> currentMonthFilledDays = workTimeOrderMapper.getDaysByDateAndStatus(userId, date);
        return currentMonthFilledDays;
    }

    // 设置单元格基本样式
    HSSFCellStyle createOrdinaryCellStyle(HSSFWorkbook sheets) {
        HSSFCellStyle cellStyle = sheets.createCellStyle();
//        cellStyle.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        // 设置全填充
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 垂直、水平中心对齐
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        //设置下边框的边框线颜色
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        //左边框
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        //上边框
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        //右边框
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 自动换行
        cellStyle.setWrapText(true);
        return cellStyle;
    }


    // 部门主键不为空时，日期格式只有某月。为空时，日期格式为某年统计的第一个月为某年某月，其余为某月
    public void conversionDateFormat(List<ProjectStatisticsByMonth> projectStatisticsByMonths, List<String> yearMonthList, Integer projectId, boolean isTotal) {
        for (ProjectStatisticsByMonth projectStatisticsByMonth : projectStatisticsByMonths) {
            List<ProjectStatisticsByMonth.StatisticsDateAndWorkTime> statisticsDateAndWorkTimes = projectStatisticsByMonth.getStatisticsDateAndWorkTimes();
            for (int i = 0; i < yearMonthList.size(); i++) {
                String s = yearMonthList.get(i);
                String date = new String();
                if (i < statisticsDateAndWorkTimes.size()) {
                    date = statisticsDateAndWorkTimes.get(i).getDate();
                } else {
                    break;
                }
                // 时间不连续，创建对象
                if (!s.equals(date)) {
                    ProjectStatisticsByMonth.StatisticsDateAndWorkTime statisticsDateAndWorkTime = new ProjectStatisticsByMonth.StatisticsDateAndWorkTime();
                    statisticsDateAndWorkTime.setDate(s);
                    statisticsDateAndWorkTime.setYear(Integer.valueOf(s.substring(0, 4)));
                    if (isTotal) {
                        statisticsDateAndWorkTime.setTotalTime(new BigDecimal("0"));
                        statisticsDateAndWorkTime.setCost(new BigDecimal("0"));
                    }
                    statisticsDateAndWorkTimes.add(i, statisticsDateAndWorkTime);
                }
                SimpleDateFormat format = new SimpleDateFormat("yyyy年M月");
                Date parse = null;
                try {
                    parse = format.parse(s);
                    // 在查询部门所有项目统计时，将除开统计首月和月份为一月的时间格式中的年分删除
                    if (projectId != null && DateUtil.getMonth(parse) != 0 && i != 0) {
                        String s1 = yearMonthList.get(i);
                        String substring = s1.substring(5);
                        statisticsDateAndWorkTimes.get(i).setDate(substring);
                    } else if (projectId == null) { // 在查询某个项目全周期统计时，删除所有时间中的年份
                        String s1 = yearMonthList.get(i);
                        String substring = s1.substring(5);
                        statisticsDateAndWorkTimes.get(i).setDate(substring);
                    }
                } catch (ParseException e) {
                    log.info(e.toString());
                }

            }
        }
    }

    // 获取用户权限
    public List<String> getUserAuthority(List<UserRoleLevelDto> roleUserLevel) {
        if (CollectionUtil.isEmpty(roleUserLevel)) {
            return null;
        }
        // 获取权限名
        List<String> collect = roleUserLevel.stream().map(UserRoleLevelDto::getLevelName).collect(Collectors.toList());
        return collect;
    }

    // 获取用户当前权限对应的级别
    public List<Integer> getUserRank(List<UserRoleLevelDto> workLevels, String levelName) {
        List<Integer> rank = new ArrayList<>();
        if (CollectionUtil.isEmpty(workLevels)) {
            return rank;
        }
        for (UserRoleLevelDto workLevel : workLevels) {
            if (workLevel.getLevelName().equals(levelName)) {
                rank.add(workLevel.getRank());
            }
        }
        return rank;
    }

    // 获取开始时间到结束时间这个时间段的所有年月集合
    List<String> getYearMonthList(String startDate, String endDate) {
        String pattern = "yyyy年M月";
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        List<String> list = new ArrayList<>();
        if ("".equals(startDate)) {
            return list;
        }
        Calendar calendar = DateUtil.convertStrToCalendar(startDate, pattern);
        Calendar calendar2 = DateUtil.convertStrToCalendar(endDate, pattern);
        list.add(startDate);
        for (; !calendar.equals(calendar2); ) {
            calendar.add(Calendar.MONTH, 1);
            String format = sdf.format(calendar.getTime());
            list.add(format);
        }
        return list;
    }

    public String simpleDateToYearMonthDay(String simple) {
        String date1 = simple.replaceFirst("-", "年");
        String date2 = date1.replaceFirst("-", "月");
        String date3 = date2 + "日";
        return date3;
    }

    //合并单元格后添加边框
    public static void setBorderStyle(BorderStyle borderStyle, CellRangeAddress region, HSSFSheet sheet) {
        RegionUtil.setBorderBottom(borderStyle, region, sheet); //下边框
        RegionUtil.setBorderLeft(borderStyle, region, sheet); //左边框
        RegionUtil.setBorderRight(borderStyle, region, sheet); //右边框
        RegionUtil.setBorderTop(borderStyle, region, sheet); //上边框
    }

    public void addProjectStatisticsTotalTime(List<ProjectStatisticsByMonth> projectStatisticsByMonths, String statisticsName) {
        for (ProjectStatisticsByMonth projectStatisticsByMonth : projectStatisticsByMonths) {
            // 一条统计的
            List<ProjectStatisticsByMonth.StatisticsDateAndWorkTime> statisticsDateAndWorkTimes = projectStatisticsByMonth.getStatisticsDateAndWorkTimes();
            // 项目合计对象
            ProjectStatisticsByMonth.StatisticsDateAndWorkTime statisticsDateAndWorkTime1 = new ProjectStatisticsByMonth.StatisticsDateAndWorkTime();
            statisticsDateAndWorkTime1.setDate(statisticsName);
            BigDecimal totalTime = new BigDecimal("0.000");
            BigDecimal cost = new BigDecimal("0.000");
            // 统计项目工时和成本
            for (ProjectStatisticsByMonth.StatisticsDateAndWorkTime statisticsDateAndWorkTime : statisticsDateAndWorkTimes) {
                if (statisticsDateAndWorkTime.getTotalTime() != null) {
                    totalTime = totalTime.add(statisticsDateAndWorkTime.getTotalTime());
                }
                if (statisticsDateAndWorkTime.getCost() != null) {
                    cost = cost.add(statisticsDateAndWorkTime.getCost());
                }
            }
            // 项目合计对象赋值
            statisticsDateAndWorkTime1.setTotalTime(totalTime);
            statisticsDateAndWorkTime1.setCost(cost);
            statisticsDateAndWorkTimes.add(statisticsDateAndWorkTime1);
        }
    }

    // 写入对应时间的工时
    public void writeWorkTimeToExcel(ProjectStatisticsByMonth projectStatisticsByMonth1, HSSFRow row, HSSFRow lastRow) {
        // 一个人的统计月份与工时
        List<ProjectStatisticsByMonth.StatisticsDateAndWorkTime> statisticsDateAndWorkTimes = projectStatisticsByMonth1.getStatisticsDateAndWorkTimes();
        // 月份匹配，写入工时
        for (ProjectStatisticsByMonth.StatisticsDateAndWorkTime statisticsDateAndWorkTime : statisticsDateAndWorkTimes) {
            for (int j = 3; j < 16; j++) {
                if (statisticsDateAndWorkTime.getDate().equals(lastRow.getCell(j).getStringCellValue()) && statisticsDateAndWorkTime.getTotalTime() != null) {
                    row.createCell(j).setCellValue(Double.valueOf(statisticsDateAndWorkTime.getTotalTime().stripTrailingZeros().toPlainString()));
                }
            }
        }
    }

    public void closeSheets(HSSFWorkbook sheets) {
        try {
            sheets.close();
        } catch (IOException e) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.DOWNLOAD_ERROR);
        }
    }

}
