feat(ai-report): 新增委托单位管理和报告审批功能
- 新增委托单位管理模块,支持增删改查、导入导出功能 - 实现委托单位 Excel 模板下载和数据导入功能 - 添加报告审批抽象处理器,支持审批流程日志记录 - 统一文件存储路径配置,将各模块独立路径改为统一根目录 - 新增 PQDIF 文件名存储字段,完善文件管理功能 - 修复代码中的乱码问题和错误提示信息 - 优化系统常量定义和字典配置管理
This commit is contained in:
@@ -18,9 +18,10 @@ import java.util.UUID;
|
||||
public class PqdifFileStorageService {
|
||||
|
||||
private static final String DEFAULT_STORAGE_DIR = "data/parse-pqdif";
|
||||
private static final String PQDIF_STORAGE_DIR = "pqdif-files";
|
||||
|
||||
@Value("${parse-pqdif.storage.path:}")
|
||||
private String storagePath;
|
||||
@Value("${files.path:}")
|
||||
private String filesPath;
|
||||
|
||||
public String save(MultipartFile pqdifFile) {
|
||||
if (pqdifFile == null || pqdifFile.isEmpty()) {
|
||||
@@ -47,8 +48,8 @@ public class PqdifFileStorageService {
|
||||
}
|
||||
|
||||
private Path resolveStorageDir() {
|
||||
String configuredPath = trimToNull(storagePath);
|
||||
Path path = configuredPath == null ? Paths.get(DEFAULT_STORAGE_DIR) : Paths.get(configuredPath);
|
||||
String configuredPath = trimToNull(filesPath);
|
||||
Path path = configuredPath == null ? Paths.get(DEFAULT_STORAGE_DIR) : Paths.get(configuredPath, PQDIF_STORAGE_DIR);
|
||||
return path.toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ public class CsPqdifPathController extends BaseController {
|
||||
|
||||
private void fillPqdifFilePath(CsPqdifPathParam param, MultipartFile pqdifFile) {
|
||||
param.setFilePath(pqdifFileStorageService.save(pqdifFile));
|
||||
param.setFileName(resolveFileName(pqdifFile));
|
||||
}
|
||||
|
||||
private String resolveFileName(MultipartFile pqdifFile) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<id column="id" property="id"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="filePath" property="filePath"/>
|
||||
<result column="fileName" property="fileName"/>
|
||||
<result column="recordCount" property="recordCount"/>
|
||||
<result column="observationCount" property="observationCount"/>
|
||||
<result column="sampleValueCount" property="sampleValueCount"/>
|
||||
@@ -27,6 +28,7 @@
|
||||
ID AS id,
|
||||
Name AS name,
|
||||
File_Path AS filePath,
|
||||
File_Name AS fileName,
|
||||
Record_Count AS recordCount,
|
||||
Observation_Count AS observationCount,
|
||||
Sample_Value_Count AS sampleValueCount,
|
||||
@@ -60,7 +62,8 @@
|
||||
SELECT
|
||||
ID AS id,
|
||||
Name AS name,
|
||||
File_Path AS filePath
|
||||
File_Path AS filePath,
|
||||
File_Name AS fileName
|
||||
FROM cs_pqdif_path
|
||||
WHERE ID = #{id}
|
||||
AND State = 1
|
||||
|
||||
@@ -23,6 +23,10 @@ public class CsPqdifPathParam {
|
||||
@JsonIgnore
|
||||
private String filePath;
|
||||
|
||||
@ApiModelProperty("PQDIF鍘熷鏂囦欢鍚?")
|
||||
@JsonIgnore
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* PQDIF 存储记录编辑参数。
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,9 @@ public class CsPqdifPathPO implements Serializable {
|
||||
@TableField("File_Path")
|
||||
private String filePath;
|
||||
|
||||
@TableField("File_Name")
|
||||
private String fileName;
|
||||
|
||||
@TableField("Record_Count")
|
||||
private Long recordCount;
|
||||
|
||||
|
||||
@@ -19,4 +19,7 @@ public class CsPqdifPathDetailVO {
|
||||
|
||||
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||
private String filePath;
|
||||
|
||||
@ApiModelProperty("PQDIF鍘熷鏂囦欢鍚?")
|
||||
private String fileName;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ public class CsPqdifPathVO {
|
||||
@ApiModelProperty("PQDIF原始文件存储路径")
|
||||
private String filePath;
|
||||
|
||||
@ApiModelProperty("PQDIF鍘熷鏂囦欢鍚?")
|
||||
private String fileName;
|
||||
|
||||
@ApiModelProperty("Record总数")
|
||||
private Long recordCount;
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ public class CsPqdifPathServiceImpl implements CsPqdifPathService {
|
||||
CsPqdifPathPO pqdifPath = new CsPqdifPathPO();
|
||||
pqdifPath.setName(requireText(param.getName(), "PQDIF名称不能为空"));
|
||||
pqdifPath.setFilePath(trimToNull(param.getFilePath()));
|
||||
pqdifPath.setFileName(trimToNull(param.getFileName()));
|
||||
return pqdifPath;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.gather.tool.parsepqdif.component;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class PqdifFileStorageServiceTest {
|
||||
|
||||
@Test
|
||||
public void saveUsesPqdifFilesDirectoryUnderFilesRoot() throws Exception {
|
||||
Path filesRoot = Files.createTempDirectory("files-root");
|
||||
PqdifFileStorageService service = new PqdifFileStorageService();
|
||||
ReflectionTestUtils.setField(service, "filesPath", filesRoot.toString());
|
||||
|
||||
String storedPath = service.save(new MockMultipartFile("pqdifFile", "sample.pqd",
|
||||
"application/octet-stream", "content".getBytes("UTF-8")));
|
||||
|
||||
Path expectedRoot = filesRoot.resolve("pqdif-files").toAbsolutePath().normalize();
|
||||
Path actualPath = Paths.get(storedPath).toAbsolutePath().normalize();
|
||||
Assert.assertTrue(actualPath.startsWith(expectedRoot));
|
||||
Assert.assertTrue(Files.exists(actualPath));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.njcn.gather.tool.parsepqdif.service.impl;
|
||||
|
||||
import com.njcn.gather.tool.parsepqdif.mapper.CsPqdifPathMapper;
|
||||
import com.njcn.gather.tool.parsepqdif.pojo.param.CsPqdifPathParam;
|
||||
import com.njcn.gather.tool.parsepqdif.pojo.po.CsPqdifPathPO;
|
||||
import com.njcn.gather.tool.parsepqdif.pojo.vo.CsPqdifPathDetailVO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class CsPqdifPathServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void addPqdifPathShouldPersistFileName() {
|
||||
CsPqdifPathMapper mapper = mock(CsPqdifPathMapper.class);
|
||||
when(mapper.insert(any(CsPqdifPathPO.class))).thenReturn(1);
|
||||
CsPqdifPathServiceImpl service = new CsPqdifPathServiceImpl(mapper);
|
||||
|
||||
CsPqdifPathParam param = new CsPqdifPathParam();
|
||||
param.setName("sample");
|
||||
param.setFilePath("D:/files/pqdif-files/uuid_sample.pqd");
|
||||
param.setFileName("sample.pqd");
|
||||
|
||||
boolean result = service.addPqdifPath(param);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
ArgumentCaptor<CsPqdifPathPO> captor = ArgumentCaptor.forClass(CsPqdifPathPO.class);
|
||||
verify(mapper).insert(captor.capture());
|
||||
Assert.assertEquals("sample.pqd", captor.getValue().getFileName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePqdifPathShouldPersistFileName() {
|
||||
CsPqdifPathMapper mapper = mock(CsPqdifPathMapper.class);
|
||||
CsPqdifPathDetailVO detail = new CsPqdifPathDetailVO();
|
||||
detail.setId("pqdif-id");
|
||||
when(mapper.selectPqdifPathDetailById("pqdif-id")).thenReturn(detail);
|
||||
when(mapper.updateById(any(CsPqdifPathPO.class))).thenReturn(1);
|
||||
CsPqdifPathServiceImpl service = new CsPqdifPathServiceImpl(mapper);
|
||||
|
||||
CsPqdifPathParam.UpdateParam param = new CsPqdifPathParam.UpdateParam();
|
||||
param.setId("pqdif-id");
|
||||
param.setName("sample");
|
||||
param.setFilePath("D:/files/pqdif-files/uuid_sample_new.pqd");
|
||||
param.setFileName("sample-new.pqd");
|
||||
|
||||
boolean result = service.updatePqdifPath(param);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
ArgumentCaptor<CsPqdifPathPO> captor = ArgumentCaptor.forClass(CsPqdifPathPO.class);
|
||||
verify(mapper).updateById(captor.capture());
|
||||
Assert.assertEquals("sample-new.pqd", captor.getValue().getFileName());
|
||||
verify(mapper).selectPqdifPathDetailById(eq("pqdif-id"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user