diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/controller/ImsDutyMainController.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/controller/ImsDutyMainController.java index 1c7727b..7ec8515 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/controller/ImsDutyMainController.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/controller/ImsDutyMainController.java @@ -1,12 +1,16 @@ package com.hnac.hzims.operational.duty.controller; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.DateUtils; import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.hnac.hzims.common.logs.annotation.OperationAnnotation; import com.hnac.hzims.common.logs.enums.BusinessType; import com.hnac.hzims.common.logs.enums.OperatorType; import com.hnac.hzims.operational.duty.entity.ImsDutyMainEntity; +import com.hnac.hzims.operational.duty.entity.ImsDutyMainReportExcel; import com.hnac.hzims.operational.duty.service.IImsDutyMainService; +import com.hnac.hzims.operational.duty.utils.ExcelMergeHandler; import com.hnac.hzims.operational.duty.vo.ChangeDutyMainVo; import com.hnac.hzims.operational.duty.vo.HomePageDutyMainInfoVo; import com.hnac.hzims.operational.duty.vo.ImsSchedulingVo; @@ -20,9 +24,16 @@ import org.springblade.core.mp.support.Query; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.Func; +import org.springblade.system.feign.ISysClient; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; import java.util.List; @@ -39,6 +50,8 @@ public class ImsDutyMainController extends BladeController { private final IImsDutyMainService imsDutyMainService; + private final ISysClient sysClient; + /** * 详情 */ @@ -204,4 +217,29 @@ public class ImsDutyMainController extends BladeController { public R updateDutyMainInfoVoById(@RequestBody ChangeDutyMainVo changeDutyMainVo) { return imsDutyMainService.updateDutyMainInfoVoById(changeDutyMainVo); } + + @GetMapping("/exportDuty") + @ApiOperation(value = "导出排班计划") + public void exportTemplate(HttpServletResponse response, Integer year, Integer month, Long deptId) throws IOException { + if (Func.isEmpty(deptId)) { + deptId = Long.valueOf(AuthUtil.getDeptId()); + } + List list = imsDutyMainService.getExcelDutyData(year, month, deptId); + + String deptName = sysClient.getDeptName(deptId).getData(); + + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setHeader("content-Type", "application/vnd.ms-excel"); + response.setHeader("Content-Disposition", + "attachment;filename=" + URLEncoder.encode(year + "年" + month + "月" + deptName + "项目排班表.xlsx", StandardCharsets.UTF_8.name())); + + // 从第二行后开始合并 + int mergeRowIndex = 2; + // 需要合并的列 + int[] mergeColumeIndex = {0}; + // 导出Excel,合并第一列相同内容的单元格 + EasyExcel.write(response.getOutputStream(), ImsDutyMainReportExcel.class) + .registerWriteHandler(new ExcelMergeHandler(mergeRowIndex, mergeColumeIndex)).sheet().doWrite(list); + } + } diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/entity/ImsDutyMainReportExcel.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/entity/ImsDutyMainReportExcel.java new file mode 100644 index 0000000..6024392 --- /dev/null +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/entity/ImsDutyMainReportExcel.java @@ -0,0 +1,34 @@ +package com.hnac.hzims.operational.duty.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentLoopMerge; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author tanghaihao + * @date 2023年06月09日 10:56 + */ +@Data +public class ImsDutyMainReportExcel { + @ExcelProperty(value = "排班日期", index = 0) + @ColumnWidth(value = 20) + @ApiModelProperty(value = "排班日期") + private String dutyDate; + + @ExcelProperty(value = "班次", index = 1) + @ColumnWidth(value = 30) + @ApiModelProperty(value = "班次") + private String className; + + @ExcelProperty(value = "班组长", index = 2) + @ColumnWidth(value = 20) + @ApiModelProperty(value = "班组长") + private String managerName; + + @ExcelProperty(value = "组员", index = 3) + @ColumnWidth(value = 100) + @ApiModelProperty(value = "组员") + private String personNames; +} diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/IImsDutyMainService.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/IImsDutyMainService.java index 88845d9..7d3b831 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/IImsDutyMainService.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/IImsDutyMainService.java @@ -1,6 +1,7 @@ package com.hnac.hzims.operational.duty.service; import com.hnac.hzims.operational.duty.entity.ImsDutyMainEntity; +import com.hnac.hzims.operational.duty.entity.ImsDutyMainReportExcel; import com.hnac.hzims.operational.duty.entity.ImsDutyRecEntity; import com.hnac.hzims.operational.duty.vo.*; import com.hnac.hzims.operational.main.vo.DutyPersonalReportVO; @@ -148,4 +149,6 @@ public interface IImsDutyMainService extends BaseService { R getDutyEmergencyEntityById(Long deptId, Long personId); R updateDutyMainInfoVoById(ChangeDutyMainVo changeDutyMainVo); + + List getExcelDutyData(Integer year, Integer month, Long deptId); } diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/impl/ImsDutyMainServiceImpl.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/impl/ImsDutyMainServiceImpl.java index dd03367..9d2de73 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/impl/ImsDutyMainServiceImpl.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/service/impl/ImsDutyMainServiceImpl.java @@ -3,6 +3,7 @@ package com.hnac.hzims.operational.duty.service.impl; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.Query; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.hnac.hzims.monitor.utils.DateUtils; @@ -15,10 +16,7 @@ import com.hnac.hzims.operational.duty.enume.DutyRecStatus; import com.hnac.hzims.operational.duty.enume.JoinStatus; import com.hnac.hzims.operational.duty.mapper.*; import com.hnac.hzims.operational.duty.scheduled.ThreadTask; -import com.hnac.hzims.operational.duty.service.IImsDutyGroupPService; -import com.hnac.hzims.operational.duty.service.IImsDutyMainPersonService; -import com.hnac.hzims.operational.duty.service.IImsDutyMainService; -import com.hnac.hzims.operational.duty.service.IImsDutyMainTemplateService; +import com.hnac.hzims.operational.duty.service.*; import com.hnac.hzims.operational.duty.vo.*; import com.hnac.hzims.operational.main.vo.DutyPersonalReportVO; import com.hnac.hzims.operational.report.vo.DutyReportVO; @@ -33,18 +31,22 @@ import org.springblade.system.user.entity.User; import org.springblade.system.user.feign.IUserClient; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; +import javax.annotation.Resource; import java.sql.Time; import java.text.DateFormat; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -55,23 +57,25 @@ import java.util.stream.Collectors; @Service @Slf4j public class ImsDutyMainServiceImpl extends BaseServiceImpl implements IImsDutyMainService { - @Autowired + @Resource private ImsDutyGroupPMapper imsDutyGroupPMapper; @Autowired private IImsDutyMainTemplateService iImsDutyMainTemplateService; - @Autowired + @Resource private ImsDutyGroupMapper dutyGroupMapper; - @Autowired + @Resource private OperPhenomenonMapper operPhenomenonMapper; - @Autowired + @Resource private ImsDutyMainPersonMapper imsDutyMainPersonMapper; @Autowired private IImsDutyMainPersonService iImsDutyMainPersonService; - @Autowired + @Resource private ImsDutyRecMapper imsDutyRecMapper; @Autowired private IImsDutyGroupPService imsDutyGroupPService; @Autowired + private IImsDutyClassService iImsDutyClassService; + @Resource private DutyGroupGeneratingCapacityMapper groupGeneratingCapacityMapper; @Autowired private IUserClient userClient; @@ -1370,8 +1374,123 @@ public class ImsDutyMainServiceImpl extends BaseServiceImpl getExcelDutyData(Integer year, Integer month, Long deptId) { + List dutyMainReportExcelList = new ArrayList<>(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String yearAndMonth = ""; + + if (month < 10) { + yearAndMonth = year + "-0" + month; + } else { + yearAndMonth = year + "-" + month; + } + + // 获取部门所有班次 + LambdaQueryWrapper classWrapper = new LambdaQueryWrapper(); + classWrapper.eq(ImsDutyClassEntity::getCreateDept, deptId); + List deptDutyClassList = iImsDutyClassService.list(classWrapper); + Map deptDutyClassMap = deptDutyClassList.stream().collect(Collectors.toMap(ImsDutyClassEntity::getId, Function.identity())); + + // 获取部门的所有组员 + List allUserList = userClient.userListByDeptId(deptId).getData(); + Map deptUserMap = allUserList.stream().collect(Collectors.toMap(User::getId, User::getName)); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(ImsDutyMainEntity::getCreateDept, deptId); + wrapper.like(ImsDutyMainEntity::getDutyDate, yearAndMonth); + // 获取部门一个月的排班 + List dutyMainList = this.baseMapper.selectList(wrapper); + + // 获取部门所有分组 + LambdaQueryWrapper groupWrapper = new LambdaQueryWrapper(); + groupWrapper.eq(ImsDutyGroupEntity::getCreateDept, deptId); + List deptDutyGroupList = dutyGroupMapper.selectList(groupWrapper); + Map deptDutyGroupMap = deptDutyGroupList.stream().collect(Collectors.toMap(ImsDutyGroupEntity::getId, Function.identity())); + + // 获取部门所有没有分组的组员 + LambdaQueryWrapper personWrapper = new LambdaQueryWrapper(); + personWrapper.eq(ImsDutyMainPersonEntity::getCreateDept, deptId); + List deptPersonList = imsDutyMainPersonMapper.selectList(personWrapper); + + // 获取本月天数 + int days = getDaysByYearMonth(year, month); + for (int i = 1; i <= days; i++) { + String dateStr = getDate(year, month, i); + List restUserList = userClient.userListByDeptId(deptId).getData(); + + // 获取一天的排班 + List dutyMainDayList = dutyMainList.stream().filter(var -> dateFormat.format(var.getDutyDate()).equals(dateStr)).collect(Collectors.toList()); + + // 循环获取当前日期每个班次组员id + for (ImsDutyMainEntity imsDutyMainEntity : dutyMainDayList) { + ImsDutyMainReportExcel reportExcel = new ImsDutyMainReportExcel(); + + ImsDutyClassEntity imsDutyClass = deptDutyClassMap.get(imsDutyMainEntity.getClassId()); + reportExcel.setDutyDate(dateStr); + reportExcel.setClassName(imsDutyClass.getClassName() + "(" + imsDutyClass.getStartTime() + " - " + imsDutyClass.getEndTime() + ")"); + + List personIds; + String managerName; + if (Func.isNotEmpty(imsDutyMainEntity.getDutyGroupId())) { + // 存在分组id需要从分组中获取组长和组员 + LambdaQueryWrapper groupPWrapper = new LambdaQueryWrapper(); + groupPWrapper.eq(ImsDutyGroupPEntity::getGroupId, imsDutyMainEntity.getDutyGroupId()); + List list = imsDutyGroupPService.list(groupPWrapper); + + managerName = deptUserMap.get(deptDutyGroupMap.get(imsDutyMainEntity.getDutyGroupId()).getManagerId()); + personIds = list.stream().map(ImsDutyGroupPEntity::getPersonId).collect(Collectors.toList()); + } else { + // 不存在分组id从排班人员中获取组长和组员 + List personList = deptPersonList.stream().filter(var -> var.getDutyMainId().equals(imsDutyMainEntity.getId())).collect(Collectors.toList()); + + managerName = deptUserMap.get(personList.get(0).getDutyChargePerson()); + personIds = personList.stream().map(ImsDutyMainPersonEntity::getDutyPerson).collect(Collectors.toList()); + } + + String personNames = ""; + // 获取排班组员名称 + for (int j = 0; j < personIds.size(); j++) { + Long userId = personIds.get(j); + String userName = deptUserMap.get(userId); + // 把排班的组员从休息名单中移除 + restUserList.removeIf(user -> user.getId().equals(userId)); + if (ObjectUtil.isNotEmpty(userName)) { + if (j == personIds.size() - 1) { + personNames += userName; + } else { + personNames += userName + "、"; + } + } + } + reportExcel.setManagerName(managerName); + reportExcel.setPersonNames(personNames); + dutyMainReportExcelList.add(reportExcel); + } + // 剩下组员都休息,添加休息排班 + ImsDutyMainReportExcel restReportExcel = new ImsDutyMainReportExcel(); + restReportExcel.setDutyDate(dateStr); + restReportExcel.setClassName("休息"); + restReportExcel.setManagerName("无班组长"); + String personNames = ""; + // 获取休息组员的名称 + for (int j = 0; j < restUserList.size(); j++) { + User user = restUserList.get(j); + if (ObjectUtil.isNotEmpty(user)) { + if (j == restUserList.size() - 1) { + personNames += user.getName(); + } else { + personNames += user.getName() + "、"; + } + } + } + restReportExcel.setPersonNames(personNames); + dutyMainReportExcelList.add(restReportExcel); + } + return dutyMainReportExcelList; + } /** diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/utils/ExcelMergeHandler.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/utils/ExcelMergeHandler.java new file mode 100644 index 0000000..455e82a --- /dev/null +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/duty/utils/ExcelMergeHandler.java @@ -0,0 +1,110 @@ +package com.hnac.hzims.operational.duty.utils; + +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.List; + +/** + * 合并相同内容的单元格处理类 + * @author tanghaihao + * @date 2023年06月12日 16:43 + */ +public class ExcelMergeHandler implements CellWriteHandler { + private int[] mergeColumnIndex; + private int mergeRowIndex; + + public ExcelMergeHandler() { + } + + /** + * + * @param mergeRowIndex 从第几行后开始合并,行数从1开始 + * @param mergeColumnIndex 需要合并的列,数组类型可以选择多列,列数从0开始 + */ + public ExcelMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) { + this.mergeRowIndex = mergeRowIndex; + this.mergeColumnIndex = mergeColumnIndex; + } + + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + + //当前行 + int curRowIndex = cell.getRowIndex(); + //当前列 + int curColIndex = cell.getColumnIndex(); + + if (curRowIndex > mergeRowIndex) { + for (int i = 0; i < mergeColumnIndex.length; i++) { + if (curColIndex == mergeColumnIndex[i]) { + mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); + break; + } + } + } + } + + + /** + * 当前单元格向上合并 + * + * @param writeSheetHolder + * @param cell 当前单元格 + * @param curRowIndex 当前行 + * @param curColIndex 当前列 + */ + private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { + Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); + // 将当前单元格数据与上一个单元格数据比较 + Boolean dataBool = preData.equals(curData); + String s1 = cell.getRow().getCell(0).getStringCellValue(); + String s2 = cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue(); + Boolean bool = s1.compareTo(s2) == 0 ? true:false; + if (dataBool && bool) { + Sheet sheet = writeSheetHolder.getSheet(); + List mergeRegions = sheet.getMergedRegions(); + boolean isMerged = false; + for (int i = 0; i < mergeRegions.size() && !isMerged; i++) { + CellRangeAddress cellRangeAddr = mergeRegions.get(i); + // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 + if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { + sheet.removeMergedRegion(i); + cellRangeAddr.setLastRow(curRowIndex); + sheet.addMergedRegion(cellRangeAddr); + isMerged = true; + } + } + // 若上一个单元格未被合并,则新增合并单元 + if (!isMerged) { + CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); + sheet.addMergedRegion(cellRangeAddress); + } + } + } +}