xiongzhu 5 ani în urmă
părinte
comite
482d030e1a

+ 2 - 0
src/main/java/com/x1ongzhu/wisFactory/domain/StaffInfo.java

@@ -42,4 +42,6 @@ public class StaffInfo extends BaseEntity {
 
     @ApiModelProperty("联系方式")
     private String phone;
+
+    private long rev;
 }

+ 159 - 2
src/main/java/com/x1ongzhu/wisFactory/service/AttendanceService.java

@@ -1,5 +1,9 @@
 package com.x1ongzhu.wisFactory.service;
 
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
 import com.x1ongzhu.wisFactory.config.Constants;
 import com.x1ongzhu.wisFactory.domain.*;
 import com.x1ongzhu.wisFactory.dto.StaffAttendanceBrief;
@@ -9,13 +13,19 @@ import com.x1ongzhu.wisFactory.enums.HolidayType;
 import com.x1ongzhu.wisFactory.exception.BusinessException;
 import com.x1ongzhu.wisFactory.repo.*;
 import com.x1ongzhu.wisFactory.utils.DateTimeUtils;
+import com.x1ongzhu.wisFactory.utils.excel.*;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.Range;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 
+import java.io.IOException;
+import java.io.OutputStream;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
@@ -24,7 +34,9 @@ import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
+import java.util.function.IntUnaryOperator;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
 @Service
@@ -454,7 +466,7 @@ public class AttendanceService {
                         .name(staffInfo.getName())
                         .department(staffInfo.getDepartment())
                         .date(date)
-                        .weekDay(DateTimeUtils.format(date, "E"))
+                        .weekDay(DateTimeUtils.weekDay(date))
                         .absent(true)
                         .build();
             }
