From 0a2457f3b2ff1e07f7ffa60ba6ddd7d4298470e5 Mon Sep 17 00:00:00 2001 From: wucongxing8150 <815046773@qq.com> Date: Thu, 31 Jul 2025 18:28:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E8=A7=86=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../caseData/controller/UserController.java | 18 +- .../dao/CaseClinicalDoctorCertDao.java | 9 + .../example/caseData/extend/aliyun/Oss.java | 14 + .../extend/weChat/WxMaServiceUtils.java | 35 ++ .../model/CaseClinicalArticleModel.java | 6 + .../model/CaseClinicalDoctorCertModel.java | 58 ++++ .../model/CaseClinicalVideoModel.java | 6 + .../service/CaseClinicalVideoService.java | 306 ++++++++++++++++-- .../example/caseData/service/CertService.java | 15 +- .../example/caseData/service/UserService.java | 176 +++++++++- src/main/resources/static/cert/wechatMa.jpg | Bin 0 -> 10864 bytes 11 files changed, 608 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/example/caseData/dao/CaseClinicalDoctorCertDao.java create mode 100644 src/main/java/com/example/caseData/model/CaseClinicalDoctorCertModel.java create mode 100644 src/main/resources/static/cert/wechatMa.jpg diff --git a/src/main/java/com/example/caseData/controller/UserController.java b/src/main/java/com/example/caseData/controller/UserController.java index d788834..2228523 100644 --- a/src/main/java/com/example/caseData/controller/UserController.java +++ b/src/main/java/com/example/caseData/controller/UserController.java @@ -164,13 +164,19 @@ public class UserController extends BaseController { @GetMapping("/user/test") public Response getUser() { try { - String avt = "src/main/resources/static/cert/avt.png"; - String sealPath = "src/main/resources/static/cert/seal.png"; - String certificateNo = "GDXZALK" + String.valueOf(Year.now().getValue()) + "123456"; - String name = "吴从兴"; - String content = "您的案例《儿童肾上腺危象一例》经评议,被肝胆相照临床病例库收录,特发此"; +// byte[] qrCodeByte = new byte[0]; +// +// // 生成证书 +// String avt = "src/main/resources/static/cert/avt.png"; +// String sealPath = "src/main/resources/static/cert/seal.png"; +// String certificateNo = "GDXZALK" + String.valueOf(Year.now().getValue()) + "123456"; +// String name = "吴从兴"; +// String content = "您的案例《儿童肾上腺危象一例》经评议,被肝胆相照临床病例库收录,特发此"; +// +// certService.createCert(avt,sealPath,certificateNo,name,content,qrCodeByte); - certService.createCert(avt,sealPath,certificateNo,name,content); + // 生成用户分享二维码-文章/视频 +// userService.CreateUserCaseClinicalContentUnlimitedQrcode(String.valueOf(1),1); } catch (Exception e) { return Response.error(e.getMessage()); } diff --git a/src/main/java/com/example/caseData/dao/CaseClinicalDoctorCertDao.java b/src/main/java/com/example/caseData/dao/CaseClinicalDoctorCertDao.java new file mode 100644 index 0000000..433d7ff --- /dev/null +++ b/src/main/java/com/example/caseData/dao/CaseClinicalDoctorCertDao.java @@ -0,0 +1,9 @@ +package com.example.caseData.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.example.caseData.model.CaseClinicalDoctorCertModel; +import com.example.caseData.model.CaseClinicalDoctorModel; + +public interface CaseClinicalDoctorCertDao extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/example/caseData/extend/aliyun/Oss.java b/src/main/java/com/example/caseData/extend/aliyun/Oss.java index c7c3c0c..636cfc9 100644 --- a/src/main/java/com/example/caseData/extend/aliyun/Oss.java +++ b/src/main/java/com/example/caseData/extend/aliyun/Oss.java @@ -170,4 +170,18 @@ public class Oss { client.shutdown(); } } + + // 下载文件为 byte[] + public static byte[] getObjectToByte(String fileName) { + OSS client = createClient(); + try (OSSObject ossObject = client.getObject(ossConfig.getBucket(), fileName); + InputStream content = ossObject.getObjectContent()) { + return content.readAllBytes(); + } catch (Exception e) { + log.error("OSS 下载失败: fileName={}, error={}", fileName, e.getMessage(), e); + return null; + } finally { + client.shutdown(); + } + } } diff --git a/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java index 848fd8c..83130ea 100644 --- a/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java +++ b/src/main/java/com/example/caseData/extend/weChat/WxMaServiceUtils.java @@ -1,20 +1,29 @@ package com.example.caseData.extend.weChat; +import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import com.example.caseData.config.EnvConfig; +import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.springframework.stereotype.Component; +import java.util.Objects; + @Slf4j @Component @RequiredArgsConstructor public class WxMaServiceUtils { private final WxMaService wxMaService; + @Resource + private EnvConfig envConfig; + /** * 通过 code 换取 session 信息(openid/unionid) */ @@ -50,4 +59,30 @@ public class WxMaServiceUtils { throw new RuntimeException("获取 access_token 失败", e); } } + + /** + * 获取永久小程序码(base64 或保存成文件都可以) + * @param scene 场景值(最长32个可见字符,只能是数字、英文、下划线、减号) + * @param page 跳转页面路径(如 pages/index/index) + * @return 二进制图片数据(image/jpeg) + */ + public byte[] getUnlimitedQrcode(String scene, String page) { + boolean checkPath = false; // 不校验 page 是否存在 + String envVersion = "release"; // 可选:trial、develop、release + if (Objects.equals(envConfig.getActive(), "dev")){ + envVersion = "trial"; + } + + int width = 430; + boolean autoColor = true; + WxMaCodeLineColor lineColor = new WxMaCodeLineColor(); + boolean isHyaline = false; + + try { + WxMaQrcodeService qrcodeService = wxMaService.getQrcodeService(); + return qrcodeService.createWxaCodeUnlimitBytes(scene,page,checkPath,envVersion,width,autoColor,lineColor,isHyaline); + } catch (Exception e) { + throw new RuntimeException("获取小程序码失败", e); + } + } } diff --git a/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java b/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java index c69ffd0..afa32f5 100644 --- a/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java +++ b/src/main/java/com/example/caseData/model/CaseClinicalArticleModel.java @@ -73,6 +73,12 @@ public class CaseClinicalArticleModel { @TableField("is_link_url") private String isLinkUrl; + /** + * 分享二维码地址 + */ + @TableField("share_qrcode") + private String shareQrcode; + /** * 内容 */ diff --git a/src/main/java/com/example/caseData/model/CaseClinicalDoctorCertModel.java b/src/main/java/com/example/caseData/model/CaseClinicalDoctorCertModel.java new file mode 100644 index 0000000..2ee0b24 --- /dev/null +++ b/src/main/java/com/example/caseData/model/CaseClinicalDoctorCertModel.java @@ -0,0 +1,58 @@ +package com.example.caseData.model; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 医生证书信息实体类 + */ +@Data +@TableName("`case_clinical_doctor_cert`") +public class CaseClinicalDoctorCertModel { + /** + * 主键id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long certId; + + /** + * 医生id + */ + @TableField("doctor_id") + private Long doctorId; + + /** + * 关联的视频/文章id + */ + @TableField("id") + private Long id; + + /** + * 类型(1:文章 2:视频) + */ + @TableField("type") + private Integer type; + + /** + * 证书图片(存储路径或URL) + */ + @TableField("cert_image") + private String certImage; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonProperty("created_at") + private LocalDateTime createdAt; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonProperty("updated_at") + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java b/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java index 8d2d67c..134fb2d 100644 --- a/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java +++ b/src/main/java/com/example/caseData/model/CaseClinicalVideoModel.java @@ -82,6 +82,12 @@ public class CaseClinicalVideoModel { @TableField("is_link_url") private String isLinkUrl; + /** + * 分享二维码地址 + */ + @TableField("share_qrcode") + private String shareQrcode; + /** * 创建时间 */ diff --git a/src/main/java/com/example/caseData/service/CaseClinicalVideoService.java b/src/main/java/com/example/caseData/service/CaseClinicalVideoService.java index 2042ce8..16ab361 100644 --- a/src/main/java/com/example/caseData/service/CaseClinicalVideoService.java +++ b/src/main/java/com/example/caseData/service/CaseClinicalVideoService.java @@ -1,8 +1,10 @@ package com.example.caseData.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.example.caseData.config.EnvConfig; import com.example.caseData.dao.*; import com.example.caseData.exception.BusinessException; +import com.example.caseData.extend.aliyun.Oss; import com.example.caseData.extend.app.Base; import com.example.caseData.extend.app.UserInfo.GetUserInfoResponse; import com.example.caseData.extend.app.UserInfo.UserInfo; @@ -20,6 +22,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validation; import jakarta.validation.Validator; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -34,6 +37,7 @@ import java.util.*; //import static com.baomidou.mybatisplus.extension.toolkit.Db.removeById; //import static com.baomidou.mybatisplus.extension.toolkit.Db.save; +@Slf4j @Service public class CaseClinicalVideoService { @Resource @@ -51,6 +55,9 @@ public class CaseClinicalVideoService { @Resource private UserDao userDao; + @Resource + private EnvConfig envConfig; + @Resource private BasicHospitalDao basicHospitalDao; @@ -90,6 +97,12 @@ public class CaseClinicalVideoService { @Resource private CaseClinicalService caseClinicalService; + @Resource + private CertService certService; + + @Resource + private CaseClinicalDoctorCertDao caseClinicalDoctorCertDao; + /** * 新增收藏-临床病例库-视频 * @param videoId 视频id @@ -545,6 +558,9 @@ public class CaseClinicalVideoService { ObjectMapper objectMapper = new ObjectMapper(); addClinicalVideoApp r = objectMapper.readValue(request.getInputStream(), addClinicalVideoApp.class); + System.out.println(r); + log.info(r.toString()); + // 2. 自动校验(@Validated) Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set> violations = validator.validate(r); @@ -568,9 +584,12 @@ public class CaseClinicalVideoService { } } - System.out.println(r); + // 二维码-文章/视频 + byte[] qrCodeByte = new byte[0]; + // 新增 if (Objects.equals(r.getAction(), "add")){ + if (caseClinicalVideo != null){ if (caseClinicalVideo.getDeleteStatus() == 0){ // 已存在该视频 @@ -598,10 +617,19 @@ public class CaseClinicalVideoService { caseClinicalVideo.setPushDate(pushDate); caseClinicalVideo.setIsLink(r.getIsLink()); caseClinicalVideo.setIsLinkUrl(r.getIsLinkUrl()); + + int res = caseClinicalVideoDao.insert(caseClinicalVideo); if (res <= 0){ throw new BusinessException("-1", "内部错误,添加视频失败"); } + + try { + // 生成用户分享二维码-文章/视频 + qrCodeByte = userService.CreateUserCaseClinicalUnlimitedQrcode(String.valueOf(caseClinicalVideo.getVideoId()),2); + } catch (Exception e) { + // 不处理 + } } // 新增统计 @@ -609,7 +637,7 @@ public class CaseClinicalVideoService { // 作者处理 if (r.getAuthor() != null) { - AddClinicalVideoAppAuthor(caseClinicalVideo,r); + AddClinicalVideoAppAuthor(caseClinicalVideo,r,qrCodeByte); } // 标签处理 @@ -641,7 +669,7 @@ public class CaseClinicalVideoService { // 作者处理 if (r.getAuthor() != null) { - AddClinicalVideoAppAuthor(caseClinicalVideo,r); + AddClinicalVideoAppAuthor(caseClinicalVideo,r,qrCodeByte); } // 标签处理 @@ -671,12 +699,112 @@ public class CaseClinicalVideoService { * @param r */ @Transactional - public void AddClinicalVideoAppAuthor(CaseClinicalVideoModel caseClinicalVideo,addClinicalVideoApp r){ + public void AddClinicalVideoAppAuthor(CaseClinicalVideoModel caseClinicalVideo,addClinicalVideoApp r,byte[] qrCodeByte){ + // 需新增的 + List addList = new ArrayList<>(); + + // 需删除的 + List deleteList = new ArrayList<>(); + + // 已存在的 + List existsList = new ArrayList<>(); + // 获取全部作者 LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); authorQueryWrapper.eq(CaseClinicalVideoAuthorModel::getVideoId, caseClinicalVideo.getVideoId()); List caseClinicalVideoAuthors = caseClinicalVideoAuthorDao.selectList(authorQueryWrapper); - for (CaseClinicalVideoAuthorModel author : caseClinicalVideoAuthors){ + for (CaseClinicalVideoAuthorModel b : caseClinicalVideoAuthors){ + // 获取医生数据 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(b.getDoctorId()); + if (caseClinicalDoctor == null){ + throw new BusinessException("-1", "医生数据错误"); + } + + // 获取医生医院数据 + BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); + if (basicHospital == null) { + throw new BusinessException("-1", "医生医院数据错误"); + } + + caseClinicalDoctor.setBasicHospital(basicHospital); + b.setCaseClinicalDoctor(caseClinicalDoctor); + } + + // 处理新增的情况 + for (addClinicalVideoApp.Author a : r.getAuthor()){ + // 默认本条为新增 + boolean exists = true; + for (CaseClinicalVideoAuthorModel b : caseClinicalVideoAuthors){ + // 检测医生唯一标识 + if (Objects.equals(a.getDoctorIden(), b.getCaseClinicalDoctor().getDoctorIden())){ + exists = false; + break; // 已存在,跳出内层循环 + } + + // 检测医生姓名+医院唯一标识 + String akey = a.getDoctorName() + a.getHospitalIden(); + String bkey = b.getCaseClinicalDoctor().getDoctorName() + b.getCaseClinicalDoctor().getBasicHospital().getHospitalIden(); + if (akey.equals(bkey)){ + exists = false; + break; // 已存在,跳出内层循环 + } + } + + if (exists) { + addList.add(a); // 不存在于旧数据中,加入新增列表 + } + } + + // 处理删除的情况 + for (CaseClinicalVideoAuthorModel b : caseClinicalVideoAuthors){ + // 默认本条为删除 + boolean exists = true; + for (addClinicalVideoApp.Author a : r.getAuthor()){ + if (Objects.equals(a.getDoctorIden(), b.getCaseClinicalDoctor().getDoctorIden())){ + exists = false; + break; // 已存在,跳出内层循环 + } + + // 检测医生姓名+医院唯一标识 + String akey = a.getDoctorName() + a.getHospitalIden(); + String bkey = b.getCaseClinicalDoctor().getDoctorName() + b.getCaseClinicalDoctor().getBasicHospital().getHospitalIden(); + if (akey.equals(bkey)){ + exists = false; + break; // 已存在,跳出内层循环 + } + } + + if (exists) { + deleteList.add(b); // 加入删除列表 + } + } + + // 处理已存在的情况 + for (CaseClinicalVideoAuthorModel b : caseClinicalVideoAuthors){ + // 默认本条不添加 + boolean exists = false; + for (addClinicalVideoApp.Author a : r.getAuthor()){ + if (Objects.equals(a.getDoctorIden(), b.getCaseClinicalDoctor().getDoctorIden())){ + exists = true; + break; // 已存在,跳出内层循环 + } + + // 检测医生姓名+医院唯一标识 + String akey = a.getDoctorName() + a.getHospitalIden(); + String bkey = b.getCaseClinicalDoctor().getDoctorName() + b.getCaseClinicalDoctor().getBasicHospital().getHospitalIden(); + if (akey.equals(bkey)){ + exists = true; + break; // 已存在,跳出内层循环 + } + } + + if (exists) { + existsList.add(b); // 加入已存在列表 + } + } + + // 删除 + for (CaseClinicalVideoAuthorModel author : deleteList){ // 获取医生数据 LambdaQueryWrapper doctorQueryWrapper = new LambdaQueryWrapper<>(); doctorQueryWrapper.eq(CaseClinicalDoctorModel::getDoctorId, author.getDoctorId()); @@ -699,26 +827,20 @@ public class CaseClinicalVideoService { // 删除该作者 caseClinicalVideoAuthorDao.deleteById(author.getAuthorId()); + + // 删除该作者证书 + LambdaQueryWrapper certWrapper = new LambdaQueryWrapper<>(); + certWrapper.eq(CaseClinicalDoctorCertModel::getDoctorId, caseClinicalDoctor.getDoctorId()); + certWrapper.eq(CaseClinicalDoctorCertModel::getId, caseClinicalVideo.getVideoId()); + certWrapper.eq(CaseClinicalDoctorCertModel::getType, 2); + caseClinicalDoctorCertDao.delete(certWrapper); } // 新增新的作者 - - // 获取app用户数据 - for (addClinicalVideoApp.Author author : r.getAuthor()){ - CaseClinicalDoctorModel caseClinicalDoctor = new CaseClinicalDoctorModel(); - - if (author.getDoctorIden() != null && !author.getDoctorIden().isEmpty()) { - GetUserInfoResponse result = userInfo.getUserInfoByUuid(author.getDoctorIden()); - caseClinicalDoctor = userService.GetCaseClinicalDoctor(result); - }else{ - GetUserInfoResponse result = new GetUserInfoResponse(); - GetUserInfoResponse.ResponsData resultData = new GetUserInfoResponse.ResponsData(); - resultData.setOfficeName(author.getDoctorName()); - resultData.setRealname(author.getDoctorName()); - resultData.setHospitalUuid(author.getHospitalIden()); - result.setData(resultData); - caseClinicalDoctor = userService.GetCaseClinicalDoctor(result); - } + for (addClinicalVideoApp.Author author : addList){ + // 获取医生数据 + GetUserInfoResponse result = userInfo.getUserInfoByUuid(author.getDoctorIden()); + CaseClinicalDoctorModel caseClinicalDoctor = userService.GetCaseClinicalDoctor(result); CaseClinicalVideoAuthorModel caseClinicalVideoAuthor = new CaseClinicalVideoAuthorModel(); caseClinicalVideoAuthor.setVideoId(caseClinicalVideo.getVideoId()); @@ -732,9 +854,149 @@ public class CaseClinicalVideoService { // 新增医院统计 caseClinicalService.IncStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),2,lastPushDate); + + // 生成用户证书-文章/视频 + if(qrCodeByte == null){ + // 下载二维码图片 + if (caseClinicalVideo.getShareQrcode() == null){ + throw new BusinessException("-1", "无法完成此操作"); + } + + qrCodeByte = Oss.getObjectToByte(caseClinicalVideo.getShareQrcode().replaceFirst("^/+", "")); + if (qrCodeByte == null) { + throw new BusinessException("-1", "无法完成此操作"); + } + } + + // 下载头像 + byte[] avatarByte = Oss.getObjectToByte(caseClinicalDoctor.getAvatar().replaceFirst("^/+", "")); + if (avatarByte == null) { + throw new BusinessException("-1", "无法完成此操作"); + } + + + userService.CreateUserCert( + String.valueOf(caseClinicalVideo.getVideoId()), + 2, + String.valueOf(caseClinicalDoctor.getDoctorId()), + qrCodeByte, + avatarByte + ); + } + + // 已存在的 + for (CaseClinicalVideoAuthorModel b : existsList){ + // 如果现有作者的唯一标识为空 + if (b.getCaseClinicalDoctor().getDoctorIden() == null || b.getCaseClinicalDoctor().getDoctorIden().isEmpty()) { + for (addClinicalVideoApp.Author a : r.getAuthor()){ + // 检测医生姓名+医院唯一标识 + String akey = a.getDoctorName() + a.getHospitalIden(); + String bkey = b.getCaseClinicalDoctor().getDoctorName() + b.getCaseClinicalDoctor().getBasicHospital().getHospitalIden(); + if (akey.equals(bkey)){ + // 相等 + b.getCaseClinicalDoctor().setDoctorIden(a.getDoctorIden()); + caseClinicalDoctorDao.updateById(b.getCaseClinicalDoctor()); + } + } + } } } +// /** +// * 临床病例库-视频-同步app视频-作者处理 +// * @param caseClinicalVideo +// * @param r +// */ +// @Transactional +// public void AddClinicalVideoAppAuthor(CaseClinicalVideoModel caseClinicalVideo,addClinicalVideoApp r,byte[] qrCodeByte){ +// // 获取全部作者 +// LambdaQueryWrapper authorQueryWrapper = new LambdaQueryWrapper<>(); +// authorQueryWrapper.eq(CaseClinicalVideoAuthorModel::getVideoId, caseClinicalVideo.getVideoId()); +// List caseClinicalVideoAuthors = caseClinicalVideoAuthorDao.selectList(authorQueryWrapper); +// for (CaseClinicalVideoAuthorModel author : caseClinicalVideoAuthors){ +// // 获取医生数据 +// LambdaQueryWrapper doctorQueryWrapper = new LambdaQueryWrapper<>(); +// doctorQueryWrapper.eq(CaseClinicalDoctorModel::getDoctorId, author.getDoctorId()); +// CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectOne(doctorQueryWrapper); +// if (caseClinicalDoctor == null) { +// throw new BusinessException("-1", "无法完成此操作"); +// } +// +// // 获取医院数据 +// BasicHospitalModel basicHospital = basicHospitalDao.selectById(caseClinicalDoctor.getHospitalId()); +// if (basicHospital == null) { +// throw new BusinessException("-1", "无法完成此操作"); +// } +// +// // 减少作者统计 +// caseClinicalService.DecStatsCaseClinicalDoctor(String.valueOf(caseClinicalDoctor.getDoctorId()),2); +// +// // 减少医院统计 +// caseClinicalService.DecStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),2); +// +// // 删除该作者 +// caseClinicalVideoAuthorDao.deleteById(author.getAuthorId()); +// +// // 删除该作者证书 +// LambdaQueryWrapper certWrapper = new LambdaQueryWrapper<>(); +// certWrapper.eq(CaseClinicalDoctorCertModel::getDoctorId, caseClinicalDoctor.getDoctorId()); +// certWrapper.eq(CaseClinicalDoctorCertModel::getId, caseClinicalVideo.getVideoId()); +// certWrapper.eq(CaseClinicalDoctorCertModel::getType, 2); +// caseClinicalDoctorCertDao.delete(certWrapper); +// } +// +// // 新增新的作者 +// for (addClinicalVideoApp.Author author : r.getAuthor()){ +// CaseClinicalDoctorModel caseClinicalDoctor = new CaseClinicalDoctorModel(); +// +// if (author.getDoctorIden() != null && !author.getDoctorIden().isEmpty()) { +// GetUserInfoResponse result = userInfo.getUserInfoByUuid(author.getDoctorIden()); +// caseClinicalDoctor = userService.GetCaseClinicalDoctor(result); +// }else{ +// GetUserInfoResponse result = new GetUserInfoResponse(); +// GetUserInfoResponse.ResponsData resultData = new GetUserInfoResponse.ResponsData(); +// resultData.setOfficeName(author.getDoctorName()); +// resultData.setRealname(author.getDoctorName()); +// resultData.setHospitalUuid(author.getHospitalIden()); +// result.setData(resultData); +// caseClinicalDoctor = userService.GetCaseClinicalDoctor(result); +// } +// +// CaseClinicalVideoAuthorModel caseClinicalVideoAuthor = new CaseClinicalVideoAuthorModel(); +// caseClinicalVideoAuthor.setVideoId(caseClinicalVideo.getVideoId()); +// caseClinicalVideoAuthor.setDoctorId(String.valueOf(caseClinicalDoctor.getDoctorId())); +// caseClinicalVideoAuthorDao.insert(caseClinicalVideoAuthor); +// +// LocalDateTime lastPushDate = caseClinicalVideoDao.selectLastVideoPushDateByDoctorId(caseClinicalDoctor.getDoctorId()); +// +// // 新增作者统计 +// caseClinicalService.IncStatsCaseClinicalDoctor(String.valueOf(caseClinicalDoctor.getDoctorId()),2,lastPushDate); +// +// // 新增医院统计 +// caseClinicalService.IncStatsCaseClinicalHospital(String.valueOf(caseClinicalDoctor.getHospitalId()),2,lastPushDate); +// +// // 生成用户证书-文章/视频 +// if(qrCodeByte == null){ +// // 下载二维码图片 +// if (Objects.equals(caseClinicalVideo.getShareQrcode(), "")){ +// throw new BusinessException("-1", "无法完成此操作"); +// } +// +// qrCodeByte = Oss.getObjectToByte(fileName); +// if (qrCodeByte == null) { +// throw new BusinessException("-1", "无法完成此操作"); +// } +// } +// +// userService.CreateUserCert( +// String.valueOf(caseClinicalVideo.getVideoId()), +// 2, +// String.valueOf(caseClinicalDoctor.getDoctorId()), +// qrCodeByte +// ); +// } +// } + /** * 临床病例库-视频-同步app视频-标签处理 * @param caseClinicalVideo diff --git a/src/main/java/com/example/caseData/service/CertService.java b/src/main/java/com/example/caseData/service/CertService.java index e4d2b5b..8c53ae4 100644 --- a/src/main/java/com/example/caseData/service/CertService.java +++ b/src/main/java/com/example/caseData/service/CertService.java @@ -11,6 +11,7 @@ import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; @@ -24,11 +25,13 @@ public class CertService { private EnvConfig envConfig; // 生成证书 - public String createCert(String avatarPath, + public String createCert( byte[] avatarPath, String sealPath, String certificateNo, String name, - String content){ + String content, + byte[] qrCodeByte + ){ try { // 加载背景模板图片 BufferedImage background = ImageIO.read(new File("src/main/resources/static/cert/template.png")); @@ -46,7 +49,7 @@ public class CertService { g2d.drawString(certificateNo, 285, 570); // 2. 处理并添加头像 - BufferedImage avatar = ImageIO.read(new File(avatarPath)); + BufferedImage avatar = ImageIO.read(new ByteArrayInputStream(avatarPath)); int size = 116; // 目标大小 BufferedImage circleAvatar = createCircularImage(avatar, size); g2d.drawImage(circleAvatar, 465, 620, null); @@ -83,6 +86,11 @@ public class CertService { seal = resize(seal, 264, 264); // 调整印章大小 g2d.drawImage(seal, 645, 1150, null); + // 6. 添加小程序二维码 + BufferedImage wechatMa = ImageIO.read(new ByteArrayInputStream(qrCodeByte)); + wechatMa = resize(wechatMa, 264, 264); // 调整印章大小 + g2d.drawImage(wechatMa, 645, 1150, null); + // 释放资源 g2d.dispose(); @@ -158,4 +166,5 @@ public class CertService { } } + } diff --git a/src/main/java/com/example/caseData/service/UserService.java b/src/main/java/com/example/caseData/service/UserService.java index 49775ee..d974aa7 100644 --- a/src/main/java/com/example/caseData/service/UserService.java +++ b/src/main/java/com/example/caseData/service/UserService.java @@ -4,10 +4,7 @@ import cn.hutool.crypto.SecureUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.example.caseData.config.EnvConfig; -import com.example.caseData.dao.BasicHospitalDao; -import com.example.caseData.dao.CaseClinicalDoctorDao; -import com.example.caseData.dao.CaseClinicalRecordScoreDao; -import com.example.caseData.dao.UserDao; +import com.example.caseData.dao.*; import com.example.caseData.dto.publicDto.LoginDto; import com.example.caseData.exception.BusinessException; import com.example.caseData.extend.aliyun.Oss; @@ -16,6 +13,7 @@ import com.example.caseData.extend.app.Hospital.Hospital; import com.example.caseData.extend.app.Score.Score; import com.example.caseData.extend.app.UserInfo.GetUserInfoResponse; import com.example.caseData.extend.app.UserInfo.UserInfo; +import com.example.caseData.extend.weChat.WxMaServiceUtils; import com.example.caseData.model.*; import com.example.caseData.request.UserRequest.ReportUserScoreRequest; import com.example.caseData.utils.JwtUtil; @@ -31,6 +29,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.time.LocalDateTime; +import java.time.Year; import java.time.format.DateTimeFormatter; import java.util.Random; @@ -61,6 +60,15 @@ public class UserService { @Resource private CaseClinicalDoctorDao caseClinicalDoctorDao; + @Resource + private CaseClinicalDoctorCertDao caseClinicalDoctorCertDao; + + @Resource + private CaseClinicalArticleDao caseClinicalArticleDao; + + @Resource + private CaseClinicalVideoDao caseClinicalVideoDao; + @Resource private CaseClinicalRecordScoreDao caseClinicalRecordScoreDao; @@ -76,6 +84,15 @@ public class UserService { @Resource private EnvConfig envConfig; + @Resource + private WxMaServiceUtils wxMaServiceUtils; + + @Resource + private CertService certService; + + @Resource + private StatsCaseClinicalDao statsCaseClinicalDao; + /** * 用户登陆-手机号 * @return UserModel @@ -457,4 +474,155 @@ public class UserService { } } } + + /** + * 生成用户分享二维码-文章/视频 + * @param id 文章/视频id + * @param type 类型 1:文章 2:视频 + */ + @Transactional + public byte[] CreateUserCaseClinicalUnlimitedQrcode(String id,Integer type) throws BusinessException{ + String scene = ""; + String page = "pages/detail/detail"; + + if (type == 1){ + scene = "?id=" + id + "&type=article"; + }else if (type == 2){ + scene = "?id=" + id + "&type=video"; + }else{ + throw new BusinessException("生成二维码类型错误"); + } + + try { + // 生成二维码 + byte[] fileByte = wxMaServiceUtils.getUnlimitedQrcode(scene,page); + + // 上传oss + String fileName = ""; + String no = ""; + + if (type == 1){ + no = "a" + id; + }else { + no = "v" + id; + } + + if (Objects.equals(envConfig.getActive(), "dev")){ + fileName = "dev/static/images/" + no + ".png"; + }else{ + fileName = "prod/static/images/" + no + ".png"; + } + + boolean res = Oss.putObject(fileName, fileByte); + if (!res) { + throw new BusinessException("生成失败"); + } + + if (type == 1){ + // 修改文章证书 + CaseClinicalArticleModel caseClinicalArticle = caseClinicalArticleDao.selectById(Long.valueOf(id)); + if (caseClinicalArticle == null){ + throw new BusinessException("生成失败"); + } + + caseClinicalArticle.setShareQrcode("/" + fileName); + caseClinicalArticleDao.updateById(caseClinicalArticle); + }else{ + // 修改视频证书 + CaseClinicalVideoModel caseClinicalVideo = caseClinicalVideoDao.selectById(Long.valueOf(id)); + if (caseClinicalVideo == null){ + throw new BusinessException("生成失败"); + } + + caseClinicalVideo.setShareQrcode("/" + fileName); + caseClinicalVideoDao.updateById(caseClinicalVideo); + } + + return fileByte; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + /** + * 生成用户证书-文章/视频 + * @param id 文章/视频id + * @param type 类型 1:文章 2:视频 + */ + @Transactional + public boolean CreateUserCert(String id,Integer type,String doctorId, byte[] qrCodeByte, byte[] avatarByte) throws BusinessException{ + try { + String title = ""; // 标题 + + if (type == 1){ + // 获取文章数据 + CaseClinicalArticleModel caseClinicalArticle = caseClinicalArticleDao.selectById(Long.valueOf(id)); + if (caseClinicalArticle == null){ + throw new BusinessException("生成证书错误"); + } + + title = caseClinicalArticle.getArticleTitle(); + + }else if (type == 2){ + CaseClinicalVideoModel caseClinicalVideo = caseClinicalVideoDao.selectById(Long.valueOf(id)); + + if (caseClinicalVideo == null){ + throw new BusinessException("生成证书错误"); + } + + title = caseClinicalVideo.getVideoTitle(); + + }else{ + throw new BusinessException("生成证书错误"); + } + + // 获取医生数据 + CaseClinicalDoctorModel caseClinicalDoctor = caseClinicalDoctorDao.selectById(doctorId); + if (caseClinicalDoctor == null){ + throw new BusinessException("生成证书错误"); + } + + // 获取证书文件 + LambdaQueryWrapper certWrapper = new LambdaQueryWrapper<>(); + certWrapper.eq(CaseClinicalDoctorCertModel::getDoctorId, doctorId); + certWrapper.eq(CaseClinicalDoctorCertModel::getId, id); + certWrapper.eq(CaseClinicalDoctorCertModel::getType, type); + CaseClinicalDoctorCertModel caseClinicalDoctorCert = caseClinicalDoctorCertDao.selectOne(certWrapper); + if (caseClinicalDoctorCert != null){ + return true; + } + + // 获取统计数据 + StatsCaseClinicalModel statsCaseClinical = statsCaseClinicalDao.selectById(1); + if (statsCaseClinical == null){ + throw new BusinessException("生成证书错误"); + } + + // 生成证书 + String certificateNo = "GDXZALK" + + String.valueOf(Year.now().getValue()) + + String.format("%06d", (statsCaseClinical.getArticleNum() + statsCaseClinical.getVideoNum())); + + String ossPath = certService.createCert( + avatarByte, + "src/main/resources/static/cert/seal.png", + certificateNo, + caseClinicalDoctor.getDoctorName(), + "您的案例《" + title + "》经评议,被肝胆相照临床病例库收录,特发此证", + qrCodeByte + ); + + // 新增证书文件 + caseClinicalDoctorCert = new CaseClinicalDoctorCertModel(); + caseClinicalDoctorCert.setDoctorId(Long.valueOf(doctorId)); + caseClinicalDoctorCert.setId(Long.valueOf(id)); + caseClinicalDoctorCert.setType(type); + caseClinicalDoctorCert.setCertImage(ossPath); + caseClinicalDoctorCertDao.insert(caseClinicalDoctorCert); + + return true; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } } \ No newline at end of file diff --git a/src/main/resources/static/cert/wechatMa.jpg b/src/main/resources/static/cert/wechatMa.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6798a3df3dc79e77f8e2282d05513de852a3bb8c GIT binary patch literal 10864 zcmcIo2Ut{Bw>@|66zWh#LD4~^2!ep3hz+C*3L@BIR2-^QhhmK_1|u4~SQBgP(L`g7 z6*bn_d;3vi#F7MK?8bTflv@VP`;+f|Z*ZJ*&)H}1wbx$z+&g2uVys5CU8Cco5yv4E z3xCLX8zn>y&&fonTQ}r`5HdsDq#UG#5ttwscq7CwAnZ7;Y^y*eFjRz4VKKL7E{E@O;$>^8(j zL<~$yPK=IAh#~;(7N->zk?>?-g z2#-g@*fBRHIReHrz{ZO0g=y3zCZiz3kfYbd7}7@QV$$;S({w@pLAoSEVP;O=2T*+)9~shN{WTa6p(3*AXyV3Ts&~mPZK!B?X}*f|g>y>p02-7Nrn& zq?1^5AI_6vivY|8Xe6v*Y$SJOePw{M6};Ok6Od5H-rK(aj1#G5OO_b|~C@K9t z-9RkWIn^1}E!732gU_E;7gaSdx~{qbe^*63QVp=Ca$ufnf~rl=@x&6VFdUf4Bdhtq z2Ch^FsZ$K>O9Ot3fxS}D9j>(>C_r8dQ-xq}@^!2T8a)gA(kn^vdNP9*g5zVgywA_S z=@40eWERYDDJmMUYV@0oB3eIOyNpTQpLa(SS_FI>@Hk*)z=nXQ0k;SXq<#UH1AYy- z7_bah9`UpJt^6K-C%=n7iF9zai$B2cB%=-dZut97+-KSmlw;G5!1~m)4#3%$Fb&Fk zMSd#adSE}e8rWXoa0u&cxmGdbat&cF{~01V*QO^3tv=~et-Cf*tI_&sgSFvWPU{AL zLE11Fxoewh6SVbVHCF4Tjnp<2`4B3W2QyefSb35b>ABYzPzp-J`DH`(4dj$dWBJz2 zQD>4RJ^^#&ea2ZsC(}su3=v`qypjr=oS>-?DF+P$90uSOpAH3Z_UKG(@Y#(|El@o7 z5vkz^G^!3&d#R(;Ua*&*RyuX0I#wNxbm~AnuWqUC3gdRzO4(Q$sEmVCFA?dK;mTlT z7#ri0umk+zbC7c6r|b-?os^Nv5PU|;vjrrSTYOr6I8%8S!m~z6#&CFEK`5fIXoMjr zE4xG&4o^lIy0`+pe+ykuKp@-^@pBfoLFj1@^8Ca(oz#~a%IF+<9%r)UWIA1P^3*kC(QCtF-%=P64aamje zSIUj%KINuxv$%!aGHxyR9k-J^z#Zexa#y+A+ym|p?zMtfSScJ8t_n{@OGStxToJEG zQGBe(QVdm$R7_M%Q_NQ^S8PyhQyfs7P+U}0D;_DH@rbwNop?9ij}PG^_(Z-RpUE5e zF?h5>jB=`Sp>mCKoAQwIyz;iP zR{2h4t!kw5RfVeJRDD!gs$r^fRi$c`YOCrnoZ9zP&(&(R6X>EX=%ufEh$tnt-!)Ff)sG$opH%>vB^%|6XJ%{|RaGfT53WW!{Vu>rDapgc9uOXb1cVM&bR#5@~Gu)%U4$RRz6k{R{gC?t)^M6w%TuX)#|CW zwY8^pm~}tv66k2H1?WskGT* zbK2&yt+}nIZG>%_?HJodwmWSv+di{%unV+Hw9B`fYPZhrm|cy%#@^FD%0AtGqWuc{ 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 Z$g>?>{=