Compare commits

..

28 Commits

Author SHA1 Message Date
97aa3efef6 新增检验报告打印接口 2025-06-25 10:01:50 +08:00
25597dcfc9 小票门诊缴费模板优化 2025-06-19 18:26:40 +08:00
3bc83f07db 后端地址改为正式 2025-06-19 17:36:01 +08:00
9740a85f65 Merge remote-tracking branch 'origin/2.0' into 2.0 2025-06-19 16:21:48 +08:00
7b5ca7edfc 医保动态库 2025-06-19 16:21:25 +08:00
4fc1335cc8 微信刷脸 2025-06-19 11:25:10 +08:00
40f6728cea 配置文件 2025-06-19 11:23:46 +08:00
20ac1e4bb3 微信刷脸 金额单位 2025-06-19 11:22:54 +08:00
9c990e8103 微信刷脸 金额单位 2025-06-19 10:52:48 +08:00
8728b62a47 微信刷脸 金额单位 2025-06-19 10:51:23 +08:00
7b75ce8438 医保及配置更新 2025-06-19 10:29:55 +08:00
73fb4f18ff 更新配置 2025-06-19 10:21:36 +08:00
5e3c75d227 更新配置 2025-06-19 10:04:55 +08:00
5071814758 中医院配置 2025-06-19 09:22:55 +08:00
8c47f5b204 中医院配置 2025-06-19 09:22:19 +08:00
09407c70c7 小票模板优化 2025-06-18 18:41:14 +08:00
4da90e9a04 小票缴费模板优化 2025-06-18 18:29:00 +08:00
55bcca0dff 医保预结算优化 2025-06-18 17:34:06 +08:00
1904cec8f8 后端项目访问地址 2025-06-18 10:38:59 +08:00
60019a4283 支付宝刷脸完善 2025-06-17 16:20:27 +08:00
9e7fc2d5a2 Merge branch 'refs/heads/1.0' into 2.0 2025-06-17 16:00:26 +08:00
547bdb6d08 医保调用修改 2025-06-17 15:59:09 +08:00
235306ae33 医保调用形式修改 2025-06-17 14:51:57 +08:00
789d0d17cb 医保结算参数优化 2025-06-17 09:12:01 +08:00
26e504232e 更新医保入参 2025-06-13 14:59:23 +08:00
367429587f 更新医保入参 2025-06-13 13:48:08 +08:00
1343d01478 电子医保凭证支付 2025-06-13 09:49:23 +08:00
c6e3d65245 小票缴费模板添加医保 2025-06-12 18:33:26 +08:00
29 changed files with 603 additions and 316 deletions

53
pom.xml
View File

@@ -4,7 +4,6 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.dpkj</groupId> <groupId>com.dpkj</groupId>
<!-- 银医通-澜沧中医院-DLL-台式机 -->
<artifactId>yinyitong-dll-stand</artifactId> <artifactId>yinyitong-dll-stand</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<name>yinyitong-dll-stand</name> <name>yinyitong-dll-stand</name>
@@ -18,7 +17,7 @@
</parent> </parent>
<properties> <properties>
<java.version>1.8</java.version> <java.version>11</java.version>
<hutool.version>5.8.36</hutool.version> <hutool.version>5.8.36</hutool.version>
<jna.version>5.17.0</jna.version> <jna.version>5.17.0</jna.version>
<pdfbox.version>3.0.2</pdfbox.version> <pdfbox.version>3.0.2</pdfbox.version>
@@ -160,22 +159,42 @@
<groupId>jakarta.xml.bind</groupId> <groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId> <artifactId>jakarta.xml.bind-api</artifactId>
</dependency> </dependency>
<!-- 报告打印转PDF -->
<!-- iText 核心 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- XML Worker (HTML 转 PDF) -->
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.3</version>
</dependency>
<!-- 中文字体支持 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<!--打包时将resource下的文件一起打包--> <!-- <resources>
<resources> <resource>
<resource> <directory>src/main/resources</directory>
<directory>src/main/resources</directory> <filtering>false</filtering>
<includes> <includes>
<include>**/**</include> <include>**/**</include>
</includes> </includes>
<filtering>false</filtering> </resource>
</resource> </resources>-->
</resources>
<plugins> <plugins>
<plugin> <plugin>
@@ -278,14 +297,20 @@
<profiles> <profiles>
<profile> <profile>
<id>dev</id> <id>dev</id>
<activation>
<!--默认激活配置-->
<activeByDefault>true</activeByDefault>
</activation>
<properties> <properties>
<!--测试环境-->
<profile.name>dev</profile.name>
</properties> </properties>
</profile> </profile>
<profile> <profile>
<id>pro</id> <id>pro</id>
<properties> <properties>
<!--正式环境-->
<profile.name>pro</profile.name>
</properties> </properties>
</profile> </profile>
</profiles> </profiles>

View File

@@ -0,0 +1,59 @@
package com.dpkj.modules.chs.constant;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: 萧道子
* @Date: 2025/6/18 15:57
* @Description: 医保状态记录常量类
*/
public class ChsPayStateConst {
private static Map<String, Integer> chsPayState = new HashMap<String, Integer>(1);
/**
* 清除所有
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void clear() {
chsPayState.clear();
}
/**
* 按key删除
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void remove(String key) {
chsPayState.remove(key);
}
/**
* 添加
*
* @return void
* @author 萧道子 2025/6/18
*/
public static void put(String key, Integer val) {
chsPayState.put(key, val);
}
/**
* 获取
*
* @return void
* @author 萧道子 2025/6/18
*/
public static Integer get(String key) {
return chsPayState.get(key);
}
}

View File

@@ -1,20 +1,8 @@
package com.dpkj.modules.chs.controller; package com.dpkj.modules.chs.controller;
import cn.hutool.core.lang.Console;
import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.config.ChsConfig;
import com.dpkj.common.constant.ChsConst;
import com.dpkj.common.vo.Result;
import com.dpkj.modules.chs.dll.AlipayDll;
import com.dpkj.modules.chs.entity.AlipayEcRequestData;
import com.dpkj.modules.chs.service.IAlipayService; import com.dpkj.modules.chs.service.IAlipayService;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -28,54 +16,6 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@RequestMapping("/chs/alipay") @RequestMapping("/chs/alipay")
public class AlipayController { public class AlipayController {
private final IAlipayService alipayService; private final IAlipayService alipayService;
private final ChsConfig charsConfig;
@GetMapping("test")
public Result<?> test() {
try {
AlipayDll.Dll dll = AlipayDll.instance();
// Native.load("libeay32", AlipayDll.Dll.class);
// Native.load("ssleay32", AlipayDll.Dll.class);
JSONObject data = new JSONObject();
AlipayEcRequestData alipayEcRequestData = new AlipayEcRequestData()
.setOrgId(charsConfig.getOrgcode())
.setTransType(ChsConst.APITYPE_DECODE)
.setData(data);
String dataJson = JSONObject.toJSONString(alipayEcRequestData);
Pointer resultStr = new Memory(1024 * 10);
String rs = dll.NationEcTrans(
"http://172.16.11.13:5946/api/chs/qrCodeQuery",
dataJson,
resultStr
);
String rsStrString = resultStr.getString(0, "GB18030");
Console.log(rsStrString);
Console.log(rs);
return Result.ok("成功", rsStrString);
} catch (Exception e) {
e.printStackTrace();
return Result.error("失败");
}
}
@PostMapping("qrCodeQuery")
public Result<?> qrCodeQuery(@RequestBody JSONObject data) {
try {
Console.log(data);
return Result.ok("成功", null);
} catch (Exception e) {
e.printStackTrace();
return Result.error("失败");
}
}
} }

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.vo.Result; import com.dpkj.common.vo.Result;
import com.dpkj.common.vo.ResultData; import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.constant.ChsPayStateConst;
import com.dpkj.modules.chs.service.IHispayService; import com.dpkj.modules.chs.service.IHispayService;
import com.dpkj.modules.chs.vo.OutpatientBeginModel; import com.dpkj.modules.chs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.vo.OutpatientFinalModel; import com.dpkj.modules.chs.vo.OutpatientFinalModel;
@@ -26,7 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/chs/hispay") @RequestMapping("/chs/hispay")
public class HispayController { public class HispayController {
private final IHispayService iHispayService; private final IHispayService hispayService;
/** /**
@@ -38,7 +39,7 @@ public class HispayController {
@PostMapping("findReadCode") @PostMapping("findReadCode")
public Result<?> findReadCode() { public Result<?> findReadCode() {
try { try {
JSONObject res = iHispayService.readCode(); JSONObject res = hispayService.readCode();
return Result.ok("成功", res); return Result.ok("成功", res);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -63,7 +64,7 @@ public class HispayController {
throw new RuntimeException("密码不可为空"); throw new RuntimeException("密码不可为空");
} }
JSONObject res = iHispayService.readCard(password); JSONObject res = hispayService.readCard(password);
return Result.ok("成功", res); return Result.ok("成功", res);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -83,8 +84,11 @@ public class HispayController {
@PostMapping("chsCodeAsOutpatientBegin") @PostMapping("chsCodeAsOutpatientBegin")
public Result<?> chsCodeAsOutpatientBegin(@RequestBody @Validated OutpatientBeginModel data) { public Result<?> chsCodeAsOutpatientBegin(@RequestBody @Validated OutpatientBeginModel data) {
try { try {
// 清空状态常量
ChsPayStateConst.clear();
log.info("[HispayController][chsCodeAsOutpatientBegin][门诊缴费-预算-电子医保凭证] 参数:{}", data); log.info("[HispayController][chsCodeAsOutpatientBegin][门诊缴费-预算-电子医保凭证] 参数:{}", data);
ResultData res = iHispayService.chsCodeAsOutpatientBegin(data); ResultData res = hispayService.chsCodeAsOutpatientBegin(data);
return Result.ok("成功", res); return Result.ok("成功", res);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -105,7 +109,7 @@ public class HispayController {
public Result<?> chsCodeAsOutpatientFinal(@RequestBody @Validated OutpatientFinalModel data) { public Result<?> chsCodeAsOutpatientFinal(@RequestBody @Validated OutpatientFinalModel data) {
try { try {
log.info("[HispayController][chsCodeAsOutpatientFinal][门诊缴费-结算-电子医保凭证] 参数:{}", data); log.info("[HispayController][chsCodeAsOutpatientFinal][门诊缴费-结算-电子医保凭证] 参数:{}", data);
ResultData res = iHispayService.chsCodeAsOutpatientFinal(data); ResultData res = hispayService.chsCodeAsOutpatientFinal(data);
return Result.ok("成功", res); return Result.ok("成功", res);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -114,4 +118,20 @@ public class HispayController {
} }
} }
/**
* 获取医保支付状态
*
* @return com.dpkj.common.vo.Result<?>
* @author 萧道子 2025/6/18
*/
@PostMapping("getChsPayState")
public Result<?> getChsPayState(@RequestBody OutpatientBeginModel data) {
String no = data.getPrescriptionNo();
if (StrUtil.isEmpty(no)) {
return Result.error("收据号不可为空");
}
Integer num = ChsPayStateConst.get(no);
return Result.ok("成功", num);
}
} }

