|
|
@@ -2,6 +2,7 @@
|
|
|
package org.sky.scientific.service.impl;
|
|
|
|
|
|
import com.alibaba.excel.EasyExcel;
|
|
|
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
@@ -11,12 +12,17 @@ import lombok.SneakyThrows;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.sky.core.log.exception.ServiceException;
|
|
|
import org.sky.core.mp.base.BaseServiceImpl;
|
|
|
+import org.sky.core.mp.support.Condition;
|
|
|
+import org.sky.core.mp.support.Query;
|
|
|
import org.sky.core.secure.utils.SecureUtil;
|
|
|
+import org.sky.core.tool.utils.Charsets;
|
|
|
import org.sky.core.tool.utils.CollectionUtil;
|
|
|
import org.sky.core.tool.utils.Func;
|
|
|
import org.sky.core.tool.utils.StringUtil;
|
|
|
import org.sky.scientific.excel.XmTechnicianHoursExcel;
|
|
|
import org.sky.scientific.excel.XmTechnicianHoursListener;
|
|
|
+import org.sky.scientific.excel.handle.AttendanceMergeStrategy;
|
|
|
+import org.sky.scientific.excel.handle.CustomCellStyleHandler;
|
|
|
import org.sky.scientific.mapper.*;
|
|
|
import org.sky.scientific.pojo.dto.TechnicianDTO;
|
|
|
import org.sky.scientific.pojo.entity.XmTechnicianHours;
|
|
|
@@ -30,7 +36,9 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import java.io.BufferedInputStream;
|
|
|
+import java.net.URLEncoder;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -58,7 +66,7 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
EasyExcel.read(new BufferedInputStream(file.getInputStream()))
|
|
|
.registerReadListener(listener)
|
|
|
.sheet(0)
|
|
|
- .headRowNumber(4) // 重要:设置表头行数(0-based)
|
|
|
+ .headRowNumber(3) // 重要:设置表头行数(0-based)
|
|
|
.doRead();
|
|
|
List<XmTechnicianHoursExcel> records = listener.getRecords();
|
|
|
if (CollectionUtil.isEmpty(records)) {
|
|
|
@@ -308,10 +316,128 @@ public class XmTechnicianHoursServiceImpl extends BaseServiceImpl<XmTechnicianHo
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- //
|
|
|
@Override
|
|
|
- public void export(HttpServletResponse response, XmTechnicianHoursVO param) {
|
|
|
+ public void export(HttpServletResponse response, XmTechnicianHoursVO dto) {
|
|
|
+ try {
|
|
|
+ response.setContentType("application/vnd.ms-excel");
|
|
|
+ response.setCharacterEncoding("utf-8");
|
|
|
+ response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("每月考勤信息.xls", Charsets.UTF_8));
|
|
|
+
|
|
|
+ Query query = new Query().setCurrent(1).setSize(Integer.MAX_VALUE);
|
|
|
+
|
|
|
+ List<XmTechnicianHoursVO> list = this.selectPage(dto, Condition.getPage(query)).getRecords();
|
|
|
+ AtomicInteger index = new AtomicInteger(1);
|
|
|
+ for (XmTechnicianHoursVO vo : list) {
|
|
|
+ vo.setXh(index.getAndIncrement());
|
|
|
+ }
|
|
|
+ Integer year = Integer.valueOf(dto.getYearAndMonth().substring(0, 4));
|
|
|
+ Integer month = Integer.valueOf(dto.getYearAndMonth().substring(5));
|
|
|
+
|
|
|
+ // 构建数据
|
|
|
+ List<List<Object>> data = buildData(list, year, month);
|
|
|
+
|
|
|
+ // 导出Excel(包含合并单元格策略)
|
|
|
+ EasyExcel.write(response.getOutputStream())
|
|
|
+ .registerWriteHandler(new AttendanceMergeStrategy(year, month))
|
|
|
+ .registerWriteHandler(new CustomCellStyleHandler())
|
|
|
+ .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
|
|
|
+ .autoCloseStream(true)
|
|
|
+ .sheet("考勤信息")
|
|
|
+ .doWrite(data);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ServiceException("导出失败:" + e.getLocalizedMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 构建数据行
|
|
|
+ */
|
|
|
+ private List<List<Object>> buildData(List<XmTechnicianHoursVO> list, Integer year, Integer month) {
|
|
|
+ List<List<Object>> data = new ArrayList<>();
|
|
|
+
|
|
|
+// LocalDate startDate = LocalDate.of(year, month, 1);
|
|
|
+// int daysInMonth = startDate.lengthOfMonth();
|
|
|
+// DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
+// DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("E", Locale.CHINA);
|
|
|
+// DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("d");
|
|
|
+//
|
|
|
+// // 第一行:标题行
|
|
|
+// List<Object> titleRow = new ArrayList<>();
|
|
|
+// titleRow.add("研发工时记录表" + year + "年" + month + "月");
|
|
|
+// for (int i = 1; i < daysInMonth + 7; i++) { // 7 = 5个固定列 + 2个统计列
|
|
|
+// titleRow.add("");
|
|
|
+// }
|
|
|
+// data.add(titleRow);
|
|
|
+//
|
|
|
+// // 第二行:纵向表头标题
|
|
|
+// List<Object> verticalHeaderRow = new ArrayList<>();
|
|
|
+// verticalHeaderRow.add("序号");
|
|
|
+// verticalHeaderRow.add("姓名");
|
|
|
+// verticalHeaderRow.add("工号");
|
|
|
+// verticalHeaderRow.add("身份证号码");
|
|
|
+// verticalHeaderRow.add("科研人员类别");
|
|
|
+// //第二行:周几行
|
|
|
+// for (int i = 1; i <= daysInMonth; i++) {
|
|
|
+// LocalDate date = LocalDate.of(year, month, i);
|
|
|
+// verticalHeaderRow.add(date.format(weekFormatter).substring(1));
|
|
|
+// }
|
|
|
+// verticalHeaderRow.add("本月出勤/小时");
|
|
|
+// verticalHeaderRow.add("本月出勤/天");
|
|
|
+// data.add(verticalHeaderRow);
|
|
|
+//
|
|
|
+// // 第三行:日期数字行
|
|
|
+// List<Object> dayRow = new ArrayList<>();
|
|
|
+// dayRow.add("");
|
|
|
+// dayRow.add("");
|
|
|
+// dayRow.add("");
|
|
|
+// dayRow.add("");
|
|
|
+// dayRow.add("");
|
|
|
+// for (int day = 1; day <= daysInMonth; day++) {
|
|
|
+// LocalDate date = LocalDate.of(year, month, day);
|
|
|
+// dayRow.add(date.format(dayFormatter));
|
|
|
+// }
|
|
|
+// dayRow.add("");
|
|
|
+// dayRow.add("");
|
|
|
+// data.add(dayRow);
|
|
|
+//
|
|
|
+// // 第4行开始:数据行
|
|
|
+// for (AttendanceVO attendance : attendanceList) {
|
|
|
+// List<Object> dataRow = new ArrayList<>();
|
|
|
+//
|
|
|
+// // 序号
|
|
|
+// dataRow.add(attendance.getXh());
|
|
|
+// // 姓名
|
|
|
+// dataRow.add(attendance.getName());
|
|
|
+// // 工号
|
|
|
+// dataRow.add(attendance.getNumber());
|
|
|
+// // 身份证号码
|
|
|
+// dataRow.add(attendance.getIdCard());
|
|
|
+// // 科研人员类别
|
|
|
+// dataRow.add(attendance.getPersonnelType());
|
|
|
+//
|
|
|
+// // 每日考勤数据
|
|
|
+// Map<String, Double> dailyMap = new HashMap<>();
|
|
|
+// if (attendance.getDailyAttendances() != null) {
|
|
|
+// for (DailyAttendance daily : attendance.getDailyAttendances()) {
|
|
|
+// dailyMap.put(daily.getWorkDate(), daily.getWorkHours());
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// for (int day = 1; day <= daysInMonth; day++) {
|
|
|
+// LocalDate currentDate = LocalDate.of(year, month, day);
|
|
|
+// String dateKey = currentDate.format(dateFormatter);
|
|
|
+// dataRow.add(dailyMap.getOrDefault(dateKey, 0.0));
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 统计信息
|
|
|
+// dataRow.add(attendance.getMonthlyHours());
|
|
|
+// dataRow.add(attendance.getMonthlyDays());
|
|
|
+//
|
|
|
+// data.add(dataRow);
|
|
|
+// }
|
|
|
+
|
|
|
+ return data;
|
|
|
}
|
|
|
|
|
|
@Override
|