|
@@ -45,6 +45,7 @@ import com.jeeplus.modules.workcontractinfo.service.WorkContractInfoService;
|
|
|
import com.jeeplus.modules.workfullmanage.utils.ZipUtils;
|
|
import com.jeeplus.modules.workfullmanage.utils.ZipUtils;
|
|
|
import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
|
|
import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
|
|
|
import com.jeeplus.modules.workinvoice.entity.WorkInvoiceProjectRelation;
|
|
import com.jeeplus.modules.workinvoice.entity.WorkInvoiceProjectRelation;
|
|
|
|
|
+import com.jeeplus.modules.workinvoice.service.WorkInvoiceDownloadRecordService;
|
|
|
import com.jeeplus.modules.workinvoice.service.WorkInvoiceService;
|
|
import com.jeeplus.modules.workinvoice.service.WorkInvoiceService;
|
|
|
import com.jeeplus.modules.workinvoicealter.entity.WorkInvoiceAlter;
|
|
import com.jeeplus.modules.workinvoicealter.entity.WorkInvoiceAlter;
|
|
|
import com.jeeplus.modules.workinvoicealter.service.WorkInvoiceAlterService;
|
|
import com.jeeplus.modules.workinvoicealter.service.WorkInvoiceAlterService;
|
|
@@ -94,6 +95,8 @@ public class WorkInvoiceController extends BaseController {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private WorkInvoiceService workInvoiceService;
|
|
private WorkInvoiceService workInvoiceService;
|
|
|
@Autowired
|
|
@Autowired
|
|
|
|
|
+ private WorkInvoiceDownloadRecordService downloadRecordService;
|
|
|
|
|
+ @Autowired
|
|
|
private AreaService areaService;
|
|
private AreaService areaService;
|
|
|
|
|
|
|
|
@Autowired
|
|
@Autowired
|
|
@@ -1768,14 +1771,17 @@ public class WorkInvoiceController extends BaseController {
|
|
|
String zipFilePath = null;
|
|
String zipFilePath = null;
|
|
|
InputStream is = null;
|
|
InputStream is = null;
|
|
|
OutputStream os = null;
|
|
OutputStream os = null;
|
|
|
|
|
+ boolean downloadSuccess = false;
|
|
|
|
|
+ List<String> failedMessages = new ArrayList<>();
|
|
|
|
|
+ Set<String> failedInvoiceIds = new HashSet<>();
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
|
String timeStamp = sdf.format(new Date());
|
|
String timeStamp = sdf.format(new Date());
|
|
|
String fileName = "数电发票批量下载_" + timeStamp;
|
|
String fileName = "数电发票批量下载_" + timeStamp;
|
|
|
|
|
|
|
|
- // 1. 调用Service生成ZIP文件
|
|
|
|
|
- zipFilePath = workInvoiceService.exportInvoiceAll(idList, fileName);
|
|
|
|
|
|
|
+ // 1. 调用Service生成ZIP文件(传入failedMessages收集失败信息)
|
|
|
|
|
+ zipFilePath = workInvoiceService.exportInvoiceAll(idList, fileName, failedMessages, failedInvoiceIds);
|
|
|
|
|
|
|
|
// 2. 校验ZIP文件
|
|
// 2. 校验ZIP文件
|
|
|
File zipFile = new File(zipFilePath);
|
|
File zipFile = new File(zipFilePath);
|
|
@@ -1800,7 +1806,10 @@ public class WorkInvoiceController extends BaseController {
|
|
|
os.write(buffer, 0, len);
|
|
os.write(buffer, 0, len);
|
|
|
}
|
|
}
|
|
|
os.flush();
|
|
os.flush();
|
|
|
- logger.info("批量下载ZIP文件已返回给前端:{}", zipFileName);
|
|
|
|
|
|
|
+ downloadSuccess = true;
|
|
|
|
|
+ // 将失败信息存入session,供前端AJAX查询
|
|
|
|
|
+ request.getSession().setAttribute("batchDownloadFailures", failedMessages);
|
|
|
|
|
+ logger.info("批量下载ZIP文件已返回给前端:{},失败数:{}", zipFileName, failedMessages.size());
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
// 失败:返回JSON格式错误信息
|
|
// 失败:返回JSON格式错误信息
|
|
@@ -1829,6 +1838,43 @@ public class WorkInvoiceController extends BaseController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 批量下载成功后,只记录成功下载的发票(排除失败的)
|
|
|
|
|
+ if (downloadSuccess) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ for (String invoiceId : idList) {
|
|
|
|
|
+ if (!failedInvoiceIds.contains(invoiceId)) {
|
|
|
|
|
+ downloadRecordService.recordDownloadSuccess(invoiceId, "batch_download");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.info("批量下载记录成功:invoiceIds={}, userId={}", idList, UserUtils.getUser().getId());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error("批量下载记录失败!", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询批量下载失败详情(AJAX接口)
|
|
|
|
|
+ * 返回JSON格式:{code:200, failures:["msg1","msg2"]} 或 {code:200, failures:[]}
|
|
|
|
|
+ */
|
|
|
|
|
+ @ResponseBody
|
|
|
|
|
+ @RequestMapping(value = "batchDownloadFailures")
|
|
|
|
|
+ public String batchDownloadFailures(HttpServletRequest request) {
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
|
+ List<String> failures = (List<String>) request.getSession().getAttribute("batchDownloadFailures");
|
|
|
|
|
+ // 查询后立即清除,避免重复读取
|
|
|
|
|
+ request.getSession().removeAttribute("batchDownloadFailures");
|
|
|
|
|
+ if (failures == null || failures.isEmpty()) {
|
|
|
|
|
+ return "{\"code\":200,\"failures\":[]}";
|
|
|
|
|
+ }
|
|
|
|
|
+ StringBuilder sb = new StringBuilder("{\"code\":200,\"failures\":[");
|
|
|
|
|
+ for (int i = 0; i < failures.size(); i++) {
|
|
|
|
|
+ if (i > 0) sb.append(",");
|
|
|
|
|
+ sb.append("\"").append(failures.get(i).replace("\"", "\\\"")).append("\"");
|
|
|
|
|
+ }
|
|
|
|
|
+ sb.append("]}");
|
|
|
|
|
+ return sb.toString();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1836,11 +1882,13 @@ public class WorkInvoiceController extends BaseController {
|
|
|
*/
|
|
*/
|
|
|
private void writeErrorResponse(HttpServletResponse response, String message) {
|
|
private void writeErrorResponse(HttpServletResponse response, String message) {
|
|
|
response.setCharacterEncoding("UTF-8");
|
|
response.setCharacterEncoding("UTF-8");
|
|
|
- response.setContentType("application/json;charset=UTF-8"); // 改为JSON格式
|
|
|
|
|
|
|
+ response.setContentType("application/json;charset=UTF-8");
|
|
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
|
try {
|
|
try {
|
|
|
- // 输出标准JSON,方便前端解析
|
|
|
|
|
- String errorJson = "{\"code\":500,\"msg\":\"" + message.replace("\"", "\\\"") + "\"}";
|
|
|
|
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
|
|
+ result.put("code", 500);
|
|
|
|
|
+ result.put("msg", message);
|
|
|
|
|
+ String errorJson = JsonMapper.getInstance().toJson(result);
|
|
|
response.getWriter().write(errorJson);
|
|
response.getWriter().write(errorJson);
|
|
|
} catch (IOException ioException) {
|
|
} catch (IOException ioException) {
|
|
|
logger.error("响应错误信息失败!", ioException);
|
|
logger.error("响应错误信息失败!", ioException);
|