View File

@@ -43,5 +43,4 @@ public interface IHispayService {
*/ */
ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data); ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data);
} }

View File

@@ -1,6 +1,5 @@
package com.dpkj.modules.chs.service.impl; package com.dpkj.modules.chs.service.impl;
import cn.hutool.core.lang.Console;
import com.dpkj.modules.chs.dll.AlipayDll; import com.dpkj.modules.chs.dll.AlipayDll;
import com.dpkj.modules.chs.service.IAlipayService; import com.dpkj.modules.chs.service.IAlipayService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -17,22 +16,22 @@ import javax.annotation.PostConstruct;
@Service @Service
public class AlipayServiceImpl implements IAlipayService { public class AlipayServiceImpl implements IAlipayService {
private AlipayDll.Dll dll = AlipayDll.instance(); private AlipayDll.Dll dll;
public AlipayServiceImpl() throws AlipayDll.DllRegistrationException {
}
@PostConstruct @PostConstruct
public void postConstruct() { public void postConstruct() {
log.info("[AlipayServiceImpl][postConstruct][医保DLL] 初始化动态链接库"); log.info("[AlipayServiceImpl][postConstruct][医保DLL] 初始化动态链接库");
try {
dll = AlipayDll.instance();
} catch (AlipayDll.DllRegistrationException e) {
// TODO 萧道子 2025/6/19 :
}
initPrinter(); initPrinter();
} }
private void initPrinter() { private void initPrinter() {
Console.log(dll);
} }
} }

View File

