Browse Source

update

tags/v0
zhaohe 8 months ago
parent
commit
7053a8ecd1
  1. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_01_FLOW1.java
  2. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_02_FLOW2.java
  3. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_03.java
  4. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_04.java
  5. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_05.java
  6. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_06.java
  7. 2
      src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_07_EXPIRED.java
  8. 2
      src/main/java/a8k/a8kproj/fakeproj/FakeProjInfo.java
  9. 97
      src/main/java/a8k/controler/filemgr/OptFileMgrController.java
  10. 8
      src/main/java/a8k/service/app/appctrl/AppConsumablesScanService.java
  11. 4
      src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java
  12. 17
      src/main/java/a8k/service/dao/ProjectBaseInfoDao.java
  13. 4
      src/main/java/a8k/service/dao/type/a8kidcard/zenum/A8kReactionFlowType.java
  14. 2
      src/main/java/a8k/unittest/TestOptAnalyzer.java
  15. 4
      src/main/java/a8k/utils/ProjProcessContextUtils.java
  16. 31
      src/main/java/a8k/utils/ZCSVUtils.java
  17. 11
      src/main/java/a8k/utils/ZSqlite.java
  18. 24
      src/main/java/a8k/utils/ZSqliteJdbcHelper.java
  19. 32
      src/main/resources/a8k/db/zapp_a8k_project_info.csv
  20. 119
      src/main/resources/templates/optfilemgr/index.html

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_01_FLOW1.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_01_FLOW1 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType1; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBS; // 反应流程类型
}
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_02_FLOW2.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_02_FLOW2 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType2; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBSAndProbeSubstance; // 反应流程类型
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_03.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_03 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType1; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBS; // 反应流程类型
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_04.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_04 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType2; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBSAndProbeSubstance; // 反应流程类型
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_05.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_05 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType2; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBSAndProbeSubstance; // 反应流程类型
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_06.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_06 extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType2; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBSAndProbeSubstance; // 反应流程类型
}

2
src/main/java/a8k/a8kproj/fakeproj/FAKE_PROJ_07_EXPIRED.java

@ -9,7 +9,7 @@ public class FAKE_PROJ_07_EXPIRED extends FakeProjInfo {
subProjNum = 1; // 子项目数量
reactionTemperature = 25; // 反应温度
reactionPlateIncubationTimeMin = 1; // 反应板孵育时间(min)
reactionFlowType = A8kReactionFlowType.FlowType2; // 反应流程类型
reactionFlowType = A8kReactionFlowType.SampleAndBSAndProbeSubstance; // 反应流程类型
expired = true;
}

2
src/main/java/a8k/a8kproj/fakeproj/FakeProjInfo.java

