Commit 252a387f6c53b06f6fbcaf77f75c35983f3bec79
Merge branch 'master_dev' into 'master'
fix: 报表导出存在数据异常的情况 See merge request yunteng/thingskit!270
Showing
2 changed files
with
73 additions
and
37 deletions
... | ... | @@ -12,4 +12,10 @@ public class CustomDataForExcelDTO { |
12 | 12 | List<List<String>> sheetHeads; |
13 | 13 | /** sheet的数据 */ |
14 | 14 | List<?> sheetData; |
15 | + | |
16 | + public CustomDataForExcelDTO(String sheetName, List<List<String>> sheetHeads, List<?> sheetData) { | |
17 | + this.sheetName = sheetName; | |
18 | + this.sheetHeads = sheetHeads; | |
19 | + this.sheetData = sheetData; | |
20 | + } | |
15 | 21 | } | ... | ... |
... | ... | @@ -48,8 +48,7 @@ import java.time.LocalDateTime; |
48 | 48 | import java.time.ZoneOffset; |
49 | 49 | import java.time.format.DateTimeFormatter; |
50 | 50 | import java.util.*; |
51 | -import java.util.concurrent.CompletableFuture; | |
52 | -import java.util.concurrent.ExecutionException; | |
51 | +import java.util.concurrent.atomic.AtomicInteger; | |
53 | 52 | import java.util.stream.Collectors; |
54 | 53 | |
55 | 54 | @Service |
... | ... | @@ -65,6 +64,7 @@ public class TkReportGenerateRecordServiceImpl |
65 | 64 | private final TimeseriesService tsService; |
66 | 65 | private final FileStorageService fileStorageService; |
67 | 66 | private final UserOrganizationMappingService userOrganizationMappingService; |
67 | + private volatile HashMap<String,List<CustomDataForExcelDTO>> excelReportMap = new HashMap<>(); | |
68 | 68 | |
69 | 69 | @Override |
70 | 70 | public TkPageData<ReportGenerateRecordDTO> page( |
... | ... | @@ -179,11 +179,14 @@ public class TkReportGenerateRecordServiceImpl |
179 | 179 | @Override |
180 | 180 | public void generateExcelUpdateReportRecord(ReportFormConfigDTO formConfigDTO,List<ExecuteAttributesDTO> executeAttributes, |
181 | 181 | String recordId){ |
182 | - List<CustomDataForExcelDTO> list = new ArrayList<>(); | |
183 | - for(ExecuteAttributesDTO dto:executeAttributes){ | |
184 | - Long startTs = formConfigDTO.getQueryCondition().getStartTs(); | |
185 | - Long endTs = formConfigDTO.getQueryCondition().getEndTs(); | |
186 | - //获取当前定时任务的执行时间,并计算新的开始时间、结束时间 | |
182 | + String executeReportKey = formConfigDTO.getTenantId() + "_" + formConfigDTO.getName() + "_" | |
183 | + + System.currentTimeMillis(); | |
184 | + //剩余执行次数 | |
185 | + AtomicInteger remainTimes = new AtomicInteger(executeAttributes.size()); | |
186 | + Long startTs = formConfigDTO.getQueryCondition().getStartTs(); | |
187 | + Long endTs = formConfigDTO.getQueryCondition().getEndTs(); | |
188 | + //如果是固定周期,均以执行定时任务的时间作为开始-结束时间 | |
189 | + if (formConfigDTO.getQueryCondition().getQueryMode() == FastIotConstants.MagicNumber.ZERO){ | |
187 | 190 | ReportGenerateRecordDTO recordDTO = |
188 | 191 | findReportGenerateRecordById(recordId, formConfigDTO.getTenantId()); |
189 | 192 | long differenceTs = endTs - startTs; |
... | ... | @@ -191,26 +194,18 @@ public class TkReportGenerateRecordServiceImpl |
191 | 194 | startTs = endTs - differenceTs; |
192 | 195 | formConfigDTO.getQueryCondition().setStartTs(startTs); |
193 | 196 | formConfigDTO.getQueryCondition().setEndTs(endTs); |
194 | - CustomDataForExcelDTO result = getTsKvValuesOrGenerateExcel(formConfigDTO, dto).join(); | |
195 | - list.add(result); | |
196 | 197 | } |
197 | - // 获取所有结果 | |
198 | - ObjectNode executeCondition = JacksonUtil.newObjectNode(); | |
199 | - QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); | |
200 | - executeCondition.replace( | |
201 | - FastIotConstants.CHART_EXECUTE_CONDITION, | |
202 | - JacksonUtil.convertValue(queryCondition, JsonNode.class)); | |
203 | - executeCondition.replace( | |
204 | - FastIotConstants.CHART_EXECUTE_ATTRIBUTES, | |
205 | - JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(), JsonNode.class)); | |
206 | - // 汇总所有数据,生成Excel并上传 | |
207 | - generateExcelAndUpload(list,formConfigDTO.getName(),recordId,formConfigDTO.getTenantId(), | |
208 | - executeCondition); | |
198 | + for(ExecuteAttributesDTO dto:executeAttributes){ | |
199 | + getTsKvValuesOrGenerateExcel(formConfigDTO, dto,executeReportKey,remainTimes,recordId); | |
200 | + } | |
209 | 201 | } |
210 | 202 | |
211 | - private CompletableFuture<CustomDataForExcelDTO> getTsKvValuesOrGenerateExcel( | |
203 | + private void getTsKvValuesOrGenerateExcel( | |
212 | 204 | ReportFormConfigDTO formConfigDTO, |
213 | - ExecuteAttributesDTO dto) { | |
205 | + ExecuteAttributesDTO dto, | |
206 | + String executeReportKey, | |
207 | + AtomicInteger remainTimes, | |
208 | + String recordId) { | |
214 | 209 | QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); |
215 | 210 | boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes(); |
216 | 211 | Long interval = queryCondition.getInterval(); |
... | ... | @@ -232,12 +227,10 @@ public class TkReportGenerateRecordServiceImpl |
232 | 227 | .collect(Collectors.toList()); |
233 | 228 | queryCondition.setStartTs(finalStartTs); |
234 | 229 | queryCondition.setEndTs(finalEndTs); |
235 | - CustomDataForExcelDTO result = new CustomDataForExcelDTO(); | |
236 | 230 | Futures.addCallback( |
237 | 231 | tsService.findAll(tenantId, entityId, queries), |
238 | - getTsKvListCallback(result, useStrictDataTypes, dto.getName(), keys), | |
232 | + getTsKvListCallback(useStrictDataTypes, dto.getName(), keys,executeReportKey,remainTimes,formConfigDTO,recordId), | |
239 | 233 | MoreExecutors.directExecutor()); |
240 | - return CompletableFuture.supplyAsync(()->result); | |
241 | 234 | } |
242 | 235 | |
243 | 236 | @Override |
... | ... | @@ -254,10 +247,13 @@ public class TkReportGenerateRecordServiceImpl |
254 | 247 | } |
255 | 248 | |
256 | 249 | private FutureCallback<List<TsKvEntry>> getTsKvListCallback( |
257 | - CustomDataForExcelDTO response, | |
258 | 250 | Boolean useStrictDataTypes, |
259 | 251 | String deviceName, |
260 | - List<String> keys) { | |
252 | + List<String> keys, | |
253 | + String executeReportKey, | |
254 | + AtomicInteger remainTimes, | |
255 | + ReportFormConfigDTO formConfigDTO, | |
256 | + String recordId) { | |
261 | 257 | return new FutureCallback<>() { |
262 | 258 | @Override |
263 | 259 | public void onSuccess(List<TsKvEntry> data) { |
... | ... | @@ -277,13 +273,44 @@ public class TkReportGenerateRecordServiceImpl |
277 | 273 | } |
278 | 274 | } |
279 | 275 | generateExcelHeadAndValues(result, deviceName, heads, values); |
280 | - response.setSheetName(deviceName); | |
281 | - response.setSheetHeads(heads); | |
282 | - response.setSheetData(values); | |
276 | + List<CustomDataForExcelDTO> list = excelReportMap.get(executeReportKey); | |
277 | + if(null == list){ | |
278 | + list = new ArrayList<>(); | |
279 | + } | |
280 | + list.add(new CustomDataForExcelDTO(deviceName,heads,values)); | |
281 | + excelReportMap.put(executeReportKey,list); | |
282 | + if(remainTimes.get() == 1){ | |
283 | + // 获取所有结果 | |
284 | + ObjectNode executeCondition = JacksonUtil.newObjectNode(); | |
285 | + QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); | |
286 | + executeCondition.replace( | |
287 | + FastIotConstants.CHART_EXECUTE_CONDITION, | |
288 | + JacksonUtil.convertValue(queryCondition, JsonNode.class)); | |
289 | + executeCondition.replace( | |
290 | + FastIotConstants.CHART_EXECUTE_ATTRIBUTES, | |
291 | + JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(), JsonNode.class)); | |
292 | + //移除数据 | |
293 | + excelReportMap.remove(executeReportKey); | |
294 | + // 汇总所有数据,生成Excel并上传 | |
295 | + generateExcelAndUpload(list,formConfigDTO.getName(),recordId,formConfigDTO.getTenantId(), | |
296 | + executeCondition,true,null); | |
297 | + }else{ | |
298 | + remainTimes.decrementAndGet(); | |
299 | + } | |
283 | 300 | } |
284 | 301 | |
285 | 302 | @Override |
286 | 303 | public void onFailure(@NotNull Throwable e) { |
304 | + ObjectNode executeCondition = JacksonUtil.newObjectNode(); | |
305 | + QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); | |
306 | + executeCondition.replace( | |
307 | + FastIotConstants.CHART_EXECUTE_CONDITION, | |
308 | + JacksonUtil.convertValue(queryCondition, JsonNode.class)); | |
309 | + executeCondition.replace( | |
310 | + FastIotConstants.CHART_EXECUTE_ATTRIBUTES, | |
311 | + JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(), JsonNode.class)); | |
312 | + generateExcelAndUpload(null,formConfigDTO.getName(),recordId,formConfigDTO.getTenantId(), | |
313 | + executeCondition,false,e.getMessage()); | |
287 | 314 | log.error("Failed to fetch historical data", e); |
288 | 315 | } |
289 | 316 | }; |
... | ... | @@ -339,15 +366,18 @@ public class TkReportGenerateRecordServiceImpl |
339 | 366 | String reportFormName, |
340 | 367 | String reportGenerateRecordId, |
341 | 368 | String tenantId, |
342 | - JsonNode executeCondition) { | |
369 | + JsonNode executeCondition, | |
370 | + boolean needUpload, | |
371 | + String errorMessage) { | |
343 | 372 | String response = null; |
344 | - String errorMessage = null; | |
345 | 373 | int status = StatusEnum.SUCCESS.getIndex(); |
346 | 374 | try { |
347 | - ByteArrayOutputStream byteArrayOutputStream = ExcelUtil.manySheetWrite(list); | |
348 | - String fileName = reportFormName + System.currentTimeMillis() + ".xlsx"; | |
349 | - InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); | |
350 | - response = fileStorageService.uploadFile(fileName, CONTENT_TYPE, inputStream); | |
375 | + if(needUpload){ | |
376 | + ByteArrayOutputStream byteArrayOutputStream = ExcelUtil.manySheetWrite(list); | |
377 | + String fileName = reportFormName + System.currentTimeMillis() + ".xlsx"; | |
378 | + InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); | |
379 | + response = fileStorageService.uploadFile(fileName, CONTENT_TYPE, inputStream); | |
380 | + } | |
351 | 381 | } catch (Exception e) { |
352 | 382 | errorMessage = e.getLocalizedMessage(); |
353 | 383 | } | ... | ... |