@@ -7,20 +7,20 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.dpkj.common.config.ChsConfig; import com.dpkj.common.config.ChsConfig;
import com.dpkj.common.config.HisConfig; import com.dpkj.common.config.HisConfig;
import com.dpkj.common.utils.IDGenerator;
import com.dpkj.common.vo.ResultData; import com.dpkj.common.vo.ResultData;
import com.dpkj.modules.chs.constant.ChsPayStateConst;
import com.dpkj.modules.chs.service.IHispayService; import com.dpkj.modules.chs.service.IHispayService;
import com.dpkj.modules.chs.vo.OutpatientBeginModel; import com.dpkj.modules.chs.vo.OutpatientBeginModel;
import com.dpkj.modules.chs.vo.OutpatientFinalModel; import com.dpkj.modules.chs.vo.OutpatientFinalModel;
import com.jacob.activeX.ActiveXComponent; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch; import com.jacob.com.Dispatch;
import com.jacob.com.Variant; import com.jacob.com.Variant;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import javax.annotation.PostConstruct;
import java.util.Map; import java.util.Map;
@@ -31,11 +31,21 @@ import java.util.Map;
*/ */
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor // @AllArgsConstructor
public class HispayServiceImpl implements IHispayService { public class HispayServiceImpl implements IHispayService {
private final HisConfig hisConfig; @Autowired
private final ChsConfig chsConfig; private HisConfig hisConfig;
@Autowired
private ChsConfig chsConfig;
// COM对象
private static ActiveXComponent dispatch;
@PostConstruct
public void postConstruct() {
dispatch = instanceActive();
}
/** /**
* 获取HIS医保实例 * 获取HIS医保实例
@@ -43,14 +53,13 @@ public class HispayServiceImpl implements IHispayService {
* @return com.jacob.activeX.ActiveXComponent * @return com.jacob.activeX.ActiveXComponent
* @author 萧道子 2025/5/21 * @author 萧道子 2025/5/21
*/ */
private ActiveXComponent instanceActive() { private static ActiveXComponent instanceActive() {
try { try {
// 初始化 // 初始化
ComThread.InitSTA(); // ComThread.InitSTA(); //容易导致线程发生阻塞
// 获取COM对象 ActiveXComponent activeXComponent = new ActiveXComponent("PayClient.clsPayClient");
ActiveXComponent active = new ActiveXComponent("PayClient.clsPayClient");
log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载成功"); log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载成功");
return active; return activeXComponent;
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载失败:{}", e.getMessage()); log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载失败:{}", e.getMessage());
throw new RuntimeException("HIS医保COM库加载失败" + e.getMessage(), e); throw new RuntimeException("HIS医保COM库加载失败" + e.getMessage(), e);
@@ -65,7 +74,7 @@ public class HispayServiceImpl implements IHispayService {
* @author 萧道子 2025/5/21 * @author 萧道子 2025/5/21
*/ */
private void releaseActive() { private void releaseActive() {
ComThread.Release(); // ComThread.Release(); //容易导致线程发生阻塞
} }
/** /**
@@ -78,9 +87,9 @@ public class HispayServiceImpl implements IHispayService {
*/ */
private String processParameters(JSONObject params, String password) { private String processParameters(JSONObject params, String password) {
JSONObject req = new JSONObject() {{ JSONObject req = new JSONObject() {{
put("timestamp", DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")); // 请求发送时间 put("timestamp", ""); // 请求发送时间 DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")
put("requestid", IDGenerator.getSnowflakeIdToStr()); // 唯一请求id put("requestid", ""); // 唯一请求id IDGenerator.getSnowflakeIdToStr()
put("operid", hisConfig.getOperationId()); // 调用者代码 put("operid", ""); // 调用者代码 hisConfig.getOperationId()
put("password", password); // 密码 put("password", password); // 密码
put("params", params); put("params", params);
}}; }};
@@ -120,9 +129,6 @@ public class HispayServiceImpl implements IHispayService {
@Override @Override
public JSONObject readCode() { public JSONObject readCode() {
// 加载资源
Dispatch dispatch = instanceActive();
/** 1、组装参数 */ /** 1、组装参数 */
JSONObject val = new JSONObject() JSONObject val = new JSONObject()
.fluentPut("cardtype", "9") // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证 .fluentPut("cardtype", "9") // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
@@ -140,8 +146,6 @@ public class HispayServiceImpl implements IHispayService {
String resStr = vres.getStringRef(); String resStr = vres.getStringRef();
log.info("[HispayServiceImpl][readCode][医保读卡-电子凭证] call返回值{} 结果:{}", call, resStr); log.info("[HispayServiceImpl][readCode][医保读卡-电子凭证] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理读卡结果 */ /** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr); JSONObject result = verifyResult(resStr);
@@ -154,8 +158,6 @@ public class HispayServiceImpl implements IHispayService {
@Override @Override
public JSONObject readCard(String password) { public JSONObject readCard(String password) {
// 加载资源
Dispatch dispatch = instanceActive();
/** 1、组装参数 */ /** 1、组装参数 */
JSONObject val = new JSONObject() JSONObject val = new JSONObject()
@@ -174,9 +176,6 @@ public class HispayServiceImpl implements IHispayService {
String resStr = vres.getStringRef(); String resStr = vres.getStringRef();
log.info("[HispayServiceImpl][readCard][医保读卡-医保卡] call返回值{} 结果:{}", call, resStr); log.info("[HispayServiceImpl][readCard][医保读卡-医保卡] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理读卡结果 */ /** 3、处理读卡结果 */
JSONObject result = verifyResult(resStr); JSONObject result = verifyResult(resStr);
if (!result.containsKey("item")) { if (!result.containsKey("item")) {
@@ -187,67 +186,7 @@ public class HispayServiceImpl implements IHispayService {
} }
// public JSONObject getPatientInfo_old(String type, String content) {
// Dispatch dispatch = instanceActive();
//
// /**
// * 1、删除保存HIS读卡内容的文件 避免读取到错误信息
// */
// // 获取HIS-CHS医保库路径
// String chsPath = System.getProperty("java.library.path");
// String filePath = chsPath + "/" + chsConfig.getFileName();
// // 删除文件
// FileUtil.del(FileUtil.file(filePath));
//
// /**
// * 2、组装参数
// */
// JSONObject val = new JSONObject()
// .fluentPut("cardtype", type) // 1.就诊卡2.医保卡5.门诊号6.患者姓名和电话号码8.电子健康码/卡9.医保电子凭证
// .fluentPut("cardno", "") // 患者就诊卡号
// .fluentPut("sfzh", "") // 身份证号
// .fluentPut("hzxm", "") // 患者姓名
// .fluentPut("phone", ""); // 患者电话号码
// String params = processParameters(val, content);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] 接口入参:{}", params);
//
// /**
// * 3、调用COM函数
// */
// Variant rest = new Variant();
// Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, rest);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] call返回值{}", call);
//
// // 释放资源
// releaseActive();
//
// /**
// * 4、处理读卡结果
// */
// // COM函数调用之后会生成新的文件 需要判断
// File file = FileUtil.file(filePath);
// if (!file.exists()) {
// throw new RuntimeException("读卡失败:数据未读取");
// }
//
// // 获取读卡结果
// FileReader fileReader = new FileReader(file, "GBK");
// String data = fileReader.readString();
//
// JSONObject result;
// try {
// result = JSONObject.parseObject(data);
// log.info("[HispayServiceImpl][getPatientInfo][医保读卡] 读卡值:{}", result);
// } catch (Exception e) {
// throw new RuntimeException("读卡失败:" + data);
// }
// return result;
// }
private ResultData outpatientBudget(OutpatientBeginModel data) { private ResultData outpatientBudget(OutpatientBeginModel data) {
// 加载资源
ActiveXComponent dispatch = instanceActive();
/** 1、组装参数 */ /** 1、组装参数 */
JSONObject val = new JSONObject() JSONObject val = new JSONObject()
@@ -269,8 +208,6 @@ public class HispayServiceImpl implements IHispayService {
String resStr = resVariant.getStringRef(); String resStr = resVariant.getStringRef();
log.info("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] call返回值{} 结果:{}", call, resStr); log.info("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
/** 3、处理结果 */ /** 3、处理结果 */
JSONObject result = verifyResult(resStr); JSONObject result = verifyResult(resStr);
@@ -291,22 +228,29 @@ public class HispayServiceImpl implements IHispayService {
JSONObject userInfo = readCode(); JSONObject userInfo = readCode();
String patientId = userInfo.getString("patid"); String patientId = userInfo.getString("patid");
data.setPatientId(patientId); data.setPatientId(patientId);
// 更新常量状态 已读卡
ChsPayStateConst.put(data.getPrescriptionNo(), 1);
return outpatientBudget(data); return outpatientBudget(data);
} }
@Override @Override
public ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data) { public ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data) {
// 加载资源
ActiveXComponent dispatch = instanceActive();
/** 1、组装参数 */ /** 1、组装参数 */
JSONObject val = (JSONObject) JSON.toJSON(data); String requestTime = DateUtil.now();
data.setPaytime(requestTime);
JSONObject val = ((JSONObject) JSON.toJSON(data))
.fluentPut("czksfbz", "0") // 是否扣院内账户,与预算保持一致
.fluentPut("zfjsbz", "0") // 是否自费结算与预算保持一致0根据病人医保代码结算1自费结算
.fluentPut("ybrc", "")
.fluentPut("ptlsh", "")
.fluentPut("jysm", "");
String params = processParameters(val, null); String params = processParameters(val, null);
log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] 接口入参:{}", params); log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] 接口入参:{}", params);
String requestTime = DateUtil.now();
/** 2、调用COM函数 */ /** 2、调用COM函数 */
Variant resVariant = new Variant("", true); Variant resVariant = new Variant("", true);
Variant call = Dispatch.call(dispatch, "fRun", "BMZJF002", params, resVariant); Variant call = Dispatch.call(dispatch, "fRun", "BMZJF002", params, resVariant);
@@ -315,13 +259,6 @@ public class HispayServiceImpl implements IHispayService {
String resStr = resVariant.getStringRef(); String resStr = resVariant.getStringRef();
log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] call返回值{} 结果:{}", call, resStr); log.info("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] call返回值{} 结果:{}", call, resStr);
// 释放资源
releaseActive();
// TODO BEGIN 萧道子 2025/6/10 : 模拟参数
// String resStr = "<response><resultCode>0</resultCode><resultMessage/><result><sjh>123456789</sjh><sfrq>2025-06-10 10:23:14</sfrq><bz/><pyckjh/><fyckjh/><yflshjh/><ybcc/></result></response>";
// TODO END 萧道子 2025/6/10 : 模拟参数
/** 3、处理结果 */ /** 3、处理结果 */
JSONObject result = verifyResult(resStr); JSONObject result = verifyResult(resStr);

View File

@@ -43,5 +43,7 @@ public class OutpatientFinalModel implements Serializable {
/** /**
* 支付时间 * 支付时间
*/ */
// @NotEmpty(message = "支付时间不可为空!")
private String paytime; private String paytime;
} }

View File

@@ -4,10 +4,13 @@ import com.dpkj.common.dto.LexMarkResultDTO;
import com.dpkj.common.vo.Result; import com.dpkj.common.vo.Result;
import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.request.MS439Request;
import com.dpkj.modules.print.service.MS439PrintService; import com.dpkj.modules.print.service.MS439PrintService;
import com.dpkj.modules.print.vo.PrinterStatus;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/** /**
* MS439控制层利盟打印机 * MS439控制层利盟打印机
@@ -24,12 +27,28 @@ public class MS439Controller {
private MS439PrintService ms439PrintService; private MS439PrintService ms439PrintService;
@PostMapping("/print") @PostMapping("/print")
public Result<LexMarkResultDTO<?>> print(@Validated @RequestBody MS439Request request){ public Result<LexMarkResultDTO<?>> print(@Validated @RequestBody MS439Request request) {
return Result.ok(ms439PrintService.printImage(request)); return Result.ok(ms439PrintService.printImage(request));
} }
/**
* 检验报告打印
*
* @return
*/
@PostMapping("/printJY")
public Result<LexMarkResultDTO<?>> printJY() {
MS439Request ms439Request = new MS439Request();
// 获取检验报告PDF
String path = ms439PrintService.getJYPDFPath();
ms439Request.setPagesource("A5");
ms439Request.setFileDir(path);
LexMarkResultDTO<?> result = ms439PrintService.printImage(ms439Request);
return Result.ok(result);
}
@PostMapping("/getStatus") @PostMapping("/getStatus")
public Result<String> print(@RequestParam(defaultValue = "A4") String papersource){ public Result<String> print(@RequestParam(defaultValue = "A4") String papersource) {
this.ms439PrintService.getStatus(papersource); this.ms439PrintService.getStatus(papersource);
return Result.ok(); return Result.ok();
} }

View File

@@ -3,11 +3,12 @@ package com.dpkj.modules.print.service;
import com.dpkj.common.dto.LexMarkResultDTO; import com.dpkj.common.dto.LexMarkResultDTO;
import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.request.MS439Request;
import com.dpkj.modules.print.vo.PrinterStatus; import com.dpkj.modules.print.vo.PrinterStatus;
import javassist.compiler.Lex;
public interface MS439PrintService { public interface MS439PrintService {
LexMarkResultDTO<?> printImage(MS439Request request); LexMarkResultDTO<?> printImage(MS439Request request);
LexMarkResultDTO<PrinterStatus> getStatus(String papersource); LexMarkResultDTO<PrinterStatus> getStatus(String papersource);
String getJYPDFPath();
} }

View File

@@ -6,17 +6,48 @@ import com.dpkj.common.dto.LexMarkDTO;
import com.dpkj.common.dto.LexMarkResultDTO; import com.dpkj.common.dto.LexMarkResultDTO;
import com.dpkj.common.exception.RRException; import com.dpkj.common.exception.RRException;
import com.dpkj.common.utils.ThirdService; import com.dpkj.common.utils.ThirdService;
import com.dpkj.modules.print.enums.*; import com.dpkj.modules.print.enums.MS439DeviceStatusEnum;
import com.dpkj.modules.print.enums.MS439InkStatusEnum;
import com.dpkj.modules.print.enums.MS439MediaStatusEnum;
import com.dpkj.modules.print.enums.MS439PaperStatusEnum;
import com.dpkj.modules.print.enums.MS439StampStatusEnum;
import com.dpkj.modules.print.enums.MS439TonerStatusEnum;
import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.request.MS439Request;
import com.dpkj.modules.print.service.MS439PrintService; import com.dpkj.modules.print.service.MS439PrintService;
import com.dpkj.modules.print.utils.FolderUtils; import com.dpkj.modules.print.utils.FolderUtils;
import com.dpkj.modules.print.utils.FontLoader;
import com.dpkj.modules.print.utils.PDFUtils; import com.dpkj.modules.print.utils.PDFUtils;
import com.dpkj.modules.print.vo.PrinterStatus; import com.dpkj.modules.print.vo.PrinterStatus;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* 利盟MS439打印机服务 * 利盟MS439打印机服务
@@ -49,7 +80,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
PrinterStatus ms439 = status.getData(); PrinterStatus ms439 = status.getData();
// 如果是要盖章,校验盖章机器是否正常 // 如果是要盖章,校验盖章机器是否正常
if ( request.getStamp() == 1) { if (request.getStamp() == 1) {
String deviceExStatus = ms439.getStDeviceExStatus(); String deviceExStatus = ms439.getStDeviceExStatus();
if (deviceExStatus == null || deviceExStatus.equals("")) { if (deviceExStatus == null || deviceExStatus.equals("")) {
throw new RRException("获取打印机设备状态出问题"); throw new RRException("获取打印机设备状态出问题");
@@ -60,7 +91,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
} }
String device = devices[1]; String device = devices[1];
// 校验盖章机是否正常,除了HEALTHY都抛异常 // 校验盖章机是否正常,除了HEALTHY都抛异常
if (!device.equals(MS439StampStatusEnum.HEALTHY.getPrintCode()) ) { if (!device.equals(MS439StampStatusEnum.HEALTHY.getPrintCode())) {
throw new RRException(MS439StampStatusEnum.getPCode(device), throw new RRException(MS439StampStatusEnum.getPCode(device),
MS439StampStatusEnum.getMessage(device)); MS439StampStatusEnum.getMessage(device));
} }
@@ -72,7 +103,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
lexMarkDTO.setDevName("HtmPrinter"); lexMarkDTO.setDevName("HtmPrinter");
lexMarkDTO.setPluginMethod("exec"); lexMarkDTO.setPluginMethod("exec");
JSONObject param = new JSONObject(); JSONObject param = new JSONObject();
// printType 选择箱子 // printType 选择箱子
// param.put("prtData", String.format("PrintType=%d;pagesource=%s;copies=%d;file[0]=%s;stamp=%d;duplex=%d;color=%d;direction=%d", // param.put("prtData", String.format("PrintType=%d;pagesource=%s;copies=%d;file[0]=%s;stamp=%d;duplex=%d;color=%d;direction=%d",
@@ -104,7 +135,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
lexMarkDTO.setParam(param.toString()); lexMarkDTO.setParam(param.toString());
LexMarkResultDTO<LexMarkResultDTO.Param> paramLexMarkResultDTO = thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class); LexMarkResultDTO<LexMarkResultDTO.Param> paramLexMarkResultDTO = thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class);
if ( paramLexMarkResultDTO.getData().getResult() != 0){ if (paramLexMarkResultDTO.getData().getResult() != 0) {
throw new RRException(500, paramLexMarkResultDTO.getData().getResult() + ""); throw new RRException(500, paramLexMarkResultDTO.getData().getResult() + "");
} }
@@ -132,7 +163,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
lexMarkDTO.setPluginMethod("exec"); lexMarkDTO.setPluginMethod("exec");
LexMarkResultDTO<PrinterStatus> status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class); LexMarkResultDTO<PrinterStatus> status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
if ( status.getResult() != 0){ if (status.getResult() != 0) {
thirdService.open("HtmPrinter", 0); thirdService.open("HtmPrinter", 0);
status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class); status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
} }
@@ -142,7 +173,7 @@ public class MS439PrintServiceImpl implements MS439PrintService {
throw new RRException("获取打印机纸张状态出问题"); throw new RRException("获取打印机纸张状态出问题");
} }
String[] papers = stPaperEx.split("\\|"); String[] papers = stPaperEx.split("\\|");
if ( papers.length < 2) { if (papers.length < 2) {
throw new RRException("打印机纸盒数量不对"); throw new RRException("打印机纸盒数量不对");
} }
String paperStatus = ""; String paperStatus = "";
@@ -154,13 +185,13 @@ public class MS439PrintServiceImpl implements MS439PrintService {
if (papersource.equals("A5")) { if (papersource.equals("A5")) {
paperStatus = printerConfig.getLevelOne().equals("A5") ? papers[0] : papers[1]; paperStatus = printerConfig.getLevelOne().equals("A5") ? papers[0] : papers[1];
} }
if ( !(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))){ if (!(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))) {
throw new RRException(500, paperStatus); throw new RRException(500, paperStatus);
} }
PrinterStatus ms439 = status.getData(); PrinterStatus ms439 = status.getData();
// 校验打印机是否正常,除了HEALTHY都抛异常 // 校验打印机是否正常,除了HEALTHY都抛异常
if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode()) ) { if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode())) {
throw new RRException(500, ms439.getStDeviceStatus()); throw new RRException(500, ms439.getStDeviceStatus());
} }
@@ -170,19 +201,131 @@ public class MS439PrintServiceImpl implements MS439PrintService {
} }
// 校验磁带 满或者少才放行 // 校验磁带 满或者少才放行
if ( !(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))){ if (!(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))) {
throw new RRException(500, ms439.getStToner()); throw new RRException(500, ms439.getStToner());
} }
// 校验墨盒 满或者少才放行,当前获取为未知 // 校验墨盒 满或者少才放行,当前获取为未知
if ( false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode()) if (false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode())
|| ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))){ || ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))) {
throw new RRException(500, ms439.getStInk()); throw new RRException(500, ms439.getStInk());
} }
return status; return status;
} }
@Override
public String getJYPDFPath() {
// 1. 准备输出路径
String dirPath = "D:/TempJYPDF/";
File dir = new File(dirPath);// 确保目录存在
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = "report_jy_" + System.currentTimeMillis() + ".pdf";
String pdfPath = dirPath + fileName;
try {
// 2. 准备模板数据
Map<String, Object> data = prepareReportData();
// 3. 渲染Thymeleaf模板
String htmlContent = renderThymeleafTemplate(data);
// 4. 生成PDF文件
createPdfFromHtml(htmlContent, pdfPath);
return pdfPath;
} catch (Exception e) {
e.printStackTrace(); // 打印完整异常堆栈
throw new RuntimeException("PDF生成失败: " + e.getMessage());
}
}
private void createPdfFromHtml(String html, String outputPath)
throws IOException, DocumentException {
// 大小为A5纸
Document document = new Document(PageSize.A5);
try (OutputStream os = Files.newOutputStream(Paths.get(outputPath))) {
PdfWriter writer = PdfWriter.getInstance(document, os);
document.open();
// 加载自定义字体
BaseFont simfangFont = FontLoader.loadFont("/font/simfang.ttf");
// 创建自定义字体提供器
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider() {
@Override
public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {
return new Font(simfangFont, size, style, color);
}
};
// 解析 HTML 并生成 PDF
XMLWorkerHelper.getInstance().parseXHtml(
writer, document,
new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)),
null, StandardCharsets.UTF_8,
fontProvider // 注入字体提供器
);
document.close(); // 这里关闭,确保 OutputStream 还没被关闭
}
}
// 模板渲染方法(保持不变)
private String renderThymeleafTemplate(Map<String, Object> data) {
// 设置模板数据
Context context = new Context();
context.setVariables(data);
// 填充数据到html
TemplateEngine templateEngine = new TemplateEngine();
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCacheable(true);
resolver.setApplicationContext(new AnnotationConfigReactiveWebApplicationContext());
templateEngine.setTemplateResolver(resolver);
return templateEngine.process("reportJY", context);
}
// 报告数据准备(根据实际业务实现)
private Map<String, Object> prepareReportData() {
Map<String, Object> data = new HashMap<>();
// 患者信息
Map<String, String> patient = new HashMap<>();
patient.put("name", "余文财");
patient.put("gender", "");
patient.put("age", "25岁");
patient.put("medicalRecord", "20240624001");
patient.put("department", "内科");
patient.put("bedNumber", "A301");
data.put("patient", patient);
// 检验项目数据
List<Map<String, Object>> items = new ArrayList<>();
addItem(items, "白细胞计数", "7.26", "3.5-9.5", "10^9/L", false);
addItem(items, "血红蛋白", "165", "115-150", "g/L", true);
// ...其他检验项
data.put("items", items);
// 系统信息
data.put("reportTime", new Date());
data.put("doctor", "李医师");
data.put("reviewer", "王主任");
return data;
}
private void addItem(List<Map<String, Object>> items, String name,
String value, String range, String unit, boolean abnormal) {
Map<String, Object> item = new HashMap<>();
item.put("name", name);
item.put("result", value);
item.put("referenceRange", range);
item.put("unit", unit);
item.put("isAbnormal", abnormal);
items.add(item);
}
} }