@@ -466,7 +478,7 @@ public class AttendanceService {
                 .name(staffInfo.getName())
                 .department(staffInfo.getDepartment())
                 .date(date)
-                .weekDay(DateTimeUtils.format(date, "E"))
+                .weekDay(DateTimeUtils.weekDay(date))
                 .start(timeBucket.start)
                 .end(timeBucket.end)
                 .remark(timeBucket.subList.stream()
@@ -588,4 +600,149 @@ public class AttendanceService {
             this.subList = subList;
         }
     }
+
+
+    public void exportRaw(LocalDate start, LocalDate end, List<String> departmentNames, OutputStream outputStream) throws IOException {
+        ExcelUtil excelUtil = ExcelUtil.Create();
+        List<String> dates = new ArrayList<>();
+        List<String> weeks = new ArrayList<>();
+
+        Font cellStyleFont = excelUtil.getWorkbook().createFont();
+        cellStyleFont.setFontHeightInPoints((short) 18);
+        cellStyleFont.setColor(IndexedColors.BLACK.getIndex());
+        cellStyleFont.setBold(true);
+        cellStyleFont.setFontName("微软雅黑");
+
+        CellStyle cellStyle = excelUtil.getWorkbook().createCellStyle();
+        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中设置
+        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        cellStyle.setWrapText(true);
+        cellStyle.setBorderRight(BorderStyle.THIN);
+        cellStyle.setBorderLeft(BorderStyle.THIN);
+        cellStyle.setBorderTop(BorderStyle.THIN);
+        cellStyle.setBorderBottom(BorderStyle.THIN);
+        cellStyle.setFont(cellStyleFont);
+
+        Font nameCellStyleFont = excelUtil.getWorkbook().createFont();
+        cellStyleFont.setFontHeightInPoints((short) 12);
+        cellStyleFont.setColor(IndexedColors.BLACK.getIndex());
+        cellStyleFont.setFontName("微软雅黑");
+
+        CellStyle nameCellStyle1 = nameStyle1(excelUtil.getWorkbook());
+        CellStyle nameCellStyle2 = nameStyle2(excelUtil.getWorkbook());
+
+        int totalDays = (int) (ChronoUnit.DAYS.between(start, end) + 1);
+        for (int i = 0; i < totalDays; i++) {
+            dates.add(DateTimeUtils.format(start.plusDays(i), "dd"));
+            weeks.add(DateTimeUtils.weekDay(start.plusDays(i)));
+        }
+        for (String departmentName : departmentNames) {
+            String[] arr = departmentName.split("/");
+            String sheetName = arr[arr.length - 1];
+            excelUtil.createSheet(sheetName);
+            excelUtil.writeRow(RowModel.Builder()
+                    .addCell(CellModel.builder()
+                            .startColumn(0)
+                            .endColumn(totalDays - 1)
+                            .style(cellStyle)
+                            .value("考勤记录表")
+                            .build())
+                    .build(), (short) (32 * 20));
+            excelUtil.writeRow(RowModel.Builder()
+                    .addCell(CellModel.builder()
+                            .startColumn(0)
+                            .endColumn(totalDays - 1)
+                            .value("部门" + departmentName + "        记录时间:" + DateTimeUtils
+                                    .format(start, "yyyy-MM-dd") + " ~ "
+                                    + DateTimeUtils.format(end, "yyyy-MM-dd"))
+                            .build())
+                    .build(), (short) (25 * 20));
+            excelUtil.writeRow(RowModel.Builder()
+                    .addCells(dates.toArray(new String[0]))
+                    .build());
+            excelUtil.writeRow(RowModel.Builder()
+                    .addCells(weeks.toArray(new String[0]))
+                    .build());
+            for (StaffInfo staffInfo : staffInfoRepo.findByDepartment(departmentName)) {
+                if (totalDays > 10) {
+                    excelUtil.writeRow(RowModel.Builder()
+                            .addCell(CellModel.builder()
+                                    .startColumn(0)
+                                    .endColumn((int) Math.floor(totalDays / 2.0) - 1)
+                                    .value("姓名:" + staffInfo.getName())
+                                    .style(nameCellStyle1)
+                                    .build())
+                            .addCell(CellModel.builder()
+                                    .startColumn((int) Math.floor(totalDays / 2.0))
+                                    .endColumn(totalDays - 1)
+                                    .value("部门:" + departmentName)
+                                    .style(nameCellStyle2)
+                                    .build())
+                            .build(), (short) (25 * 20));
+                } else {
+                    excelUtil.writeRow(RowModel.Builder()
+                            .addCell(CellModel.builder()
+                                    .startColumn(0)
+                                    .endColumn(totalDays - 1)
+                                    .value("姓名:" + staffInfo.getName() + "        部门:" + departmentName)
+                                    .build())
+                            .build(), (short) (25 * 20));
+                }
+                List<StaffAccess> staffAccessList = staffAccessRepo
+                        .findByEmployNoAndAccessTimeBetweenOrderByAccessTimeAsc(staffInfo.getEmployNo(), start
+                                .atStartOfDay(), end.atTime(Constants.TIME_MAX));
+                excelUtil.writeRow(RowModel.Builder()
+                        .addCells(IntStream.range(0, (int) ChronoUnit.DAYS.between(start, end) + 1)
+                                .mapToObj(i -> staffAccessList.stream()
+                                        .filter(staffAccess -> {
+                                            LocalDate date = start.plusDays(i);
+                                            return staffAccess.getAccessTime().isAfter(date.atStartOfDay())
+                                                    && staffAccess.getAccessTime()
+                                                    .isBefore(date.atTime(Constants.TIME_MAX));
+                                        })
+                                        .sorted(Comparator.comparing(StaffAccess::getAccessTime))
+                                        .map(staffAccess -> DateTimeUtils.format(staffAccess.getAccessTime(), "HH:mm"))
+                                        .distinct()
+                                        .collect(Collectors.joining("\r\n"))).toArray(String[]::new))
+                        .build());
+            }
+        }
+        excelUtil.to(outputStream);
+    }
+
+    private CellStyle nameStyle1(Workbook workbook) {
+        Font nameCellStyleFont = workbook.createFont();
+        nameCellStyleFont.setFontHeightInPoints((short) 12);
+        nameCellStyleFont.setColor(IndexedColors.BLACK.getIndex());
+        nameCellStyleFont.setFontName("微软雅黑");
+
+        CellStyle nameCellStyle = workbook.createCellStyle();
+        nameCellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中设置
+        nameCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        nameCellStyle.setWrapText(true);
+        nameCellStyle.setBorderRight(BorderStyle.NONE);
+        nameCellStyle.setBorderLeft(BorderStyle.THIN);
+        nameCellStyle.setBorderTop(BorderStyle.THIN);
+        nameCellStyle.setBorderBottom(BorderStyle.THIN);
+        nameCellStyle.setFont(nameCellStyleFont);
+        return nameCellStyle;
+    }
+
+    private CellStyle nameStyle2(Workbook workbook) {
+        Font nameCellStyleFont = workbook.createFont();
+        nameCellStyleFont.setFontHeightInPoints((short) 12);
+        nameCellStyleFont.setColor(IndexedColors.BLACK.getIndex());
+        nameCellStyleFont.setFontName("微软雅黑");
+
+        CellStyle nameCellStyle = workbook.createCellStyle();
+        nameCellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中设置
+        nameCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        nameCellStyle.setWrapText(true);
+        nameCellStyle.setBorderRight(BorderStyle.THIN);
+        nameCellStyle.setBorderLeft(BorderStyle.NONE);
+        nameCellStyle.setBorderTop(BorderStyle.THIN);
+        nameCellStyle.setBorderBottom(BorderStyle.THIN);
+        nameCellStyle.setFont(nameCellStyleFont);
+        return nameCellStyle;
+    }
 }

