Selaa lähdekoodia

add
输注列表新增输注标识

lifang 2 kuukautta sitten
vanhempi
commit
2a42304977

+ 6 - 1
nb-admin/src/main/resources/application.yml

@@ -98,4 +98,9 @@ management:
   endpoints:
     web:
       exposure:
-        include: heapdump,metrics
+        include: heapdump,metrics
+yixinqian:
+  baseUrl: http://192.168.188.169:8091
+  appId: 1753176443000
+  appKey: 82bdcf8ea9ae053e7b30a6a5633466d6
+  tokenExpire: 3600

+ 29 - 0
nb-admin/src/main/resources/db/migration/V6__init_20251011.sql

@@ -0,0 +1,29 @@
+CREATE TABLE IF NOT EXISTS bus_user_cert_info (
+    -- 用户基础信息
+    user_type VARCHAR(50) NULL COMMENT '用户类型(预留字段,当前为null)',
+    org_id VARCHAR(50) NULL COMMENT '机构ID(预留字段,当前为null)',
+    user_id VARCHAR(20) NOT NULL COMMENT '用户ID(唯一标识)',
+    user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',
+    user_idcard VARCHAR(20) NOT NULL COMMENT '用户身份证号',
+    user_phone VARCHAR(20) NOT NULL COMMENT '用户手机号',
+    user_email VARCHAR(100) NULL COMMENT '用户邮箱(预留字段,当前为null)',
+    real_name_status VARCHAR(10) NOT NULL COMMENT '实名认证状态(0:未认证/待认证,其他值需结合业务定义)',
+
+    -- 微信关联信息
+    wechat_open_id VARCHAR(100) NOT NULL COMMENT '微信OpenID',
+
+    -- 证书相关信息
+    cert_sn VARCHAR(100) NOT NULL COMMENT '证书序列号',
+    cert_dn VARCHAR(255) NOT NULL COMMENT '证书主体名称(Distinguished Name)',
+    cert_start_time DATETIME NOT NULL COMMENT '证书生效时间',
+    cert_end_time DATETIME NOT NULL COMMENT '证书过期时间',
+    cert_issuer VARCHAR(100) NOT NULL COMMENT '证书颁发机构',
+    signature_img TEXT NOT NULL COMMENT '签名图片(Base64编码字符串)',
+    dep_name VARCHAR(100) NOT NULL COMMENT '所属部门(如:临床医疗科室-麻醉科)',
+    is_auth_valid VARCHAR(10) NOT NULL COMMENT '认证有效性(0:无效/待验证,其他值需结合业务定义)',
+    sign_cert TEXT NOT NULL COMMENT '签名证书内容(PEM格式或相关证书字符串)',
+    image_update_time DATETIME NOT NULL COMMENT '签名图片更新时间',
+    tenant_id varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+    -- 主键约束(确保id唯一)
+    PRIMARY KEY (user_id) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户证书信息表(存储用户基础信息及关联证书数据)';

+ 1 - 0
nb-auth/src/main/java/com/nb/auth/sa/SaTokenConfig.java

@@ -70,6 +70,7 @@ public class SaTokenConfig {
         IGNORE_URL.add("/assist/phone/**");
         IGNORE_URL.add("/bus/device/info/hospitalCode");
         IGNORE_URL.add("/iot/**");
+        IGNORE_URL.add("/bus/yixinqian/get/**");
     }
 
 }

+ 2 - 2
nb-service/web-service/src/main/java/com/nb/web/service/bus/YiXinQian/UserInfoQueryParam.java

@@ -20,8 +20,8 @@ public class UserInfoQueryParam {
     @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
     private String userPhone;
 
-    /** 是否返回签名证书:0=不返回(默认),1=返回 */
-    private String isBackSignCert = "0";
+    /** 是否返回签名证书:0=不返回,1=返回(默认) */
+    private String isBackSignCert = "1";
 
     /**
      * 校验参数:userId、userIdcard、userPhone必须三选一

+ 1 - 1
nb-service/web-service/src/main/java/com/nb/web/service/bus/YiXinQian/YixinqianConfig.java

@@ -18,5 +18,5 @@ public class YixinqianConfig {
     /** 应用密钥 */
     private String appKey;
     /** AccessToken有效期(毫秒) */
-    private Long tokenExpire=100L;
+    private Long tokenExpire;
 }

+ 11 - 3
nb-service/web-service/src/main/java/com/nb/web/service/bus/YiXinQian/YixinqianService.java

@@ -8,24 +8,32 @@ import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.PostConstruct;
 import java.util.HashMap;
 import java.util.Map;
 
 /**
  * 医信签核心服务(实现4.1.1获取Token、4.2.3查询用户信息)
  */