View File

@@ -74,8 +74,8 @@ public class RegisterServiceImpl implements PrintService {
int dinyHeight = 0; int dinyHeight = 0;
if (templateName.equals("department")) { if (templateName.equals("department")) {
// 由于是使用的门诊小票-T2那么默认的高度为1000强行设置通过动态修改渲染的图片的高度 // 由于是使用的门诊小票-T2那么默认的高度为1100强行设置通过动态修改渲染的图片的高度
height = 1000; height = 1100;
// 单行最大长度为10 // 单行最大长度为10
int singleLineMaxLength = 10; int singleLineMaxLength = 10;

View File

@@ -0,0 +1,31 @@
package com.dpkj.modules.print.utils;
import com.itextpdf.text.pdf.BaseFont;
import java.io.InputStream;
/**
* @author 余文财
* @description 字体加载
* @date 2025.6.24
*/
public class FontLoader {
public static BaseFont loadFont(String resourcePath) {
try (InputStream fontStream = FontLoader.class.getResourceAsStream(resourcePath)) {
if (fontStream == null) {
throw new IllegalArgumentException("字体文件未找到: " + resourcePath);
}
// 创建支持中文的 BaseFont
return BaseFont.createFont(
resourcePath,
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED,
false,
fontStream.readAllBytes(),
null
);
} catch (Exception e) {
throw new RuntimeException("字体加载失败: " + resourcePath, e);
}
}
}

View File

@@ -69,21 +69,21 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
String json = params.toJSONString(); String json = params.toJSONString();
String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化 String service_code = AliFaceConstants.SMILEVERIFYNIN_V1; //调用的组件编码:初始化
Result<Object> startServiceIniResult = this.startServiceIni(json, service_code); Result<Object> startServiceIniResult = this.startServiceIni(json, service_code);
log.info("[AliScanFaceServiceImpl][aliFacePay][72][调用ABCP调用刷脸的结果] {}", startServiceIniResult.toString()); log.info("[AliScanFaceServiceImpl][aliFacePay][72][1、获取刷脸去初始化服务的结果] {}", startServiceIniResult.toString());
if (startServiceIniResult.isSuccess()) { if (startServiceIniResult.isSuccess()) {
Map<String, String> res = (Map<String, String>) startServiceIniResult.getResult(); Map<String, String> res = (Map<String, String>) startServiceIniResult.getResult();
String ftoken = res.get("ftoken"); String ftoken = res.get("ftoken");
log.info("[AliScanFaceServiceImpl][aliFacePay][76][调用ABCP调用刷脸的结果ftoken] {}", ftoken.toString()); log.info("[AliScanFaceServiceImpl][aliFacePay][76][[1、获取刷脸去初始化服务的结果-ftoken] {}", ftoken);
/** /**
* 2、调用后端的支付宝统一收单交易支付接口、存入hisPay * 2、调用后端的支付宝统一收单交易支付接口、存入hisPay
*/ */
aliOrderVo.setAuthCode(ftoken);//Demo值"fp128d26333fa66e66e7f34c493d30cdh76" aliOrderVo.setAuthCode(ftoken);//Demo值"fp128d26333fa66e66e7f34c493d30cdh76"
JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo); JSONObject serverParams = (JSONObject) JSON.toJSON(aliOrderVo);
log.info("[AliScanFaceServiceImpl][aliFacePay][83][调用后端的支付宝统一收单交易支付接口参数] {}", serverParams.toString());
String url = serverUrl + "openapi/aliPayOrderApi/createOrder"; String url = serverUrl + "openapi/aliPayOrderApi/createOrder";
log.info("[AliScanFaceServiceImpl][aliFacePay][85][调用后端的支付宝统一收单交易支付接口路径] {}", serverUrl); log.info("[AliScanFaceServiceImpl][aliFacePay][86][调用后端的支付宝统一收单交易支付接口路径] {}", url);
log.info("[AliScanFaceServiceImpl][aliFacePay][85][调用后端的支付宝统一收单交易支付接口参数] {}", serverParams.toJSONString());
String req = HttpRequest.post(url) String req = HttpRequest.post(url)
.header(Header.CONTENT_TYPE, ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8)) .header(Header.CONTENT_TYPE, ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8))
.body(serverParams.toJSONString()) .body(serverParams.toJSONString())
@@ -191,7 +191,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() { AbcpInvoke.CallbackRsp callbackRsp = new AbcpInvoke.CallbackRsp() {
@Override @Override
public void OnProcess(int code, String subCode, String subMsg, String result) { public void OnProcess(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnProcess][189][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result); log.info("[AliScanFaceServiceImpl][OnProcess][123][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
try { try {
processCode.set(code); processCode.set(code);
processResult.set(result); processResult.set(result);
@@ -202,7 +202,7 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
@Override @Override
public void OnFinish(int code, String subCode, String subMsg, String result) { public void OnFinish(int code, String subCode, String subMsg, String result) {
log.info("[AliScanFaceServiceImpl][OnFinish][200][ABCP服务调用 刷脸初始化服务,获取ftoken:][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result); log.info("[AliScanFaceServiceImpl][OnFinish][128][service_code:{}][code:{}][subCode:{}][subMsg:{}][result:{}]", service_code, code, subCode, subMsg, result);
/**Demo示例记录 /**Demo示例记录
* [service_code:BPaaSSmileVerifyNonInitV1][code:1000][subCode:E00000][subMsg:SUCCESS][result:{"code":1000,"subCode":"OK_SUCCESS","subMessage":"SUCCESS","barCode":"281215320962898068","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","alipayUid":"2088812449506047","accountList":"[\"104***@qq.com\"]","authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","result":{"accountList":["104***@qq.com"],"alipayUid":"2088812449506047","allowRetry":false,"authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","barCode":"281215320962898068","certName":"您好,*雪","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","type":"selectUid"},"easterEgg":false,"zolozConfig":{"installAngle":90},"serviceId":"pay","traceId":"2444-44-1745802328","callStartTimeMs":1745802328114,"localTime":"2025-04-28-09-05-41-791"}] * [service_code:BPaaSSmileVerifyNonInitV1][code:1000][subCode:E00000][subMsg:SUCCESS][result:{"code":1000,"subCode":"OK_SUCCESS","subMessage":"SUCCESS","barCode":"281215320962898068","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","alipayUid":"2088812449506047","accountList":"[\"104***@qq.com\"]","authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","result":{"accountList":["104***@qq.com"],"alipayUid":"2088812449506047","allowRetry":false,"authToken":"44686f7195c77ee2e09c09bcdc657dd5h28i","barCode":"281215320962898068","certName":"您好,*雪","ftoken":"fp1efd3d4c0230a28f5261efe7c5050eh28","type":"selectUid"},"easterEgg":false,"zolozConfig":{"installAngle":90},"serviceId":"pay","traceId":"2444-44-1745802328","callStartTimeMs":1745802328114,"localTime":"2025-04-28-09-05-41-791"}]
@@ -223,12 +223,13 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
// 等待process回调完成设置超时避免死锁 // 等待process回调完成设置超时避免死锁
boolean awaitSuccess = latch.await(10, TimeUnit.SECONDS); boolean awaitSuccess = latch.await(10, TimeUnit.SECONDS);
if (!awaitSuccess) { if (!awaitSuccess) {
log.info("[AliScanFaceServiceImpl][startServiceIni][221][service_code:{}][ABCP调用刷脸:等待process回调超时]", service_code); log.info("[AliScanFaceServiceImpl][startServiceIni][226][10秒-等待process回调超时]");
return Result.error("等待process回调超时"); return Result.error("等待process回调超时");
} else { } else {
log.info("[AliScanFaceServiceImpl][startServiceIni][229][ABCP调用刷脸初始化服务-process回调结果-processCode] {}", processCode);
if (processCode.get() == 0) { if (processCode.get() == 0) {
JSONObject jsonObject = JSONObject.parseObject(processResult.get()); JSONObject jsonObject = JSONObject.parseObject(processResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][225][service_code:{}][ABCP调用刷脸-等待process回调完成结果] {}", service_code, jsonObject.toString()); log.info("[AliScanFaceServiceImpl][startServiceIni][232][ABCP调用刷脸初始化服务-process回调结果] {}", jsonObject.toString());
if (jsonObject.containsKey("traceId")) { if (jsonObject.containsKey("traceId")) {
res.put("traceId", jsonObject.getString("traceId")); res.put("traceId", jsonObject.getString("traceId"));
} else { } else {
@@ -242,11 +243,13 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
// 等待finish回调完成设置超时避免死锁 // 等待finish回调完成设置超时避免死锁
boolean awaitFinishSuccess = latchFinish.await(120, TimeUnit.SECONDS); boolean awaitFinishSuccess = latchFinish.await(120, TimeUnit.SECONDS);
if (!awaitFinishSuccess) { if (!awaitFinishSuccess) {
log.info("[AliScanFaceServiceImpl][startServiceIni][246][120秒-等待finish回调超时]");
return Result.error("等待finish回调超时"); return Result.error("等待finish回调超时");
} else { } else {
log.info("[AliScanFaceServiceImpl][startServiceIni][249][ABCP调用刷脸初始化服务-finish回调结果-finishCode] {}", finishCode);
if (finishCode.get() == 1000) { if (finishCode.get() == 1000) {
JSONObject jsonObject = JSONObject.parseObject(finishResult.get()); JSONObject jsonObject = JSONObject.parseObject(finishResult.get());
log.info("[AliScanFaceServiceImpl][startServiceIni][244][service_code:{}] [ABCP调用刷脸-等待finish回调完成结果]{}", service_code, jsonObject.toString()); log.info("[AliScanFaceServiceImpl][startServiceIni][252][ABCP调用刷脸初始化服务-finish回调结果] {}", jsonObject.toString());
if (jsonObject.containsKey("ftoken")) { if (jsonObject.containsKey("ftoken")) {
res.put("ftoken", jsonObject.getString("ftoken"));//ftoken参数的有效期为2分钟 res.put("ftoken", jsonObject.getString("ftoken"));//ftoken参数的有效期为2分钟
res.put("barCode", jsonObject.getString("barCode")); res.put("barCode", jsonObject.getString("barCode"));
@@ -260,10 +263,10 @@ public class AliScanFaceServiceImpl implements IAliScanFaceService {
} }
//结果返回 //结果返回
log.info("[AliScanFaceServiceImpl][startServiceIni][266][][ABCP调用刷脸初始化服务成功返回结果] {}", finishResultRef.get());
return finishResultRef.get(); return finishResultRef.get();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
log.info("[AliScanFaceServiceImpl][startServiceIni][261][ABCP调用刷脸初始化服务失败] {}", e.getMessage());
return Result.error("ABCP调用刷脸初始化服务失败" + e.getMessage()); return Result.error("ABCP调用刷脸初始化服务失败" + e.getMessage());
} }
} }

View File

@@ -37,7 +37,7 @@ public class AliOrderVo implements Serializable {
private String outTradeNo; private String outTradeNo;
/** /**
* 用户支付金额 * 用户支付金额 单位元
*/ */
//@ApiModelProperty(value = "用户支付金额") //@ApiModelProperty(value = "用户支付金额")
private String totalAmount; private String totalAmount;

View File

@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@@ -79,6 +80,10 @@ public class WxFacePayController {
public Result<String> doFacePay(@RequestBody WxFaceOrderVo wxFaceOrderVo) throws Exception { public Result<String> doFacePay(@RequestBody WxFaceOrderVo wxFaceOrderVo) throws Exception {
Result<String> result = new Result<>(); Result<String> result = new Result<>();
try { try {
//元转分
int money = new BigDecimal(wxFaceOrderVo.getTotalAmount()).multiply(new BigDecimal(100)).intValue();
wxFaceOrderVo.setTotalAmount(String.valueOf(money));
//1 初始化 //1 初始化
this.initWxpayface(); this.initWxpayface();
@@ -95,6 +100,7 @@ public class WxFacePayController {
WxPayMicropayResult micropayResult = new WxPayMicropayResult(); WxPayMicropayResult micropayResult = new WxPayMicropayResult();
if (StringUtil.isNotBlank(authinfoResp.getFace_code())) { if (StringUtil.isNotBlank(authinfoResp.getFace_code())) {
//5、调用后台人脸支付API发起支付 //5、调用后台人脸支付API发起支付
System.out.println("---------调用后台人脸支付API发起支付");
wxFaceOrderVo.setOutTradeNo(getOutTradeNo()); wxFaceOrderVo.setOutTradeNo(getOutTradeNo());
micropayResult = this.toCreateWxOrder(authinfoResp, wxFaceOrderVo, wxFacePayResp0); micropayResult = this.toCreateWxOrder(authinfoResp, wxFaceOrderVo, wxFacePayResp0);
@@ -184,6 +190,7 @@ public class WxFacePayController {
public WxFacePayAuthinfoResp getWxpayfaceCode(@RequestBody WxFaceOrderVo wxFaceOrderVo, WxFacePayAuthinfoResp wxFacePayResp0) throws Exception { public WxFacePayAuthinfoResp getWxpayfaceCode(@RequestBody WxFaceOrderVo wxFaceOrderVo, WxFacePayAuthinfoResp wxFacePayResp0) throws Exception {
//4、进行人脸识别getWxpayfaceCode获取支付凭证 //4、进行人脸识别getWxpayfaceCode获取支付凭证
String outTradeNo = getOutTradeNo();//获取流水号 String outTradeNo = getOutTradeNo();//获取流水号
// 构建请求参数的JSON字符串 // 构建请求参数的JSON字符串
WxFacePayReq wxFacePayReq = new WxFacePayReq("getWxpayfaceCode", "1", System.currentTimeMillis() / 1000); WxFacePayReq wxFacePayReq = new WxFacePayReq("getWxpayfaceCode", "1", System.currentTimeMillis() / 1000);
wxFacePayReq.setAuthinfo(wxFacePayResp0.getAuthinfo()) wxFacePayReq.setAuthinfo(wxFacePayResp0.getAuthinfo())

View File

@@ -56,7 +56,6 @@ public class CallWxpayFaceServiceImpl implements CallWxpayFaceService {
// 调用本地方法 // 调用本地方法
WxpayFaceSDKDll.Dll dll = WxpayFaceSDKDll.instance(); WxpayFaceSDKDll.Dll dll = WxpayFaceSDKDll.instance();
int result = dll.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize); int result = dll.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize);
//使用C:\Windows\System32目录下 int result = WxpayFaceSDK.INSTANCE.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize);
if (result == 0) { if (result == 0) {
Pointer pointer = new Pointer(pRespBuf[0]); Pointer pointer = new Pointer(pRespBuf[0]);

View File

@@ -36,8 +36,10 @@ public class WxFaceOrderVo {
private String outTradeNo; private String outTradeNo;
/** /**
* 用户支付金额 * 用户支付金额 单位元
* 调用微信时需要转为分
*/ */
private String totalAmount; private String totalAmount;
} }

View File

@@ -1,5 +1,29 @@
server: server:
port: 5948 port: 5948
servlet:
context-path: /api
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
logging:
level:
com.dpkj: debug
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
resource:
static-locations: classpath:/static/,classpath:/public/
dpkj: dpkj:
#后端项目访问地址 #https://yinyitong.yzqingyan.cn/ http://172.16.11.13:15946/ ttps://yinyitong.yzqingyan.cn #后端项目访问地址 #https://yinyitong.yzqingyan.cn/ http://172.16.11.13:15946/ ttps://yinyitong.yzqingyan.cn

View File

@@ -1,10 +1,34 @@
server: server:
port: 5946 port: 5946
servlet:
context-path: /api
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
logging:
level:
com.dpkj: debug
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
resource:
static-locations: classpath:/static/,classpath:/public/
dpkj: dpkj:
#后端项目访问地址 #后端项目访问地址
#TODO 改为正式的地址 http://www.lczyyy.com/api http://127.0.0.1:15946/api # 改为正式的地址 http://www.lczyyy.com/api/ http://127.0.0.1:5946/api/ http://www.lczyyy.com/apitest/
serverurl: http://www.lczyyy.com/api serverurl: http://www.lczyyy.com/api/
# 医保配置 # 医保配置
chs: chs:
# 医保机构编码 # 医保机构编码
@@ -45,27 +69,27 @@ dpkj:
service-id: pay service-id: pay
#微信模块 #微信模块
wx: wx:
configs: # 清研家 configs: #中医院
- app-id: wxc12fa4977f66974d #wxc12fa4977f66974d #wx024903d1d2e1a55a - app-id: wxc12fa4977f66974d
# 公众号的appsecret # 公众号的appsecret
secret: a51dbcac25a73d7e4812a43cf550c5fc #f83420d79cc6ecd1d7fe9684ac9cdfe4 secret: a51dbcac25a73d7e4812a43cf550c5fc
# 接口配置里的Token值 DPKJ-YINYITONG #DPKJ-YINYITONG#dpkjylwjvote # 接口配置里的Token值
token: DPKJ-YINYITONG token: DPKJYINYITONG
# 接口配置里的EncodingAESKey值 # 接口配置里的EncodingAESKey值
aes-key: yIBgBrHwRGjO2L3CLIE9hmnlf1FrXQQ7qJZVIg4r6Dx aes-key: yIBgBrHwRGjO2L3CLIE9hmnlf1FrXQQ7qJZVIg4r6Dx
mch-config: #商户信息 驿路万家-扬州清研软件科技 mch-config: #商户信息 中医院
app-id: wxc12fa4977f66974d app-id: wxc12fa4977f66974d
secret: f83420d79cc6ecd1d7fe9684ac9cdfe4 secret: a51dbcac25a73d7e4812a43cf550c5fc
#调用接口所需service_id #调用接口所需service_id
service-id: service_id service-id: service_id
#商户号 #商户号
mch-id: 1557642321 mch-id: 1603658732
#商户秘钥 #商户秘钥
mch-key: yndpkj15288216506YndpkjKsjytZx12 mch-key: lczyywxc12fa4977f66974dyytzz1234
#报文解密 APIv3密钥 #报文解密 APIv3密钥
v3-key: yndpkj15288216506YndpkjKsjytZx12 v3-key: lczyywxc12fa4977f66974dyytzz1234
#微信: 商户APIv2密钥 #微信: 商户APIv2密钥
key-api: yndpkj15288216506YndpkjKsjytZx12 key-api: lczyywxc12fa4977f66974dyytzz1234
#p12证书的位置可以指定绝对路径也可以指定类路径以classpath;开头) #p12证书的位置可以指定绝对路径也可以指定类路径以classpath;开头)
key-path: classpath:test\apiclient_cert.p12 key-path: classpath:test\apiclient_cert.p12
private-key-path: classpath:test\apiclient_key.pem private-key-path: classpath:test\apiclient_key.pem

View File

@@ -1,29 +1,5 @@
server:
servlet:
context-path: /api
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
logging:
level:
com.dpkj: debug
spring: spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
resource:
static-locations: classpath:/static/,classpath:/public/
application: application:
name: ems-express-bridge name: yinyitong-zhongyuyuan-dll-stand
profiles: profiles:
active: dev active: '@profile.name@'

Binary file not shown.

View File

@@ -7,48 +7,54 @@
<body> <body>
<div style="font-size: 32px;font-weight: bold;"> <div style="font-size: 32px;font-weight: bold;">
<div> <div>
<div style="text-align: center; font-size: 40px; "><span th:text="${hospitalName}"></span> <div style="text-align: center; font-size: 40px;font-weight: bold;"><span th:text="${hospitalName}"></span>
</div> </div>
<div style="text-align: center; font-size: 28px;"><span>****<span <div style="text-align: center; font-size: 28px;font-weight: bold;"><span>****<span
th:text="${registeTerminalName}"></span>****</span> th:text="${registeTerminalName}"></span>****</span>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
<div style="text-align: center; font-size: 40px; "><span th:text="${registeType}"></span></div> <div style="text-align: center; font-size: 40px;font-weight: bold;"><span th:text="${registeType}"></span></div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
</div> </div>
<div style="font-size: 35px;word-break: break-all;margin: 10px 20px;"> <div style="font-size: 35px;margin: 10px 20px;">
<div style="display: flex;"> <div style="margin-top: 10px;word-break: break-all;" th:if="${outpatientNumber}">门诊号:<span
th:text="${outpatientNumber}"></span>
</div>
<div style="margin-top: 10px;word-break: break-all;">
<span style="margin-right: 25px;">姓名:<span th:text="${name}"></span></span> <span style="margin-right: 25px;">姓名:<span th:text="${name}"></span></span>
<span style="margin-right: 25px;">性别:<span th:text="${gender}"></span></span> <span style="margin-right: 25px;">性别:<span th:text="${gender}"></span></span>
<span>年龄:<span th:text="${age}"></span></span> <span>年龄:<span th:text="${age}"></span></span>
</div> </div>
<div style="word-break: break-all;margin-top: 10px;"> <div style="margin-top: 10px;word-break: break-all;" th:if="${doctor}">
<span style="margin-right: 25px;" th:if="${outpatientNumber}"> 就诊医生:<span th:text="${doctor}"></span>
门诊号:<span th:text="${outpatientNumber}"></span></span>
<span th:if="${doctor}">
就诊医生:<span th:text="${doctor}"></span>
</span>
</div> </div>
<div style="margin-top: 10px;" th:if="${department}">就诊科室:<span th:text="${department}"></span> <div style="margin-top: 10px;word-break: break-all;" th:if="${department}">就诊科室:<span
th:text="${department}"></span>
</div> </div>
</div> </div>
<div style="text-align: center; font-size: 32px;"> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
-----------------------------------------------------------------------------
</div>
<div style="font-size: 35px; margin: 10px 20px"> <div style="font-size: 35px; margin: 10px 20px">
<div style="word-break: break-all;"> <div style="text-align: center; font-size: 40px;font-weight: bold;"><span>费用信息</span></div>
<span style="margin-right: 25px;">费用总额:<span th:text="${totalFee}"></span></span> <div style="margin-top: 10px;">
<span>个人支付:<span th:text="${personalPayment}"></span></span> <div style="float: left;width: 190px;">金额合计:</div>
<div style="margin-left: 190px;word-break: break-all;">
<span><span th:text="${totalFee}"></span>(小写金额)</span><br/>
<span><span th:text="${actualReceiptAmountChinese}"></span>(大写金额)</span>
</div>
</div> </div>
<div style="margin-top: 10px;word-break: break-all;"> <div th:if="${chs==1}">
<span>实收金额</span><span <div style="margin-top: 10px;word-break: break-all;">医保统筹支付<span th:text="${ybtcjj}"></span></div>
th:text="${actualReceiptAmount}"></span></div> <div style="margin-top: 10px;word-break: break-all;">个人医保支付:<span th:text="${ybgrzh}"></span></div>
<div style="margin-top: 10px;"><span>实收金额:</span><span th:text="${actualReceiptAmountChinese}"></span></div> <div style="margin-top: 10px;word-break: break-all;">医院账户支付:<span th:text="${yyzh}"></span></div>
<div style="margin-top: 10px;word-break: break-all;">医院优惠金额:<span th:text="${yyyh}"></span></div>
</div>
<div style="margin-top: 10px;word-break: break-all;">个人自费:<span th:text="${personalPayment}"></span></div>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
<div style="margin: 10px 20px"> <div style="margin: 10px 20px">
<div style="text-align: center; font-size: 40px;font-weight: bold;"><span>费用明细</span></div>
<table style="width: 100%; table-layout: fixed; border-collapse: collapse;"> <table style="width: 100%; table-layout: fixed; border-collapse: collapse;">
<tr style="font-size: 35px;"> <tr style="font-size: 32px;">
<th style="width: 300px;text-align: left;">项目名称</th> <th style="width: 300px;text-align: left;">项目名称</th>
<th style="width: calc(25% - 5px);text-align: center;">数量</th> <th style="width: calc(25% - 5px);text-align: center;">数量</th>
<th style="width: calc(25% - 5px);text-align: center;">单价</th> <th style="width: calc(25% - 5px);text-align: center;">单价</th>
@@ -63,9 +69,11 @@
</table> </table>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div> <div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div>
<div style="margin-left: 35px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div> <div style="margin-left: 20px;font-size: 36px;word-break: break-all;">终端编号:<span
<div style="margin-left: 35px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div> th:text="${terminalNumber}"></span></div>
<div style="margin-left: 35px;font-size: 36px;margin-top: 10px;"> <div style="margin-left: 20px;font-size: 36px;word-break: break-all;">打印时间:<span th:text="${printTime}"></span>
</div>
<div style="margin-left: 20px;font-size: 36px;word-break: break-all;">
<span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span> <span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<title>挂号单</title> <title>住院押金预缴</title>
</head> </head>
<body> <body>
<div style="font-size: 32px;font-weight: bold;"> <div style="font-size: 32px;font-weight: bold;">
@@ -16,21 +16,21 @@
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
</div> </div>
<div style=" font-size: 37px;"> <div style=" font-size: 37px;">
<div style="margin-left: 35px;">&emsp;&emsp;名:<span th:text="${name}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;名:<span th:text="${name}"></span></div>
<div style="margin-left: 35px;">&emsp;&emsp;别:<span th:text="${gender}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;别:<span th:text="${gender}"></span></div>
<div style="margin-left: 35px;">&emsp;&emsp;龄:<span th:text="${age}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;龄:<span th:text="${age}"></span></div>
<div style="margin-left: 35px;">出生日期:<span th:text="${birthDate}"></span></div> <div style="margin-left: 20px;">出生日期:<span th:text="${birthDate}"></span></div>
<div style="margin-left: 35px;">&ensp;&ensp;号:<span th:text="${outpatientNumber}"></span></div> <div style="margin-left: 20px;">&ensp;&ensp;号:<span th:text="${outpatientNumber}"></span></div>
<div style="margin-left: 35px;">入院科室:<span th:text="${department}"></span></div> <div style="margin-left: 20px;">入院科室:<span th:text="${department}"></span></div>
<div style="margin-left: 35px;">&ensp;&ensp;用:<span th:text="${totalFee}"></span>&thinsp;</div> <div style="margin-left: 20px;">&ensp;&ensp;用:<span th:text="${totalFee}"></span>&thinsp;</div>
<div style="margin-left: 35px;">支付方式:<span th:text="${paymentMethod}"></span></div> <div style="margin-left: 20px;">支付方式:<span th:text="${paymentMethod}"></span></div>
<div style="margin-left: 35px;">交易流水:<span style="font-size: 35px;" th:text="${transactionNumber}"></span> <div style="margin-left: 20px;">交易流水:<span style="font-size: 35px;" th:text="${transactionNumber}"></span>
</div> </div>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div> <div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div>
<div style="margin-left: 35px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div> <div style="margin-left: 20px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 35px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div> <div style="margin-left: 20px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 35px;font-size: 36px;margin-top: 10px;"> <div style="margin-left: 20px;font-size: 36px;">
<span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span> <span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span>
</div> </div>
</div> </div>

View File

@@ -26,9 +26,9 @@
</div> </div>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div> <div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div>
<div style="margin-left: 35px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div> <div style="margin-left: 20px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 35px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div> <div style="margin-left: 20px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 35px;font-size: 36px;margin-top: 10px;"> <div style="margin-left: 20px;font-size: 36px;">
<span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span> <span>温馨提示:请取走缴费凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span>
</div> </div>
</div> </div>

View File

@@ -16,19 +16,19 @@
<div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div> <div style="border-bottom: 1px dashed #000;margin: 3px 0;"></div>
</div> </div>
<div style=" font-size: 37px;"> <div style=" font-size: 37px;">
<div style="margin-left: 35px;">&emsp;&emsp;名:<span th:text="${name}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;名:<span th:text="${name}"></span></div>
<div style="margin-left: 35px;">&emsp;&emsp;别:<span th:text="${gender}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;别:<span th:text="${gender}"></span></div>
<div style="margin-left: 35px;">&emsp;&emsp;龄:<span th:text="${age}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;龄:<span th:text="${age}"></span></div>
<div style="margin-left: 35px;">出生日期:<span th:text="${birthDate}"></span></div> <div style="margin-left: 20px;">出生日期:<span th:text="${birthDate}"></span></div>
<div style="margin-left: 35px;">&ensp;&ensp;号:<span th:text="${outpatientNumber}"></span></div> <div style="margin-left: 20px;">&ensp;&ensp;号:<span th:text="${outpatientNumber}"></span></div>
<div style="margin-left: 35px;">就诊科室:<span th:text="${department}"></span></div> <div style="margin-left: 20px;">就诊科室:<span th:text="${department}"></span></div>
<div style="margin-left: 35px;">出诊级别:<span th:text="${visitLevel}"></span></div> <div style="margin-left: 20px;">出诊级别:<span th:text="${visitLevel}"></span></div>
<div style="margin-left: 35px;">就诊医生:<span th:text="${doctor}"></span></div> <div style="margin-left: 20px;">就诊医生:<span th:text="${doctor}"></span></div>
<div style="margin-left: 35px;">&emsp;&emsp;序:<span th:text="${sequence}"></span></div> <div style="margin-left: 20px;">&emsp;&emsp;序:<span th:text="${sequence}"></span></div>
<div style="margin-left: 35px;">挂号日期:<span th:text="${registerDate}"></span></div> <div style="margin-left: 20px;">挂号日期:<span th:text="${registerDate}"></span></div>
<div style="margin-left: 35px;">&ensp;&ensp;用:<span th:text="${totalFee}"></span>&thinsp;</div> <div style="margin-left: 20px;">&ensp;&ensp;用:<span th:text="${totalFee}"></span>&thinsp;</div>
<div style="margin-left: 35px;">支付方式:<span th:text="${paymentMethod}"></span></div> <div style="margin-left: 20px;">支付方式:<span th:text="${paymentMethod}"></span></div>
<div style="margin-left: 35px;">交易流水:<span style="font-size: 35px;" <div style="margin-left: 20px;">交易流水:<span style="font-size: 35px;"
th:text="${transactionNumber}"></span></div> th:text="${transactionNumber}"></span></div>
<div style="width:100%;text-align: center;"> <div style="width:100%;text-align: center;">
<img th:src="${qrCodeBase64}" <img th:src="${qrCodeBase64}"
@@ -36,9 +36,9 @@
</div> </div>
</div> </div>
<div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div> <div style="border-bottom: 1px dashed #000;margin-bottom: 3px;"></div>
<div style="margin-left: 35px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div> <div style="margin-left: 20px;font-size: 36px;">终端编号:<span th:text="${terminalNumber}"></span></div>
<div style="margin-left: 35px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div> <div style="margin-left: 20px;font-size: 36px;">打印时间:<span th:text="${printTime}"></span></div>
<div style="margin-left: 35px;font-size: 36px;margin-top: 10px;"> <div style="margin-left: 20px;font-size: 36px;">
<span>温馨提示:请取走挂号凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span> <span>温馨提示:请取走挂号凭证,并妥善保管。如果对缴费存在疑问,请到人工窗口咨询!</span>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>检验报告单</title>
</head>
<body>
<div>
<!-- 标题区域 -->
<div style="text-align:center; margin-bottom:20px;">
<h2 style="color:#003366;">澜沧拉祜族自治县中医医院血常规检验报告单</h2>
<p>报告时间: <span th:text="${#dates.format(reportTime, 'yyyy-MM-dd HH:mm')}"></span></p>
</div>
<!-- 患者信息表格 -->
<div>
<table style="width:100%; border-collapse:collapse;">
<tr>
<td style="width:15%; padding:5px; border:1px solid #ddd;">姓名</td>
<td style="width:35%; padding:5px; border:1px solid #ddd;" th:text="${patient.name}"></td>
<td style="width:15%; padding:5px; border:1px solid #ddd;">性别</td>
<td style="width:35%; padding:5px; border:1px solid #ddd;" th:text="${patient.gender}"></td>
</tr>
<tr>
<td style="padding:5px; border:1px solid #ddd;">年龄</td>
<td style="padding:5px; border:1px solid #ddd;" th:text="${patient.age}"></td>
<td style="padding:5px; border:1px solid #ddd;">病历号</td>
<td style="padding:5px; border:1px solid #ddd;" th:text="${patient.medicalRecord}"></td>
</tr>
<tr>
<td style="padding:5px; border:1px solid #ddd;">科室</td>
<td style="padding:5px; border:1px solid #ddd;" th:text="${patient.department}"></td>
<td style="padding:5px; border:1px solid #ddd;">床号</td>
<td style="padding:5px; border:1px solid #ddd;" th:text="${patient.bedNumber}"></td>
</tr>
</table>
</div>
<!-- 检测结果表格 -->
<table style="width:100%; border-collapse:collapse; margin-top:20px;">
<thead>
<tr>
<th style="border:1px solid #ddd; padding:8px; text-align:center; background-color:#f2f2f2;">检测项目</th>
<th style="border:1px solid #ddd; padding:8px; text-align:center; background-color:#f2f2f2;">结果</th>
<th style="border:1px solid #ddd; padding:8px; text-align:center; background-color:#f2f2f2;">参考范围</th>
<th style="border:1px solid #ddd; padding:8px; text-align:center; background-color:#f2f2f2;">单位</th>
</tr>
</thead>
<tbody>
<!-- 动态行渲染+异常值红色高亮 -->
<tr th:each="item : ${items}"
th:style="${item.isAbnormal} ? 'color:red;' : ''">
<td style="border:1px solid #ddd; padding:8px; text-align:center;" th:text="${item.name}"></td>
<td style="border:1px solid #ddd; padding:8px; text-align:center;" th:text="${item.result}"></td>
<td style="border:1px solid #ddd; padding:8px; text-align:center;" th:text="${item.referenceRange}"></td>
<td style="border:1px solid #ddd; padding:8px; text-align:center;" th:text="${item.unit}"></td>
</tr>
</tbody>
</table>
<!-- 页脚声明 -->
<div style="margin-top:30px; text-align:right;">
<div>检验医生: <span th:text="${doctor}"></span></div>
<div>审核医生: <span th:text="${reviewer}"></span></div>
<div>声明: 本报告仅对此标本负责如有疑问请3日内联系检验科</div>
</div>
</div>
</body>
</html>

Binary file not shown.