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,4 +12,10 @@ public class CustomDataForExcelDTO { | ||
12 | List<List<String>> sheetHeads; | 12 | List<List<String>> sheetHeads; |
13 | /** sheet的数据 */ | 13 | /** sheet的数据 */ |
14 | List<?> sheetData; | 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,8 +48,7 @@ import java.time.LocalDateTime; | ||
48 | import java.time.ZoneOffset; | 48 | import java.time.ZoneOffset; |
49 | import java.time.format.DateTimeFormatter; | 49 | import java.time.format.DateTimeFormatter; |
50 | import java.util.*; | 50 | import java.util.*; |
51 | -import java.util.concurrent.CompletableFuture; | ||
52 | -import java.util.concurrent.ExecutionException; | 51 | +import java.util.concurrent.atomic.AtomicInteger; |
53 | import java.util.stream.Collectors; | 52 | import java.util.stream.Collectors; |
54 | 53 | ||
55 | @Service | 54 | @Service |
@@ -65,6 +64,7 @@ public class TkReportGenerateRecordServiceImpl | @@ -65,6 +64,7 @@ public class TkReportGenerateRecordServiceImpl | ||
65 | private final TimeseriesService tsService; | 64 | private final TimeseriesService tsService; |
66 | private final FileStorageService fileStorageService; | 65 | private final FileStorageService fileStorageService; |
67 | private final UserOrganizationMappingService userOrganizationMappingService; | 66 | private final UserOrganizationMappingService userOrganizationMappingService; |
67 | + private volatile HashMap<String,List<CustomDataForExcelDTO>> excelReportMap = new HashMap<>(); | ||
68 | 68 | ||
69 | @Override | 69 | @Override |
70 | public TkPageData<ReportGenerateRecordDTO> page( | 70 | public TkPageData<ReportGenerateRecordDTO> page( |
@@ -179,11 +179,14 @@ public class TkReportGenerateRecordServiceImpl | @@ -179,11 +179,14 @@ public class TkReportGenerateRecordServiceImpl | ||
179 | @Override | 179 | @Override |
180 | public void generateExcelUpdateReportRecord(ReportFormConfigDTO formConfigDTO,List<ExecuteAttributesDTO> executeAttributes, | 180 | public void generateExcelUpdateReportRecord(ReportFormConfigDTO formConfigDTO,List<ExecuteAttributesDTO> executeAttributes, |
181 | String recordId){ | 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 | ReportGenerateRecordDTO recordDTO = | 190 | ReportGenerateRecordDTO recordDTO = |
188 | findReportGenerateRecordById(recordId, formConfigDTO.getTenantId()); | 191 | findReportGenerateRecordById(recordId, formConfigDTO.getTenantId()); |
189 | long differenceTs = endTs - startTs; | 192 | long differenceTs = endTs - startTs; |
@@ -191,26 +194,18 @@ public class TkReportGenerateRecordServiceImpl | @@ -191,26 +194,18 @@ public class TkReportGenerateRecordServiceImpl | ||
191 | startTs = endTs - differenceTs; | 194 | startTs = endTs - differenceTs; |
192 | formConfigDTO.getQueryCondition().setStartTs(startTs); | 195 | formConfigDTO.getQueryCondition().setStartTs(startTs); |
193 | formConfigDTO.getQueryCondition().setEndTs(endTs); | 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 | ReportFormConfigDTO formConfigDTO, | 204 | ReportFormConfigDTO formConfigDTO, |
213 | - ExecuteAttributesDTO dto) { | 205 | + ExecuteAttributesDTO dto, |
206 | + String executeReportKey, | ||
207 | + AtomicInteger remainTimes, | ||
208 | + String recordId) { | ||
214 | QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); | 209 | QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); |
215 | boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes(); | 210 | boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes(); |
216 | Long interval = queryCondition.getInterval(); | 211 | Long interval = queryCondition.getInterval(); |
@@ -232,12 +227,10 @@ public class TkReportGenerateRecordServiceImpl | @@ -232,12 +227,10 @@ public class TkReportGenerateRecordServiceImpl | ||
232 | .collect(Collectors.toList()); | 227 | .collect(Collectors.toList()); |
233 | queryCondition.setStartTs(finalStartTs); | 228 | queryCondition.setStartTs(finalStartTs); |
234 | queryCondition.setEndTs(finalEndTs); | 229 | queryCondition.setEndTs(finalEndTs); |
235 | - CustomDataForExcelDTO result = new CustomDataForExcelDTO(); | ||
236 | Futures.addCallback( | 230 | Futures.addCallback( |
237 | tsService.findAll(tenantId, entityId, queries), | 231 | tsService.findAll(tenantId, entityId, queries), |
238 | - getTsKvListCallback(result, useStrictDataTypes, dto.getName(), keys), | 232 | + getTsKvListCallback(useStrictDataTypes, dto.getName(), keys,executeReportKey,remainTimes,formConfigDTO,recordId), |
239 | MoreExecutors.directExecutor()); | 233 | MoreExecutors.directExecutor()); |
240 | - return CompletableFuture.supplyAsync(()->result); | ||
241 | } | 234 | } |
242 | 235 | ||
243 | @Override | 236 | @Override |
@@ -254,10 +247,13 @@ public class TkReportGenerateRecordServiceImpl | @@ -254,10 +247,13 @@ public class TkReportGenerateRecordServiceImpl | ||
254 | } | 247 | } |
255 | 248 | ||
256 | private FutureCallback<List<TsKvEntry>> getTsKvListCallback( | 249 | private FutureCallback<List<TsKvEntry>> getTsKvListCallback( |
257 | - CustomDataForExcelDTO response, | ||
258 | Boolean useStrictDataTypes, | 250 | Boolean useStrictDataTypes, |
259 | String deviceName, | 251 | String deviceName, |
260 | - List<String> keys) { | 252 | + List<String> keys, |
253 | + String executeReportKey, | ||
254 | + AtomicInteger remainTimes, | ||
255 | + ReportFormConfigDTO formConfigDTO, | ||
256 | + String recordId) { | ||
261 | return new FutureCallback<>() { | 257 | return new FutureCallback<>() { |
262 | @Override | 258 | @Override |
263 | public void onSuccess(List<TsKvEntry> data) { | 259 | public void onSuccess(List<TsKvEntry> data) { |
@@ -277,13 +273,44 @@ public class TkReportGenerateRecordServiceImpl | @@ -277,13 +273,44 @@ public class TkReportGenerateRecordServiceImpl | ||
277 | } | 273 | } |
278 | } | 274 | } |
279 | generateExcelHeadAndValues(result, deviceName, heads, values); | 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 | @Override | 302 | @Override |
286 | public void onFailure(@NotNull Throwable e) { | 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 | log.error("Failed to fetch historical data", e); | 314 | log.error("Failed to fetch historical data", e); |
288 | } | 315 | } |
289 | }; | 316 | }; |
@@ -339,15 +366,18 @@ public class TkReportGenerateRecordServiceImpl | @@ -339,15 +366,18 @@ public class TkReportGenerateRecordServiceImpl | ||
339 | String reportFormName, | 366 | String reportFormName, |
340 | String reportGenerateRecordId, | 367 | String reportGenerateRecordId, |
341 | String tenantId, | 368 | String tenantId, |
342 | - JsonNode executeCondition) { | 369 | + JsonNode executeCondition, |
370 | + boolean needUpload, | ||
371 | + String errorMessage) { | ||
343 | String response = null; | 372 | String response = null; |
344 | - String errorMessage = null; | ||
345 | int status = StatusEnum.SUCCESS.getIndex(); | 373 | int status = StatusEnum.SUCCESS.getIndex(); |
346 | try { | 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 | } catch (Exception e) { | 381 | } catch (Exception e) { |
352 | errorMessage = e.getLocalizedMessage(); | 382 | errorMessage = e.getLocalizedMessage(); |
353 | } | 383 | } |