/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.sxkj.gd.workorder.service.impl; import org.sxkj.gd.workorder.entity.GdTaskResultEntity; import org.sxkj.gd.workorder.vo.GdTaskResultVO; import org.sxkj.gd.workorder.excel.GdTaskResultExcel; import org.sxkj.gd.workorder.mapper.GdTaskResultMapper; import org.sxkj.gd.workorder.service.IGdTaskResultService; import org.sxkj.common.utils.HeaderUtils; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.utils.Func; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * 成果表 服务实现类 * * @author lw * @since 2026-01-14 */ @Service public class GdTaskResultServiceImpl extends BaseServiceImpl implements IGdTaskResultService { @Override public IPage selectGdTaskResultPage(IPage page, GdTaskResultVO gdTaskResult) { return page.setRecords(baseMapper.selectGdTaskResultPage(page, gdTaskResult)); } @Override public List listByPatrolTaskId(Long patrolTaskId) { List gdTaskResultVOS = baseMapper.selectGdTaskResultListByPatrolTaskId(patrolTaskId); for (GdTaskResultVO gdTaskResultVO : gdTaskResultVOS) { gdTaskResultVO.setResultUrl(unescapeUrl(gdTaskResultVO.getResultUrl())); } return gdTaskResultVOS; } @Override public List exportGdTaskResult(Wrapper queryWrapper) { List gdTaskResultList = baseMapper.exportGdTaskResult(queryWrapper); //gdTaskResultList.forEach(gdTaskResult -> { // gdTaskResult.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdTaskResult.getType())); //}); return gdTaskResultList; } @Override public boolean saveBatchTaskResult(List gdTaskResultEntities) { if (gdTaskResultEntities == null || gdTaskResultEntities.isEmpty()) { log.error("saveBatchTaskResult-批量新增-对外接口数据为空"); return false; } gdTaskResultEntities.forEach(gdTaskResult -> { String resultUrl = gdTaskResult.getResultUrl(); // 使用HeaderUtils处理区域代码 // resultUrl = http://220.177.172.27:8100/S3/xcy010.eoshlw.internal.jazwy.cn/2026/04/23/DJI_20260128135433_0005_V_20260423111422A015.jpeg // resultUrl = http://220.177.172.27:8100/S3/xcy010.eoshlw.internal.jazwy.cn/2026/04/23/2026-04-23-09-50-29-0_20260423190046A001.mp4 gdTaskResult.setAttachmentType(HeaderUtils.getAttachmentType(resultUrl)); String processedAreaCode = HeaderUtils.processAreaCode(gdTaskResult.getAreaCode()); gdTaskResult.setAreaCode(processedAreaCode); gdTaskResult.setStatus(0); gdTaskResult.setUpdateTime(new Date()); gdTaskResult.setCreateTime(new Date()); gdTaskResult.setIsDeleted(0); gdTaskResult.setCreateDept(1L); gdTaskResult.setUpdateUser(1L); gdTaskResult.setDistributeStatus(0); }); // 执行批量保存并返回结果 int result = baseMapper.insertBatch(gdTaskResultEntities); return result > 0; } @Override public boolean updateTaskResultById(GdTaskResultEntity taskResult) { int result = baseMapper.updateTaskResultById(taskResult); return result > 0; } /** * 将URL中的HTML/XML转义字符还原为原始字符 * 主要处理 & 转换为 & * * @param url 包含转义字符的URL * @return 还原后的URL */ public static String unescapeUrl(String url) { if (url == null || url.isEmpty()) { return url; } // 按照优先级顺序进行替换,避免重复替换问题 String result = url; // 处理常见的HTML/XML转义字符 result = result.replace("&", "&"); // &符号 result = result.replace("<", "<"); // 小于号 result = result.replace(">", ">"); // 大于号 result = result.replace(""", "\""); // 双引号 result = result.replace("'", "'"); // 单引号 result = result.replace("'", "'"); // 单引号 return result; } @Override public void downloadResultFiles(String ids, HttpServletResponse response) { // 根据ID列表查询成果记录 List idList = Func.toLongList(ids); List resultList = listByIds(idList); if (resultList == null || resultList.isEmpty()) { throw new RuntimeException("未找到成果数据"); } // 设置响应头 response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=result_files.zip"); try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { for (GdTaskResultEntity result : resultList) { String resultUrl = result.getResultUrl(); if (resultUrl == null || resultUrl.isEmpty()) { continue; } // 处理转义字符 resultUrl = unescapeUrl(resultUrl); try { // 从URL下载文件 URL url = new URL(resultUrl); URLConnection connection = url.openConnection(); connection.setConnectTimeout(5000); connection.setReadTimeout(10000); // 从URL中提取文件名 String fileName = extractFileName(resultUrl, result.getId()); // 添加到ZIP ZipEntry zipEntry = new ZipEntry(fileName); zos.putNextEntry(zipEntry); try (InputStream is = connection.getInputStream()) { byte[] buffer = new byte[4096]; int len; while ((len = is.read(buffer)) > 0) { zos.write(buffer, 0, len); } } zos.closeEntry(); } catch (Exception e) { // 单个文件下载失败,继续处理其他文件 // 可以记录日志 } } } catch (IOException e) { throw new RuntimeException("下载文件失败", e); } } /** * 从URL中提取文件名 */ private String extractFileName(String url, Long resultId) { if (url == null || url.isEmpty()) { return resultId + "_unknown"; } // 从URL中提取最后一部分作为文件名 int lastSlash = url.lastIndexOf('/'); if (lastSlash != -1 && lastSlash < url.length() - 1) { String fileName = url.substring(lastSlash + 1); // 处理可能的查询参数 int questionMark = fileName.indexOf('?'); if (questionMark != -1) { fileName = fileName.substring(0, questionMark); } return resultId + "_" + fileName; } return resultId + "_file"; } }