diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/template/设计输入资料清单及评审表.docx b/xinnengyuan/ruoyi-admin/src/main/resources/template/设计输入资料清单及评审表.docx new file mode 100644 index 00000000..216875d8 Binary files /dev/null and b/xinnengyuan/ruoyi-admin/src/main/resources/template/设计输入资料清单及评审表.docx differ diff --git a/xinnengyuan/ruoyi-admin/src/main/resources/template/设计验证表.docx b/xinnengyuan/ruoyi-admin/src/main/resources/template/设计验证表.docx new file mode 100644 index 00000000..a08f4a1f Binary files /dev/null and b/xinnengyuan/ruoyi-admin/src/main/resources/template/设计验证表.docx differ diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/SubConstructionUserQueryReq.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/SubConstructionUserQueryReq.java index 549b363f..946d51c1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/SubConstructionUserQueryReq.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/domain/dto/constructionuser/SubConstructionUserQueryReq.java @@ -101,4 +101,7 @@ public class SubConstructionUserQueryReq implements Serializable { */ private String userId; + + private String phone; + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubConstructionUserServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubConstructionUserServiceImpl.java index 8e76bc75..f9f52e75 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubConstructionUserServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/contractor/service/impl/SubConstructionUserServiceImpl.java @@ -209,8 +209,10 @@ public class SubConstructionUserServiceImpl extends ServiceImpl lqw = Wrappers.lambdaQuery(); // 从对象中取值 String userName = req.getUserName(); + String phone = req.getPhone(); // 模糊查询 + lqw.like(StringUtils.isNotBlank(phone), SubConstructionUser::getPhone, phone); lqw.like(StringUtils.isNotBlank(userName), SubConstructionUser::getUserName, userName); lqw.isNull(SubConstructionUser::getProjectId); lqw.isNull(SubConstructionUser::getTeamId); diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/BusDrawingreviewReceiptsController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/BusDrawingreviewReceiptsController.java index 9e53b4e6..60ad7583 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/BusDrawingreviewReceiptsController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/BusDrawingreviewReceiptsController.java @@ -1,17 +1,40 @@ package org.dromara.design.controller; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import cn.hutool.core.util.StrUtil; +import com.deepoove.poi.XWPFTemplate; +import com.deepoove.poi.config.Configure; +import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; +import org.dromara.design.domain.BusDrawingreviewReceipts; +import org.dromara.design.domain.DesCollectFile; +import org.dromara.design.domain.DesDesignChange; import org.dromara.design.domain.bo.DesUserBo; +import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto; +import org.dromara.design.domain.vo.DesCollectFileWordVo; import org.dromara.design.domain.vo.DesUserVo; +import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; +import org.dromara.design.service.IDesDesignChangeService; import org.dromara.design.service.IDesUserService; +import org.dromara.project.domain.BusProject; import org.dromara.project.domain.vo.project.BusSubProjectVo; import org.dromara.project.service.IBusProjectService; +import org.dromara.system.service.ISysDictDataService; +import org.dromara.system.service.ISysUserService; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import org.dromara.common.idempotent.annotation.RepeatSubmit; @@ -44,6 +67,12 @@ public class BusDrawingreviewReceiptsController extends BaseController { private final IDesUserService desUserService; + private final IDesDesignChangeService desDesignChangeService; + + private final ISysDictDataService dictDataService; + + private final ISysUserService userService; + /** * 查询设计-图纸评审验证列表 */ @@ -132,4 +161,85 @@ public class BusDrawingreviewReceiptsController extends BaseController { return R.ok(desUserService.queryList(bo)); } + + 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 desDesignChangeVo = desDesignChangeService.queryById(id); + BusDrawingreviewReceipts receipts = busDrawingreviewReceiptsService.lambdaQuery() + .eq(BusDrawingreviewReceipts::getDrawingreviewId, id) + .last("limit 1") + .one(); + DesDesignExtendDetailDto extendDetail = desDesignChangeVo.getExtendDetail(); + String s = dictDataService.selectDictLabel("des_user_major", receipts.getProfessional()); + String designerName = null; + if(StrUtil.isNotBlank(receipts.getDesigner())){ + Long userId = Long.parseLong(receipts.getDesigner()); + designerName= userService.queryNameById(userId); + } + + Map placeholderData = new HashMap<>(); + placeholderData.put("projectName", receipts.getProjectName()); + placeholderData.put("subName",extendDetail.getSubName()); + placeholderData.put("stage", receipts.getStage()); + placeholderData.put("professionalName", s); + placeholderData.put("volume", receipts.getVolume()); + placeholderData.put("designerName", designerName); + placeholderData.put("verificationOpinion", receipts.getVerificationOpinion()); + placeholderData.put("executionOpinion", receipts.getExecutionOpinion()); + // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- + // 读取resources下的“设计项目负责人任命通知单.docx”模板 + ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); + try (InputStream templateIs = templateResource.getInputStream(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + + XWPFTemplate template = XWPFTemplate.compile(templateIs).render(placeholderData); + + // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- + template.write(outputStream); + template.close(); // 关闭模板资源 + return outputStream.toByteArray(); + } + } + + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectFileController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectFileController.java index d81700be..036294ef 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectFileController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/controller/DesCollectFileController.java @@ -1,15 +1,31 @@ package org.dromara.design.controller; -import java.util.List; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.util.*; +import java.util.stream.Collectors; +import com.deepoove.poi.XWPFTemplate; +import com.deepoove.poi.config.Configure; +import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; +import org.dromara.design.domain.DesCollectFile; import org.dromara.design.domain.bo.DesCollectFileBo; import org.dromara.design.domain.dto.ExportDto; +import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto; import org.dromara.design.domain.vo.DesCollectFileVo; +import org.dromara.design.domain.vo.DesCollectFileWordVo; +import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; import org.dromara.design.service.IDesCollectFileService; +import org.dromara.project.domain.BusProject; +import org.dromara.project.service.IBusProjectService; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import org.dromara.common.idempotent.annotation.RepeatSubmit; @@ -39,6 +55,8 @@ public class DesCollectFileController extends BaseController { private final IDesCollectFileService desCollectFileService; + private final IBusProjectService projectService; + /** * 查询收资文件列表 */ @@ -106,7 +124,6 @@ public class DesCollectFileController extends BaseController { return toAjax(desCollectFileService.deleteWithValidByIds(List.of(ids), true)); } - /** * 上传资料文件 */ @@ -119,10 +136,92 @@ public class DesCollectFileController extends BaseController { return toAjax(desCollectFileService.addFile(file, catalogueId, projectId)); } - - @PostMapping("/exportZip") public void exportZip(ExportDto dto, HttpServletResponse response) throws Exception { desCollectFileService.exportAsZip(dto, response); } + + 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获取项目名称、负责人等) + List list = desCollectFileService.lambdaQuery() + .eq(DesCollectFile::getProjectId, projectId).list(); + + List files = new ArrayList<>(); + int i = 1; + for (DesCollectFile desCollectFile : list) { + DesCollectFileWordVo desCollectFileWordVo = new DesCollectFileWordVo(); + desCollectFileWordVo.setNum(i); + i++; + desCollectFileWordVo.setFileName(desCollectFile.getFileName()); + files.add(desCollectFileWordVo); + } + + BusProject project = projectService.getById(projectId); + + + Map placeholderData = new HashMap<>(); + placeholderData.put("projectName", project.getProjectName()); + placeholderData.put("files",files); + // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- + // 读取resources下的“设计项目负责人任命通知单.docx”模板 + ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); + try (InputStream templateIs = templateResource.getInputStream(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + + LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); + + Configure config = Configure.builder() + .bind("files", policy).build(); + + XWPFTemplate template = XWPFTemplate.compile(templateIs, config).render(placeholderData); + + // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- + template.write(outputStream); + template.close(); // 关闭模板资源 + return outputStream.toByteArray(); + } + } + + + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/domain/vo/DesCollectFileWordVo.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/domain/vo/DesCollectFileWordVo.java new file mode 100644 index 00000000..2ded510b --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/design/domain/vo/DesCollectFileWordVo.java @@ -0,0 +1,15 @@ +package org.dromara.design.domain.vo; + +import lombok.Data; + +@Data +public class DesCollectFileWordVo { + + private Integer num; + + private String fileName; + + private String opinion; + + +}