commit 7401fe1beecbbd329a17d76f27738bc92ba88747
Author: linjj <850658129@qq.com>
Date: Mon Jan 26 12:33:04 2026 +0800
省口腔同步需求
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() {
+ }
+
+}