+ 3 - 0
src/main/java/com/x1ongzhu/wisFactory/service/StaffInfoService.java

@@ -38,6 +38,7 @@ public class StaffInfoService {
     }
 
     public void importStaff(MultipartFile file) throws IOException {
+        long rev = System.currentTimeMillis();
         List<StaffInfoImportModel> list = EasyExcel.read(file.getInputStream()).head(StaffInfoImportModel.class)
                 .sheet().doReadSync();
         list.stream().parallel().forEach(model -> {
@@ -58,6 +59,7 @@ public class StaffInfoService {
                         .department(model.getDepartment())
                         .employNo(employNo)
                         .phone(model.getPhone())
+                        .rev(rev)
                         .build();
             } else {
                 staffInfo.setCards(cards);
@@ -66,6 +68,7 @@ public class StaffInfoService {
                 staffInfo.setDepartment(model.getDepartment());
                 staffInfo.setEmployNo(employNo);
                 staffInfo.setPhone(model.getPhone());
+                staffInfo.setRev(rev);
             }
             staffInfoRepo.save(staffInfo);
         });

+ 26 - 0
src/main/java/com/x1ongzhu/wisFactory/utils/excel/CellModel.java

@@ -0,0 +1,26 @@
+package com.x1ongzhu.wisFactory.utils.excel;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.poi.ss.usermodel.CellStyle;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class CellModel {
+    private int       startColumn;
+    private int       endColumn;
+    private String    value;
+    private CellStyle style;
+
+    public CellModel(int startColumn, int endColumn, String value) {
+        this.startColumn = startColumn;
+        this.endColumn = endColumn;
+        this.value = value;
+    }
+
+
+}

+ 213 - 0
src/main/java/com/x1ongzhu/wisFactory/utils/excel/ExcelUtil.java

@@ -0,0 +1,213 @@
+package com.x1ongzhu.wisFactory.utils.excel;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.RegionUtil;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExcelUtil {
+    private Workbook              workbook;
+    private List<Sheet>           sheets;
+    private int                   currentSheet = -1;
+    private Map<Integer, Integer> rowNum;
+    private XSSFCellStyle         titleStyle;
+    private XSSFCellStyle         headerStyle;
+    private XSSFCellStyle         cellStyle;
+    private XSSFCellStyle         currentStyle;
+
+    public enum Style {
+        TITLE, HEADER, CELL
+    }
+
+    public static ExcelUtil Create() {
+        return new ExcelUtil();
+    }
+
+    public ExcelUtil() {
+        sheets = new ArrayList<>();
+        workbook = new XSSFWorkbook();
+        rowNum = new HashMap<>();
+
+        titleStyle = (XSSFCellStyle) ExcelUtils.titleCellStyle(workbook);
+        headerStyle = (XSSFCellStyle) ExcelUtils.headerCellStyle(workbook);
+        cellStyle = (XSSFCellStyle) ExcelUtils.contentCellStyle(workbook);
+
+        currentStyle = cellStyle;
+    }
+
+    public ExcelUtil createSheet(String sheetName, int... columnWidths) {
+        Sheet sheet = workbook.createSheet(sheetName);
+        for (int i = 0; i < columnWidths.length; i++) {
+            sheet.setColumnWidth(i, columnWidths[i] * 256);
+        }
+
+        sheet.setDefaultColumnWidth(60);
+        sheets.add(sheet);
+        currentSheet = sheets.size() - 1;
+        rowNum.putIfAbsent(currentSheet, 0);
+        return this;
+    }
+
+    public ExcelUtil createSheet(String sheetName) {
+        Sheet sheet = workbook.createSheet(sheetName);
+        sheets.add(sheet);
+        currentSheet = sheets.size() - 1;
+        rowNum.putIfAbsent(currentSheet, 0);
+        return this;
+    }
+
+    public ExcelUtil writeData(List<List<CellModel>> data) {
+        Sheet sheet = sheets.get(currentSheet);
+        data.forEach(cells -> {
+            int currentRowNum = rowNum.get(currentSheet);
+            Row row = sheet.createRow(currentRowNum);
+            cells.forEach(cellModel -> {
+                writeCell(sheet, row, cellModel);
+            });
+            currentRowNum++;
+            rowNum.put(currentSheet, currentRowNum);
+        });
+        return this;
+    }
+
+    public ExcelUtil writeRows(List<RowModel> data) {
+        data.forEach(this::writeRow);
+        return this;
+    }
+
+    public ExcelUtil writeRow(RowModel rowModel) {
+        Sheet sheet = sheets.get(currentSheet);
+        int currentRowNum = rowNum.get(currentSheet);
+        Row row = sheet.createRow(currentRowNum);
+        rowModel.getCells().forEach(cellModel -> writeCell(sheet, row, cellModel));
+        currentRowNum++;
+        rowNum.put(currentSheet, currentRowNum);
+        return this;
+    }
+
+    public ExcelUtil writeRow(RowModel rowModel, short height) {
+        Sheet sheet = sheets.get(currentSheet);
+        int currentRowNum = rowNum.get(currentSheet);
+        Row row = sheet.createRow(currentRowNum);
+        row.setHeight(height);
+        rowModel.getCells().forEach(cellModel -> writeCell(sheet, row, cellModel));
+        currentRowNum++;
+        rowNum.put(currentSheet, currentRowNum);
+        return this;
+    }
+
+    public ExcelUtil writeRow(CellModel... cells) {
+        Sheet sheet = sheets.get(currentSheet);
+        int currentRowNum = rowNum.get(currentSheet);
+        Row row = sheet.createRow(currentRowNum);
+        for (CellModel cell : cells) {
+            writeCell(sheet, row, cell);
+        }
+        currentRowNum++;
+        rowNum.put(currentSheet, currentRowNum);
+        return this;
+    }
+
+    public ExcelUtil writeHeaders(List<RowModel> data) {
+        data.forEach(this::writeHeader);
+        return this;
+    }
+
+    public ExcelUtil writeHeader(RowModel rowModel) {
+        Sheet sheet = sheets.get(currentSheet);
+        int currentRowNum = rowNum.get(currentSheet);
+        Row row = sheet.createRow(currentRowNum);
+        rowModel.getCells().forEach(cellModel -> {
+            cellModel.setStyle(headerStyle);
+            writeCell(sheet, row, cellModel);
+        });
+        currentRowNum++;
+        rowNum.put(currentSheet, currentRowNum);
+        return this;
+    }
+
+    public ExcelUtil writeHeader(CellModel... cells) {
+        Sheet sheet = sheets.get(currentSheet);
+        int currentRowNum = rowNum.get(currentSheet);
+        Row row = sheet.createRow(currentRowNum);
+        for (CellModel cell : cells) {
+            cell.setStyle(headerStyle);
+            writeCell(sheet, row, cell);
+        }
+        currentRowNum++;
+        rowNum.put(currentSheet, currentRowNum);
+        return this;
+    }
+
+    private void writeCell(Sheet sheet, Row row, CellModel cellModel) {
+        Cell cell = row.createCell(cellModel.getStartColumn());
+        cell.setCellValue(cellModel.getValue());
+        if (cellModel.getEndColumn() > cellModel.getStartColumn()) {
+            CellRangeAddress region = new CellRangeAddress(rowNum.get(currentSheet), rowNum.get(currentSheet), cellModel
+                    .getStartColumn(), cellModel.getEndColumn());
+            sheet.addMergedRegion(region);
+            setBorderStyle(BorderStyle.THIN, region, sheet);
+        }
+        if (cellModel.getStyle() != null) {
+            cell.setCellStyle(cellModel.getStyle());
+        } else {
+            cell.setCellStyle(currentStyle);
+        }
+    }
+
+    public ExcelUtil style(Style style) {
+        if (style == Style.TITLE) {
+            currentStyle = titleStyle;
+        } else if (style == Style.HEADER) {
+            currentStyle = headerStyle;
+        } else if (style == Style.CELL) {
+            currentStyle = cellStyle;
+        }
+        return this;
+    }
+
+    public void setBorderStyle(BorderStyle border, CellRangeAddress region, Sheet sheet) {
+        RegionUtil.setBorderBottom(border, region, sheet);
+        RegionUtil.setBorderLeft(border, region, sheet);
+        RegionUtil.setBorderRight(border, region, sheet);
+        RegionUtil.setBorderTop(border, region, sheet);
+    }
+
+    public void to(OutputStream outputStream) throws IOException {
+        workbook.write(outputStream);
+        workbook.close();
+    }
+
+    public void toFile(String fileName) throws IOException {
+        try (OutputStream outputStream = new FileOutputStream(fileName)) {
+            workbook.write(outputStream);
+        } finally {
+            workbook.close();
+        }
+    }
+
+    public Workbook getWorkbook() {
+        return workbook;
+    }
+
+    public void setTitleStyle(XSSFCellStyle titleStyle) {
+        this.titleStyle = titleStyle;
+    }
+
+    public void setHeaderStyle(XSSFCellStyle headerStyle) {
+        this.headerStyle = headerStyle;
+    }
+
+    public void setCellStyle(XSSFCellStyle cellStyle) {
+        this.cellStyle = cellStyle;
+    }
+}

+ 60 - 0
src/main/java/com/x1ongzhu/wisFactory/utils/excel/ExcelUtils.java

@@ -1,6 +1,7 @@
 package com.x1ongzhu.wisFactory.utils.excel;
 
 import com.alibaba.excel.EasyExcel;
+import org.apache.poi.ss.usermodel.*;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -26,4 +27,63 @@ public class ExcelUtils<T> {
                 .registerConverter(new BooleanConverter())
                 .doWrite(data);
     }
+
+
+    public static CellStyle contentCellStyle(Workbook workbook) {
+        // 正文样式
+        Font cellStyleFont = workbook.createFont();
+        cellStyleFont.setFontHeightInPoints((short) 12);
+        cellStyleFont.setColor(IndexedColors.BLACK.getIndex());
+        cellStyleFont.setFontName("微软雅黑");
+
+        CellStyle cellStyle = workbook.createCellStyle();
+        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中设置
+        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        cellStyle.setWrapText(true);
+        cellStyle.setBorderRight(BorderStyle.THIN);
+        cellStyle.setBorderLeft(BorderStyle.THIN);
+        cellStyle.setBorderTop(BorderStyle.THIN);
+        cellStyle.setBorderBottom(BorderStyle.THIN);
+        cellStyle.setFont(cellStyleFont);
+        return cellStyle;
+    }
+
+    public static CellStyle headerCellStyle(Workbook workbook) {
+        // 文件头样式
+        CellStyle headerStyle = workbook.createCellStyle();
+        headerStyle.setAlignment(HorizontalAlignment.CENTER);
+        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 前景色
+        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 颜色填充方式
+        headerStyle.setWrapText(true);
+        headerStyle.setBorderRight(BorderStyle.THIN); // 设置边界
+        headerStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
+        headerStyle.setBorderLeft(BorderStyle.THIN);
+        headerStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
+        headerStyle.setBorderTop(BorderStyle.THIN);
+        headerStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
+        headerStyle.setBorderBottom(BorderStyle.THIN);
+        headerStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+        Font headerFont = workbook.createFont();
+        headerFont.setFontHeightInPoints((short) 12);
+        headerFont.setColor(IndexedColors.BLACK.getIndex());
+        headerFont.setFontName("微软雅黑");
+        headerStyle.setFont(headerFont);
+        return headerStyle;
+    }
+
+    public static CellStyle titleCellStyle(Workbook workbook) {
+        // 文件头样式
+        CellStyle titleStyle = workbook.createCellStyle();
+        titleStyle.setAlignment(HorizontalAlignment.CENTER); // 水平对齐
+        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直对齐
+        titleStyle.setLocked(true); // 样式锁定
+        titleStyle.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
+        Font titleFont = workbook.createFont();
+        titleFont.setFontHeightInPoints((short) 16);
+        titleFont.setBold(true);
+        titleFont.setFontName("微软雅黑");
+        titleStyle.setFont(titleFont);
+        return titleStyle;
+    }
 }

+ 33 - 0
src/main/java/com/x1ongzhu/wisFactory/utils/excel/LocalTimeConverter.java

@@ -0,0 +1,33 @@
+package com.x1ongzhu.wisFactory.utils.excel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+public class LocalTimeConverter implements Converter<LocalTime> {
+    @Override
+    public Class supportJavaTypeKey() {
+        return LocalTime.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public LocalTime convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return LocalTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("HH:mm"));
+    }
+
+    @Override
+    public CellData convertToExcelData(LocalTime localTime, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        return new CellData(DateTimeFormatter.ofPattern("HH:mm").format(localTime));
+    }
+}