@ -21,7 +21,7 @@ public class FakeProjInfo {
public String projShortName = "FA";
public Integer reactionTemperature = 25;
public String color;
public A8kReactionFlowType reactionFlowType = A8kReactionFlowType.FlowType1;
public A8kReactionFlowType reactionFlowType = A8kReactionFlowType.SampleAndBS;
public Integer wBloodSampleVolUl = 100;
public Integer serumSampleVolUl = 100;
public Integer shakeTimes = 5;

97
src/main/java/a8k/controler/filemgr/OptFileMgrController.java

@ -0,0 +1,97 @@
package a8k.controler.filemgr;
import a8k.service.app.appdata.FileMgrService;
import a8k.type.appret.ApiV1Ret;
import a8k.type.appret.AppRetV1;
import cn.hutool.core.net.URLDecoder;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.List;
@Controller
@Slf4j
@RequestMapping("/optfilemgr")
public class OptFileMgrController {
@Resource
FileMgrService fileMgrService;
record FileGroup(String name, List<FileInfo> files) {
}
record FileInfo(String filePath, String name) {
}
FileGroup buidOptFileGroup() {
List<FileInfo> files = fileMgrService.getOptReportList().stream()
.map(fileName -> new FileInfo(fileMgrService.getOptReportFilePath(fileName), fileName))
.toList();
return new FileGroup("光学报告", files);
}
@GetMapping("")
public String fileDownloadPage(Model model) {
// Mock data for file groups and files
List<FileGroup> fileGroups = List.of(
buidOptFileGroup()
);
model.addAttribute("fileGroups", fileGroups);
return "optfilemgr/index.html";
}
@GetMapping("/download/**")
@ResponseBody
public ResponseEntity<org.springframework.core.io.Resource> download(HttpServletRequest request) {
String path = request.getRequestURI().substring("/optfilemgr/download/".length());
//转义地址中空格TODO:支持处理中文文件名
// path = path.replaceAll("%20", " ");
path = URLDecoder.decode(path, StandardCharsets.UTF_8);
String fileName = Paths.get(path).getFileName().toString();
log.info("Download file:{} path:{}", fileName, path);
File file = new File(path);
String contentDisposition = ContentDisposition
.builder("attachment")
.filename(fileName, StandardCharsets.UTF_8) // Use the original filename
.build().toString();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
.body(new FileSystemResource(file.getAbsolutePath()));
}
// http://127.0.0.1/optfilemgr/download/runenv/files/optReport/Fake(%20xxxx)-FOPT-20241112172645.txt
@GetMapping("/export/**")
@ResponseBody
public ResponseEntity<?> export(HttpServletRequest request) {
String path = request.getRequestURI().substring("/optfilemgr/export/".length());
log.info("Export file: {}", path);
//返回AppRetV1.success("导出成功")
// %2Ffiles%2FoptReport%2FFake(%20xxxx)-FOPT-20241112172645.txt
return ResponseEntity.ok(AppRetV1.success("导出成功"));
}
}

8
src/main/java/a8k/service/app/appctrl/AppConsumablesScanService.java

@ -100,7 +100,7 @@ public class AppConsumablesScanService {
Integer projId = projExtInfoCard.projId;
A8kReactionFlowType reactionType = projBuildinInfo.projBaseInfo.reactionFlowType;
if (reactionType.equals(A8kReactionFlowType.FlowType1)) {
if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) {
//校验小瓶缓冲液,小瓶缓冲液+样本
if (ZStringUtils.isNullOrEmpty(rawResult.littBSScanResult)) {
ret.report = ConsumablesScanReportErrorType.MISS_LITTSB;
@ -112,7 +112,7 @@ public class AppConsumablesScanService {
return ret;
}
} else if (reactionType.equals(A8kReactionFlowType.FlowType2)) {
} else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) {
// 校验大瓶缓冲液,大瓶缓冲液+小瓶缓冲液+样本
if (ZStringUtils.isNullOrEmpty(rawResult.larBSScanResult)) {
ret.report = ConsumablesScanReportErrorType.MISS_LARBS;
@ -162,11 +162,11 @@ public class AppConsumablesScanService {
LarBottleGroup larBottleGroup;
reactionPlateGroup = new ReactionPlateGroup(result.projId, projExtInfoCard.projName, projInfo.projShortName, result.lotId, projExtInfoCard.color, AppConstant.CONSUMABLE_NUM);
if (reactionType.equals(A8kReactionFlowType.FlowType1)) {
if (reactionType.equals(A8kReactionFlowType.SampleAndBS)) {
littBottleGroup = new LittBottleGroup(LittleBottleConsumableType.BufferSolution, result.projId, projExtInfoCard.projName, projInfo.projShortName, result.lotId,
projExtInfoCard.color, AppConstant.CONSUMABLE_NUM);
larBottleGroup = new LarBottleGroup();
} else if (reactionType.equals(A8kReactionFlowType.FlowType2)) {
} else if (reactionType.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) {
littBottleGroup = new LittBottleGroup(LittleBottleConsumableType.ProbeSubstance, result.projId, projExtInfoCard.projName, projInfo.projShortName, result.lotId,
projExtInfoCard.color, AppConstant.CONSUMABLE_NUM);
larBottleGroup = new LarBottleGroup(result.projId, projExtInfoCard.projName, projInfo.projShortName, result.lotId, projExtInfoCard.color, AppConstant.CONSUMABLE_NUM);

4
src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java

@ -377,7 +377,7 @@ public class SEQ5_PROCESS extends A8kStepAction {
//
// 初步反应准备
//
if (type.equals(A8kReactionFlowType.FlowType1)) {
if (type.equals(A8kReactionFlowType.SampleAndBS)) {
log.info("FlowType1:");
doSampleFlowType1PreProcess(cxt);
@ -394,7 +394,7 @@ public class SEQ5_PROCESS extends A8kStepAction {
hbotCtrlService.moveToLittleBufferSamplePos(consumableGroup, consumablePos);
}
} else if (type.equals(A8kReactionFlowType.FlowType2)) {
} else if (type.equals(A8kReactionFlowType.SampleAndBSAndProbeSubstance)) {
log.info("FlowType2:");
doSampleFlowType2PreProcess(cxt);

17
src/main/java/a8k/service/dao/ProjectBaseInfoDao.java

@ -3,15 +3,22 @@ package a8k.service.dao;
import a8k.service.app.appdata.UtilsProjectColorAllocer;
import a8k.service.dao.type.ProjectBaseInfo;
import a8k.utils.ZCSVUtils;
import a8k.utils.ZJsonHelper;
import a8k.utils.ZSqlite;
import cn.hutool.core.io.resource.ResourceUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
@Component
public class ProjectBaseInfoDao extends ZSqlite<ProjectBaseInfo> {
private static final Logger log = LoggerFactory.getLogger(ProjectBaseInfoDao.class);
@Resource
JdbcTemplate jdbcTemplate;
@ -20,7 +27,13 @@ public class ProjectBaseInfoDao extends ZSqlite<ProjectBaseInfo> {
@PostConstruct
void init() {
init(jdbcTemplate, "zapp_a8k_project_info", ProjectBaseInfo.class);
init(jdbcTemplate, "zapp_a8k_project_info", ProjectBaseInfo.class, true);
var list = ZCSVUtils.readCSVFromResource("a8k/db/zapp_a8k_project_info.csv", ProjectBaseInfo.class);
for (var val : list) {
log.info("{}", ZJsonHelper.objectToJson(val));
val.id = val.projId;
add(val);
}
}
@ -35,7 +48,7 @@ public class ProjectBaseInfoDao extends ZSqlite<ProjectBaseInfo> {
public void loadCfg() {
//
// ProjectBaseInfo
// ProjectBaseInfo
}

4
src/main/java/a8k/service/dao/type/a8kidcard/zenum/A8kReactionFlowType.java

@ -12,7 +12,7 @@ public enum A8kReactionFlowType {
* 取样
* 滴定
*/
FlowType1(1, 2), //样本和小瓶缓冲反应
SampleAndBS(1, 2), //样本和小瓶缓冲反应
/**
*
@ -28,7 +28,7 @@ public enum A8kReactionFlowType {
* 取样
* 滴定
*/
FlowType2(2, 2),//样本大瓶缓冲液探测物质反应
SampleAndBSAndProbeSubstance(2, 2),//样本大瓶缓冲液探测物质反应
;
public final int tipUseNum;
public final int valInIdCard;

2
src/main/java/a8k/unittest/TestOptAnalyzer.java

@ -21,7 +21,7 @@ public class TestOptAnalyzer {
}
public Boolean TEST_OPT_RESULT_PARSE_01() {
var cfg = FakeProjInfoContextFactory.createCfg("TEST_PROJ", 2, A8kReactionFlowType.FlowType1, 3);
var cfg = FakeProjInfoContextFactory.createCfg("TEST_PROJ", 2, A8kReactionFlowType.SampleAndBS, 3);
ProjInfo projInfoContext = FakeProjInfoContextFactory.build(cfg);
SampleInfo sampleInfo = new SampleInfo();

4
src/main/java/a8k/utils/ProjProcessContextUtils.java

@ -158,8 +158,8 @@ public class ProjProcessContextUtils {
HbotConsumableParamMgr hbotConsumableParamMgr = SpringBootBeanUtil.getBean(HbotConsumableParamMgr.class);
A8kReactionFlowType type = ctx.getProjBuildinInfo().projBaseInfo.reactionFlowType;
return switch (type) {
case FlowType1 -> hbotConsumableParamMgr.getLittleBufferSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos());
case FlowType2 -> hbotConsumableParamMgr.getProbeSubstanceSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos());
case SampleAndBS -> hbotConsumableParamMgr.getLittleBufferSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos());
case SampleAndBSAndProbeSubstance -> hbotConsumableParamMgr.getProbeSubstanceSamplePos(ctx.getConsumable().getGroup(), ctx.getConsumable().getPos());
};
}

31
src/main/java/a8k/utils/ZCSVUtils.java

@ -1,14 +1,17 @@
package a8k.utils;
import a8k.service.dao.ProjectBaseInfoDao;
import a8k.service.dao.type.ProjectBaseInfo;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@ -42,7 +45,7 @@ public class ZCSVUtils {
}
log.info("row: {}", row);
// log.info("row: {}", row);
csvWriter.write(row);
}
csvWriter.flush();
@ -52,10 +55,21 @@ public class ZCSVUtils {
}
public static <T> List<T> readCSV(String filePath, Class<T> clazz) {
return null;
File file = new File(filePath);
final CsvReader reader = CsvUtil.getReader();
String csvContent = ResourceUtil.readUtf8Str(file.getAbsolutePath());
return reader.read(csvContent, clazz);
}
public static <T> List<T> readCSVFromResource(String filePath, Class<T> clazz) {
String csvContent = ResourceUtil.readUtf8Str(filePath);
final CsvReader reader = CsvUtil.getReader();
return reader.read(csvContent, clazz);
}
public static void main(String[] args) {
// write demo
List<ProjectBaseInfo> objects = new ArrayList<>();
for (int i = 0; i < 10; i++) {
@ -68,7 +82,16 @@ public class ZCSVUtils {
projectBaseInfo.color = "color" + i;
objects.add(projectBaseInfo);
}
writeCSV("tmp/test.csv", ProjectBaseInfo.class, objects);
writeCSV("tmp/zapp_a8k_project_info.csv", ProjectBaseInfo.class, objects);
// read demo
List<ProjectBaseInfo> projectBaseInfos = readCSV("tmp/zapp_a8k_project_info.csv", ProjectBaseInfo.class);
for (var projectBaseInfo : projectBaseInfos) {
log.info("{}", ZJsonHelper.objectToJson(projectBaseInfo));
}
}

11
src/main/java/a8k/utils/ZSqlite.java

@ -19,15 +19,24 @@ public class ZSqlite<T> {
public ZSqlite() {
}
public void init(JdbcTemplate jdbcTemplate, String tableName, Class<T> tClass) {
public void init(JdbcTemplate jdbcTemplate, String tableName, Class<T> tClass, boolean foreceCreate) {
this.tableName = tableName;
this.tClass = tClass;
this.jdbcTemplate = jdbcTemplate;
if (foreceCreate) {
this.forceDeleteTable();
}
if (!this.isTableExist()) {
this.createTable();
}
}
public void init(JdbcTemplate jdbcTemplate, String tableName, Class<T> tClass) {
init(jdbcTemplate, tableName, tClass, false);
}
public List<T> getAll() {
return jdbcTemplate.query("select * from " + tableName, this::rowMapperList);
}

24
src/main/java/a8k/utils/ZSqliteJdbcHelper.java

@ -200,17 +200,37 @@ public class ZSqliteJdbcHelper {
StringBuilder sql = new StringBuilder("insert into " + tableName + "(");
StringBuilder values = new StringBuilder(" values(");
int idval = 0;
for (java.lang.reflect.Field field : tClass.getDeclaredFields()) {
if (field.getName().equals("id"))
if (field.getName().equals("id")) {
if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) {
field.setAccessible(true);
try {
idval = field.getInt(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
continue;
}
sql.append(field.getName()).append(",");
values.append("?,");
}
if (idval != 0) {
sql.append("id,");
values.append("?,");
}
sql.deleteCharAt(sql.length() - 1).append(")");
values.deleteCharAt(values.length() - 1).append(")");
sql.append(values);
jdbcTemplate.update(sql.toString(), buildArgs(tClass, obj).toArray());
var args = buildArgs(tClass, obj);
if (idval != 0)
args.add(idval);
jdbcTemplate.update(sql.toString(), args.toArray());
}
public static void updateObj(JdbcTemplate jdbcTemplate, String tableName, Class<?> tClass, Object obj) {

32
src/main/resources/a8k/db/zapp_a8k_project_info.csv

@ -0,0 +1,32 @@
projId,projName,projShortName,subProjNum,reactionTemperature,color,reactionFlowType,wBloodSampleVolUl,serumSampleVolUl,shakeTimes,bigBufferSampleUl,reactionPlateIncubationTimeMin,reactionPlateDropletVolUl,
1,hsCRP,CA,1,25,#FFC0CB,SampleAndBS,10,10,3,0,3,75,
2,PCT,PC,1,25,#DC143C,SampleAndBS,150,150,3,0,12,75,
3,TSH,TS,1,25,#DB7093,SampleAndBSAndProbeSubstance,150,150,3,75,12,75,
4,PRL,PL,1,25,#FF69B4,SampleAndBS,75,75,3,0,10,75,
5,T3,T3,1,25,#FF1493,SampleAndBSAndProbeSubstance,75,75,3,75,8,75,
6,T4,T4,1,25,#C71585,SampleAndBSAndProbeSubstance,75,75,3,75,8,75,
7,Total β hCG,HC,1,25,#DA70D6,SampleAndBS,50,30,3,0,15,75,
8,LH,LH,1,25,#D8BFD8,SampleAndBS,150,150,3,0,15,75,
9,FSH,FS,1,25,#DDA0DD,SampleAndBS,150,150,3,0,15,75,
10,Progesterone,PG,1,25,#EE82EE,SampleAndBS,30,30,3,0,15,75,
12,Tn-I plus,TG,1,25,#FF00FF,SampleAndBSAndProbeSubstance,50,50,3,150,12,75,
13,NT-proBNP,NB,1,25,#8B008B,SampleAndBSAndProbeSubstance,10,10,3,150,12,75,
14,CK-MB,CK,1,25,#800080,SampleAndBS,75,75,3,0,12,75,
15,Myoglobin,MY,1,25,#BA55D3,SampleAndBS,10,10,3,0,12,75,
16,D-Dimer,DD,1,25,#9400D3,SampleAndBS,10,10,3,0,12,75,
17,HbAlC,HB,1,25,#9932CC,SampleAndBSAndProbeSubstance,5,5,3,100,12,75,
18,PCT plus,PP,1,25,#4B0082,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,
20,Tn-I/CK-MB/Myoglobin,CT,3,25,#9370DB,SampleAndBSAndProbeSubstance,75,75,3,150,12,75,
22,PCT/hsCRP,PR,1,25,#6A5ACD,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,
24,SAA,SA,1,25,#E6E6FA,SampleAndBS,10,10,3,0,3,75,
25,AMH,AM,1,25,#F8F8FF,SampleAndBSAndProbeSubstance,50,50,3,150,12,75,
26,SAA/CRP,SC,2,25,#0000FF,SampleAndBS,10,10,3,0,3,75,
27,Vitamin D,VD,1,25,#0000FF,SampleAndBSAndProbeSubstance,30,30,3,150,12,75,
33,ST2,ST,1,25,#6495ED,SampleAndBSAndProbeSubstance,75,75,3,150,12,75,
36,MxA,MX,1,25,#708090,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,
48,IL-6,IL,1,25,#AFEEEE,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,
49,Gastrin 17,GA,1,25,#00FFFF,SampleAndBSAndProbeSubstance,50,50,3,150,15,75,
50,Pepsinogen I/II,PS,2,25,#00FFFF,SampleAndBSAndProbeSubstance,10,10,3,150,10,75,
52,NT-proBNP/ST2,NS,2,25,#2F4F4F,SampleAndBSAndProbeSubstance,10,10,3,150,12,75,
54,Troponin T,TT,1,25,#008080,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,
55,BNP,BP,1,25,#48D1CC,SampleAndBSAndProbeSubstance,35,35,3,150,12,75,

119
src/main/resources/templates/optfilemgr/index.html

@ -0,0 +1,119 @@
<!-- src/main/resources/templates/optfilemgr/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>光学报告管理</title>
<link href="/background/js/bootstrap.min.css" rel="stylesheet">
<style>
body {
padding: 20px;
}
h1 {
margin-bottom: 20px;
}
.download-title {
font-size: 2em;
color: #007bff;
text-align: left;
margin-bottom: 30px;
}
table {
width: 100%;
margin-bottom: 20px;
}
th, td {
padding: 10px;
text-align: left;
}
th {
background-color: #f8f9fa;
}
</style>
</head>
<body>
<div class="container">
<h1 class="download-title">光学报告管理</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>文件名称</th>
<th>下载</th>
<th>导出</th>
</tr>
</thead>
<tbody th:each="group : ${fileGroups}">
<tr th:each="file : ${group.files}">
<td th:text="${file.name}"></td>
<td>
<a th:href="@{'/optfilemgr/download/' + ${file.filePath}}"
class="btn btn-outline-primary download-link">下载</a>
</td>
<td>
<button class="btn btn-outline-secondary export-link" th:data-filepath="${file.filePath}">导出</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Notification Modal -->
<div class="modal fade" id="notificationModal" tabindex="-1" role="dialog" aria-labelledby="notificationModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="notificationModalLabel">通知</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="notificationModalContent">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<script src="/background/js/jquery-3.5.1.min.js"></script>
<script src="/background/js/bootstrap.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var downloadLinks = document.querySelectorAll('.download-link');
downloadLinks.forEach(function (link) {
link.addEventListener('click', function () {
$('#notificationModalContent').text('文件下载成功');
$('#notificationModal').modal('show');
});
});
var exportLinks = document.querySelectorAll('.export-link');
exportLinks.forEach(function (link) {
link.addEventListener('click', function () {
var filePath = link.getAttribute('data-filepath');
fetch('/optfilemgr/export/' + filePath, {
method: 'GET'
})
.then(response => response.json())
.then(data => {
var formattedJson = JSON.stringify(data, null, 2);
$('#notificationModalContent').html('<pre>' + formattedJson + '</pre>');
$('#notificationModal').modal('show');
})
.catch(error => {
console.error('Error:', error);
});
});
});
});
</script>
</body>
</html>
Loading…
Cancel
Save