-//@Service
+@Service
 @RequiredArgsConstructor // 构造器注入配置类
+@ImportAutoConfiguration(YixinqianConfig.class)
 public class YixinqianService {
     // 注入医信签配置
-    private final YixinqianConfig yixinqianConfig=new YixinqianConfig();
+    private final YixinqianConfig yixinqianConfig;
 
     // 本地缓存:存储AccessToken(key=固定值,value=accessToken),有效期=配置的tokenExpire
-    private final Cache<String, String> accessTokenCache = CacheUtil.newTimedCache(yixinqianConfig.getTokenExpire());
+    private Cache<String, String> accessTokenCache ;
     private static final String CACHE_KEY_ACCESS_TOKEN = "YIXINQIAN_ACCESS_TOKEN";
 
+    @PostConstruct
+    public void init(){
+        accessTokenCache=CacheUtil.newTimedCache(yixinqianConfig.getTokenExpire());
+    }
     /**
      * 1. 获取AccessToken(4.1.1接口)
      * 逻辑:优先从缓存取,缓存不存在/过期则调用接口获取,并更新缓存

+ 66 - 0
nb-service/web-service/src/main/java/com/nb/web/service/bus/controller/BusYixinQianController.java

@@ -0,0 +1,66 @@
+package com.nb.web.service.bus.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.nb.core.exception.CustomException;
+import com.nb.core.result.R;
+import com.nb.web.api.bean.FormulaDrugDetailDomain;
+import com.nb.web.api.bean.FormulaDrugDomain;
+import com.nb.web.service.bus.YiXinQian.UserInfoQueryParam;
+import com.nb.web.service.bus.YiXinQian.YixinqianService;
+import com.nb.web.service.bus.controller.vo.BusLiquidListVO;
+import com.nb.web.service.bus.excel.ExportResult;
+import com.nb.web.service.bus.excel.ExportType;
+import com.nb.web.service.bus.excel.LiquidExcelMergeWriteHandler;
+import com.nb.web.service.bus.service.LocalBusClinicService;
+import com.nb.web.service.bus.service.LocalBusUserCertInfoService;
+import com.nb.web.service.bus.service.dto.BusLiquidExcelVO;
+import com.nb.web.service.bus.service.dto.BusLiquidQuery;
+import com.nb.web.service.bus.service.dto.LiquidBatchHandleDTO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName BusHospitalController.java
+ * @Description
+ * @createTime 2022年03月19日 09:28:00
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/bus/yixinqian")
+@Slf4j
+@Api(tags = "电子签名",description = "")
+public class BusYixinQianController {
+    private final LocalBusUserCertInfoService localBusUserCertInfoService;
+
+    @GetMapping("/get/{userId}")
+    @ApiOperation(value = "根据工号查询签名信息",notes = "权限  无")
+    @SaIgnore
+    public R<String> page(@PathVariable("userId") String userId) {
+        UserInfoQueryParam userInfoQueryParam = new UserInfoQueryParam();
+        userInfoQueryParam.setUserId(userId);
+        return R.success(localBusUserCertInfoService.queryUserBase64Info(userInfoQueryParam));
+    }
+}

+ 145 - 0
nb-service/web-service/src/main/java/com/nb/web/service/bus/entity/BusUserCertInfo.java

@@ -0,0 +1,145 @@
+package com.nb.web.service.bus.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.nb.core.entity.TenantGenericEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+
+import java.util.Date;
+
+/**
+ * 用户证书信息表(存储用户基础信息及关联证书数据)
+ */
+@Data
+@TableName(value = "bus_user_cert_info", autoResultMap = true)
+@ApiModel(value = "用户证书信息", description = "存储用户基础信息及关联证书数据")
+@ToString
+@NoArgsConstructor
+public class BusUserCertInfo{
+    /**
+     * 用户ID(唯一标识)
+     */
+    @ApiModelProperty(value = "用户ID(唯一标识)")
+    @TableId
+    private String userId;
+
+    /**
+     * 用户类型(预留字段,当前为null)
+     */
+    @ApiModelProperty(value = "用户类型(预留字段,当前为null)")
+    private String userType;
+
+    /**
+     * 机构ID(预留字段,当前为null)
+     */
+    @ApiModelProperty(value = "机构ID(预留字段,当前为null)")
+    private String orgId;
+
+    /**
+     * 用户姓名
+     */
+    @ApiModelProperty(value = "用户姓名")
+    private String userName;
+
+    /**
+     * 用户身份证号
+     */
+    @ApiModelProperty(value = "用户身份证号")
+    private String userIdcard;
+
+    /**
+     * 用户手机号
+     */
+    @ApiModelProperty(value = "用户手机号")
+    private String userPhone;
+
+    /**
+     * 用户邮箱(预留字段,当前为null)
+     */
+    @ApiModelProperty(value = "用户邮箱(预留字段,当前为null)")
+    private String userEmail;
+
+    /**
+     * 实名认证状态(0:未认证/待认证,其他值需结合业务定义)
+     */
+    @ApiModelProperty(value = "实名认证状态(0:未认证/待认证,其他值需结合业务定义)")
+    private String realNameStatus;
+
+    /**
+     * 微信OpenID
+     */
+    @ApiModelProperty(value = "微信OpenID")
+    private String wechatOpenId;
+
+    /**
+     * 证书序列号
+     */
+    @ApiModelProperty(value = "证书序列号")
+    private String certSn;
+
+    /**
+     * 证书主体名称(Distinguished Name)
+     */
+    @ApiModelProperty(value = "证书主体名称(Distinguished Name)")
+    private String certDn;
+
+    /**
+     * 证书生效时间
+     */
+    @ApiModelProperty(value = "证书生效时间")
+    private Date certStartTime;
+
+    /**
+     * 证书过期时间
+     */
+    @ApiModelProperty(value = "证书过期时间")
+    private Date certEndTime;
+
+    /**
+     * 证书颁发机构
+     */
+    @ApiModelProperty(value = "证书颁发机构")
+    private String certIssuer;
+
+    /**
+     * 签名图片(Base64编码字符串)
+     */
+    @ApiModelProperty(value = "签名图片(Base64编码字符串)")
+    private String signatureImg;
+
+    /**
+     * 所属部门(如:临床医疗科室-麻醉科)
+     */
+    @ApiModelProperty(value = "所属部门(如:临床医疗科室-麻醉科)")
+    private String depName;
+
+    /**
+     * 认证有效性(0:无效/待验证,其他值需结合业务定义)
+     */
+    @ApiModelProperty(value = "认证有效性(0:无效/待验证,其他值需结合业务定义)")
+    private String isAuthValid;
+
+    /**
+     * 签名证书内容(PEM格式或相关证书字符串)
+     */
+    @ApiModelProperty(value = "签名证书内容(PEM格式或相关证书字符串)")
+    private String signCert;
+
+    /**
+     * 签名图片更新时间
+     */
+    @ApiModelProperty(value = "签名图片更新时间")
+    private Date imageUpdateTime;
+
+    @Getter
+    @TableField(value = "tenant_id",fill = FieldFill.INSERT)
+    @Setter
+    @JsonSerialize(using = ToStringSerializer.class)
+    private String tenantId;
+}

+ 22 - 0
nb-service/web-service/src/main/java/com/nb/web/service/bus/mapper/BusUserCertInfoMapper.java

@@ -0,0 +1,22 @@
+package com.nb.web.service.bus.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.nb.web.api.entity.AppArticleEntity;
+import com.nb.web.service.bus.entity.BusUserCertInfo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName AppArticleMapper.java
+ * @Description app宣教文章
+ * @createTime 2022年03月19日 09:15:00
+ */
+@Mapper
+public interface BusUserCertInfoMapper extends BaseMapper<BusUserCertInfo> {
+
+}

+ 150 - 0
nb-service/web-service/src/main/java/com/nb/web/service/bus/service/LocalBusUserCertInfoService.java

@@ -0,0 +1,150 @@
+package com.nb.web.service.bus.service;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.nb.common.crud.BaseService;
+import com.nb.web.service.bus.YiXinQian.UserInfoData;
+import com.nb.web.service.bus.YiXinQian.UserInfoQueryParam;
+import com.nb.web.service.bus.YiXinQian.YixinqianService;
+import com.nb.web.service.bus.entity.BusUserCertInfo;
+import com.nb.web.service.bus.mapper.BusUserCertInfoMapper;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName LocalAppArticleService.java
+ * @Description app宣教文章
+ * @createTime 2022年03月19日 09:27:00
+ */
+@Service
+@Slf4j
+@AllArgsConstructor
+public class LocalBusUserCertInfoService extends BaseService<BusUserCertInfoMapper, BusUserCertInfo,String> {
+    private final YixinqianService yixinqianService;
+    @Override
+    public void validateBeforeSave(BusUserCertInfo entity) {
+    }
+
+    @Override
+    public void validateBeforeUpdate(BusUserCertInfo entity) {
+    }
+
+    @Override
+    public void validateBeforeDelete(String id) {
+
+    }
+
+    public String queryUserBase64Info(UserInfoQueryParam query){
+        String userId = query.getUserId();
+        BusUserCertInfo busUserCertInfo = baseMapper.selectById(userId);
+
+        // 判断证书是否过期
+        if (ObjectUtil.isNull(busUserCertInfo) || isCertificateExpired(busUserCertInfo)) {
+            // 如果记录不存在或证书已过期,删除旧记录(如果存在)
+            if (!ObjectUtil.isNull(busUserCertInfo)) {
+                baseMapper.deleteById(userId);
+            }
+
+            // 从接口重新查询
+            UserInfoData userInfoData = yixinqianService.queryUserInfo(query);
+            busUserCertInfo = convertToBusUserCertInfo(userInfoData);
+            baseMapper.insert(busUserCertInfo);
+        }
+        return busUserCertInfo.getSignCert();
+    }
+
+    /**
+     * 判断证书是否过期
+     * @param certInfo 证书信息
+     * @return true表示已过期,false表示未过期
+     */
+    private boolean isCertificateExpired(BusUserCertInfo certInfo) {
+        if (certInfo.getCertEndTime() == null) {
+            return true; // 如果结束时间为空,认为已过期
+        }
+
+        // 比较证书结束时间和当前时间
+        return certInfo.getCertEndTime().before(new Date());
+    }
+
+    /**
+     * 将 UserInfoData 对象转换为 BusUserCertInfo 对象
+     * @param userInfoData 源数据对象
+     * @return 转换后的 BusUserCertInfo 对象
+     */
+    public static BusUserCertInfo convertToBusUserCertInfo(UserInfoData userInfoData) {
+        if (userInfoData == null) {
+            return null;
+        }
+
+        BusUserCertInfo certInfo = new BusUserCertInfo();
+
+        // 基础信息转换
+        certInfo.setUserType(userInfoData.getUserType());
+        certInfo.setOrgId(userInfoData.getOrgId());
+        certInfo.setUserId(userInfoData.getUserId());
+        certInfo.setUserName(userInfoData.getUserName());
+        certInfo.setUserIdcard(userInfoData.getUserIdcard());
+        certInfo.setUserPhone(userInfoData.getUserPhone());
+        certInfo.setUserEmail(userInfoData.getUserEmail());
+        certInfo.setRealNameStatus(userInfoData.getRealNameStatus());
+        certInfo.setWechatOpenId(userInfoData.getWechatOpenId());
+
+        // 证书信息转换
+        certInfo.setCertSn(userInfoData.getCertSN());
+        certInfo.setCertDn(userInfoData.getCertDN());
+        certInfo.setCertIssuer(userInfoData.getCertIssuer());
+        certInfo.setSignatureImg(userInfoData.getSignatureImg());
+        certInfo.setDepName(userInfoData.getDepName());
+        certInfo.setIsAuthValid(userInfoData.getIsAuthValid());
+        certInfo.setSignCert(userInfoData.getSignCert());
+
+        // 日期转换 (字符串转Date)
+        if (userInfoData.getCertStartTime() != null && !userInfoData.getCertStartTime().isEmpty()) {
+            // 注意:这里需要根据实际的日期格式进行解析
+            // 假设格式为 "yyyy-MM-dd HH:mm:ss"
+            try {
+                certInfo.setCertStartTime(parseDate(userInfoData.getCertStartTime()));
+            } catch (Exception e) {
+                // 处理日期解析异常
+                certInfo.setCertStartTime(null);
+            }
+        }
+
+        if (userInfoData.getCertEndTime() != null && !userInfoData.getCertEndTime().isEmpty()) {
+            try {
+                certInfo.setCertEndTime(parseDate(userInfoData.getCertEndTime()));
+            } catch (Exception e) {
+                certInfo.setCertEndTime(null);
+            }
+        }
+
+        if (userInfoData.getImageUpdateTime() != null && !userInfoData.getImageUpdateTime().isEmpty()) {
+            try {
+                certInfo.setImageUpdateTime(parseDate(userInfoData.getImageUpdateTime()));
+            } catch (Exception e) {
+                certInfo.setImageUpdateTime(null);
+            }
+        }
+
+        return certInfo;
+    }
+
+    /**
+     * 日期字符串解析方法(根据实际格式调整)
+     * @param dateStr 日期字符串
+     * @return Date 对象
+     * @throws ParseException 解析异常
+     */
+    private static Date parseDate(String dateStr) throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.parse(dateStr);
+    }
+
+}