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 0000000..6798a3d Binary files /dev/null and b/src/main/resources/static/cert/wechatMa.jpg differ