+ 82 - 0
src/main/java/com/x1ongzhu/wisFactory/utils/excel/RowModel.java

@@ -0,0 +1,82 @@
+package com.x1ongzhu.wisFactory.utils.excel;
+
+import lombok.Data;
+import org.apache.poi.ss.usermodel.CellStyle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Data
+public class RowModel {
+    private Integer         rowNum;
+    private List<CellModel> cells;
+
+    public static Builder Builder() {
+        return new Builder();
+    }
+
+    public RowModel() {
+        this.cells = new ArrayList<>();
+    }
+
+    public RowModel(CellModel... cells) {
+        this.cells = new ArrayList<>(Arrays.asList(cells));
+    }
+
+    public RowModel(String... values) {
+        List<CellModel> list = new ArrayList<>();
+        for (int i = 0; i < values.length; i++) {
+            list.add(new CellModel(i, i, values[i]));
+        }
+        this.cells = list;
+    }
+
+    public static class Builder {
+        private int             row;
+        private List<CellModel> cellModels;
+        private CellStyle       style;
+
+        public Builder() {
+            this.row = 0;
+            this.cellModels = new ArrayList<>();
+        }
+
+        public Builder style(CellStyle cellStyle) {
+            this.style = cellStyle;
+            return this;
+        }
+
+        public Builder rowNum(int row) {
+            this.row = row;
+            return this;
+        }
+
+        public Builder addCell(CellModel cellModel) {
+            cellModels.add(cellModel);
+            return this;
+        }
+
+        public Builder addCells(String... values) {
+            for (int i = 0; i < values.length; i++) {
+                cellModels.add(CellModel.builder()
+                        .startColumn(i)
+                        .value(values[i])
+                        .build());
+            }
+            return this;
+        }
+
+        public RowModel build() {
+            if (style!=null){
+                for (CellModel cellModel : this.cellModels) {
+                    cellModel.setStyle(style);
+                }
+            }
+            RowModel rowModel = new RowModel();
+            rowModel.setRowNum(this.row);
+            rowModel.setCells(this.cellModels);
+            return rowModel;
+        }
+    }
+}

