|
@@ -1,5 +1,7 @@
|
|
|
package cn.iocoder.yudao.module.pms.controller.admin.qhse.soc;
|
|
package cn.iocoder.yudao.module.pms.controller.admin.qhse.soc;
|
|
|
|
|
|
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
|
|
+import cn.hutool.core.net.URLEncodeUtil;
|
|
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
|
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
@@ -11,16 +13,26 @@ import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummaryRes
|
|
|
import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummarySaveReqVO;
|
|
import cn.iocoder.yudao.module.pms.controller.admin.qhse.soc.vo.IotSocSummarySaveReqVO;
|
|
|
import cn.iocoder.yudao.module.pms.dal.dataobject.qhse.soc.IotSocSummaryDO;
|
|
import cn.iocoder.yudao.module.pms.dal.dataobject.qhse.soc.IotSocSummaryDO;
|
|
|
import cn.iocoder.yudao.module.pms.service.qhse.soc.IotSocSummaryService;
|
|
import cn.iocoder.yudao.module.pms.service.qhse.soc.IotSocSummaryService;
|
|
|
|
|
+import cn.iocoder.yudao.module.pms.util.SafetyObservationCardGenerator;
|
|
|
|
|
+import com.google.common.collect.ImmutableList;
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
|
|
|
+import liquibase.repackaged.org.apache.commons.lang3.StringUtils;
|
|
|
|
|
+import org.springframework.core.io.ByteArrayResource;
|
|
|
|
|
+import org.springframework.core.io.InputStreamResource;
|
|
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
|
|
+import org.springframework.http.MediaType;
|
|
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
|
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 javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
|
|
+import javax.annotation.security.PermitAll;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
import javax.validation.Valid;
|
|
import javax.validation.Valid;
|
|
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
|
|
@@ -91,4 +103,72 @@ public class IotSocSummaryController {
|
|
|
BeanUtils.toBean(list, IotSocSummaryRespVO.class));
|
|
BeanUtils.toBean(list, IotSocSummaryRespVO.class));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 下载接口:前端直接调用,触发文件下载
|
|
|
|
|
+ @GetMapping("/safety-card/download/{id}")
|
|
|
|
|
+ @PermitAll
|
|
|
|
|
+ public ResponseEntity<ByteArrayResource> downloadSafetyCard(@PathVariable("id") Long id) throws Exception {
|
|
|
|
|
+ IotSocSummaryDO iotSocSummary = iotSocSummaryService.getIotSocSummary(id);
|
|
|
|
|
+ String person = iotSocSummary.getUserName();
|
|
|
|
|
+ String date = DateUtil.format(iotSocSummary.getObservationDate(), "yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
+ String remark = iotSocSummary.getRemark();
|
|
|
|
|
+ // 1. 构建生成参数(实际业务中需从前端/数据库获取checkItems)
|
|
|
|
|
+ List<SafetyObservationCardGenerator.CheckItem> checkItems = buildCheckItems(); // 替换为实际业务逻辑
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 生成文件字节流(你原有逻辑)
|
|
|
|
|
+ byte[] docBytes = SafetyObservationCardGenerator.generateCardToBytes(checkItems, person, date, remark);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 【关键修复】中文文件名必须 URL 编码!!!
|
|
|
|
|
+ String fileName = "行为安全观察与沟通卡" + StringUtils.substring(date, 0, 10) + person + ".docx";
|
|
|
|
|
+ String encodeFileName = URLEncodeUtil.encode(fileName); // Hutool编码
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 正确设置响应头
|
|
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
|
|
+ headers.add(HttpHeaders.CONTENT_DISPOSITION,
|
|
|
|
|
+ "attachment; filename=\"" + encodeFileName + "\""); // 加引号更规范
|
|
|
|
|
+ headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
|
|
|
|
+
|
|
|
|
|
+ return ResponseEntity.ok()
|
|
|
|
|
+ .headers(headers)
|
|
|
|
|
+ .contentLength(docBytes.length)
|
|
|
|
|
+ .body(new ByteArrayResource(docBytes));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 预览接口:供KKFileView调用(核心:返回文件流,不触发下载)
|
|
|
|
|
+ @GetMapping("/safety-card/preview/{id}")
|
|
|
|
|
+ @PermitAll
|
|
|
|
|
+ public ResponseEntity<InputStreamResource> previewSafetyCard(@PathVariable("id") Long id) throws Exception {
|
|
|
|
|
+ IotSocSummaryDO iotSocSummary = iotSocSummaryService.getIotSocSummary(id);
|
|
|
|
|
+ String person = iotSocSummary.getUserName();
|
|
|
|
|
+ String date = DateUtil.format(iotSocSummary.getObservationDate(), "yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
+ String remark = iotSocSummary.getRemark();
|
|
|
|
|
+ // 1. 构建生成参数
|
|
|
|
|
+ List<SafetyObservationCardGenerator.CheckItem> checkItems = buildCheckItems(); // 替换为实际业务逻辑
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 动态生成文档字节数组
|
|
|
|
|
+ byte[] docBytes = SafetyObservationCardGenerator.generateCardToBytes(checkItems, person, date, remark);
|
|
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(docBytes);
|
|
|
|
|
+ InputStreamResource resource = new InputStreamResource(bais);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 设置响应头(关键:不设置attachment,让KKFileView能读取流)
|
|
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
|
|
+ headers.add(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
|
|
|
|
+ // 可选:设置缓存(根据业务需求)
|
|
|
|
|
+ headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
|
|
|
+
|
|
|
|
|
+ return ResponseEntity.ok()
|
|
|
|
|
+ .headers(headers)
|
|
|
|
|
+ .contentLength(docBytes.length)
|
|
|
|
|
+ .body(resource);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 示例:构建检查项(实际业务中需从前端参数/数据库获取)
|
|
|
|
|
+ private List<SafetyObservationCardGenerator.CheckItem> buildCheckItems() {
|
|
|
|
|
+ return ImmutableList.of(
|
|
|
|
|
+ new SafetyObservationCardGenerator.CheckItem("个人防护", "头部", "Personal Protection Equipment", "Head"),
|
|
|
|
|
+ new SafetyObservationCardGenerator.CheckItem("规范操作", "其他", "Tools and Equipment", "Other"),
|
|
|
|
|
+ new SafetyObservationCardGenerator.CheckItem("作业场所", "地面滑(水/雨/雪/油污等)", "Housekeeping", "Slippery floor (Water / Rain / Snow / Oil etc.)")
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|