@@ -35,6 +35,16 @@ import java.util.zip.ZipOutputStream; | |||
@Slf4j | |||
public class FreemarkerWordUtil { | |||
private static void setDownFileName(HttpServletResponse response, String fileName) { | |||
String fileNameEncoded; | |||
try { | |||
fileNameEncoded = URLEncoder.encode(fileName, "UTF-8"); | |||
} catch (UnsupportedEncodingException e) { | |||
throw new RuntimeException("文件名编码异常"); | |||
} | |||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEncoded); | |||
} | |||
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_31); | |||
static { | |||
@@ -75,7 +85,7 @@ public class FreemarkerWordUtil { | |||
Template template = CONFIGURATION.getTemplate(templateName); | |||
response.setCharacterEncoding(StandardCharsets.UTF_8.displayName()); | |||
response.setContentType(ContentType.APPLICATION_JSON.getMimeType()); | |||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8")); | |||
setDownFileName(response, fileName); | |||
try (StringWriter out = new StringWriter(); | |||
Writer writer = new BufferedWriter(out, 4096)) { | |||
template.process(data, writer); | |||
@@ -97,9 +107,7 @@ public class FreemarkerWordUtil { | |||
public static void exportBatch(HttpServletResponse response, List<FreemarkerBatchExportDTO> fbeList, String fileName) throws IOException, TemplateException { | |||
response.setCharacterEncoding(StandardCharsets.UTF_8.displayName()); | |||
response.setContentType("application/zip"); | |||
String encode = URLEncoder.encode(fileName, "UTF-8"); | |||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encode); | |||
setDownFileName(response, fileName); | |||
try (ServletOutputStream os = response.getOutputStream(); | |||
ZipOutputStream zos = new ZipOutputStream(os)) { | |||
for (FreemarkerBatchExportDTO param : fbeList) { | |||
@@ -1,5 +1,6 @@ | |||
package com.ningdatech.pmapi.expert.manage; | |||
import cn.hutool.core.util.StrUtil; | |||
import cn.hutool.json.JSONUtil; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
@@ -8,7 +9,9 @@ import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.cache.lock.DistributedLock; | |||
import com.ningdatech.file.entity.vo.result.AttachFileVo; | |||
import com.ningdatech.file.service.FileService; | |||
import com.ningdatech.pmapi.expert.constant.ReviewResultEnum; | |||
import com.ningdatech.pmapi.expert.model.dto.ReviewTemplateOptionDTO; | |||
import com.ningdatech.pmapi.expert.model.dto.ReviewTemplateSettingsDTO; | |||
import com.ningdatech.pmapi.expert.model.entity.ExpertReview; | |||
import com.ningdatech.pmapi.expert.model.entity.ReviewTemplateSettings; | |||
import com.ningdatech.pmapi.expert.model.req.ExpertReviewDetailReq; | |||
@@ -206,4 +209,35 @@ public class ExpertReviewManage { | |||
return expertReviewService.list(query); | |||
} | |||
public Map<Long, String> buildExpertReviewToStr(Long meetingId) { | |||
List<ExpertReview> reviews = listFinalExpertReviews(meetingId); | |||
if (reviews.isEmpty()) { | |||
return Collections.emptyMap(); | |||
} | |||
List<Long> templateIds = CollUtils.fieldList(reviews, ExpertReview::getTemplateId); | |||
List<ReviewTemplateSettings> ts = templateSettingsService.listByIds(templateIds); | |||
Map<Long, ReviewTemplateSettings> tsMap = CollUtils.listToMap(ts, ReviewTemplateSettings::getId); | |||
Map<Long, String> resMap = new HashMap<>(8); | |||
for (ExpertReview review : reviews) { | |||
ReviewTemplateSettings settings = tsMap.get(review.getTemplateId()); | |||
List<ReviewTemplateSettingsDTO> optionTemplates = JSONUtil.toList(settings.getContent(), ReviewTemplateSettingsDTO.class); | |||
List<ReviewTemplateOptionDTO> options = JSONUtil.toList(review.getContent(), ReviewTemplateOptionDTO.class); | |||
Map<Integer, ReviewTemplateOptionDTO> optionsMap = CollUtils.listToMap(options, ReviewTemplateOptionDTO::getQuestionSerialNo); | |||
StringBuilder str = new StringBuilder(); | |||
optionTemplates.forEach(ot -> { | |||
ReviewTemplateOptionDTO rto = optionsMap.get(ot.getSerialNo()); | |||
String optionsContent = ot.getOptions().stream() | |||
.filter(w -> rto.getOptionSerialNo().contains(w.getSerialNo())) | |||
.map(ReviewTemplateSettingsDTO.OptionDTO::getOption) | |||
.collect(Collectors.joining("、")); | |||
str.append("<w:br/>").append(ot.getTitle()).append(":").append(optionsContent).append(";"); | |||
}); | |||
str.append("<w:br/>").append("其他意见或建议").append(":") | |||
.append(StrUtil.blankToDefault(review.getOtherAdvice(), "--")).append(";"); | |||
str.append("<w:br/>").append("评审结果").append(":") | |||
.append(ReviewResultEnum.getByCode(review.getReviewResult()).getValue()).append(";"); | |||
resMap.put(review.getProjectId(), str.toString()); | |||
} | |||
return resMap; | |||
} | |||
} |
@@ -25,4 +25,6 @@ public class ExpertReviewTableDTO implements Serializable { | |||
private String holdOrg; | |||
private String reviewResult; | |||
} |
@@ -151,6 +151,7 @@ public class ExpertExportManage { | |||
List<FreemarkerBatchExportDTO> fbeList; | |||
if (meeting.getIsInnerProject()) { | |||
List<MeetingInnerProject> inners = meetingInnerProjectService.listByMeetingId(meetingId); | |||
Map<Long, String> reviewResultMap = expertReviewManage.buildExpertReviewToStr(meetingId); | |||
List<Long> projectIds = CollUtils.fieldList(inners, MeetingInnerProject::getProjectId); | |||
List<Project> projects = projectService.listByIds(projectIds); | |||
fbeList = projects.stream().map(w -> { | |||
@@ -160,6 +161,7 @@ public class ExpertExportManage { | |||
currData.setMeetingTime(startTime); | |||
currData.setMeetingAddress(meeting.getMeetingAddress()); | |||
currData.setProjectName(w.getProjectName()); | |||
currData.setReviewResult(reviewResultMap.get(w.getId())); | |||
fbe.setData(currData); | |||
fbe.setTemplate(EXPERT_REVIEW); | |||
fbe.setFileName(w.getProjectName() + ".doc"); | |||
@@ -553,21 +553,36 @@ | |||
<w:sz w:val="30"/> | |||
<w:sz-cs w:val="30"/> | |||
</w:rPr> | |||
<w:t>${meetingTime},${holdOrg}组织专家在${meetingAddress}对${projectName}进行评审。专家组认真听取了项目业主方、建设方的情况汇报,审阅了项目材料,实地查看了设备及平台演示,专家组织质询、讨论后提出以下意见: | |||
<w:t>${meetingTime},${holdOrg}组织专家在${meetingAddress}对${projectName} | |||
进行评审。专家组认真听取了项目业主方、建设方的情况汇报,审阅了项目材料,实地查看了设备及平台演示,专家组织质询、讨论后提出以下意见: | |||
</w:t> | |||
</w:r> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="244" w:line-rule="auto"/> | |||
<w:spacing w:line="257" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="244" w:line-rule="auto"/> | |||
<w:ind w:first-line="500" w:first-line-chars="0"/> | |||
<w:rPr> | |||
<w:rFonts w:ascii="微软雅黑" w:h-ansi="微软雅黑" w:fareast="微软雅黑" w:cs="微软雅黑" | |||
w:hint="fareast"/> | |||
<w:sz w:val="30"/> | |||
<w:sz-cs w:val="30"/> | |||
</w:rPr> | |||
</w:pPr> | |||
<w:r> | |||
<w:rPr> | |||
<w:rFonts w:ascii="微软雅黑" w:h-ansi="微软雅黑" w:fareast="微软雅黑" w:cs="微软雅黑" | |||
w:hint="fareast"/> | |||
<w:sz w:val="30"/> | |||
<w:sz-cs w:val="30"/> | |||
</w:rPr> | |||
<w:t>${(reviewResult)!}</w:t> | |||
</w:r> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
@@ -644,73 +659,13 @@ | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
<w:spacing w:line="244" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||
<w:pPr> | |||
<w:pStyle w:val="a2"/> | |||
<w:spacing w:line="245" w:line-rule="auto"/> | |||
<w:spacing w:line="244" w:line-rule="auto"/> | |||
</w:pPr> | |||
</w:p> | |||
<w:p> | |||