+ 11 - 0
src/main/java/com/x1ongzhu/wisFactory/web/AttendanceController.java

@@ -121,6 +121,17 @@ public class AttendanceController extends BaseController {
         }
     }
 
+    @GetMapping("/departmentRaw")
+    @ResponseBody
+    public void departmentRaw(HttpServletResponse response, @RequestParam List<String> departments,
+                              @RequestParam LocalDate start, @RequestParam LocalDate end) throws IOException {
+        Map<String, List<StaffAttendanceBrief>> map = departmentReport(departments, start, end);
+        response.setContentType("application/vnd.ms-excel");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-Disposition", "attachment;filename=考勤记录表.xlsx");
+        attendanceService.exportRaw(start, end, departments, response.getOutputStream());
+    }
+
     @GetMapping("/staffReport")
     @ResponseBody
     public List<StaffAttendanceBrief> staffReport(@RequestParam List<Long> ids,

+ 39 - 2
src/main/vue/src/views/DepartmentAttendanceReport.vue

@@ -21,6 +21,7 @@
                 placeholder="请选择日期"
                 class="filter-item"
                 value-format="yyyy-MM-dd"
+                :pickerOptions="pickerOptions"
             ></el-date-picker>
             <el-button @click="getData" type="primary" icon="el-icon-search" class="filter-item">查询 </el-button>
             <el-button
@@ -31,6 +32,14 @@
                 class="filter-item"
                 >导出EXCEL
             </el-button>
+            <el-button
+                @click="downloadRaw"
+                type="primary"
+                icon="el-icon-download"
+                :loading="downloadingRaw"
+                class="filter-item"
+                >导出原始记录
+            </el-button>
         </div>
         <el-table
             :data="tableData"
@@ -100,7 +109,8 @@ export default {
                         }
                     }
                 ]
