Compare commits
66 Commits
master
...
58c1975b05
| Author | SHA1 | Date | |
|---|---|---|---|
| 58c1975b05 | |||
| 906928ea0f | |||
| 3eb441d41c | |||
| 12f2374ccf | |||
| aa0dc12805 | |||
| 6755206d2e | |||
| 3938301b66 | |||
| 546f644ffd | |||
| ffaa06f934 | |||
| 20b25042b5 | |||
| 503ff3a73e | |||
| ee2115e367 | |||
| c9592dfd90 | |||
| 85b2b1bd87 | |||
| 6c126a6757 | |||
| 9e3608772f | |||
| 32e17374dd | |||
| b2f2e8cd49 | |||
| e36ffeb994 | |||
| 85909ab1f8 | |||
| ac183aa473 | |||
| e945c2cb1f | |||
| 817450ea0b | |||
| 05cea4a7fc | |||
| 44ceb7e671 | |||
| 77fa2397c0 | |||
| 86bf02cf02 | |||
| 6df8da44a7 | |||
| 101de5e6e6 | |||
| 2ba0e48256 | |||
| 18f0a0bb66 | |||
| df17c286fe | |||
| da5c10b632 | |||
| d3e775b720 | |||
| f029719a42 | |||
| b2b9f15f79 | |||
| 4fbe38b04a | |||
| 620bf524db | |||
| 32db058c31 | |||
| 9d01a5d498 | |||
| 46810f941d | |||
| 3f0d3e5026 | |||
| 0601dbf25a | |||
| 4d5ee0c593 | |||
| 2ee5b3015a | |||
| f4edd0189b | |||
| 5c34a03e7f | |||
| f088a42aff | |||
| 7c55b7d2d2 | |||
| 6107203f9f | |||
| 563bc271f3 | |||
| 787892924b | |||
| 40b26f94d8 | |||
| aec28f662a | |||
| fd2baf7d33 | |||
| 478d88f3c4 | |||
| 63a9070f56 | |||
| 5a84be620d | |||
| ed61a25ac4 | |||
| fc1e02264d | |||
| f966dd9387 | |||
| 117f293e83 | |||
| 0ebf6d4258 | |||
| 9f3596abd6 | |||
| 52abbf6a8f | |||
| 0fdb14af2a |
175
pom.xml
175
pom.xml
@@ -4,10 +4,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.dpkj</groupId>
|
||||
<artifactId>银医通-澜沧中医院-DLL-台式机</artifactId>
|
||||
<!-- 银医通-澜沧中医院-DLL-台式机 -->
|
||||
<artifactId>yinyitong-dll-stand</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>ems-express-call-dll</name>
|
||||
<description>ems-express-call-dll</description>
|
||||
<name>yinyitong-dll-stand</name>
|
||||
<description>银医通-澜沧中医院-DLL-台式机</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -34,11 +35,13 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -50,12 +53,14 @@
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 调用DLL -->
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>${jna.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna-platform</artifactId>
|
||||
@@ -68,16 +73,70 @@
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>${pdfbox.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- json处理-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf-->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring5</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Flying Saucer for HTML to Image 把html转换为图片 -->
|
||||
<dependency>
|
||||
<groupId>org.xhtmlrenderer</groupId>
|
||||
<artifactId>flying-saucer-core</artifactId>
|
||||
<version>9.1.22</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ZXing for QR Code 二维码生成-->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSoup HTML Parser -->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.15.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ognl</groupId>
|
||||
<artifactId>ognl</artifactId>
|
||||
<version>3.1.28</version> <!-- 可以根据实际情况调整版本 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.15</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据校验-->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>2.0.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>ems-express-call-dll</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
|
||||
<!--打包时将resource下的文件一起打包-->
|
||||
<resources>
|
||||
<resource>
|
||||
@@ -88,6 +147,102 @@
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- 跳过单元测试 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- 生成API文档插件 -->
|
||||
<!--<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>-->
|
||||
|
||||
<!--打jar包,排除资源文件和依赖jar,同时外部的lib、resource目录加入到classpath中, 用命令java -jar运行jar时就不需要用-Dloader.path指定外部资源路径了! 不需要spring-boot-maven-plugin插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<!--MANIFEST.MF 中 Class-Path 加入前缀!用命令java -jar运行jar时就不用-Dloader.path指定外部资源路径了-->
|
||||
<classpathPrefix>lib/</classpathPrefix>
|
||||
<!--jar包名字是否包含唯一版本标识-->
|
||||
<useUniqueVersions>false</useUniqueVersions>
|
||||
<!--指定含main方法的主类入口-->
|
||||
<mainClass>com.dpkj.Application</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录!用命令java -jar时就不用-Dloader.path指定外部资源路径了 -->
|
||||
<Class-Path>resources/</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<!-- 打包时从jar包里排除资源文件 -->
|
||||
<excludes>
|
||||
<!--<exclude>*.yml</exclude>
|
||||
<exclude>*.xml</exclude>
|
||||
<exclude>templates/**</exclude>
|
||||
<exclude>win32-x86-64/**</exclude>
|
||||
<exclude>win32-x86/**</exclude>-->
|
||||
</excludes>
|
||||
<!-- 指定项目打成jar包输出位置 -->
|
||||
<outputDirectory>${project.build.directory}/output</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 拷贝依赖jar包!插件maven-jar-plugin只是打包排除文件, 而把依赖jar包拷贝到外部lib目录就需要maven-dependency-plugin插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/output/lib/</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!--拷贝资源文件! 插件maven-jar-plugin只负责打包时排除文件, 而把资源文件拷贝到外部resource目录就需要maven-dependency-plugin插件-->
|
||||
<!--<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-resources</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<resources>
|
||||
<resource>
|
||||
<!–拷贝此目录下的所有文件到指定的外部目录。只负责拷贝,而不是从jar包中排除!–>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<!– 把“<resource><directory>”指定目录中的文件输出到此处指定目录 –>
|
||||
<outputDirectory>${project.build.directory}/output/resources</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
|
||||
22
src/main/java/com/dpkj/common/config/ChsConfig.java
Normal file
22
src/main/java/com/dpkj/common/config/ChsConfig.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.dpkj.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/28 14:55
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "dpkj.chs")
|
||||
public class ChsConfig {
|
||||
|
||||
/**
|
||||
* 医保机构编码
|
||||
*/
|
||||
private String orgcode;
|
||||
|
||||
}
|
||||
37
src/main/java/com/dpkj/common/config/MvcConfig.java
Normal file
37
src/main/java/com/dpkj/common/config/MvcConfig.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.dpkj.common.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
/**
|
||||
* mvcConfig配置类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-05-23 15:24:43
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration
|
||||
public class MvcConfig extends WebMvcConfigurationSupport {
|
||||
|
||||
/**
|
||||
* 添加资源过滤处理器
|
||||
* @param registry 资源处理器
|
||||
*/
|
||||
@Override
|
||||
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("classpath:/static/");
|
||||
registry.addResourceHandler("/swagger-ui.html/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/");
|
||||
registry.addResourceHandler("/webjars/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||
.resourceChain(false);
|
||||
|
||||
super.addResourceHandlers(registry);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.dpkj.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -29,4 +28,15 @@ public class PrinterConfig {
|
||||
* 波特率 串口连接下使用
|
||||
*/
|
||||
private Integer baudRate;
|
||||
|
||||
/**
|
||||
* 终端号
|
||||
*/
|
||||
private String terminalNumber;
|
||||
|
||||
/**
|
||||
* 时间格式
|
||||
*/
|
||||
private String timeType;
|
||||
|
||||
}
|
||||
|
||||
36
src/main/java/com/dpkj/common/constant/ChsConst.java
Normal file
36
src/main/java/com/dpkj/common/constant/ChsConst.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
public interface ChsConst {
|
||||
|
||||
/**
|
||||
* 电子凭证二维码解码接口
|
||||
*/
|
||||
String APITYPE_QRCODE = "ec.query";
|
||||
|
||||
/**
|
||||
* 医保电子凭证密码核验接口
|
||||
*/
|
||||
String APITYPE_VERIFY = "cn.nhsa.ec.pwd";
|
||||
|
||||
|
||||
/**
|
||||
* 终端医保电子凭证码解码接口
|
||||
*/
|
||||
String APITYPE_DECODE = "cn.nhsa.qrcode.get";
|
||||
|
||||
/**
|
||||
* 刷脸获取医保用户身份授权接口
|
||||
*/
|
||||
String APITYPE_AUTHORIZATION = "cn.nhsa.ec.auth";
|
||||
|
||||
/**
|
||||
* 刷脸授权获取医保身份接口
|
||||
*/
|
||||
String APITYPE_CHECK = "cn.nhsa.auth.check";
|
||||
|
||||
/**
|
||||
* 结算结果通知接口
|
||||
*/
|
||||
String APITYPE_Notify = "cn.nhsa.settle.notify";
|
||||
|
||||
}
|
||||
264
src/main/java/com/dpkj/common/constant/ErrorCodeConstants.java
Normal file
264
src/main/java/com/dpkj/common/constant/ErrorCodeConstants.java
Normal file
@@ -0,0 +1,264 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ErrorCodeConstants {
|
||||
private ErrorCodeConstants() {
|
||||
throw new AssertionError("This class should not be instantiated.");
|
||||
}
|
||||
|
||||
// 公共错误码
|
||||
public static final Map<Integer, String> COMMON_ERROR_CODE;
|
||||
|
||||
static {
|
||||
COMMON_ERROR_CODE = new HashMap<>();
|
||||
COMMON_ERROR_CODE.put(-1, "应用已经调用过WFSStartUp并且之后并未调用WFSCleanUp");
|
||||
COMMON_ERROR_CODE.put(-2, "应用要求的XFS API版本过高");
|
||||
COMMON_ERROR_CODE.put(-3, "应用要求的XFS API版本过低");
|
||||
COMMON_ERROR_CODE.put(-4, "请求被取消");
|
||||
COMMON_ERROR_CODE.put(-5, "hKey并未对应当前打开的key(注册表项)");
|
||||
COMMON_ERROR_CODE.put(-6, "在当前的key中不存在指定的lpszValueName(键名)");
|
||||
COMMON_ERROR_CODE.put(-7, "在当前的key中不存在指定的lpszSubKey(子键)");
|
||||
COMMON_ERROR_CODE.put(-8, "在当前的key中不存在指定的键值");
|
||||
COMMON_ERROR_CODE.put(-9, "待删除的key包含子键,无法删除");
|
||||
COMMON_ERROR_CODE.put(-10, "返回的键名字符串的长度超过了缓存的长度");
|
||||
COMMON_ERROR_CODE.put(-11, "本项已经为最后一项,没有下一项");
|
||||
COMMON_ERROR_CODE.put(-12, "返回的键值数据的长度超过了缓存的长度");
|
||||
COMMON_ERROR_CODE.put(-13, "函数必须的设备访问,但设备尚未准备好或已超时");
|
||||
COMMON_ERROR_CODE.put(-14, "函数必须的设备访问,但设备出错");
|
||||
COMMON_ERROR_CODE.put(-15, "XFS子系统内发生的内部不一致或其他异常错误");
|
||||
COMMON_ERROR_CODE.put(-16, "lpvOriginal地址参数错误,未指向上次申请的缓存");
|
||||
COMMON_ERROR_CODE.put(-17, "无效的应用句柄(例如由不当的函数调用顺序引起)");
|
||||
COMMON_ERROR_CODE.put(-18, "lpvData参数未指向一个申请的缓存结构");
|
||||
COMMON_ERROR_CODE.put(-19, "当前的服务类(service class)不支持dwCategory参数");
|
||||
COMMON_ERROR_CODE.put(-20, "当前的服务类不支持发出的dwCommand");
|
||||
COMMON_ERROR_CODE.put(-21, "当前的服务类不支持dwEventClass指定的一个或多个事件类");
|
||||
COMMON_ERROR_CODE.put(-22, "hService参数是无效的服务句柄");
|
||||
COMMON_ERROR_CODE.put(-23, "hProvider参数是无效的Provier句柄");
|
||||
COMMON_ERROR_CODE.put(-24, "hWnd参数是无效的窗口句柄");
|
||||
COMMON_ERROR_CODE.put(-25, "hWndReg参数是无效的窗口句柄");
|
||||
COMMON_ERROR_CODE.put(-26, "指针参数不指向可访问内存");
|
||||
COMMON_ERROR_CODE.put(-27, "RequestID参数不符合对服务的未处理请求");
|
||||
COMMON_ERROR_CODE.put(-28, "lpResult参数不是一个指向WFSRESULT结构的指针");
|
||||
COMMON_ERROR_CODE.put(-29, "SP的文件无效或损坏");
|
||||
COMMON_ERROR_CODE.put(-30, "hWnd与usTimerID没有对应当前活动的timer");
|
||||
COMMON_ERROR_CODE.put(-31, "dwTraceLevel参数的值为无效值");
|
||||
COMMON_ERROR_CODE.put(-32, "服务被另一个hService锁定");
|
||||
COMMON_ERROR_CODE.put(-33, "调用被阻塞");
|
||||
COMMON_ERROR_CODE.put(-34, "SP的文件不存在");
|
||||
COMMON_ERROR_CODE.put(-35, "指定的线程不存在");
|
||||
COMMON_ERROR_CODE.put(-36, "timer创建失败");
|
||||
COMMON_ERROR_CODE.put(-37, "应用请求解锁,而此设备并未被加锁");
|
||||
COMMON_ERROR_CODE.put(-38, "XFS卸载SP DLL失败");
|
||||
COMMON_ERROR_CODE.put(-39, "应用程序此前还没有成功的执行WFSStartUp");
|
||||
COMMON_ERROR_CODE.put(-40, "hWndReg窗口没有指定接收任何事件类");
|
||||
COMMON_ERROR_CODE.put(-41, "在该线程上有一个阻塞操作正在进行;此时只允许WFSCancelBlockingCall和WFSIsBlocking");
|
||||
COMMON_ERROR_CODE.put(-42, "申请的空间不足");
|
||||
COMMON_ERROR_CODE.put(-43, "逻辑名无效");
|
||||
COMMON_ERROR_CODE.put(-44, "SPI版本过高");
|
||||
COMMON_ERROR_CODE.put(-45, "SPI版本过低");
|
||||
COMMON_ERROR_CODE.put(-46, "应用请求的服务版本过高");
|
||||
COMMON_ERROR_CODE.put(-47, "应用请求的服务版本过低");
|
||||
COMMON_ERROR_CODE.put(-48, "超时周期到期");
|
||||
COMMON_ERROR_CODE.put(-49, "dwCategory虽然有效,但不被SP支持");
|
||||
COMMON_ERROR_CODE.put(-50, "尽管发出的dwCommand对此服务类别有效,但此服务提供程序或设备不支持发出的dwCommand");
|
||||
COMMON_ERROR_CODE.put(-51, "服务中的两个模块版本不匹配");
|
||||
COMMON_ERROR_CODE.put(-52, "输入参数中包含无效数据");
|
||||
COMMON_ERROR_CODE.put(-53, "函数必须的配置信息访问,但软件出错");
|
||||
COMMON_ERROR_CODE.put(-54, "与服务的连接丢失");
|
||||
COMMON_ERROR_CODE.put(-55, "用户在阻止设备的正确操作");
|
||||
COMMON_ERROR_CODE.put(-56, "尽管作为输入参数传递的数据结构对此服务类别有效,但此服务提供程序或设备不支持该数据结构");
|
||||
COMMON_ERROR_CODE.put(-57, "一些设备能够识别试图欺骗获得重要信息或媒介的恶意物理攻击。在这些情况下,将返回此错误代码,显示用户试图对该设备采取欺骗行为");
|
||||
COMMON_ERROR_CODE.put(-58, "此时被请求的操作无效,或在设备当时的状态下,被请求的操作无效");
|
||||
}
|
||||
|
||||
// 社保卡相关错误码
|
||||
public static final Map<Integer, String> SOCIAL_SECURITYCARD_ERROR_CODE;
|
||||
|
||||
static {
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE = new HashMap<>();
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-1, "卡类型不对");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-2, "无卡");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-3, "有卡未上电");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-4, "卡无应答");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-5, "加载动态库错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-11, "读卡器连接错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-12, "未建立连接");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-13, "(动态库)不支持该命令");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-14, "(发给动态库的)命令参数错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-15, "信息校验和出错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-20, "卡识别码格式错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-21, "内部认证失败(用户卡不合法)");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-22, "传入数据与卡内不符");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-23, "传入数据不合法");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-24, "PSAM卡密钥级别不够");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-31, "用户取消密码输入");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-32, "密码输入操作超时");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-33, "输入密码长度错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-34, "两次输入密码不一致");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-35, "(预留) 初始密码不能交易");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-36, "(预留) 不能改为初始密码");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-41, "运算数据含非法字符");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-42, "运算数据长度错");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-51, "PIN校验失败,剩余次数N次(根据卡返回信息)");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-52, "PIN锁定");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-2201, "无PSAM卡");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-2202, "PSAM卡算法不支持(即PSAM卡内没有SSF33算法或SM4算法)");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-2203, "PSAM卡内没有RKSSSE密钥(3.0卡读个人基本信息需要RKSSSE密钥外部认证)");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-2204, "不需要加密机认证");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-25536, "外部认证失败,剩余可尝试次数2次");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-25537, "外部认证失败,剩余可尝试次数1次");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-25538, "外部认证失败,剩余可尝试次数0次");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-26368, "Lc/Le不正确");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-26881, "命令不接受(无效状态)");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27009, "命令与文件结构不相符、当前文件非所需文件");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27010, "不满足安全条件");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27011, "密钥锁定(算法锁定)鉴别方法锁定");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27012, "引用数据无效、随机数无效");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27013, "不满足使用条件、应用被锁定、应用未选择、余额上溢");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27016, "安全报文数据项不正确、MAC不正确");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27264, "数据域参数不正确");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27265, "不支持该功能、卡中无MF、卡被锁定、应用锁定");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27266, "未找到文件、文件标识相重、SFI不正确");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27267, "未找到记录");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-27272, "未找到引用数据、未找到密钥");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-37634, "MAC无效");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-37635, "应用已被永久锁定、卡片锁定");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-37891, "PSAM卡不支持消费交易");
|
||||
SOCIAL_SECURITYCARD_ERROR_CODE.put(-37894, "所需MAC(或/和TAC)不可用");
|
||||
}
|
||||
|
||||
|
||||
public static final Map<Integer, String> KEYPAD_ERROR_CODE;
|
||||
|
||||
static {
|
||||
KEYPAD_ERROR_CODE = new HashMap<>();
|
||||
|
||||
KEYPAD_ERROR_CODE.put(400, "按键未找到");
|
||||
KEYPAD_ERROR_CODE.put(401, "不支持的模式");
|
||||
KEYPAD_ERROR_CODE.put(402, "访问拒绝");
|
||||
KEYPAD_ERROR_CODE.put(403, "ID无效");
|
||||
KEYPAD_ERROR_CODE.put(404, "Key已存在");
|
||||
KEYPAD_ERROR_CODE.put(406, "Key没有加载");
|
||||
KEYPAD_ERROR_CODE.put(407, "Key使用不对");
|
||||
KEYPAD_ERROR_CODE.put(408, "键盘中没有密码");
|
||||
KEYPAD_ERROR_CODE.put(409, "无效的Key长度");
|
||||
KEYPAD_ERROR_CODE.put(410, "无效的按键");
|
||||
KEYPAD_ERROR_CODE.put(411, "存在不支持的按键");
|
||||
KEYPAD_ERROR_CODE.put(412, "没有激活任何按键");
|
||||
KEYPAD_ERROR_CODE.put(413, "无效的key");
|
||||
KEYPAD_ERROR_CODE.put(414, "没有终止键");
|
||||
KEYPAD_ERROR_CODE.put(415, "最小密码长度无效");
|
||||
KEYPAD_ERROR_CODE.put(416, "协议不支持");
|
||||
KEYPAD_ERROR_CODE.put(417, "无效的数据");
|
||||
KEYPAD_ERROR_CODE.put(418, "不允许进行操作");
|
||||
KEYPAD_ERROR_CODE.put(419, "Key RAM空间不够");
|
||||
KEYPAD_ERROR_CODE.put(420, "还没开始ChipTransaction");
|
||||
KEYPAD_ERROR_CODE.put(421, "算法不支持");
|
||||
KEYPAD_ERROR_CODE.put(422, "格式不支持");
|
||||
KEYPAD_ERROR_CODE.put(423, "HSMSTATE无效");
|
||||
KEYPAD_ERROR_CODE.put(424, "MAC无效");
|
||||
KEYPAD_ERROR_CODE.put(425, "协议无效");
|
||||
KEYPAD_ERROR_CODE.put(426, "格式无效");
|
||||
KEYPAD_ERROR_CODE.put(427, "内容无效");
|
||||
|
||||
KEYPAD_ERROR_CODE.put(-999, "找不到设备服务,原因设备服务名不存在");
|
||||
KEYPAD_ERROR_CODE.put(-998, "无法连接到设备服务,或设备服务未打开");
|
||||
KEYPAD_ERROR_CODE.put(-1, "应用已经调用过WFSStartUp并且之后并未调用WFSCleanUp");
|
||||
KEYPAD_ERROR_CODE.put(-2, "应用要求的XFS API版本过高");
|
||||
KEYPAD_ERROR_CODE.put(-3, "应用要求的XFS API版本过低");
|
||||
KEYPAD_ERROR_CODE.put(-4, "请求被取消");
|
||||
KEYPAD_ERROR_CODE.put(-5, "hKey并未对应当前打开的key(注册表项)");
|
||||
KEYPAD_ERROR_CODE.put(-6, "在当前的key中不存在指定的lpszValueName(键名)");
|
||||
KEYPAD_ERROR_CODE.put(-7, "在当前的key中不存在指定的lpszSubKey(子键)");
|
||||
KEYPAD_ERROR_CODE.put(-8, "在当前的key中不存在指定的键值");
|
||||
KEYPAD_ERROR_CODE.put(-9, "待删除的key包含子键,无法删除");
|
||||
KEYPAD_ERROR_CODE.put(-10, "返回的键名字符串的长度超过了缓存的长度");
|
||||
KEYPAD_ERROR_CODE.put(-11, "本项已经为最后一项,没有下一项");
|
||||
KEYPAD_ERROR_CODE.put(-12, "返回的键值数据的长度超过了缓存的长度");
|
||||
KEYPAD_ERROR_CODE.put(-13, "函数必须的设备访问,但设备尚未准备好或已超时");
|
||||
KEYPAD_ERROR_CODE.put(-14, "函数必须的设备访问,但设备出错");
|
||||
KEYPAD_ERROR_CODE.put(-15, "XFS子系统内发生的内部不一致或其他异常错误");
|
||||
KEYPAD_ERROR_CODE.put(-16, "lpvOriginal地址参数错误,未指向上次申请的缓存");
|
||||
KEYPAD_ERROR_CODE.put(-17, "无效的应用句柄(例如由不当的函数调用顺序引起)");
|
||||
KEYPAD_ERROR_CODE.put(-18, "lpvData参数未指向一个申请的缓存结构");
|
||||
KEYPAD_ERROR_CODE.put(-19, "当前的服务类(service class)不支持dwCategory参数");
|
||||
KEYPAD_ERROR_CODE.put(-20, "当前的服务类不支持发出的dwCommand");
|
||||
KEYPAD_ERROR_CODE.put(-21, "当前的服务类不支持dwEventClass指定的一个或多个事件类");
|
||||
KEYPAD_ERROR_CODE.put(-22, "hService参数是无效的服务句柄");
|
||||
KEYPAD_ERROR_CODE.put(-23, "hProvider参数是无效的Provier句柄");
|
||||
KEYPAD_ERROR_CODE.put(-24, "hWnd参数是无效的窗口句柄");
|
||||
KEYPAD_ERROR_CODE.put(-25, "hWndReg参数是无效的窗口句柄");
|
||||
KEYPAD_ERROR_CODE.put(-26, "指针参数不指向可访问内存");
|
||||
KEYPAD_ERROR_CODE.put(-27, "RequestID参数不符合对服务的未处理请求");
|
||||
KEYPAD_ERROR_CODE.put(-28, "lpResult参数不是一个指向WFSRESULT结构的指针");
|
||||
KEYPAD_ERROR_CODE.put(-29, "SP的文件无效或损坏");
|
||||
KEYPAD_ERROR_CODE.put(-30, "hWnd与usTimerID没有对应当前活动的timer");
|
||||
KEYPAD_ERROR_CODE.put(-31, "dwTraceLevel参数的值为无效值");
|
||||
KEYPAD_ERROR_CODE.put(-32, "服务被另一个hService锁定");
|
||||
KEYPAD_ERROR_CODE.put(-33, "调用被阻塞");
|
||||
KEYPAD_ERROR_CODE.put(-34, "SP的文件不存在");
|
||||
KEYPAD_ERROR_CODE.put(-35, "指定的线程不存在");
|
||||
KEYPAD_ERROR_CODE.put(-36, "timer创建失败");
|
||||
KEYPAD_ERROR_CODE.put(-37, "应用请求解锁,而此设备并未被加锁");
|
||||
KEYPAD_ERROR_CODE.put(-38, "XFS卸载SP DLL失败");
|
||||
KEYPAD_ERROR_CODE.put(-39, "应用程序此前还没有成功的执行WFSStartUp");
|
||||
KEYPAD_ERROR_CODE.put(-40, "hWndReg窗口没有指定接收任何事件类");
|
||||
KEYPAD_ERROR_CODE.put(-41, "在该线程上有一个阻塞操作正在进行;此时只允许WFSCancelBlockingCall和WFSIsBlocking");
|
||||
KEYPAD_ERROR_CODE.put(-42, "申请的空间不足");
|
||||
KEYPAD_ERROR_CODE.put(-43, "逻辑名无效");
|
||||
KEYPAD_ERROR_CODE.put(-44, "SPI版本过高");
|
||||
KEYPAD_ERROR_CODE.put(-45, "SPI版本过低");
|
||||
KEYPAD_ERROR_CODE.put(-46, "应用请求的服务版本过高");
|
||||
KEYPAD_ERROR_CODE.put(-47, "应用请求的服务版本过低");
|
||||
KEYPAD_ERROR_CODE.put(-48, "超时周期到期");
|
||||
KEYPAD_ERROR_CODE.put(-49, "dwCategory虽然有效,但不被SP支持");
|
||||
KEYPAD_ERROR_CODE.put(-50, "尽管发出的dwCommand对此服务类别有效,但此服务提供程序或设备不支持发出的dwCommand");
|
||||
KEYPAD_ERROR_CODE.put(-51, "服务中的两个模块版本不匹配");
|
||||
KEYPAD_ERROR_CODE.put(-52, "输入参数中包含无效数据");
|
||||
KEYPAD_ERROR_CODE.put(-53, "函数必须的配置信息访问,但软件出错");
|
||||
KEYPAD_ERROR_CODE.put(-54, "与服务的连接丢失");
|
||||
KEYPAD_ERROR_CODE.put(-55, "用户在阻止设备的正确操作");
|
||||
KEYPAD_ERROR_CODE.put(-56, "尽管作为输入参数传递的数据结构对此服务类别有效,但此服务提供程序或设备不支持该数据结构");
|
||||
KEYPAD_ERROR_CODE.put(-57, "一些设备能够识别试图欺骗获得重要信息或媒介的恶意物理攻击。在这些情况下,将返回此错误代码,显示用户试图对该设备采取欺骗行为");
|
||||
KEYPAD_ERROR_CODE.put(-58, "此时被请求的操作无效,或在设备当时的状态下,被请求的操作无效");
|
||||
}
|
||||
|
||||
|
||||
public static final Map<Integer, String> MS439_PRINT_ERROR_CODE;
|
||||
|
||||
static {
|
||||
MS439_PRINT_ERROR_CODE = new HashMap<>();
|
||||
MS439_PRINT_ERROR_CODE.put(-100, "FORM未找到");
|
||||
MS439_PRINT_ERROR_CODE.put(-101, "FIELD未找到");
|
||||
MS439_PRINT_ERROR_CODE.put(-102, "缺纸");
|
||||
MS439_PRINT_ERROR_CODE.put(-103, "设备不支持读操作");
|
||||
MS439_PRINT_ERROR_CODE.put(-104, "不支持FLUSH");
|
||||
MS439_PRINT_ERROR_CODE.put(-105, "Media超域");
|
||||
MS439_PRINT_ERROR_CODE.put(-106, "Field语法错误");
|
||||
MS439_PRINT_ERROR_CODE.put(-107, "处理Field时发生错误");
|
||||
MS439_PRINT_ERROR_CODE.put(-108, "Media未找到");
|
||||
MS439_PRINT_ERROR_CODE.put(-109, "设备无法获得范围");
|
||||
MS439_PRINT_ERROR_CODE.put(-110, "无效的Media");
|
||||
MS439_PRINT_ERROR_CODE.put(-111, "无效的Form");
|
||||
MS439_PRINT_ERROR_CODE.put(-112, "无效的Field");
|
||||
MS439_PRINT_ERROR_CODE.put(-113, "Media错误");
|
||||
MS439_PRINT_ERROR_CODE.put(-114, "回收箱满");
|
||||
MS439_PRINT_ERROR_CODE.put(-115, "STACKE满");
|
||||
MS439_PRINT_ERROR_CODE.put(-116, "设备不能翻页");
|
||||
MS439_PRINT_ERROR_CODE.put(-117, "设备不能翻转介质");
|
||||
MS439_PRINT_ERROR_CODE.put(-118, "Shutter执行命令失败");
|
||||
MS439_PRINT_ERROR_CODE.put(-119, "卡纸");
|
||||
MS439_PRINT_ERROR_CODE.put(-120, "文件读取失败");
|
||||
MS439_PRINT_ERROR_CODE.put(-121, "字符集不一致");
|
||||
MS439_PRINT_ERROR_CODE.put(-122, "卡纸");
|
||||
MS439_PRINT_ERROR_CODE.put(-123, "缺纸");
|
||||
MS439_PRINT_ERROR_CODE.put(-124, "墨水用完");
|
||||
MS439_PRINT_ERROR_CODE.put(-125, "色带用完");
|
||||
MS439_PRINT_ERROR_CODE.put(-126, "成象灯不可操作");
|
||||
MS439_PRINT_ERROR_CODE.put(-127, "资源无效");
|
||||
MS439_PRINT_ERROR_CODE.put(-128, "命令序列不对");
|
||||
MS439_PRINT_ERROR_CODE.put(-129, "介质的长度不对");
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/dpkj/common/constant/LexMarkConst.java
Normal file
27
src/main/java/com/dpkj/common/constant/LexMarkConst.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
/**
|
||||
* 利盟台式机 设备调用逻辑名
|
||||
*/
|
||||
public interface LexMarkConst {
|
||||
/**
|
||||
* 身份证读取
|
||||
*/
|
||||
String ID_CARD_READ = "RFIDCardReader";
|
||||
/**
|
||||
* 社保卡读取
|
||||
*/
|
||||
String CARD_READER = "CardReader";
|
||||
/**
|
||||
* 打印机
|
||||
*/
|
||||
String RECEIPT_PRINTER = "ReceiptPrinter";
|
||||
/**
|
||||
* 数字键盘
|
||||
*/
|
||||
String ENCRYPTOR = "Encryptor";
|
||||
/**
|
||||
* 扫描仪
|
||||
*/
|
||||
String BARCODE_READER = "BarcodeReader";
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.dpkj.common.constant;
|
||||
|
||||
/**
|
||||
* 利盟台式机 中间件 方法名常量
|
||||
*/
|
||||
public interface MiddlewareFunctionsConst {
|
||||
|
||||
/**-------------------- 公共模块 ---------------------*/
|
||||
/**
|
||||
* 打开设备(异步)/ (同步)
|
||||
*/
|
||||
String OPEN_CONNECTION = "OpenConnection";
|
||||
String OPEN_CONNECTION_SYNC = "OpenConnectionSync";
|
||||
|
||||
/**
|
||||
* 关闭设备(异步)/ (同步)
|
||||
*/
|
||||
String CLOSE_CONNECTION = "CloseConnection";
|
||||
String CLOSE_CONNECTION_SYNC = "CloseConnectionSync";
|
||||
|
||||
|
||||
/**
|
||||
* 复位(初始化)
|
||||
*/
|
||||
String RESET = "Reset";
|
||||
|
||||
/** ------------------- 读卡模块 --------------------*/
|
||||
/**
|
||||
* 进卡读卡(异步)/ (同步)
|
||||
*/
|
||||
String ACCEPT_AND_READ_TRACKS = "AcceptAndReadTracks";
|
||||
String ACCEPT_AND_READ_TRACKS_SYNC = "AcceptAndReadTracksSync";
|
||||
|
||||
/**
|
||||
* 同步取消进卡
|
||||
*/
|
||||
String CANCEL_ACCEPT = "CancelAccept";
|
||||
|
||||
/**
|
||||
* 异步Chip(IC卡片)数据交互 / 同步Chip(IC卡片)数据交互
|
||||
*/
|
||||
String CHIP_IO = "ChipIo";
|
||||
String CHIP_IO_SYNC = "ChipIoSync";
|
||||
|
||||
/**
|
||||
* IC卡上电
|
||||
*/
|
||||
String CHIPPOWER = "ChipPower";
|
||||
|
||||
/**
|
||||
* 退卡
|
||||
*/
|
||||
String EJECT = "Eject";
|
||||
|
||||
/**
|
||||
* 获取属性
|
||||
*/
|
||||
String GET_CAPABILITIES = "GetCapabilities";
|
||||
|
||||
/**
|
||||
* 获取状态 同步/异步
|
||||
*/
|
||||
String GET_STATUS = "GetStatus";
|
||||
String GET_STATUS_SYNC = "GetStatusSync";
|
||||
|
||||
/**
|
||||
* 社保卡读取 读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS = "iReadCardBas";
|
||||
|
||||
/**
|
||||
* 社保卡读取 基于加密机的读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS_HSM_STEP1 = "iReadCardBas_HSM_Step1";
|
||||
|
||||
/**
|
||||
* 社保卡读取 基于加密机的读基本信息
|
||||
*/
|
||||
String I_READ_CARD_BAS_HSM_STEP2 = "iReadCardBas_HSM_Step2";
|
||||
|
||||
|
||||
/** -------------------- 数字键盘模块 -----------------*/
|
||||
/**
|
||||
* 明文输入
|
||||
*/
|
||||
String INPUT_DATA = "InputData";
|
||||
|
||||
/**
|
||||
* 密文输入
|
||||
*/
|
||||
String INPUT_PIN = "InputPIN";
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
*/
|
||||
String CANCEL_INPUT = "CancelInput";
|
||||
|
||||
/** ------------------ 条码读取模块 -------------------*/
|
||||
|
||||
/**
|
||||
* 扫描条码
|
||||
*/
|
||||
String SCAN_BARCODE = "ScanBarcode";
|
||||
|
||||
/**
|
||||
* 取消扫描
|
||||
*/
|
||||
String CANCEL_SCAN = "CancelScan";
|
||||
|
||||
/**
|
||||
* 获取扫描仪状态
|
||||
*/
|
||||
String GET_SCANNER_STATUS = "GetStatus";
|
||||
|
||||
/**
|
||||
* 获取能力
|
||||
*/
|
||||
String GET_SCANNER_CAPABILITIES = "GetCapabilities";
|
||||
|
||||
}
|
||||
63
src/main/java/com/dpkj/common/dto/LexMarkDTO.java
Normal file
63
src/main/java/com/dpkj/common/dto/LexMarkDTO.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟请求参数DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:46:44
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 默认异步
|
||||
* 0:代表同步,1:代表异步,3:代表属性
|
||||
*/
|
||||
private Integer methodType = 1;
|
||||
|
||||
/**
|
||||
* 默认:com.gwi.device
|
||||
* 插件名称:如果是设备调用,则固定填写com.gwi.device;如果是插件调用,此处填
|
||||
* 写插件动态库文件名(去掉文件名前面的lib和文件后缀名,如:GWI_Plugin)
|
||||
*/
|
||||
private String pluginName = "com.gwi.device";
|
||||
|
||||
/**
|
||||
* 固定填写execute
|
||||
*/
|
||||
private String pluginMethod = "execute";
|
||||
|
||||
/**
|
||||
* 设备名。如果是设备调用,则填写设备名称,需要和SP服务配置中的 DevList.ini 配置的设备名称一致;
|
||||
* 如果是插件调用,可忽略此参数
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 调用id,应用生成,用于区分不同的调用
|
||||
*/
|
||||
private Integer callID;
|
||||
|
||||
/**
|
||||
* 调用的函数名称,设备执行的动作名称,简称动作名
|
||||
*/
|
||||
private String actionName;
|
||||
|
||||
/**
|
||||
* 设备执行的输入参数,格式为json字符串(注意,此处为字符串,不是json对象)
|
||||
*/
|
||||
private String param;
|
||||
|
||||
}
|
||||
|
||||
115
src/main/java/com/dpkj/common/dto/LexMarkResultDTO.java
Normal file
115
src/main/java/com/dpkj/common/dto/LexMarkResultDTO.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟接口返回值DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 11:03:06
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkResultDTO <T> implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* 利盟服务返回的参数
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String param;
|
||||
|
||||
/**
|
||||
* 实际返回的接受的参数对象(通过param转换过后的)
|
||||
*/
|
||||
private T data;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Param {
|
||||
|
||||
/**
|
||||
* 请求ID
|
||||
*/
|
||||
private int RequestID;
|
||||
|
||||
/**
|
||||
* 命令编码
|
||||
*/
|
||||
private int dwCommandCode;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String eventName;
|
||||
|
||||
/**
|
||||
* 事件类型编码
|
||||
*/
|
||||
private int eventType;
|
||||
|
||||
/**
|
||||
* 服务
|
||||
*/
|
||||
private int hService;
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
58
src/main/java/com/dpkj/common/dto/LexMarkResultVO.java
Normal file
58
src/main/java/com/dpkj/common/dto/LexMarkResultVO.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.dpkj.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 利盟接口返回值DTO
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 11:03:06
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LexMarkResultVO<T> implements Serializable {
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private T param;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
}
|
||||
|
||||
139
src/main/java/com/dpkj/common/exception/ControllerAdvice.java
Normal file
139
src/main/java/com/dpkj/common/exception/ControllerAdvice.java
Normal file
@@ -0,0 +1,139 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* controller控制器异常处理接口实现类
|
||||
* <p>其它module可以集成此类进行controller层的异常处理</p>
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RestControllerAdvice(annotations = {RestController.class, Controller.class})
|
||||
public class ControllerAdvice {
|
||||
|
||||
/**
|
||||
* controller方法中的参数校验失败,但是前提是要使用
|
||||
* #@Validated注解开启参数校验
|
||||
*
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = MethodArgumentNotValidException.class)
|
||||
public Result<String> bindingException(MethodArgumentNotValidException e) {
|
||||
// 获得所有校验出错的返回集
|
||||
BindingResult bindingResult = e.getBindingResult();
|
||||
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
|
||||
// 循环获得所有校验异常的字段
|
||||
Map<String, String> fieldMap = new HashMap<>();
|
||||
for (FieldError fieldError : fieldErrors) {
|
||||
fieldMap.put(fieldError.getField(), fieldError.getDefaultMessage());
|
||||
}
|
||||
|
||||
String errMsg = fieldMap.values().toString().replaceAll("]", "").replaceAll("\\[", "");
|
||||
log.warn(errMsg);
|
||||
// 返回给前端
|
||||
return Result.error(errMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理空指针异常
|
||||
* @param nullPointerException 空指针异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = NullPointerException.class)
|
||||
public Result<String> nullPointException(NullPointerException nullPointerException) {
|
||||
log.error("空指针异常类型: {},信息: {}", nullPointerException.getClass(), nullPointerException);
|
||||
return Result.error(ErrorEnum.NULL_POINTER_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有的运行时异常,抛出异常
|
||||
* @param throwable 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = Throwable.class)
|
||||
public Result<String> handleException(Throwable throwable) {
|
||||
log.error("异常类型: {}, {}, 信息为: {}", throwable.getCause(), throwable.getClass(), throwable.getMessage());
|
||||
if (throwable instanceof RRException){
|
||||
RRException rrException = (RRException) throwable;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* http信息无可读
|
||||
* @param e 异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpMessageNotReadableException.class)
|
||||
public Result<String> httpMessageNotReadAbleException(HttpMessageNotReadableException e){
|
||||
log.warn("异常类型: {} 无可读信息: ", e.getClass(), e);
|
||||
return Result.error(ErrorEnum.HTTP_MESSAGE_NOT_READABLE_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行时异常
|
||||
* @param e 运行异常对象
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
public Result<String> runtimeException(RuntimeException e){
|
||||
log.error("运行时异常:", e);
|
||||
if (e instanceof RRException){
|
||||
RRException rrException = (RRException) e;
|
||||
return Result.error(rrException.getCode(), rrException.getMsg());
|
||||
}
|
||||
return Result.error(ErrorEnum.RUNTIME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求不支持
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
|
||||
public Result<String> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
|
||||
log.warn("暂不支持该请求: ", e);
|
||||
return Result.error("暂不支持此请求方式");
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数类型错误
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public Result<String> methodArgument(MethodArgumentTypeMismatchException e){
|
||||
log.warn("参数发生错误: ", e);
|
||||
return Result.error("参数发生错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 缺少请求参数
|
||||
* @param e 缺少请求参数异常
|
||||
* @return Result
|
||||
*/
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public Result<String> exception(MissingServletRequestParameterException e){
|
||||
log.warn("缺少请求参数: ", e);
|
||||
return Result.error("缺少请求参数");
|
||||
}
|
||||
|
||||
}
|
||||
70
src/main/java/com/dpkj/common/exception/ErrorEnum.java
Normal file
70
src/main/java/com/dpkj/common/exception/ErrorEnum.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
/**
|
||||
* 错误返回枚举类
|
||||
*/
|
||||
@Getter
|
||||
public enum ErrorEnum implements ErrorInterface{
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* 成功范围
|
||||
* @code 200
|
||||
* @apiNote 访问成功
|
||||
*/
|
||||
SUCCESS(200, "访问成功"),
|
||||
|
||||
/**
|
||||
* 系统异常
|
||||
* @code 500
|
||||
* @apiNote 系统异常
|
||||
*/
|
||||
FAIL(500, "系统异常"),
|
||||
|
||||
/**
|
||||
* 调用对象位空(null)
|
||||
* @code 10002
|
||||
* @apiNote 调用对象位空(null)
|
||||
*/
|
||||
NULL_POINTER_EXCEPTION(501, "调用对象位空(null)"),
|
||||
|
||||
/**
|
||||
* 运行时异常,
|
||||
* @code 10003
|
||||
* @apiNote 系统发生错误,请联系管理员
|
||||
*/
|
||||
RUNTIME_EXCEPTION(502, "系统发生错误,请联系管理员"),
|
||||
|
||||
/**
|
||||
* Http传入的参数没有可以读的数据
|
||||
* @code 10004
|
||||
* @apiNote 传入的数据不可读
|
||||
*/
|
||||
HTTP_MESSAGE_NOT_READABLE_EXCEPTION(503, "传入的数据不可读"),
|
||||
|
||||
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
;
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
ErrorEnum(Integer code, String message){
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage(){
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/dpkj/common/exception/ErrorInterface.java
Normal file
23
src/main/java/com/dpkj/common/exception/ErrorInterface.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
/**
|
||||
* 错误枚举接口,所有的错误枚举都需要实现该接口,如果需要自定义
|
||||
* 错误信息,可通过实现该接口与RespBean进行使用
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @see com.dpkj.common.vo.Result
|
||||
* @since 2023-07-27 13:05:00
|
||||
*/
|
||||
public interface ErrorInterface {
|
||||
|
||||
/**
|
||||
* 获取响应码
|
||||
*/
|
||||
int getCode();
|
||||
|
||||
/**
|
||||
* 获取响应信息
|
||||
*/
|
||||
String getMessage();
|
||||
|
||||
}
|
||||
59
src/main/java/com/dpkj/common/exception/RRException.java
Normal file
59
src/main/java/com/dpkj/common/exception/RRException.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.dpkj.common.exception;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 总的异常,所有的自定义异常都需要继承类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2023-07-24 09:42:00
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class RRException extends RuntimeException{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String msg;
|
||||
private int code = 500;
|
||||
|
||||
public RRException(){
|
||||
super("系统错误");
|
||||
this.msg = "系统错误";
|
||||
}
|
||||
|
||||
public RRException(Throwable throwable){
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
public RRException(String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(int code, String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
public RRException(ErrorInterface error){
|
||||
super(error.getMessage());
|
||||
this.code = error.getCode();
|
||||
this.msg = error.getMessage();
|
||||
}
|
||||
|
||||
public RRException(int code,String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
350
src/main/java/com/dpkj/common/utils/TemplateUtils.java
Normal file
350
src/main/java/com/dpkj/common/utils/TemplateUtils.java
Normal file
@@ -0,0 +1,350 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.oned.Code128Writer;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
|
||||
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 org.thymeleaf.templateresolver.StringTemplateResolver;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xhtmlrenderer.layout.SharedContext;
|
||||
import org.xhtmlrenderer.simple.Graphics2DRenderer;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 模板服务类
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-01-18 15:33:51
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class TemplateUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 生成小票图片
|
||||
*
|
||||
* @param data json数据,用来填充模板
|
||||
* @param template 模板(html字符串或者模板名称)
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param saveDir 图片的保存路径,如果为空,那么不进行图片的保存
|
||||
* @return 图片字节数组
|
||||
*/
|
||||
public byte[] generateReceiptImage(JSONObject data, String template, int width, int height, StringBuilder saveDir) {
|
||||
try {
|
||||
// 获取模板上下文
|
||||
Context context = this.getContext(data);
|
||||
|
||||
TemplateEngine templateEngine = new TemplateEngine();
|
||||
if (checkIsHtml(template)) {
|
||||
StringTemplateResolver resolver = new StringTemplateResolver();
|
||||
resolver.setTemplateMode("HTML");
|
||||
// 设置模板引擎使用这个自定义的模板解析器
|
||||
templateEngine.setTemplateResolver(resolver);
|
||||
}else {
|
||||
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);
|
||||
}
|
||||
|
||||
// 渲染模板
|
||||
String html = templateEngine.process(template, context);
|
||||
|
||||
BufferedImage image = this.generate(html, width, height);
|
||||
|
||||
// 保存图片
|
||||
if (saveDir != null && !"".equals(saveDir.toString())) {
|
||||
String outputPath = saveDir.toString() + "/genera_image_" + System.currentTimeMillis() + ".png";
|
||||
ImageIO.write(image, "PNG", new File(outputPath));
|
||||
saveDir.delete(0, saveDir.length());
|
||||
saveDir.append(outputPath);
|
||||
}
|
||||
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "PNG", byteOutputStream);
|
||||
return byteOutputStream.toByteArray();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成图片
|
||||
* @param html html内容
|
||||
*/
|
||||
private BufferedImage generate(String html, int width, int height){
|
||||
try {
|
||||
// 转换为xhtml
|
||||
String xhtml = this.htmlToXhtml(html);
|
||||
|
||||
// 转换为document
|
||||
Document document = this.xhtmlToDocument(xhtml);
|
||||
|
||||
// 生成图片
|
||||
return createImageToDocument(document, width, height);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RRException("图片打印失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过JsonObject进行context内容填充
|
||||
* @param data jsonObject
|
||||
* @return context
|
||||
*/
|
||||
private Context getContext(JSONObject data) {
|
||||
// 创建Thymeleaf上下文
|
||||
Context context = new Context();
|
||||
if ( data != null) {
|
||||
Set<String> keys = data.keySet();
|
||||
for (String key : keys) {
|
||||
// 判单是否有图片生成,统一后面采用的是_2base64Type
|
||||
String[] split = key.split("_");
|
||||
if (split.length > 1 && split[1].equals("2base64Type")) {
|
||||
int type = split.length > 2 ? Integer.parseInt(split[2]) : 1;
|
||||
int width = split.length > 2 ? Integer.parseInt(split[3]) : 100;
|
||||
int height = split.length > 3 ? Integer.parseInt(split[4]) : 100;
|
||||
// 如果是图片类型,需要进行base64转换
|
||||
String base64 = this.generateQRCode(type, String.valueOf(data.get(key)), width, height);
|
||||
context.setVariable(split[0], "data:image/jpeg;base64," + base64);
|
||||
} else {
|
||||
// 普通字段直接设置
|
||||
context.setVariable(key, data.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
private String generateQRCode(int type, String content, int width, int height) {
|
||||
try {
|
||||
BufferedImage qrImage = null;
|
||||
BitMatrix bitMatrix = null;
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符编码为 UTF-8
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 设置纠错级别
|
||||
// 设置外边距为 0 以去除白边
|
||||
hints.put(EncodeHintType.MARGIN, 0);
|
||||
|
||||
if (type == 1) {
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
} else if (type == 2) {
|
||||
Code128Writer barcodeWriter = new Code128Writer();
|
||||
bitMatrix = barcodeWriter.encode(content, BarcodeFormat.CODE_128, width, height, hints);
|
||||
|
||||
qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
|
||||
}
|
||||
if ( qrImage == null ){
|
||||
throw new RRException("图片渲染失败");
|
||||
}
|
||||
|
||||
qrImage.createGraphics();
|
||||
Graphics2D graphics = (Graphics2D) qrImage.getGraphics();
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
graphics.setColor(Color.BLACK);
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
if (bitMatrix.get(i, j)) {
|
||||
graphics.fillRect(i, j, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(qrImage, "png", baos);
|
||||
return Base64.getEncoder().encodeToString(baos.toByteArray());
|
||||
} catch (Exception e) {
|
||||
log.error("二维码/条形码生成失败", e);
|
||||
throw new RRException("二维码/条形码生成失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xhtml 转换为 Document
|
||||
* @param xhtml xhtml
|
||||
* @return document
|
||||
* @throws Exception e
|
||||
*/
|
||||
private Document xhtmlToDocument(String xhtml) throws Exception {
|
||||
// 创建DocumentBuilder
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setValidating(false);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
// 解析XHTML字符串为Document
|
||||
return builder.parse(new ByteArrayInputStream(xhtml.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换,将html转换为xhtml
|
||||
* @param html html内容
|
||||
* @return xhtml
|
||||
*/
|
||||
private String htmlToXhtml(String html) {
|
||||
org.jsoup.nodes.Document doc = Jsoup.parse(html);
|
||||
doc.outputSettings()
|
||||
.syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml)
|
||||
.charset(StandardCharsets.UTF_8);
|
||||
|
||||
// 不使用外部DTD
|
||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
"<head>\n" +
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n" +
|
||||
"<style type=\"text/css\">\n" +
|
||||
"body { font-family: SimSun, serif; }\n" +
|
||||
"</style>\n" +
|
||||
"</head>\n" +
|
||||
"<body>\n" +
|
||||
doc.body().html() +
|
||||
"\n</body>\n" +
|
||||
"</html>";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过document转换为图片
|
||||
* @param document doc
|
||||
* @param width 图片的宽度
|
||||
* @param height 图片的高度
|
||||
* @return bufferedImage
|
||||
*/
|
||||
private BufferedImage createImageToDocument(Document document, int width, int height) {
|
||||
try {
|
||||
// 创建Dimension对象
|
||||
Dimension dimension = new Dimension(width, height);
|
||||
|
||||
// 创建图片
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D graphics = (Graphics2D) image.getGraphics();
|
||||
|
||||
// 设置白色背景
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, width, height);
|
||||
|
||||
// 设置渲染提示
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
// 创建渲染器
|
||||
Graphics2DRenderer renderer = new Graphics2DRenderer();
|
||||
renderer.setDocument(document, null);
|
||||
|
||||
// 设置渲染参数
|
||||
SharedContext sharedContext = renderer.getSharedContext();
|
||||
sharedContext.setInteractive(false);
|
||||
sharedContext.setDPI(256f);
|
||||
|
||||
// 使用系统默认字体,假设系统默认字体支持UTF - 8
|
||||
Font font = new Font(Font.DIALOG, Font.PLAIN, 20);
|
||||
graphics.setFont(font);
|
||||
|
||||
// 使用Dimension对象进行布局
|
||||
renderer.layout(graphics, dimension);
|
||||
renderer.render(graphics);
|
||||
|
||||
graphics.dispose();
|
||||
return image;
|
||||
} catch (Exception e) {
|
||||
throw new RRException("渲染图片失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验这个模板内容是不是html字符串,而非模板名称
|
||||
* @param template template
|
||||
* @return 是否是html字符串
|
||||
*/
|
||||
private boolean checkIsHtml(String template){
|
||||
try {
|
||||
String pattern = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
|
||||
Pattern r = Pattern.compile(pattern);
|
||||
return r.matcher(template).find();
|
||||
}catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将document对象转换为字符串
|
||||
* @param doc document
|
||||
* @return document转换为的字符串
|
||||
*/
|
||||
private String documentToString(Document doc) {
|
||||
try {
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
transformer.transform(new DOMSource(doc), new StreamResult(writer));
|
||||
return writer.getBuffer().toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
205
src/main/java/com/dpkj/common/utils/ThirdService.java
Normal file
205
src/main/java/com/dpkj/common/utils/ThirdService.java
Normal file
@@ -0,0 +1,205 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.util.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 第三方服务,主要是调用打印机等
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:45:01
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ThirdService {
|
||||
|
||||
@Value("${app.custom.lexMarkServiceIp}")
|
||||
private String lexMarkServiceIp;
|
||||
@Value("${app.custom.lexMarkServicePort}")
|
||||
private String lexMarkServicePort;
|
||||
|
||||
private static final Map<String, String> devNameMap = new HashMap<>();
|
||||
static {
|
||||
devNameMap.put("HtmPrinter", "激光打印机");
|
||||
devNameMap.put("ReceiptPrinter", "凭条打印机");
|
||||
}
|
||||
|
||||
/**
|
||||
* 利盟台式机-立体机 接口请求
|
||||
*
|
||||
* @param lexMarkDTO 请求DTO
|
||||
* @param clazz 返回类型
|
||||
* @return result
|
||||
*/
|
||||
public <T> LexMarkResultDTO<T> callDevice(LexMarkDTO lexMarkDTO, Class<T> clazz) {
|
||||
try {
|
||||
URL url = new URL(lexMarkServiceIp + ":" + lexMarkServicePort + "/CallDevice");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
|
||||
// 将LexMarkDTO对象转换为JSON字符串
|
||||
String jsonInputString = JSON.toJSONString(lexMarkDTO);
|
||||
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
|
||||
wr.write(input, 0, input.length);
|
||||
log.info(jsonInputString);
|
||||
}
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||
log.error("利盟服务请求失败,响应码:{},请求参数:{}", responseCode, lexMarkDTO);
|
||||
throw new RRException("利盟服务请求失败,响应码:" + responseCode);
|
||||
}
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
// 将响应JSON字符串转换为LexMarkResultDTO对象
|
||||
LexMarkResultDTO<T> lexMarkResultDTO = JSON.parseObject(response.toString(), LexMarkResultDTO.class);
|
||||
// if (lexMarkResultDTO.getResult() != 0) {
|
||||
// log.error("利盟服务请求出错:{}", lexMarkResultDTO);
|
||||
// throw new RRException(lexMarkResultDTO.toString());
|
||||
// }
|
||||
|
||||
// 实例化param位data
|
||||
String param = lexMarkResultDTO.getParam();
|
||||
if (!StringUtils.isEmpty(param)) {
|
||||
try {
|
||||
T t = JSON.parseObject(param, clazz);
|
||||
lexMarkResultDTO.setData(t);
|
||||
}catch (Exception e){
|
||||
log.error("类型转换失败");
|
||||
throw new RRException("转换param位data时,类型与实际类型不匹配");
|
||||
}
|
||||
}
|
||||
|
||||
return lexMarkResultDTO;
|
||||
} catch (Exception e) {
|
||||
log.error("利盟服务请求失败:{}", lexMarkDTO, e);
|
||||
if (e instanceof RRException) {
|
||||
throw new RRException(((RRException) e).getCode(), e.getMessage());
|
||||
}
|
||||
throw new RRException("利盟服务请求失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 数据对象的data采用JSONObject进行接收
|
||||
*
|
||||
* @param lexMarkDTO 请求参数
|
||||
* @return result
|
||||
*/
|
||||
public LexMarkResultDTO<JSONObject> callDevice(LexMarkDTO lexMarkDTO) {
|
||||
return callDevice(lexMarkDTO, JSONObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开设备连接或者 链接+初始化
|
||||
* @param devName 设备名称
|
||||
* @param resterType 初始化类型,如果不设置,那么就不会进行初始化
|
||||
*/
|
||||
public void open(String devName, Integer resterType) {
|
||||
// 优先自动连接对应的设备
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("OpenConnection");
|
||||
lexMarkDTO.setCallID(19283);
|
||||
lexMarkDTO.setDevName(devName);
|
||||
lexMarkDTO.setPluginMethod("exec");
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("", String.format("{\"ServiceName\":\"%s\",\"TimeOut\":90000}", devName));
|
||||
lexMarkDTO.setParam(param.toString());
|
||||
LexMarkResultDTO<JSONObject> jsonObjectLexMarkResultDTO = this.callDevice(lexMarkDTO, JSONObject.class);
|
||||
JSONObject data = jsonObjectLexMarkResultDTO.getData();
|
||||
if (data != null) {
|
||||
if (!String.valueOf(data.get("result")).equals("0")) {
|
||||
throw new RRException("设备: " + devNameMap.get(devName) + " 打开失败!");
|
||||
}
|
||||
}
|
||||
|
||||
// 打开后直接进行重置
|
||||
if ( resterType != null && data != null) {
|
||||
lexMarkDTO.setActionName("Reset");
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("", String.format("{\"ResetAction\":%d,\"binNumber\":0}", resterType));
|
||||
lexMarkDTO.setParam(jsonObject.toString());
|
||||
LexMarkResultDTO<JSONObject> resultDTO = this.callDevice(lexMarkDTO, JSONObject.class);
|
||||
JSONObject data1 = resultDTO.getData();
|
||||
if (data1 != null) {
|
||||
if (!String.valueOf(data1.get("result")).equals("0")) {
|
||||
throw new RRException("设备: " + devNameMap.get(devName) + " _ " + resterType + " 初始化失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭设备练级
|
||||
* @param devName 设备名称
|
||||
*/
|
||||
public void close(String devName) {
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("CloseConnection");
|
||||
lexMarkDTO.setCallID(19283);
|
||||
lexMarkDTO.setDevName(devName);
|
||||
lexMarkDTO.setPluginMethod("exec");
|
||||
LexMarkResultDTO<JSONObject> jsonObjectLexMarkResultDTO = this.callDevice(lexMarkDTO, JSONObject.class);
|
||||
JSONObject data = jsonObjectLexMarkResultDTO.getData();
|
||||
if (data != null) {
|
||||
if (!String.valueOf(data.get("result")).equals("0")) {
|
||||
throw new RRException("设备: " + devNameMap.get(devName) + " 关闭失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切纸,但是目前凭条和ms439打印机都是可以自动切纸的
|
||||
* @param devName 设备名称
|
||||
* @param actionName action名称,实际的动作函数名称
|
||||
* @param mediaType 媒介类型
|
||||
*/
|
||||
public void cutPaper(String devName, String actionName, Integer mediaType){
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName(actionName);
|
||||
lexMarkDTO.setCallID(19283);
|
||||
lexMarkDTO.setDevName(devName);
|
||||
lexMarkDTO.setPluginMethod("exec");
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("", String.format("{\"mediaCtrol\":%d}", mediaType));
|
||||
lexMarkDTO.setParam(param.toString());
|
||||
|
||||
LexMarkResultDTO<JSONObject> jsonObjectLexMarkResultDTO = this.callDevice(lexMarkDTO, JSONObject.class);
|
||||
JSONObject data = jsonObjectLexMarkResultDTO.getData();
|
||||
if (data != null) {
|
||||
if (!String.valueOf(data.get("result")).equals("0")) {
|
||||
throw new RRException("设备: " + devNameMap.get(devName) + " 切纸失败!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
87
src/main/java/com/dpkj/common/utils/ThirdServiceUtil.java
Normal file
87
src/main/java/com/dpkj/common/utils/ThirdServiceUtil.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package com.dpkj.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultVO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* 第三方服务,主要是调用打印机等
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:45:01
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ThirdServiceUtil {
|
||||
|
||||
@Value("${app.custom.lexMarkServiceIp}")
|
||||
private String lexMarkServiceIp;
|
||||
@Value("${app.custom.lexMarkServicePort}")
|
||||
private String lexMarkServicePort;
|
||||
|
||||
/**
|
||||
* 利盟台式机-立体机 接口请求
|
||||
* @param lexMarkDTO 请求DTO
|
||||
* @return result
|
||||
*/
|
||||
public <T> T callDevice(LexMarkDTO lexMarkDTO, Class<T> responseType) {
|
||||
try {
|
||||
String urlStr = lexMarkServiceIp + ":" + lexMarkServicePort + "/CallDevice";
|
||||
URL url = new URL(urlStr);
|
||||
log.info("开始请求利盟服务,URL: {}, 请求体: {}", urlStr, JSON.toJSONString(lexMarkDTO));
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
// 将 LexMarkDTO 对象转换为 JSON 字符串
|
||||
String jsonInputString = JSON.toJSONString(lexMarkDTO);
|
||||
try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
|
||||
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
|
||||
wr.write(input, 0, input.length);
|
||||
}
|
||||
int responseCode = connection.getResponseCode();
|
||||
log.info("利盟服务响应码: {}", responseCode);
|
||||
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||
throw new RRException("利盟服务请求失败,响应码:" + responseCode);
|
||||
}
|
||||
// 指定编码为 UTF-8
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
String inputLine;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
String responseStr = response.toString();
|
||||
log.info("利盟服务响应内容: {}", responseStr);
|
||||
// 将响应 JSON 字符串转换为泛型对象
|
||||
T result = JSON.parseObject(responseStr, responseType);
|
||||
if (result instanceof LexMarkResultVO && ((LexMarkResultVO) result).getResult() != 0) {
|
||||
throw new RRException(result.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("利盟服务请求发生异常", e);
|
||||
if (e instanceof RRException) {
|
||||
throw new RRException(((RRException) e).getCode(), e.getMessage());
|
||||
}
|
||||
throw new RRException("利盟服务请求失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dpkj.common.vo;
|
||||
|
||||
import com.dpkj.common.constant.CommonConst;
|
||||
import com.dpkj.common.exception.ErrorEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -27,6 +28,11 @@ public class Result<T> implements Serializable {
|
||||
*/
|
||||
private Integer code = 0;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private int state;
|
||||
|
||||
/**
|
||||
* 返回数据对象 data
|
||||
*/
|
||||
@@ -41,41 +47,61 @@ public class Result<T> implements Serializable {
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok() {
|
||||
return ok("", null);
|
||||
return ok("", null, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(String msg) {
|
||||
return ok(msg, null);
|
||||
return ok(msg, null, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(T data) {
|
||||
return error("", data);
|
||||
return ok("", data, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(String msg, T data) {
|
||||
return ok(msg, data, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(String msg, T data, int state) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConst.SC_200);
|
||||
r.setMessage(msg);
|
||||
r.setResult(data);
|
||||
r.setState(state);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String msg, T data) {
|
||||
return error(CommonConst.SC_500, msg, data);
|
||||
return error(CommonConst.SC_500, msg, data, 0);
|
||||
}
|
||||
public static <T> Result<T> error(String msg, int state) {
|
||||
return error(CommonConst.SC_500, msg, null, state);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String msg) {
|
||||
return error(CommonConst.SC_500, msg, null);
|
||||
return error(CommonConst.SC_500, msg, null, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(ErrorEnum errorEnum) {
|
||||
return error(errorEnum.getCode(), errorEnum.getMessage(), null, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String message) {
|
||||
return error(code, message, null, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String msg, T data) {
|
||||
return error(code, msg, data, 0);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String msg, T data, int state) {
|
||||
Result<T> r = new Result<T>();
|
||||
r.setCode(code);
|
||||
r.setMessage(msg);
|
||||
r.setSuccess(false);
|
||||
r.setResult(data);
|
||||
r.setState(state);
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.dpkj.modules.barcode.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.barcode.service.BarCodeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.controller
|
||||
* @Author: wzc
|
||||
* @Description: 条码读取
|
||||
* @CreateTime: 2025-02-10 15:21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("barcode")
|
||||
public class BarCodeController {
|
||||
|
||||
@Autowired
|
||||
private BarCodeService barcodeService;
|
||||
|
||||
/**
|
||||
* 条码扫描
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("scanBarcode")
|
||||
public Result scanBarcode() {
|
||||
return barcodeService.scanBarcode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.dpkj.modules.barcode.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface BarCodeService {
|
||||
|
||||
Result scanBarcode();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.dpkj.modules.barcode.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.barcode.service.BarCodeService;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-10 15:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BarCodeServiceImpl implements BarCodeService {
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
@Override
|
||||
public Result scanBarcode() {
|
||||
// 连接扫描仪
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setDevName(LexMarkConst.BARCODE_READER);
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(1000);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 90000);
|
||||
connectParam.put("ServiceName", LexMarkConst.BARCODE_READER);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
if (connectResult.getResult() == 0) {
|
||||
// 扫描条码
|
||||
LexMarkDTO scanBarcode = new LexMarkDTO();
|
||||
scanBarcode.setDevName(LexMarkConst.BARCODE_READER);
|
||||
scanBarcode.setActionName(MiddlewareFunctionsConst.SCAN_BARCODE);
|
||||
scanBarcode.setCallID(1000);
|
||||
JSONObject scanBarcodeParam = new JSONObject();
|
||||
scanBarcodeParam.put("BarcodeDataMode", 0);
|
||||
scanBarcodeParam.put("TimeOut", 0);
|
||||
scanBarcode.setParam(scanBarcodeParam.toJSONString());
|
||||
IDCardReadResultVO scanBarcodeResult = thirdServiceUtil.callDevice(scanBarcode, IDCardReadResultVO.class);
|
||||
if (scanBarcodeResult.getResult() == 0) {
|
||||
return Result.ok(scanBarcodeResult);
|
||||
} else {
|
||||
return Result.error("扫描异常!详情:" + connectResult.getDesc());
|
||||
}
|
||||
} else {
|
||||
return Result.error("扫描仪设备连接失败!详情:" + connectResult.getDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
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.sun.jna.Memory;
|
||||
import com.sun.jna.Pointer;
|
||||
import lombok.AllArgsConstructor;
|
||||
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.RestController;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 16:25
|
||||
* @Description: 医保模块-阿里设备
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chs/alipay")
|
||||
public class AlipayController {
|
||||
|
||||
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("失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
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.IHispayService;
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.Pointer;
|
||||
import lombok.AllArgsConstructor;
|
||||
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.RestController;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 16:25
|
||||
* @Description: 医保模块-HIS医保
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/chs/hispay")
|
||||
public class HispayController {
|
||||
|
||||
private final IHispayService hispayService;
|
||||
|
||||
private final ChsConfig charsConfig;
|
||||
|
||||
|
||||
@GetMapping("test")
|
||||
public Result<?> test() {
|
||||
try {
|
||||
|
||||
return Result.ok("成功", null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
59
src/main/java/com/dpkj/modules/chs/dll/AlipayDll.java
Normal file
59
src/main/java/com/dpkj/modules/chs/dll/AlipayDll.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.dpkj.modules.chs.dll;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 17:48
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public class AlipayDll {
|
||||
|
||||
/**
|
||||
* 获取 AlipayDll 实例,同时注册 AlipayDll 控件。
|
||||
*
|
||||
* @return AlipayDll 实例
|
||||
* @throws DllRegistrationException 如果注册控件失败,抛出此异常
|
||||
*/
|
||||
public static Dll instance() throws DllRegistrationException {
|
||||
try {
|
||||
return Native.load("NationECCode", Dll.class);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
log.info("[AlipayDll][getPrintSDK][医保动态库] SDK注册失败:{}", e.getMessage());
|
||||
throw new DllRegistrationException("Failed to load AlipayDll library: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义自定义异常类,用于表示注册控件时发生的错误
|
||||
*/
|
||||
public static class DllRegistrationException extends Exception {
|
||||
public DllRegistrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DllRegistrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 定义接口映射本地库中的函数。
|
||||
*/
|
||||
public interface Dll extends Library {
|
||||
|
||||
/**
|
||||
* 设置打印端口和波特率。
|
||||
*
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
String NationEcTrans(String strUrl, String InData, Pointer OutData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
59
src/main/java/com/dpkj/modules/chs/dll/HispayDll.java
Normal file
59
src/main/java/com/dpkj/modules/chs/dll/HispayDll.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.dpkj.modules.chs.dll;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 17:48
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
public class HispayDll {
|
||||
|
||||
/**
|
||||
* 获取 AlipayDll 实例,同时注册 AlipayDll 控件。
|
||||
*
|
||||
* @return AlipayDll 实例
|
||||
* @throws DllRegistrationException 如果注册控件失败,抛出此异常
|
||||
*/
|
||||
public static Dll instance() throws DllRegistrationException {
|
||||
try {
|
||||
return Native.load("PayClient", Dll.class);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
log.info("[HispayDll][getPrintSDK][医保动态库] SDK注册失败:{}", e.getMessage());
|
||||
throw new DllRegistrationException("Failed to load AlipayDll library: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义自定义异常类,用于表示注册控件时发生的错误
|
||||
*/
|
||||
public static class DllRegistrationException extends Exception {
|
||||
public DllRegistrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DllRegistrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 定义接口映射本地库中的函数。
|
||||
*/
|
||||
public interface Dll extends Library {
|
||||
|
||||
/**
|
||||
* 设置打印端口和波特率。
|
||||
*
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
String NationEcTrans(String strUrl, String InData, Pointer OutData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.dpkj.modules.chs.entity;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/23 11:56
|
||||
* @Description: 医保请求
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AlipayEcRequestData implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* 机构 ID 必填
|
||||
*/
|
||||
private String orgId;
|
||||
|
||||
/**
|
||||
* 交易类型 必填
|
||||
* ec.query: 电子凭证二维码解码接口
|
||||
* cn.nhsa.qrcode.get: 终端医保电子凭证码解码接口
|
||||
* cn.nhsa.auth.check:刷脸授权获取医保身份接口
|
||||
* cn.nhsa.ec.pwd: 医保电子凭证密码核验接口
|
||||
*/
|
||||
private String transType;
|
||||
|
||||
/**
|
||||
* 接口请求参数 JSON格式字符串 必填
|
||||
*/
|
||||
private JSONObject data;
|
||||
|
||||
/**
|
||||
* 扩展参数 JSON格式字符串
|
||||
*/
|
||||
private JSONObject extra;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.dpkj.modules.chs.service;
|
||||
|
||||
public interface IAlipayService {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.dpkj.modules.chs.service;
|
||||
|
||||
public interface IHispayService {
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
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.service.IAlipayService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 16:29
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayServiceImpl implements IAlipayService {
|
||||
|
||||
private AlipayDll.Dll dll = AlipayDll.instance();
|
||||
|
||||
|
||||
public AlipayServiceImpl() throws AlipayDll.DllRegistrationException {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
log.info("[AlipayServiceImpl][postConstruct][医保DLL] 初始化动态链接库");
|
||||
initPrinter();
|
||||
}
|
||||
|
||||
|
||||
private void initPrinter() {
|
||||
Console.log(dll);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.dpkj.modules.chs.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import com.dpkj.modules.chs.dll.HispayDll;
|
||||
import com.dpkj.modules.chs.service.IHispayService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2025/3/22 16:29
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class HispayServiceImpl implements IHispayService {
|
||||
|
||||
private HispayDll.Dll dll = HispayDll.instance();
|
||||
|
||||
|
||||
public HispayServiceImpl() throws HispayDll.DllRegistrationException {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
log.info("[HispayServiceImpl][postConstruct][医保DLL-HIS] 初始化动态链接库");
|
||||
initPrinter();
|
||||
}
|
||||
|
||||
|
||||
private void initPrinter() {
|
||||
Console.log(dll);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package com.dpkj.modules.express.controller;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.dpkj.common.config.FileConfig;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.express.service.PrinterService;
|
||||
import com.dpkj.modules.express.utils.FileUtils;
|
||||
import com.dpkj.modules.express.utils.PrinterUtil;
|
||||
import com.dpkj.modules.express.vo.Print;
|
||||
import com.dpkj.modules.express.vo.PrinterStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/28 13:58
|
||||
* @Description: 打印机
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("printer")
|
||||
public class PrinterController {
|
||||
@Autowired
|
||||
private PrinterService printerService;
|
||||
@Autowired
|
||||
private FileConfig fileConfig;
|
||||
|
||||
/**
|
||||
* 获取打印机状态
|
||||
*
|
||||
* @return com.dpkj.common.vo.Result
|
||||
* @author 萧道子 2024/4/28
|
||||
*/
|
||||
@GetMapping("status")
|
||||
public Result getStatus() {
|
||||
try {
|
||||
PrinterStatus val = printerService.getPrinterStatus();
|
||||
return Result.ok("获取成功", val);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.info("[printer][PrinterController.getStatus]获取打印机状态失败 {}", e.getMessage());
|
||||
return Result.error("打印机状态获取失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印文件
|
||||
*
|
||||
* @return com.dpkj.common.vo.Result
|
||||
* @author 萧道子 2024/4/29
|
||||
*/
|
||||
@PostMapping("print")
|
||||
public Result print(@RequestBody Print val) {
|
||||
try {
|
||||
String base64 = val.getBase64();
|
||||
if (StrUtil.isEmpty(base64)) throw new Exception("参数缺失!");
|
||||
|
||||
List<File> files = FileUtils.saveBase64ToBmp(base64);
|
||||
if (files.isEmpty()) throw new Exception("打印失败,面单未生成!");
|
||||
|
||||
File file = files.get(0);
|
||||
String filePath = file.getAbsolutePath();
|
||||
Integer num = printerService.printBmpByPath(filePath);// 打印
|
||||
FileUtil.del(file); // 删除文件
|
||||
|
||||
if (num != 0) throw new Exception("打印失败,请检查打印机是否连接正常!");
|
||||
|
||||
return Result.ok("打印成功");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.info("[printer][PrinterController.print] 打印面单 {}", e.getMessage());
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.dpkj.modules.express.service;
|
||||
|
||||
import com.dpkj.modules.express.utils.PrinterUtil;
|
||||
import com.dpkj.modules.express.vo.PrinterStatus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface PrinterService {
|
||||
|
||||
/**
|
||||
* 获取打印机状态
|
||||
*
|
||||
* @return com.dpkj.modules.express.vo.PrinterStatus
|
||||
* @author 萧道子 2024/4/28
|
||||
*/
|
||||
PrinterStatus getPrinterStatus();
|
||||
|
||||
/**
|
||||
* 通过路径打印BMP文件
|
||||
*
|
||||
* @param path :
|
||||
* @return java.lang.Integer
|
||||
* @author 萧道子 2024/4/29
|
||||
*/
|
||||
Integer printBmpByPath(String path) throws Exception;
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
package com.dpkj.modules.express.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.dpkj.common.config.PrinterConfig;
|
||||
import com.dpkj.modules.express.service.PrinterService;
|
||||
import com.dpkj.modules.express.utils.PrinterUtil;
|
||||
import com.dpkj.modules.express.vo.PrinterStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/28 14:34
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PrinterServiceImpl implements PrinterService {
|
||||
@Resource
|
||||
private PrinterConfig printerConfig;
|
||||
|
||||
private PrinterUtil.MsPrintSdk printSDK = PrinterUtil.getPrintSDK();
|
||||
|
||||
public PrinterServiceImpl() throws PrinterUtil.PrinterRegistrationException {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
log.info("[printer] 打印机初始化");
|
||||
initPrinter();
|
||||
}
|
||||
|
||||
private void initPrinter() {
|
||||
if (StrUtil.equals(printerConfig.getConnectionType(), "USB")) {
|
||||
// USB连接
|
||||
Integer n = printSDK.SetUsbportauto();
|
||||
log.info("[printer][SetUsbportauto] USB自动识别 {}", n);
|
||||
} else {
|
||||
// 串口连接
|
||||
String portName = printerConfig.getPortName();
|
||||
Integer baudRate = printerConfig.getBaudRate();
|
||||
Integer n = printSDK.SetPrintPort(portName, baudRate);
|
||||
log.info("[printer][SetPrintPort] 串口配置 {}", n);
|
||||
}
|
||||
Integer n = printSDK.SetInit();
|
||||
log.info("[printer][SetInit] 初始化打印机设置 {}", n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrinterStatus getPrinterStatus() {
|
||||
Integer num = printSDK.GetStatusspecial();
|
||||
PrinterStatus statusVo = getStatusVo(num);
|
||||
return statusVo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer printBmpByPath(String path) {
|
||||
initPrinter();
|
||||
|
||||
String formattedFilePath = path.replace("\\", "\\\\");
|
||||
int n = printSDK.PrintDiskimgfile(formattedFilePath);
|
||||
log.info("[printer][PrintDiskimgfile] 打印BMP文件 {}", n);
|
||||
|
||||
printMarkpositioncut();
|
||||
// printMarkcutpaper();
|
||||
printCutpaper();
|
||||
return n;
|
||||
}
|
||||
|
||||
private PrinterStatus getStatusVo(Integer num) {
|
||||
PrinterStatus val = new PrinterStatus().setValue(num);
|
||||
switch (num) {
|
||||
case 0:
|
||||
val.setText("打印机正常");
|
||||
break;
|
||||
case 1:
|
||||
val.setText("打印机未连接或未上电");
|
||||
break;
|
||||
case 2:
|
||||
val.setText("打印机和调用库不匹配");
|
||||
break;
|
||||
case 3:
|
||||
val.setText("当前使用打印机无特殊功能");
|
||||
break;
|
||||
case 4:
|
||||
val.setText("容纸器没有可靠上纸");
|
||||
break;
|
||||
case 5:
|
||||
val.setText("纸张堵在出票口,持续堆叠");
|
||||
break;
|
||||
case 6:
|
||||
val.setText("卡纸");
|
||||
break;
|
||||
case 7:
|
||||
val.setText("拽纸");
|
||||
break;
|
||||
case 8:
|
||||
val.setText("出纸传感器有纸");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测黑标进纸到切纸位置
|
||||
*/
|
||||
private Integer printMarkpositioncut() {
|
||||
int n = printSDK.PrintMarkpositioncut();
|
||||
log.info("[printer][PrintMarkpositioncut] 检测黑标进纸到切纸位置 {}", n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印切纸
|
||||
*/
|
||||
private Integer printCutpaper() {
|
||||
int n = printSDK.PrintCutpaper(0);
|
||||
log.info("[printer][PrintCutpaper] 打印切纸 {}", n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* 黑标切纸
|
||||
*/
|
||||
private Integer printMarkcutpaper() {
|
||||
int n = printSDK.PrintMarkcutpaper(0);
|
||||
log.info("[printer][printMarkcutpaper] 打印黑标切纸 {}", n);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测黑标进纸到打印位置
|
||||
*/
|
||||
private Integer printMarkpositionPrint() {
|
||||
int n = printSDK.PrintMarkpositionPrint();
|
||||
log.info("[printer][printMarkpositionPrint] 检测黑标进纸到打印位置 {}", n);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package com.dpkj.modules.express.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.dpkj.common.config.FileConfig;
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/29 14:47
|
||||
* @Description:
|
||||
*/
|
||||
@Component
|
||||
public class FileUtils {
|
||||
|
||||
private static FileConfig fileConfig;
|
||||
|
||||
@Autowired
|
||||
public void setFileConfig(FileConfig fileConfig) {
|
||||
this.fileConfig = fileConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64Pdf 转字节流
|
||||
*
|
||||
* @param base64Pdf :
|
||||
* @return java.util.List<java.awt.image.BufferedImage>
|
||||
* @author 萧道子 2024/4/29
|
||||
*/
|
||||
public static List<BufferedImage> convertBase64PdfToBufferedImage(String base64Pdf) throws IOException {
|
||||
List<BufferedImage> images = new ArrayList<>();
|
||||
base64Pdf = base64Pdf.replaceAll("[^A-Za-z0-9+/=]", "");
|
||||
byte[] base64Bytes = Base64.getDecoder().decode(base64Pdf);
|
||||
PDDocument document = Loader.loadPDF(base64Bytes);
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
for (int i = 0; i < document.getNumberOfPages(); i++) {
|
||||
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(i, 188);
|
||||
int h = bufferedImage.getHeight();
|
||||
int w = bufferedImage.getWidth();
|
||||
int x = 15;
|
||||
int y = 28;
|
||||
// int y = new BigDecimal(0.03).multiply(new BigDecimal(h)).setScale(0, BigDecimal.ROUND_UP).intValue();
|
||||
BufferedImage croppedImageTopOne = bufferedImage.getSubimage(x, y, w - x, h - y);
|
||||
images.add(croppedImageTopOne);
|
||||
}
|
||||
document.close();
|
||||
return images;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将BufferedImage 保存为 BMP文件
|
||||
*
|
||||
* @param images :
|
||||
* @return java.util.List<java.io.File>
|
||||
* @author 萧道子 2024/4/29
|
||||
*/
|
||||
public static List<File> saveBufferedImageToBmp(List<BufferedImage> images) throws IOException {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
String path = fileConfig.getPath();
|
||||
// 创建文件夹
|
||||
FileUtil.mkdir(fileConfig.getPath());
|
||||
for (BufferedImage bufferedImage : images) {
|
||||
String filePath = path + "/" + IdUtil.simpleUUID() + ".bmp";
|
||||
filePath = FileUtil.normalize(filePath);
|
||||
File bmpFile = new File(filePath);
|
||||
// 使用ImageIO将BufferedImage保存为BMP文件
|
||||
ImageIO.write(bufferedImage, "BMP", bmpFile);
|
||||
fileList.add(bmpFile);
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将base64保存为Bmp文件
|
||||
*
|
||||
* @param base64 :
|
||||
* @return java.util.List<java.io.File>
|
||||
* @author 萧道子 2024/4/29
|
||||
*/
|
||||
public static List<File> saveBase64ToBmp(String base64) throws IOException {
|
||||
List<BufferedImage> bufferedImages = FileUtils.convertBase64PdfToBufferedImage(base64);
|
||||
List<File> files = FileUtils.saveBufferedImageToBmp(bufferedImages);
|
||||
return files;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
package com.dpkj.modules.express.utils;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Slf4j
|
||||
public class PrinterUtil {
|
||||
|
||||
/**
|
||||
* 获取 MsPrintSdk 实例,同时注册 MsPrintSdk 控件。
|
||||
*
|
||||
* @return MsPrintSdk 实例
|
||||
* @throws PrinterRegistrationException 如果注册控件失败,抛出此异常
|
||||
*/
|
||||
public static MsPrintSdk getPrintSDK() throws PrinterRegistrationException {
|
||||
/* String ocxPath = "src/lib/Msprintsdk.ocx";
|
||||
ProcessBuilder processBuilder = new ProcessBuilder("regsvr32", "/s", ocxPath);
|
||||
try {
|
||||
Process process = processBuilder.start();
|
||||
int exitCode = process.waitFor();
|
||||
// if (exitCode != 0) {
|
||||
// throw new PrinterRegistrationException("Failed to register MsPrintSdk OCX. Exit code: " + exitCode);
|
||||
// }
|
||||
} catch (InterruptedException | IOException e) {
|
||||
throw new PrinterRegistrationException("Error occurred while registering MsPrintSdk OCX.", e);
|
||||
}*/
|
||||
|
||||
try {
|
||||
return Native.load("Msprintsdk.x64", MsPrintSdk.class);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
log.info("[printer][PrinterUtil.getPrintSDK] SDK注册失败 {}", e.getMessage());
|
||||
throw new PrinterRegistrationException("Failed to load MsPrintSdk library: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void convertAndPassStringAsJCharArray(String filePath) {
|
||||
// 将字符串转换为char[]
|
||||
char[] chars = filePath.toCharArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义接口映射本地库中的函数。
|
||||
*/
|
||||
public interface MsPrintSdk extends Library {
|
||||
|
||||
/**
|
||||
* 设置打印端口和波特率。
|
||||
*
|
||||
* @param strPort 打印端口名
|
||||
* @param baudRate 波特率
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer SetPrintPort(String strPort, int baudRate);
|
||||
|
||||
/**
|
||||
* 设置打印连接方式、名称和值。
|
||||
*
|
||||
* @param iConnWay 连接方式
|
||||
* @param strName 名称
|
||||
* @param strValue 值
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer SetPrintConn(int iConnWay, String strName, String strValue);
|
||||
|
||||
/**
|
||||
* 设置 USB 端口自动识别。
|
||||
*
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer SetUsbportauto();
|
||||
|
||||
/**
|
||||
* 获取打印机状态。
|
||||
* 0 打印机正常
|
||||
* 1 打印机未连接或未上电
|
||||
* 2 打印机和调用库不匹配
|
||||
* 3 打印头打开
|
||||
* 4 切刀未复位
|
||||
* 5 打印头温度异常
|
||||
* 6 黑标错误,可能的情况为 黑标传感器坏 | 使用错误白纸 | 黑标不标准,浓度偏低
|
||||
* 7 纸尽
|
||||
* 8 纸将尽
|
||||
*
|
||||
* @return 返回打印机状态代码 0:成功 1:失败
|
||||
*/
|
||||
Integer GetStatus();
|
||||
|
||||
/**
|
||||
* 获取打印机特殊功能状态
|
||||
* 0 打印机正常
|
||||
* 1 打印机未连接或未上电
|
||||
* 2 打印机和调用库不匹配
|
||||
* 3 当前使用打印机无特殊功能
|
||||
* 4 容纸器没有可靠上纸
|
||||
* 5 纸张堵在出票口,持续堆叠
|
||||
* 6 卡纸,出纸口未堵的情况下,胶辊无法驱动纸持续前进了。 比如纸卷在胶辊上了、切刀堵住了纸的前进、纸张被拉住无法前进等
|
||||
* 7 拽纸,打印机感受到凭条被外力拖拽
|
||||
* 8 出纸传感器有纸
|
||||
*
|
||||
* @return 返回打印机状态代码 0:成功 1:失败
|
||||
*/
|
||||
Integer GetStatusspecial();
|
||||
|
||||
/**
|
||||
* 初始化打印机设置。
|
||||
*
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer SetInit();
|
||||
|
||||
/**
|
||||
* 打印二维码。
|
||||
*
|
||||
* @param s 二维码数据
|
||||
* @param i 参数 i
|
||||
* @param i1 参数 i1
|
||||
* @param i2 参数 i2
|
||||
*/
|
||||
void PrintQrcode(String s, int i, int i1, int i2);
|
||||
|
||||
/**
|
||||
* 设置左边距。
|
||||
*
|
||||
* @param i 左边距值
|
||||
*/
|
||||
void SetLeftmargin(int i);
|
||||
|
||||
/**
|
||||
* 打印字符串。
|
||||
*
|
||||
* @param s 字符串内容
|
||||
* @param i 参数 i
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer PrintString(String s, int i);
|
||||
|
||||
/**
|
||||
* 打印剩余的二维码。
|
||||
*
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer PrintRemainQR();
|
||||
|
||||
/**
|
||||
* 设置 设置汉字模式 模式。
|
||||
*
|
||||
* @param i 模式参数
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer SetReadZKmode(int i);
|
||||
|
||||
/**
|
||||
* 切纸。
|
||||
*
|
||||
* @param i 切纸参数
|
||||
* 0 全切
|
||||
* 1 半切
|
||||
* @return 返回操作结果代码
|
||||
*/
|
||||
Integer PrintCutpaper(int i);
|
||||
|
||||
/**
|
||||
* 设置 HT 座位信息。
|
||||
*
|
||||
* @param s 座位信息
|
||||
* @param i 参数 i
|
||||
*/
|
||||
void SetHTseat(String s, int i);
|
||||
|
||||
/**
|
||||
* 打印下一个 HT 数据。
|
||||
*/
|
||||
void PrintNextHT();
|
||||
|
||||
/**
|
||||
* 打印BMP
|
||||
*
|
||||
* @param strPath BMP文件路径
|
||||
*/
|
||||
Integer PrintDiskbmpfile(String strPath);
|
||||
|
||||
/**
|
||||
* 打印BMP
|
||||
*
|
||||
* @param strPath BMP文件路径
|
||||
*/
|
||||
Integer PrintDiskimgfile(String strPath);
|
||||
|
||||
|
||||
/**
|
||||
* 检测黑标进纸到打印位置
|
||||
*/
|
||||
Integer PrintMarkpositionPrint();
|
||||
|
||||
/**
|
||||
* 检测黑标进纸到切纸位置
|
||||
*/
|
||||
Integer PrintMarkpositioncut();
|
||||
|
||||
/**
|
||||
* 打印黑标切纸
|
||||
* <p>
|
||||
* 0 检测黑标全切
|
||||
* 1 不检测黑标半切
|
||||
*/
|
||||
Integer PrintMarkcutpaper(int iMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义自定义异常类,用于表示注册控件时发生的错误
|
||||
*/
|
||||
public static class PrinterRegistrationException extends Exception {
|
||||
public PrinterRegistrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PrinterRegistrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.dpkj.modules.express.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/29 17:03
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class Print implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String base64;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dpkj.modules.express.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Auther: 萧道子
|
||||
* @Date: 2024/4/28 14:44
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PrinterStatus implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String text;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.dpkj.modules.keypad.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.keypad.service.KeypadService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.controller
|
||||
* @Author: wzc
|
||||
* @Description: 数字键盘
|
||||
* @CreateTime: 2025-02-10 15:21
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("keypad")
|
||||
public class KeypadController {
|
||||
|
||||
@Autowired
|
||||
private KeypadService keypadService;
|
||||
/**
|
||||
* 数字键盘 明文输入
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("inputData")
|
||||
public Result inputData() {
|
||||
return keypadService.inputData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("cancelInput")
|
||||
public Result CancelInput() {
|
||||
return keypadService.cancelInput();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.dpkj.modules.keypad.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface KeypadService {
|
||||
Result inputData();
|
||||
|
||||
Result cancelInput();
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.dpkj.modules.keypad.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.ErrorCodeConstants;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.keypad.service.KeypadService;
|
||||
import com.dpkj.modules.keypad.util.WebSocketClient;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.keypad.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-10 15:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class KeypadServiceImpl implements KeypadService {
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
/**
|
||||
* 数字键盘 明文输入
|
||||
* 1. 连接数字键盘
|
||||
* 2. 明文输入
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result inputData() {
|
||||
Result result = null;
|
||||
// 获取设备状态
|
||||
LexMarkDTO status = new LexMarkDTO();
|
||||
status.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
status.setCallID(0);
|
||||
status.setActionName(MiddlewareFunctionsConst.GET_STATUS_SYNC);
|
||||
JSONObject statusParam = new JSONObject();
|
||||
statusParam.put("timeout", 0);
|
||||
log.info("[KeypadServiceImpl][inputData][50]: 获取设备状态,参数: {}", status);
|
||||
IDCardReadResultVO statusResult = thirdServiceUtil.callDevice(status, IDCardReadResultVO.class);
|
||||
log.info("[KeypadServiceImpl][inputData][52]: 获取设备状态结果: {}", statusResult);
|
||||
if (statusResult.getResult() == 0) {
|
||||
// 连接状态,初始化
|
||||
LexMarkDTO reset = new LexMarkDTO();
|
||||
reset.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
reset.setCallID(0);
|
||||
reset.setActionName(MiddlewareFunctionsConst.RESET);
|
||||
JSONObject resetParam = new JSONObject();
|
||||
resetParam.put("ResetAction", 1);
|
||||
log.info("[KeypadServiceImpl][inputData][61]: 调用复位(初始化)方法,参数: {}", reset);
|
||||
IDCardReadResultVO resetResult = thirdServiceUtil.callDevice(reset, IDCardReadResultVO.class);
|
||||
log.info("[KeypadServiceImpl][inputData][63]: 设备复位(初始化)结果: {}", resetResult);
|
||||
if (resetResult.getResult() == 0) {
|
||||
// 复位成功
|
||||
result = connectAndInputData(result);
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()));
|
||||
log.info("[KeypadServiceImpl][inputData][69]: 密码键盘(初始化)异常,详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()));
|
||||
}
|
||||
} else {
|
||||
// 设备未连接,无需复位(初始化)
|
||||
result = connectAndInputData(result);
|
||||
}
|
||||
log.info("[KeypadServiceImpl][inputData][76]: 密码输入流程结束,最终返回结果: {}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result connectAndInputData(Result result){
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][81]: {}", "开始执行密码输入流程");
|
||||
|
||||
// 连接数字键盘
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][84]: {}", "准备连接数字键盘设备");
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(1000);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 30000);
|
||||
connectParam.put("ServiceName", LexMarkConst.ENCRYPTOR);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][93]: {}", "调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][95]: 设备连接结果: {}", connectResult);
|
||||
|
||||
WebSocketClient webSocketClient = null;
|
||||
try {
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][100]: {}", "数字键盘设备连接成功,准备进行明文输入");
|
||||
|
||||
// 明文输入
|
||||
LexMarkDTO plaintext = new LexMarkDTO();
|
||||
plaintext.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
plaintext.setActionName(MiddlewareFunctionsConst.INPUT_DATA);
|
||||
plaintext.setCallID(1000);
|
||||
JSONObject plaintextParam = new JSONObject();
|
||||
// 密码最小长度
|
||||
plaintextParam.put("MINLength", 0);
|
||||
// 密码最大长度
|
||||
plaintextParam.put("MAXLength", 6);
|
||||
// 是否自动结束
|
||||
plaintextParam.put("bAutoEnd", 1);
|
||||
// 超时时间
|
||||
plaintextParam.put("TimeOut", 80000);
|
||||
|
||||
plaintextParam.put("ActiveKeys", 81919);
|
||||
plaintextParam.put("TerminateKeys", 1024);
|
||||
plaintext.setParam(plaintextParam.toJSONString());
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][120]: 调用明文输入方法,参数: {}", plaintext);
|
||||
|
||||
// 创建 WebSocket 客户端
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][123]: {}", "创建 WebSocket 客户端,连接地址: ws://127.0.0.1:12347");
|
||||
webSocketClient = new WebSocketClient("ws://127.0.0.1:12347");
|
||||
|
||||
IDCardReadResultVO plaintextResult = thirdServiceUtil.callDevice(plaintext, IDCardReadResultVO.class);
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][127]: 明文输入操作结果: {}", plaintextResult);
|
||||
|
||||
if (plaintextResult.getResult() == 0) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][130]: {}", "明文输入成功,开始等待确认");
|
||||
try {
|
||||
// 适当延长等待时间
|
||||
while (true) {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
Boolean confirm = webSocketClient.getConfirm();
|
||||
if (confirm) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][137]: {}", "收到确认信息,结束等待");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][142]: 等待确认信息时被中断{}", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
String password = webSocketClient.getPassword();
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][146]: 密码输入完成,密码为: {}", password);
|
||||
result = Result.ok("密码输入完成!", password);
|
||||
} else {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][149]: 密码输入异常!详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(plaintextResult.getResult()));
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(plaintextResult.getResult()));
|
||||
}
|
||||
} else {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][154]: 数字键盘设备连接失败!详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(connectResult.getResult()));
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(connectResult.getResult()));
|
||||
}
|
||||
} finally {
|
||||
if (webSocketClient != null) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][160]: {}", "关闭 WebSocket 客户端");
|
||||
webSocketClient.close();
|
||||
}
|
||||
// 关闭身份证读卡设备
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][164]: {}", "准备关闭数字键盘设备");
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][169]: 调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][171]: 设备关闭结果: {}", closeResult);
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.info("[KeypadServiceImpl][connectAndInputData][173]: 数字键盘设备关闭异常!详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(closeResult.getResult()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消输入 (明文或者密文)
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result cancelInput() {
|
||||
LexMarkDTO cancelInput = new LexMarkDTO();
|
||||
cancelInput.setDevName(LexMarkConst.ENCRYPTOR);
|
||||
cancelInput.setActionName(MiddlewareFunctionsConst.CANCEL_INPUT);
|
||||
cancelInput.setCallID(1000);
|
||||
cancelInput.setParam("{\"\"}");
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(cancelInput, IDCardReadResultVO.class);
|
||||
if (connectResult.getResult() == 0) {
|
||||
return Result.ok("取消输入 (明文或者密文)完成!");
|
||||
} else {
|
||||
return Result.error(connectResult.getDesc());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/dpkj/modules/keypad/util/WebSocketClient.java
Normal file
115
src/main/java/com/dpkj/modules/keypad/util/WebSocketClient.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.dpkj.modules.keypad.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import javax.websocket.*;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ClientEndpoint
|
||||
public class WebSocketClient {
|
||||
|
||||
private Session session;
|
||||
// 密码
|
||||
private String password = "";
|
||||
// 是否确认
|
||||
private boolean confirm = false;
|
||||
|
||||
public WebSocketClient(String uri) {
|
||||
try {
|
||||
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||
session = container.connectToServer(this, new URI(uri));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session) {
|
||||
System.out.println("Connected to WebSocket server");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message) {
|
||||
System.out.println("Received message: " + message);
|
||||
|
||||
// 解析外层 JSON 对象
|
||||
JSONObject outerObj = JSONObject.parseObject(message);
|
||||
|
||||
// 获取 "param" 字段对应的 JSON 对象
|
||||
JSONObject paramObj = outerObj.getJSONObject("param");
|
||||
|
||||
// 从 "param" 对象中获取 "Key" 的值
|
||||
Integer keyValue = paramObj.getInteger("Key");
|
||||
|
||||
if (keyValue != null) {
|
||||
// 更正
|
||||
if (keyValue == 8) {
|
||||
password = password.substring(0, password.length() - 1);
|
||||
// 取消
|
||||
} else if (keyValue == 27) {
|
||||
password = "";
|
||||
// 确认
|
||||
} else if (keyValue == 13) {
|
||||
confirm = true;
|
||||
} else if (keyValue == 2) {
|
||||
password += "00";
|
||||
} else {
|
||||
password += KEYPAD_MAPPING.get("0x" + Integer.toHexString(keyValue));
|
||||
}
|
||||
} else {
|
||||
System.out.println("未找到 Key 字段或其值为空。");
|
||||
}
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason closeReason) {
|
||||
System.out.println("Connection closed: " + closeReason.getReasonPhrase());
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public Boolean getConfirm() {
|
||||
return confirm;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (session != null && session.isOpen()) {
|
||||
session.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String, String> KEYPAD_MAPPING = new HashMap<>();
|
||||
|
||||
static {
|
||||
// 初始化映射关系
|
||||
KEYPAD_MAPPING.put("0x30", "0");
|
||||
KEYPAD_MAPPING.put("0x31", "1");
|
||||
KEYPAD_MAPPING.put("0x32", "2");
|
||||
KEYPAD_MAPPING.put("0x33", "3");
|
||||
KEYPAD_MAPPING.put("0x34", "4");
|
||||
KEYPAD_MAPPING.put("0x35", "5");
|
||||
KEYPAD_MAPPING.put("0x36", "6");
|
||||
KEYPAD_MAPPING.put("0x37", "7");
|
||||
KEYPAD_MAPPING.put("0x38", "8");
|
||||
KEYPAD_MAPPING.put("0x39", "9");
|
||||
KEYPAD_MAPPING.put("0x08", "BACKSPACE"); // 更正按键
|
||||
KEYPAD_MAPPING.put("0x10", "CLEAR");
|
||||
KEYPAD_MAPPING.put("0x0D", "ENTER"); // 确认按键
|
||||
KEYPAD_MAPPING.put("0x1B", "CANCEL"); // 取消
|
||||
KEYPAD_MAPPING.put("0xA1", "HELP"); // 帮助
|
||||
KEYPAD_MAPPING.put("0x2E", "DECPOINT");
|
||||
KEYPAD_MAPPING.put("0x02", "00");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.dpkj.modules.print.controller;
|
||||
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.print.request.MS439Request;
|
||||
import com.dpkj.modules.print.service.MS439PrintService;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* MS439控制层,利盟打印机
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-03 10:47:06
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/ms439")
|
||||
public class MS439Controller {
|
||||
|
||||
@Autowired
|
||||
private MS439PrintService ms439PrintService;
|
||||
|
||||
@PostMapping("/print")
|
||||
public Result<LexMarkResultDTO<?>> print(@Validated @RequestBody MS439Request request){
|
||||
return Result.ok(ms439PrintService.printImage(request));
|
||||
}
|
||||
|
||||
@PostMapping("/getStatus")
|
||||
public Result<String> print(@RequestParam(defaultValue = "A4") String papersource){
|
||||
this.ms439PrintService.getStatus(papersource);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.dpkj.modules.print.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.print.request.ReceiptPrintRequest;
|
||||
import com.dpkj.modules.print.service.PrintService;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* 挂号controller
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2025-02-08 11:49:46
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/receipt")
|
||||
public class RegisterController {
|
||||
|
||||
@Resource(name = "registerService")
|
||||
private PrintService printService;
|
||||
|
||||
/**
|
||||
* 挂号
|
||||
*/
|
||||
@PostMapping("/register/{templateName}")
|
||||
public Result<LexMarkResultDTO> register(@RequestParam String jsonData,
|
||||
@PathVariable String templateName,
|
||||
@RequestParam(defaultValue = "600") Integer width,
|
||||
@RequestParam(defaultValue = "950") Integer height
|
||||
){
|
||||
return Result.ok((LexMarkResultDTO)printService.printImage(JSONObject.parseObject(jsonData), templateName, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂号,通过文件路径
|
||||
*/
|
||||
@PostMapping("/print")
|
||||
public Result<LexMarkResultDTO> registerByFilePath(@RequestBody @Validated ReceiptPrintRequest request) throws UnsupportedEncodingException {
|
||||
// String testData = "{\"hospitalName\":\"澜沧县中医医院\",\"registeTerminalName\":\"中国农业银行自助终端\",\"registeType\":\"自助挂号\",\"name\":\"刘博雅\",\"gender\":\"男\",\"age\":28,\"birthDate\":\"1996-06-31\",\"cardNumber\":\"6221**********0731\",\"outpatientNumber\":\"2501150038\",\"department\":\"普外科门诊\",\"visitLevel\":\"普通号\",\"doctor\":\"普通门诊\",\"sequence\":\"1\",\"registerDate\":\"2025-01-15\",\"totalFee\":4.00,\"paymentMethod\":\"微信扫码支付\",\"orderNumber\":\"\",\"transactionNumber\":\"2025011513090412092794szztzzj\",\"qrCodeBase64_2base64Type_1_250_250\":\"maby this is a Base64 code data if has\",\"terminalNumber\":\"12092794\",\"printTime\":\"2025-01-15 13:10:08\"}";
|
||||
// String testData = "{\"hospitalName\":\"澜沧县中医医院\",\"registeTerminalName\":\"中国农业银行自助终端\",\"registeType\":\"自助挂号\",\"name\":\"刘博雅\",\"gender\":\"男\",\"age\":28,\"birthDate\":\"1996-06-31\",\"cardNumber\":\"6221**********0731\",\"outpatientNumber\":\"2501150038\",\"department\":\"普外科门诊\",\"visitLevel\":\"普通号\",\"doctor\":\"普通门诊\",\"sequence\":\"1\",\"registerDate\":\"2025-01-15\",\"totalFee\":4.00,\"paymentMethod\":\"微信扫码支付\",\"orderNumber\":\"\",\"transactionNumber\":\"2025011513090412092794szztzzj\",\"qrCodeBase64_2base64Type_2_500_160\":\"maby this is a Base64 code data if has\",\"terminalNumber\":\"12092794\",\"printTime\":\"2025-01-15 13:10:08\"}";
|
||||
return Result.ok((LexMarkResultDTO)printService.printImage(
|
||||
JSONObject.parseObject(URLDecoder.decode(request.getTemplateFillData(), "UTF-8")),
|
||||
request.getTemplateName(),
|
||||
request.getWidth(),
|
||||
request.getHeight(),
|
||||
request.getFileDir()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小票打印机状态
|
||||
*/
|
||||
@PostMapping("/getStatus")
|
||||
public Result<String> getStatus(){
|
||||
this.printService.getStatus();
|
||||
return Result.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* ms439打印机设备状态枚举
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 11:31:25
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439DeviceStatusEnum {
|
||||
/**
|
||||
* 打印机正常
|
||||
*/
|
||||
HEALTHY(439200, "正常", "HEALTHY"),
|
||||
|
||||
/**
|
||||
* 打印机忙碌,请稍后
|
||||
*/
|
||||
BUSY(439201, "打印机忙碌,请稍后", "BUSY"),
|
||||
|
||||
/**
|
||||
* 打印机发生故障
|
||||
*/
|
||||
FATAL(439500, "打印机发生故障", "FATAL"),
|
||||
|
||||
/**
|
||||
* 未发现打印机
|
||||
*/
|
||||
NODEVICE(439501, "未发现打印机", "NODEVICE"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439DeviceStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439DeviceStatusEnum value : MS439DeviceStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "打印机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439DeviceStatusEnum value : MS439DeviceStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* MS439打印机墨盒状态
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 11:39:35
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439InkStatusEnum {
|
||||
|
||||
/**
|
||||
* 墨盒满
|
||||
*/
|
||||
INKFULL(439200, "墨盒满", "INKFULL"),
|
||||
|
||||
/**
|
||||
* 墨盒少
|
||||
*/
|
||||
INKLOW(439203, "墨盒少", "INKLOW"),
|
||||
|
||||
/**
|
||||
* 缺墨盒
|
||||
*/
|
||||
INKOUT(439511, "缺墨盒", "INKOUT"),
|
||||
|
||||
/**
|
||||
* 不支持墨盒检测
|
||||
*/
|
||||
INKNOTSUPP(439512, "不支持墨盒检测", "INKNOTSUPP"),
|
||||
|
||||
/**
|
||||
* 墨盒状态未知
|
||||
*/
|
||||
INKUNKNOWN(439513, "墨盒未知", "INKUNKNOWN");
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439InkStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439InkStatusEnum value : MS439InkStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "打印机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439InkStatusEnum value : MS439InkStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* ms439打印机介质枚举
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 11:38:08
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439MediaStatusEnum {
|
||||
|
||||
|
||||
/**
|
||||
* 介质在通道
|
||||
*/
|
||||
PRESENT(439200, "介质在通道", "PRESENT"),
|
||||
|
||||
/**
|
||||
* 无介质
|
||||
*/
|
||||
NOTPRESENT(439502, "无介质", "NOTPRESENT"),
|
||||
|
||||
/**
|
||||
* 卡介质
|
||||
*/
|
||||
JAMMED(439503, "卡介质", "JAMMED"),
|
||||
|
||||
/**
|
||||
* 不支持
|
||||
*/
|
||||
NOTSUPP(439504, "不支持", "NOTSUPP"),
|
||||
|
||||
/**
|
||||
* 未知
|
||||
*/
|
||||
UNKNOWN(439505, "未知", "UNKNOWN"),
|
||||
|
||||
/**
|
||||
* 介质在出口
|
||||
*/
|
||||
EXITING(439506, "介质在出口", "EXITING"),
|
||||
|
||||
/**
|
||||
* 介质被回收(复位时)
|
||||
*/
|
||||
RETRACTED(439507, "介质被回收(复位时)", "RETRACTED"),
|
||||
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439MediaStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439MediaStatusEnum value : MS439MediaStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "打印机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439MediaStatusEnum value : MS439MediaStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* MS439打印机纸盒状态枚举
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 11:53:21
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439PaperStatusEnum {
|
||||
|
||||
/**
|
||||
* 纸满
|
||||
*/
|
||||
PAPERFULL(439200, "纸满", "PAPERFULL"),
|
||||
|
||||
/**
|
||||
* 少纸
|
||||
*/
|
||||
PAPERLOW(439204, "少纸", "PAPERLOW"),
|
||||
|
||||
/**
|
||||
* 缺纸
|
||||
*/
|
||||
PAPEROUT(439514, "缺纸", "PAPEROUT"),
|
||||
|
||||
/**
|
||||
* 不支持纸箱检测
|
||||
*/
|
||||
PAPERNOTSUPP(439515, "不支持纸箱检测", "PAPERNOTSUPP"),
|
||||
|
||||
/**
|
||||
* 卡纸
|
||||
*/
|
||||
PAPERJAMMED(439516, "卡纸", "PAPERJAMMED"),
|
||||
|
||||
/**
|
||||
* 纸箱未知
|
||||
*/
|
||||
PAPERUNKNOWN(439517, "纸箱未知", "PAPERUNKNOWN");
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439PaperStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439PaperStatusEnum value : MS439PaperStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "打印机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439PaperStatusEnum value : MS439PaperStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 盖章机状态枚举
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 15:13:58
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439StampStatusEnum {
|
||||
|
||||
/**
|
||||
* 盖章机正常
|
||||
*/
|
||||
HEALTHY(439200, "正常", "HEALTHY"),
|
||||
|
||||
/**
|
||||
* 盖章机忙碌,请稍后
|
||||
*/
|
||||
BUSY(439201, "盖章机忙碌,请稍后", "BUSY"),
|
||||
|
||||
/**
|
||||
* 盖章机发生故障
|
||||
*/
|
||||
FATAL(439500, "盖章机发生故障", "FATAL"),
|
||||
|
||||
/**
|
||||
* 未发现盖章机
|
||||
*/
|
||||
NODEVICE(439501, "未发现盖章机", "NODEVICE"),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439StampStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439StampStatusEnum value : MS439StampStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "盖章机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439StampStatusEnum value : MS439StampStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* MS439打印机 磁带状态
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-06 11:38:48
|
||||
*/
|
||||
@Getter
|
||||
public enum MS439TonerStatusEnum {
|
||||
|
||||
/**
|
||||
* 磁带满
|
||||
*/
|
||||
TONERFULL(439200, "碳带满", "TONERFULL"),
|
||||
|
||||
/**
|
||||
* 碳带少
|
||||
*/
|
||||
TONERLOW(439202, "碳带少", "TONERLOW"),
|
||||
|
||||
/**
|
||||
* 缺碳带
|
||||
*/
|
||||
TONEROUT(439508, "缺碳带", "TONEROUT"),
|
||||
|
||||
/**
|
||||
* 不支持碳带检测
|
||||
*/
|
||||
TONERNOTSUPP(439509, "不支持碳带检测", "TONERNOTSUPP"),
|
||||
|
||||
/**
|
||||
* 碳带状态未知
|
||||
*/
|
||||
TONERUNKNOWN(439510, "碳带未知", "TONERUNKNOWN")
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
private final String printCode;
|
||||
|
||||
|
||||
MS439TonerStatusEnum(Integer code, String msg, String printCode) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.printCode = printCode;
|
||||
}
|
||||
|
||||
public static String getMessage(String printCode){
|
||||
for (MS439TonerStatusEnum value : MS439TonerStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.msg;
|
||||
}
|
||||
}
|
||||
return "打印机未知的错误";
|
||||
}
|
||||
|
||||
public static int getPCode(String printCode){
|
||||
for (MS439TonerStatusEnum value : MS439TonerStatusEnum.values()) {
|
||||
if ( value.getPrintCode().equals(printCode)){
|
||||
return value.code;
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.dpkj.modules.print.enums;
|
||||
|
||||
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ReceiptTemplateEnum {
|
||||
|
||||
/**
|
||||
* 自足挂号模板
|
||||
*/
|
||||
REGISTER("1", "register", "自助挂号的"),
|
||||
|
||||
/**
|
||||
* 住院缴费的模板
|
||||
*/
|
||||
HOSPITAL_PAYMENT("2", "hospitalPayment", "住院缴费的小票"),
|
||||
|
||||
/**
|
||||
* 门诊缴费的模板
|
||||
*/
|
||||
OUTPATIENT_T1("3", "outpatientPayment", "门诊缴费的小票-T1"),
|
||||
|
||||
/**
|
||||
* 门诊缴费的模板
|
||||
*/
|
||||
OUTPATIENT_T2("4", "department", "门诊缴费的小票-T2"),
|
||||
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
private final String templateName;
|
||||
|
||||
private final String desc;
|
||||
|
||||
|
||||
ReceiptTemplateEnum(String code, String templateName, String desc){
|
||||
this.code = code;
|
||||
this.templateName = templateName;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过code获取模板名称
|
||||
* @param code code/也有可能直接是一个名称
|
||||
* @return 模板的名称
|
||||
*/
|
||||
public static String getTemplateName(String code){
|
||||
if (code == null || "".equals(code)) {
|
||||
throw new RRException("模板名称不能为空");
|
||||
}
|
||||
|
||||
String name = null;
|
||||
for (ReceiptTemplateEnum enumEntity : ReceiptTemplateEnum.values()) {
|
||||
String enumCode = enumEntity.getCode();
|
||||
if ( enumCode.equals(code)){
|
||||
name = enumEntity.getTemplateName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name == null ? code : name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.dpkj.modules.print.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @since 2025-02-28 16:29:27
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MS439Request implements Serializable {
|
||||
|
||||
/**
|
||||
* 什么类型的纸张,默认A4
|
||||
*/
|
||||
private String pagesource = "A4";
|
||||
|
||||
/**
|
||||
* 份数,默认1
|
||||
*/
|
||||
@Min(value = 1, message = "份数最少要为一份")
|
||||
private Integer copies = 1;
|
||||
|
||||
/**
|
||||
* 文件的路径
|
||||
*/
|
||||
@NotBlank(message = "文件路径不能为空")
|
||||
private String fileDir;
|
||||
|
||||
/**
|
||||
* 是否盖章,默认不盖章 1盖章,0不盖章
|
||||
*/
|
||||
private Integer stamp = 0;
|
||||
|
||||
/**
|
||||
* 单面打印,或者双面 duplex 1/2,默认1
|
||||
*/
|
||||
private Integer duplex = 1;
|
||||
|
||||
/**
|
||||
* 颜色 0黑白,1彩色,默认是黑白的
|
||||
*/
|
||||
private Integer color = 0;
|
||||
|
||||
/**
|
||||
* 打印方向 direction 0纵向/1横向
|
||||
*/
|
||||
private Integer direction = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.dpkj.modules.print.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 小票打印请求,壁挂和打印机接口 进行统一
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-03-10 9:25:34
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ReceiptPrintRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* 文件路径地址,填写本地路径,默认为 D:/images
|
||||
*/
|
||||
@NotBlank(message = "文件路径不能为空")
|
||||
private String fileDir = "D:/images";
|
||||
|
||||
/**
|
||||
* 模板名称,也可以是自己写的html的字符串文件
|
||||
*/
|
||||
private String templateName = "receipt";
|
||||
|
||||
/**
|
||||
* 填充模板的数据,必填,也可以通过自己设置的模板名称进行设计,部分设计规则
|
||||
* <p>1、特殊字段(二维码图片)类型:qrCodeBase64_2base64Type_1_120_120,字段解析,qrCodeBase64为字段名称,
|
||||
* 第一个1为打印类型,1为二维码,2为条形码
|
||||
* _2base64Type为将这个数据转换为图片类型的base64编码,第二个_120图片的宽度,第三个_120的为图片高度</p>
|
||||
* <p>2、需要对传入的JSON数据进行URI编码</p>
|
||||
* <p>3、{"hospitalName":"澜沧县中医医院","registeTerminalName":"中国农业银行自助终端","registeType":"自助挂号","name":"刘博雅","gender":"男","age":28,"birthDate":"1996-06-31","cardNumber":"6221**********0731","outpatientNumber":"2501150038","department":"普外科门诊","visitLevel":"普通号","doctor":"普通门诊","sequence":"1","registerDate":"2025-01-15","totalFee":4.00,"paymentMethod":"微信扫码支付","orderNumber":"","transactionNumber":"2025011513090412092794szztzzj","qrCodeBase64_2base64Type_120_120":"这里应是二维码的Base64编码数据(如果有)","terminalNumber":"12092794","printTime":"2025-01-15 13:10:08"}</p>
|
||||
*/
|
||||
@NotBlank(message = "模板填充数据不能为空")
|
||||
private String templateFillData;
|
||||
|
||||
/**
|
||||
* 小票渲染宽度,默认为:690
|
||||
*/
|
||||
private Integer width = 690;
|
||||
|
||||
/**
|
||||
* 生成的模板的高度,默认为:1200
|
||||
*/
|
||||
private Integer height = 1200;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dpkj.modules.print.service;
|
||||
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.modules.print.request.MS439Request;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
import javassist.compiler.Lex;
|
||||
|
||||
public interface MS439PrintService {
|
||||
|
||||
LexMarkResultDTO<?> printImage(MS439Request request);
|
||||
|
||||
LexMarkResultDTO<PrinterStatus> getStatus(String papersource);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.dpkj.modules.print.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
|
||||
/**
|
||||
* 打印服务接口
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:35:27
|
||||
*/
|
||||
public interface PrintService {
|
||||
|
||||
|
||||
/**
|
||||
* 生成小票图片
|
||||
*
|
||||
* @param data json数据,用来填充模板
|
||||
* @param template 模板(html字符串或者模板名称)
|
||||
* @param width 图片宽度
|
||||
* @param height 图片高度
|
||||
* @param saveDir 图片的保存路径,如果为空,那么不进行图片的保存
|
||||
*/
|
||||
Object printImage(JSONObject data, String template, int width, int height, String saveDir);
|
||||
|
||||
/**
|
||||
* 默认实现,给定一个默认可用的图片保存路径
|
||||
*/
|
||||
default Object printImage(JSONObject data, String template, int width, int height) {
|
||||
return printImage(data, template, width, height, "D:\\images");
|
||||
}
|
||||
|
||||
|
||||
LexMarkResultDTO<PrinterStatus> getStatus();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.dpkj.modules.print.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import com.dpkj.common.utils.ThirdService;
|
||||
import com.dpkj.modules.print.enums.*;
|
||||
import com.dpkj.modules.print.request.MS439Request;
|
||||
import com.dpkj.modules.print.service.MS439PrintService;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 利盟MS439打印机服务
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-10 11:49:26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MS439PrintServiceImpl implements MS439PrintService {
|
||||
|
||||
@Resource
|
||||
private ThirdService thirdService;
|
||||
|
||||
@Override
|
||||
public LexMarkResultDTO<?> printImage(MS439Request request) {
|
||||
LexMarkResultDTO<PrinterStatus> status = this.getStatus(request.getPagesource());
|
||||
PrinterStatus ms439 = status.getData();
|
||||
|
||||
// 如果是要盖章,校验盖章机器是否正常
|
||||
if ( request.getStamp() == 1) {
|
||||
String deviceExStatus = ms439.getStDeviceExStatus();
|
||||
if (deviceExStatus == null || deviceExStatus.equals("")) {
|
||||
throw new RRException("获取打印机设备状态出问题");
|
||||
}
|
||||
String[] devices = deviceExStatus.split("\\|");
|
||||
if (devices.length < 2) {
|
||||
throw new RRException("打印机默认设备数量不对");
|
||||
}
|
||||
String device = devices[1];
|
||||
// 校验盖章机是否正常,除了HEALTHY都抛异常
|
||||
if (!device.equals(MS439StampStatusEnum.HEALTHY.getPrintCode()) ) {
|
||||
throw new RRException(MS439StampStatusEnum.getPCode(device),
|
||||
MS439StampStatusEnum.getMessage(device));
|
||||
}
|
||||
}
|
||||
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("PrintText");
|
||||
lexMarkDTO.setCallID(19283);
|
||||
lexMarkDTO.setDevName("HtmPrinter");
|
||||
lexMarkDTO.setPluginMethod("exec");
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
|
||||
// printType 选择箱子
|
||||
// param.put("prtData", String.format("PrintType=%d;pagesource=%s;copies=%d;file[0]=%s;stamp=%d;duplex=%d;color=%d;direction=%d",
|
||||
// request.getPagesource(), request.getCopies(), request.getFileDir(), request.getStamp(),
|
||||
// request.getDuplex(), request.getColor(), request.getDirection()));
|
||||
param.put("prtData", String.format("PaperNum=%d;PrintType=%d;Stamp=%d;File[0]=%s;WaitNum=%d;copies=%d;stamp=%d;duplex=%d;color=%d;direction=%d",
|
||||
request.getCopies(), // 盖章事件分数,和打印份数一致
|
||||
Objects.equals(request.getPagesource(), "A4") ? 1 : 2, // 打印类型1-A4或者2-A5
|
||||
request.getStamp(), // 是否盖章
|
||||
request.getFileDir(), // 要打印的文件的路径
|
||||
request.getCopies(), // 盖章事件分数,和打印份数一致
|
||||
request.getCopies(), // 实际要打印的份数
|
||||
request.getStamp(), // 是否盖章 0-不盖章 1-盖章
|
||||
request.getDuplex(), // 单面还是双面打印 1-单面 2-双面
|
||||
request.getColor(), // 打印的颜色0-黑色,1-彩色
|
||||
request.getDirection()));
|
||||
|
||||
lexMarkDTO.setParam(param.toString());
|
||||
LexMarkResultDTO<LexMarkResultDTO.Param> paramLexMarkResultDTO = thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class);
|
||||
// thirdService.close("HtmPrinter");
|
||||
return paramLexMarkResultDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LexMarkResultDTO<PrinterStatus> getStatus(String papersource) {
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("GetStatus");
|
||||
lexMarkDTO.setCallID(19283);
|
||||
lexMarkDTO.setDevName("HtmPrinter");
|
||||
lexMarkDTO.setPluginMethod("exec");
|
||||
|
||||
LexMarkResultDTO<PrinterStatus> status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
|
||||
if ( status.getResult() != 0){
|
||||
thirdService.open("HtmPrinter", 0);
|
||||
status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
|
||||
}
|
||||
|
||||
String stPaperEx = status.getData().getStPaperEx();
|
||||
if (stPaperEx == null || stPaperEx.equals("")) {
|
||||
throw new RRException("获取打印机纸张状态出问题");
|
||||
}
|
||||
String[] papers = stPaperEx.split("\\|");
|
||||
if ( papers.length < 2) {
|
||||
throw new RRException("打印机纸盒数量不对");
|
||||
}
|
||||
String paperStatus = "";
|
||||
// 如果是A4,当前是取第一层纸盒作为A4
|
||||
if (papersource.equals("A4")) {
|
||||
paperStatus = papers[0];
|
||||
}
|
||||
// 如果是A5,当前是取第二层纸盒只作为A5
|
||||
if (papersource.equals("A5")) {
|
||||
paperStatus = papers[1];
|
||||
}
|
||||
if ( !(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))){
|
||||
throw new RRException(500, paperStatus);
|
||||
}
|
||||
|
||||
PrinterStatus ms439 = status.getData();
|
||||
// 校验打印机是否正常,除了HEALTHY都抛异常
|
||||
if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode()) ) {
|
||||
throw new RRException(500, ms439.getStDeviceStatus());
|
||||
}
|
||||
|
||||
// 校验介质 介质在通道才放行
|
||||
if (!ms439.getStMedia().equals(MS439MediaStatusEnum.PRESENT.getPrintCode())) {
|
||||
throw new RRException(500, ms439.getStMedia());
|
||||
}
|
||||
|
||||
// 校验磁带 满或者少才放行
|
||||
if ( !(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))){
|
||||
throw new RRException(500, ms439.getStToner());
|
||||
}
|
||||
|
||||
// 校验墨盒 满或者少才放行,当前获取为未知
|
||||
if ( false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode())
|
||||
|| ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))){
|
||||
throw new RRException(500, ms439.getStInk());
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.dpkj.modules.print.service.impl;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.config.PrinterConfig;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.dto.LexMarkResultDTO;
|
||||
import com.dpkj.common.exception.RRException;
|
||||
import com.dpkj.common.utils.TemplateUtils;
|
||||
import com.dpkj.common.utils.ThirdService;
|
||||
import com.dpkj.modules.print.enums.*;
|
||||
import com.dpkj.modules.print.service.PrintService;
|
||||
import com.dpkj.modules.print.vo.PrinterStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thymeleaf.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 挂号服务打印
|
||||
*
|
||||
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
|
||||
* @version 1.0
|
||||
* @since 2025-02-08 10:36:25
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("registerService")
|
||||
public class RegisterServiceImpl implements PrintService {
|
||||
|
||||
@Resource
|
||||
private PrinterConfig printerConfig;
|
||||
|
||||
@Resource
|
||||
private ThirdService thirdService;
|
||||
|
||||
private static final int MAX_HEIGHT = 1000;
|
||||
private static final int FIXED_WIDTH = 730;
|
||||
|
||||
@Override
|
||||
public LexMarkResultDTO<LexMarkResultDTO.Param> printImage(JSONObject data, String template, int width, int height, String saveDir) {
|
||||
if ( height <= 0){
|
||||
width = FIXED_WIDTH;
|
||||
}
|
||||
|
||||
if ( StringUtils.isEmpty(printerConfig.getTimeType())){
|
||||
throw new RRException("获取打印时间格式出错:" + printerConfig.getTimeType());
|
||||
}
|
||||
if ( StringUtils.isEmpty(printerConfig.getTerminalNumber())){
|
||||
throw new RRException("获取终端号出错:" + printerConfig.getTerminalNumber());
|
||||
}
|
||||
|
||||
// 强行设置终端号
|
||||
data.put("terminalNumber", printerConfig.getTerminalNumber());
|
||||
|
||||
// 强行设置终端号和打印时间
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(printerConfig.getTimeType());
|
||||
String formattedDate = sdf.format( new Date());
|
||||
data.put("printTime", formattedDate);
|
||||
|
||||
// 获取模板
|
||||
String templateName = ReceiptTemplateEnum.getTemplateName(template);
|
||||
|
||||
int dinyHeight = 0;
|
||||
if (templateName.equals("department")) {
|
||||
// 由于是使用的门诊小票-T2,那么默认的高度为1000,强行设置,通过动态修改渲染的图片的高度
|
||||
height = 1000;
|
||||
|
||||
// 单行最大长度为10
|
||||
int singleLineMaxLength = 10;
|
||||
// 这里的长度取自于department.html模板中的项目单个tr高度,并且略高于该高度
|
||||
int singleLineHeight = 40;
|
||||
// 动态计算长度
|
||||
JSONArray items = data.getJSONArray("items");
|
||||
for (Object item : items) {
|
||||
JSONObject itemEntity = (JSONObject) item;
|
||||
String projectName = String.valueOf(itemEntity.get("name"));
|
||||
int length = projectName.length();
|
||||
int count = (int)Math.ceil((double) length / singleLineMaxLength);
|
||||
dinyHeight += count * singleLineHeight;
|
||||
}
|
||||
|
||||
// 计算是否有门诊号
|
||||
String outpatientNumber = data.getString("outpatientNumber");
|
||||
if ( !StringUtils.isEmpty(outpatientNumber)){
|
||||
dinyHeight += 35;
|
||||
}
|
||||
|
||||
// 计算是否有就诊医生
|
||||
String doctor = data.getString("doctor");
|
||||
if ( !StringUtils.isEmpty(doctor)){
|
||||
dinyHeight += 35;
|
||||
}
|
||||
|
||||
// 计算是否有就诊科室
|
||||
String department = data.getString("department");
|
||||
if ( !StringUtils.isEmpty(department)){
|
||||
dinyHeight += 35;
|
||||
}
|
||||
|
||||
}
|
||||
height += dinyHeight;
|
||||
|
||||
this.getStatus();
|
||||
StringBuilder filePath = new StringBuilder(saveDir);
|
||||
// 校验是否选中了模板,如果没选中模板的话则不需要另外生成了
|
||||
if ( !StringUtils.isEmpty(templateName) && !StringUtils.isEmpty(saveDir)){
|
||||
byte[] image = new TemplateUtils().generateReceiptImage(data, templateName, width, height, filePath);
|
||||
}else {
|
||||
throw new RRException("模板渲染错误");
|
||||
}
|
||||
|
||||
// 计算切割的块数
|
||||
int numPieces = (int) Math.ceil((double) height / MAX_HEIGHT);
|
||||
|
||||
String[] deletePathList = new String[numPieces + 1];
|
||||
deletePathList[0] = filePath.toString();
|
||||
String[] filePathList = new String[numPieces];
|
||||
// 对图片进行分块处理,当前台式打印机最大参数配置 宽度690,高度1200
|
||||
if ( height > MAX_HEIGHT){
|
||||
try {
|
||||
// 读取输入图片
|
||||
BufferedImage originalImage = ImageIO.read(new File(filePath.toString()));
|
||||
|
||||
// 循环切割图片并保存每一块
|
||||
for (int i = 0; i < numPieces; i++) {
|
||||
int startY = i * MAX_HEIGHT;
|
||||
int pieceHeight = Math.min(MAX_HEIGHT, height - startY);
|
||||
|
||||
// 创建一个新的 BufferedImage 对象,用于存储切割的部分
|
||||
BufferedImage piece = new BufferedImage(width, pieceHeight, BufferedImage.TYPE_INT_RGB);
|
||||
piece.getGraphics().drawImage(originalImage, 0, 0, width, pieceHeight, 0, startY, width, startY + pieceHeight, null);
|
||||
|
||||
// 保存切割的图片块
|
||||
File outputFile = new File(saveDir + "/output_" + (i + 1) + ".jpg");
|
||||
filePathList[i] = "LOGO" + (i + 1) + "=" + saveDir + "/output_" + (i + 1) + ".jpg";
|
||||
deletePathList[i + 1] = saveDir + "/output_" + (i + 1) + ".jpg";
|
||||
ImageIO.write(piece, "jpg", outputFile);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("模板切割失败");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else {
|
||||
filePathList[0] = "LOGO1=" + filePath;
|
||||
}
|
||||
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("PrintForm");
|
||||
lexMarkDTO.setCallID(19256);
|
||||
lexMarkDTO.setDevName("ReceiptPrinter");
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("TimeOut", 30000);
|
||||
param.put("formName", "GWIReceiptForm_example"); // 表单名从
|
||||
param.put("mediaName", "GWIReceiptMedia_example"); // 媒介类型
|
||||
param.put("alignment", 0); // 对齐方式
|
||||
param.put("offsetX", 0); // x
|
||||
param.put("offsetY", 0); // y
|
||||
param.put("resolution", 1); // 1\2\4\6\8打印的清晰度
|
||||
param.put("mediaCtrl", 1); // 媒介类型,当前为:打印缓冲区 + 弹出 + 剪纸
|
||||
param.put("fields", StringUtils.join(filePathList, "&"));
|
||||
lexMarkDTO.setParam(param.toJSONString());
|
||||
LexMarkResultDTO<LexMarkResultDTO.Param> paramLexMarkResultDTO = thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class);
|
||||
|
||||
for (String path : deletePathList) {
|
||||
if ( path != null && !path.isEmpty()) {
|
||||
File file = new File(path);
|
||||
// 检查文件是否存在
|
||||
if (file.exists()) {
|
||||
// 尝试删除文件
|
||||
if (file.delete()) {
|
||||
log.info("文件删除成功: " + path);
|
||||
} else {
|
||||
log.info("文件删除失败: " + path);
|
||||
}
|
||||
} else {
|
||||
log.info("文件不存在: " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paramLexMarkResultDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LexMarkResultDTO<PrinterStatus> getStatus() {
|
||||
LexMarkDTO lexMarkDTO = new LexMarkDTO();
|
||||
lexMarkDTO.setActionName("GetStatus");
|
||||
lexMarkDTO.setCallID(11225);
|
||||
lexMarkDTO.setDevName("ReceiptPrinter");
|
||||
lexMarkDTO.setPluginMethod("getInfo");
|
||||
// lexMarkDTO.setMethodType(0);
|
||||
LexMarkResultDTO<PrinterStatus> status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
|
||||
if ( status.getResult() != 0){
|
||||
thirdService.open("ReceiptPrinter", 1);
|
||||
status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class);
|
||||
}
|
||||
|
||||
PrinterStatus ms439 = status.getData();
|
||||
// 获取打印机纸张
|
||||
String stPaperEx = ms439.getStPaperEx();
|
||||
if (stPaperEx == null || stPaperEx.isEmpty()) {
|
||||
throw new RRException("获取打印机纸张状态出问题");
|
||||
}
|
||||
String[] papers = stPaperEx.split("\\|");
|
||||
if ( papers.length < 1) {
|
||||
throw new RRException("打印机纸盒数量不对");
|
||||
}
|
||||
String paperStatus = papers[0];
|
||||
if ( !(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))){
|
||||
throw new RRException(500, paperStatus);
|
||||
}
|
||||
|
||||
// 校验打印机是否正常,除了HEALTHY都抛异常
|
||||
if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode()) ) {
|
||||
throw new RRException(500, ms439.getStDeviceStatus());
|
||||
}
|
||||
|
||||
// 校验介质 介质在通道才放行
|
||||
if (!ms439.getStMedia().equals(MS439MediaStatusEnum.PRESENT.getPrintCode())) {
|
||||
throw new RRException(500, ms439.getStMedia());
|
||||
}
|
||||
|
||||
// 校验磁带 满或者少才放行
|
||||
if ( false && !(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))){
|
||||
throw new RRException(500, ms439.getStToner());
|
||||
}
|
||||
|
||||
// 校验墨盒 满或者少才放行,当前获取为未知
|
||||
if ( false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode())
|
||||
|| ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))){
|
||||
throw new RRException(500, ms439.getStInk());
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
68
src/main/java/com/dpkj/modules/print/vo/PrinterStatus.java
Normal file
68
src/main/java/com/dpkj/modules/print/vo/PrinterStatus.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.dpkj.modules.print.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PrinterStatus {
|
||||
/**
|
||||
* sp服务版本号
|
||||
*/
|
||||
private String SPVersion;
|
||||
|
||||
/**
|
||||
* 打印机状态
|
||||
* HEALTHY: 正常
|
||||
* FATAL: 故障
|
||||
* BUSY: 忙
|
||||
* NODEVICE: 无设备
|
||||
*/
|
||||
private String StDeviceStatus;
|
||||
|
||||
/**
|
||||
* 介质状态
|
||||
* PRESENT: 介质在通道
|
||||
* NOTPRESENT: 无介质
|
||||
* JAMMED: 卡介质
|
||||
* NOTSUPP: 不支持
|
||||
* UNKNOWN: 未知
|
||||
* EXITING: 介质在出口
|
||||
* RETRACTED 介质被回收(复位时)
|
||||
*/
|
||||
private String StMedia;
|
||||
|
||||
/**
|
||||
* 磁带状态
|
||||
* TONERFULL: 碳带满
|
||||
* TONERLOW: 碳带少
|
||||
* TONEROUT: 缺碳带
|
||||
* TONERNOTSUPP: 不支持碳带检测
|
||||
* TONERUNKNOWN: 碳带未知
|
||||
*/
|
||||
private String StToner;
|
||||
|
||||
/**
|
||||
* 墨盒状态
|
||||
* INKFULL: 墨盒满
|
||||
* INKLOW: 墨盒少
|
||||
* INKOUT: 缺墨盒
|
||||
* INKNOTSUPP: 不支持墨盒检测
|
||||
* INKUNKNOWN: 墨盒未知
|
||||
*/
|
||||
private String StInk;
|
||||
|
||||
/**
|
||||
* 纸盒扩展,取前面两个
|
||||
*/
|
||||
private String StPaperEx;
|
||||
|
||||
/**
|
||||
* 设备扩展,第一个是打印机状态,第二个是盖章机状态
|
||||
*/
|
||||
private String StDeviceExStatus;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dpkj.modules.readcard.controller;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.readcard.service.ReadCardService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("readCard")
|
||||
public class ReadCardController {
|
||||
@Autowired
|
||||
private ReadCardService readCardService;
|
||||
|
||||
/**
|
||||
* 身份证读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("IDCardReader")
|
||||
public Result IDCardReader() {
|
||||
return readCardService.IDCardReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* 社保卡读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("SocialSecurityCardReader")
|
||||
public Result SocialSecurityCardReader() {
|
||||
return readCardService.SocialSecurityCardReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* 社保卡退卡
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("cardRefund")
|
||||
public Result cardRefund() {
|
||||
return readCardService.cardRefund();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dpkj.modules.readcard.service;
|
||||
|
||||
import com.dpkj.common.vo.Result;
|
||||
|
||||
public interface ReadCardService {
|
||||
|
||||
Result IDCardReader();
|
||||
|
||||
Result SocialSecurityCardReader();
|
||||
|
||||
Result cardRefund();
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
package com.dpkj.modules.readcard.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.dpkj.common.constant.ErrorCodeConstants;
|
||||
import com.dpkj.common.constant.LexMarkConst;
|
||||
import com.dpkj.common.constant.MiddlewareFunctionsConst;
|
||||
import com.dpkj.common.dto.LexMarkDTO;
|
||||
import com.dpkj.common.utils.ThirdService;
|
||||
import com.dpkj.common.utils.ThirdServiceUtil;
|
||||
import com.dpkj.common.vo.Result;
|
||||
import com.dpkj.modules.readcard.service.ReadCardService;
|
||||
import com.dpkj.modules.readcard.vo.IDCardReadResultVO;
|
||||
import com.dpkj.modules.readcard.vo.SocialSecurityCardInfoVO;
|
||||
import com.dpkj.modules.readcard.vo.UserInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @BelongsProject: 银医通-澜沧中医院-DLL-台式机
|
||||
* @BelongsPackage: com.dpkj.modules.readcard.service.impl
|
||||
* @Author: wzc
|
||||
* @Description:
|
||||
* @CreateTime: 2025-02-07 10:21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ReadCardServiceImpl implements ReadCardService {
|
||||
|
||||
@Autowired
|
||||
private ThirdService thirdService;
|
||||
|
||||
@Autowired
|
||||
private ThirdServiceUtil thirdServiceUtil;
|
||||
|
||||
private String getLogPrefix() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
String methodName = stackTrace[3].getMethodName();
|
||||
return "[" + this.getClass().getSimpleName() + "#" + methodName + "] ";
|
||||
}
|
||||
|
||||
/**
|
||||
* 身份证读取
|
||||
* 1. 获取设备状态
|
||||
* 2. 设备连接状态需初始化
|
||||
* 3. 连接身份证读取设备
|
||||
* 4. 非接触身份证读取
|
||||
* 5. 关闭设备
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result IDCardReader() {
|
||||
// String logPrefix = getLogPrefix();
|
||||
Result result = null;
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][60]: {}", "开始执行身份证读取流程");
|
||||
try {
|
||||
// 获取设备状态
|
||||
|
||||
LexMarkDTO status = new LexMarkDTO();
|
||||
status.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
status.setCallID(0);
|
||||
status.setActionName(MiddlewareFunctionsConst.GET_STATUS_SYNC);
|
||||
JSONObject statusParam = new JSONObject();
|
||||
statusParam.put("timeout", 0);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][69]: 获取设备状态,参数:{}", status);
|
||||
IDCardReadResultVO statusResult = thirdServiceUtil.callDevice(status, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][71]: 获取设备状态结果{}", statusResult);
|
||||
if (statusResult.getResult() == 0) {
|
||||
// 连接状态,初始化
|
||||
LexMarkDTO reset = new LexMarkDTO();
|
||||
reset.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
reset.setCallID(0);
|
||||
reset.setActionName(MiddlewareFunctionsConst.RESET);
|
||||
JSONObject resetParam = new JSONObject();
|
||||
resetParam.put("ResetAction", 1);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][80]: 调用复位(初始化)方法,参数:{}", reset);
|
||||
IDCardReadResultVO resetResult = thirdServiceUtil.callDevice(reset, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][82]: 设备复位(初始化)结果: {}", resetResult);
|
||||
if (resetResult.getResult() == 0) {
|
||||
// 复位成功
|
||||
result = connectAndReadIDCard(result);
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()), resetResult.getResult());
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][88]: 身份证读取设备(初始化)异常,详情:{}", ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()));
|
||||
}
|
||||
} else {
|
||||
// 设备未连接,无需复位(初始化)
|
||||
result = connectAndReadIDCard(result);
|
||||
}
|
||||
} finally {
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][95]: {}", "准备关闭身份证读卡设备");
|
||||
// 关闭身份证读卡设备
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][101]: 调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][103]: 设备关闭结果: {}", closeResult);
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][105]: {}", "身份证读卡设备关闭异常!");
|
||||
}
|
||||
}
|
||||
log.info("[ReadCardServiceImpl][IDCardReader][108]: 身份证读取流程结束,最终返回结果: {}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result connectAndReadIDCard(Result result) {
|
||||
// String logPrefix = getLogPrefix();
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][114]: {}", "准备连接非接身份证读卡模块");
|
||||
// 连接非接身份证读卡模块
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(19256);
|
||||
connect.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 30000);
|
||||
connectParam.put("ServiceName", LexMarkConst.ID_CARD_READ);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][124]: 调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][126]: 设备连接结果: {}", connectResult);
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][128]: {}", "设备连接成功,准备读取身份证");
|
||||
// 身份证读取
|
||||
LexMarkDTO read = new LexMarkDTO();
|
||||
read.setActionName(MiddlewareFunctionsConst.ACCEPT_AND_READ_TRACKS);
|
||||
read.setCallID(19256);
|
||||
read.setDevName(LexMarkConst.ID_CARD_READ);
|
||||
JSONObject readParam = new JSONObject();
|
||||
readParam.put("TimeOut", 80000);
|
||||
readParam.put("TrackMap", 776);
|
||||
read.setParam(readParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][138]: 调用设备读取方法,参数: {}", read);
|
||||
IDCardReadResultVO readResult = thirdServiceUtil.callDevice(read, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][140]: 设备读取结果: {}", readResult);
|
||||
if (readResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][142]: {}", "身份证读取成功,开始解析身份证信息");
|
||||
IDCardReadResultVO.Param resultParam = JSON.parseObject(readResult.getParam().toString(), IDCardReadResultVO.Param.class);
|
||||
if (resultParam.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][145]: {}", "身份证信息解析成功,开始封装用户信息");
|
||||
UserInfoVO userInfoVO = new UserInfoVO();
|
||||
// 身份证基本信息 解析
|
||||
String[] array = Stream.of(resultParam.getChipdata().getDatas().split("\\|"))
|
||||
.filter(pair -> pair.contains("="))
|
||||
.map(pair -> pair.split("=")[1])
|
||||
.toArray(String[]::new);
|
||||
userInfoVO.setName(array[0]);
|
||||
userInfoVO.setSex(array[1]);
|
||||
userInfoVO.setNation(array[2]);
|
||||
userInfoVO.setBorn(array[3]);
|
||||
userInfoVO.setAddress(array[4]);
|
||||
userInfoVO.setIDCardNo(array[5]);
|
||||
userInfoVO.setGrantDept(array[6]);
|
||||
userInfoVO.setUserLifeBegin(array[7]);
|
||||
userInfoVO.setUserLifeEnd(array[8]);
|
||||
userInfoVO.setIDhead(array[9].replace("\\\\", "/"));
|
||||
// 正面
|
||||
userInfoVO.setFrontimage(resultParam.getFrontimage().getDatas().replace("\\\\", "/"));
|
||||
// 反面
|
||||
userInfoVO.setBackimage(resultParam.getBackimage().getDatas().replace("\\\\", "/"));
|
||||
result = Result.ok(userInfoVO);
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][167]: 用户信息封装成功,返回结果: {}", result);
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(resultParam.getResult()), resultParam.getResult());
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][170]: 身份证信息解析失败,错误信息: {}, 返回结果: {}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(resultParam.getResult()), result);
|
||||
}
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(readResult.getResult()), readResult.getResult());
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][175]: 身份证读取失败,错误信息: {}, 返回结果: {}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(readResult.getResult()), result);
|
||||
}
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(connectResult.getResult()), connectResult.getResult());
|
||||
log.info("[ReadCardServiceImpl][connectAndReadIDCard][180]: 设备连接失败,错误信息: {}, 返回结果: {}", connectResult, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 社保卡读取
|
||||
* 1. 获取社保卡读取设备状态
|
||||
* 2. 连接状态需复位(初始化)
|
||||
* 3. 连接社保卡读取设备
|
||||
* 4. 进卡读卡
|
||||
* 5. 读卡器上电
|
||||
* 6. 社保卡信息读取
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result SocialSecurityCardReader() {
|
||||
// String logPrefix = getLogPrefix();
|
||||
Result result = null;
|
||||
// 获取设备状态
|
||||
LexMarkDTO status = new LexMarkDTO();
|
||||
status.setDevName(LexMarkConst.CARD_READER);
|
||||
status.setCallID(0);
|
||||
status.setActionName(MiddlewareFunctionsConst.GET_STATUS_SYNC);
|
||||
JSONObject statusParam = new JSONObject();
|
||||
statusParam.put("timeout", 0);
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][208]: 获取设备状态,参数: {}", status);
|
||||
IDCardReadResultVO statusResult = thirdServiceUtil.callDevice(status, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][210]: 获取设备状态结果: {}", statusResult);
|
||||
if (statusResult.getResult() == 0) {
|
||||
// 连接状态,初始化
|
||||
LexMarkDTO reset = new LexMarkDTO();
|
||||
reset.setDevName(LexMarkConst.CARD_READER);
|
||||
reset.setCallID(0);
|
||||
reset.setActionName(MiddlewareFunctionsConst.RESET);
|
||||
JSONObject resetParam = new JSONObject();
|
||||
resetParam.put("ResetAction", 1);
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][219]: 调用复位(初始化)方法,参数: {}", reset);
|
||||
IDCardReadResultVO resetResult = thirdServiceUtil.callDevice(reset, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][221]: 设备复位(初始化)结果: {}", resetResult);
|
||||
if (resetResult.getResult() == 0) {
|
||||
// 复位成功
|
||||
result = connectAndSocialSecurityCardReader(result);
|
||||
} else {
|
||||
result = Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()), resetResult.getResult());
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][227]: 社保卡读取设备(初始化)异常,详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(resetResult.getResult()));
|
||||
}
|
||||
} else {
|
||||
// 设备未连接,无需复位(初始化)
|
||||
result = connectAndSocialSecurityCardReader(result);
|
||||
}
|
||||
log.info("[ReadCardServiceImpl][SocialSecurityCardReader][234]: 社保卡读取流程结束,最终返回结果: {}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result connectAndSocialSecurityCardReader(Result result) {
|
||||
// String logPrefix = getLogPrefix();
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][240]: {}", "开始执行社保卡读取流程");
|
||||
|
||||
// 社保卡读卡设备连接
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][243]: {}", "准备连接社保卡读卡设备");
|
||||
LexMarkDTO connect = new LexMarkDTO();
|
||||
connect.setActionName(MiddlewareFunctionsConst.OPEN_CONNECTION);
|
||||
connect.setCallID(19256);
|
||||
connect.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject connectParam = new JSONObject();
|
||||
connectParam.put("TimeOut", 30000);
|
||||
connectParam.put("ServiceName", LexMarkConst.CARD_READER);
|
||||
connect.setParam(connectParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][252]: 调用设备连接方法,参数: {}", connect);
|
||||
IDCardReadResultVO connectResult = thirdServiceUtil.callDevice(connect, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][254]: 设备连接结果: {}", connectResult);
|
||||
if (connectResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][256]: {}", "社保卡读卡设备连接成功,准备进卡");
|
||||
|
||||
// 进卡
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][259]: {}", "准备执行进卡操作");
|
||||
LexMarkDTO enterTheCard = new LexMarkDTO();
|
||||
enterTheCard.setActionName(MiddlewareFunctionsConst.ACCEPT_AND_READ_TRACKS);
|
||||
enterTheCard.setCallID(19256);
|
||||
enterTheCard.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject enterTheCardParam = new JSONObject();
|
||||
enterTheCardParam.put("DevType", 5);
|
||||
enterTheCardParam.put("TrackMap", 11);
|
||||
enterTheCardParam.put("TimeOut", 80000);
|
||||
enterTheCard.setParam(enterTheCardParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][269]: 调用进卡方法,参数: {}", enterTheCard);
|
||||
IDCardReadResultVO enterTheCardResult = thirdServiceUtil.callDevice(enterTheCard, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][271]: 进卡操作结果: {}", enterTheCardResult);
|
||||
if (enterTheCardResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][273]: {}", "进卡操作成功,准备上电");
|
||||
|
||||
// 上电
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][276]: {}", "准备执行上电操作");
|
||||
LexMarkDTO powerOn = new LexMarkDTO();
|
||||
powerOn.setActionName(MiddlewareFunctionsConst.CHIPPOWER);
|
||||
powerOn.setCallID(19256);
|
||||
powerOn.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject powerOnParam = new JSONObject();
|
||||
powerOnParam.put("PsamNo", 1);
|
||||
powerOnParam.put("ChipAction", 2);
|
||||
powerOn.setParam(powerOnParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][285]: 调用上电方法,参数: {}", powerOn);
|
||||
IDCardReadResultVO powerOnResult = thirdServiceUtil.callDevice(powerOn, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][287]: 上电操作结果: {}", powerOnResult);
|
||||
if (powerOnResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][289]: {}", "上电操作成功,准备读取社保卡信息");
|
||||
|
||||
// 社保卡信息读取
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][292]: {}", "准备读取社保卡信息");
|
||||
LexMarkDTO socialSecurityCardReader = new LexMarkDTO();
|
||||
socialSecurityCardReader.setActionName(MiddlewareFunctionsConst.I_READ_CARD_BAS);
|
||||
socialSecurityCardReader.setCallID(19256);
|
||||
socialSecurityCardReader.setDevName(LexMarkConst.CARD_READER);
|
||||
JSONObject socialSecurityCardReaderParam = new JSONObject();
|
||||
socialSecurityCardReaderParam.put("iType", 3);
|
||||
socialSecurityCardReader.setParam(socialSecurityCardReaderParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][300]: 调用读取社保卡信息方法,参数: {}", socialSecurityCardReader);
|
||||
IDCardReadResultVO socialSecurityCardReaderResult = thirdServiceUtil.callDevice(socialSecurityCardReader, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][302]: 读取社保卡信息结果: {}", socialSecurityCardReaderResult);
|
||||
if (socialSecurityCardReaderResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][304]: {}", "社保卡信息读取成功,开始解析信息");
|
||||
|
||||
// 社保信息
|
||||
IDCardReadResultVO.SocialSecurityCard resultParam = JSON.parseObject(socialSecurityCardReaderResult.getParam().toString(), IDCardReadResultVO.SocialSecurityCard.class);
|
||||
String[] split = resultParam.getRerurnData().split("\\|");
|
||||
SocialSecurityCardInfoVO socialSecurityCardInfoVO = new SocialSecurityCardInfoVO();
|
||||
// 区号代码截取
|
||||
socialSecurityCardInfoVO.setAreaCode(split[0].substring(split[0].length() - 6));
|
||||
socialSecurityCardInfoVO.setSocialSecurityNo(split[1]);
|
||||
socialSecurityCardInfoVO.setCardNumber(split[2]);
|
||||
socialSecurityCardInfoVO.setIdentificationCode(split[3]);
|
||||
socialSecurityCardInfoVO.setName(split[4]);
|
||||
socialSecurityCardInfoVO.setCardResetInformation(split[5]);
|
||||
socialSecurityCardInfoVO.setSpecificationVersion(split[6]);
|
||||
socialSecurityCardInfoVO.setIssuanceDate(split[7]);
|
||||
socialSecurityCardInfoVO.setExpireDate(split[8]);
|
||||
socialSecurityCardInfoVO.setTerminalNumber(split[9]);
|
||||
socialSecurityCardInfoVO.setTerminalDeviceNumber(split[10]);
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][322]: {}", "社保卡信息解析完成,返回成功结果");
|
||||
return Result.ok(socialSecurityCardInfoVO);
|
||||
} else {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][325]: 社保卡信息读取失败,详情:{}",
|
||||
ErrorCodeConstants.SOCIAL_SECURITYCARD_ERROR_CODE.get(socialSecurityCardReaderResult.getResult()));
|
||||
return Result.error(ErrorCodeConstants.SOCIAL_SECURITYCARD_ERROR_CODE.get(socialSecurityCardReaderResult.getResult()), socialSecurityCardReaderResult.getResult());
|
||||
}
|
||||
} else {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][330]: 社保卡读取设备上电失败,详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(powerOnResult.getResult()));
|
||||
return Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(powerOnResult.getResult()), powerOnResult.getResult());
|
||||
}
|
||||
} else {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][335]: 社保卡读取设备进卡失败,详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(enterTheCardResult.getResult()));
|
||||
return Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(enterTheCardResult.getResult()), enterTheCardResult.getResult());
|
||||
}
|
||||
} else {
|
||||
log.info("[ReadCardServiceImpl][connectAndSocialSecurityCardReader][340]: 社保卡读取设备连接失败,详情:{}",
|
||||
ErrorCodeConstants.COMMON_ERROR_CODE.get(connectResult.getResult()));
|
||||
return Result.error(ErrorCodeConstants.COMMON_ERROR_CODE.get(connectResult.getResult()), connectResult.getResult());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退卡并关闭设备
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result cardRefund() {
|
||||
// String logPrefix = getLogPrefix();
|
||||
log.info("[ReadCardServiceImpl][cardRefund][354]: {}", "开始执行社保卡退卡流程");
|
||||
|
||||
// 社保卡退卡
|
||||
log.info("[ReadCardServiceImpl][cardRefund][357]: {}", "准备发起社保卡退卡请求");
|
||||
LexMarkDTO cardRefund = new LexMarkDTO();
|
||||
cardRefund.setDevName(LexMarkConst.CARD_READER);
|
||||
cardRefund.setCallID(19256);
|
||||
cardRefund.setActionName(MiddlewareFunctionsConst.EJECT);
|
||||
JSONObject cardRefundParam = new JSONObject();
|
||||
cardRefundParam.put("position", 1);
|
||||
cardRefundParam.put("ejectpos", 1);
|
||||
cardRefund.setParam(cardRefundParam.toJSONString());
|
||||
log.info("[ReadCardServiceImpl][cardRefund][366]: 调用设备退卡方法,参数: {}", cardRefund);
|
||||
IDCardReadResultVO cardRefundResult = thirdServiceUtil.callDevice(cardRefund, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][cardRefund][368]: 设备退卡操作结果: {}", cardRefundResult);
|
||||
|
||||
if (cardRefundResult.getResult() == 0) {
|
||||
log.info("[ReadCardServiceImpl][cardRefund][371]: {}", "社保卡退卡成功,准备关闭社保卡读卡设备");
|
||||
|
||||
// 退卡成功再关闭社保卡读卡设备
|
||||
LexMarkDTO close = new LexMarkDTO();
|
||||
close.setDevName(LexMarkConst.CARD_READER);
|
||||
close.setCallID(0);
|
||||
close.setActionName(MiddlewareFunctionsConst.CLOSE_CONNECTION);
|
||||
log.info("[ReadCardServiceImpl][cardRefund][378]: {}", "调用设备关闭方法,参数: {}", close);
|
||||
IDCardReadResultVO closeResult = thirdServiceUtil.callDevice(close, IDCardReadResultVO.class);
|
||||
log.info("[ReadCardServiceImpl][cardRefund][380]: 设备关闭操作结果: {}", closeResult);
|
||||
|
||||
if (closeResult.getResult() != 0) {
|
||||
log.info("[ReadCardServiceImpl][cardRefund][383]: 社保卡读卡设备关闭异常!详情:{}",
|
||||
ErrorCodeConstants.SOCIAL_SECURITYCARD_ERROR_CODE.get(closeResult.getResult()), closeResult.getResult());
|
||||
}
|
||||
log.info("[ReadCardServiceImpl][cardRefund][386]: {}", "社保卡退卡流程完成,退卡成功");
|
||||
return Result.ok("退卡成功!");
|
||||
} else {
|
||||
log.info("[ReadCardServiceImpl][cardRefund][389]: 退卡失败!请联系工作人员!失败原因:{}",
|
||||
ErrorCodeConstants.SOCIAL_SECURITYCARD_ERROR_CODE.get(cardRefundResult.getResult()));
|
||||
return Result.error(ErrorCodeConstants.SOCIAL_SECURITYCARD_ERROR_CODE.get(cardRefundResult.getResult()), cardRefundResult.getResult());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 身份证读取模块返回值
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class IDCardReadResultVO<T> implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 对应发送请求中的devName
|
||||
*/
|
||||
private String devName;
|
||||
|
||||
/**
|
||||
* 事件名,由发送请求中的actionName+Over组成。
|
||||
*/
|
||||
private String msgName;
|
||||
|
||||
/**
|
||||
* 对应发送请求的callID。
|
||||
*/
|
||||
private int callID;
|
||||
|
||||
/**
|
||||
* 错误码:0表示成功;其他表示失败,比如-4表示取消,-48表示超时,-14表示硬件故障
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 发送请求中的actionName
|
||||
*/
|
||||
private String cmdName;
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private T param;
|
||||
|
||||
/**
|
||||
* 详情描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Param {
|
||||
|
||||
/**
|
||||
* 请求ID
|
||||
*/
|
||||
private int RequestID;
|
||||
|
||||
/**
|
||||
* 身份证反面图像数据
|
||||
*/
|
||||
private Backimage backimage;
|
||||
|
||||
/**
|
||||
* 身份证基础信息
|
||||
*/
|
||||
private Chipdata chipdata;
|
||||
|
||||
/**
|
||||
* 指令ID
|
||||
*/
|
||||
private int dwCommandCode;
|
||||
|
||||
/**
|
||||
* 结束事件名称
|
||||
*/
|
||||
private String AcceptAndReadTracksOver;
|
||||
|
||||
/**
|
||||
* 事件ID
|
||||
*/
|
||||
private int eventType;
|
||||
|
||||
/**
|
||||
* 身份证正面图像数据
|
||||
*/
|
||||
private Frontimage frontimage;
|
||||
|
||||
/**
|
||||
* 服务ID
|
||||
*/
|
||||
private int hService;
|
||||
|
||||
/**
|
||||
* 读取结果 0成功 <0失败
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 调用的方法名称(操作函数)
|
||||
*/
|
||||
private String cmdName;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Backimage {
|
||||
/**
|
||||
* 身份证反面图像存储路径
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Frontimage {
|
||||
/**
|
||||
* 身份证正面图像存储路径
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Chipdata {
|
||||
/**
|
||||
* 身份证基本信息
|
||||
*/
|
||||
private String datas;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private int len;
|
||||
|
||||
/**
|
||||
* 返回的数据状态
|
||||
* DATAOK 读取正常
|
||||
* BLANK 空
|
||||
* INVALID 无效
|
||||
* NOTREAD 未读取
|
||||
*/
|
||||
private String status;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class SocialSecurityCard {
|
||||
/**
|
||||
* 社保卡基本信息
|
||||
*/
|
||||
private String RerurnData;
|
||||
|
||||
/**
|
||||
* 社保卡读取响应信息
|
||||
*/
|
||||
private String msgerror;
|
||||
|
||||
/**
|
||||
* 社保卡读取响应结果 0成功 <0失败
|
||||
*/
|
||||
private int result;
|
||||
|
||||
/**
|
||||
* 调用的方法
|
||||
*/
|
||||
private String cmdName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 社保卡信息
|
||||
*/
|
||||
@Data
|
||||
public class SocialSecurityCardInfoVO {
|
||||
// 发卡地区行政区划代码
|
||||
private String areaCode;
|
||||
// 社会保障号码
|
||||
private String socialSecurityNo;
|
||||
// 卡号
|
||||
private String cardNumber;
|
||||
// 卡识别码
|
||||
private String identificationCode;
|
||||
// 姓名
|
||||
private String name;
|
||||
// 卡复位信息
|
||||
private String cardResetInformation;
|
||||
// 规范版本
|
||||
private String specificationVersion;
|
||||
// 发卡日期
|
||||
private String issuanceDate;
|
||||
// 卡有效期
|
||||
private String expireDate;
|
||||
// 终端机编号
|
||||
private String terminalNumber;
|
||||
// 终端设备号
|
||||
private String terminalDeviceNumber;
|
||||
}
|
||||
35
src/main/java/com/dpkj/modules/readcard/vo/UserInfoVO.java
Normal file
35
src/main/java/com/dpkj/modules/readcard/vo/UserInfoVO.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.dpkj.modules.readcard.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 身份证读取信息
|
||||
*/
|
||||
@Data
|
||||
public class UserInfoVO {
|
||||
// 姓名
|
||||
private String name;
|
||||
// 性别
|
||||
private String sex;
|
||||
// 名族
|
||||
private String nation;
|
||||
// 出生年月
|
||||
private String born;
|
||||
// 地址
|
||||
private String address;
|
||||
// 身份证号
|
||||
private String IDCardNo;
|
||||
// 签发机关
|
||||
private String grantDept;
|
||||
// 有效期起始日期
|
||||
private String userLifeBegin;
|
||||
// 有效期截止日期
|
||||
private String userLifeEnd;
|
||||
// 头像照片存储位置
|
||||
private String IDhead;
|
||||
// 证件正面照存储位置
|
||||
private String frontimage;
|
||||
// 证件反面面照存储位置
|
||||
private String backimage;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,11 @@
|
||||
server:
|
||||
port: 5946
|
||||
|
||||
dpkj:
|
||||
# 医保配置
|
||||
chs:
|
||||
# 医保机构编码
|
||||
orgcode: H53082800070
|
||||
file:
|
||||
# 文件保存地址
|
||||
path: G:\Temp\img
|
||||
@@ -6,8 +13,18 @@ dpkj:
|
||||
printer:
|
||||
# 打印机连接方式 USB: usb连接 | BTMS:串口连接
|
||||
connection-type: USB
|
||||
# 终端号设置
|
||||
terminal-Number: PORT-000000001
|
||||
# 打印时间格式化
|
||||
time-Type: yyyy-MM-dd HH:mm:ss
|
||||
# 打印端口 串口连接下使用
|
||||
port-name:
|
||||
# 波特率 串口连接下使用
|
||||
baud-rate:
|
||||
|
||||
# 自定义app参数
|
||||
app:
|
||||
custom:
|
||||
lexMarkServiceIp: http://127.0.0.1
|
||||
lexMarkServicePort: 12346
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
server:
|
||||
port: 5946
|
||||
|
||||
dpkj:
|
||||
# 医保配置
|
||||
chs:
|
||||
# 医保机构编码
|
||||
orgcode: H53082800070
|
||||
file:
|
||||
# 文件保存地址
|
||||
path: D:\Project\Express\upload
|
||||
@@ -6,8 +13,17 @@ dpkj:
|
||||
printer:
|
||||
# 打印机连接方式 USB: usb连接 | BTMS:串口连接
|
||||
connection-type: USB
|
||||
# 终端号设置
|
||||
terminal-Number: PORT-000000001
|
||||
# 打印时间格式化
|
||||
time-Type: yyyy-MM-dd HH:mm:ss
|
||||
# 打印端口 串口连接下使用
|
||||
port-name:
|
||||
# 波特率 串口连接下使用
|
||||
baud-rate:
|
||||
|
||||
# 自定义app参数
|
||||
app:
|
||||
custom:
|
||||
lexMarkServiceIp: http://127.0.0.1
|
||||
lexMarkServicePort: 12346
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
resource:
|
||||
static-locations: classpath:/static/,classpath:/public/
|
||||
application:
|
||||
name: ems-express-bridge
|
||||
profiles:
|
||||
#active: '@profile.name@'
|
||||
active: pro
|
||||
|
||||
server:
|
||||
port: 5946
|
||||
servlet:
|
||||
context-path: /api
|
||||
tomcat:
|
||||
@@ -25,3 +11,15 @@ server:
|
||||
enabled: true
|
||||
min-response-size: 1024
|
||||
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
resource:
|
||||
static-locations: classpath:/static/,classpath:/public/
|
||||
application:
|
||||
name: ems-express-bridge
|
||||
profiles:
|
||||
active: pro
|
||||
|
||||
78
src/main/resources/templates/department.html
Normal file
78
src/main/resources/templates/department.html
Normal file
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>门诊缴费凭证</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="font-weight: 700;">
|
||||
<div style="text-align: center;margin-top: 40px;">
|
||||
<div><span style="font-size: 28px;">******<span th:text="${hospitalName}"></span>******</span></div>
|
||||
<div style="font-size: 38px; margin-top: 20px;"><span th:text="${registeTerminalName}"></span></div>
|
||||
<div style="font-size: 38px; margin-top: 10px;"><span th:text="${registeType}"></span></div>
|
||||
</div>
|
||||
<div style="text-align: center; font-size: 32px;">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div style="font-size: 35px; margin: 10px 20px">
|
||||
<div style="display: flex">
|
||||
<div style="width: 38.3%;word-break: break-all;">
|
||||
<span>姓名:</span><span th:text="${name}"></span>
|
||||
</div>
|
||||
<div style="width: 28.3%;word-break: break-all;"><span>性别:</span><span th:text="${gender}"></span></div>
|
||||
<div style="width: 33.3%;word-break: break-all;"><span>年龄:</span><span th:text="${age}"></span></div>
|
||||
</div>
|
||||
<div style="display: flex;margin-top: 10px;">
|
||||
<div style="width: 50%;word-break: break-all;" th:if="${outpatientNumber}">
|
||||
<span>门诊号:</span><span th:text="${outpatientNumber}"></span></div>
|
||||
<div style="width: 50%;word-break: break-all;" th:if="${doctor}">
|
||||
<span>就诊医生:</span><span th:text="${doctor}"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px;" th:if="${department}"><span>就诊科室:</span><span th:text="${department}"></span></div>
|
||||
</div>
|
||||
<div style="text-align: center; font-size: 32px;">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div style="font-size: 35px; margin: 10px 20px">
|
||||
<div style="display: flex;">
|
||||
<div style="flex: 1;"><span>费用总额:</span><span th:text="${totalFee}"></span></div>
|
||||
<div style="flex: 1;"><span>个人支付:</span><span th:text="${personalPayment}"></span></div>
|
||||
</div>
|
||||
<div style="margin-top: 10px;"><span>实收金额:</span><span th:text="${actualReceiptAmount}"></span></div>
|
||||
<div style="margin-top: 10px;"><span>实收金额:</span><span th:text="${actualReceiptAmountChinese}"></span></div>
|
||||
</div>
|
||||
<div style="text-align: center; font-size: 32px;">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div style="margin: 10px 20px">
|
||||
<table style="width: 100%; table-layout: fixed; border-collapse: collapse;">
|
||||
<tr style="font-size: 35px;">
|
||||
<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>
|
||||
</tr>
|
||||
<tr style="font-size: 30px;" th:each="item : ${items}">
|
||||
<td style="text-align: left;width: 300px;word-break: break-all;" th:text="${item.name}"></td>
|
||||
<td style="text-align: center;" th:text="${item.quantity}"></td>
|
||||
<td style="text-align: center;" th:text="${item.unitPrice}"></td>
|
||||
<td style="text-align: center;" th:text="${item.subtotal}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 32px;">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div style="margin-left: 20px; font-weight: 700; font-size: 35px;">
|
||||
<div>终端编号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div>打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
<div style="margin-left: 20px; font-size: 35px; font-weight: 700; margin-top: 20px;">
|
||||
<span style="margin-top: 20px;">温馨提示</span><br>
|
||||
<span>1.请取走全部凭条、并妥善保管</span><br>
|
||||
<span>2.如果对缴费结算存在疑问,请到人工窗口咨询</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
188
src/main/resources/templates/department2.html
Normal file
188
src/main/resources/templates/department2.html
Normal file
@@ -0,0 +1,188 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>门诊缴费凭证</title>
|
||||
<style>
|
||||
.bold-text {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.text-35 {
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
.text-30 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.center-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.margin-top-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.margin-top-40 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.header-terminal {
|
||||
font-size: 38px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.header-receipt {
|
||||
font-size: 38px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.patient-info {
|
||||
font-size: 35px;
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
.patient-info .info-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.patient-info .info-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.payment-info {
|
||||
font-size: 35px;
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
.payment-info .info-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.payment-info .info-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
.table-container table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
.table-container .first-th {
|
||||
width: 300px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.table-container .df-th {
|
||||
width: calc(25% - 5px);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-container .first-td {
|
||||
text-align: left;
|
||||
width: 300px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.table-container .df-td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.terminal-info {
|
||||
margin-left: 20px;
|
||||
font-weight: 700;
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-left: 20px;
|
||||
font-size: 35px;
|
||||
font-weight: 700;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="bold-text">
|
||||
<div class="center-text margin-top-40">
|
||||
<div><span class="header-title">******<span th:text="${hospitalName}"></span>******</span></div>
|
||||
<div class="header-terminal"><span th:text="${registeTerminalName}"></span></div>
|
||||
<div class="header-receipt"><span th:text="${registeType}"></span></div>
|
||||
</div>
|
||||
<div class="divider">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div class="patient-info">
|
||||
<div class="info-row">
|
||||
<div class="info-item">姓名:<span th:text="${name}"></span></div>
|
||||
<div class="info-item">性别:<span th:text="${gender}"></span></div>
|
||||
<div class="info-item">年龄:<span th:text="${age}"></span></div>
|
||||
</div>
|
||||
<div class="info-row margin-top-10">
|
||||
<div class="info-item" th:if="${outpatientNumber}">门诊号:<span th:text="${outpatientNumber}"></span></div>
|
||||
<div class="info-item" th:if="${doctor}">就诊医生:<span th:text="${doctor}"></span></div>
|
||||
</div>
|
||||
<div class="margin-top-10" th:if="${department}">就诊科室:<span th:text="${department}"></span></div>
|
||||
</div>
|
||||
<div class="divider">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div class="payment-info">
|
||||
<div class="info-row">
|
||||
<div class="info-item">费用总额:<span th:text="${totalFee}"></span></div>
|
||||
<div class="info-item">个人支付:<span th:text="${personalPayment}"></span></div>
|
||||
</div>
|
||||
<div class="margin-top-10">实收金额:<span th:text="${actualReceiptAmount}"></span></div>
|
||||
<div class="margin-top-10">实收金额:<span th:text="${actualReceiptAmountChinese}"></span></div>
|
||||
</div>
|
||||
<div class="divider">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<tr class="text-35">
|
||||
<th class="first-th">项目名称</th>
|
||||
<th class="df-th">数量</th>
|
||||
<th class="df-th">单价</th>
|
||||
<th class="df-th">小计</th>
|
||||
</tr>
|
||||
<tr class="text-30" th:each="item : ${items}">
|
||||
<td class="first-td" th:text="${item.name}"></td>
|
||||
<td class="df-td" th:text="${item.quantity}"></td>
|
||||
<td class="df-td" th:text="${item.unitPrice}"></td>
|
||||
<td class="df-td" th:text="${item.subtotal}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="divider">
|
||||
-----------------------------------------------------------------------------
|
||||
</div>
|
||||
<div class="terminal-info">
|
||||
<div>终端编号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div>打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
<div class="tips">
|
||||
<span>温馨提示</span><br>
|
||||
<span>1.请取走全部凭条、并妥善保管</span><br>
|
||||
<span>2.如果对缴费结算存在疑问,请到人工窗口咨询</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
34
src/main/resources/templates/hospitalPayment.html
Normal file
34
src/main/resources/templates/hospitalPayment.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>挂号单</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="font-size: 32px; margin-top: 20px;">
|
||||
<div style="">
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${hospitalName}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 28px;">****<span th:text="${registeTerminalName}"></span></span>****</div>
|
||||
<div style="text-align: center; font-weight: 700; margin-bottom: -10px; margin-top: -10px;">-----------------------------------------------------------------------------</div>
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${registeType}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; margin-top: -15px;">-----------------------------------------------------------------------------</div>
|
||||
</div>
|
||||
<div style="font-weight: 700; font-size: 37px;">
|
||||
<div style="margin-left: 35px;">姓  名:<span th:text="${name}"></span></div>
|
||||
<div style="margin-left: 35px;">性  别:<span th:text="${gender}"></span></div>
|
||||
<div style="margin-left: 35px;">年  龄:<span th:text="${age}"></span></div>
|
||||
<div style="margin-left: 35px;">出生日期:<span th:text="${birthDate}"></span></div>
|
||||
<div style="margin-left: 35px;">门 诊 号:<span th:text="${outpatientNumber}"></span></div>
|
||||
<div style="margin-left: 35px;">入院科室:<span th:text="${department}"></span></div>
|
||||
<div style="margin-left: 35px;">总 费 用:<span th:text="${totalFee}"></span> 元</div>
|
||||
<div style="margin-left: 35px;">支付方式:<span th:text="${paymentMethod}"></span></div>
|
||||
<div style="margin-left: 35px;">交易流水:<span style="font-size: 35px;" th:text="${transactionNumber}"></span></div>
|
||||
</div>
|
||||
<div style="font-weight: 700; margin-top: 8px;">
|
||||
<!-- <div style="margin-top: -40px; text-align: center; ">-----------------------------------------------------------------------------</div>-->
|
||||
<div style="font-size: 36px;margin-left: 35px; ">备注:缴费凭证,请妥善保管!</div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">终 端 号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
32
src/main/resources/templates/outpatientPayment.html
Normal file
32
src/main/resources/templates/outpatientPayment.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>门诊缴费</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="font-size: 32px; margin-top: 20px;">
|
||||
<div style="">
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${hospitalName}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 28px;">****<span th:text="${registeTerminalName}"></span></span>****</div>
|
||||
<div style="text-align: center; font-weight: 700; margin-bottom: -10px; margin-top: -10px;">-----------------------------------------------------------------------------</div>
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${registeType}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; margin-top: -15px;">-----------------------------------------------------------------------------</div>
|
||||
</div>
|
||||
<div style="font-weight: 700; font-size: 37px;">
|
||||
<div style="margin-left: 35px;">姓  名:<span th:text="${name}"></span></div>
|
||||
<div style="margin-left: 35px;">性  别:<span th:text="${gender}"></span></div>
|
||||
<div style="margin-left: 35px;">年  龄:<span th:text="${age}"></span></div>
|
||||
<div style="margin-left: 35px;">出生日期:<span th:text="${birthDate}"></span></div>
|
||||
<div style="margin-left: 35px;">总 费 用:<span th:text="${totalFee}"></span> 元</div>
|
||||
<div style="margin-left: 35px;">支付方式:<span th:text="${paymentMethod}"></span></div>
|
||||
<div style="margin-left: 35px;">交易流水:<span style="font-size: 35px;" th:text="${transactionNumber}"></span></div>
|
||||
</div>
|
||||
<div style="font-weight: 700; margin-top: 8px;">
|
||||
<!-- <div style="margin-top: -40px; text-align: center; ">-----------------------------------------------------------------------------</div>-->
|
||||
<div style="font-size: 36px;margin-left: 35px; ">备注:缴费凭证,请妥善保管!</div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">终 端 号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
63
src/main/resources/templates/register.html
Normal file
63
src/main/resources/templates/register.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>挂号单</title>
|
||||
</head>
|
||||
<style>
|
||||
.x-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.x-start {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.x-end {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.x-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div style="font-size: 32px; margin-top: 20px;">
|
||||
<div style="">
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${hospitalName}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; font-size: 28px;">****<span th:text="${registeTerminalName}"></span></span>****</div>
|
||||
<div style="text-align: center; font-weight: 700; margin-bottom: -10px; margin-top: -10px;">-----------------------------------------------------------------------------</div>
|
||||
<div style="text-align: center; font-size: 40px; font-weight: 700;"><span th:text="${registeType}"></span></div>
|
||||
<div style="text-align: center; font-weight: 700; margin-top: -15px;">-----------------------------------------------------------------------------</div>
|
||||
</div>
|
||||
<div style="font-weight: 700; font-size: 37px;">
|
||||
<div style="margin-left: 35px;">姓  名:<span th:text="${name}"></span></div>
|
||||
<div style="margin-left: 35px;">性  别:<span th:text="${gender}"></span></div>
|
||||
<div style="margin-left: 35px;">年  龄:<span th:text="${age}"></span></div>
|
||||
<div style="margin-left: 35px;">出生日期:<span th:text="${birthDate}"></span></div>
|
||||
<!-- <div style="margin-left: 35px;">卡  号:<span th:text="${cardNumber}"></span></div>-->
|
||||
<div style="margin-left: 35px;">门 诊 号:<span th:text="${outpatientNumber}"></span></div>
|
||||
<div style="margin-left: 35px;">就诊科室:<span th:text="${department}"></span></div>
|
||||
<div style="margin-left: 35px;">出诊级别:<span th:text="${visitLevel}"></span></div>
|
||||
<div style="margin-left: 35px;">就诊医生:<span th:text="${doctor}"></span></div>
|
||||
<div style="margin-left: 35px;">号  序:<span th:text="${sequence}"></span></div>
|
||||
<div style="margin-left: 35px;">挂号日期:<span th:text="${registerDate}"></span></div>
|
||||
<div style="margin-left: 35px;">总 费 用:<span th:text="${totalFee}"></span> 元</div>
|
||||
<div style="margin-left: 35px;">支付方式:<span th:text="${paymentMethod}"></span></div>
|
||||
<!-- <div style="margin-left: 35px;">订 单 号:<span style="font-size: 36px;" th:text="${orderNumber}"></span></div>-->
|
||||
<div style="margin-left: 35px;">交易流水:<span style="font-size: 35px;"
|
||||
th:text="${transactionNumber}"></span></div>
|
||||
<div style="width: 100%; text-align: center; margin-bottom: -20px;">
|
||||
<img style="display: inline-block; "
|
||||
th:src="${qrCodeBase64}"
|
||||
alt="QR Code" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-weight: 700; margin-top: 8px;">
|
||||
<div style="margin-top: -40px; text-align: center; ">-----------------------------------------------------------------------------</div>
|
||||
<div style="font-size: 36px;margin-left: 35px; ">备注:凭此条退费,请妥善保管!</div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">终 端 号:<span th:text="${terminalNumber}"></span></div>
|
||||
<div style="font-size: 36px;margin-left: 35px;">打印时间:<span th:text="${printTime}"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/win32-x86/NationECCode.dll
Normal file
BIN
src/main/resources/win32-x86/NationECCode.dll
Normal file
Binary file not shown.
BIN
src/main/resources/win32-x86/PayClient.dll
Normal file
BIN
src/main/resources/win32-x86/PayClient.dll
Normal file
Binary file not shown.
@@ -1,79 +0,0 @@
|
||||
package com.dpkj.ems.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import com.dpkj.Application;
|
||||
import com.dpkj.common.config.FileConfig;
|
||||
import com.dpkj.modules.express.service.PrinterService;
|
||||
import com.dpkj.modules.express.utils.FileUtils;
|
||||
import com.dpkj.modules.express.utils.PrinterUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class)
|
||||
class PrinterUtilTest {
|
||||
|
||||
@Autowired
|
||||
private PrinterService printerService;
|
||||
@Autowired
|
||||
private FileConfig fileConfig;
|
||||
|
||||
@Test
|
||||
void getPrintSDK() throws PrinterUtil.PrinterRegistrationException {
|
||||
PrinterUtil.MsPrintSdk sdk = PrinterUtil.getPrintSDK();
|
||||
int i = sdk.SetUsbportauto();
|
||||
Console.log(i);
|
||||
|
||||
int i1 = sdk.SetInit();
|
||||
Console.log(i1);
|
||||
|
||||
int i2 = sdk.GetStatusspecial();
|
||||
Console.log(i2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void t2() throws IOException {
|
||||
String base64Path = "G:\\Temp\\text\\base64.txt";
|
||||
String base64 = FileUtil.readString(FileUtil.file(base64Path), StandardCharsets.UTF_8);
|
||||
|
||||
String bpmPath = "G:\\Temp\\img";
|
||||
List<BufferedImage> bufferedImages = FileUtils.convertBase64PdfToBufferedImage(base64);
|
||||
FileUtils.saveBufferedImageToBmp(bufferedImages);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void t3() throws Exception {
|
||||
String base64Path = "G:\\Temp\\text\\base64.txt";
|
||||
String base64 = FileUtil.readString(FileUtil.file(base64Path), StandardCharsets.UTF_8);
|
||||
|
||||
// String bpmPath = "G:\\Temp\\img";
|
||||
String bpmPath = fileConfig.getPath();
|
||||
List<BufferedImage> bufferedImages = FileUtils.convertBase64PdfToBufferedImage(base64);
|
||||
List<File> files = FileUtils.saveBufferedImageToBmp(bufferedImages);
|
||||
|
||||
/*for (File file : files) {
|
||||
String filePath = file.getAbsolutePath();
|
||||
printerService.printBmpByPath(filePath);
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
void t4() throws IOException {
|
||||
String base64Path = "G:\\Temp\\text\\base64.txt";
|
||||
String base64 = FileUtil.readString(FileUtil.file(base64Path), StandardCharsets.UTF_8);
|
||||
|
||||
List<BufferedImage> bufferedImages = FileUtils.convertBase64PdfToBufferedImage(base64);
|
||||
System.out.println(bufferedImages);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dpkj.ems.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.dpkj.modules.express.utils.FileUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
class PrinterUtilTest2 {
|
||||
|
||||
@Test
|
||||
void t4() throws IOException {
|
||||
String base64Path = "G:\\Temp\\text\\base64.txt";
|
||||
String base64 = FileUtil.readString(FileUtil.file(base64Path), StandardCharsets.UTF_8);
|
||||
|
||||
List<BufferedImage> bufferedImages = FileUtils.convertBase64PdfToBufferedImage(base64);
|
||||
System.out.println(bufferedImages);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user