设计导出
This commit is contained in:
Binary file not shown.
BIN
xinnengyuan/ruoyi-admin/src/main/resources/template/设计更改通知单.docx
Normal file
BIN
xinnengyuan/ruoyi-admin/src/main/resources/template/设计更改通知单.docx
Normal file
Binary file not shown.
Binary file not shown.
@ -1,12 +1,20 @@
|
|||||||
package org.dromara.common.utils;
|
package org.dromara.common.utils;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.utils.MessageUtils;
|
import org.dromara.common.core.utils.MessageUtils;
|
||||||
import org.dromara.common.sse.dto.SseMessageDto;
|
import org.dromara.common.sse.dto.SseMessageDto;
|
||||||
import org.dromara.common.sse.utils.SseMessageUtils;
|
import org.dromara.common.sse.utils.SseMessageUtils;
|
||||||
|
import org.dromara.contractor.domain.SubConstructionUser;
|
||||||
|
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
|
||||||
|
import org.dromara.mobileAttendanceMachine.KqjEntity;
|
||||||
|
import org.dromara.project.domain.BusAttendanceMachine;
|
||||||
|
import org.dromara.project.service.IBusAttendanceMachineService;
|
||||||
import org.dromara.sms4j.api.SmsBlend;
|
import org.dromara.sms4j.api.SmsBlend;
|
||||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||||
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
|
import org.dromara.system.service.ISysOssService;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -17,6 +25,13 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class AsyncUtil {
|
public class AsyncUtil {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeviceMessageSender deviceMessageSender;
|
||||||
|
@Resource
|
||||||
|
private ISysOssService ossService;
|
||||||
|
@Resource
|
||||||
|
private IBusAttendanceMachineService attendanceMachineService;
|
||||||
|
|
||||||
//发送短信
|
//发送短信
|
||||||
@Async
|
@Async
|
||||||
public void sendSms(List<String> mobileList, String config) {
|
public void sendSms(List<String> mobileList, String config) {
|
||||||
@ -39,4 +54,27 @@ public class AsyncUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//下发考勤人员
|
||||||
|
@Async
|
||||||
|
public void sendPersonnel(Long teamId, SubConstructionUser constructionUser) {
|
||||||
|
SysOssVo byId = ossService.getById(Long.valueOf(constructionUser.getFacePic()));
|
||||||
|
List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", teamId).list();
|
||||||
|
for (BusAttendanceMachine machine : list) {
|
||||||
|
deviceMessageSender.sendPersonnelInformation(machine.getSn(), constructionUser.getSysUserId().toString(), constructionUser.getUserName(), byId.getUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除考勤人员
|
||||||
|
@Async
|
||||||
|
public void deletePersonnel(SubConstructionUser constructionUser) {
|
||||||
|
List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", constructionUser.getTeamId()).list();
|
||||||
|
for (BusAttendanceMachine machine : list) {
|
||||||
|
try {
|
||||||
|
deviceMessageSender.deleteUser(machine.getSn(), constructionUser.getSysUserId().toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除考勤人员异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import org.dromara.common.oss.core.OssClient;
|
|||||||
import org.dromara.common.oss.exception.OssException;
|
import org.dromara.common.oss.exception.OssException;
|
||||||
import org.dromara.common.oss.factory.OssFactory;
|
import org.dromara.common.oss.factory.OssFactory;
|
||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
|
import org.dromara.common.utils.AsyncUtil;
|
||||||
import org.dromara.common.utils.IdCardEncryptorUtil;
|
import org.dromara.common.utils.IdCardEncryptorUtil;
|
||||||
import org.dromara.common.utils.baiduUtil.BaiDuFace;
|
import org.dromara.common.utils.baiduUtil.BaiDuFace;
|
||||||
import org.dromara.common.utils.baiduUtil.BaiDuOCR;
|
import org.dromara.common.utils.baiduUtil.BaiDuOCR;
|
||||||
@ -46,6 +47,7 @@ import org.dromara.contractor.mapper.SubConstructionUserMapper;
|
|||||||
import org.dromara.contractor.service.ISubConstructionUserFileService;
|
import org.dromara.contractor.service.ISubConstructionUserFileService;
|
||||||
import org.dromara.contractor.service.ISubConstructionUserService;
|
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||||
import org.dromara.contractor.service.ISubContractorService;
|
import org.dromara.contractor.service.ISubContractorService;
|
||||||
|
import org.dromara.mobileAttendanceMachine.DeviceMessageSender;
|
||||||
import org.dromara.project.domain.*;
|
import org.dromara.project.domain.*;
|
||||||
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
|
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
|
||||||
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
|
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
|
||||||
@ -151,6 +153,11 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
|
|||||||
@Resource
|
@Resource
|
||||||
private ISysRoleService roleService;
|
private ISysRoleService roleService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AsyncUtil asyncUtil;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询施工人员
|
* 查询施工人员
|
||||||
*
|
*
|
||||||
@ -290,6 +297,8 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
|
|||||||
//强退
|
//强退
|
||||||
roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId()));
|
roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId()));
|
||||||
|
|
||||||
|
asyncUtil.sendPersonnel(dto.getTeamId(), constructionUser);
|
||||||
|
|
||||||
return i > 0;
|
return i > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,13 @@ package org.dromara.design.controller;
|
|||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.apache.poi.xwpf.usermodel.*;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.excel.utils.ExcelUtil;
|
import org.dromara.common.excel.utils.ExcelUtil;
|
||||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
@ -13,18 +16,37 @@ import org.dromara.common.log.annotation.Log;
|
|||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
import org.dromara.common.web.core.BaseController;
|
import org.dromara.common.web.core.BaseController;
|
||||||
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
import org.dromara.design.domain.DesConstructionSchedulePlan;
|
||||||
|
import org.dromara.design.domain.DesUser;
|
||||||
import org.dromara.design.domain.dto.constructionscheduleplan.*;
|
import org.dromara.design.domain.dto.constructionscheduleplan.*;
|
||||||
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo;
|
||||||
|
import org.dromara.design.exportUtil.plan.AttachmentPersonnel;
|
||||||
import org.dromara.design.service.IDesConstructionSchedulePlanService;
|
import org.dromara.design.service.IDesConstructionSchedulePlanService;
|
||||||
|
|
||||||
|
|
||||||
|
import org.dromara.design.service.IDesUserService;
|
||||||
|
import org.dromara.system.domain.vo.SysDictDataVo;
|
||||||
|
import org.dromara.system.service.ISysDictDataService;
|
||||||
|
import org.dromara.system.service.ISysDictTypeService;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.util.List;
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
/**
|
/**
|
||||||
* 设计计划
|
* 设计计划
|
||||||
*
|
*
|
||||||
@ -38,7 +60,10 @@ public class DesConstructionSchedulePlanController extends BaseController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IDesConstructionSchedulePlanService desConstructionSchedulePlanService;
|
private IDesConstructionSchedulePlanService desConstructionSchedulePlanService;
|
||||||
|
@Resource
|
||||||
|
private IDesUserService desUserService;
|
||||||
|
@Resource
|
||||||
|
private ISysDictTypeService dictTypeService;
|
||||||
/**
|
/**
|
||||||
* 查询设计计划列表
|
* 查询设计计划列表
|
||||||
*/
|
*/
|
||||||
@ -150,4 +175,168 @@ public class DesConstructionSchedulePlanController extends BaseController {
|
|||||||
desConstructionSchedulePlanService.exportSchedule(response,projectId);
|
desConstructionSchedulePlanService.exportSchedule(response,projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String TEMPLATE_RESOURCE_PATH = "template/CCCET-JL-CX-25设计计划表.docx";
|
||||||
|
// -------------------------- 2. 核心接口:修复单元格清空逻辑与数据填充 --------------------------
|
||||||
|
@PostMapping("/downloadWord")
|
||||||
|
public void fillCccetTemplate(Long projectId, HttpServletResponse response) {
|
||||||
|
// 1. 基础参数校验(避免空数据)
|
||||||
|
|
||||||
|
// 2. 读取resource中的模板+填充数据
|
||||||
|
try (
|
||||||
|
// 关键:通过ClassPathResource读取resource/template下的模板
|
||||||
|
InputStream templateIs = new ClassPathResource(TEMPLATE_RESOURCE_PATH).getInputStream();
|
||||||
|
XWPFDocument doc = new XWPFDocument(templateIs); // 加载模板
|
||||||
|
OutputStream out = response.getOutputStream() // 响应流
|
||||||
|
) {
|
||||||
|
// --------------------------
|
||||||
|
// 步骤1:填充第1页-主信息表(索引0,固定6列)
|
||||||
|
// --------------------------
|
||||||
|
// XWPFTable mainTable = doc.getTables().get(0);
|
||||||
|
// // 工程名称(第1行第0列)
|
||||||
|
// if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(0) != null) {
|
||||||
|
// mainTable.getRow(1).getCell(0).setText(request.getProjectName() == null ? "" : request.getProjectName());
|
||||||
|
// }
|
||||||
|
// // 工程号(第1行第1列)
|
||||||
|
// if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(1) != null) {
|
||||||
|
// mainTable.getRow(1).getCell(1).setText(request.getProjectNo());
|
||||||
|
// }
|
||||||
|
// // 编制日期(第2行第3列)
|
||||||
|
// if (mainTable.getRows().size() > 2 && mainTable.getRow(2).getCell(3) != null) {
|
||||||
|
// mainTable.getRow(2).getCell(3).setText(request.getCompileDate() == null ? "" : request.getCompileDate());
|
||||||
|
// }
|
||||||
|
// // 编制人(第3行第0列)
|
||||||
|
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(0) != null) {
|
||||||
|
// mainTable.getRow(3).getCell(0).setText(request.getCompiler() == null ? "" : request.getCompiler());
|
||||||
|
// }
|
||||||
|
// // 批准人(第3行第2列)
|
||||||
|
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(2) != null) {
|
||||||
|
// mainTable.getRow(3).getCell(2).setText(request.getApprover() == null ? "" : request.getApprover());
|
||||||
|
// }
|
||||||
|
// // 设计阶段(第3行第4列)
|
||||||
|
// if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(4) != null) {
|
||||||
|
// mainTable.getRow(3).getCell(4).setText(request.getDesignStage() == null ? "" : request.getDesignStage());
|
||||||
|
// }
|
||||||
|
// // 设计规模(第4行第0列)
|
||||||
|
// if (mainTable.getRows().size() > 4 && mainTable.getRow(4).getCell(0) != null) {
|
||||||
|
// mainTable.getRow(4).getCell(0).setText(request.getDesignScale() == null ? "" : request.getDesignScale());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// 步骤2:填充第3页-附件1人员配置表(索引2,固定11列)
|
||||||
|
// --------------------------
|
||||||
|
XWPFTable staffTable = doc.getTables().get(2);
|
||||||
|
// 删除模板中附件1的空数据行(保留第0行表头)
|
||||||
|
while (staffTable.getRows().size() > 2) {
|
||||||
|
staffTable.removeRow(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AttachmentPersonnel> list = getPersonnelDataByProjectId(projectId);
|
||||||
|
for (AttachmentPersonnel staff : list) {
|
||||||
|
XWPFTableRow newRow = staffTable.createRow();
|
||||||
|
// 补全11列(避免POI默认列数不足导致null)
|
||||||
|
while (newRow.getTableCells().size() < 11) {
|
||||||
|
newRow.createCell();
|
||||||
|
}
|
||||||
|
// 按附件1列顺序填充
|
||||||
|
newRow.getCell(0).setText(staff.getProfessional() == null ? "" : staff.getProfessional());
|
||||||
|
newRow.getCell(1).setText(staff.getLeaderName() == null ? "" : staff.getLeaderName());
|
||||||
|
newRow.getCell(2).setText(staff.getLeaderTitle() == null ? "" : staff.getLeaderTitle());
|
||||||
|
newRow.getCell(3).setText(staff.getDesignerName() == null ? "" : staff.getDesignerName());
|
||||||
|
newRow.getCell(4).setText(staff.getDesignerTitle() == null ? "" : staff.getDesignerTitle());
|
||||||
|
newRow.getCell(5).setText(staff.getReviewerName() == null ? "" : staff.getReviewerName());
|
||||||
|
newRow.getCell(6).setText(staff.getReviewerTitle() == null ? "" : staff.getReviewerTitle());
|
||||||
|
newRow.getCell(7).setText(staff.getCheckerName() == null ? "" : staff.getCheckerName());
|
||||||
|
newRow.getCell(8).setText(staff.getCheckerTitle() == null ? "" : staff.getCheckerTitle());
|
||||||
|
newRow.getCell(9).setText(staff.getApproverName() == null ? "" : staff.getApproverName());
|
||||||
|
newRow.getCell(10).setText(staff.getApproverTitle() == null ? "" : staff.getApproverTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// 步骤3:设置响应头(触发前端下载)
|
||||||
|
// --------------------------
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
// 文件名:填充后_工程号_CCCET-JL-CX-25设计计划表.docx
|
||||||
|
String fileName = "CCCET-JL-CX-25设计计划表.docx";
|
||||||
|
response.setHeader("Content-Disposition",
|
||||||
|
"attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
|
||||||
|
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 允许前端获取文件名
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// 步骤4:写出文件到前端
|
||||||
|
// --------------------------
|
||||||
|
doc.write(out);
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 异常封装(前端可捕获具体错误)
|
||||||
|
throw new RuntimeException("CCCET-JL-CX-25模板填充失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据projectId获取数据(仅针对CCCET-JL-CX-25设计计划表.docx附件1)
|
||||||
|
*/
|
||||||
|
private List<AttachmentPersonnel> getPersonnelDataByProjectId(Long projectId) {
|
||||||
|
// 模拟数据库查询(实际项目替换为真实Service调用)
|
||||||
|
List<DesUser> userList = desUserService.list(Wrappers.<DesUser>lambdaQuery()
|
||||||
|
.eq(DesUser::getProjectId, projectId)
|
||||||
|
);
|
||||||
|
if (userList.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 专业字典映射(编码→名称)
|
||||||
|
List<SysDictDataVo> majorDict = dictTypeService.selectDictDataByType("des_user_major");
|
||||||
|
Map<String, String> majorMap = majorDict.stream()
|
||||||
|
.collect(Collectors.toMap(SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel));
|
||||||
|
|
||||||
|
// 按角色分组(1-专业负责人,2-设计人,3-校审人,4-审定人,5-审核人)
|
||||||
|
DesUser leader = userList.stream().filter(u -> "1".equals(u.getUserType())).findFirst().orElse(null);
|
||||||
|
Map<String, List<DesUser>> designerMap = userList.stream()
|
||||||
|
.filter(u -> "2".equals(u.getUserType()))
|
||||||
|
.collect(Collectors.groupingBy(DesUser::getUserMajor));
|
||||||
|
Map<String, List<DesUser>> reviewerMap = userList.stream()
|
||||||
|
.filter(u -> "3".equals(u.getUserType()))
|
||||||
|
.collect(Collectors.groupingBy(DesUser::getUserMajor));
|
||||||
|
Map<String, List<DesUser>> checkerMap = userList.stream()
|
||||||
|
.filter(u -> "5".equals(u.getUserType()))
|
||||||
|
.collect(Collectors.groupingBy(DesUser::getUserMajor));
|
||||||
|
Map<String, List<DesUser>> approverMap = userList.stream()
|
||||||
|
.filter(u -> "4".equals(u.getUserType()))
|
||||||
|
.collect(Collectors.groupingBy(DesUser::getUserMajor));
|
||||||
|
|
||||||
|
// 构建附件1数据(一个专业一行,避免重复)
|
||||||
|
List<AttachmentPersonnel> dataList = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, List<DesUser>> entry : designerMap.entrySet()) {
|
||||||
|
String majorCode = entry.getKey();
|
||||||
|
String majorName = majorMap.getOrDefault(majorCode, majorCode);
|
||||||
|
List<DesUser> designers = entry.getValue();
|
||||||
|
|
||||||
|
// 获取对应专业的其他角色
|
||||||
|
DesUser reviewer = reviewerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
|
||||||
|
DesUser checker = checkerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
|
||||||
|
DesUser approver = approverMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null);
|
||||||
|
// 封装数据(多个设计人用顿号分隔)
|
||||||
|
AttachmentPersonnel data = new AttachmentPersonnel();
|
||||||
|
data.setProfessional(majorName);
|
||||||
|
data.setLeaderName(leader != null ? leader.getUserName() : "");
|
||||||
|
//data.setLeadeTitle(leader != null ? leader.getUserTitle() : "");
|
||||||
|
data.setDesignerName(designers.stream().map(DesUser::getUserName).collect(Collectors.joining("、")));
|
||||||
|
//data.setDesignerTitle(designers.stream().map(DesUser::getUserTitle).collect(Collectors.joining("、")));
|
||||||
|
data.setReviewerName(reviewer != null ? reviewer.getUserName() : "");
|
||||||
|
//data.setReviewerTitle(reviewer != null ? reviewer.getUserTitle() : "");
|
||||||
|
data.setCheckerName(checker != null ? checker.getUserName() : "");
|
||||||
|
//data.setCheckerTitle(checker != null ? checker.getUserTitle() : "");
|
||||||
|
data.setApproverName(approver != null ? approver.getUserName() : "");
|
||||||
|
//data.setApproverTitle(approver != null ? approver.getUserTitle() : "");
|
||||||
|
|
||||||
|
dataList.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.dromara.design.controller;
|
|||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
@ -16,24 +17,36 @@ import org.dromara.common.log.enums.BusinessType;
|
|||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.common.web.core.BaseController;
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.design.domain.DesUser;
|
||||||
import org.dromara.design.domain.DesVolumeCatalog;
|
import org.dromara.design.domain.DesVolumeCatalog;
|
||||||
import org.dromara.design.domain.DesVolumeFile;
|
import org.dromara.design.domain.DesVolumeFile;
|
||||||
import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq;
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq;
|
||||||
import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq;
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq;
|
||||||
import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq;
|
import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq;
|
||||||
|
import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto;
|
||||||
import org.dromara.design.domain.dto.volumecatalog.DesVolumeCatalogQueryReq;
|
import org.dromara.design.domain.dto.volumecatalog.DesVolumeCatalogQueryReq;
|
||||||
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
|
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
|
||||||
import org.dromara.design.domain.vo.volumecatalog.DesVolumeCatalogVo;
|
import org.dromara.design.domain.vo.volumecatalog.DesVolumeCatalogVo;
|
||||||
import org.dromara.design.service.IDesDesignChangeService;
|
import org.dromara.design.service.IDesDesignChangeService;
|
||||||
import org.dromara.design.service.IDesVolumeCatalogService;
|
import org.dromara.design.service.IDesVolumeCatalogService;
|
||||||
import org.dromara.design.service.IDesVolumeFileService;
|
import org.dromara.design.service.IDesVolumeFileService;
|
||||||
|
import org.dromara.project.domain.BusProject;
|
||||||
import org.dromara.system.domain.vo.SysOssVo;
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
|
import org.dromara.system.service.ISysDictDataService;
|
||||||
import org.dromara.system.service.ISysOssService;
|
import org.dromara.system.service.ISysOssService;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,6 +69,9 @@ public class DesDesignChangeController extends BaseController {
|
|||||||
@Resource
|
@Resource
|
||||||
private IDesVolumeFileService desVolumeFileService;
|
private IDesVolumeFileService desVolumeFileService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ISysDictDataService dictDataService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设计变更管理列表
|
* 查询设计变更管理列表
|
||||||
*/
|
*/
|
||||||
@ -146,4 +162,92 @@ public class DesDesignChangeController extends BaseController {
|
|||||||
return R.ok(list);
|
return R.ok(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String TEMPLATE_PATH = "template/设计更改通知单.docx";
|
||||||
|
|
||||||
|
@PostMapping("/downloadWord")
|
||||||
|
public void generateDesignLeaderDoc(Long id, HttpServletResponse response) {
|
||||||
|
OutputStream outputStream = null;
|
||||||
|
try {
|
||||||
|
// 1. 调用Service生成目标模板的Word字节流
|
||||||
|
byte[] docBytes = generateDocBytes(id);
|
||||||
|
|
||||||
|
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
|
||||||
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
|
||||||
|
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名)
|
||||||
|
String downloadFileName = URLEncoder.encode(
|
||||||
|
"设计更改通知单.docx",
|
||||||
|
"UTF-8"
|
||||||
|
);
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
|
||||||
|
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
|
||||||
|
|
||||||
|
// 3. 将Word字节流写入响应
|
||||||
|
outputStream = response.getOutputStream();
|
||||||
|
outputStream.write(docBytes);
|
||||||
|
outputStream.flush();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 异常处理:返回500错误状态码
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
} finally {
|
||||||
|
// 关闭流,避免资源泄漏
|
||||||
|
if (outputStream != null) {
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateDocBytes(Long id) throws Exception {
|
||||||
|
// -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) --------------------------
|
||||||
|
// 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等)
|
||||||
|
DesDesignChangeVo vo = desDesignChangeService.queryById(id);
|
||||||
|
DesDesignExtendDetailDto extendDetail = vo.getExtendDetail()==null?new DesDesignExtendDetailDto():vo.getExtendDetail();
|
||||||
|
|
||||||
|
Map<String, Object> placeholderData = new HashMap<>();
|
||||||
|
placeholderData.put("projectName", vo.getProjectName());
|
||||||
|
placeholderData.put("designPhase",extendDetail.getDesignPhase());
|
||||||
|
placeholderData.put("subName",extendDetail.getSubName());
|
||||||
|
String s = dictDataService.selectDictLabel("des_user_major", vo.getSpecialty());
|
||||||
|
placeholderData.put("specialty",s);
|
||||||
|
placeholderData.put("volumeNo",vo.getVolumeNo());
|
||||||
|
|
||||||
|
String changeReason = vo.getChangeReason();
|
||||||
|
List<String> reasons = Arrays.asList("设计漏项", "设计改进", "设计差错", "接口差错",
|
||||||
|
"业主要求", "施工承包商要求", "外部资料与最终情况不符", "材料代用或其他");
|
||||||
|
|
||||||
|
String reason = reasons.stream()
|
||||||
|
.map(item -> changeReason.contains(String.valueOf(reasons.indexOf(item) + 1)) ? " ☑" + item : " □" + item)
|
||||||
|
.collect(Collectors.joining());
|
||||||
|
|
||||||
|
placeholderData.put("changeReason", reason);
|
||||||
|
placeholderData.put("designDisposal1", "1".equals(extendDetail.getDesignDisposal())?"☑" : "□");
|
||||||
|
placeholderData.put("designDisposal2", "2".equals(extendDetail.getDesignDisposal())?"☑" : "□");
|
||||||
|
placeholderData.put("designDisposal3", "3".equals(extendDetail.getDesignDisposal())?"☑" : "□");
|
||||||
|
placeholderData.put("changeContent",vo.getChangeContent());
|
||||||
|
placeholderData.put("changeCategory1", "1".equals(extendDetail.getChangeCategory())?"☑" : "□");
|
||||||
|
placeholderData.put("changeCategory2", "2".equals(extendDetail.getChangeCategory())?"☑" : "□");
|
||||||
|
placeholderData.put("involvingProfessions", extendDetail.getInvolvingProfessions());
|
||||||
|
// -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 --------------------------
|
||||||
|
// 读取resources下的“设计项目负责人任命通知单.docx”模板
|
||||||
|
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
|
||||||
|
try (InputStream templateIs = templateResource.getInputStream();
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||||
|
|
||||||
|
// 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(templateIs)
|
||||||
|
.render(placeholderData); // 自动匹配{{变量名}}占位符
|
||||||
|
|
||||||
|
// -------------------------- 步骤3:将生成的文档写入字节流 --------------------------
|
||||||
|
template.write(outputStream);
|
||||||
|
template.close(); // 关闭模板资源
|
||||||
|
return outputStream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
package org.dromara.design.controller;
|
package org.dromara.design.controller;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.rmi.ServerException;
|
import java.rmi.ServerException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.deepoove.poi.XWPFTemplate;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.constraints.*;
|
import jakarta.validation.constraints.*;
|
||||||
@ -22,8 +24,15 @@ import org.apache.poi.ss.usermodel.Row;
|
|||||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
//import org.dromara.design.domain.DesUserExcelData;
|
//import org.dromara.design.domain.DesUserExcelData;
|
||||||
|
import org.dromara.design.domain.DesUser;
|
||||||
import org.dromara.design.domain.DesUserExcelData;
|
import org.dromara.design.domain.DesUserExcelData;
|
||||||
import org.dromara.design.domain.dto.desUser.DesUserBatchDto;
|
import org.dromara.design.domain.dto.desUser.DesUserBatchDto;
|
||||||
|
import org.dromara.project.domain.BusProject;
|
||||||
|
import org.dromara.project.service.IBusProjectService;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
@ -54,6 +63,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
public class DesUserController extends BaseController {
|
public class DesUserController extends BaseController {
|
||||||
|
|
||||||
private final IDesUserService desUserService;
|
private final IDesUserService desUserService;
|
||||||
|
private final IBusProjectService projectService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设计人员列表
|
* 查询设计人员列表
|
||||||
@ -142,5 +152,75 @@ public class DesUserController extends BaseController {
|
|||||||
return toAjax(desUserService.batchAddOrUpdate(dto));
|
return toAjax(desUserService.batchAddOrUpdate(dto));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String TEMPLATE_PATH = "template/设计项目负责人任命通知单.docx";
|
||||||
|
|
||||||
|
@PostMapping("/downloadWord")
|
||||||
|
public void generateDesignLeaderDoc( Long projectId,
|
||||||
|
HttpServletResponse response
|
||||||
|
) {
|
||||||
|
OutputStream outputStream = null;
|
||||||
|
try {
|
||||||
|
// 1. 调用Service生成目标模板的Word字节流
|
||||||
|
byte[] docBytes = generateDocBytes(projectId);
|
||||||
|
|
||||||
|
// 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型)
|
||||||
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型
|
||||||
|
// 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名)
|
||||||
|
String downloadFileName = URLEncoder.encode(
|
||||||
|
"设计负责人任命通知单.docx",
|
||||||
|
"UTF-8"
|
||||||
|
);
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
|
||||||
|
response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验)
|
||||||
|
|
||||||
|
// 3. 将Word字节流写入响应
|
||||||
|
outputStream = response.getOutputStream();
|
||||||
|
outputStream.write(docBytes);
|
||||||
|
outputStream.flush();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 异常处理:返回500错误状态码
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
} finally {
|
||||||
|
// 关闭流,避免资源泄漏
|
||||||
|
if (outputStream != null) {
|
||||||
|
try {
|
||||||
|
outputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateDocBytes(Long projectId) throws Exception {
|
||||||
|
// -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) --------------------------
|
||||||
|
// 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等)
|
||||||
|
BusProject byId = projectService.getById(projectId);
|
||||||
|
DesUser desUser = desUserService.lambdaQuery().eq(DesUser::getProjectId, projectId)
|
||||||
|
.eq(DesUser::getUserType, "1")
|
||||||
|
.last("limit 1").one();
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Object> placeholderData = new HashMap<>();
|
||||||
|
placeholderData.put("projectName", byId==null?"" :byId.getProjectName());
|
||||||
|
placeholderData.put("leaderName",desUser==null?"": desUser.getUserName());
|
||||||
|
|
||||||
|
// -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 --------------------------
|
||||||
|
// 读取resources下的“设计项目负责人任命通知单.docx”模板
|
||||||
|
ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH);
|
||||||
|
try (InputStream templateIs = templateResource.getInputStream();
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||||
|
|
||||||
|
// 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档
|
||||||
|
XWPFTemplate template = XWPFTemplate.compile(templateIs)
|
||||||
|
.render(placeholderData); // 自动匹配{{变量名}}占位符
|
||||||
|
|
||||||
|
// -------------------------- 步骤3:将生成的文档写入字节流 --------------------------
|
||||||
|
template.write(outputStream);
|
||||||
|
template.close(); // 关闭模板资源
|
||||||
|
return outputStream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
package org.dromara.design.exportUtil.plan;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class AttachmentPersonnel {
|
||||||
|
String professional; // 专业及人员分工
|
||||||
|
String leaderName; // 专业负责人姓名
|
||||||
|
String leaderTitle; // 专业负责人职称
|
||||||
|
String designerName; // 设计人姓名
|
||||||
|
String designerTitle; // 设计人职称
|
||||||
|
String reviewerName; // 校审人姓名
|
||||||
|
String reviewerTitle; // 校审人职称
|
||||||
|
String checkerName; // 审核人姓名
|
||||||
|
String checkerTitle; // 审核人职称
|
||||||
|
String approverName; // 审定人姓名
|
||||||
|
String approverTitle; // 审定人职称
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -91,4 +91,16 @@ public class BusAttendanceMachineController extends BaseController {
|
|||||||
@PathVariable Long[] ids) {
|
@PathVariable Long[] ids) {
|
||||||
return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true));
|
return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量重新下发
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("project:attendanceMachine:reissue")
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping("/reissue/{ids}")
|
||||||
|
public void reissue(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] ids){
|
||||||
|
busAttendanceMachineService.reissue(List.of(ids));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,8 +128,8 @@ public class BusAttendanceAppController extends BaseController {
|
|||||||
* 获取用户打卡异常记录
|
* 获取用户打卡异常记录
|
||||||
*/
|
*/
|
||||||
@GetMapping("/getAbnormalAttendance/{projectId}")
|
@GetMapping("/getAbnormalAttendance/{projectId}")
|
||||||
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery){
|
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId,String handle, PageQuery pageQuery){
|
||||||
return attendanceService.getAbnormalAttendance(projectId,pageQuery);
|
return attendanceService.getAbnormalAttendance(projectId,handle,pageQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
package org.dromara.project.service;
|
package org.dromara.project.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.project.domain.BusAttendanceMachine;
|
import org.dromara.project.domain.BusAttendanceMachine;
|
||||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq;
|
||||||
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq;
|
||||||
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
import org.dromara.project.domain.vo.BusAttendanceMachineVo;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -75,4 +78,7 @@ public interface IBusAttendanceMachineService extends IService<BusAttendanceMach
|
|||||||
* @return 是否删除成功
|
* @return 是否删除成功
|
||||||
*/
|
*/
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
|
||||||
|
void reissue(Collection<Long> ids);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,7 +131,7 @@ public interface IBusAttendanceService extends IService<BusAttendance>{
|
|||||||
/**
|
/**
|
||||||
* 获取用户打卡异常记录
|
* 获取用户打卡异常记录
|
||||||
*/
|
*/
|
||||||
TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery);
|
TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计指定日期的打卡人员
|
* 统计指定日期的打卡人员
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.dromara.project.service.impl;
|
package org.dromara.project.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
@ -28,13 +29,13 @@ import org.dromara.project.service.IBusAttendanceMachineService;
|
|||||||
import org.dromara.project.service.IBusProjectService;
|
import org.dromara.project.service.IBusProjectService;
|
||||||
import org.dromara.project.service.IBusProjectTeamMemberService;
|
import org.dromara.project.service.IBusProjectTeamMemberService;
|
||||||
import org.dromara.project.service.IBusProjectTeamService;
|
import org.dromara.project.service.IBusProjectTeamService;
|
||||||
|
import org.dromara.system.domain.vo.SysOssVo;
|
||||||
|
import org.dromara.system.service.ISysOssService;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,6 +64,10 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
|||||||
@Resource
|
@Resource
|
||||||
private ISubConstructionUserService constructionUserService;
|
private ISubConstructionUserService constructionUserService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ISysOssService ossService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询考勤机
|
* 查询考勤机
|
||||||
*
|
*
|
||||||
@ -300,4 +305,57 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa
|
|||||||
}
|
}
|
||||||
return baseMapper.deleteByIds(ids) > 0;
|
return baseMapper.deleteByIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
@Override
|
||||||
|
public void reissue(Collection<Long> ids) {
|
||||||
|
List<BusAttendanceMachine> busAttendanceMachines = baseMapper.selectByIds(ids);
|
||||||
|
|
||||||
|
for (BusAttendanceMachine machine : busAttendanceMachines) {
|
||||||
|
String sn = machine.getSn();
|
||||||
|
try {
|
||||||
|
deviceMessageSender.deleteAllUsers(sn);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除考勤人员异常", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String teams = machine.getTeams();
|
||||||
|
if (StrUtil.isBlank(teams)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<Long> oldTeamIds = Arrays.stream(teams.split(","))
|
||||||
|
.map(Long::parseLong)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
List<Long> userIds = projectTeamMemberService.lambdaQuery()
|
||||||
|
.select(BusProjectTeamMember::getMemberId)
|
||||||
|
.in(BusProjectTeamMember::getTeamId, oldTeamIds)
|
||||||
|
.list()
|
||||||
|
.stream().map(BusProjectTeamMember::getMemberId)
|
||||||
|
.toList();
|
||||||
|
if (CollUtil.isEmpty(userIds)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SubConstructionUser> users = constructionUserService.lambdaQuery()
|
||||||
|
.in(SubConstructionUser::getSysUserId, userIds)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
Map<Long, String> faceMap = new HashMap<>();
|
||||||
|
List<String> list = users.stream().map(SubConstructionUser::getFacePic).filter(StrUtil::isNotBlank).toList();
|
||||||
|
if (CollUtil.isNotEmpty(list)) {
|
||||||
|
//转成Long的集合
|
||||||
|
List<Long> list1 = list.stream().map(Long::parseLong).toList();
|
||||||
|
List<SysOssVo> sysOssVos = ossService.listByIds(list1);
|
||||||
|
faceMap = sysOssVos.stream().collect(Collectors.toMap(SysOssVo::getOssId, SysOssVo::getUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SubConstructionUser user : users) {
|
||||||
|
String facePic = StrUtil.isBlank(user.getFacePic()) ? "" : faceMap.get(Long.valueOf(user.getFacePic()));
|
||||||
|
deviceMessageSender.sendPersonnelInformation(sn, user.getSysUserId().toString()
|
||||||
|
, user.getUserName(), facePic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -792,7 +792,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId, PageQuery pageQuery) {
|
public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery) {
|
||||||
|
|
||||||
List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(),
|
List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(),
|
||||||
BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(),
|
BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(),
|
||||||
@ -809,6 +809,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
|
|||||||
|
|
||||||
IPage<BusAttendanceVo> busAttendanceVoIPage = baseMapper.selectVoPage(pageQuery.build(), Wrappers.lambdaQuery(BusAttendance.class)
|
IPage<BusAttendanceVo> busAttendanceVoIPage = baseMapper.selectVoPage(pageQuery.build(), Wrappers.lambdaQuery(BusAttendance.class)
|
||||||
.eq(BusAttendance::getUserId, userId)
|
.eq(BusAttendance::getUserId, userId)
|
||||||
|
.eq(StrUtil.isNotBlank(handle), BusAttendance::getHandle, handle)
|
||||||
.eq(b, BusAttendance::getProjectId, projectId)
|
.eq(b, BusAttendance::getProjectId, projectId)
|
||||||
.in(BusAttendance::getClockStatus, abnormalList)
|
.in(BusAttendance::getClockStatus, abnormalList)
|
||||||
.ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29))
|
.ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29))
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import org.dromara.common.enums.AppUserTypeEnum;
|
|||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
|
import org.dromara.common.utils.AsyncUtil;
|
||||||
import org.dromara.common.utils.IdCardEncryptorUtil;
|
import org.dromara.common.utils.IdCardEncryptorUtil;
|
||||||
import org.dromara.contractor.domain.SubConstructionUser;
|
import org.dromara.contractor.domain.SubConstructionUser;
|
||||||
import org.dromara.contractor.service.ISubConstructionUserService;
|
import org.dromara.contractor.service.ISubConstructionUserService;
|
||||||
@ -90,6 +91,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
|
|||||||
@Resource
|
@Resource
|
||||||
private ISysOssService ossService;
|
private ISysOssService ossService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AsyncUtil asyncUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询项目班组下的成员
|
* 查询项目班组下的成员
|
||||||
@ -219,6 +222,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
|
|||||||
userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false);
|
userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asyncUtil.sendPersonnel(req.getTeamId(), constructionUser);
|
||||||
|
|
||||||
return projectTeamMember.getId();
|
return projectTeamMember.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +361,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
|
|||||||
.set(SubConstructionUser::getTeamId, null)
|
.set(SubConstructionUser::getTeamId, null)
|
||||||
.set(SubConstructionUser::getLeaveDate, new Date());
|
.set(SubConstructionUser::getLeaveDate, new Date());
|
||||||
constructionUserService.update(constructionUserLuw);
|
constructionUserService.update(constructionUserLuw);
|
||||||
|
|
||||||
|
asyncUtil.deletePersonnel(constructionUser);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user