-            }
+            },
+            downloadingRaw: false
         };
     },
     created() {
@@ -114,7 +124,7 @@ export default {
     methods: {
         beforeOnCreate() {
             this.department = [this.$store.state.userInfo.department];
-            let d = addMonths(new Date(), -1);
+            let d = new Date();
             this.date = [format(startOfMonth(d), 'yyyy-MM-dd'), format(endOfMonth(d), 'yyyy-MM-dd')];
         },
         getData() {
@@ -168,6 +178,33 @@ export default {
                     this.downloading = false;
                     this.$message.error(e.error);
                 });
+        },
+        downloadRaw() {
+            if (!(this.department && this.date)) {
+                return;
+            }
+            this.downloadingRaw = true;
+            this.$axios
+                .get('/attendance/departmentRaw', {
+                    responseType: 'blob',
+                    params: { departments: this.department.join(), start: this.date[0], end: this.date[1] }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloadingRaw = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', '考勤记录表.xlsx');
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloadingRaw = false;
+                    this.$message.error(e.error);
+                });
         }
     }
 };

+ 2 - 1
src/main/vue/src/views/StaffAttendanceReport.vue

@@ -26,6 +26,7 @@
                 placeholder="请选择日期"
                 class="filter-item"
                 value-format="yyyy-MM-dd"
