From 7401fe1beecbbd329a17d76f27738bc92ba88747 Mon Sep 17 00:00:00 2001 From: linjj <850658129@qq.com> Date: Mon, 26 Jan 2026 12:33:04 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9C=81=E5=8F=A3=E8=85=94=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 33 +++ pom.xml | 107 ++++++++ .../record/RecordSystemApplication.java | 13 + .../client/MedicalRecordHttpClient.java | 231 ++++++++++++++++++ .../medical/record/config/SwaggerConfig.java | 19 ++ .../controller/MedicalRecordController.java | 125 ++++++++++ .../com/medical/record/dto/AuthResponse.java | 43 ++++ .../record/dto/MedicalAttachmentFile.java | 91 +++++++ .../medical/record/dto/MedicalRecordData.java | 154 ++++++++++++ .../record/dto/MedicalRecordException.java | 7 + .../medical/record/dto/MedicalRecordXml.java | 39 +++ .../medical/record/dto/UploadResponse.java | 47 ++++ src/main/resources/application.yml | 71 ++++++ src/main/resources/logback-spring.xml | 87 +++++++ src/main/resources/static/index.html | 6 + .../record/RecordSystemApplicationTests.java | 13 + 16 files changed, 1086 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/medical/record/RecordSystemApplication.java create mode 100644 src/main/java/com/medical/record/client/MedicalRecordHttpClient.java create mode 100644 src/main/java/com/medical/record/config/SwaggerConfig.java create mode 100644 src/main/java/com/medical/record/controller/MedicalRecordController.java create mode 100644 src/main/java/com/medical/record/dto/AuthResponse.java create mode 100644 src/main/java/com/medical/record/dto/MedicalAttachmentFile.java create mode 100644 src/main/java/com/medical/record/dto/MedicalRecordData.java create mode 100644 src/main/java/com/medical/record/dto/MedicalRecordException.java create mode 100644 src/main/java/com/medical/record/dto/MedicalRecordXml.java create mode 100644 src/main/java/com/medical/record/dto/UploadResponse.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/logback-spring.xml create mode 100644 src/main/resources/static/index.html create mode 100644 src/test/java/com/medical/record/RecordSystemApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dba8955 --- /dev/null +++ b/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.18 + + + + com.medical + record-system + 1.0.0 + + + 1.8 + 3.5.3.2 + 4.5.14 + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springdoc + springdoc-openapi-ui + 1.7.0 + + + + + + com.microsoft.sqlserver + mssql-jdbc + 9.4.1.jre8 + + + + + org.slf4j + slf4j-api + 1.7.36 + + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + + org.apache.httpcomponents + httpmime + 4.5.14 + + + + + + org.projectlombok + lombok + true + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/src/main/java/com/medical/record/RecordSystemApplication.java b/src/main/java/com/medical/record/RecordSystemApplication.java new file mode 100644 index 0000000..ea7fa07 --- /dev/null +++ b/src/main/java/com/medical/record/RecordSystemApplication.java @@ -0,0 +1,13 @@ +package com.medical.record; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.medical.record.mapper") // 扫描Mapper接口 +public class RecordSystemApplication { + public static void main(String[] args) { + SpringApplication.run(RecordSystemApplication.class, args); + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/client/MedicalRecordHttpClient.java b/src/main/java/com/medical/record/client/MedicalRecordHttpClient.java new file mode 100644 index 0000000..8ede346 --- /dev/null +++ b/src/main/java/com/medical/record/client/MedicalRecordHttpClient.java @@ -0,0 +1,231 @@ +package com.medical.record.client; + +import com.medical.record.controller.MedicalRecordController; +import com.medical.record.dto.*; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.BufferedHttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * 历史病案数据对接客户端(JDK 1.8 + Apache HttpClient) + * 请求方式:POST multipart/form-data + */ +public class MedicalRecordHttpClient { + + private final ObjectMapper jsonMapper; + private final XmlMapper xmlMapper; + private final String baseUrl; + private final CloseableHttpClient httpClient; + + // 创建SLF4J Logger实例 + private static final Logger log = LoggerFactory.getLogger(MedicalRecordHttpClient.class); + + public MedicalRecordHttpClient(String baseUrl) { + this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; + this.jsonMapper = new ObjectMapper(); + + /* ===== 空值也输出 XML 标签 ===== */ + this.xmlMapper = XmlMapper.builder() + .defaultUseWrapper(false) // 保持原设置 + .serializationInclusion(JsonInclude.Include.ALWAYS) // 1. 输出 null + .build(); + // 2. 把 null 映射成空串,避免 xsi:nil + this.xmlMapper.configOverride(String.class) + .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); + /* ===== 空值也输出 XML 标签 ===== */ + + this.httpClient = HttpClients.createDefault(); + } + + /** + * 【POST multipart/form-data】获取认证SID + */ + public String getSid(String accessKey) throws IOException, MedicalRecordException { + String url = baseUrl + "apps/com.itmppaas.user.apps.dzblgd/medicalRecord/getSidByAccessKey"; + log.info("url::::::::"+url); + HttpPost httpPost = new HttpPost(url); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("accessKey", accessKey, ContentType.TEXT_PLAIN); + + httpPost.setEntity(builder.build()); + + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String result = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + + if (statusCode != 200) { + throw new MedicalRecordException("认证请求失败, HTTP状态码: " + statusCode); + } + + AuthResponse authResponse = jsonMapper.readValue(result, AuthResponse.class); + + if (!"ok".equals(authResponse.getResult())) { + throw new MedicalRecordException("认证失败: " + authResponse.getMsg()); + } + + return authResponse.getData(); + } + } + + /** + * 【POST multipart/form-data】上传病案数据 + */ + public String uploadMedicalRecord(String sid, MedicalRecordXml medicalRecordXml, Path zipFile) + throws IOException, MedicalRecordException { + + if (!Files.exists(zipFile)) { + throw new IllegalArgumentException("ZIP文件不存在: " + zipFile); + } + + String url = baseUrl + "apps/com.itmppaas.user.apps.dzblgd/medicalRecord/saveMedicalRecordHistoryData"; + HttpPost httpPost = new HttpPost(url); + + + /* 把 XML 对象序列化成字符串 */ + String xmlContent = xmlMapper.writeValueAsString(medicalRecordXml); + + /* 保存到本地(可选,调试时打开) */ + Path xmlPath = Paths.get("medicalRecord.xml"); // 可改成绝对路径 + Files.write(xmlPath, + xmlContent.getBytes(StandardCharsets.UTF_8), + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + + + //把 XML 对象序列化成字节数组,准备当“文件”传 */ + byte[] xmlBytes = xmlMapper.writeValueAsBytes(medicalRecordXml); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addTextBody("sid", sid, ContentType.TEXT_PLAIN); + builder.addBinaryBody("xml", xmlBytes, + ContentType.create("application/xml"), + "medicalRecord.xml"); + builder.addBinaryBody("zip", zipFile.toFile(), + ContentType.create("application/zip"), + zipFile.getFileName().toString()); + + + + + // 1. 先 build 实体 + HttpEntity rawEntity = builder.build(); + + // 2. 包成可重复读实体,这样后面真正发请求时还能再用 + BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(rawEntity); + + // 3. 输出到内存缓冲区 + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + bufferedEntity.writeTo(buf); // 不会把流弄空 + String multipartTxt = buf.toString(String.valueOf(StandardCharsets.UTF_8)); + + // 4. 用 log 打印(slf4j 的 info 级别) + log.info("---------- multipart 原文本 ----------\n{}", multipartTxt); + + // 5. 再放回请求,正常发 + httpPost.setEntity(bufferedEntity); + + +// httpPost.setEntity(builder.build()); + + + + + + + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String result = EntityUtils.toString(response.getEntity()); + int statusCode = response.getStatusLine().getStatusCode(); + + if (statusCode != 200) { + throw new MedicalRecordException("上传请求失败, HTTP状态码: " + statusCode); + } + + UploadResponse uploadResponse = jsonMapper.readValue(result, UploadResponse.class); + + if (!"ok".equals(uploadResponse.getResult())) { + throw new MedicalRecordException("上传失败: " + uploadResponse.getMsg()); + } + + return uploadResponse.getData().getRecordId(); + } + } + + /** + * 将多个图像打包成ZIP + */ + public static Path packageImagesToZip(List imagePaths, Path outputZipPath) + throws IOException, MedicalRecordException { + + for (Path imagePath : imagePaths) { + if (!Files.exists(imagePath)) { + throw new MedicalRecordException("图像文件不存在: " + imagePath); + } + } + + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outputZipPath.toFile()))) { + byte[] buffer = new byte[8192]; + + for (Path imagePath : imagePaths) { + ZipEntry zipEntry = new ZipEntry(imagePath.getFileName().toString()); + zipEntry.setSize(Files.size(imagePath)); + zos.putNextEntry(zipEntry); + + try (FileInputStream fis = new FileInputStream(imagePath.toFile())) { + int len; + while ((len = fis.read(buffer)) > 0) { + zos.write(buffer, 0, len); + } + } + + zos.closeEntry(); + } + } + + return outputZipPath; + } + + /** + * MD5工具方法 + */ + public static String calculateMD5(Path filePath) throws IOException { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] fileBytes = Files.readAllBytes(filePath); + byte[] digest = md.digest(fileBytes); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("MD5算法不可用", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/config/SwaggerConfig.java b/src/main/java/com/medical/record/config/SwaggerConfig.java new file mode 100644 index 0000000..8305990 --- /dev/null +++ b/src/main/java/com/medical/record/config/SwaggerConfig.java @@ -0,0 +1,19 @@ +package com.medical.record.config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .info(new Info() + .title("同步接口") + .version("1.0") + .description("同步接口系统接口文档")); + } +} diff --git a/src/main/java/com/medical/record/controller/MedicalRecordController.java b/src/main/java/com/medical/record/controller/MedicalRecordController.java new file mode 100644 index 0000000..837d6f5 --- /dev/null +++ b/src/main/java/com/medical/record/controller/MedicalRecordController.java @@ -0,0 +1,125 @@ +package com.medical.record.controller; + +import com.medical.record.client.MedicalRecordHttpClient; +import com.medical.record.dto.MedicalAttachmentFile; +import com.medical.record.dto.MedicalRecordData; +import com.medical.record.dto.MedicalRecordException; +import com.medical.record.dto.MedicalRecordXml; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +@RestController +@RequestMapping("/api/record") +@Tag(name = "同步接口接口") +public class MedicalRecordController { + // 创建SLF4J Logger实例 + private static final Logger log = LoggerFactory.getLogger(MedicalRecordController.class); + + + /** + * 同步病案数据到第三方系统、 + * 测试版本 图像需要在实际业务中动态获取 + */ + @PostMapping("/sync") + @Operation(summary = "获取影像记录", description = "获取影像记录") + public String syncMedicalRecord(@RequestParam String accessKey) { + Path zipFile = null; + try { + // 1. 初始化HTTP客户端 + MedicalRecordHttpClient httpClient = new MedicalRecordHttpClient("http://172.16.1.133/emras"); + + // 2. 获取SID + String sid = httpClient.getSid(accessKey); + log.info("sid:::::::::::::::::"+sid); + // 3. 准备图像文件(实际业务中动态获取) + List imagePaths = new ArrayList<>(); + imagePaths.add(Paths.get("D:/test/image1.jpg")); + imagePaths.add(Paths.get("D:/test/image2.jpg")); + // 4. 打包成ZIP + zipFile = Paths.get("D:/temp/upload_" + System.currentTimeMillis() + ".zip"); + MedicalRecordHttpClient.packageImagesToZip(imagePaths, zipFile); + + // 5. 构建附件信息 + List fileList = new ArrayList<>(); + for (Path img : imagePaths) { + MedicalAttachmentFile file = new MedicalAttachmentFile(); + file.setFileName(img.getFileName().toString()); + file.setFileSize(Files.size(img)); + file.setFileSuffix(getExtension(img)); + file.setMd5(MedicalRecordHttpClient.calculateMD5(img)); + file.setCatalogue("病历首页"); + file.setCatalogueId("C6A8308D842B450FB9FA0D21762237AB"); + file.setCode("CODE_" + System.currentTimeMillis()); + file.setTimeStapPrice(String.valueOf(System.currentTimeMillis())); + fileList.add(file); + } + + // 6. 构建病人信息 + MedicalRecordData data = new MedicalRecordData(); + data.setNumber("BA" + System.currentTimeMillis()); + data.setSickName("测试患者"); + data.setSerialNumber("SN" + System.currentTimeMillis()); + data.setInHospitalNumber(1); + data.setInSection("影像科"); + data.setInSectionId(" "); + data.setOutSection("影像科"); + data.setOutSectionId(" "); + data.setAttendingPhysician(" "); + data.setAttendingPhysicianId(" "); + data.setIdentityCard(" "); + data.setInHospitalDate("2024-01-20 08:00:00"); + data.setOutHospitalDate("2024-01-20 10:30:00"); + + + // 7. 构建XML对象 + MedicalRecordXml xml = + new MedicalRecordXml(fileList, data); + + // 8. 上传第三方系统 + String recordId = httpClient.uploadMedicalRecord(sid, xml, zipFile); + + + // 9 清理临时文件 + Files.deleteIfExists(zipFile); + + return "同步成功!病案ID: " + recordId; + + } catch (MedicalRecordException e) { + log.error("业务异常: {}", e.getMessage(), e); + return "同步失败(业务异常): " + e.getMessage(); + } catch (IOException e) { + log.error("IO异常: {}", e.getMessage(), e); + return "同步失败(IO异常): " + e.getMessage(); + } catch (Exception e) { + log.error("未知异常: {}", e.getMessage(), e); + return "同步失败(未知异常): " + e.getMessage(); + } + finally { + if (zipFile != null) { + try { + Files.deleteIfExists(zipFile); + log.debug("临时文件在finally中已清理"); + } catch (IOException e) { + log.warn("清理临时文件失败: {}", e.getMessage()); + } + } + } + } + + private String getExtension(Path path) { + String name = path.getFileName().toString(); + int i = name.lastIndexOf('.'); + return i > 0 ? name.substring(i + 1) : ""; + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/AuthResponse.java b/src/main/java/com/medical/record/dto/AuthResponse.java new file mode 100644 index 0000000..9d0727d --- /dev/null +++ b/src/main/java/com/medical/record/dto/AuthResponse.java @@ -0,0 +1,43 @@ +package com.medical.record.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class AuthResponse { + private String msg; + private String result; + private String data; + private Integer code; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/MedicalAttachmentFile.java b/src/main/java/com/medical/record/dto/MedicalAttachmentFile.java new file mode 100644 index 0000000..60930a5 --- /dev/null +++ b/src/main/java/com/medical/record/dto/MedicalAttachmentFile.java @@ -0,0 +1,91 @@ +package com.medical.record.dto; + +public class MedicalAttachmentFile { + private String fileName; + private Long fileSize; + private String fileSuffix; + private String md5; + private String catalogue; + private String catalogueId; + + private String code; + private String timeStapPrice; + + public MedicalAttachmentFile() {} + + public MedicalAttachmentFile(String fileName, Long fileSize, String fileSuffix, String md5, + String catalogue, String catalogueId) { + this.fileName = fileName; + this.fileSize = fileSize; + this.fileSuffix = fileSuffix; + this.md5 = md5; + this.catalogue = catalogue; + this.catalogueId = catalogueId; + } + + // Getters and Setters + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Long getFileSize() { + return fileSize; + } + + public void setFileSize(Long fileSize) { + this.fileSize = fileSize; + } + + public String getFileSuffix() { + return fileSuffix; + } + + public void setFileSuffix(String fileSuffix) { + this.fileSuffix = fileSuffix; + } + + public String getMd5() { + return md5; + } + + public void setMd5(String md5) { + this.md5 = md5; + } + + public String getCatalogue() { + return catalogue; + } + + public void setCatalogue(String catalogue) { + this.catalogue = catalogue; + } + + public String getCatalogueId() { + return catalogueId; + } + + public void setCatalogueId(String catalogueId) { + this.catalogueId = catalogueId; + } + + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getTimeStapPrice() { + return timeStapPrice; + } + + public void setTimeStapPrice(String timeStapPrice) { + this.timeStapPrice = timeStapPrice; + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/MedicalRecordData.java b/src/main/java/com/medical/record/dto/MedicalRecordData.java new file mode 100644 index 0000000..5c87817 --- /dev/null +++ b/src/main/java/com/medical/record/dto/MedicalRecordData.java @@ -0,0 +1,154 @@ +package com.medical.record.dto; + +public class MedicalRecordData { + + /** 病案号 */ + private String number; + + /** 患者姓名 */ + private String sickName; + + /** 流水号 */ + private String serialNumber; + + /** 住院次数 */ + private Integer inHospitalNumber; + + /** 入院科室 */ + private String inSection; + + /** 入院科室id */ + private String inSectionId; + + /** 出院科室 */ + private String outSection; + + /** 出院科室ID(非必填) */ + private String outSectionId; + + + /** 主治医生(非必填) */ + private String attendingPhysician; + + /** 主治医生ID(非必填) */ + private String attendingPhysicianId; + + /** 身份证号(非必填) */ + private String identityCard; + + + /** 入院时间,格式:yyyy-MM-dd HH:mm:ss */ + private String inHospitalDate; + + /** 出院时间,格式:yyyy-MM-dd HH:mm:ss */ + private String outHospitalDate; + + + + public String getAttendingPhysician() { + return attendingPhysician; + } + + public void setAttendingPhysician(String attendingPhysician) { + this.attendingPhysician = attendingPhysician; + } + + public String getAttendingPhysicianId() { + return attendingPhysicianId; + } + + public void setAttendingPhysicianId(String attendingPhysicianId) { + this.attendingPhysicianId = attendingPhysicianId; + } + + public String getIdentityCard() { + return identityCard; + } + + public void setIdentityCard(String identityCard) { + this.identityCard = identityCard; + } + + public String getOutSectionId() { + return outSectionId; + } + + public String getInSectionId() { + return inSectionId; + } + + public void setInSectionId(String inSectionId) { + this.inSectionId = inSectionId; + } + + public void setOutSectionId(String outSectionId) { + this.outSectionId = outSectionId; + } + + + + // Getters and Setters + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public String getSickName() { + return sickName; + } + + public void setSickName(String sickName) { + this.sickName = sickName; + } + + public String getSerialNumber() { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + public Integer getInHospitalNumber() { + return inHospitalNumber; + } + + public void setInHospitalNumber(Integer inHospitalNumber) { + this.inHospitalNumber = inHospitalNumber; + } + + public String getInSection() { + return inSection; + } + + public void setInSection(String inSection) { + this.inSection = inSection; + } + + public String getOutSection() { + return outSection; + } + + public void setOutSection(String outSection) { + this.outSection = outSection; + } + + public String getInHospitalDate() { + return inHospitalDate; + } + + public void setInHospitalDate(String inHospitalDate) { + this.inHospitalDate = inHospitalDate; + } + + public String getOutHospitalDate() { + return outHospitalDate; + } + + public void setOutHospitalDate(String outHospitalDate) { + this.outHospitalDate = outHospitalDate; + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/MedicalRecordException.java b/src/main/java/com/medical/record/dto/MedicalRecordException.java new file mode 100644 index 0000000..2809eff --- /dev/null +++ b/src/main/java/com/medical/record/dto/MedicalRecordException.java @@ -0,0 +1,7 @@ +package com.medical.record.dto; + +public class MedicalRecordException extends Exception { + public MedicalRecordException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/MedicalRecordXml.java b/src/main/java/com/medical/record/dto/MedicalRecordXml.java new file mode 100644 index 0000000..146143a --- /dev/null +++ b/src/main/java/com/medical/record/dto/MedicalRecordXml.java @@ -0,0 +1,39 @@ +package com.medical.record.dto; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.List; + +@JacksonXmlRootElement(localName = "datas") +public class MedicalRecordXml { + @JacksonXmlProperty(localName = "file") + @JacksonXmlElementWrapper(useWrapping = false) + private List files; + + @JacksonXmlProperty(localName = "data") + private MedicalRecordData data; + + public MedicalRecordXml() {} + + public MedicalRecordXml(List files, MedicalRecordData data) { + this.files = files; + this.data = data; + } + + public List getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = files; + } + + public MedicalRecordData getData() { + return data; + } + + public void setData(MedicalRecordData data) { + this.data = data; + } +} \ No newline at end of file diff --git a/src/main/java/com/medical/record/dto/UploadResponse.java b/src/main/java/com/medical/record/dto/UploadResponse.java new file mode 100644 index 0000000..945cf1a --- /dev/null +++ b/src/main/java/com/medical/record/dto/UploadResponse.java @@ -0,0 +1,47 @@ +package com.medical.record.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UploadResponse { + private String msg; + private String result; + private RecordData data; + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public RecordData getData() { + return data; + } + + public void setData(RecordData data) { + this.data = data; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class RecordData { + private String recordId; + + public String getRecordId() { + return recordId; + } + + public void setRecordId(String recordId) { + this.recordId = recordId; + } + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..5c6d5dc --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,71 @@ +server: + port: 8891 + +spring: + datasource: + driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver + url: jdbc:sqlserver://localhost:1433;databaseName=medical_record_db;encrypt=true;trustServerCertificate=true; + username: SA + password: YourStrong@Passw0rd + hikari: + minimum-idle: 5 + maximum-pool-size: 15 + auto-commit: true + connection-timeout: 30000 + idle-timeout: 300000 + max-lifetime: 1200000 + +# MyBatis-Plus配置 +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + mapper-locations: classpath*:/mapper/**/*.xml + type-aliases-package: com.medical.record.entity + global-config: + db-config: + id-type: auto + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 +# ========================================== +# SLF4J + Logback 日志配置 +# ========================================== +logging: + # 日志级别 + level: + root: INFO + com.medical.record: DEBUG + com.medical.record.client: DEBUG # 第三方接口调用日志 + com.medical.record.service: DEBUG + com.medical.record.mapper: DEBUG # SQL日志 + org.springframework.web: INFO + org.apache.http: INFO + com.baomidou.mybatisplus: INFO + + # 控制台输出格式 + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{50}] - %msg%n" + file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{50}] - %msg%n" + + # 文件输出配置 + file: + # 日志文件路径(生产环境必须配置) + path: D:/logs/medical-record + name: ${logging.file.path}/medical-record.log + # 日志文件大小限制 + max-size: 100MB + # 保留天数 + max-history: 30 + # 总大小限制(达到后自动清理) + total-size-cap: 3GB + + # 日志分组(便于管理) + group: + medical: + - "com.medical.record" + - "com.medical.record.controller" + - "com.medical.record.service" + external: + - "org.apache.http" + - "com.medical.record.client" \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..9424164 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{50}] - %msg%n + UTF-8 + + + + + + ${LOG_FILE} + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{50}] - %msg%n + UTF-8 + + + + ${LOG_PATH}/medical-record.%d{yyyy-MM-dd}.%i.log + + ${MAX_HISTORY} + + ${TOTAL_SIZE_CAP} + + + ${MAX_FILE_SIZE} + + + + + + + ${LOG_PATH}/medical-record-error.log + + ERROR + ACCEPT + DENY + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{50}] - %msg%n + UTF-8 + + + ${LOG_PATH}/medical-record-error.%d{yyyy-MM-dd}.%i.log + ${MAX_HISTORY} + + ${MAX_FILE_SIZE} + + + + + + + + 512 + 0 + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..89bb8ba --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,6 @@ + + +

hello word!!!

+

this is a html page

+ + \ No newline at end of file diff --git a/src/test/java/com/medical/record/RecordSystemApplicationTests.java b/src/test/java/com/medical/record/RecordSystemApplicationTests.java new file mode 100644 index 0000000..f4c43f6 --- /dev/null +++ b/src/test/java/com/medical/record/RecordSystemApplicationTests.java @@ -0,0 +1,13 @@ +package com.medical.record; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RecordSystemApplicationTests { + + @Test + void contextLoads() { + } + +}