Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -16,6 +16,12 @@ public class ExportExcelFormat {
|
||||
@NotNull(message = "excel表头不能为空")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "表头对应的数据属性类型")
|
||||
private String locateType;
|
||||
|
||||
@Schema(description = "表头对应的数据属性类型数据值")
|
||||
private String locateValue;
|
||||
|
||||
@Schema(description = "属性值对应的字典编码")
|
||||
private String dictCode;
|
||||
|
||||
@@ -31,6 +37,8 @@ public class ExportExcelFormat {
|
||||
ExportExcelFormat format = new ExportExcelFormat();
|
||||
format.key = key;
|
||||
format.title = title;
|
||||
format.locateType = locateType;
|
||||
format.locateValue = locateValue;
|
||||
format.dictCode = dictCode;
|
||||
format.dictData = dictData;
|
||||
return format;
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class FlowNodeDto {
|
||||
@@ -37,6 +38,12 @@ public class FlowNodeDto {
|
||||
@Schema(description = "节点状态:finished/active/pending")
|
||||
private String nodeStatus;
|
||||
|
||||
@Schema(description = "流程实例唯一ID")
|
||||
private String processInstanceId;
|
||||
|
||||
@Schema(description = "用户输入参数")
|
||||
private Map<String, Object> userParams;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private Long creator;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.sdm.common.entity.ExportExcelFormat;
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
@@ -242,8 +243,17 @@ public class ExcelUtil {
|
||||
* @param exportExcelFormats
|
||||
* @return
|
||||
*/
|
||||
private static List<HeadVO> getExcelHeader(List<ExportExcelFormat> exportExcelFormats)
|
||||
private static List<HeadVO> getExcelHeader(List<ExportExcelFormat> exportExcelFormats,List<ExportExcelFormat> filterFormats)
|
||||
{
|
||||
Map<String,ExportExcelFormat> showFormatMap = new HashMap<>();
|
||||
if(filterFormats!=null && !filterFormats.isEmpty()) {
|
||||
for (ExportExcelFormat exportExcelFormat : filterFormats) {
|
||||
String key = exportExcelFormat.getKey();
|
||||
if (showFormatMap.get(key) == null) {
|
||||
showFormatMap.put(key, exportExcelFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<HeadVO> excelHeader = new ArrayList<>();
|
||||
for(ExportExcelFormat exportExcelFormat : exportExcelFormats)
|
||||
{
|
||||
@@ -253,6 +263,10 @@ public class ExcelUtil {
|
||||
excelHeaderInfo.setTitle(exportExcelFormat.getTitle());
|
||||
excelHeaderInfo.setKeyType(exportExcelFormat.getKey());
|
||||
headVO.setExcelHeaderInfo(excelHeaderInfo);
|
||||
if(!showFormatMap.isEmpty() && !showFormatMap.containsKey(exportExcelFormat.getKey()))
|
||||
{
|
||||
excelHeaderInfo.setBShow(false);
|
||||
}
|
||||
excelHeader.add(headVO);
|
||||
}
|
||||
return excelHeader;
|
||||
@@ -268,7 +282,7 @@ public class ExcelUtil {
|
||||
ExcelSheet excelSheet = new ExcelSheet();
|
||||
excelSheet.setSheetName("export sheet1");
|
||||
//获取excel表头
|
||||
List<HeadVO> excelHeader = getExcelHeader(exportExcelFormats);
|
||||
List<HeadVO> excelHeader = getExcelHeader(exportExcelFormats,null);
|
||||
excelSheet.setHeads(excelHeader);
|
||||
|
||||
//获取excel表行数据
|
||||
@@ -363,7 +377,6 @@ public class ExcelUtil {
|
||||
{
|
||||
parent.addchildren(paraseData);
|
||||
}
|
||||
//paraseData.increaseLine();
|
||||
}
|
||||
String value = jsonObject.getString(key);
|
||||
JSONObject dictObj = format.getDictData();
|
||||
@@ -487,17 +500,56 @@ public class ExcelUtil {
|
||||
paraseData.lastRow = rowIndex+paraseData.lines-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表头第一个属性有效性检查
|
||||
* @param topObject
|
||||
* @param exportExcelFormats
|
||||
*/
|
||||
private static int filterExcelHeader(JSONObject topObject,List<ExportExcelFormat> exportExcelFormats)
|
||||
{
|
||||
Iterator<ExportExcelFormat> iterator = exportExcelFormats.iterator();
|
||||
int filterCount = 0;
|
||||
while (iterator.hasNext()) {
|
||||
ExportExcelFormat format = iterator.next();
|
||||
String locateType = format.getLocateType();
|
||||
String locateValue = format.getLocateValue();
|
||||
if(locateType!=null && !locateType.isEmpty())
|
||||
{
|
||||
if(!topObject.containsKey(locateType))
|
||||
{
|
||||
iterator.remove();
|
||||
filterCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!topObject.get(locateType).equals(locateValue)) {
|
||||
iterator.remove();
|
||||
filterCount++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return filterCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出有合并单元格excel
|
||||
* @param dataArray
|
||||
* @param exportExcelFormats
|
||||
* @param response
|
||||
*/
|
||||
public static void exportExcelWithMerge(JSONArray dataArray,List<ExportExcelFormat> exportExcelFormats,HttpServletResponse response)
|
||||
public static void exportExcelWithMerge(JSONArray dataArray,List<ExportExcelFormat> exportExcelFormats,List<ExportExcelFormat> filterFormat,HttpServletResponse response)
|
||||
{
|
||||
ExcelSheet excelSheet = new ExcelSheet();
|
||||
excelSheet.setSheetName("export sheet1");
|
||||
List<HeadVO> excelHeader = getExcelHeader(exportExcelFormats);
|
||||
List<HeadVO> excelHeader = getExcelHeader(exportExcelFormats,filterFormat);
|
||||
excelSheet.setHeads(excelHeader);
|
||||
Map<Integer,List<ExcelCellValue>> paraseDataMap = new HashMap<>();
|
||||
int rowNum = 1;
|
||||
|
||||
@@ -28,6 +28,8 @@ public class MinioConfig {
|
||||
// allocateDirect 单次缓冲的数据
|
||||
private int directMemory;
|
||||
|
||||
private String lifecycleConfig;
|
||||
|
||||
// 初始化超级管理员客户端(用于 admin 操作:桶、用户、策略)
|
||||
@Bean
|
||||
public MinioAdminClient minioAdminClient() {
|
||||
|
||||
@@ -21,10 +21,12 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@@ -428,11 +430,29 @@ public class DataFileController implements IDataFeignClient {
|
||||
IDataFileService.downloadFileToLocal(fileId,path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出知识库
|
||||
* @param knowledgeExportExcelFormat
|
||||
* @param httpservletResponse
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/exportKnowledgeList")
|
||||
@Operation(summary = "导出知识库", description = "导出知识库")
|
||||
public SdmResponse exportKnowledgeList(@RequestBody KnowledgeExportExcelFormat knowledgeExportExcelFormat , HttpServletResponse httpservletResponse) {
|
||||
return IDataFileService.exportKnowledgeList(knowledgeExportExcelFormat, httpservletResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* only office 回调
|
||||
* @param callbackData
|
||||
* @return
|
||||
*/
|
||||
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})
|
||||
@PostMapping("/onlyOfficeCallback")
|
||||
@Operation(summary = "only office 回调", description = "only office 回调")
|
||||
public ResponseEntity onlyOfficeCallback(@RequestBody CallbackData callbackData) {
|
||||
return IDataFileService.onlyOfficeCallback(callbackData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
72
data/src/main/java/com/sdm/data/model/req/CallbackData.java
Normal file
72
data/src/main/java/com/sdm/data/model/req/CallbackData.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.sdm.data.model.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CallbackData {
|
||||
/**
|
||||
* 用户与文档的交互状态。0:用户断开与文档共同编辑的连接;1:新用户连接到文档共同编辑;2:用户单击强制保存按钮
|
||||
*/
|
||||
// @IsArray()
|
||||
// actions?:IActions[] =null;
|
||||
|
||||
/**
|
||||
* 字段已在 4.2 后版本废弃,请使用 history 代替
|
||||
*/
|
||||
Object changeshistory;
|
||||
|
||||
/**
|
||||
* 文档变更的历史记录,仅当 status 等于 2 或者 3 时该字段才有值。其中的 serverVersion 字段也是 refreshHistory 方法的入参
|
||||
*/
|
||||
Object history;
|
||||
|
||||
/**
|
||||
* 文档编辑的元数据信息,用来跟踪显示文档更改记录,仅当 status 等于 2 或者 2 时该字段才有值。该字段也是 setHistoryData(显示与特定文档版本对应的更改,类似 Git 历史记录)方法的入参
|
||||
*/
|
||||
String changesurl;
|
||||
|
||||
/**
|
||||
* url 字段下载的文档扩展名,文件类型默认为 OOXML 格式,如果启用了 assemblyFormatAsOrigin(https://api.onlyoffice.com/editors/save#assemblyFormatAsOrigin) 服务器设置则文件以原始格式保存
|
||||
*/
|
||||
String filetype;
|
||||
|
||||
/**
|
||||
* 文档强制保存类型。0:对命令服务(https://api.onlyoffice.com/editors/command/forcesave)执行强制保存;1:每次保存完成时都会执行强制保存请求,仅设置 forcesave 等于 true 时生效;2:强制保存请求由计时器使用服务器中的设置执行。该字段仅 status 等于 7 或者 7 时才有值
|
||||
*/
|
||||
Integer forcesavetype;
|
||||
|
||||
/**
|
||||
* 文档标识符,类似 id,在 Onlyoffice 服务内部唯一
|
||||
*/
|
||||
String key;
|
||||
|
||||
/**
|
||||
* 文档状态。1:文档编辑中;2:文档已准备好保存;3:文档保存出错;4:文档没有变化无需保存;6:正在编辑文档,但保存了当前文档状态;7:强制保存文档出错
|
||||
*/
|
||||
Integer status;
|
||||
|
||||
/**
|
||||
* 已编辑文档的链接,可以通过它下载到最新的文档,仅当 status 等于 2、3、6 或 7 时该字段才有值
|
||||
*/
|
||||
String url;
|
||||
|
||||
/**
|
||||
* 自定义参数,对应指令服务的 userdata 字段
|
||||
*/
|
||||
Object userdata;
|
||||
|
||||
/**
|
||||
* 打开文档进行编辑的用户标识列表,当文档被修改时,该字段将返回最后编辑文档的用户标识符,当 status 字段等于 2 或者 6 时有值
|
||||
*/
|
||||
String[] users;
|
||||
|
||||
/**
|
||||
* 最近保存时间
|
||||
*/
|
||||
String lastsave;
|
||||
|
||||
/**
|
||||
* 加密令牌
|
||||
*/
|
||||
String token;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
|
||||
import com.sdm.data.model.req.*;
|
||||
import com.sdm.data.model.resp.KKFileViewURLFromMinioResp;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -331,4 +332,6 @@ public interface IDataFileService {
|
||||
*/
|
||||
SdmResponse exportKnowledgeList(KnowledgeExportExcelFormat knowledgeExportExcelFormat, HttpServletResponse httpservletResponse);
|
||||
|
||||
ResponseEntity<Object> onlyOfficeCallback(CallbackData callbackData);
|
||||
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public interface IMinioService {
|
||||
String getMinioPresignedUrl(String objectKey);
|
||||
String getMinioPresignedUrl(String objectKey, String bucketName);
|
||||
|
||||
Boolean chunkUpload(String bucketName, MultipartFile file, String fileName);
|
||||
Boolean chunkUpload(String bucketName, MultipartFile file, String fileName,Map<String, String> tags);
|
||||
|
||||
Boolean merge(String tempBucketName,String tempFilePath,String mergeBucketName,String fileName);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -252,7 +253,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
Objects.equals(req.getChunk(),NumberConstants.ONE)){
|
||||
// 第一步业务数据入表已经规定好这个文件的路径了
|
||||
String finalFileName = req.getObjectKey();
|
||||
Boolean b = minioService.chunkUpload(chunkBucket, req.getFile(), finalFileName);
|
||||
Boolean b = minioService.chunkUpload(chunkBucket, req.getFile(), finalFileName,null);
|
||||
if(!b){
|
||||
return buildFailedResponse(resp,"单一文件上传失败",req);
|
||||
}
|
||||
@@ -264,7 +265,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
// 1. 保存当前分片到临时目录 1 2 3 4 ....temp
|
||||
String chunkFileName =tempDirPath+req.getChunk()+ PermConstants.CHUNK_TEMPFILE_SUFFIX;
|
||||
// 片文件上传到minio
|
||||
Boolean b = minioService.chunkUpload(chunkBucket, req.getFile(), chunkFileName);
|
||||
Map<String, String> tags = new HashMap<>();
|
||||
tags.put("auto-expire", "1d");
|
||||
Boolean b = minioService.chunkUpload(chunkBucket, req.getFile(), chunkFileName,tags);
|
||||
if(!b){
|
||||
deleteTempFileAfterFailed(tempDirPath,chunkBucket);
|
||||
return buildFailedResponse(resp,"chunkUpload第"+req.getChunk()+"次失败",req);
|
||||
@@ -2410,4 +2413,64 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Object> onlyOfficeCallback(CallbackData callbackData) {
|
||||
log.info("调用回调接口,userdata:{}",callbackData.getKey());
|
||||
//状态监听
|
||||
//参见https://api.onlyoffice.com/editors/callback
|
||||
Integer status = callbackData.getStatus();
|
||||
switch (status) {
|
||||
case 1: {
|
||||
//document is being edited 文档已经被编辑
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
//document is ready for saving,文档已准备好保存
|
||||
System.out.println("document is ready for saving");
|
||||
String url = callbackData.getUrl();
|
||||
log.info("回调地址为:{}",url);
|
||||
try {
|
||||
// saveFile(url); //保存文件
|
||||
System.out.println(callbackData);
|
||||
} catch (Exception e) {
|
||||
System.out.println("保存文件异常");
|
||||
}
|
||||
System.out.println("save success.");
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
//document saving error has occurred,保存出错
|
||||
System.out.println("document saving error has occurred,保存出错");
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
//document is closed with no changes,未保存退出
|
||||
System.out.println("document is closed with no changes,未保存退出");
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
//document is being edited, but the current document state is saved,编辑保存
|
||||
String url = callbackData.getUrl();
|
||||
try {
|
||||
// saveFile(url); //保存文件
|
||||
System.out.println(callbackData);
|
||||
} catch (Exception e) {
|
||||
System.out.println("保存文件异常");
|
||||
}
|
||||
System.out.println("save success.");
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
//error has occurred while force saving the document. 强制保存文档出错
|
||||
System.out.println("error has occurred while force saving the document. 强制保存文档出错");
|
||||
}
|
||||
default: {
|
||||
|
||||
}
|
||||
}
|
||||
// 返回响应
|
||||
return ResponseEntity.<Object>ok(Collections.singletonMap("error", 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -1609,5 +1610,10 @@ public class SystemFileIDataFileServiceImpl implements IDataFileService {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Object> onlyOfficeCallback(CallbackData callbackData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sdm.data.service.minio;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.sdm.common.entity.constants.NumberConstants;
|
||||
import com.sdm.common.log.CoreLogger;
|
||||
import com.sdm.data.config.MinioConfig;
|
||||
@@ -8,9 +9,7 @@ import com.sdm.data.service.IMinioService;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.*;
|
||||
import io.minio.http.Method;
|
||||
import io.minio.messages.DeleteError;
|
||||
import io.minio.messages.DeleteObject;
|
||||
import io.minio.messages.Item;
|
||||
import io.minio.messages.*;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -37,6 +36,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -64,15 +64,18 @@ public class MinioService implements IMinioService {
|
||||
} catch (Exception e) {
|
||||
log.error("桶{}初始化失败", minioConfig.getSpdmBucket(), e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
createBucketIfNotExists(minioConfig.getSecretBusinessBucket());
|
||||
log.info("桶{}初始化完成", minioConfig.getSecretBusinessBucket());
|
||||
} catch (Exception e) {
|
||||
log.error("桶{}初始化失败", minioConfig.getSecretBusinessBucket(), e);
|
||||
}
|
||||
createBucketLifecycle(minioConfig.getSpdmBucket(),minioConfig.getLifecycleConfig());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getBucketName() {
|
||||
return minioConfig.getSpdmBucket();
|
||||
}
|
||||
@@ -104,7 +107,7 @@ public class MinioService implements IMinioService {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建目录(默认使用spdmBucket)
|
||||
*
|
||||
@@ -175,7 +178,7 @@ public class MinioService implements IMinioService {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 递归删除指定目录下的所有对象(默认使用spdmBucket)。
|
||||
*
|
||||
@@ -303,7 +306,7 @@ public class MinioService implements IMinioService {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重命名MinIO中的文件(默认使用spdmBucket)
|
||||
*
|
||||
@@ -391,7 +394,7 @@ public class MinioService implements IMinioService {
|
||||
public InputStream getMinioInputStream(String objectName) {
|
||||
return getMinioInputStream(objectName, minioConfig.getSpdmBucket());
|
||||
}
|
||||
|
||||
|
||||
public InputStream getMinioInputStream(String objectName, String bucketName) {
|
||||
try {
|
||||
return minioClient.getObject(
|
||||
@@ -425,7 +428,7 @@ public class MinioService implements IMinioService {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据标签查询文件(默认使用spdmBucket)
|
||||
*/
|
||||
@@ -472,6 +475,77 @@ public class MinioService implements IMinioService {
|
||||
}
|
||||
}
|
||||
|
||||
private void createBucketLifecycle(String bucketName, String configJson) {
|
||||
// configJson 示例: {"tag-based-expire-3d":"3d","tag-based-expire-7d":"7d"}
|
||||
Map<String, String> targetRuleMap = JSONObject.parseObject(configJson, Map.class);
|
||||
try {
|
||||
LifecycleConfiguration existingConfig = null;
|
||||
try {
|
||||
existingConfig = minioClient.getBucketLifecycle(
|
||||
GetBucketLifecycleArgs.builder().bucket(bucketName).build()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
existingConfig = null;
|
||||
}
|
||||
|
||||
List<LifecycleRule> existingRules = existingConfig == null ? new ArrayList<>() : existingConfig.rules();
|
||||
Map<String, LifecycleRule> retained = existingRules.stream()
|
||||
.filter(rule -> rule.id() != null && targetRuleMap.containsKey(rule.id()))
|
||||
.collect(Collectors.toMap(LifecycleRule::id, r -> r));
|
||||
List<LifecycleRule> finalRules = new ArrayList<>(retained.values());
|
||||
for (Map.Entry<String, String> entry : targetRuleMap.entrySet()) {
|
||||
String ruleId = entry.getKey();
|
||||
String v = entry.getValue();
|
||||
if (v == null) continue;
|
||||
String daysStr = v.replace("d", "").trim();
|
||||
int expireDays;
|
||||
try {
|
||||
expireDays = Integer.parseInt(daysStr);
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new IllegalArgumentException("invalid expire days for rule " + ruleId + ": " + v);
|
||||
}
|
||||
if (expireDays <= 0) {
|
||||
throw new IllegalArgumentException("expireDays must be > 0 for rule " + ruleId);
|
||||
}
|
||||
if (retained.containsKey(ruleId)) {
|
||||
continue;
|
||||
}
|
||||
// days 使用 Integer
|
||||
Expiration expiration = new Expiration(
|
||||
(ResponseDate) null,
|
||||
Integer.valueOf(expireDays),
|
||||
null
|
||||
);
|
||||
// 构建 Filter(标签匹配)
|
||||
RuleFilter filter = new RuleFilter(new Tag("auto-expire", v));
|
||||
LifecycleRule rule = new LifecycleRule(
|
||||
Status.ENABLED, // status
|
||||
null, // AbortIncompleteMultipartUpload (null)
|
||||
expiration, // Expiration (非空,满足至少一个 action 的要求)
|
||||
filter, // Filter (不得为 null)
|
||||
ruleId, // ID
|
||||
null, // NoncurrentVersionExpiration
|
||||
null, // NoncurrentVersionTransition
|
||||
null // Transition
|
||||
);
|
||||
finalRules.add(rule);
|
||||
}
|
||||
//(覆盖)规则
|
||||
LifecycleConfiguration newConfig = new LifecycleConfiguration(finalRules);
|
||||
minioClient.setBucketLifecycle(
|
||||
SetBucketLifecycleArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.config(newConfig)
|
||||
.build()
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
CoreLogger.error("设置 MinIO 生命周期失败:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getMinioPresignedUrl(String objectKey) {
|
||||
return getMinioPresignedUrl(objectKey, minioConfig.getSpdmBucket());
|
||||
@@ -500,7 +574,7 @@ public class MinioService implements IMinioService {
|
||||
* @date 2023/5/21 13:06
|
||||
*/
|
||||
@Override
|
||||
public Boolean chunkUpload(String bucketName, MultipartFile file, String fileName) {
|
||||
public Boolean chunkUpload(String bucketName, MultipartFile file, String fileName,Map<String, String> tags) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = file.getInputStream();
|
||||
|
||||
@@ -114,4 +114,5 @@ minio:
|
||||
secure: false
|
||||
secret-business-bucket: secretbusiness # 存放保密业务代码、脚本的桶(仅超级管理员访问)
|
||||
spdm-bucket: spdm # 普通业务数据桶(分配给用户读写权限)
|
||||
directMemory: 16384 # 16kb
|
||||
directMemory: 16384 # 16kb
|
||||
lifecycleConfig: '{"auto-expire-1d":"1d"}'
|
||||
@@ -31,4 +31,6 @@ public interface SimulationDemandMapper extends BaseMapper<SimulationDemand> {
|
||||
List<SpdmDemandMemberVo> getMemberList(@Param("demandIdList") List<String> demandIdList, @Param("memberType") Integer memberType);
|
||||
|
||||
SpdmDemandVo getDemandByName(@Param("tenantId") Long tenantId,@Param("demandName") String demandName);
|
||||
|
||||
List<SpdmDemandExtraVo> getDemandExtraList(@Param("demandIdList") List<String> demandIdList);
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ public class SpdmDemandListReq {
|
||||
*/
|
||||
private String achieveStatus;
|
||||
|
||||
private String projectName;
|
||||
private String projectId;
|
||||
|
||||
private String phaseName;
|
||||
private String phaseId;
|
||||
|
||||
private String disciplineName;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.sdm.project.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.sdm.project.model.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.sdm.common.entity.pojo.BaseEntity;
|
||||
import com.sdm.common.entity.resp.system.CIDUserResp;
|
||||
import com.sdm.project.model.req.SpdmDemandExtraReq;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SpdmDemandExtraVo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 关联的需求id
|
||||
*/
|
||||
private String demandId;
|
||||
|
||||
/**
|
||||
* 需求拓展属性编码
|
||||
*/
|
||||
private String propertyName;
|
||||
|
||||
/**
|
||||
* 需求拓展属性值
|
||||
*/
|
||||
private String propertyValue;
|
||||
|
||||
|
||||
/**
|
||||
* 需求拓展属性值类型
|
||||
*/
|
||||
private String valueType;
|
||||
|
||||
/**
|
||||
* 需求拓展属性class
|
||||
*/
|
||||
private String propertyClass;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class SpdmDemandVo extends BaseEntity {
|
||||
/**
|
||||
* 预留拓展属性
|
||||
*/
|
||||
private List<SpdmDemandExtraReq> extraList;
|
||||
private List<SpdmDemandExtraVo> extraList;
|
||||
|
||||
/**
|
||||
* 项目名称
|
||||
|
||||
@@ -439,7 +439,12 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
userMap = userList.stream().collect(Collectors.groupingBy(CIDUserResp::getUserId));
|
||||
}
|
||||
}
|
||||
|
||||
List<String> demandIdList = demandList.stream().map(SpdmDemandVo::getUuid).toList();
|
||||
List<SpdmDemandExtraVo> demandExtraList = mapper.getDemandExtraList(demandIdList);
|
||||
Map<String, List<SpdmDemandExtraVo>> demandExtraMap = Map.of();
|
||||
if (CollectionUtils.isNotEmpty(demandExtraList)) {
|
||||
demandExtraMap = demandExtraList.stream().collect(Collectors.groupingBy(SpdmDemandExtraVo::getDemandId));
|
||||
}
|
||||
for (SpdmDemandVo spdmDemandVo : demandList) {
|
||||
eachTaskList = taskMap.get(spdmDemandVo.getUuid());
|
||||
spdmDemandVo.setProgress(CollectionUtils.isEmpty(eachTaskList) ? 0 : eachTaskList.stream().mapToInt(SpdmTaskVo::getProgress).sum() / eachTaskList.size());
|
||||
@@ -467,6 +472,7 @@ public class DemandServiceImpl extends BaseService implements IDemandService {
|
||||
}
|
||||
}
|
||||
spdmDemandVo.setEMemberList(spdmEUserVoList);
|
||||
spdmDemandVo.setExtraList(demandExtraMap.get(spdmDemandVo.getUuid()));
|
||||
}
|
||||
jsonObject.put("data", demandList);
|
||||
return SdmResponse.success(jsonObject);
|
||||
|
||||
@@ -91,6 +91,9 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
|
||||
|
||||
String firstNodeTag;
|
||||
|
||||
List<String> nodeTypeList = Arrays.asList(NodeTypeEnum.MACHINE.getValue(),NodeTypeEnum.WORKSPACE.getValue(),NodeTypeEnum.DISCIPLINE.getValue(),NodeTypeEnum.TASK.getValue(),NodeTypeEnum.PERFORMANCE.getValue());
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public SdmResponse add(JSONObject jsonObject) {
|
||||
@@ -1974,16 +1977,111 @@ public class ProjectServiceImpl extends BaseService implements IProjectService {
|
||||
List<ExportExcelFormat> exportExcelFormats = taskTreeExportExcelFormat.getExcelHeaders();
|
||||
SdmResponse taskRespond = getTaskTree(req);
|
||||
SdmResponse response = new SdmResponse();
|
||||
List<ProjectNodePo> allTopProjectNodeList = new ArrayList<>();
|
||||
if(taskRespond.isSuccess()) {
|
||||
List<ProjectNodePo> realTopProjectNodeList = (List<ProjectNodePo>) taskRespond.getData();
|
||||
if (CollectionUtils.isEmpty(realTopProjectNodeList)) {
|
||||
return response;
|
||||
}
|
||||
ExcelUtil.exportExcelWithMerge(JSONArray.from(taskRespond.getData()),exportExcelFormats,httpServletResponse);
|
||||
// 补充空节点,暂时定死顺序:机台——》工位——》学科——》任务——》指标
|
||||
for (ProjectNodePo projectNodePo : realTopProjectNodeList) {
|
||||
if (NodeTypeEnum.MACHINE.getValue().equals(projectNodePo.getNodeType())) {
|
||||
fillChildrenNode(projectNodePo);
|
||||
allTopProjectNodeList.add(projectNodePo);
|
||||
continue;
|
||||
}
|
||||
// 先补全前面类型节点
|
||||
ProjectNodePo machineNode = new ProjectNodePo();
|
||||
if (NodeTypeEnum.WORKSPACE.getValue().equals(projectNodePo.getNodeType())) {
|
||||
machineNode.setNodeName(" ");
|
||||
machineNode.setNodeCode(" ");
|
||||
machineNode.setNodeType(NodeTypeEnum.MACHINE.getValue());
|
||||
machineNode.setChildren(Collections.singletonList(projectNodePo));
|
||||
fillChildrenNode(machineNode);
|
||||
}else if (NodeTypeEnum.DISCIPLINE.getValue().equals(projectNodePo.getNodeType())) {
|
||||
machineNode.setNodeName(" ");
|
||||
machineNode.setNodeCode(" ");
|
||||
machineNode.setNodeType(NodeTypeEnum.MACHINE.getValue());
|
||||
NodeAllBase workspaceNode = new ProjectNodePo();
|
||||
workspaceNode.setNodeName(" ");
|
||||
workspaceNode.setNodeCode(" ");
|
||||
workspaceNode.setNodeType(NodeTypeEnum.WORKSPACE.getValue());
|
||||
workspaceNode.setChildren(Collections.singletonList(projectNodePo));
|
||||
machineNode.setChildren(Collections.singletonList(workspaceNode));
|
||||
fillChildrenNode(machineNode);
|
||||
}else if (NodeTypeEnum.TASK.getValue().equals(projectNodePo.getNodeType())) {
|
||||
machineNode.setNodeName(" ");
|
||||
machineNode.setNodeCode(" ");
|
||||
machineNode.setNodeType(NodeTypeEnum.MACHINE.getValue());
|
||||
ProjectNodePo workspaceNode = new ProjectNodePo();
|
||||
workspaceNode.setNodeName(" ");
|
||||
workspaceNode.setNodeCode(" ");
|
||||
workspaceNode.setNodeType(NodeTypeEnum.WORKSPACE.getValue());
|
||||
ProjectNodePo disciplineNode = new ProjectNodePo();
|
||||
disciplineNode.setNodeName(" ");
|
||||
disciplineNode.setNodeCode(" ");
|
||||
disciplineNode.setNodeType(NodeTypeEnum.DISCIPLINE.getValue());
|
||||
disciplineNode.setChildren(Collections.singletonList(projectNodePo));
|
||||
workspaceNode.setChildren(Collections.singletonList(disciplineNode));
|
||||
machineNode.setChildren(Collections.singletonList(workspaceNode));
|
||||
fillChildrenNode(machineNode);
|
||||
}
|
||||
allTopProjectNodeList.add(machineNode);
|
||||
}
|
||||
ExcelUtil.exportExcelWithMerge(JSONArray.from(allTopProjectNodeList),exportExcelFormats,new ArrayList<>(),httpServletResponse);
|
||||
} else {
|
||||
response = SdmResponse.failed(taskRespond.getMessage());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
private NodeAllBase fillChildrenNode(NodeAllBase projectNodePo) {
|
||||
String nodeType = projectNodePo.getNodeType();
|
||||
if (StringUtils.isBlank(projectNodePo.getNodeCode())) {
|
||||
projectNodePo.setNodeCode(" ");
|
||||
}
|
||||
List<NodeAllBase> childrenNodeList = projectNodePo.getChildren();
|
||||
if (CollectionUtils.isEmpty(childrenNodeList)) {
|
||||
return projectNodePo;
|
||||
}
|
||||
String childrenNodeType = nodeTypeList.get(nodeTypeList.indexOf(nodeType) + 1);
|
||||
List<Long> removeIdList = new ArrayList<>();
|
||||
List<ProjectNodePo> newNodeList = new ArrayList<>();
|
||||
for (NodeAllBase childNode : childrenNodeList) {
|
||||
if ((nodeType.equals(childNode.getNodeType()) || childrenNodeType.equals(childNode.getNodeType())) && CollectionUtils.isEmpty(childNode.getChildren())) {
|
||||
continue;
|
||||
}
|
||||
if (!childrenNodeType.equals(childNode.getNodeType()) && nodeTypeList.indexOf(childrenNodeType) < nodeTypeList.indexOf(childNode.getNodeType())) {
|
||||
ProjectNodePo emptyNode = new ProjectNodePo();
|
||||
emptyNode.setNodeName(" ");
|
||||
emptyNode.setNodeCode(" ");
|
||||
emptyNode.setNodeType(childrenNodeType);
|
||||
if (CollectionUtils.isEmpty(childNode.getChildren())) {
|
||||
emptyNode.setChildren(Collections.singletonList(childNode));
|
||||
}else {
|
||||
emptyNode.setChildren(Collections.singletonList(fillChildrenNode(childNode)));
|
||||
}
|
||||
removeIdList.add(childNode.getId());
|
||||
newNodeList.add(emptyNode);
|
||||
}else {
|
||||
fillChildrenNode(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(removeIdList)) {
|
||||
Iterator<NodeAllBase> iterator = childrenNodeList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
NodeAllBase nodeAllBase = iterator.next();
|
||||
if (removeIdList.contains(nodeAllBase.getId())) { // 假设我们想删除所有偶数
|
||||
iterator.remove(); // 使用迭代器的remove方法安全删除元素
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(newNodeList)) {
|
||||
childrenNodeList.addAll(newNodeList);
|
||||
}
|
||||
return projectNodePo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -926,7 +926,7 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
||||
public SdmResponse startProcessInstance(SpdmTaskRunReq req) {
|
||||
SimulationRun simulationRun = this.lambdaQuery().eq(SimulationRun::getUuid, req.getRunId()).one();
|
||||
// 启动流程实例 多次执行会生成多个流程实例id,更新算例run表、同时更新flowable流程参数的流程实例id
|
||||
SdmResponse<ProcessInstanceResp> sdmResponse = flowableFeignClient.startByProcessDefinitionId(simulationRun.getProcessDefinitionId(), null);
|
||||
SdmResponse<ProcessInstanceResp> sdmResponse = flowableFeignClient.startByProcessDefinitionId(simulationRun.getProcessDefinitionId(), Collections.emptyMap());
|
||||
if (sdmResponse.getData() != null) {
|
||||
this.lambdaUpdate().set(SimulationRun::getFlowInstanceId, sdmResponse.getData().getProcessInstanceId()).eq(SimulationRun::getUuid, req.getRunId()).update();
|
||||
flowableFeignClient.updateNodeParamProcessInstanceId(simulationRun.getProcessDefinitionId(), sdmResponse.getData().getProcessInstanceId());
|
||||
@@ -950,25 +950,17 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
||||
definitionDTO.getFlowElements().stream().filter(i -> StringUtils.equals(i.getId(), flowNodeDto.getNodeId())).findFirst().ifPresent(i -> {
|
||||
if (i.getExtensionElements() != null && i.getExtensionElements().getExecuteConfig() != null) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if ("HPC".equals(i.getExtensionElements().getExecuteConfig().getExecuteType())) {
|
||||
// 计算节点 输出文件夹id 保存到用户输入参数
|
||||
params.put("outputDirId", flowNodeDto.getOutputDirId());
|
||||
} else if ("exportWordScript".equals(i.getExtensionElements().getExecuteConfig().getExecuteType())) {
|
||||
// 脚本节点
|
||||
// 处理脚本上传到当前节点文件夹下,获得 脚本文件id
|
||||
// 脚本文件id 保存到用户输入参数
|
||||
// 正则表达式 保存到用户输入参数
|
||||
params.putAll(req.getInputParams());
|
||||
// 脚本输出文件夹id 保存到用户输入参数
|
||||
params.put("outputDirId", flowNodeDto.getOutputDirId());
|
||||
}
|
||||
// 输出文件夹id 保存到用户输入参数
|
||||
params.put("outputDirId", flowNodeDto.getOutputDirId());
|
||||
// 前端用户输入参数
|
||||
params.putAll(req.getInputParams());
|
||||
flowableFeignClient.saveParamsByDefinitionId(simulationRun.getProcessDefinitionId(), flowNodeDto.getNodeId(), params);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return SdmResponse.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -979,28 +971,23 @@ public class SimulationRunServiceImpl extends ServiceImpl<SimulationRunMapper, S
|
||||
if (sdmResponse.getData() != null) {
|
||||
List<FlowNodeDto> flowNodeDtoList = sdmResponse.getData();
|
||||
SimulationRun simulationRun = this.lambdaQuery().eq(SimulationRun::getUuid, req.getRunId()).one();
|
||||
if (simulationRun.getFlowInstanceId() != null) {
|
||||
SdmResponse<ProcessInstanceDetailResponse> response = flowableFeignClient.getProcessAndNodeDetailByInstanceId(simulationRun.getFlowInstanceId());
|
||||
if (response.getData() != null && CollectionUtils.isNotEmpty(response.getData().getNodes())) {
|
||||
for (FlowNodeDto flowNodeDto : flowNodeDtoList) {
|
||||
response.getData().getNodes().stream().filter(i -> StringUtils.equals(i.getId(), flowNodeDto.getNodeId())).findFirst().ifPresent(i -> {
|
||||
flowNodeDto.setNodeStatus(i.getStatus());
|
||||
});
|
||||
}
|
||||
SdmResponse<ProcessInstanceDetailResponse> response = flowableFeignClient.getProcessAndNodeDetailByInstanceId(simulationRun.getProcessDefinitionId(), simulationRun.getFlowInstanceId());
|
||||
if (response.getData() != null && CollectionUtils.isNotEmpty(response.getData().getNodes())) {
|
||||
for (FlowNodeDto flowNodeDto : flowNodeDtoList) {
|
||||
response.getData().getNodes().stream().filter(i -> StringUtils.equals(i.getId(), flowNodeDto.getNodeId())).findFirst().ifPresent(i -> {
|
||||
flowNodeDto.setNodeStatus(i.getStatus());
|
||||
flowNodeDto.setUserParams(i.getUserParam());
|
||||
flowNodeDto.setProcessInstanceId(simulationRun.getFlowInstanceId());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (simulationRun.getFlowInstanceId() == null) {
|
||||
flowNodeDtoList.forEach(node -> {
|
||||
node.setNodeStatus("pending");
|
||||
});
|
||||
}
|
||||
List<NodeStructureInfo> nodeStructureInfoList = flowableFeignClient.listNodesByProcessDefinitionId(simulationRun.getProcessDefinitionId()).getData();
|
||||
if (CollectionUtils.isNotEmpty(nodeStructureInfoList)) {
|
||||
for (FlowNodeDto flowNodeDto : flowNodeDtoList) {
|
||||
nodeStructureInfoList.stream().filter(i -> StringUtils.equals(i.getId(), flowNodeDto.getNodeId())).findFirst().ifPresent(i -> {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
return SdmResponse.success(flowNodeDtoList);
|
||||
}
|
||||
return SdmResponse.success(new ArrayList<>());
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
</insert>
|
||||
|
||||
<insert id="addDemandExtra">
|
||||
insert into simulation_demand_extra (uuid,demand_id,nodeId,property_name,property_value,value_type,property_class,creator,create_time) values
|
||||
insert into simulation_demand_extra (demand_id,property_name,property_value,value_type,property_class,creator,create_time) values
|
||||
<foreach collection='demandExtraList' item='extra' index='index' separator=','>
|
||||
(#{extra.uuid},#{extra.demandId},#{extra.nodeId},#{extra.propertyName},#{extra.propertyValue},#{extra.valueType},#{extra.propertyClass},#{extra.creator},#{extra.createTime})
|
||||
(#{extra.demandId},#{extra.propertyName},#{extra.propertyValue},#{extra.valueType},#{extra.propertyClass},#{extra.creator},#{extra.createTime})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
@@ -113,14 +113,11 @@
|
||||
<if test="req.demandName != null and req.demandName != ''">
|
||||
and demand_name like CONCAT('%',#{req.demandName},'%')
|
||||
</if>
|
||||
<if test="req.projectName != null and req.projectName != ''">
|
||||
and project_name = #{req.projectName}
|
||||
<if test="req.projectId != null and req.projectId != ''">
|
||||
and project_id = #{req.projectId}
|
||||
</if>
|
||||
<if test="req.phaseName != null and req.phaseName != ''">
|
||||
and phase_name = #{req.phaseName}
|
||||
</if>
|
||||
<if test="req.disciplineName != null and req.disciplineName != ''">
|
||||
and disciplineName = #{req.disciplineName}
|
||||
<if test="req.phaseId != null and req.phaseId != ''">
|
||||
and phase_id = #{req.phaseId}
|
||||
</if>
|
||||
<if test="req.demandType != null and req.demandType != ''">
|
||||
and demand_type = #{req.demandType}
|
||||
@@ -152,4 +149,12 @@
|
||||
select * from simulation_demand where tenant_id = #{tenantId} and demand_name = #{demandName} limit 1
|
||||
</select>
|
||||
|
||||
<select id="getDemandExtraList" resultType="com.sdm.project.model.vo.SpdmDemandExtraVo">
|
||||
select * from simulation_demand_extra where demand_id in (
|
||||
<foreach collection='demandIdList' item='demandId' index='index' separator=','>
|
||||
#{demandId}
|
||||
</foreach>
|
||||
)
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -250,7 +250,7 @@ public class SimulationTaskPoolServiceImpl extends BaseService implements ISimul
|
||||
else
|
||||
{
|
||||
JSONObject taskPool = (JSONObject) taskPoolResp.getData();
|
||||
ExcelUtil.exportExcelWithMerge(taskPool.getJSONArray("nodes"),req.excelHeaders,httpServletResponse);
|
||||
ExcelUtil.exportExcelWithMerge(taskPool.getJSONArray("nodes"),req.excelHeaders,new ArrayList<>(),httpServletResponse);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user