+                :pickerOptions="pickerOptions"
             ></el-date-picker>
             <el-button @click="getData" type="primary" icon="el-icon-search" class="filter-item">查询 </el-button>
             <el-button
@@ -129,7 +130,7 @@ export default {
     methods: {
         beforeOnCreate() {
             this.department = this.$store.state.userInfo.department;
-            let d = addMonths(new Date(), -1);
+            let d = new Date();
             this.date = [format(startOfMonth(d), 'yyyy-MM-dd'), format(endOfMonth(d), 'yyyy-MM-dd')];
         },
         getData() {

+ 5 - 3
src/test/java/com/x1ongzhu/wisFactory/CommonTest.java

@@ -36,6 +36,7 @@ import java.util.*;
 import java.util.List;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
 import static java.nio.file.StandardOpenOption.CREATE;
@@ -187,9 +188,10 @@ public class CommonTest {
 
     @Test
     public void testsss() {
-        System.out.println(
-                DateTimeUtils.weekDay(LocalDate.of(2020, 12, 27))
-        );
+        IntStream.range(0, (int) ChronoUnit.DAYS.between(LocalDate.of(2020, 12, 01),
+                LocalDate.of(2020, 12, 31)) + 1).forEach(i -> {
+            System.out.println(i);
+        });
     }
 
 }

+ 22 - 0
src/test/java/com/x1ongzhu/wisFactory/service/AttendanceServiceTest.java

@@ -0,0 +1,22 @@
+package com.x1ongzhu.wisFactory.service;
+
+import com.x1ongzhu.wisFactory.ApplicationTests;
+import junit.framework.TestCase;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.Arrays;
+
+public class AttendanceServiceTest extends ApplicationTests {
+    @Autowired
+    private AttendanceService attendanceService;
+
+    @Test
+    public void testExportRaw() throws IOException {
+        attendanceService.exportRaw(LocalDate.of(2020, 12, 1),
+                LocalDate.of(2020, 12, 31),
+                Arrays.asList("上海电气国轩高科/设备部", "上海电气国轩高科/研发中心"), null);
+    }
+}