收资,提资清单导出

This commit is contained in:
zt
2025-08-12 21:38:56 +08:00
parent e4d1be276b
commit 1a7ba72978
14 changed files with 243 additions and 7 deletions

View File

@ -3,6 +3,7 @@ package org.dromara.design.constant;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.design.domain.DesCollect;
import org.dromara.design.domain.DesDesignChange;
import org.dromara.design.domain.DesExtract;
import java.text.SimpleDateFormat;
@ -22,6 +23,10 @@ public interface DesDesignConstant {
*/
String DESIGN_COLLECT_TEMPLATE_PATH = "template/收集资料清单模板.docx";
/**
* 提资清单模版路径
*/
String DESIGN_EXTRACT_TEMPLATE_PATH = "template/互相提交资料清单模板.docx";
/**
* 设计变更申请单文件路径
@ -29,10 +34,15 @@ public interface DesDesignConstant {
String DESIGN_CHANGE_FILE_URL = "docs/design/change/";
/**
* 设计变更申请单文件路径
* 收集资料清单文件路径
*/
String DESIGN_COLLECT_FILE_URL = "docs/design/collect/";
/**
* 提资清单文件路径
*/
String DESIGN_EXTRACT_FILE_URL = "docs/design/extract/";
/**
* 设计变更申请单文件名
*/
@ -63,6 +73,23 @@ public interface DesDesignConstant {
*/
static String getDesignCollectFileName(DesCollect desCollect) {
String createDate = DateUtils.formatDate(desCollect.getCreateTime());
return String.format("设计变更申请单(%s.docx", createDate);
return String.format("收集清单(%s.docx", createDate);
}
/**
* 提资清单路径
*/
static String getDesignExtractFileUrl(DesExtract desExtract) {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(desExtract.getUpdateTime());
return String.format("%s%s/%s", DESIGN_EXTRACT_FILE_URL, desExtract.getId(), timestamp);
}
/**
* 提资清单文件名
*/
static String getDesignExtractFileName(DesExtract desExtract) {
String createDate = DateUtils.formatDate(desExtract.getCreateTime());
return String.format("提资清单(%s.docx", createDate);
}
}

View File

@ -113,4 +113,16 @@ public class DesExtractController extends BaseController {
public R<Long> batchAddOrUpdate(@RequestBody DesExtractBatchDto dto) {
return R.ok(desExtractService.batchAddOrUpdate(dto));
}
/**
* 清单导出
*/
@SaCheckPermission("design:extract:export")
@Log(title = "提资清单", businessType = BusinessType.EXPORT)
@PostMapping("/exportWord")
public void exportWordById(Long id, HttpServletResponse response){
desExtractService.exportWordById(id, response);
}
}

View File

@ -109,4 +109,9 @@ public class DesDesignChange extends BaseEntity {
*/
private String remark;
/**
* 额外内容
*/
private String detail;
}

View File

@ -5,8 +5,6 @@ import lombok.Data;
@Data
public class DesCollectCatalogueWordDto {
private Integer num;
private String catalogueName;
private String remark;

View File

@ -98,4 +98,9 @@ public class DesDesignChangeCreateReq implements Serializable {
*/
private String remark;
/**
* 额外参数
*/
private DesDesignExtendDetailDto extendDetail;
}

View File

@ -98,4 +98,9 @@ public class DesDesignChangeUpdateReq implements Serializable {
*/
private String remark;
/**
* 额外参数
*/
private DesDesignExtendDetailDto extendDetail;
}

View File

@ -0,0 +1,50 @@
package org.dromara.design.domain.dto.designchange;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lilemy
* @date 2025/7/3 18:48
*/
@Data
public class DesDesignExtendDetailDto implements Serializable {
/**
* 子项名称
*/
private String subName;
/**
* 设计阶段
*/
private String designPhase;
/**
* 原设计处置(1-原图作废2-原图保留部分修改3-原图保留,补充设计)
*/
private String designDisposal;
/**
* 变更类别(1-重大2-一般)
*/
private String changeCategory;
/**
* 实施程序1-建设单位重新申报初步设计审批2-建设单位送原施工图审查机构审查、建设主管部门备案后交付实施;3-建设单位确认后交付实施)
*/
private String ImpProcedure;
/**
* 涉及专业
*/
private String involvingProfessions;
}

View File

@ -3,6 +3,7 @@ package org.dromara.design.domain.vo.designchange;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.design.domain.DesDesignChange;
import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto;
import org.dromara.system.domain.vo.SysOssVo;
import java.io.Serial;
@ -129,4 +130,9 @@ public class DesDesignChangeVo implements Serializable {
*/
private Date createTime;
/**
* 额外参数
*/
private DesDesignExtendDetailDto extendDetail;
}

View File

@ -1,5 +1,6 @@
package org.dromara.design.service;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.design.domain.dto.desExtract.DesExtractBatchDto;
import org.dromara.design.domain.vo.DesExtractVo;
import org.dromara.design.domain.bo.DesExtractBo;
@ -75,4 +76,9 @@ public interface IDesExtractService extends IService<DesExtract>{
* 批量添加或更新提资清单
*/
Long batchAddOrUpdate(DesExtractBatchDto dto);
/**
* 导出Word
*/
void exportWordById(Long id, HttpServletResponse response);
}

View File

@ -219,6 +219,8 @@ public class DesCollectServiceImpl extends ServiceImpl<DesCollectMapper, DesColl
return desCollectVo;
}
@Override
public void exportWordById(Long id, HttpServletResponse response) {
DesCollect descCollect = this.getById(id);
if (descCollect == null) {

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -32,6 +33,7 @@ import org.dromara.design.domain.DesDesignChange;
import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq;
import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq;
import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq;
import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto;
import org.dromara.design.domain.vo.designchange.DesDesignChangeVo;
import org.dromara.design.mapper.DesDesignChangeMapper;
import org.dromara.design.service.IDesDesignChangeService;
@ -85,7 +87,9 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
if (designChange == null) {
throw new ServiceException("设计变更不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(designChange);
DesDesignChangeVo vo = this.getVo(designChange);
vo.setExtendDetail(JSONUtil.toBean(designChange.getDetail(), DesDesignExtendDetailDto.class));
return vo;
}
/**
@ -197,11 +201,17 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
DesDesignChange entity = new DesDesignChange();
BeanUtils.copyProperties(req, entity);
validEntityBeforeSave(entity, true);
entity.setDetail(JSONUtil.toJsonStr(req.getExtendDetail()));
if("1".equals(req.getExtendDetail().getDesignDisposal())){
//todo: 卷册号文件作废
}
boolean save = this.save(entity);
if (!save) {
throw new ServiceException("新增设计变更单失败", HttpStatus.ERROR);
}
return this.getVo(this.getById(entity.getId()));
DesDesignChangeVo vo = this.getVo(this.getById(entity.getId()));
vo.setExtendDetail(req.getExtendDetail());
return vo;
}
/**
@ -219,11 +229,14 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
DesDesignChange entity = new DesDesignChange();
BeanUtils.copyProperties(req, entity);
validEntityBeforeSave(entity, false);
entity.setDetail(JSONUtil.toJsonStr(req.getExtendDetail()));
boolean result = this.updateById(entity);
if (!result) {
throw new ServiceException("修改设计变更单失败", HttpStatus.ERROR);
}
return this.getVo(this.getById(entity.getId()));
DesDesignChangeVo vo = this.getVo(this.getById(entity.getId()));
vo.setExtendDetail(req.getExtendDetail());
return vo;
}

View File

@ -3,26 +3,42 @@ package org.dromara.design.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.oss.exception.OssException;
import org.dromara.common.utils.DocumentUtil;
import org.dromara.design.constant.DesDesignConstant;
import org.dromara.design.domain.DesCollect;
import org.dromara.design.domain.DesCollectCatalogue;
import org.dromara.design.domain.DesExtractCatalogue;
import org.dromara.design.domain.bo.DesExtractCatalogueBo;
import org.dromara.design.domain.dto.desCollect.DesCollectCatalogueWordDto;
import org.dromara.design.domain.dto.desCollect.DesCollectWordDto;
import org.dromara.design.domain.dto.desExtract.DesExtractBatchDto;
import org.dromara.design.domain.vo.DesExtractCatalogueVo;
import org.dromara.design.service.IDesExtractCatalogueService;
import org.dromara.project.service.IBusProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.event.EventListener;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.dromara.design.domain.bo.DesExtractBo;
import org.dromara.design.domain.vo.DesExtractVo;
@ -31,9 +47,17 @@ import org.dromara.design.mapper.DesExtractMapper;
import org.dromara.design.service.IDesExtractService;
import org.springframework.transaction.annotation.Transactional;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.zip.ZipOutputStream;
/**
* 提资清单Service业务层处理
@ -50,6 +74,10 @@ public class DesExtractServiceImpl extends ServiceImpl<DesExtractMapper, DesExtr
private final IDesExtractCatalogueService extractCatalogueService;
private final IBusProjectService projectService;
private final DictService dictService;
/**
* 查询提资清单
*
@ -177,6 +205,85 @@ public class DesExtractServiceImpl extends ServiceImpl<DesExtractMapper, DesExtr
return convert.getId();
}
@Override
public void exportWordById(Long id, HttpServletResponse response) {
DesExtract desExtract = this.getById(id);
if (desExtract == null) {
throw new ServiceException("数据不存在");
}
Path targetDir = Paths.get(DesDesignConstant.getDesignExtractFileUrl(desExtract));
// 如果存在目录则直接返回,不存在则生成文件并返回
if (!Files.exists(targetDir)) {
// 清理旧文件
String baseUrl = DesDesignConstant.DESIGN_EXTRACT_FILE_URL + desExtract.getId();
try {
Path dirPath = Paths.get(baseUrl);
if (Files.exists(dirPath)) {
FileUtils.deleteDirectory(dirPath);
}
} catch (IOException e) {
log.error("文件目录:{},清理失败", baseUrl, e);
}
// 准备数据
List<DesExtractCatalogue> itemList = extractCatalogueService.list(Wrappers.
<DesExtractCatalogue>lambdaQuery().eq(DesExtractCatalogue::getExtractId, id));
DesCollectWordDto data = this.getReplacementDto(desExtract, itemList);
// 生成文件
try (InputStream is = getClass().getClassLoader().getResourceAsStream(DesDesignConstant.DESIGN_EXTRACT_TEMPLATE_PATH)) {
if (is == null) {
throw new ServiceException("模板文件不存在");
}
LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder().bind("items", hackLoopTableRenderPolicy).build();
XWPFTemplate template = XWPFTemplate.compile(is, config);
template.render(data);
// 创建目标目录
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir);
}
// 组合目标文件名
String fileName = DesDesignConstant.getDesignExtractFileName(desExtract);
// 保存修改后的文件
try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) {
template.write(fos);
}
template.close();
} catch (IOException e) {
throw new OssException("生成Word文件失败错误信息: " + e.getMessage());
}
}
// 设置响应头返回ZIP文件
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
DocumentUtil.zipDirectory(targetDir, targetDir, zos);
zos.flush();
} catch (Exception e) {
throw new OssException("生成ZIP文件失败错误信息: " + e.getMessage());
}
}
/**
* 根据实体获取替换数据
*/
private DesCollectWordDto getReplacementDto(DesExtract desExtract, List<DesExtractCatalogue> items) {
DesCollectWordDto dto = new DesCollectWordDto();
BeanUtils.copyProperties(desExtract, dto);
dto.setProjectName(projectService.getById(desExtract.getProjectId()).getProjectName());
dto.setMajorName(dictService.getDictLabel("des_user_major", desExtract.getUserMajor()));
// 明细项信息
List<DesCollectCatalogueWordDto> dtoItems = new ArrayList<>();
for (DesExtractCatalogue desc : items) {
DesCollectCatalogueWordDto itemDto = new DesCollectCatalogueWordDto();
BeanUtils.copyProperties(desc, itemDto);
dtoItems.add(itemDto);
}
dto.setItems(dtoItems);
return dto;
}
/**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
* 正常使用只需#processEvent.flowCode=='leave1'