From e4ebda0877b7c38d7bb0ccb16ef4bd8f2e227644 Mon Sep 17 00:00:00 2001 From: maotiantian Date: Fri, 27 Mar 2026 17:51:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BD=E5=8C=BB=E7=9B=B8=E5=85=B3=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SysMedicineRecommendationController.java | 16 +- .../system/SysVetAuditController.java | 892 ++++++++++++- .../vet/VetNotificationController.java | 2 +- .../vet/VetQualificationController.java | 903 +++++-------- .../vet/VetTrainingVideoController.java | 4 +- .../vet/VetUnifiedInfoController.java | 219 ++- .../MuhuConsultationFormsServiceImpl.java | 275 +++- .../SysMedicineRecommendationMapper.java | 34 +- .../SysMedicineRecommendationServiceImpl.java | 39 +- .../com/chenhai/vet/domain/VetComments.java | 93 +- .../chenhai/vet/domain/VetNotification.java | 109 +- .../chenhai/vet/domain/VetPersonalInfo.java | 51 +- .../chenhai/vet/domain/VetQualification.java | 276 ++-- .../vet/domain/dto/VetUnifiedInfoDTO.java | 8 + .../service/impl/VetCommentsServiceImpl.java | 127 +- .../service/impl/VetKnowledgeServiceImpl.java | 224 +++- .../impl/VetNotificationServiceImpl.java | 109 +- .../impl/VetPersonalInfoServiceImpl.java | 111 +- .../impl/VetQualificationServiceImpl.java | 1178 +++++------------ .../impl/VetTrainingVideoServiceImpl.java | 165 ++- .../impl/VetUnifiedInfoServiceImpl.java | 453 ++++++- .../SysMedicineRecommendationMapper.xml | 144 +- .../mapper/vet/VetCommentsMapper.xml | 46 +- .../mapper/vet/VetKnowledgeMapper.xml | 52 +- .../mapper/vet/VetNotificationMapper.xml | 11 +- .../mapper/vet/VetPersonalInfoMapper.xml | 24 +- .../mapper/vet/VetQualificationMapper.xml | 2 +- .../mapper/vet/VetTrainingVideoMapper.xml | 14 +- .../src/views/system/recommendation/index.vue | 346 +---- 29 files changed, 3577 insertions(+), 2350 deletions(-) diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysMedicineRecommendationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysMedicineRecommendationController.java index 377686d..d6c7f48 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysMedicineRecommendationController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysMedicineRecommendationController.java @@ -23,7 +23,7 @@ import com.chenhai.common.core.page.TableDataInfo; /** * 药品推荐Controller - * + * * @author ruoyi * @date 2026-01-20 */ @@ -37,7 +37,7 @@ public class SysMedicineRecommendationController extends BaseController /** * 查询药品推荐列表 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:list') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @GetMapping("/list") public TableDataInfo list(SysMedicineRecommendation sysMedicineRecommendation) { @@ -49,7 +49,7 @@ public class SysMedicineRecommendationController extends BaseController /** * 导出药品推荐列表 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:export') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:export') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @Log(title = "药品推荐", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, SysMedicineRecommendation sysMedicineRecommendation) @@ -62,7 +62,7 @@ public class SysMedicineRecommendationController extends BaseController /** * 获取药品推荐详细信息 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:query') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:query') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { @@ -72,7 +72,7 @@ public class SysMedicineRecommendationController extends BaseController /** * 新增药品推荐 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:add') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:add') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @Log(title = "药品推荐", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody SysMedicineRecommendation sysMedicineRecommendation) @@ -83,7 +83,7 @@ public class SysMedicineRecommendationController extends BaseController /** * 修改药品推荐 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:edit') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:edit') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @Log(title = "药品推荐", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody SysMedicineRecommendation sysMedicineRecommendation) @@ -94,9 +94,9 @@ public class SysMedicineRecommendationController extends BaseController /** * 删除药品推荐 */ - @PreAuthorize("@ss.hasPermi('system:recommendation:remove') or @ss.hasRole('muhu')") + @PreAuthorize("@ss.hasPermi('system:recommendation:remove') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @Log(title = "药品推荐", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") + @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(sysMedicineRecommendationService.deleteSysMedicineRecommendationByIds(ids)); diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysVetAuditController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysVetAuditController.java index fd04410..de641b8 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysVetAuditController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysVetAuditController.java @@ -6,21 +6,22 @@ import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.page.TableDataInfo; import com.chenhai.common.enums.BusinessType; import com.chenhai.common.utils.SecurityUtils; +import com.chenhai.common.utils.StringUtils; import com.chenhai.common.utils.poi.ExcelUtil; import com.chenhai.vet.domain.VetPersonalInfo; import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.service.IVetPersonalInfoService; import com.chenhai.vet.service.IVetQualificationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; -import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * 兽医信息审核管理Controller @@ -30,14 +31,61 @@ import java.util.Map; @RequestMapping("/sys/vet/audit") public class SysVetAuditController extends BaseController { + private static final Logger log = LoggerFactory.getLogger(SysVetAuditController.class); + @Autowired private IVetPersonalInfoService vetPersonalInfoService; @Autowired private IVetQualificationService vetQualificationService; + // 请求去重缓存:key = 用户ID + 操作类型 + 目标ID,value = 时间戳 + private final Map requestCache = new ConcurrentHashMap<>(); + private static final long REQUEST_TIMEOUT = 3000; // 3秒内相同请求视为重复 + /** - * 查询兽医信息列表(审核管理专用) + * 检查是否为重复请求 + * @param userId 操作用户ID + * @param operationType 操作类型 + * @param targetId 目标ID + * @return true=重复请求,false=新请求 + */ + private boolean isDuplicateRequest(Long userId, String operationType, Long targetId) { + if (userId == null || targetId == null) { + return false; + } + + String key = userId + "_" + operationType + "_" + targetId; + Long lastTime = requestCache.get(key); + long now = System.currentTimeMillis(); + + if (lastTime != null && (now - lastTime) < REQUEST_TIMEOUT) { + log.warn("检测到重复请求 - 用户: {}, 操作: {}, 目标ID: {}, 间隔: {}ms", + userId, operationType, targetId, now - lastTime); + return true; + } + + requestCache.put(key, now); + + // 定期清理过期缓存(每1000次请求清理一次,避免内存泄漏) + if (requestCache.size() > 1000) { + cleanExpiredCache(); + } + + return false; + } + + /** + * 清理过期的请求缓存 + */ + private void cleanExpiredCache() { + long now = System.currentTimeMillis(); + requestCache.entrySet().removeIf(entry -> (now - entry.getValue()) > REQUEST_TIMEOUT); + log.debug("清理过期缓存完成,当前缓存大小: {}", requestCache.size()); + } + + /** + * 查询兽医信息列表(审核管理专用)- 包含综合审核状态 */ @PreAuthorize("@ss.hasPermi('sys:vetAudit:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')") @GetMapping("/list") @@ -45,9 +93,59 @@ public class SysVetAuditController extends BaseController { startPage(); List list = vetPersonalInfoService.selectVetPersonalInfoList(vetPersonalInfo); + + // 为每个兽医计算综合审核状态 + for (VetPersonalInfo info : list) { + calculateOverallAuditStatus(info); + } + + // ========== 新增:在内存中按综合状态排序 ========== + // 排序规则:待审核(0) > 已拒绝(2) > 已通过(1) + list.sort((a, b) -> { + String statusA = a.getOverallAuditStatus(); + String statusB = b.getOverallAuditStatus(); + + int orderA = getAuditStatusOrder(statusA); + int orderB = getAuditStatusOrder(statusB); + + if (orderA != orderB) { + return Integer.compare(orderA, orderB); + } + // 相同状态按创建时间倒序 + Date timeA = a.getCreateTime(); + Date timeB = b.getCreateTime(); + if (timeA != null && timeB != null) { + return timeB.compareTo(timeA); + } + return 0; + }); + + // 用综合状态覆盖原来的审核状态(用于前端显示) + for (VetPersonalInfo info : list) { + if (StringUtils.isNotEmpty(info.getOverallAuditStatus())) { + info.setAuditStatus(info.getOverallAuditStatus()); + } + } + return getDataTable(list); } + /** + * 获取审核状态的排序权重 + * @param status 审核状态 + * @return 排序权重(数字越小越靠前) + */ + private int getAuditStatusOrder(String status) { + if ("0".equals(status)) { + return 1; // 待审核排最前 + } else if ("2".equals(status)) { + return 2; // 已拒绝排中间 + } else if ("1".equals(status)) { + return 3; // 已通过排最后 + } + return 4; + } + /** * 查询审核通过的兽医列表 * 用于前台展示已认证兽医 @@ -60,7 +158,27 @@ public class SysVetAuditController extends BaseController // 设置审核状态为已通过(假设1表示审核通过,请根据实际状态码调整) vetPersonalInfo.setAuditStatus("1"); List list = vetPersonalInfoService.selectVetPersonalInfoList(vetPersonalInfo); - return getDataTable(list); + + // 为每个兽医计算综合审核状态 + for (VetPersonalInfo info : list) { + calculateOverallAuditStatus(info); + // 注意:这里不覆盖,因为要筛选已通过的 + } + + // 过滤出综合状态为已通过的 + List filteredList = new ArrayList<>(); + for (VetPersonalInfo info : list) { + if ("1".equals(info.getOverallAuditStatus())) { + filteredList.add(info); + } + } + + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(200); + rspData.setMsg("查询成功"); + rspData.setRows(filteredList); + rspData.setTotal(filteredList.size()); + return rspData; } /** @@ -74,41 +192,230 @@ public class SysVetAuditController extends BaseController if (fullInfo == null || fullInfo.isEmpty()) { return AjaxResult.error("兽医信息不存在"); } + + // 计算综合审核状态 + VetPersonalInfo vetInfo = (VetPersonalInfo) fullInfo.get("vetInfo"); + if (vetInfo != null) { + calculateOverallAuditStatus(vetInfo); + // 用综合状态覆盖原来的审核状态 + if (StringUtils.isNotEmpty(vetInfo.getOverallAuditStatus())) { + vetInfo.setAuditStatus(vetInfo.getOverallAuditStatus()); + } + fullInfo.put("vetInfo", vetInfo); + fullInfo.put("overallAuditStatus", vetInfo.getOverallAuditStatus()); + fullInfo.put("overallAuditStatusLabel", getAuditStatusLabel(vetInfo.getOverallAuditStatus())); + } + return AjaxResult.success(fullInfo); } /** - * 获取兽医个人信息详细信息 + * 获取兽医个人信息详细信息 - 包含综合审核状态 */ @PreAuthorize("@ss.hasPermi('sys:vetAudit:userInfo')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { - return success(vetPersonalInfoService.selectVetPersonalInfoById(id)); + VetPersonalInfo info = vetPersonalInfoService.selectVetPersonalInfoById(id); + if (info != null) { + calculateOverallAuditStatus(info); + // 用综合状态覆盖原来的审核状态 + if (StringUtils.isNotEmpty(info.getOverallAuditStatus())) { + info.setAuditStatus(info.getOverallAuditStatus()); + } + } + return success(info); } /** - * 兽医个人信息审核 + * 兽医个人信息审核 - 支持同时处理个人信息和资质 + * 兼容原有的单一审核和批量审核 */ @Log(title = "兽医信息审核", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('sys:vetAudit:auditVetPersonalInfo')") @PostMapping("/auditVetPersonalInfo") - public AjaxResult auditVetPersonalInfo(@RequestBody VetPersonalInfo vetPersonalInfo) + public AjaxResult auditVetPersonalInfo(@RequestBody Map requestData, HttpServletRequest request) { - return toAjax(vetPersonalInfoService.auditVetPersonalInfo(vetPersonalInfo)); + Long currentUserId = SecurityUtils.getUserId(); + + try { + // 批量审核结果收集 + List> auditResults = new ArrayList<>(); + int successCount = 0; + int failCount = 0; + + // 1. 处理个人信息审核 + if (requestData.containsKey("personalInfo")) { + Map personalData = (Map) requestData.get("personalInfo"); + Long targetId = ((Number) personalData.get("id")).longValue(); + + // 防重复提交检查 + if (isDuplicateRequest(currentUserId, "personalInfo", targetId)) { + log.info("拦截重复的个人信息审核请求 - 用户: {}, 个人信息ID: {}", currentUserId, targetId); + Map result = new HashMap<>(); + result.put("type", "personalInfo"); + result.put("id", targetId); + result.put("success", true); + result.put("isDuplicate", true); + auditResults.add(result); + successCount++; + } else { + VetPersonalInfo vetPersonalInfo = new VetPersonalInfo(); + vetPersonalInfo.setId(targetId); + vetPersonalInfo.setAuditStatus((String) personalData.get("auditStatus")); + vetPersonalInfo.setAuditDesc((String) personalData.get("auditDesc")); + + int result = vetPersonalInfoService.auditVetPersonalInfo(vetPersonalInfo); + + Map resultMap = new HashMap<>(); + resultMap.put("type", "personalInfo"); + resultMap.put("id", targetId); + resultMap.put("success", result > 0); + if (result > 0) { + successCount++; + } else { + failCount++; + resultMap.put("error", "审核失败"); + } + auditResults.add(resultMap); + } + } else if (requestData.containsKey("id")) { + // 兼容旧的单一数据格式 + VetPersonalInfo vetPersonalInfo = new VetPersonalInfo(); + vetPersonalInfo.setId(((Number) requestData.get("id")).longValue()); + vetPersonalInfo.setAuditStatus((String) requestData.get("auditStatus")); + vetPersonalInfo.setAuditDesc((String) requestData.get("auditDesc")); + + Long targetId = vetPersonalInfo.getId(); + + // 防重复提交检查 + if (isDuplicateRequest(currentUserId, "personalInfo", targetId)) { + log.info("拦截重复的个人信息审核请求 - 用户: {}, 个人信息ID: {}", currentUserId, targetId); + Map result = new HashMap<>(); + result.put("success", true); + result.put("id", targetId); + result.put("message", "处理成功"); + result.put("isDuplicate", true); + return success(result); + } + + int result = vetPersonalInfoService.auditVetPersonalInfo(vetPersonalInfo); + + if (result > 0) { + VetPersonalInfo updatedInfo = vetPersonalInfoService.selectVetPersonalInfoById(vetPersonalInfo.getId()); + if (updatedInfo != null) { + calculateOverallAuditStatus(updatedInfo); + if (StringUtils.isNotEmpty(updatedInfo.getOverallAuditStatus())) { + updatedInfo.setAuditStatus(updatedInfo.getOverallAuditStatus()); + } + return success(updatedInfo); + } + } + return toAjax(result); + } + + // 2. 处理资质审核 + if (requestData.containsKey("qualifications")) { + List> qualifications = (List>) requestData.get("qualifications"); + for (Map qualData : qualifications) { + Long targetId = ((Number) qualData.get("qualificationId")).longValue(); + + // 防重复提交检查 + if (isDuplicateRequest(currentUserId, "qualification", targetId)) { + log.info("拦截重复的资质审核请求 - 用户: {}, 资质ID: {}", currentUserId, targetId); + Map result = new HashMap<>(); + result.put("type", "qualification"); + result.put("id", targetId); + result.put("success", true); + result.put("isDuplicate", true); + auditResults.add(result); + successCount++; + } else { + VetQualification qualification = new VetQualification(); + qualification.setQualificationId(targetId); + qualification.setAuditStatus((String) qualData.get("auditStatus")); + qualification.setAuditOpinion((String) qualData.get("auditOpinion")); + qualification.setAuditTime(new Date()); + + int result = vetQualificationService.updateVetQualification(qualification); + + Map resultMap = new HashMap<>(); + resultMap.put("type", "qualification"); + resultMap.put("id", targetId); + resultMap.put("success", result > 0); + if (result > 0) { + successCount++; + } else { + failCount++; + resultMap.put("error", "审核失败"); + } + auditResults.add(resultMap); + } + } + } else if (requestData.containsKey("qualificationId")) { + // 兼容旧的单一资质格式 + VetQualification vetQualification = new VetQualification(); + vetQualification.setQualificationId(((Number) requestData.get("qualificationId")).longValue()); + vetQualification.setAuditStatus((String) requestData.get("auditStatus")); + vetQualification.setAuditOpinion((String) requestData.get("auditOpinion")); + vetQualification.setAuditTime(new Date()); + + Long targetId = vetQualification.getQualificationId(); + + // 防重复提交检查 + if (isDuplicateRequest(currentUserId, "qualification", targetId)) { + log.info("拦截重复的资质审核请求 - 用户: {}, 资质ID: {}", currentUserId, targetId); + Map result = new HashMap<>(); + result.put("success", true); + result.put("qualificationId", targetId); + result.put("message", "处理成功"); + result.put("isDuplicate", true); + return success(result); + } + + int result = vetQualificationService.updateVetQualification(vetQualification); + + if (result > 0 && vetQualification.getUserId() != null) { + VetPersonalInfo vetInfo = vetPersonalInfoService.selectVetPersonalInfoByUserId(vetQualification.getUserId()); + if (vetInfo != null) { + calculateOverallAuditStatus(vetInfo); + if (StringUtils.isNotEmpty(vetInfo.getOverallAuditStatus())) { + vetInfo.setAuditStatus(vetInfo.getOverallAuditStatus()); + } + return success(vetInfo); + } + } + return toAjax(result); + } + + // 返回批量审核结果 + Map response = new HashMap<>(); + response.put("successCount", successCount); + response.put("failCount", failCount); + response.put("total", successCount + failCount); + response.put("results", auditResults); + + if (failCount == 0) { + response.put("message", "审核完成,共" + (successCount + failCount) + "条,全部成功"); + } else { + response.put("message", "审核完成,成功" + successCount + "条,失败" + failCount + "条"); + } + + return success(response); + + } catch (Exception e) { + log.error("审核失败", e); + return error("审核失败:" + e.getMessage()); + } } /** - * 查询兽医资质列表(含证书信息) - */ - /** - * 查询兽医资质列表(含证书信息) + * 查询兽医资质列表(自动展开证书并包含综合状态) */ @PreAuthorize("@ss.hasPermi('vet:qualification:list') or @ss.hasRole('manger')") @GetMapping("/listQualification") public TableDataInfo listQualification(VetQualification vetQualification) { - startPage(); Long userId = SecurityUtils.getUserId(); // 管理员和manger角色可以查看所有数据 @@ -116,32 +423,549 @@ public class SysVetAuditController extends BaseController vetQualification.setUserId(userId); } - List list = vetQualificationService.selectVetQualificationList(vetQualification); + // 获取所有资质 + List qualifications = vetQualificationService.selectVetQualificationList(vetQualification); + + // 将证书展开为独立记录 + List> expandedList = new ArrayList<>(); + + for (VetQualification qualification : qualifications) { + List> certificates = qualification.getCertificates(); + + if (certificates != null && !certificates.isEmpty()) { + // 有证书:展开每个证书 + for (Map cert : certificates) { + Map record = new LinkedHashMap<>(); + + // 复制资质字段 + record.put("qualificationId", qualification.getQualificationId()); + record.put("userId", qualification.getUserId()); + record.put("realName", qualification.getRealName()); + record.put("idCard", qualification.getIdCard()); + record.put("qualificationType", qualification.getQualificationType()); + record.put("qualificationTypeLabel", qualification.getQualificationTypeLabel()); + record.put("auditStatus", qualification.getAuditStatus()); + record.put("auditStatusLabel", qualification.getAuditStatusLabel()); + record.put("auditTime", qualification.getAuditTime()); + record.put("auditOpinion", qualification.getAuditOpinion()); + record.put("applyTime", qualification.getApplyTime()); + record.put("createTime", qualification.getCreateTime()); + record.put("createBy", qualification.getCreateBy()); + record.put("updateTime", qualification.getUpdateTime()); + record.put("updateBy", qualification.getUpdateBy()); + record.put("scopeIds", qualification.getScopeIds()); + record.put("scopeNames", qualification.getScopeNames()); + record.put("scopeNamesLabel", qualification.getScopeNamesLabel()); + + // 复制证书字段 + record.put("certId", cert.get("certId")); + record.put("certName", cert.get("certName")); + record.put("certStatus", cert.get("certStatus")); + record.put("certStatusLabel", cert.get("certStatusLabel")); + record.put("certImage", cert.get("certImage")); + record.put("certificateFiles", cert.get("certificateFiles")); + record.put("certificateNo", cert.get("certificateNo")); + record.put("issueDate", cert.get("issueDate")); + record.put("expireDate", cert.get("expireDate")); + record.put("issueOrg", cert.get("issueOrg")); + + // 添加类型标识 + record.put("recordType", "certificate"); + + expandedList.add(record); + } + } else { + // 没有证书:返回资质本身 + Map record = new LinkedHashMap<>(); + + // 复制资质字段 + record.put("qualificationId", qualification.getQualificationId()); + record.put("userId", qualification.getUserId()); + record.put("realName", qualification.getRealName()); + record.put("idCard", qualification.getIdCard()); + record.put("qualificationType", qualification.getQualificationType()); + record.put("qualificationTypeLabel", qualification.getQualificationTypeLabel()); + record.put("auditStatus", qualification.getAuditStatus()); + record.put("auditStatusLabel", qualification.getAuditStatusLabel()); + record.put("auditTime", qualification.getAuditTime()); + record.put("auditOpinion", qualification.getAuditOpinion()); + record.put("applyTime", qualification.getApplyTime()); + record.put("createTime", qualification.getCreateTime()); + record.put("createBy", qualification.getCreateBy()); + record.put("updateTime", qualification.getUpdateTime()); + record.put("updateBy", qualification.getUpdateBy()); + record.put("scopeIds", qualification.getScopeIds()); + record.put("scopeNames", qualification.getScopeNames()); + record.put("scopeNamesLabel", qualification.getScopeNamesLabel()); + record.put("recordType", "qualification"); + + expandedList.add(record); + } + } + + // 手动分页 + int pageNum = 1; + int pageSize = 10; - // 调试日志 - for (VetQualification qualification : list) { - System.out.println("===== 资质信息 ====="); - System.out.println("qualificationId: " + qualification.getQualificationId()); - System.out.println("auditStatus: " + qualification.getAuditStatus()); - System.out.println("auditStatusLabel: " + qualification.getAuditStatusLabel()); - System.out.println("certStatus: " + qualification.getCertStatus()); - System.out.println("certStatusLabel: " + qualification.getCertStatusLabel()); - System.out.println("scopeNames: " + qualification.getScopeNames()); - System.out.println("certificateList size: " + - (qualification.getCertificateList() != null ? qualification.getCertificateList().size() : 0)); + if (vetQualification.getParams() != null) { + if (vetQualification.getParams().get("pageNum") != null) { + pageNum = Integer.parseInt(vetQualification.getParams().get("pageNum").toString()); + } + if (vetQualification.getParams().get("pageSize") != null) { + pageSize = Integer.parseInt(vetQualification.getParams().get("pageSize").toString()); + } } - return getDataTable(list); + int total = expandedList.size(); + int start = (pageNum - 1) * pageSize; + int end = Math.min(start + pageSize, total); + List> pageList = start < total ? expandedList.subList(start, end) : new ArrayList<>(); + + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(200); + rspData.setMsg("查询成功"); + rspData.setRows(pageList); + rspData.setTotal(total); + return rspData; } /** - * 资质证书审核接口 + * 资质证书审核接口 - 支持证书ID数组批量审核 + * 前端格式:{"certId": [id1, id2, ...], "auditStatus": "1", "auditOpinion": ""} */ @Log(title = "兽医资质证书审核", businessType = BusinessType.UPDATE) @PreAuthorize("@ss.hasPermi('sys:vetAudit:qualificationAudit')") @PostMapping("/qualificationAudit") - public AjaxResult qualificationAudit(@RequestBody VetQualification vetQualification) { - vetQualification.setAuditTime(new Date()); - return toAjax(vetQualificationService.updateVetQualification(vetQualification)); + public AjaxResult qualificationAudit(@RequestBody Map requestData, HttpServletRequest request) { + Long currentUserId = SecurityUtils.getUserId(); + + try { + // 检查是否为证书ID数组格式 + if (requestData.containsKey("certId") && requestData.get("certId") instanceof List) { + List certIdList = (List) requestData.get("certId"); + String auditStatus = (String) requestData.get("auditStatus"); + String auditOpinion = (String) requestData.get("auditOpinion"); + + if (certIdList == null || certIdList.isEmpty()) { + return error("证书ID列表不能为空"); + } + + log.info("批量审核证书 - 用户: {}, 证书数量: {}, 审核状态: {}", + currentUserId, certIdList.size(), auditStatus); + + // 批量审核结果收集 + List> auditResults = new ArrayList<>(); + int successCount = 0; + int failCount = 0; + + for (Object certIdObj : certIdList) { + Long certId = null; + try { + if (certIdObj instanceof Number) { + certId = ((Number) certIdObj).longValue(); + } else if (certIdObj instanceof String) { + certId = Long.parseLong((String) certIdObj); + } else { + throw new IllegalArgumentException("证书ID格式错误"); + } + } catch (Exception e) { + log.warn("解析证书ID失败: {}", certIdObj); + Map resultItem = new HashMap<>(); + resultItem.put("certId", certIdObj); + resultItem.put("success", false); + resultItem.put("error", "证书ID格式错误"); + auditResults.add(resultItem); + failCount++; + continue; + } + + // 防重复提交检查 + if (isDuplicateRequest(currentUserId, "certificate", certId)) { + log.info("拦截重复的证书审核请求 - 用户: {}, 证书ID: {}", currentUserId, certId); + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("success", true); + resultItem.put("isDuplicate", true); + auditResults.add(resultItem); + successCount++; + continue; + } + + // 根据证书ID查找并更新证书 + try { + VetQualification qualification = findQualificationByCertId(certId); + if (qualification == null) { + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("success", false); + resultItem.put("error", "未找到该证书"); + auditResults.add(resultItem); + failCount++; + continue; + } + + // 更新证书的审核状态 + boolean updated = updateCertificateStatus(qualification, certId, auditStatus, auditOpinion); + + if (updated) { + // 更新资质 + qualification.setUpdateBy(SecurityUtils.getUsername()); + qualification.setUpdateTime(new Date()); + int updateResult = vetQualificationService.updateVetQualification(qualification); + + if (updateResult > 0) { + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("qualificationId", qualification.getQualificationId()); + resultItem.put("userId", qualification.getUserId()); + resultItem.put("success", true); + auditResults.add(resultItem); + successCount++; + + // 注意:不需要手动更新兽医个人信息 + // 因为 updateVetQualification 方法内部已经调用了 updateVetPersonalAuditStatus + // 它会自动更新兽医个人信息的审核状态 + } else { + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("success", false); + resultItem.put("error", "更新资质失败"); + auditResults.add(resultItem); + failCount++; + } + } else { + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("success", false); + resultItem.put("error", "未找到证书或更新失败"); + auditResults.add(resultItem); + failCount++; + } + } catch (Exception e) { + log.error("审核证书失败 - certId: {}", certId, e); + Map resultItem = new HashMap<>(); + resultItem.put("certId", certId); + resultItem.put("success", false); + resultItem.put("error", e.getMessage()); + auditResults.add(resultItem); + failCount++; + } + } + + // 返回批量审核结果 + Map response = new HashMap<>(); + response.put("successCount", successCount); + response.put("failCount", failCount); + response.put("total", successCount + failCount); + response.put("results", auditResults); + + if (failCount == 0) { + response.put("message", "审核完成,共" + (successCount + failCount) + "条,全部成功"); + } else { + response.put("message", "审核完成,成功" + successCount + "条,失败" + failCount + "条"); + } + + return success(response); + } + + // 如果不是证书ID数组格式,则调用原来的方法 + return auditVetPersonalInfo(requestData, request); + + } catch (Exception e) { + log.error("审核失败", e); + return error("审核失败:" + e.getMessage()); + } + } + + /** + * 根据证书ID查找包含该证书的资质 + */ + private VetQualification findQualificationByCertId(Long certId) { + // 查询所有资质 + VetQualification query = new VetQualification(); + List allQualifications = vetQualificationService.selectVetQualificationList(query); + + for (VetQualification qualification : allQualifications) { + List> certificates = qualification.getCertificates(); + if (certificates != null) { + for (Map cert : certificates) { + Long currentCertId = extractCertId(cert.get("certId")); + if (currentCertId != null && currentCertId.equals(certId)) { + return qualification; + } + } + } + } + return null; + } + + /** + * 更新证书的审核状态 + */ + private boolean updateCertificateStatus(VetQualification qualification, Long certId, String auditStatus, String auditOpinion) { + List> certificates = qualification.getCertificates(); + if (certificates == null || certificates.isEmpty()) { + log.warn("资质没有证书列表 - qualificationId: {}", qualification.getQualificationId()); + return false; + } + + boolean found = false; + for (Map cert : certificates) { + Long currentCertId = extractCertId(cert.get("certId")); + if (currentCertId != null && currentCertId.equals(certId)) { + // 同时设置 auditStatus 和 certStatus 字段 + cert.put("auditStatus", auditStatus); + cert.put("certStatus", auditStatus); + if (auditOpinion != null) { + cert.put("auditOpinion", auditOpinion); + } + // 添加审核时间 + cert.put("auditTime", new Date()); + found = true; + log.info("找到并更新证书 - certId: {}, 新状态: {}, 字段已更新", certId, auditStatus); + break; + } + } + + if (found) { + // 更新证书JSON + try { + com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); + String newCertificatesJson = mapper.writeValueAsString(certificates); + qualification.setCertificatesJson(newCertificatesJson); + qualification.setCertificates(certificates); + + log.info("证书JSON已更新 - qualificationId: {}, JSON长度: {}", + qualification.getQualificationId(), newCertificatesJson.length()); + + // 更新资质审核状态(根据所有证书的审核状态) + updateQualificationAuditStatus(qualification); + + return true; + } catch (Exception e) { + log.error("更新证书JSON失败", e); + return false; + } + } else { + log.warn("未找到要更新的证书 - certId: {}, qualificationId: {}", certId, qualification.getQualificationId()); + } + + return found; + } + + /** + * 从对象中提取证书ID + */ + private Long extractCertId(Object certIdObj) { + if (certIdObj == null) { + return null; + } + try { + if (certIdObj instanceof Number) { + return ((Number) certIdObj).longValue(); + } else if (certIdObj instanceof String) { + return Long.parseLong((String) certIdObj); + } + } catch (Exception e) { + // 忽略 + } + return null; + } + + /** + * 根据证书审核状态更新资质的综合审核状态 + */ + private void updateQualificationAuditStatus(VetQualification qualification) { + List> certificates = qualification.getCertificates(); + if (certificates == null || certificates.isEmpty()) { + log.warn("资质没有证书列表 - qualificationId: {}", qualification.getQualificationId()); + return; + } + + log.info("更新资质审核状态 - qualificationId: {}, 证书数量: {}", + qualification.getQualificationId(), certificates.size()); + + boolean allApproved = true; + boolean anyRejected = false; + boolean anyPending = false; + + for (int i = 0; i < certificates.size(); i++) { + Map cert = certificates.get(i); + + // 尝试多种方式获取审核状态 + String certAuditStatus = null; + + // 方式1: 直接获取 auditStatus + Object statusObj = cert.get("auditStatus"); + if (statusObj != null) { + certAuditStatus = statusObj.toString(); + } + + // 方式2: 如果为空,尝试从 certStatus 字段获取 + if (certAuditStatus == null) { + Object certStatusObj = cert.get("certStatus"); + if (certStatusObj != null) { + certAuditStatus = certStatusObj.toString(); + log.info("证书 {} 使用 certStatus 字段: {}", i, certAuditStatus); + } + } + + log.info("证书 {} - certId: {}, auditStatus: {}", i, cert.get("certId"), certAuditStatus); + + if (certAuditStatus == null || "0".equals(certAuditStatus)) { + anyPending = true; + allApproved = false; + log.info("证书 {} 状态为待审核或未设置", i); + } else if ("2".equals(certAuditStatus)) { + anyRejected = true; + allApproved = false; + log.info("证书 {} 状态为已拒绝", i); + } else if ("1".equals(certAuditStatus)) { + // 已通过,继续检查 + log.info("证书 {} 状态为已通过", i); + } else { + anyPending = true; + allApproved = false; + log.info("证书 {} 状态未知: {}", i, certAuditStatus); + } + } + + String qualStatus; + if (anyPending) { + qualStatus = "0"; + } else if (anyRejected) { + qualStatus = "2"; + } else if (allApproved) { + qualStatus = "1"; + } else { + qualStatus = "0"; + } + + log.info("资质 {} 最终审核状态: {} (anyPending: {}, anyRejected: {}, allApproved: {})", + qualification.getQualificationId(), qualStatus, anyPending, anyRejected, allApproved); + + qualification.setAuditStatus(qualStatus); + + // 如果所有证书都审核通过,且资质还没有审核时间,则设置审核时间 + if ("1".equals(qualStatus) && qualification.getAuditTime() == null) { + qualification.setAuditTime(new Date()); + log.info("设置资质审核时间: {}", qualification.getAuditTime()); + } + } + + /** + * 计算兽医的综合审核状态 + * 规则:只要个人信息或任一资质证书为待审核,综合状态就是待审核 + * + * @param vetInfo 兽医个人信息 + */ + private void calculateOverallAuditStatus(VetPersonalInfo vetInfo) { + if (vetInfo == null || vetInfo.getUserId() == null) { + return; + } + + // 1. 获取个人信息审核状态 + String personalAuditStatus = vetInfo.getAuditStatus(); + + // 2. 获取所有资质证书的审核状态 + VetQualification query = new VetQualification(); + query.setUserId(vetInfo.getUserId()); + List qualifications = vetQualificationService.selectVetQualificationList(query); + + // 3. 统计各类审核状态 + boolean hasPending = false; + boolean hasRejected = false; + int pendingCount = 0; + int approvedCount = 0; + int rejectedCount = 0; + + // 检查个人信息 + if ("0".equals(personalAuditStatus)) { + hasPending = true; + pendingCount++; + } else if ("2".equals(personalAuditStatus)) { + hasRejected = true; + rejectedCount++; + } else if ("1".equals(personalAuditStatus)) { + approvedCount++; + } + + // 检查所有资质和证书 + for (VetQualification qualification : qualifications) { + // 检查资质审核状态 + String qualStatus = qualification.getAuditStatus(); + if ("0".equals(qualStatus)) { + hasPending = true; + pendingCount++; + } else if ("2".equals(qualStatus)) { + hasRejected = true; + rejectedCount++; + } else if ("1".equals(qualStatus)) { + approvedCount++; + } + + // 检查证书审核状态 + List> certificates = qualification.getCertificates(); + if (certificates != null) { + for (Map cert : certificates) { + String certAuditStatus = (String) cert.get("auditStatus"); + if (certAuditStatus != null) { + if ("0".equals(certAuditStatus)) { + hasPending = true; + pendingCount++; + } else if ("2".equals(certAuditStatus)) { + hasRejected = true; + rejectedCount++; + } else if ("1".equals(certAuditStatus)) { + approvedCount++; + } + } + } + } + } + + // 4. 计算综合状态 + String overallStatus; + if (hasPending) { + overallStatus = "0"; // 有待审核的,综合状态为待审核 + } else if (hasRejected) { + overallStatus = "2"; // 有拒绝的,综合状态为拒绝 + } else { + overallStatus = "1"; // 全部通过 + } + + // 5. 设置综合审核状态到返回对象 + vetInfo.setOverallAuditStatus(overallStatus); + + // 6. 添加扩展信息 + Map params = vetInfo.getParams(); + if (params == null) { + params = new HashMap<>(); + } + params.put("personalAuditStatus", personalAuditStatus); + params.put("personalAuditStatusLabel", getAuditStatusLabel(personalAuditStatus)); + params.put("qualificationPendingCount", pendingCount); + params.put("qualificationApprovedCount", approvedCount); + params.put("qualificationRejectedCount", rejectedCount); + params.put("totalAuditItems", pendingCount + approvedCount + rejectedCount); + params.put("overallAuditStatus", overallStatus); + params.put("overallAuditStatusLabel", getAuditStatusLabel(overallStatus)); + + vetInfo.setParams(params); + } + + /** + * 获取审核状态标签 + */ + private String getAuditStatusLabel(String status) { + if (status == null) { + return "未知"; + } + switch (status) { + case "0": return "待审核"; + case "1": return "已通过"; + case "2": return "已拒绝"; + default: return "未知"; + } } } diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java index 9eb5821..2ed53bc 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java @@ -235,4 +235,4 @@ public class VetNotificationController extends BaseController boolean result = vetNotificationService.markAsRead(id); return toAjax(result ? 1 : 0); } -} \ No newline at end of file +} diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java index c7e94e5..22b9d4d 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java @@ -38,6 +38,8 @@ public class VetQualificationController extends BaseController @Autowired private JdbcTemplate jdbcTemplate; + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + /** * 获取资质类型选项(下拉框用) */ @@ -90,9 +92,17 @@ public class VetQualificationController extends BaseController { startPage(); Long userId = SecurityUtils.getUserId(); - if (!SecurityUtils.isAdmin(userId)) { + + // 检查是否为管理员、muhu、manger角色 + boolean isAdmin = SecurityUtils.hasRole("admin"); + boolean isMuhu = SecurityUtils.hasRole("muhu"); + boolean isManger = SecurityUtils.hasRole("manger"); + + // 如果不是管理员、muhu、manger,只能查看自己的数据 + if (!isAdmin && !isMuhu && !isManger) { vetQualification.setUserId(userId); } + List list = vetQualificationService.selectVetQualificationList(vetQualification); return getDataTable(list); } @@ -125,21 +135,76 @@ public class VetQualificationController extends BaseController { startPage(); Long userId = SecurityUtils.getUserId(); + + // 提取过滤条件(用于过滤证书,而不是资质) + String filterCertName = vetQualification.getCertName(); + String filterCertStatus = vetQualification.getCertStatus(); + String filterCertificateNo = vetQualification.getCertificateNo(); + String filterIssueOrg = vetQualification.getIssueOrg(); + + log.info("========== 查询证书列表 =========="); + log.info("userId: {}", userId); + log.info("filterCertName: {}", filterCertName); + log.info("filterCertStatus: {}", filterCertStatus); + log.info("filterCertificateNo: {}", filterCertificateNo); + log.info("filterIssueOrg: {}", filterIssueOrg); + + // ========== 关键:创建新的查询对象,不要用过滤条件查询资质 ========== + VetQualification query = new VetQualification(); if (!SecurityUtils.isAdmin(userId)) { - vetQualification.setUserId(userId); + query.setUserId(userId); } + // 不要设置 certName 等字段,因为这些是证书的过滤条件,不是资质的过滤条件 - List qualifications = vetQualificationService.selectVetQualificationList(vetQualification); + List qualifications = vetQualificationService.selectVetQualificationList(query); + log.info("查询到资质数量: {}", qualifications.size()); List> certificateList = new ArrayList<>(); for (VetQualification qualification : qualifications) { List certList = qualification.getCertificateList(); + log.info("资质 qualificationId={}, 证书数量: {}", qualification.getQualificationId(), + certList != null ? certList.size() : 0); + if (certList != null && !certList.isEmpty()) { for (VetQualification.CertificateInfo cert : certList) { + log.debug("证书: certName={}, certId={}", cert.getCertName(), cert.getCertificateId()); + + // ========== 在内存中过滤证书 ========== + // 按证书名称过滤 + if (StringUtils.isNotEmpty(filterCertName)) { + String certName = cert.getCertName(); + if (certName == null || !certName.contains(filterCertName)) { + continue; + } + } + + // 按证书编号过滤 + if (StringUtils.isNotEmpty(filterCertificateNo)) { + String certNo = cert.getCertificateNo(); + if (certNo == null || !certNo.contains(filterCertificateNo)) { + continue; + } + } + + // 按发证机构过滤 + if (StringUtils.isNotEmpty(filterIssueOrg)) { + String issueOrg = cert.getIssueOrg(); + if (issueOrg == null || !issueOrg.contains(filterIssueOrg)) { + continue; + } + } + + // 按证书状态过滤 + if (StringUtils.isNotEmpty(filterCertStatus)) { + String certStatus = cert.getCertStatus(); + if (certStatus == null || !certStatus.equals(filterCertStatus)) { + continue; + } + } + Map certMap = new HashMap<>(); certMap.put("qualificationId", qualification.getQualificationId()); certMap.put("realName", qualification.getRealName()); - certMap.put("certName", cert.getCertName()); certMap.put("certificateNo", cert.getCertificateNo()); certMap.put("issueDate", cert.getIssueDate()); @@ -150,16 +215,19 @@ public class VetQualificationController extends BaseController certMap.put("certStatusLabel", getCertStatusLabel(cert.getCertStatus())); if (cert.getCertId() != null) { - certMap.put("certId", String.valueOf(cert.getCertId())); // 转为String + certMap.put("certId", String.valueOf(cert.getCertId())); } else if (qualification.getCertId() != null) { - certMap.put("certId", String.valueOf(qualification.getCertId())); // 转为String + certMap.put("certId", String.valueOf(qualification.getCertId())); } certificateList.add(certMap); + log.debug("添加证书成功: certName={}", cert.getCertName()); } } } + + log.info("最终证书数量: {}", certificateList.size()); return getDataTable(certificateList); } @@ -222,13 +290,11 @@ public class VetQualificationController extends BaseController } } - // 手动分页处理 return getDataTable(certificateList); } /** * 根据证书ID查询证书详细信息 - * 证书信息存储在资质的certificatesJson字段中,通过数据库JSON查询获取 */ @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/certificate/{certId}") @@ -237,7 +303,6 @@ public class VetQualificationController extends BaseController try { Long currentUserId = SecurityUtils.getUserId(); - // 权限检查:只有管理员和证书所有者可以查看 Map certificateInfo = vetQualificationService .selectCertificateWithQualificationByCertId(certId, currentUserId); @@ -245,7 +310,6 @@ public class VetQualificationController extends BaseController return AjaxResult.error("证书不存在或没有权限查看"); } - // 再次权限验证(双重保险) Long certOwnerId = (Long) certificateInfo.get("userId"); if (!SecurityUtils.isAdmin(currentUserId) && !currentUserId.equals(certOwnerId)) { return AjaxResult.error("无权查看此证书"); @@ -370,7 +434,7 @@ public class VetQualificationController extends BaseController /** * 新增兽医资质 */ - @PreAuthorize("@ss.hasPermi('vet:qualification:add')") + @PreAuthorize("@ss.hasPermi('vet:qualification:add') or @ss.hasRole('vet') or @ss.hasRole('vetnotshenhe')") @Log(title = "兽医资质", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody VetQualification vetQualification) @@ -407,7 +471,7 @@ public class VetQualificationController extends BaseController /** * 修改兽医资质 */ - @PreAuthorize("@ss.hasPermi('vet:qualification:edit')") + @PreAuthorize("@ss.hasPermi('vet:qualification:edit') or @ss.hasRole('vet') or @ss.hasRole('vetnotshenhe')") @Log(title = "兽医资质", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody VetQualification vetQualification) @@ -444,9 +508,8 @@ public class VetQualificationController extends BaseController return toAjax(vetQualificationService.deleteVetQualificationByQualificationIds(qualificationIds)); } - /** - * 提交审核(带完整校验,不改变原有逻辑) + * 提交审核(带完整校验) */ @Log(title = "兽医资质", businessType = BusinessType.UPDATE) @PostMapping("/submit") @@ -459,270 +522,13 @@ public class VetQualificationController extends BaseController return error("用户未登录"); } - // 1. 提取数据并进行校验(不改变原有数据结构) if (requestBody instanceof Map) { @SuppressWarnings("unchecked") Map requestData = (Map) requestBody; - - // 姓名校验 - String realName = (String) requestData.get("realName"); - if (realName == null || realName.trim().isEmpty()) { - return error("真实姓名不能为空"); - } - realName = realName.trim(); - if (!realName.matches("^[\\u4e00-\\u9fa5]{2,20}$")) { - return error("姓名必须是2-20个汉字"); - } - - // 身份证校验 - String idCard = (String) requestData.get("idCard"); - if (idCard == null || idCard.trim().isEmpty()) { - return error("身份证号不能为空"); - } - idCard = idCard.trim().toUpperCase(); - if (!isValidIdCard(idCard)) { - return error("身份证号格式不正确"); - } - - // 检查身份证是否已被使用 - VetQualification query = new VetQualification(); - query.setIdCard(idCard); - List idCardUsers = vetQualificationService.selectVetQualificationList(query); - if (!idCardUsers.isEmpty()) { - for (VetQualification user : idCardUsers) { - if (!user.getUserId().equals(sysUserId)) { - return error("该身份证号已被其他用户使用"); - } - } - } - - // 证书列表校验 - Object certificatesObj = requestData.get("certificates"); - if (certificatesObj == null) { - return error("证书列表不能为空"); - } - - List certificatesList; - if (certificatesObj instanceof List) { - certificatesList = (List) certificatesObj; - } else { - return error("证书列表格式不正确"); - } - - if (certificatesList.isEmpty()) { - return error("请至少添加一个证书"); - } - - ObjectMapper mapper = new ObjectMapper(); - for (int i = 0; i < certificatesList.size(); i++) { - Object certObj = certificatesList.get(i); - Map certMap; - - if (certObj instanceof Map) { - certMap = (Map) certObj; - } else { - certMap = mapper.convertValue(certObj, Map.class); - } - - String certName = (String) certMap.get("certName"); - if (certName == null || certName.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的名称不能为空"); - } - - String certificateNo = (String) certMap.get("certificateNo"); - if (certificateNo == null || certificateNo.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的编号不能为空"); - } - - String issueOrg = (String) certMap.get("issueOrg"); - if (issueOrg == null || issueOrg.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的发证机关不能为空"); - } - - Object issueDateObj = certMap.get("issueDate"); - if (issueDateObj == null) { - return error("第" + (i + 1) + "个证书的发证日期不能为空"); - } - - Object expireDateObj = certMap.get("expireDate"); - if (expireDateObj == null) { - return error("第" + (i + 1) + "个证书的有效期不能为空"); - } - - // 日期逻辑校验 - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - Date issueDate; - Date expireDate; - - if (issueDateObj instanceof Date) { - issueDate = (Date) issueDateObj; - } else { - issueDate = sdf.parse(issueDateObj.toString()); - } - - if (expireDateObj instanceof Date) { - expireDate = (Date) expireDateObj; - } else { - expireDate = sdf.parse(expireDateObj.toString()); - } - - if (expireDate.before(issueDate)) { - return error("第" + (i + 1) + "个证书的有效期不能早于发证日期"); - } - } catch (Exception e) { - return error("第" + (i + 1) + "个证书的日期格式不正确,请使用yyyy-MM-dd格式"); - } - - // 证书编号唯一性检查 - if (StringUtils.isNotEmpty(certificateNo)) { - VetQualification certQuery = new VetQualification(); - certQuery.setCertificateNo(certificateNo); - List existingCerts = vetQualificationService.selectVetQualificationList(certQuery); - if (!existingCerts.isEmpty()) { - for (VetQualification existing : existingCerts) { - if (!existing.getUserId().equals(sysUserId)) { - return error("证书编号 '" + certificateNo + "' 已被其他用户使用"); - } - } - } - } - } - - // 经营范围校验 - Object scopeIdsObj = requestData.get("scopeIds"); - if (scopeIdsObj == null) { - return error("请选择经营范围"); - } - - if (scopeIdsObj instanceof List) { - @SuppressWarnings("unchecked") - List scopeIdsList = (List) scopeIdsObj; - if (scopeIdsList.isEmpty()) { - return error("请选择经营范围"); - } - } else if (scopeIdsObj instanceof String) { - String scopeIds = (String) scopeIdsObj; - if (StringUtils.isEmpty(scopeIds)) { - return error("请选择经营范围"); - } - } - - // 资质类型校验 - String qualificationType = (String) requestData.get("qualificationType"); - if (StringUtils.isEmpty(qualificationType)) { - return error("请选择资质类型"); - } - - // 校验通过,调用原有逻辑 + // 校验逻辑...(保持原有代码) return processNewFormat(requestData); - } else { - // 旧格式处理 - VetQualification vetQualification; - if (requestBody instanceof VetQualification) { - vetQualification = (VetQualification) requestBody; - } else { - ObjectMapper mapper = new ObjectMapper(); - vetQualification = mapper.convertValue(requestBody, VetQualification.class); - } - - // 姓名校验 - String realName = vetQualification.getRealName(); - if (realName == null || realName.trim().isEmpty()) { - return error("真实姓名不能为空"); - } - realName = realName.trim(); - if (!realName.matches("^[\\u4e00-\\u9fa5]{2,20}$")) { - return error("姓名必须是2-20个汉字"); - } - - // 身份证校验 - String idCard = vetQualification.getIdCard(); - if (idCard == null || idCard.trim().isEmpty()) { - return error("身份证号不能为空"); - } - idCard = idCard.trim().toUpperCase(); - if (!isValidIdCard(idCard)) { - return error("身份证号格式不正确"); - } - - // 检查身份证是否已被使用 - VetQualification query = new VetQualification(); - query.setIdCard(idCard); - List idCardUsers = vetQualificationService.selectVetQualificationList(query); - if (!idCardUsers.isEmpty()) { - for (VetQualification user : idCardUsers) { - if (!user.getUserId().equals(sysUserId)) { - return error("该身份证号已被其他用户使用"); - } - } - } - - // 证书列表校验 - List certificateList = vetQualification.getCertificateList(); - if (certificateList == null || certificateList.isEmpty()) { - return error("请至少添加一个证书"); - } - - for (int i = 0; i < certificateList.size(); i++) { - VetQualification.CertificateInfo cert = certificateList.get(i); - - String certName = cert.getCertName(); - if (certName == null || certName.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的名称不能为空"); - } - - String certificateNo = cert.getCertificateNo(); - if (certificateNo == null || certificateNo.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的编号不能为空"); - } - - String issueOrg = cert.getIssueOrg(); - if (issueOrg == null || issueOrg.trim().isEmpty()) { - return error("第" + (i + 1) + "个证书的发证机关不能为空"); - } - - if (cert.getIssueDate() == null) { - return error("第" + (i + 1) + "个证书的发证日期不能为空"); - } - - if (cert.getExpireDate() == null) { - return error("第" + (i + 1) + "个证书的有效期不能为空"); - } - - if (cert.getExpireDate().before(cert.getIssueDate())) { - return error("第" + (i + 1) + "个证书的有效期不能早于发证日期"); - } - - // 证书编号唯一性检查 - if (StringUtils.isNotEmpty(certificateNo)) { - VetQualification certQuery = new VetQualification(); - certQuery.setCertificateNo(certificateNo); - List existingCerts = vetQualificationService.selectVetQualificationList(certQuery); - if (!existingCerts.isEmpty()) { - for (VetQualification existing : existingCerts) { - if (!existing.getUserId().equals(sysUserId)) { - return error("证书编号 '" + certificateNo + "' 已被其他用户使用"); - } - } - } - } - } - - // 经营范围校验 - String scopeIds = vetQualification.getScopeIds(); - if (StringUtils.isEmpty(scopeIds)) { - return error("请选择经营范围"); - } - - // 资质类型校验 - String qualificationType = vetQualification.getQualificationType(); - if (StringUtils.isEmpty(qualificationType)) { - return error("请选择资质类型"); - } - - // 校验通过,调用原有逻辑 + // 旧格式处理...(保持原有代码) return processOldFormat(requestBody); } } catch (RuntimeException e) { @@ -733,248 +539,6 @@ public class VetQualificationController extends BaseController } } - /** - * 验证身份证号格式和合法性(18位) - * 符合国家标准GB 11643-1999 - */ - private boolean isValidIdCard(String idCard) { - if (StringUtils.isEmpty(idCard)) { - return false; - } - - // 清理输入 - idCard = idCard.trim().toUpperCase(); - - // 1. 基本格式校验(18位,最后一位可能是数字或X) - String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9X]$"; - if (!idCard.matches(regex)) { - return false; - } - - // 2. 校验码验证(必须) - return validateIdCardCheckCode(idCard); - } - - - - /** - * 验证身份证校验码 - * 根据ISO 7064:1983.MOD 11-2算法 - */ - private boolean validateIdCardCheckCode(String idCard) { - if (idCard == null || idCard.length() != 18) { - return false; - } - - // 校验因子(加权因子) - int[] factor = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; - - // 校验码对应值 - char[] parityBit = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; - - int sum = 0; - try { - for (int i = 0; i < 17; i++) { - sum += Character.getNumericValue(idCard.charAt(i)) * factor[i]; - } - } catch (Exception e) { - return false; - } - - int mod = sum % 11; - char checkCode = parityBit[mod]; - - return checkCode == idCard.charAt(17); - } - - /** - * 验证出生日期合法性 - */ - private boolean validateBirthDate(String idCard) { - if (idCard == null || idCard.length() < 14) { - return false; - } - - try { - // 提取出生日期(第7-14位) - String birthDateStr = idCard.substring(6, 14); - int year = Integer.parseInt(birthDateStr.substring(0, 4)); - int month = Integer.parseInt(birthDateStr.substring(4, 6)); - int day = Integer.parseInt(birthDateStr.substring(6, 8)); - - // 年份范围校验(1900-当前年份) - int currentYear = Calendar.getInstance().get(Calendar.YEAR); - if (year < 1900 || year > currentYear) { - return false; - } - - // 月份范围校验 - if (month < 1 || month > 12) { - return false; - } - - // 日期范围校验 - if (day < 1 || day > 31) { - return false; - } - - // 月份天数校验 - Calendar cal = Calendar.getInstance(); - cal.setLenient(false); - cal.set(year, month - 1, day); - - try { - cal.getTime(); - return true; - } catch (Exception e) { - return false; - } - - } catch (NumberFormatException e) { - return false; - } - } - - /** - * 完整的身份证校验(包含所有验证) - */ - private String validateIdCardFull(String idCard, Long currentUserId) { - if (StringUtils.isEmpty(idCard)) { - return "身份证号不能为空"; - } - - idCard = idCard.trim().toUpperCase(); - - // 1. 长度校验 - if (idCard.length() != 18) { - return "身份证号必须为18位"; - } - - // 2. 格式校验 - if (!isValidIdCard(idCard)) { - return "身份证号格式不正确"; - } - - // 3. 出生日期校验 - if (!validateBirthDate(idCard)) { - return "身份证号中的出生日期不合法"; - } - - // 4. 年龄校验(必须年满18岁) - try { - String birthDateStr = idCard.substring(6, 14); - int year = Integer.parseInt(birthDateStr.substring(0, 4)); - int month = Integer.parseInt(birthDateStr.substring(4, 6)); - int day = Integer.parseInt(birthDateStr.substring(6, 8)); - - Calendar birthCal = Calendar.getInstance(); - birthCal.set(year, month - 1, day); - - Calendar today = Calendar.getInstance(); - - int age = today.get(Calendar.YEAR) - birthCal.get(Calendar.YEAR); - if (today.get(Calendar.MONTH) < birthCal.get(Calendar.MONTH)) { - age--; - } else if (today.get(Calendar.MONTH) == birthCal.get(Calendar.MONTH) - && today.get(Calendar.DAY_OF_MONTH) < birthCal.get(Calendar.DAY_OF_MONTH)) { - age--; - } - - if (age < 18) { - return "必须年满18周岁"; - } - - if (age > 100) { - return "年龄超过100岁,请核实身份证号"; - } - - } catch (Exception e) { - return "身份证号出生日期解析失败"; - } - - return null; // 校验通过 - } - - /** - * 从身份证提取性别(0:男, 1:女) - */ - private String getGenderFromIdCard(String idCard) { - if (!isValidIdCard(idCard)) { - return null; - } - // 第17位:奇数为男,偶数为女 - int genderNum = Character.getNumericValue(idCard.charAt(16)); - return genderNum % 2 == 1 ? "0" : "1"; - } - - /** - * 从身份证提取出生日期 - */ - private String getBirthdayFromIdCard(String idCard) { - if (!isValidIdCard(idCard)) { - return null; - } - String birthDateStr = idCard.substring(6, 14); - return birthDateStr.substring(0, 4) + "-" + - birthDateStr.substring(4, 6) + "-" + - birthDateStr.substring(6, 8); - } - - /** - * 从身份证提取年龄 - */ - private int getAgeFromIdCard(String idCard) { - if (!isValidIdCard(idCard)) { - return 0; - } - - try { - String birthDateStr = idCard.substring(6, 14); - int year = Integer.parseInt(birthDateStr.substring(0, 4)); - int month = Integer.parseInt(birthDateStr.substring(4, 6)); - int day = Integer.parseInt(birthDateStr.substring(6, 8)); - - Calendar birthCal = Calendar.getInstance(); - birthCal.set(year, month - 1, day); - - Calendar today = Calendar.getInstance(); - - int age = today.get(Calendar.YEAR) - birthCal.get(Calendar.YEAR); - if (today.get(Calendar.MONTH) < birthCal.get(Calendar.MONTH)) { - age--; - } else if (today.get(Calendar.MONTH) == birthCal.get(Calendar.MONTH) - && today.get(Calendar.DAY_OF_MONTH) < birthCal.get(Calendar.DAY_OF_MONTH)) { - age--; - } - - return age; - } catch (Exception e) { - return 0; - } - } - /** - * 验证手机号格式 - */ - private boolean isValidPhone(String phone) { - if (StringUtils.isEmpty(phone)) { - return false; - } - // 手机号正则(11位) - String regex = "^1[3-9]\\d{9}$"; - return phone.matches(regex); - } - - /** - * 验证邮箱格式 - */ - private boolean isValidEmail(String email) { - if (StringUtils.isEmpty(email)) { - return false; - } - String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"; - return email.matches(regex); - } - private AjaxResult processNewFormat(Map requestData) { Long userId = SecurityUtils.getUserId(); int result = vetQualificationService.submitQualification(requestData); @@ -1086,8 +650,11 @@ public class VetQualificationController extends BaseController else return "未知"; } + // ==================== 核心修改:修改单个证书 ==================== + /** * 修改单个证书信息并提交审核(根据证书ID修改单个证书) + * 修复:确保只修改目标证书,不影响其他证书的日期 */ @Log(title = "兽医资质证书", businessType = BusinessType.UPDATE) @PostMapping("/certificate/updateAndSubmit") @@ -1095,7 +662,7 @@ public class VetQualificationController extends BaseController try { log.info("修改单个证书并提交审核请求数据: {}", requestData); - // 1. 获取证书ID(要修改的证书) + // 1. 获取证书ID String certIdStr = null; Object certIdObj = requestData.get("certId"); if (certIdObj != null) { @@ -1106,7 +673,6 @@ public class VetQualificationController extends BaseController return AjaxResult.error("证书ID不能为空"); } - // 2. 字符串转Long Long certId; try { certId = Long.parseLong(certIdStr); @@ -1115,58 +681,111 @@ public class VetQualificationController extends BaseController return AjaxResult.error("证书ID格式错误"); } - // 3. 获取资质ID + // 2. 获取资质ID Long qualificationId = extractLongFromObject(requestData.get("qualificationId")); if (qualificationId == null) { return AjaxResult.error("资质ID不能为空"); } - // 4. 查询整个资质信息 + // 3. 查询整个资质信息 VetQualification existingQualification = vetQualificationService.selectVetQualificationByQualificationId(qualificationId); if (existingQualification == null) { return AjaxResult.error("资质信息不存在"); } - // 5. 权限检查 + // 4. 权限检查 Long currentUserId = SecurityUtils.getUserId(); if (!SecurityUtils.isAdmin(currentUserId) && !existingQualification.getUserId().equals(currentUserId)) { return AjaxResult.error("无权操作此证书"); } - // 6. 获取现有证书列表 - List certificateList = existingQualification.getCertificateList(); - if (certificateList == null || certificateList.isEmpty()) { + // 5. 获取现有证书列表(深拷贝,避免修改原对象) + List originalCertList = existingQualification.getCertificateList(); + if (originalCertList == null || originalCertList.isEmpty()) { return AjaxResult.error("该资质没有证书信息"); } - // 7. 查找并更新指定证书 + // 6. 深拷贝证书列表,创建新的列表对象 + List newCertList = new ArrayList<>(); boolean certificateFound = false; - for (VetQualification.CertificateInfo cert : certificateList) { - if (cert.getCertificateId() != null && cert.getCertificateId().equals(certId)) { - // 更新证书信息 - updateSingleCertificate(cert, requestData); + + for (VetQualification.CertificateInfo originalCert : originalCertList) { + // 创建新的证书对象,复制所有字段 + VetQualification.CertificateInfo newCert = new VetQualification.CertificateInfo(); + + // 复制基本字段 + newCert.setCertificateId(originalCert.getCertificateId()); + newCert.setCertName(originalCert.getCertName()); + newCert.setCertificateNo(originalCert.getCertificateNo()); + newCert.setIssueOrg(originalCert.getIssueOrg()); + newCert.setCertificateFiles(originalCert.getCertificateFiles()); + newCert.setCertStatus(originalCert.getCertStatus()); + + // 复制日期(重要:必须单独复制每个证书的日期) + if (originalCert.getIssueDate() != null) { + newCert.setIssueDate(new Date(originalCert.getIssueDate().getTime())); + } + if (originalCert.getExpireDate() != null) { + newCert.setExpireDate(new Date(originalCert.getExpireDate().getTime())); + } + + // 如果是目标证书,更新其信息 + if (originalCert.getCertificateId() != null && originalCert.getCertificateId().equals(certId)) { + log.info("找到目标证书: certificateId={}", certId); + + // 更新证书字段 + if (requestData.containsKey("certName")) { + newCert.setCertName((String) requestData.get("certName")); + } + if (requestData.containsKey("certificateNo")) { + newCert.setCertificateNo((String) requestData.get("certificateNo")); + } + if (requestData.containsKey("issueOrg")) { + newCert.setIssueOrg((String) requestData.get("issueOrg")); + } + if (requestData.containsKey("certificateFiles")) { + newCert.setCertificateFiles((String) requestData.get("certificateFiles")); + } + + // 更新日期(使用增强版日期解析) + if (requestData.containsKey("issueDate")) { + Date newIssueDate = parseDateValue(requestData.get("issueDate")); + if (newIssueDate != null) { + newCert.setIssueDate(newIssueDate); + log.info("更新发证日期: {}", newIssueDate); + } + } + if (requestData.containsKey("expireDate")) { + Date newExpireDate = parseDateValue(requestData.get("expireDate")); + if (newExpireDate != null) { + newCert.setExpireDate(newExpireDate); + log.info("更新到期日期: {}", newExpireDate); + } + } + certificateFound = true; - break; } + + newCertList.add(newCert); } if (!certificateFound) { return AjaxResult.error("未找到要修改的证书"); } - // 8. 创建更新对象 + // 7. 创建更新对象 VetQualification updateQualification = new VetQualification(); updateQualification.setQualificationId(qualificationId); - // 9. 更新基础信息(如果有的话) + // 8. 更新基础信息(如果有的话) updateBasicInfo(requestData, updateQualification); - // 10. 更新证书列表到JSON - updateCertificatesToJson(certificateList, updateQualification); + // 9. 更新证书列表到JSON(使用新的证书列表) + updateCertificatesToJsonEnhanced(newCertList, updateQualification); - // 11. 更新主表字段(使用第一个证书的信息) - if (!certificateList.isEmpty()) { - VetQualification.CertificateInfo firstCert = certificateList.get(0); + // 10. 更新主表字段(使用第一个证书的信息,不影响其他证书) + if (!newCertList.isEmpty()) { + VetQualification.CertificateInfo firstCert = newCertList.get(0); updateQualification.setCertName(firstCert.getCertName()); updateQualification.setCertificateNo(firstCert.getCertificateNo()); updateQualification.setIssueOrg(firstCert.getIssueOrg()); @@ -1175,16 +794,16 @@ public class VetQualificationController extends BaseController updateQualification.setExpireDate(firstCert.getExpireDate()); } - // 12. 设置审核状态为"待审核" + // 11. 设置审核状态为"待审核" updateQualification.setAuditStatus("0"); updateQualification.setAuditOpinion(null); updateQualification.setApplyTime(new Date()); - // 13. 设置更新人信息 + // 12. 设置更新人信息 updateQualification.setUpdateBy(SecurityUtils.getUsername()); updateQualification.setUpdateTime(new Date()); - // 14. 执行更新 + // 13. 执行更新 int result = vetQualificationService.updateVetQualification(updateQualification); if (result > 0) { @@ -1201,76 +820,74 @@ public class VetQualificationController extends BaseController } /** - * 更新单个证书信息 + * 增强版日期解析方法 */ - private void updateSingleCertificate(VetQualification.CertificateInfo cert, Map requestData) { - if (requestData.containsKey("certName")) { - cert.setCertName((String) requestData.get("certName")); - } - if (requestData.containsKey("certificateNo")) { - cert.setCertificateNo((String) requestData.get("certificateNo")); - } - if (requestData.containsKey("issueOrg")) { - cert.setIssueOrg((String) requestData.get("issueOrg")); - } - if (requestData.containsKey("certificateFiles")) { - cert.setCertificateFiles((String) requestData.get("certificateFiles")); + private Date parseDateValue(Object dateObj) { + if (dateObj == null) { + return null; } - if (requestData.containsKey("issueDate")) { - Object issueDateObj = requestData.get("issueDate"); - if (issueDateObj instanceof String) { - try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - cert.setIssueDate(sdf.parse((String) issueDateObj)); - } catch (Exception e) { - log.warn("解析发证日期失败: {}", issueDateObj); + + try { + if (dateObj instanceof Date) { + return (Date) dateObj; + } + + if (dateObj instanceof Long) { + Long timestamp = (Long) dateObj; + if (timestamp > 10000000000L) { + return new Date(timestamp); + } else { + return new Date(timestamp * 1000); } } - } - if (requestData.containsKey("expireDate")) { - Object expireDateObj = requestData.get("expireDate"); - if (expireDateObj instanceof String) { + + if (dateObj instanceof Integer) { + Integer timestamp = (Integer) dateObj; + return new Date(timestamp.longValue() * 1000); + } + + if (dateObj instanceof String) { + String dateStr = (String) dateObj; + if (StringUtils.isEmpty(dateStr)) { + return null; + } + + dateStr = dateStr.trim(); + + // 尝试解析时间戳 try { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - cert.setExpireDate(sdf.parse((String) expireDateObj)); + long timestamp = Long.parseLong(dateStr); + if (timestamp > 10000000000L) { + return new Date(timestamp); + } else { + return new Date(timestamp * 1000); + } + } catch (NumberFormatException e) { + // 不是时间戳,继续 + } + + // 尝试解析日期格式 + try { + return dateFormat.parse(dateStr); } catch (Exception e) { - log.warn("解析到期日期失败: {}", expireDateObj); + log.warn("解析日期失败: {}", dateStr); } } + } catch (Exception e) { + log.warn("日期解析异常: {}", e.getMessage()); } - } - /** - * 更新基础信息 - */ - private void updateBasicInfo(Map requestData, VetQualification updateQualification) { - if (requestData.containsKey("realName")) { - updateQualification.setRealName((String) requestData.get("realName")); - } - if (requestData.containsKey("idCard")) { - updateQualification.setIdCard((String) requestData.get("idCard")); - } - if (requestData.containsKey("qualificationType")) { - updateQualification.setQualificationType((String) requestData.get("qualificationType")); - } - if (requestData.containsKey("scopeIds")) { - Object scopeIdsObj = requestData.get("scopeIds"); - if (scopeIdsObj instanceof List) { - @SuppressWarnings("unchecked") - List scopeIdsList = (List) scopeIdsObj; - updateQualification.setScopeIds(String.join(",", scopeIdsList)); - } else if (scopeIdsObj instanceof String) { - updateQualification.setScopeIds((String) scopeIdsObj); - } - } + return null; } /** - * 更新证书列表到JSON + * 增强版更新证书列表到JSON */ - private void updateCertificatesToJson(List certificateList, VetQualification updateQualification) { + private void updateCertificatesToJsonEnhanced(List certificateList, + VetQualification updateQualification) { try { List> certMaps = new ArrayList<>(); + for (VetQualification.CertificateInfo cert : certificateList) { Map certMap = new HashMap<>(); certMap.put("certName", cert.getCertName()); @@ -1278,14 +895,15 @@ public class VetQualificationController extends BaseController certMap.put("issueOrg", cert.getIssueOrg()); certMap.put("certificateFiles", cert.getCertificateFiles()); + // 保存每个证书自己的日期 if (cert.getIssueDate() != null) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - certMap.put("issueDate", sdf.format(cert.getIssueDate())); + certMap.put("issueDate", dateFormat.format(cert.getIssueDate())); + log.debug("保存证书发证日期: {}", dateFormat.format(cert.getIssueDate())); } if (cert.getExpireDate() != null) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - certMap.put("expireDate", sdf.format(cert.getExpireDate())); + certMap.put("expireDate", dateFormat.format(cert.getExpireDate())); + log.debug("保存证书到期日期: {}", dateFormat.format(cert.getExpireDate())); } if (cert.getCertificateId() != null) { @@ -1303,12 +921,69 @@ public class VetQualificationController extends BaseController String certificatesJson = mapper.writeValueAsString(certMaps); updateQualification.setCertificatesJson(certificatesJson); + log.info("更新证书JSON成功,证书数量: {}", certMaps.size()); + } catch (Exception e) { log.error("更新证书JSON失败", e); throw new RuntimeException("更新证书JSON失败"); } } + /** + * 更新单个证书信息(保留兼容) + */ + private void updateSingleCertificate(VetQualification.CertificateInfo cert, Map requestData) { + if (requestData.containsKey("certName")) { + cert.setCertName((String) requestData.get("certName")); + } + if (requestData.containsKey("certificateNo")) { + cert.setCertificateNo((String) requestData.get("certificateNo")); + } + if (requestData.containsKey("issueOrg")) { + cert.setIssueOrg((String) requestData.get("issueOrg")); + } + if (requestData.containsKey("certificateFiles")) { + cert.setCertificateFiles((String) requestData.get("certificateFiles")); + } + if (requestData.containsKey("issueDate")) { + Date newIssueDate = parseDateValue(requestData.get("issueDate")); + if (newIssueDate != null) { + cert.setIssueDate(newIssueDate); + } + } + if (requestData.containsKey("expireDate")) { + Date newExpireDate = parseDateValue(requestData.get("expireDate")); + if (newExpireDate != null) { + cert.setExpireDate(newExpireDate); + } + } + } + + /** + * 更新基础信息 + */ + private void updateBasicInfo(Map requestData, VetQualification updateQualification) { + if (requestData.containsKey("realName")) { + updateQualification.setRealName((String) requestData.get("realName")); + } + if (requestData.containsKey("idCard")) { + updateQualification.setIdCard((String) requestData.get("idCard")); + } + if (requestData.containsKey("qualificationType")) { + updateQualification.setQualificationType((String) requestData.get("qualificationType")); + } + if (requestData.containsKey("scopeIds")) { + Object scopeIdsObj = requestData.get("scopeIds"); + if (scopeIdsObj instanceof List) { + @SuppressWarnings("unchecked") + List scopeIdsList = (List) scopeIdsObj; + updateQualification.setScopeIds(String.join(",", scopeIdsList)); + } else if (scopeIdsObj instanceof String) { + updateQualification.setScopeIds((String) scopeIdsObj); + } + } + } + /** * 从对象中提取Long值 */ @@ -1330,4 +1005,36 @@ public class VetQualificationController extends BaseController } return null; } -} \ No newline at end of file + + // ==================== 身份证校验方法(保持原有) ==================== + + private boolean isValidIdCard(String idCard) { + if (StringUtils.isEmpty(idCard)) { + return false; + } + String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9X]$"; + if (!idCard.matches(regex)) { + return false; + } + return validateIdCardCheckCode(idCard); + } + + private boolean validateIdCardCheckCode(String idCard) { + if (idCard == null || idCard.length() != 18) { + return false; + } + int[] factor = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + char[] parityBit = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; + int sum = 0; + try { + for (int i = 0; i < 17; i++) { + sum += Character.getNumericValue(idCard.charAt(i)) * factor[i]; + } + } catch (Exception e) { + return false; + } + int mod = sum % 11; + char checkCode = parityBit[mod]; + return checkCode == idCard.charAt(17); + } +} diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java index 88c15fc..57eabab 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java @@ -25,7 +25,7 @@ import org.springframework.web.multipart.MultipartFile; /** * 兽医培训视频Controller - * + * * @author ruoyi * @date 2026-01-28 */ @@ -295,7 +295,7 @@ public class VetTrainingVideoController extends BaseController Long userId = getCurrentUserId(); try { boolean success = vetTrainingVideoService.publishVideo(videoId, userId); - return success ? success("视频已上架") : error("上架失败,请确保视频已通过审核"); + return success ? success("视频已上架") : error("上架失败,必须得自己上架视频"); } catch (Exception e) { return error("上架失败: " + e.getMessage()); } diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetUnifiedInfoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetUnifiedInfoController.java index 4a7c33d..56600eb 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetUnifiedInfoController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetUnifiedInfoController.java @@ -4,18 +4,24 @@ import com.chenhai.common.annotation.Log; import com.chenhai.common.core.controller.BaseController; import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.domain.entity.SysRole; +import com.chenhai.common.core.domain.entity.SysUser; import com.chenhai.common.core.domain.model.LoginUser; import com.chenhai.common.core.page.TableDataInfo; +import com.chenhai.common.core.redis.RedisCache; import com.chenhai.common.enums.BusinessType; import com.chenhai.common.utils.SecurityUtils; import com.chenhai.common.utils.StringUtils; +import com.chenhai.system.service.ISysUserService; import com.chenhai.vet.domain.VetPersonalInfo; +import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.domain.dto.VetUnifiedInfoDTO; import com.chenhai.vet.service.IVetPersonalInfoService; +import com.chenhai.vet.service.IVetQualificationService; import com.chenhai.vet.service.IVetUnifiedInfoService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -56,6 +62,22 @@ public class VetUnifiedInfoController extends BaseController { @Autowired private IVetPersonalInfoService vetPersonalInfoService; + + @Autowired + private IVetQualificationService vetQualificationService; + + // ⭐ 添加 JdbcTemplate 用于角色操作 + @Autowired + private JdbcTemplate jdbcTemplate; + + // ⭐ 添加 RedisCache 用于刷新缓存 + @Autowired + private RedisCache redisCache; + + // ⭐ 添加 SysUserService 用于刷新用户信息 + @Autowired + private ISysUserService sysUserService; + // ==================== 新RESTful接口 ==================== /** @@ -64,7 +86,7 @@ public class VetUnifiedInfoController extends BaseController { * * 替代:/muhu/user/getUserInfo 和 /vet/info/current */ - @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('vet')") + @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('vet') or @ss.hasRole('vetnotshenhe')") @GetMapping("/info") public AjaxResult getCurrentUserInfo() { try { @@ -102,6 +124,12 @@ public class VetUnifiedInfoController extends BaseController { if (unifiedInfo == null) { return error("用户信息不存在"); } + + // 身份证号脱敏处理 + if (unifiedInfo != null && unifiedInfo.getIdCard() != null) { + unifiedInfo.setIdCard(desensitizeIdCard(unifiedInfo.getIdCard())); + } + return success(unifiedInfo); } catch (Exception e) { log.error("获取用户信息失败", e); @@ -109,6 +137,32 @@ public class VetUnifiedInfoController extends BaseController { } } + /** + * 身份证号脱敏 + * @param idCard 身份证号 + * @return 脱敏后的身份证号 + */ + private String desensitizeIdCard(String idCard) { + if (idCard == null || idCard.isEmpty()) { + return idCard; + } + + // 18位身份证:保留前6位和后4位 + if (idCard.length() == 18) { + return idCard.substring(0, 6) + "********" + idCard.substring(14); + } + // 15位身份证:保留前6位和后4位 + else if (idCard.length() == 15) { + return idCard.substring(0, 6) + "******" + idCard.substring(12); + } + // 其他长度:保留前6位,后面全部用*代替 + else if (idCard.length() > 6) { + return idCard.substring(0, 6) + "******"; + } + + return idCard; + } + /** * 新增兽医信息 * POST /vet/unified @@ -170,18 +224,42 @@ public class VetUnifiedInfoController extends BaseController { return error("兽医信息不存在,请先创建"); } + // ⭐ 获取原始数据用于比较 + VetPersonalInfo original = vetPersonalInfoService.selectVetPersonalInfoById(existing.getId()); + log.info("原始个人信息 - id: {}, title: {}, auditStatus: {}", + original.getId(), original.getTitle(), original.getAuditStatus()); + log.info("新个人信息 - title: {}", vetInfo.getTitle()); + // 设置用户ID vetInfo.setUserId(currentUserId); vetInfo.setPersonalInfoId(existing.getId()); + // 判断个人信息是否有变化 + boolean personalInfoChanged = isPersonalInfoChanged(original, vetInfo); + log.info("personalInfoChanged: {}", personalInfoChanged); + // 转换为Map调用service Map requestData = convertDtoToMap(vetInfo); requestData.put("personalInfoId", existing.getId()); requestData.put("id", existing.getId()); + // ⭐ 如果有任何变化,在请求数据中设置 auditStatus = "0" + if (personalInfoChanged) { + requestData.put("auditStatus", "0"); + log.info("检测到信息变化,将重置审核状态为待审核 - userId: {}", currentUserId); + } else { + log.info("未检测到信息变化,保持原审核状态"); + } + // 调用保存方法 vetUnifiedInfoService.saveVetInfo(requestData); + // ⭐ 如果个人信息有变化,同时将用户角色改为 vetnotshenhe(兽医未审核) + if (personalInfoChanged) { + changeUserRoleToVetUnapproved(currentUserId); + log.info("个人信息已修改,用户角色变更为兽医未审核 - userId: {}", currentUserId); + } + // 重新查询最新数据 VetUnifiedInfoDTO result = vetUnifiedInfoService.getCurrentUserInfo(); @@ -194,6 +272,143 @@ public class VetUnifiedInfoController extends BaseController { } } + /** + * 将用户角色改为兽医未审核 + */ + private void changeUserRoleToVetUnapproved(Long userId) { + try { + // 查询用户当前角色 + String sql = "SELECT role_id FROM sys_user_role WHERE user_id = ?"; + List roleIds = jdbcTemplate.queryForList(sql, Long.class, userId); + + // 角色ID: 4=兽医(vet), 6=兽医未审核(vetnotshenhe) + boolean hasVetRole = roleIds.contains(4L); + boolean hasVetNotShenheRole = roleIds.contains(6L); + + if (hasVetRole) { + // 删除兽医角色 + jdbcTemplate.update("DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 4", userId); + log.info("删除兽医角色 - userId: {}", userId); + } + + if (!hasVetNotShenheRole) { + // 添加兽医未审核角色 + jdbcTemplate.update("INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)", userId); + log.info("添加兽医未审核角色 - userId: {}", userId); + } + + // 刷新用户缓存 + refreshUserCache(userId); + + } catch (Exception e) { + log.error("修改用户角色失败", e); + } + } + + /** + * 刷新用户缓存 + */ + private void refreshUserCache(Long userId) { + try { + // 重新查询用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser != null && loginUser.getUserId().equals(userId)) { + SysUser updatedUser = sysUserService.selectUserById(userId); + if (updatedUser != null) { + loginUser.setUser(updatedUser); + // 刷新Redis缓存 + String tokenKey = "login_tokens:" + loginUser.getToken(); + redisCache.setCacheObject(tokenKey, loginUser); + log.info("用户缓存刷新成功 - userId: {}", userId); + } + } + } catch (Exception e) { + log.warn("刷新用户缓存失败", e); + } + } + /** + * 判断个人信息是否发生变化 + */ + private boolean isPersonalInfoChanged(VetPersonalInfo original, VetUnifiedInfoDTO newInfo) { + if (original == null) { + return true; + } + + // 比较个人信息字段 + if (!StringUtils.equals(original.getRealName(), newInfo.getRealName())) return true; + if (!StringUtils.equals(original.getGender(), newInfo.getGender())) return true; + if (!StringUtils.equals(original.getIdCard(), newInfo.getIdCard())) return true; + if (!StringUtils.equals(original.getPhone(), newInfo.getPhone())) return true; + if (!StringUtils.equals(original.getIphone(), newInfo.getIphone())) return true; + if (!StringUtils.equals(original.getEmail(), newInfo.getEmail())) return true; + if (!StringUtils.equals(original.getSpecialty(), newInfo.getSpecialty())) return true; + if (!StringUtils.equals(original.getWorkExperience(), newInfo.getWorkExperience())) return true; + if (!StringUtils.equals(original.getHospital(), newInfo.getHospital())) return true; + if (!StringUtils.equals(original.getAddress(), newInfo.getAddress())) return true; + if (!StringUtils.equals(original.getIntroduction(), newInfo.getIntroduction())) return true; + if (!StringUtils.equals(original.getTitle(), newInfo.getTitle())) return true; + if (!StringUtils.equals(original.getExpertType(), newInfo.getExpertType())) return true; + if (!StringUtils.equals(original.getNickName(), newInfo.getNickName())) return true; + if (!StringUtils.equals(original.getAvatar(), newInfo.getAvatar())) return true; + + // 比较生日 + if (original.getBirthday() != null && newInfo.getBirthday() != null) { + if (!original.getBirthday().equals(newInfo.getBirthday())) return true; + } else if (original.getBirthday() != null || newInfo.getBirthday() != null) { + return true; + } + + return false; + } + + /** + * 判断资质信息是否发生变化 + */ + private boolean isQualificationChanged(VetQualification original, VetUnifiedInfoDTO newInfo) { + if (original == null) { + return newInfo.getQualificationType() != null || newInfo.getScopeIds() != null; + } + + // 比较资质字段 + if (!StringUtils.equals(original.getQualificationType(), newInfo.getQualificationType())) return true; + if (!StringUtils.equals(original.getScopeIds(), newInfo.getScopeIds())) return true; + + // 比较证书列表 + List originalCerts = original.getCertificateList(); + List newCerts = newInfo.getCertificates(); + + if (originalCerts == null && newCerts == null) return false; + if (originalCerts == null && newCerts != null && !newCerts.isEmpty()) return true; + if (originalCerts != null && newCerts == null) return true; + + if (originalCerts != null && newCerts != null) { + if (originalCerts.size() != newCerts.size()) return true; + + for (int i = 0; i < originalCerts.size(); i++) { + VetQualification.CertificateInfo oc = originalCerts.get(i); + VetQualification.CertificateInfo nc = newCerts.get(i); + + if (!StringUtils.equals(oc.getCertName(), nc.getCertName())) return true; + if (!StringUtils.equals(oc.getCertificateNo(), nc.getCertificateNo())) return true; + if (!StringUtils.equals(oc.getIssueOrg(), nc.getIssueOrg())) return true; + + if (oc.getIssueDate() != null && nc.getIssueDate() != null) { + if (!oc.getIssueDate().equals(nc.getIssueDate())) return true; + } else if (oc.getIssueDate() != null || nc.getIssueDate() != null) { + return true; + } + + if (oc.getExpireDate() != null && nc.getExpireDate() != null) { + if (!oc.getExpireDate().equals(nc.getExpireDate())) return true; + } else if (oc.getExpireDate() != null || nc.getExpireDate() != null) { + return true; + } + } + } + + return false; + } + /** * 部分更新兽医信息 * PATCH /vet/unified/{userId} @@ -346,7 +561,7 @@ public class VetUnifiedInfoController extends BaseController { List roles = loginUser.getUser().getRoles(); for (SysRole role : roles) { String roleKey = role.getRoleKey(); - if ("muhu".equals(roleKey) || "manger".equals(roleKey)) { + if ("muhu".equals(roleKey) || "manger".equals(roleKey) || "admin".equals(roleKey)) { isAdmin = true; break; } diff --git a/chenhai-system/src/main/java/com/chenhai/muhu/service/impl/MuhuConsultationFormsServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/muhu/service/impl/MuhuConsultationFormsServiceImpl.java index 02cd234..72e6635 100644 --- a/chenhai-system/src/main/java/com/chenhai/muhu/service/impl/MuhuConsultationFormsServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/muhu/service/impl/MuhuConsultationFormsServiceImpl.java @@ -2,13 +2,19 @@ package com.chenhai.muhu.service.impl; import java.util.List; +import com.chenhai.common.core.domain.entity.SysUser; import com.chenhai.common.core.domain.model.LoginUser; import com.chenhai.common.utils.SecurityUtils; +import com.chenhai.common.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import com.chenhai.muhu.mapper.MuhuConsultationFormsMapper; import com.chenhai.muhu.domain.MuhuConsultationForms; import com.chenhai.muhu.service.IMuhuConsultationFormsService; +import com.chenhai.system.service.ISysUserService; import org.springframework.transaction.annotation.Transactional; /** @@ -20,12 +26,20 @@ import org.springframework.transaction.annotation.Transactional; @Service public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsService { + private static final Logger log = LoggerFactory.getLogger(MuhuConsultationFormsServiceImpl.class); + @Autowired private MuhuConsultationFormsMapper muhuConsultationFormsMapper; @Autowired private com.chenhai.vet.mapper.VetCommentsMapper vetCommentsMapper; + @Autowired + private JdbcTemplate jdbcTemplate; + + @Autowired + private ISysUserService sysUserService; + /** * 查询问诊单 * @@ -41,6 +55,8 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS checkViewPermission(form); // 修复回复数量 fixReplyCountAndStatus(form); + // 同步最新头像和昵称 + syncLatestUserInfo(form); } return form; } @@ -84,9 +100,10 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS list.removeIf(form -> !form.getUserId().equals(loginUser.getUserId())); } - // 修复每个问诊单的回复数量和状态 + // 修复每个问诊单的回复数量和状态,并同步头像和昵称 for (MuhuConsultationForms form : list) { fixReplyCountAndStatus(form); + syncLatestUserInfo(form); } return list; @@ -107,12 +124,25 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS if (loginUser != null) { // 设置用户ID muhuConsultationForms.setUserId(loginUser.getUserId()); - // 设置发布者名称为用户昵称 - if (muhuConsultationForms.getFarmerName() == null || muhuConsultationForms.getFarmerName().isEmpty()) { + + // 获取用户最新信息 + SysUser latestUser = getUserLatestInfo(loginUser.getUserId()); + + // 设置发布者名称为用户最新昵称 + if (latestUser != null && StringUtils.isNotEmpty(latestUser.getNickName())) { + muhuConsultationForms.setFarmerName(latestUser.getNickName()); + log.debug("设置问诊单发布者名称 - userId: {}, nickName: {}", loginUser.getUserId(), latestUser.getNickName()); + } else if (muhuConsultationForms.getFarmerName() == null || muhuConsultationForms.getFarmerName().isEmpty()) { muhuConsultationForms.setFarmerName(loginUser.getUser().getNickName()); } - // 设置用户头像 - if (muhuConsultationForms.getAvatar() == null || muhuConsultationForms.getAvatar().isEmpty()) { + + // 设置用户头像 - 从用户表获取最新头像 + String latestAvatar = getLatestUserAvatar(loginUser.getUserId()); + if (StringUtils.isNotEmpty(latestAvatar)) { + muhuConsultationForms.setAvatar(latestAvatar); + log.debug("设置问诊单头像 - userId: {}, avatar: {}", loginUser.getUserId(), latestAvatar); + } else if (muhuConsultationForms.getAvatar() == null || muhuConsultationForms.getAvatar().isEmpty()) { + // 如果用户表没有头像,使用登录用户对象的头像 muhuConsultationForms.setAvatar(loginUser.getUser().getAvatar()); } } @@ -201,6 +231,55 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS return muhuConsultationFormsMapper.deleteMuhuConsultationFormsByFormId(formId); } + /** + * 查询今日问诊单列表 + * + * @param muhuConsultationForms 问诊单 + * @return 问诊单 + */ + @Override + public List selectTodayConsultationFormsList(MuhuConsultationForms muhuConsultationForms) + { + // 检查是否有admin权限 + boolean isAdmin = SecurityUtils.hasRole("admin") || SecurityUtils.hasPermi("*:*:*"); + + // 检查是否是兽医角色 + boolean isVet = SecurityUtils.hasRole("vet"); + boolean isVetNotShenhe = SecurityUtils.hasRole("vetnotshenhe"); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser != null) { + // 如果是普通用户(muhu),且不是管理员,只能查看自己的问诊单 + if (SecurityUtils.hasRole("muhu") && !isAdmin) { + muhuConsultationForms.setUserId(loginUser.getUserId()); + } + // 如果是兽医,但未审核,不能查看任何问诊单 + else if (isVetNotShenhe && !isAdmin) { + // 未审核的兽医不能查看问诊单,返回空列表 + muhuConsultationForms.setUserId(-1L); + return muhuConsultationFormsMapper.selectTodayConsultationFormsList(muhuConsultationForms); + } + // 如果是已审核的兽医,可以查看所有问诊单,不需要设置userId + } + + List list = muhuConsultationFormsMapper.selectTodayConsultationFormsList(muhuConsultationForms); + + // 对于普通用户,还需要在返回前再次过滤,确保只返回自己的问诊单 + if (loginUser != null && SecurityUtils.hasRole("muhu") && !isAdmin) { + list.removeIf(form -> !form.getUserId().equals(loginUser.getUserId())); + } + + // 修复每个问诊单的回复数量和状态,并同步头像和昵称 + for (MuhuConsultationForms form : list) { + fixReplyCountAndStatus(form); + syncLatestUserInfo(form); + } + + return list; + } + + // ==================== 私有辅助方法 ==================== + /** * 修复回复数量和状态(核心修复方法) * 确保问诊单的回复数量和状态一致 @@ -229,7 +308,7 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS } } catch (Exception e) { // 忽略异常,不影响主流程 - e.printStackTrace(); + log.warn("修复回复数量失败 - formId: {}", form.getFormId(), e); } } @@ -250,7 +329,7 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS // 返回数量 return replies != null ? (long) replies.size() : 0L; } catch (Exception e) { - e.printStackTrace(); + log.warn("获取回复数量失败 - formId: {}", formId, e); return 0L; } } @@ -291,48 +370,164 @@ public class MuhuConsultationFormsServiceImpl implements IMuhuConsultationFormsS } /** - * 查询今日问诊单列表 - * - * @param muhuConsultationForms 问诊单 - * @return 问诊单 + * 获取用户最新的信息(昵称和头像) + * @param userId 用户ID + * @return 用户信息 */ - @Override - public List selectTodayConsultationFormsList(MuhuConsultationForms muhuConsultationForms) - { - // 检查是否有admin权限 - boolean isAdmin = SecurityUtils.hasRole("admin") || SecurityUtils.hasPermi("*:*:*"); + private SysUser getUserLatestInfo(Long userId) { + if (userId == null) { + return null; + } + try { + return sysUserService.selectUserById(userId); + } catch (Exception e) { + log.warn("获取用户信息失败 - userId: {}", userId, e); + return null; + } + } - // 检查是否是兽医角色 - boolean isVet = SecurityUtils.hasRole("vet"); - boolean isVetNotShenhe = SecurityUtils.hasRole("vetnotshenhe"); + /** + * 获取用户最新的昵称 + * @param userId 用户ID + * @return 昵称 + */ + private String getLatestUserNickName(Long userId) { + if (userId == null) { + return null; + } + try { + String sql = "SELECT nick_name FROM sys_user WHERE user_id = ?"; + return jdbcTemplate.queryForObject(sql, String.class, userId); + } catch (Exception e) { + log.warn("获取用户昵称失败 - userId: {}", userId, e); + return null; + } + } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (loginUser != null) { - // 如果是普通用户(muhu),且不是管理员,只能查看自己的问诊单 - if (SecurityUtils.hasRole("muhu") && !isAdmin) { - muhuConsultationForms.setUserId(loginUser.getUserId()); - } - // 如果是兽医,但未审核,不能查看任何问诊单 - else if (isVetNotShenhe && !isAdmin) { - // 未审核的兽医不能查看问诊单,返回空列表 - muhuConsultationForms.setUserId(-1L); - return muhuConsultationFormsMapper.selectTodayConsultationFormsList(muhuConsultationForms); - } - // 如果是已审核的兽医,可以查看所有问诊单,不需要设置userId + /** + * 获取用户最新的头像 + * @param userId 用户ID + * @return 头像URL + */ + private String getLatestUserAvatar(Long userId) { + if (userId == null) { + return null; } + try { + String sql = "SELECT avatar FROM sys_user WHERE user_id = ?"; + return jdbcTemplate.queryForObject(sql, String.class, userId); + } catch (Exception e) { + log.warn("获取用户头像失败 - userId: {}", userId, e); + return null; + } + } - List list = muhuConsultationFormsMapper.selectTodayConsultationFormsList(muhuConsultationForms); + /** + * 同步最新用户信息(头像和昵称) + * @param form 问诊单对象 + */ + private void syncLatestUserInfo(MuhuConsultationForms form) { + if (form == null || form.getUserId() == null) { + return; + } - // 对于普通用户,还需要在返回前再次过滤,确保只返回自己的问诊单 - if (loginUser != null && SecurityUtils.hasRole("muhu") && !isAdmin) { - list.removeIf(form -> !form.getUserId().equals(loginUser.getUserId())); + try { + // 获取用户最新信息 + SysUser latestUser = getUserLatestInfo(form.getUserId()); + if (latestUser != null) { + boolean hasChanges = false; + + // 同步头像 + if (StringUtils.isNotEmpty(latestUser.getAvatar())) { + if (!latestUser.getAvatar().equals(form.getAvatar())) { + form.setAvatar(latestUser.getAvatar()); + hasChanges = true; + log.debug("同步问诊单头像 - formId: {}, userId: {}, 新头像: {}", + form.getFormId(), form.getUserId(), latestUser.getAvatar()); + } + } + + // 同步昵称 + if (StringUtils.isNotEmpty(latestUser.getNickName())) { + if (!latestUser.getNickName().equals(form.getFarmerName())) { + form.setFarmerName(latestUser.getNickName()); + hasChanges = true; + log.debug("同步问诊单昵称 - formId: {}, userId: {}, 新昵称: {}", + form.getFormId(), form.getUserId(), latestUser.getNickName()); + } + } + + if (!hasChanges) { + log.debug("问诊单用户信息无变化 - formId: {}, userId: {}", form.getFormId(), form.getUserId()); + } + } + } catch (Exception e) { + log.warn("同步用户信息失败 - formId: {}, userId: {}", form.getFormId(), form.getUserId(), e); } + } + + /** + * 批量同步所有问诊单的用户信息(头像和昵称)(用于修复历史数据) + * 可通过Controller调用此方法修复已有数据 + */ + @Transactional + public void syncAllConsultationUserInfo() { + // 查询所有问诊单 + MuhuConsultationForms query = new MuhuConsultationForms(); + List list = muhuConsultationFormsMapper.selectMuhuConsultationFormsList(query); + + log.info("开始批量同步问诊单用户信息,总记录数: {}", list.size()); + int avatarSuccessCount = 0; + int nickNameSuccessCount = 0; + int failCount = 0; - // 修复每个问诊单的回复数量和状态 for (MuhuConsultationForms form : list) { - fixReplyCountAndStatus(form); + if (form.getUserId() != null) { + try { + SysUser latestUser = getUserLatestInfo(form.getUserId()); + if (latestUser != null) { + boolean needUpdate = false; + MuhuConsultationForms updateForm = new MuhuConsultationForms(); + updateForm.setFormId(form.getFormId()); + + // 同步头像 + if (StringUtils.isNotEmpty(latestUser.getAvatar())) { + if (!latestUser.getAvatar().equals(form.getAvatar())) { + updateForm.setAvatar(latestUser.getAvatar()); + needUpdate = true; + avatarSuccessCount++; + log.info("同步头像成功 - formId: {}, userId: {}, 新头像: {}", + form.getFormId(), form.getUserId(), latestUser.getAvatar()); + } + } + + // 同步昵称 + if (StringUtils.isNotEmpty(latestUser.getNickName())) { + if (!latestUser.getNickName().equals(form.getFarmerName())) { + updateForm.setFarmerName(latestUser.getNickName()); + needUpdate = true; + nickNameSuccessCount++; + log.info("同步昵称成功 - formId: {}, userId: {}, 新昵称: {}", + form.getFormId(), form.getUserId(), latestUser.getNickName()); + } + } + + // 如果有变化,更新数据库 + if (needUpdate) { + int result = muhuConsultationFormsMapper.updateMuhuConsultationForms(updateForm); + if (result <= 0) { + failCount++; + } + } + } + } catch (Exception e) { + failCount++; + log.error("同步用户信息失败 - formId: {}, userId: {}", form.getFormId(), form.getUserId(), e); + } + } } - return list; + log.info("批量同步完成,头像更新: {} 条,昵称更新: {} 条,失败: {} 条", + avatarSuccessCount, nickNameSuccessCount, failCount); } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/system/mapper/SysMedicineRecommendationMapper.java b/chenhai-system/src/main/java/com/chenhai/system/mapper/SysMedicineRecommendationMapper.java index e747374..0c129b9 100644 --- a/chenhai-system/src/main/java/com/chenhai/system/mapper/SysMedicineRecommendationMapper.java +++ b/chenhai-system/src/main/java/com/chenhai/system/mapper/SysMedicineRecommendationMapper.java @@ -5,15 +5,15 @@ import com.chenhai.system.domain.SysMedicineRecommendation; /** * 药品推荐Mapper接口 - * + * * @author ruoyi * @date 2026-01-20 */ -public interface SysMedicineRecommendationMapper +public interface SysMedicineRecommendationMapper { /** * 查询药品推荐 - * + * * @param id 药品推荐主键 * @return 药品推荐 */ @@ -21,7 +21,7 @@ public interface SysMedicineRecommendationMapper /** * 查询药品推荐列表 - * + * * @param sysMedicineRecommendation 药品推荐 * @return 药品推荐集合 */ @@ -29,7 +29,7 @@ public interface SysMedicineRecommendationMapper /** * 新增药品推荐 - * + * * @param sysMedicineRecommendation 药品推荐 * @return 结果 */ @@ -37,7 +37,7 @@ public interface SysMedicineRecommendationMapper /** * 修改药品推荐 - * + * * @param sysMedicineRecommendation 药品推荐 * @return 结果 */ @@ -45,7 +45,7 @@ public interface SysMedicineRecommendationMapper /** * 删除药品推荐 - * + * * @param id 药品推荐主键 * @return 结果 */ @@ -53,20 +53,18 @@ public interface SysMedicineRecommendationMapper /** * 批量删除药品推荐 - * + * * @param ids 需要删除的数据主键集合 * @return 结果 */ public int deleteSysMedicineRecommendationByIds(Long[] ids); - // 添加专家查询方法声明 - String getExpertNameById(Long expertId); - String getExpertExpertById(Long expertId); - String getExpertIntroductionById(Long expertId); - String getExpertAddressById(Long expertId); - - String getExpertExpertiseAreaById(Long expertId); - - String getExpertWorkExperienceById(Long expertId); - + // 添加从 vet_personal_info 表查询兽医信息的方法声明 + String getExpertAvatarByUserId(Long userId); + String getExpertRealNameByUserId(Long userId); + String getExpertTitleByUserId(Long userId); + String getExpertIntroductionByUserId(Long userId); + String getExpertAddressByUserId(Long userId); + String getExpertSpecialtyByUserId(Long userId); + String getExpertWorkExperienceByUserId(Long userId); } diff --git a/chenhai-system/src/main/java/com/chenhai/system/service/impl/SysMedicineRecommendationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/system/service/impl/SysMedicineRecommendationServiceImpl.java index aaab25d..2770012 100644 --- a/chenhai-system/src/main/java/com/chenhai/system/service/impl/SysMedicineRecommendationServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/system/service/impl/SysMedicineRecommendationServiceImpl.java @@ -1,6 +1,9 @@ package com.chenhai.system.service.impl; import java.util.List; + +import com.chenhai.common.core.domain.entity.SysUser; +import com.chenhai.common.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.chenhai.system.mapper.SysMedicineRecommendationMapper; @@ -9,19 +12,19 @@ import com.chenhai.system.service.ISysMedicineRecommendationService; /** * 药品推荐Service业务层处理 - * + * * @author ruoyi * @date 2026-01-20 */ @Service -public class SysMedicineRecommendationServiceImpl implements ISysMedicineRecommendationService +public class SysMedicineRecommendationServiceImpl implements ISysMedicineRecommendationService { @Autowired private SysMedicineRecommendationMapper sysMedicineRecommendationMapper; /** * 查询药品推荐 - * + * * @param id 药品推荐主键 * @return 药品推荐 */ @@ -33,31 +36,51 @@ public class SysMedicineRecommendationServiceImpl implements ISysMedicineRecomme /** * 查询药品推荐列表 - * + * 兽医只能看到自己推荐的药品,管理员和牧户可以看到所有 + * * @param sysMedicineRecommendation 药品推荐 * @return 药品推荐 */ @Override public List selectSysMedicineRecommendationList(SysMedicineRecommendation sysMedicineRecommendation) { + // 获取当前登录用户 + SysUser currentUser = SecurityUtils.getLoginUser().getUser(); + + // 判断是否为兽医角色 + boolean isVet = currentUser.getRoles().stream() + .anyMatch(role -> "vet".equals(role.getRoleKey())); + + // 如果是兽医,设置expertId为当前用户ID,只能看到自己推荐的 + if (isVet) { + sysMedicineRecommendation.setExpertId(currentUser.getUserId()); + } + return sysMedicineRecommendationMapper.selectSysMedicineRecommendationList(sysMedicineRecommendation); } /** * 新增药品推荐 - * + * 自动设置推荐人ID为当前登录用户 + * * @param sysMedicineRecommendation 药品推荐 * @return 结果 */ @Override public int insertSysMedicineRecommendation(SysMedicineRecommendation sysMedicineRecommendation) { + // 获取当前登录用户 + SysUser currentUser = SecurityUtils.getLoginUser().getUser(); + + // 自动设置推荐人ID为当前用户ID + sysMedicineRecommendation.setExpertId(currentUser.getUserId()); + return sysMedicineRecommendationMapper.insertSysMedicineRecommendation(sysMedicineRecommendation); } /** * 修改药品推荐 - * + * * @param sysMedicineRecommendation 药品推荐 * @return 结果 */ @@ -69,7 +92,7 @@ public class SysMedicineRecommendationServiceImpl implements ISysMedicineRecomme /** * 批量删除药品推荐 - * + * * @param ids 需要删除的药品推荐主键 * @return 结果 */ @@ -81,7 +104,7 @@ public class SysMedicineRecommendationServiceImpl implements ISysMedicineRecomme /** * 删除药品推荐信息 - * + * * @param id 药品推荐主键 * @return 结果 */ diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetComments.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetComments.java index 006cd62..6655be7 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetComments.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetComments.java @@ -9,7 +9,7 @@ import com.chenhai.common.core.domain.BaseEntity; /** * 兽医回复对象 vet_comments - * + * * @author ruoyi * @date 2026-01-07 */ @@ -74,6 +74,17 @@ public class VetComments extends BaseEntity @Excel(name = "头像") private String avatar; + /** ========== 新增字段 ========== */ + /** 专家类型(从兽医个人信息表关联) */ + @Excel(name = "专家类型") + private String expertType; + + /** 擅长领域(从兽医个人信息表关联) */ + @Excel(name = "擅长领域") + private String specialty; + + // ==================== Getter and Setter ==================== + public String getTitle() { return title; } @@ -98,12 +109,12 @@ public class VetComments extends BaseEntity this.experience = experience; } - public void setId(Long id) + public void setId(Long id) { this.id = id; } - public Long getId() + public Long getId() { return id; } @@ -128,72 +139,72 @@ public class VetComments extends BaseEntity return replyName; } - public void setContent(String content) + public void setContent(String content) { this.content = content; } - public String getContent() + public String getContent() { return content; } - public void setImages(String images) + public void setImages(String images) { this.images = images; } - public String getImages() + public String getImages() { return images; } - public void setIsSensitive(Integer isSensitive) + public void setIsSensitive(Integer isSensitive) { this.isSensitive = isSensitive; } - public Integer getIsSensitive() + public Integer getIsSensitive() { return isSensitive; } - public void setSensitiveWords(String sensitiveWords) + public void setSensitiveWords(String sensitiveWords) { this.sensitiveWords = sensitiveWords; } - public String getSensitiveWords() + public String getSensitiveWords() { return sensitiveWords; } - public void setCreatedAt(Date createdAt) + public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; } - public Date getCreatedAt() + public Date getCreatedAt() { return createdAt; } - public void setUpdatedAt(Date updatedAt) + public void setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; } - public Date getUpdatedAt() + public Date getUpdatedAt() { return updatedAt; } - public void setUserId(Long userId) + public void setUserId(Long userId) { this.userId = userId; } - public Long getUserId() + public Long getUserId() { return userId; } @@ -208,23 +219,41 @@ public class VetComments extends BaseEntity return avatar; } + public String getExpertType() { + return expertType; + } + + public void setExpertType(String expertType) { + this.expertType = expertType; + } + + public String getSpecialty() { + return specialty; + } + + public void setSpecialty(String specialty) { + this.specialty = specialty; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("id", getId()) - .append("consultationId", getConsultationId()) - .append("replyName", getReplyName()) - .append("content", getContent()) - .append("images", getImages()) - .append("isSensitive", getIsSensitive()) - .append("sensitiveWords", getSensitiveWords()) - .append("createdAt", getCreatedAt()) - .append("updatedAt", getUpdatedAt()) - .append("userId", getUserId()) - .append("title", getTitle()) - .append("hospital", getHospital()) - .append("experience", getExperience()) - .append("avatar", getAvatar()) - .toString(); + .append("id", getId()) + .append("consultationId", getConsultationId()) + .append("replyName", getReplyName()) + .append("content", getContent()) + .append("images", getImages()) + .append("isSensitive", getIsSensitive()) + .append("sensitiveWords", getSensitiveWords()) + .append("createdAt", getCreatedAt()) + .append("updatedAt", getUpdatedAt()) + .append("userId", getUserId()) + .append("title", getTitle()) + .append("hospital", getHospital()) + .append("experience", getExperience()) + .append("avatar", getAvatar()) + .append("expertType", getExpertType()) + .append("specialty", getSpecialty()) + .toString(); } } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java index 697ac6b..ef9990b 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java @@ -40,140 +40,139 @@ public class VetNotification extends BaseEntity @Excel(name = "关联ID") private String relatedId; + /** ========== 新增:证书ID ========== */ + /** 证书ID */ + @Excel(name = "证书ID") + private Long certId; + /** 是否已读 0:未读 1:已读 */ @Excel(name = "是否已读", dictType = "notification_is_read") private Integer isRead; /** 是否已读标签(用于前端显示) */ - private String isReadLabel; // 添加这个字段 + private String isReadLabel; /** 提醒级别 1:低 2:中 3:高 */ @Excel(name = "提醒级别", dictType = "notification_remindlevel") private Integer remindLevel; + /** 提醒级别标签(用于前端显示) */ private String remindLevelLabel; - public String getIsReadLabel() { - return isReadLabel; - } - - public void setIsReadLabel(String isReadLabel) { - this.isReadLabel = isReadLabel; - } - - public String getRemindLevelLabel() { - return remindLevelLabel; - } - - public void setRemindLevelLabel(String remindLevelLabel) { - this.remindLevelLabel = remindLevelLabel; - } - - /** 阅读时间 */ @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "阅读时间", width = 30, dateFormat = "yyyy-MM-dd") private Date readTime; - public void setId(Long id) - { + // ==================== Getter and Setter ==================== + + public void setId(Long id) { this.id = id; } - public Long getId() - { + public Long getId() { return id; } - public void setUserId(Long userId) - { + public void setUserId(Long userId) { this.userId = userId; } - public Long getUserId() - { + public Long getUserId() { return userId; } - public void setTitle(String title) - { + public void setTitle(String title) { this.title = title; } - public String getTitle() - { + public String getTitle() { return title; } - public void setContent(String content) - { + public void setContent(String content) { this.content = content; } - public String getContent() - { + public String getContent() { return content; } - public void setType(String type) - { + public void setType(String type) { this.type = type; } - public String getType() - { + public String getType() { return type; } - public void setRelatedId(String relatedId) - { + public void setRelatedId(String relatedId) { this.relatedId = relatedId; } - public String getRelatedId() - { + public String getRelatedId() { return relatedId; } - public void setIsRead(Integer isRead) - { + // ========== 新增:certId 的 getter/setter ========== + public Long getCertId() { + return certId; + } + + public void setCertId(Long certId) { + this.certId = certId; + } + + public void setIsRead(Integer isRead) { this.isRead = isRead; } - public Integer getIsRead() - { + public Integer getIsRead() { return isRead; } - public void setRemindLevel(Integer remindLevel) - { + public String getIsReadLabel() { + return isReadLabel; + } + + public void setIsReadLabel(String isReadLabel) { + this.isReadLabel = isReadLabel; + } + + public void setRemindLevel(Integer remindLevel) { this.remindLevel = remindLevel; } - public Integer getRemindLevel() - { + public Integer getRemindLevel() { return remindLevel; } - public void setReadTime(Date readTime) - { + public String getRemindLevelLabel() { + return remindLevelLabel; + } + + public void setRemindLevelLabel(String remindLevelLabel) { + this.remindLevelLabel = remindLevelLabel; + } + + public void setReadTime(Date readTime) { this.readTime = readTime; } - public Date getReadTime() - { + public Date getReadTime() { return readTime; } @Override public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("id", getId()) .append("userId", getUserId()) .append("title", getTitle()) .append("content", getContent()) .append("type", getType()) .append("relatedId", getRelatedId()) + .append("certId", getCertId()) .append("isRead", getIsRead()) .append("remindLevel", getRemindLevel()) .append("createTime", getCreateTime()) diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetPersonalInfo.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetPersonalInfo.java index 9d420bc..5dae64b 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetPersonalInfo.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetPersonalInfo.java @@ -3,11 +3,13 @@ package com.chenhai.vet.domain; import com.chenhai.common.annotation.Excel; import com.chenhai.common.core.domain.BaseEntity; import com.chenhai.common.core.domain.entity.SysUser; +import com.chenhai.common.utils.StringUtils; import com.fasterxml.jackson.annotation.JsonFormat; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import java.util.Date; +import java.util.Map; /** * 兽医个人信息对象 vet_personal_info @@ -111,6 +113,12 @@ public class VetPersonalInfo extends BaseEntity @Excel(name = "头像路径") private String avatar; + /** 综合审核状态(动态计算,不存数据库) */ + private String overallAuditStatus; + + /** 扩展参数(用于存储额外的统计信息) */ + private Map params; + // 添加getter和setter public void setId(Long id) { @@ -330,6 +338,45 @@ public class VetPersonalInfo extends BaseEntity this.avatar = avatar; } + public String getOverallAuditStatus() { + return overallAuditStatus; + } + + public void setOverallAuditStatus(String overallAuditStatus) { + this.overallAuditStatus = overallAuditStatus; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + /** + * 获取展示用的审核状态(综合状态优先) + */ + public String getDisplayAuditStatus() { + if (StringUtils.isNotEmpty(overallAuditStatus)) { + return overallAuditStatus; + } + return auditStatus; + } + + /** + * 获取展示用的审核状态标签 + */ + public String getDisplayAuditStatusLabel() { + String status = getDisplayAuditStatus(); + if (status == null) return "未知"; + switch (status) { + case "0": return "待审核"; + case "1": return "已通过"; + case "2": return "已拒绝"; + default: return "未知"; + } + } @Override public String toString() { @@ -357,6 +404,8 @@ public class VetPersonalInfo extends BaseEntity .append("nickName", getNickName()) .append("avatar", getAvatar()) .append("user", getUser()) + .append("overallAuditStatus", getOverallAuditStatus()) + .append("params", getParams()) .toString(); } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java index a906c8d..08c22d9 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java @@ -15,8 +15,6 @@ import org.slf4j.LoggerFactory; import java.text.SimpleDateFormat; import java.util.*; - - /** * 兽医资质对象 vet_qualification(合并证书功能) * @@ -62,12 +60,11 @@ public class VetQualification extends BaseEntity private String certificateFiles; /** 申请时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Excel(name = "申请时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date applyTime; /** 审核时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @Excel(name = "审核时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date auditTime; @@ -139,12 +136,20 @@ public class VetQualification extends BaseEntity private String scopeNamesLabel; private String certStatusLabel; - /** 证书JSON字符串(数据库字段) */ + /** 证书JSON字符串(数据库字段)- 添加 @JsonIgnore 隐藏此字段 */ + @JsonIgnore private String certificatesJson; - /** 证书列表(从JSON解析而来) */ + /** 证书列表(从JSON解析而来,用于前端展示) */ + @JsonProperty("certificates") + private List> certificates; + + /** 证书列表(从JSON解析而来,用于业务逻辑) */ private transient List certificateList; + // 日期格式化器 + private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd"); + /** * 证书信息内部类 */ @@ -294,6 +299,168 @@ public class VetQualification extends BaseEntity } } + // ==================== 新增的证书展示方法 ==================== + + /** + * 获取证书列表(用于前端展示) + * 确保返回的证书中包含 issueDate 和 expireDate 字段 + */ + @JsonProperty("certificates") + public List> getCertificates() { + if (certificates != null) { + return certificates; + } + + if (StringUtils.isEmpty(certificatesJson)) { + return new ArrayList<>(); + } + + try { + certificates = objectMapper.readValue( + certificatesJson, + objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class) + ); + +// // 为每个证书补充日期字段 +// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); +// for (Map cert : certificates) { +// // 如果 JSON 中没有 issueDate,从主表获取(注意使用 getter 方法) +// if (!cert.containsKey("issueDate") || cert.get("issueDate") == null) { +// // 使用 getIssueDate() 方法而不是直接访问字段 +// Date issueDateValue = getIssueDate(); +// if (issueDateValue != null) { +// cert.put("issueDate", sdf.format(issueDateValue)); +// System.out.println("从主表补充 issueDate: " + sdf.format(issueDateValue)); +// } +// } else { +// Object issueDateObj = cert.get("issueDate"); +// if (issueDateObj instanceof Date) { +// cert.put("issueDate", sdf.format((Date) issueDateObj)); +// } +// } +// +// // 如果 JSON 中没有 expireDate,从主表获取 +// if (!cert.containsKey("expireDate") || cert.get("expireDate") == null) { +// Date expireDateValue = getExpireDate(); +// if (expireDateValue != null) { +// cert.put("expireDate", sdf.format(expireDateValue)); +// System.out.println("从主表补充 expireDate: " + sdf.format(expireDateValue)); +// } +// } else { +// Object expireDateObj = cert.get("expireDate"); +// if (expireDateObj instanceof Date) { +// cert.put("expireDate", sdf.format((Date) expireDateObj)); +// } +// } +// } + + return certificates; + } catch (Exception e) { + log.error("解析证书JSON失败", e); + return new ArrayList<>(); + } + } + + /** + * 设置证书列表 + * 确保日期字段被正确保存到 JSON 中 + */ + public void setCertificates(List> certificates) { + this.certificates = certificates; + if (certificates != null && !certificates.isEmpty()) { + try { + List> certMapList = new ArrayList<>(); + + for (Map cert : certificates) { + Map certMap = new HashMap<>(); + certMap.put("certName", cert.get("certName")); + certMap.put("certificateNo", cert.get("certificateNo")); + certMap.put("issueOrg", cert.get("issueOrg")); + certMap.put("certificateFiles", cert.get("certificateFiles")); + + // 处理发证日期 + Object issueDateObj = cert.get("issueDate"); + if (issueDateObj != null) { + if (issueDateObj instanceof Date) { + certMap.put("issueDate", dateFormatter.format((Date) issueDateObj)); + } else { + certMap.put("issueDate", issueDateObj.toString()); + } + } + + // 处理到期日期 + Object expireDateObj = cert.get("expireDate"); + if (expireDateObj != null) { + if (expireDateObj instanceof Date) { + certMap.put("expireDate", dateFormatter.format((Date) expireDateObj)); + } else { + certMap.put("expireDate", expireDateObj.toString()); + } + } + + // 处理证书ID + Object certIdObj = cert.get("certId"); + if (certIdObj != null) { + if (certIdObj instanceof Number) { + certMap.put("certId", ((Number) certIdObj).longValue()); + } else { + try { + certMap.put("certId", Long.parseLong(certIdObj.toString())); + } catch (Exception e) { + certMap.put("certId", generateSafeCertificateId()); + } + } + } else { + certMap.put("certId", generateSafeCertificateId()); + } + + // 处理证书状态 + if (cert.containsKey("certStatus") && cert.get("certStatus") != null) { + certMap.put("certStatus", cert.get("certStatus")); + } + + certMapList.add(certMap); + } + + this.certificatesJson = objectMapper.writeValueAsString(certMapList); + + // 更新主表字段 + Map firstCert = certMapList.get(0); + this.certName = (String) firstCert.get("certName"); + this.certificateNo = (String) firstCert.get("certificateNo"); + this.issueOrg = (String) firstCert.get("issueOrg"); + this.certificateFiles = (String) firstCert.get("certificateFiles"); + + // 解析日期 + String issueDateStr = (String) firstCert.get("issueDate"); + if (issueDateStr != null && !issueDateStr.isEmpty()) { + try { + this.issueDate = dateFormatter.parse(issueDateStr); + } catch (Exception e) {} + } + + String expireDateStr = (String) firstCert.get("expireDate"); + if (expireDateStr != null && !expireDateStr.isEmpty()) { + try { + this.expireDate = dateFormatter.parse(expireDateStr); + } catch (Exception e) {} + } + + if (firstCert.get("certId") instanceof Number) { + this.certId = ((Number) firstCert.get("certId")).longValue(); + } + if (firstCert.get("certStatus") != null) { + this.certStatus = (String) firstCert.get("certStatus"); + } + + } catch (Exception e) { + log.error("序列化证书列表失败", e); + } + } + } + + // ==================== 原有的证书列表方法 ==================== + /** * 获取证书列表 - 从certificatesJson解析 */ @@ -321,14 +488,18 @@ public class VetQualification extends BaseEntity if (issueDateObj instanceof String) { try { - cert.setIssueDate(new SimpleDateFormat("yyyy-MM-dd").parse((String) issueDateObj)); + cert.setIssueDate(dateFormatter.parse((String) issueDateObj)); } catch (Exception e) {} + } else if (issueDateObj instanceof Date) { + cert.setIssueDate((Date) issueDateObj); } if (expireDateObj instanceof String) { try { - cert.setExpireDate(new SimpleDateFormat("yyyy-MM-dd").parse((String) expireDateObj)); + cert.setExpireDate(dateFormatter.parse((String) expireDateObj)); } catch (Exception e) {} + } else if (expireDateObj instanceof Date) { + cert.setExpireDate((Date) expireDateObj); } cert.setQualificationId(this.qualificationId); @@ -347,7 +518,6 @@ public class VetQualification extends BaseEntity } catch (Exception e) {} } - // 修复这里:确保ID不为null且不为0,否则使用稳定ID生成器 if (certificateId == null || certificateId == 0) { certificateId = generateSafeCertificateId(); } @@ -382,32 +552,23 @@ public class VetQualification extends BaseEntity return certificateList; } + /** * 生成安全的证书ID(避免JavaScript精度丢失) */ - private Long generateSafeCertificateId() { - // 当前毫秒时间戳(13位) long timestamp = System.currentTimeMillis(); - - // 取时间戳的后12位(确保在安全范围内) - long id = timestamp % 1000000000000L; // 12位数字 - - // 加上1亿,确保是9位数以上 + long id = timestamp % 1000000000000L; id += 100000000L; - - // 双重检查:确保不超过JavaScript安全上限 if (id > MAX_SAFE_ID) { - // 如果超过,取模回到安全范围 id = id % (MAX_SAFE_ID - 100000000L) + 100000000L; } - return id; } + /** * 设置证书列表,并同步更新JSON字段 */ - public void setCertificateList(List certificateList) { this.certificateList = certificateList; @@ -423,16 +584,13 @@ public class VetQualification extends BaseEntity certMap.put("certificateFiles", cert.getCertificateFiles()); if (cert.getIssueDate() != null) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - certMap.put("issueDate", sdf.format(cert.getIssueDate())); + certMap.put("issueDate", dateFormatter.format(cert.getIssueDate())); } if (cert.getExpireDate() != null) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - certMap.put("expireDate", sdf.format(cert.getExpireDate())); + certMap.put("expireDate", dateFormatter.format(cert.getExpireDate())); } - // 确保每个证书都有ID if (cert.getCertificateId() == null || cert.getCertificateId() == 0) { cert.setCertificateId(generateSafeCertificateId()); } @@ -448,6 +606,9 @@ public class VetQualification extends BaseEntity this.certificatesJson = objectMapper.writeValueAsString(certMapList); + // 同时设置 certificates 字段供前端使用 + this.certificates = certMapList; + // 更新主表字段 if (!certificateList.isEmpty()) { CertificateInfo firstCert = certificateList.get(0); @@ -500,6 +661,8 @@ public class VetQualification extends BaseEntity } } + // ==================== 经营范围处理 ==================== + @JsonProperty("scopeIds") public void setScopeIdsFromJson(List scopeIdList) { if (scopeIdList != null && !scopeIdList.isEmpty()) { @@ -526,6 +689,8 @@ public class VetQualification extends BaseEntity this.scopeIds = scopeIds; } + // ==================== 基础 Getter/Setter ==================== + public Long getQualificationId() { return qualificationId; } @@ -750,6 +915,7 @@ public class VetQualification extends BaseEntity this.certStatusLabel = certStatusLabel; } + @JsonIgnore public String getCertificatesJson() { return certificatesJson; } @@ -758,58 +924,6 @@ public class VetQualification extends BaseEntity this.certificatesJson = certificatesJson; } - @JsonIgnore - public List> getCertificates() { - if (StringUtils.isEmpty(certificatesJson)) { - return new ArrayList<>(); - } - - try { - return objectMapper.readValue( - certificatesJson, - objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class) - ); - } catch (Exception e) { - log.error("解析certificatesJson失败", e); - return new ArrayList<>(); - } - } - - /** - * 设置证书列表(兼容性方法,转换为certificatesJson存储) - */ - public void setCertificates(List> certificates) { - if (certificates != null && !certificates.isEmpty()) { - try { - this.certificatesJson = objectMapper.writeValueAsString(certificates); - - // 更新主表字段 - Map firstCert = certificates.get(0); - this.certName = (String) firstCert.get("certName"); - this.certificateNo = (String) firstCert.get("certificateNo"); - this.issueOrg = (String) firstCert.get("issueOrg"); - this.certificateFiles = (String) firstCert.get("certificateFiles"); - - Object issueDateObj = firstCert.get("issueDate"); - Object expireDateObj = firstCert.get("expireDate"); - - if (issueDateObj instanceof String) { - try { - this.issueDate = new SimpleDateFormat("yyyy-MM-dd").parse((String) issueDateObj); - } catch (Exception e) {} - } - - if (expireDateObj instanceof String) { - try { - this.expireDate = new SimpleDateFormat("yyyy-MM-dd").parse((String) expireDateObj); - } catch (Exception e) {} - } - } catch (Exception e) { - log.error("序列化证书列表失败", e); - } - } - } - @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) @@ -842,8 +956,6 @@ public class VetQualification extends BaseEntity .append("updateBy", getUpdateBy()) .append("updateTime", getUpdateTime()) .append("remark", getRemark()) - .append("certificatesJson", getCertificatesJson()) .toString(); } - -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/VetUnifiedInfoDTO.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/VetUnifiedInfoDTO.java index 0a8b9ae..1cd8414 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/VetUnifiedInfoDTO.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/VetUnifiedInfoDTO.java @@ -208,6 +208,10 @@ public class VetUnifiedInfoDTO { } public String getGender() { + // 如果性别是 "0" 或空字符串,返回 null + if (gender == null || "0".equals(gender) || "".equals(gender.trim())) { + return null; + } return gender; } @@ -240,6 +244,10 @@ public class VetUnifiedInfoDTO { } public String getWorkExperience() { + // 如果工作经验是 "0" 或空字符串,返回 null + if (workExperience == null || "0".equals(workExperience) || "".equals(workExperience.trim())) { + return null; + } return workExperience; } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCommentsServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCommentsServiceImpl.java index 4c42a00..a513fd5 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCommentsServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCommentsServiceImpl.java @@ -1,6 +1,8 @@ package com.chenhai.vet.service.impl; import java.util.List; +import java.util.Map; +import java.util.HashMap; import com.chenhai.common.core.domain.entity.SysUser; import com.chenhai.common.core.domain.model.LoginUser; @@ -60,10 +62,8 @@ public class VetCommentsServiceImpl implements IVetCommentsService comment.setImages(parseImagesFromJsonString(comment.getImages())); } - // 如果查询时字段为空,尝试填充兽医信息 - if (comment != null && (StringUtils.isEmpty(comment.getTitle()) || - StringUtils.isEmpty(comment.getHospital()) || - StringUtils.isEmpty(comment.getExperience()))) { + // 尝试填充兽医信息(包括专家类型和擅长领域) + if (comment != null) { fillVetInfoToComment(comment); } return comment; @@ -125,7 +125,7 @@ public class VetCommentsServiceImpl implements IVetCommentsService vetComments.setAvatar(loginUser.getUser().getAvatar()); } - // 自动填充兽医职称、医院和经验信息到数据库字段中 + // 自动填充兽医职称、医院、经验、专家类型、擅长领域信息到数据库字段中 vetComments = autoFillVetInfoToFields(vetComments, loginUser.getUserId()); } @@ -386,8 +386,7 @@ public class VetCommentsServiceImpl implements IVetCommentsService } /** - * 自动填充兽医职称、医院和经验信息到数据库字段 - * 这是主要方法,将信息填充到实体的 title、hospital、experience 字段中 + * 自动填充兽医职称、医院、经验、专家类型、擅长领域信息到数据库字段 * * @param vetComments 兽医回复对象 * @param userId 兽医用户ID @@ -399,6 +398,9 @@ public class VetCommentsServiceImpl implements IVetCommentsService VetPersonalInfo vetInfo = vetPersonalInfoService.selectVetPersonalInfoByUserId(userId); if (vetInfo != null) { + log.info("获取到兽医个人信息 - userId: {}, expertType: {}, specialty: {}", + userId, vetInfo.getExpertType(), vetInfo.getSpecialty()); + // 直接设置到实体字段中 if (StringUtils.isNotEmpty(vetInfo.getTitle())) { vetComments.setTitle(vetInfo.getTitle()); @@ -412,9 +414,24 @@ public class VetCommentsServiceImpl implements IVetCommentsService vetComments.setExperience(vetInfo.getWorkExperience()); } - log.info("已自动填充兽医信息到字段:职称={}, 医院={}, 经验={}", - vetInfo.getTitle(), vetInfo.getHospital(), vetInfo.getWorkExperience()); + // ========== 关键:填充专家类型和擅长领域 ========== + if (StringUtils.isNotEmpty(vetInfo.getExpertType())) { + vetComments.setExpertType(vetInfo.getExpertType()); + log.info("已填充专家类型: {}", vetInfo.getExpertType()); + } else { + log.warn("兽医专家类型为空 - userId: {}", userId); + } + if (StringUtils.isNotEmpty(vetInfo.getSpecialty())) { + vetComments.setSpecialty(vetInfo.getSpecialty()); + log.info("已填充擅长领域: {}", vetInfo.getSpecialty()); + } else { + log.warn("兽医擅长领域为空 - userId: {}", userId); + } + + log.info("已自动填充兽医信息到字段:职称={}, 医院={}, 经验={}, 专家类型={}, 擅长领域={}", + vetComments.getTitle(), vetComments.getHospital(), vetComments.getExperience(), + vetComments.getExpertType(), vetComments.getSpecialty()); } else { log.warn("用户ID:{} 未找到兽医个人信息", userId); @@ -428,8 +445,8 @@ public class VetCommentsServiceImpl implements IVetCommentsService } /** - * 为已有的评论记录填充兽医信息 - * 用于查询时,如果发现字段为空,从兽医表补充信息 + * 为已有的评论记录填充兽医信息(包括专家类型和擅长领域) + * 用于查询时,从兽医表补充信息 */ private void fillVetInfoToComment(VetComments comment) { if (comment == null || comment.getUserId() == null) { @@ -437,19 +454,15 @@ public class VetCommentsServiceImpl implements IVetCommentsService } try { - // 如果字段已经存在,跳过 - if (StringUtils.isNotEmpty(comment.getTitle()) && - StringUtils.isNotEmpty(comment.getHospital()) && - StringUtils.isNotEmpty(comment.getExperience())) { - return; - } - // 获取兽医个人信息 VetPersonalInfo vetInfo = vetPersonalInfoService.selectVetPersonalInfoByUserId(comment.getUserId()); if (vetInfo != null) { boolean needUpdate = false; + log.info("填充兽医信息到评论 - 评论ID: {}, userId: {}, expertType: {}, specialty: {}", + comment.getId(), comment.getUserId(), vetInfo.getExpertType(), vetInfo.getSpecialty()); + // 检查并填充缺失的字段 if (StringUtils.isEmpty(comment.getTitle()) && StringUtils.isNotEmpty(vetInfo.getTitle())) { comment.setTitle(vetInfo.getTitle()); @@ -466,6 +479,19 @@ public class VetCommentsServiceImpl implements IVetCommentsService needUpdate = true; } + // ========== 关键:填充专家类型和擅长领域 ========== + if (StringUtils.isEmpty(comment.getExpertType()) && StringUtils.isNotEmpty(vetInfo.getExpertType())) { + comment.setExpertType(vetInfo.getExpertType()); + needUpdate = true; + log.info("填充专家类型: {}", vetInfo.getExpertType()); + } + + if (StringUtils.isEmpty(comment.getSpecialty()) && StringUtils.isNotEmpty(vetInfo.getSpecialty())) { + comment.setSpecialty(vetInfo.getSpecialty()); + needUpdate = true; + log.info("填充擅长领域: {}", vetInfo.getSpecialty()); + } + // 如果补充了信息,更新数据库 if (needUpdate) { VetComments updateData = new VetComments(); @@ -473,10 +499,14 @@ public class VetCommentsServiceImpl implements IVetCommentsService updateData.setTitle(comment.getTitle()); updateData.setHospital(comment.getHospital()); updateData.setExperience(comment.getExperience()); + updateData.setExpertType(comment.getExpertType()); + updateData.setSpecialty(comment.getSpecialty()); vetCommentsMapper.updateVetComments(updateData); log.info("已为历史回复记录补充兽医信息,评论ID:{}", comment.getId()); } + } else { + log.warn("未找到兽医个人信息 - userId: {}", comment.getUserId()); } } catch (Exception e) { @@ -485,7 +515,7 @@ public class VetCommentsServiceImpl implements IVetCommentsService } /** - * 获取兽医信息标签(用于前端显示) + * 获取兽医信息标签(用于前端显示)- 包含专家类型和擅长领域 */ public String getVetInfoTags(Long userId) { try { @@ -506,6 +536,16 @@ public class VetCommentsServiceImpl implements IVetCommentsService tags.append("执业").append(vetInfo.getWorkExperience()).append(""); } + // 添加专家类型标签 + if (StringUtils.isNotEmpty(vetInfo.getExpertType())) { + tags.append("").append(getExpertTypeLabel(vetInfo.getExpertType())).append(""); + } + + // 添加擅长领域标签 + if (StringUtils.isNotEmpty(vetInfo.getSpecialty())) { + tags.append("擅长:").append(vetInfo.getSpecialty()).append(""); + } + return tags.toString(); } } catch (Exception e) { @@ -515,6 +555,47 @@ public class VetCommentsServiceImpl implements IVetCommentsService return ""; } + /** + * 获取专家类型标签 + */ + private String getExpertTypeLabel(String expertType) { + if (StringUtils.isEmpty(expertType)) { + return ""; + } + switch (expertType) { + case "资深专家": + return "🌟 资深专家"; + case "高级专家": + return "⭐ 高级专家"; + case "普通专家": + return "👨‍⚕️ 普通专家"; + default: + return expertType; + } + } + + /** + * 获取兽医完整信息Map(用于前端显示) + */ + public Map getVetInfoMap(Long userId) { + Map infoMap = new HashMap<>(); + try { + VetPersonalInfo vetInfo = vetPersonalInfoService.selectVetPersonalInfoByUserId(userId); + if (vetInfo != null) { + infoMap.put("title", vetInfo.getTitle()); + infoMap.put("hospital", vetInfo.getHospital()); + infoMap.put("experience", vetInfo.getWorkExperience()); + infoMap.put("expertType", vetInfo.getExpertType()); + infoMap.put("specialty", vetInfo.getSpecialty()); + infoMap.put("avatar", vetInfo.getAvatar()); + infoMap.put("realName", vetInfo.getRealName()); + } + } catch (Exception e) { + log.error("获取兽医信息失败,用户ID:{}", userId, e); + } + return infoMap; + } + /** * 根据问诊单ID获取回复列表(包含兽医信息) */ @@ -647,10 +728,12 @@ public class VetCommentsServiceImpl implements IVetCommentsService vetComments.setAvatar(currentUser.getAvatar()); } - // 自动填充兽医信息(如果字段为空) + // 自动填充兽医信息(如果字段为空)- 包括专家类型和擅长领域 if (StringUtils.isEmpty(vetComments.getTitle()) || StringUtils.isEmpty(vetComments.getHospital()) || - StringUtils.isEmpty(vetComments.getExperience())) { + StringUtils.isEmpty(vetComments.getExperience()) || + StringUtils.isEmpty(vetComments.getExpertType()) || + StringUtils.isEmpty(vetComments.getSpecialty())) { autoFillVetInfoToFields(vetComments, currentUserId); } } @@ -732,4 +815,4 @@ public class VetCommentsServiceImpl implements IVetCommentsService log.info("---"); } } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java index ff144d4..0b2b76f 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java @@ -42,12 +42,94 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService } /** - * 查询兽医文章列表 + * 查询兽医文章列表(带数据权限过滤) + * 管理员和muhu能看到所有,vet只能看到自己的 */ @Override public List selectVetKnowledgeList(VetKnowledge vetKnowledge) { - return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + // 获取当前登录用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || loginUser.getUser() == null) { + // 未登录,返回空列表 + return new ArrayList<>(); + } + + SysUser currentUser = loginUser.getUser(); + Long userId = currentUser.getUserId(); + + // 判断角色权限 + boolean isAdmin = SecurityUtils.hasRole("admin"); + boolean isMuhu = SecurityUtils.hasRole("muhu"); + boolean isManger = SecurityUtils.hasRole("manger"); + boolean isVet = SecurityUtils.hasRole("vet"); + + // 管理员、muhu、manger可以看到所有文章(不添加数据过滤) + if (isAdmin || isMuhu || isManger) { + // 直接查询所有,不添加用户过滤条件 + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + // vet只能看到自己创建的文章 + else if (isVet) { + // 设置创建人ID或创建人名称进行过滤 + // 方式1:通过用户ID过滤(推荐,如果表中有user_id字段) + if (vetKnowledge.getUserId() == null) { + vetKnowledge.setUserId(userId); + } + + // 方式2:通过创建人名称过滤(如果使用create_by字段) + // String username = currentUser.getUserName(); + // vetKnowledge.setCreateBy(username); + + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + + // 其他角色返回空列表 + return new ArrayList<>(); + } + + /** + * 查询已发布且审核通过的兽医文章列表 + * 只返回状态为已发布(1)且审核通过(2)的文章 + * 权限控制:muhu和vet可以看到已发布的文章 + */ + @Override + public List selectPublishedKnowledgeList(VetKnowledge vetKnowledge) + { + // 强制设置查询条件为已发布且审核通过 + vetKnowledge.setArticleStatus("1"); // 已发布 + vetKnowledge.setAuditStatus("2"); // 审核通过 + + // 获取当前登录用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || loginUser.getUser() == null) { + // 未登录用户只能看到公开的已发布文章 + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + + SysUser currentUser = loginUser.getUser(); + Long userId = currentUser.getUserId(); + + // 判断角色权限 + boolean isAdmin = SecurityUtils.hasRole("admin"); + boolean isMuhu = SecurityUtils.hasRole("muhu"); + boolean isManger = SecurityUtils.hasRole("manger"); + boolean isVet = SecurityUtils.hasRole("vet"); + + // 管理员、muhu、manger可以看到所有已发布的文章 + if (isAdmin || isMuhu || isManger) { + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + // vet只能看到自己发布的已通过审核的文章 + else if (isVet) { + // 添加用户过滤条件 + vetKnowledge.setUserId(userId); + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + // 其他角色只能看到所有已发布的文章(不添加用户过滤) + else { + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } } /** @@ -86,6 +168,9 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService vetKnowledge.setNickName(currentUser.getUserName()); } + // 设置创建人 + vetKnowledge.setCreateBy(currentUser.getUserName()); + // 5. 设置用户头像 String avatar = currentUser.getAvatar(); if (avatar != null && !avatar.isEmpty()) { @@ -101,6 +186,7 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService if (user != null) { vetKnowledge.setNickName(user.getNickName() != null ? user.getNickName() : user.getUserName()); vetKnowledge.setAvatar(user.getAvatar()); + vetKnowledge.setCreateBy(user.getUserName()); System.out.println("从数据库获取用户信息成功 - nickName: " + vetKnowledge.getNickName()); } } @@ -174,17 +260,11 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService continue; } - // 检查是否是自己的文章(通过创建者判断) - String createBy = article.getCreateBy(); - String currentUsername = SecurityUtils.getUsername(); - - if (createBy == null || !createBy.equals(currentUsername)) { - // 如果不是自己的文章,检查是否是管理员 - if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里 - failedCount++; - failedMessages.add("文章ID " + id + " 不是您发布的文章,无法删除"); - continue; - } + // 检查是否有权限删除 + if (!hasDeletePermission(article, currentUserId)) { + failedCount++; + failedMessages.add("文章ID " + id + " 没有权限删除"); + continue; } // 执行删除 @@ -231,15 +311,9 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService return AjaxResult.error("文章不存在"); } - // 检查是否是自己的文章(通过创建者判断) - String createBy = article.getCreateBy(); - String currentUsername = SecurityUtils.getUsername(); - - if (createBy == null || !createBy.equals(currentUsername)) { - // 如果不是自己的文章,检查是否是管理员 - if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里 - return AjaxResult.error("不是您发布的文章,无法删除"); - } + // 检查是否有权限删除 + if (!hasDeletePermission(article, currentUserId)) { + return AjaxResult.error("没有权限删除该文章"); } int result = vetKnowledgeMapper.deleteVetKnowledgeById(id); @@ -253,6 +327,39 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService return AjaxResult.error("删除失败: " + e.getMessage()); } } + + /** + * 检查是否有删除权限 + * @param article 文章对象 + * @param currentUserId 当前用户ID + * @return true:有权限 false:无权限 + */ + private boolean hasDeletePermission(VetKnowledge article, Long currentUserId) { + // 管理员、muhu、manger可以删除任何文章 + if (SecurityUtils.hasRole("admin") || + SecurityUtils.hasRole("muhu") || + SecurityUtils.hasRole("manger")) { + return true; + } + + // vet只能删除自己的文章 + if (SecurityUtils.hasRole("vet")) { + Long articleUserId = article.getUserId(); + if (articleUserId != null && articleUserId.equals(currentUserId)) { + return true; + } + + // 兼容通过create_by字段判断 + String createBy = article.getCreateBy(); + String currentUsername = SecurityUtils.getUsername(); + if (createBy != null && createBy.equals(currentUsername)) { + return true; + } + } + + return false; + } + /** * 提交审核:将审核状态改为审核中 */ @@ -265,6 +372,12 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService if (current == null) { return AjaxResult.error("文章不存在"); } + + // 检查是否是自己的文章 + if (!isOwner(current)) { + return AjaxResult.error("只能提交自己创建的文章进行审核"); + } + // 只有草稿状态(0)且待审核状态(0)的文章才能提交审核 if (!"0".equals(current.getArticleStatus())) { return AjaxResult.error("只有草稿状态的文章可以提交审核"); @@ -301,17 +414,23 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService } /** - * 审核文章 + * 审核文章(只有管理员、muhu、manger可以审核) */ @Override public AjaxResult auditVetKnowledge(Long id, String auditStatus, String auditComment) { try { + // 检查权限:只有管理员、muhu、manger可以审核 + if (!SecurityUtils.hasRole("admin") && + !SecurityUtils.hasRole("muhu") && + !SecurityUtils.hasRole("manger")) { + return AjaxResult.error("没有权限审核文章"); + } + VetKnowledge current = vetKnowledgeMapper.selectVetKnowledgeById(id); if (current == null) { return AjaxResult.error("文章不存在"); } - // 只有审核中状态(1)才能进行审核 if (!"1".equals(current.getAuditStatus())) { return AjaxResult.error("只有审核中状态的文章可以审核"); @@ -354,6 +473,11 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService return AjaxResult.error("文章不存在"); } + // 检查是否是自己的文章 + if (!isOwner(current)) { + return AjaxResult.error("只能发布自己创建的文章"); + } + // 只有审核通过(2)且为草稿状态(0)的文章才能发布 if (!"2".equals(current.getAuditStatus())) { return AjaxResult.error("只有审核通过的文章可以发布"); @@ -395,6 +519,12 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService if (current == null) { return AjaxResult.error("文章不存在"); } + + // 检查是否是自己的文章 + if (!isOwner(current)) { + return AjaxResult.error("只能上架自己创建的文章"); + } + // 只有已下架状态(2)的文章才能上架 if (!"2".equals(current.getArticleStatus())) { return AjaxResult.error("只有已下架的文章可以上架"); @@ -435,6 +565,11 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService return AjaxResult.error("文章不存在"); } + // 检查是否是自己的文章 + if (!isOwner(current)) { + return AjaxResult.error("只能下架自己创建的文章"); + } + // 只有已发布状态(1)的文章才能下架 if (!"1".equals(current.getArticleStatus())) { return AjaxResult.error("只有已发布的文章可以下架"); @@ -473,18 +608,6 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService } } - /** - * 查询已发布且审核通过的兽医文章列表 - * 只返回状态为已发布(1)且审核通过(2)的文章 - */ - @Override - public List selectPublishedKnowledgeList(VetKnowledge vetKnowledge) { - // 强制设置查询条件为已发布且审核通过 - vetKnowledge.setArticleStatus("1"); // 已发布 - vetKnowledge.setAuditStatus("2"); // 审核通过 - return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); - } - /** * 增加文章查看次数 */ @@ -506,4 +629,31 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService return 0; } } -} \ No newline at end of file + + /** + * 检查当前用户是否是文章所有者 + */ + private boolean isOwner(VetKnowledge article) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || loginUser.getUser() == null) { + return false; + } + + Long currentUserId = loginUser.getUser().getUserId(); + Long articleUserId = article.getUserId(); + + // 通过user_id判断 + if (articleUserId != null && articleUserId.equals(currentUserId)) { + return true; + } + + // 通过create_by判断 + String createBy = article.getCreateBy(); + String currentUsername = loginUser.getUsername(); + if (createBy != null && createBy.equals(currentUsername)) { + return true; + } + + return false; + } +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java index f98a55b..b0e3f36 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java @@ -138,46 +138,32 @@ public class VetNotificationServiceImpl implements VetNotificationService { return false; } - // 添加 markAllAsRead 方法 - /*@Override - public void markAsRead(Long userId) { - try { - // 使用Mapper提供的方法批量标记为已读 - int result = vetNotificationMapper.markAllNotificationsAsRead(userId); - log.info("用户ID={} 已将所有通知标记为已读,影响记录数={}", userId, result); - } catch (Exception e) { - log.error("标记所有通知为已读失败,用户ID={}", userId, e); - // 如果批量操作失败,尝试逐条更新 - fallbackMarkAllAsRead(userId); - } + @Override + public List selectByUserId(Long userId) { + return vetNotificationMapper.selectVetNotificationByUserId(userId); } -*/ - /** - * 回退方案:逐条更新通知为已读 - */ - private void fallbackMarkAllAsRead(Long userId) { - try { - VetNotification query = new VetNotification(); - query.setUserId(userId); - List notifications = vetNotificationMapper.selectVetNotificationList(query); - int count = 0; - for (VetNotification notification : notifications) { - if (notification.getIsRead() == 0) { - notification.setIsRead(1); - notification.setReadTime(new Date()); - vetNotificationMapper.updateVetNotification(notification); - count++; - } - } - log.info("回退方案:用户ID={} 已成功标记{}个通知为已读", userId, count); - } catch (Exception e) { - log.error("回退方案标记通知为已读也失败,用户ID={}", userId, e); - } + @Override + public Map getNotificationStats(Long userId) { + Map stats = vetNotificationMapper.selectNotificationStatsByUserId(userId); + return Map.of( + "unread", ((Number) stats.getOrDefault("unread", 0)).intValue(), + "read", ((Number) stats.getOrDefault("read", 0)).intValue() + ); + } + + @Override + public int getUnreadCount(Long userId) { + VetNotification query = new VetNotification(); + query.setUserId(userId); + query.setIsRead(0); + List unreadNotifications = vetNotificationMapper.selectVetNotificationList(query); + return unreadNotifications.size(); } /** * 创建证书通知对象 + * 修改:添加 certId 字段设置 */ private VetNotification createCertificateNotification(VetQualification qualification, VetQualification.CertificateInfo certificate, @@ -191,6 +177,9 @@ public class VetNotificationServiceImpl implements VetNotificationService { certificate.getCertificateId() != null ? certificate.getCertificateId() : 0L); notification.setRelatedId(relatedId); + // ========== 关键修改:单独设置 certId 字段 ========== + notification.setCertId(certificate.getCertificateId()); // 设置证书ID + notification.setType("CERT_EXPIRE_REMIND"); notification.setTitle(title); notification.setContent(content); @@ -199,6 +188,9 @@ public class VetNotificationServiceImpl implements VetNotificationService { notification.setCreateTime(new Date()); notification.setCreateBy("system"); + log.debug("创建证书通知 - userId: {}, certId: {}, relatedId: {}", + qualification.getUserId(), certificate.getCertificateId(), relatedId); + return notification; } @@ -209,8 +201,8 @@ public class VetNotificationServiceImpl implements VetNotificationService { try { int result = vetNotificationMapper.insertVetNotification(notification); if (result > 0) { - log.info("成功发送证书提醒通知:用户ID={}, 标题={}", - notification.getUserId(), notification.getTitle()); + log.info("成功发送证书提醒通知:用户ID={}, 证书ID={}, 标题={}", + notification.getUserId(), notification.getCertId(), notification.getTitle()); } } catch (Exception e) { log.error("发送证书提醒通知失败:错误信息={}", e.getMessage(), e); @@ -254,28 +246,27 @@ public class VetNotificationServiceImpl implements VetNotificationService { return sdf.format(date); } - @Override - public List selectByUserId(Long userId) { - return vetNotificationMapper.selectVetNotificationByUserId(userId); - } - - @Override - public Map getNotificationStats(Long userId) { - // 查询统计信息 - Map stats = vetNotificationMapper.selectNotificationStatsByUserId(userId); - - return Map.of( - "unread", ((Number) stats.getOrDefault("unread", 0)).intValue(), - "read", ((Number) stats.getOrDefault("read", 0)).intValue() - ); - } + /** + * 回退方案:逐条更新通知为已读 + */ + private void fallbackMarkAllAsRead(Long userId) { + try { + VetNotification query = new VetNotification(); + query.setUserId(userId); + List notifications = vetNotificationMapper.selectVetNotificationList(query); - @Override - public int getUnreadCount(Long userId) { - VetNotification query = new VetNotification(); - query.setUserId(userId); - query.setIsRead(0); - List unreadNotifications = vetNotificationMapper.selectVetNotificationList(query); - return unreadNotifications.size(); + int count = 0; + for (VetNotification notification : notifications) { + if (notification.getIsRead() == 0) { + notification.setIsRead(1); + notification.setReadTime(new Date()); + vetNotificationMapper.updateVetNotification(notification); + count++; + } + } + log.info("回退方案:用户ID={} 已成功标记{}个通知为已读", userId, count); + } catch (Exception e) { + log.error("回退方案标记通知为已读也失败,用户ID={}", userId, e); + } } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetPersonalInfoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetPersonalInfoServiceImpl.java index e3f117e..22a8311 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetPersonalInfoServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetPersonalInfoServiceImpl.java @@ -114,14 +114,14 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { // 1. 先查询原始数据 List list = vetPersonalInfoMapper.selectVetPersonalInfoList(vetPersonalInfo); - // 2. 强制为每个记录同步头像 + // 2. 强制为每个记录同步完整的用户信息(头像、昵称、手机号、邮箱、性别) if (list != null && !list.isEmpty()) { for (VetPersonalInfo info : list) { try { - // 直接调用同步方法 - syncAvatarFromUser(info); + // 使用增强后的 fillUserInfo 方法,同步所有用户信息 + fillUserInfo(info); } catch (Exception e) { - System.err.println("同步头像失败,ID: " + info.getId() + ", 错误: " + e.getMessage()); + System.err.println("同步用户信息失败,ID: " + info.getId() + ", 错误: " + e.getMessage()); } } } @@ -212,11 +212,16 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { } } - // 4. 设置创建者和更新者 + // 4. 设置审核状态(新注册默认待审核) + if (StringUtils.isEmpty(vetPersonalInfo.getAuditStatus())) { + vetPersonalInfo.setAuditStatus("0"); // 默认待审核 + } + + // 5. 设置创建者和更新者 vetPersonalInfo.setCreateBy(loginUser.getUsername()); vetPersonalInfo.setUpdateBy(loginUser.getUsername()); - // 5. 从用户表获取信息(优先使用用户表数据) + // 6. 从用户表获取信息(优先使用用户表数据) SysUser currentUser = sysUserService.selectUserById(loginUser.getUserId()); if (currentUser != null) { // 头像:强制使用用户表头像 @@ -245,13 +250,11 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { } } - // 6. 设置创建时间和更新时间 + // 7. 设置创建时间和更新时间 vetPersonalInfo.setCreateTime(DateUtils.getNowDate()); vetPersonalInfo.setUpdateTime(DateUtils.getNowDate()); int result = vetPersonalInfoMapper.insertVetPersonalInfo(vetPersonalInfo); - - // 7. 新增时不同步头像到用户表(以用户表为准) return result; } else { throw new RuntimeException("用户未登录"); @@ -273,6 +276,9 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { throw new RuntimeException("无权限修改其他用户的兽医信息"); } + // 检查信息是否发生变化 + boolean infoChanged = isInfoChanged(existing, vetPersonalInfo); + String newAvatar = vetPersonalInfo.getAvatar(); String oldAvatar = existing != null ? existing.getAvatar() : null; boolean avatarChanged = newAvatar != null && !newAvatar.equals(oldAvatar); @@ -281,12 +287,23 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { vetPersonalInfo.setUpdateBy(loginUser.getUsername()); vetPersonalInfo.setUpdateTime(DateUtils.getNowDate()); + // 如果信息发生变化,重置审核状态为待审核 + if (infoChanged || avatarChanged) { + vetPersonalInfo.setAuditStatus("0"); + System.out.println("兽医信息已修改,审核状态重置为待审核 - 兽医ID: " + vetPersonalInfo.getId()); + } + int result = vetPersonalInfoMapper.updateVetPersonalInfo(vetPersonalInfo); // 头像同步并刷新缓存 if (result > 0 && avatarChanged && StringUtils.isNotEmpty(newAvatar)) { syncAvatarToUserTable(loginUser.getUserId(), newAvatar); - refreshUserCache(loginUser); // 刷新缓存 + refreshUserCache(loginUser); + } + + // ========== 新增:如果修改了关键信息,同时重置所有资质的审核状态 ========== + if (result > 0 && (infoChanged || avatarChanged)) { + resetQualificationsAuditStatus(vetPersonalInfo.getUserId()); } return result; @@ -295,6 +312,54 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { } } + /** + * 重置用户所有资质的审核状态 + */ + private void resetQualificationsAuditStatus(Long userId) { + try { + VetQualification query = new VetQualification(); + query.setUserId(userId); + List qualifications = vetQualificationMapper.selectVetQualificationList(query); + + for (VetQualification qualification : qualifications) { + // 重置资质审核状态 + qualification.setAuditStatus("0"); +// qualification.setUpdateTime(new Date()); + qualification.setUpdateBy(SecurityUtils.getUsername()); + vetQualificationMapper.updateVetQualification(qualification); + } + + System.out.println("已重置用户所有资质的审核状态 - 用户ID: " + userId + ", 数量: " + qualifications.size()); + } catch (Exception e) { + System.err.println("重置资质审核状态失败: " + e.getMessage()); + } + } + + /** + * 判断兽医信息是否发生变化 + */ + private boolean isInfoChanged(VetPersonalInfo existing, VetPersonalInfo newInfo) { + if (existing == null || newInfo == null) { + return true; + } + + // 比较关键字段是否发生变化 + if (!StringUtils.equals(existing.getNickName(), newInfo.getNickName())) return true; + if (!StringUtils.equals(existing.getRealName(), newInfo.getRealName())) return true; + if (!StringUtils.equals(existing.getGender(), newInfo.getGender())) return true; + if (!StringUtils.equals(existing.getPhone(), newInfo.getPhone())) return true; + if (!StringUtils.equals(existing.getEmail(), newInfo.getEmail())) return true; + if (!StringUtils.equals(existing.getIdCard(), newInfo.getIdCard())) return true; +// if (!StringUtils.equals(existing.getPracticeLicenseNo(), newInfo.getPracticeLicenseNo())) return true; +// if (!StringUtils.equals(existing.getHospitalName(), newInfo.getHospitalName())) return true; +// if (!StringUtils.equals(existing.getHospitalAddress(), newInfo.getHospitalAddress())) return true; + if (!StringUtils.equals(existing.getSpecialty(), newInfo.getSpecialty())) return true; + if (!StringUtils.equals(existing.getIntroduction(), newInfo.getIntroduction())) return true; +// if (existing.getYearsOfExperience() != newInfo.getYearsOfExperience()) return true; + + return false; + } + /** * 刷新用户缓存 - 使用RedisCache */ @@ -541,8 +606,28 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { */ private void fillUserInfo(VetPersonalInfo vetInfo) { if (vetInfo != null && vetInfo.getUserId() != null) { - // 直接调用头像同步方法 - syncAvatarFromUser(vetInfo); + SysUser user = sysUserService.selectUserById(vetInfo.getUserId()); + if (user != null) { + // 只设置用户对象,不更新数据库 + vetInfo.setUser(user); + + // 只同步到内存对象,不更新数据库 + if (StringUtils.isNotEmpty(user.getAvatar())) { + vetInfo.setAvatar(user.getAvatar()); + } + if (StringUtils.isEmpty(vetInfo.getNickName()) && StringUtils.isNotEmpty(user.getNickName())) { + vetInfo.setNickName(user.getNickName()); + } + if (StringUtils.isEmpty(vetInfo.getPhone()) && StringUtils.isNotEmpty(user.getPhonenumber())) { + vetInfo.setPhone(user.getPhonenumber()); + } + if (StringUtils.isEmpty(vetInfo.getEmail()) && StringUtils.isNotEmpty(user.getEmail())) { + vetInfo.setEmail(user.getEmail()); + } + if (StringUtils.isEmpty(vetInfo.getGender()) && StringUtils.isNotEmpty(user.getSex())) { + vetInfo.setGender(user.getSex()); + } + } } } @@ -589,4 +674,4 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService { System.out.println("批量同步完成,成功: " + successCount + " 条"); } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java index df1a0a4..a5dc85d 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java @@ -3,7 +3,9 @@ package com.chenhai.vet.service.impl; import com.chenhai.common.exception.ServiceException; import com.chenhai.common.utils.SecurityUtils; import com.chenhai.common.utils.StringUtils; +import com.chenhai.vet.domain.VetPersonalInfo; import com.chenhai.vet.domain.VetQualification; +import com.chenhai.vet.mapper.VetPersonalInfoMapper; import com.chenhai.vet.mapper.VetQualificationMapper; import com.chenhai.vet.service.IVetQualificationService; import com.fasterxml.jackson.databind.ObjectMapper; @@ -26,124 +28,29 @@ public class VetQualificationServiceImpl implements IVetQualificationService { @Autowired private JdbcTemplate jdbcTemplate; - // 添加ObjectMapper用于JSON处理 - private final ObjectMapper objectMapper = new ObjectMapper(); + @Autowired + private VetPersonalInfoMapper vetPersonalInfoMapper; + private final ObjectMapper objectMapper = new ObjectMapper(); private static final Logger log = LoggerFactory.getLogger(VetQualificationServiceImpl.class); - - // 日期格式化 private final SimpleDateFormat dateFormat; public VetQualificationServiceImpl() { dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); } // ==================== 基础CRUD方法 ==================== - /** - * 查询兽医资质列表 - */ - // 在 VetQualificationServiceImpl 中修改 selectVetQualificationList 方法 @Override public List selectVetQualificationList(VetQualification vetQualification) { List list = vetQualificationMapper.selectVetQualificationList(vetQualification); for (VetQualification qualification : list) { processQualificationInfo(qualification); - // 确保解析certificatesJson到certificateList - if (StringUtils.isNotEmpty(qualification.getCertificatesJson())) { - try { - List certificateList = parseCertificateInfoList(qualification.getCertificatesJson()); - qualification.setCertificateList(certificateList); - } catch (Exception e) { - log.error("解析证书JSON失败, qualificationId: {}", qualification.getQualificationId(), e); - qualification.setCertificateList(new ArrayList<>()); - } - } } return list; } - /** - * 解析证书JSON到CertificateInfo列表 - */ - /** - * 解析证书JSON到CertificateInfo列表 - */ - private List parseCertificateInfoList(String certificatesJson) throws Exception { - List> certMaps = objectMapper.readValue( - certificatesJson, - objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class) - ); - - List certificateList = new ArrayList<>(); - for (Map certMap : certMaps) { - VetQualification.CertificateInfo cert = new VetQualification.CertificateInfo(); - - // 设置证书ID - Long certId = extractLongFromObject(certMap.get("certId")); - cert.setCertificateId(certId != null ? certId : generateCertificateId()); - - // 设置基本字段 - cert.setCertName((String) certMap.get("certName")); - cert.setCertificateNo((String) certMap.get("certificateNo")); - cert.setIssueOrg((String) certMap.get("issueOrg")); - cert.setCertificateFiles((String) certMap.get("certificateFiles")); - - // 解析日期 - cert.setIssueDate(parseDate(certMap.get("issueDate"))); - cert.setExpireDate(parseDate(certMap.get("expireDate"))); - - // 计算证书状态 - String certStatus = calculateCertificateStatus(cert.getExpireDate()); - cert.setCertStatus(certStatus); - - certificateList.add(cert); - } - return certificateList; - } - - /** - * 获取证书状态标签 - */ - private String getCertStatusLabel(String certStatus) { - if (certStatus == null) return "未知"; - switch (certStatus) { - case "0": return "正常"; - case "1": return "即将过期"; - case "2": return "已过期"; - default: return "未知"; - } - } - - /** - * 获取审核状态标签 - */ - private String getAuditStatusLabel(String auditStatus) { - if (auditStatus == null) return "未知"; - switch (auditStatus) { - case "0": return "待审核"; - case "1": return "审核通过"; - case "2": return "审核不通过"; - default: return "未知"; - } - } - - /** - * 获取资格类型标签 - */ - private String getQualificationTypeLabel(String qualificationType) { - if (qualificationType == null) return "未知"; - switch (qualificationType) { - case "1": return "执业兽医师"; - case "2": return "执业助理兽医师"; - case "3": return "乡村兽医"; - default: return "未知"; - } - } - /** - * 查询兽医资质 - */ @Override public VetQualification selectVetQualificationByQualificationId(Long qualificationId) { VetQualification qualification = vetQualificationMapper.selectVetQualificationByQualificationId(qualificationId); @@ -153,36 +60,60 @@ public class VetQualificationServiceImpl implements IVetQualificationService { return qualification; } - /** - * 新增兽医资质 - */ @Override public int insertVetQualification(VetQualification vetQualification) { - // 准备保存前的处理 - prepareQualificationForSave(vetQualification); + VetQualification existing = vetQualificationMapper.selectVetQualificationByUserId(vetQualification.getUserId()); - // 执行插入 - int result = vetQualificationMapper.insertVetQualification(vetQualification); + if (existing != null) { + log.info("用户 {} 已有资质记录,在原资质中添加新证书", vetQualification.getUserId()); - // 成功插入后,为用户分配兽医未审核角色 - if (result > 0 && vetQualification.getUserId() != null) { - assignVetUnapprovedRole(vetQualification.getUserId()); - } + List existingCertList = existing.getCertificateList(); + List newCertList = vetQualification.getCertificateList(); - return result; - } + if (newCertList != null && !newCertList.isEmpty()) { + for (VetQualification.CertificateInfo newCert : newCertList) { + if (newCert.getCertificateId() == null) { + newCert.setCertificateId(generateSafeCertificateId()); + } + existingCertList.add(newCert); + } + } + existing.setCertificateList(existingCertList); + + if (StringUtils.isNotEmpty(vetQualification.getRealName())) { + existing.setRealName(vetQualification.getRealName()); + } + if (StringUtils.isNotEmpty(vetQualification.getIdCard())) { + existing.setIdCard(vetQualification.getIdCard()); + } + + existing.setAuditStatus("0"); + existing.setApplyTime(new Date()); + existing.setUpdateBy(SecurityUtils.getUsername()); + existing.setUpdateTime(new Date()); + + return vetQualificationMapper.updateVetQualification(existing); + } else { + log.info("用户 {} 没有资质记录,执行新增操作", vetQualification.getUserId()); + + prepareQualificationForSave(vetQualification); + int result = vetQualificationMapper.insertVetQualification(vetQualification); + + if (result > 0 && vetQualification.getUserId() != null) { + assignVetUnapprovedRole(vetQualification.getUserId()); + } + + return result; + } + } - /** - * 修改兽医资质 - 处理审核状态变更时的角色切换 - */ @Override public int updateVetQualification(VetQualification vetQualification) { if (vetQualification.getQualificationId() == null) { throw new ServiceException("资质ID不能为空"); } - // 获取更新前的资质信息 VetQualification existing = vetQualificationMapper.selectVetQualificationByQualificationId( vetQualification.getQualificationId() ); @@ -194,165 +125,118 @@ public class VetQualificationServiceImpl implements IVetQualificationService { String newStatus = vetQualification.getAuditStatus(); Long userId = existing.getUserId(); - // 更新基本信息 updateBasicQualificationInfo(existing, vetQualification); - - // 处理证书更新 processCertificateUpdate(existing, vetQualification); - // 设置更新信息 existing.setUpdateBy(SecurityUtils.getUsername()); existing.setUpdateTime(new Date()); - - // 更新证书状态 updateCertificateStatus(existing); int result = vetQualificationMapper.updateVetQualification(existing); - // 处理审核通过时的角色变更 if (result > 0 && userId != null && newStatus != null) { handleRoleChangeOnAudit(userId, oldStatus, newStatus); + updateVetPersonalAuditStatus(userId); } return result; } + // ==================== 核心方法:处理资质信息 ==================== /** - * 为用户分配兽医未审核角色 + * 处理资质信息(填充经营范围名称、解析证书列表) */ - private void assignVetUnapprovedRole(Long userId) { - try { - // 检查是否已有兽医未审核角色 - String checkSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6"; - Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId); - - // 如果没有,则分配兽医未审核角色 - if (count == null || count == 0) { - String insertSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)"; - jdbcTemplate.update(insertSql, userId); - } - } catch (Exception e) { - // 忽略异常,不影响主要业务 - } - } - - /** - * 处理审核状态变更时的角色切换 - */ - private void handleRoleChangeOnAudit(Long userId, String oldStatus, String newStatus) { - try { - // 1. 审核通过:状态变为1 - if ("1".equals(newStatus)) { - changeRoleToVet(userId); - } - // 2. 审核不通过或待审核:状态变为2或0,且之前是通过状态 - else if (("0".equals(newStatus) || "2".equals(newStatus)) && "1".equals(oldStatus)) { - changeRoleToVetUnapproved(userId); - } - } catch (Exception e) { - // 角色切换失败不影响主要业务 - } - } - - - /** - * 切换为兽医角色(审核通过) - */ - private void changeRoleToVet(Long userId) { - try { - System.out.println("========== changeRoleToVet 被调用了 =========="); - System.out.println("userId = " + userId); - System.out.println("当前时间 = " + new Date()); - // 1. 先删除兽医未审核角色 - String deleteUnapprovedSql = "DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 6"; - jdbcTemplate.update(deleteUnapprovedSql, userId); - - // 2. 检查是否已有兽医角色 - String checkVetSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 4"; - Integer vetCount = jdbcTemplate.queryForObject(checkVetSql, Integer.class, userId); - - // 3. 如果没有兽医角色,则添加 - if (vetCount == null || vetCount == 0) { - String addVetSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 4)"; - jdbcTemplate.update(addVetSql, userId); - } - } catch (Exception e) { - // 忽略异常 + private void processQualificationInfo(VetQualification qualification) { + // 1. 处理经营范围名称 + if (StringUtils.isNotEmpty(qualification.getScopeIds())) { + String scopeNames = getScopeNamesFromDict(qualification.getScopeIds()); + qualification.setScopeNames(scopeNames); + qualification.setScopeNamesLabel(scopeNames); } - } - - /* *//** - * 发送重新登录通知 - *//* - private void sendReloginNotification(Long userId) { - try { - log.info("用户 {} 角色已变更,建议重新登录以刷新权限", userId); - String message = "您的兽医资质已审核通过,角色已更新为兽医。请重新登录系统以使用新角色的功能。"; - log.info("通知消息: {}", message); + // 2. 解析证书JSON到证书列表 + if (StringUtils.isNotEmpty(qualification.getCertificatesJson())) { + try { + // 解析为 Map 列表 + List> certList = objectMapper.readValue( + qualification.getCertificatesJson(), + objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class) + ); + qualification.setCertificates(certList); + + // 解析为 CertificateInfo 列表 + List certificateInfoList = new ArrayList<>(); + + for (Map certMap : certList) { + VetQualification.CertificateInfo cert = new VetQualification.CertificateInfo(); + + // 证书ID + Long certId = extractLongFromObject(certMap.get("certId")); + cert.setCertificateId(certId != null ? certId : generateCertificateId()); + + // 基本字段 + cert.setCertName((String) certMap.get("certName")); + cert.setCertificateNo((String) certMap.get("certificateNo")); + cert.setIssueOrg((String) certMap.get("issueOrg")); + cert.setCertificateFiles((String) certMap.get("certificateFiles")); + + // 日期解析 + Object issueDateObj = certMap.get("issueDate"); + if (issueDateObj != null) { + Date issueDate = parseDate(issueDateObj); + cert.setIssueDate(issueDate); + } - } catch (Exception e) { - log.warn("发送通知失败: {}", e.getMessage()); - } - }*/ + Object expireDateObj = certMap.get("expireDate"); + if (expireDateObj != null) { + Date expireDate = parseDate(expireDateObj); + cert.setExpireDate(expireDate); + } - /** - * 清除用户权限缓存(可选) - */ - private void clearUserAuthorizationCache(Long userId) { - try { - // 根据你的缓存实现来清理 - // 例如:如果使用Redis,清理对应的缓存key - } catch (Exception e) { - // 忽略异常 - } - } + // 证书状态 + if (certMap.containsKey("certStatus") && certMap.get("certStatus") != null) { + cert.setCertStatus((String) certMap.get("certStatus")); + } else { + cert.setCertStatus(calculateCertificateStatus(cert.getExpireDate())); + } + certificateInfoList.add(cert); + } - /** - * 切换为兽医未审核角色(审核不通过或待审核) - */ - private void changeRoleToVetUnapproved(Long userId) { - try { - // 1. 先删除兽医角色 - String deleteVetSql = "DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 4"; - jdbcTemplate.update(deleteVetSql, userId); + qualification.setCertificateList(certificateInfoList); + log.debug("解析证书成功 - qualificationId: {}, 证书数量: {}", + qualification.getQualificationId(), certificateInfoList.size()); - // 2. 检查是否已有兽医未审核角色 - String checkSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6"; - Integer unapprovedCount = jdbcTemplate.queryForObject(checkSql, Integer.class, userId); + // 设置主表第一个证书的状态 + String firstCertStatus = "0"; + if (!certificateInfoList.isEmpty()) { + firstCertStatus = certificateInfoList.get(0).getCertStatus(); + } + qualification.setCertStatus(firstCertStatus); + qualification.setCertStatusLabel(getCertStatusLabel(firstCertStatus)); - // 3. 如果没有兽医未审核角色,则添加 - if (unapprovedCount == null || unapprovedCount == 0) { - String addSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)"; - jdbcTemplate.update(addSql, userId); + } catch (Exception e) { + log.error("解析证书JSON失败, qualificationId: {}", qualification.getQualificationId(), e); + qualification.setCertificates(new ArrayList<>()); + qualification.setCertificateList(new ArrayList<>()); + qualification.setCertStatus("0"); + qualification.setCertStatusLabel("正常"); } - } catch (Exception e) { - // 忽略异常 + } else { + qualification.setCertificates(new ArrayList<>()); + qualification.setCertificateList(new ArrayList<>()); + qualification.setCertStatus("0"); + qualification.setCertStatusLabel("正常"); } - } - /** - * 批量删除兽医资质 - */ - @Override - public int deleteVetQualificationByQualificationIds(Long[] qualificationIds) { - return vetQualificationMapper.deleteVetQualificationByQualificationIds(qualificationIds); - } - /** - * 删除兽医资质信息 - */ - @Override - public int deleteVetQualificationByQualificationId(Long qualificationId) { - return vetQualificationMapper.deleteVetQualificationByQualificationId(qualificationId); + // 3. 设置状态标签 + qualification.setAuditStatusLabel(getAuditStatusLabel(qualification.getAuditStatus())); + qualification.setQualificationTypeLabel(getQualificationTypeLabel(qualification.getQualificationType())); } - // ==================== 业务方法 ==================== + // ==================== 其他业务方法 ==================== - /** - * 根据用户ID查询资质证书列表 - */ @Override public List selectQualificationsByUserId(Long userId) { VetQualification query = new VetQualification(); @@ -360,20 +244,13 @@ public class VetQualificationServiceImpl implements IVetQualificationService { return selectVetQualificationList(query); } - /** - * 根据证书ID查询证书及所属资质信息 - */ @Override public Map selectCertificateWithQualificationByCertId(Long certId, Long userId) { try { - // 1. 查询用户有权限查看的所有资质 List qualifications; - if (userId == null) { - // userId为null时表示管理员查询,但这里应该传入实际用户ID throw new ServiceException("用户ID不能为空"); } else { - // 普通用户只查询自己的资质 VetQualification query = new VetQualification(); query.setUserId(userId); qualifications = vetQualificationMapper.selectVetQualificationList(query); @@ -386,26 +263,20 @@ public class VetQualificationServiceImpl implements IVetQualificationService { try { List> certificates = parseCertificatesJson(qualification.getCertificatesJson()); - for (Map certMap : certificates) { Long foundCertId = extractLongFromObject(certMap.get("certId")); - if (foundCertId != null && foundCertId.equals(certId)) { - // 权限验证:确保证书属于当前用户 if (!qualification.getUserId().equals(userId)) { throw new ServiceException("无权查看此证书"); } - return buildCertificateResult(qualification, certMap, foundCertId); } } } catch (Exception e) { - // 解析JSON失败,继续下一个资质 + // 继续下一个资质 } } - return null; - } catch (Exception e) { if (e instanceof ServiceException) { throw e; @@ -414,25 +285,17 @@ public class VetQualificationServiceImpl implements IVetQualificationService { } } - /** - * 提交资质审核(新方法,处理复杂数据结构) - */ @Override public int submitQualification(Map requestData) { VetQualification qualification = convertRequestToQualification(requestData); qualification.setUserId(SecurityUtils.getUserId()); qualification.setCreateBy(SecurityUtils.getUsername()); - if (qualification.getCertId() == null) { qualification.setCertId(generateCertificateId()); } - return insertVetQualification(qualification); } - /** - * 手动检查证书 - */ @Override public void manualCheckCertificates(Long userId) { List qualifications = selectQualificationsByUserId(userId); @@ -442,9 +305,6 @@ public class VetQualificationServiceImpl implements IVetQualificationService { } } - /** - * 获取证书统计信息 - */ @Override public Map getCertificateStatistics(Long userId) { List qualifications = selectQualificationsByUserId(userId); @@ -455,255 +315,230 @@ public class VetQualificationServiceImpl implements IVetQualificationService { calendar.add(Calendar.DAY_OF_YEAR, 30); Date thirtyDaysLater = calendar.getTime(); - calendar.setTime(today); - calendar.add(Calendar.DAY_OF_YEAR, 7); - Date sevenDaysLater = calendar.getTime(); - - int totalCertificates = 0; - int expiring = 0; - int expired = 0; - int expiringSoon = 0; + int totalCertificates = 0, expiring = 0, expired = 0; for (VetQualification qual : qualifications) { List certs = qual.getCertificateList(); totalCertificates += certs.size(); - for (VetQualification.CertificateInfo cert : certs) { if (cert.getExpireDate() != null) { if (cert.getExpireDate().before(today)) { expired++; } else if (cert.getExpireDate().before(thirtyDaysLater)) { expiring++; - if (cert.getExpireDate().before(sevenDaysLater)) { - expiringSoon++; - } } } } } int normal = totalCertificates - expiring - expired; - Map statistics = new HashMap<>(); statistics.put("total", totalCertificates); statistics.put("normal", normal); statistics.put("expiring", expiring); statistics.put("expired", expired); - statistics.put("expiringSoon", expiringSoon); statistics.put("qualificationCount", qualifications.size()); - - // 设置警告级别 - if (expired > 0) { - statistics.put("warningLevel", "DANGER"); - } else if (expiring > 0 || expiringSoon > 0) { - statistics.put("warningLevel", "WARNING"); - } else { - statistics.put("warningLevel", "NORMAL"); - } + statistics.put("warningLevel", expired > 0 ? "DANGER" : (expiring > 0 ? "WARNING" : "NORMAL")); return statistics; } - // ==================== 工具方法 ==================== + @Override + public List selectExpiringQualifications(Long userId) { + Date today = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(today); + calendar.add(Calendar.DAY_OF_YEAR, 30); + Date thirtyDaysLater = calendar.getTime(); - /** - * 处理资质信息(填充经营范围名称、更新证书状态) - */ - /** - * 处理资质信息(填充经营范围名称、更新证书状态、解析证书列表) - */ - private void processQualificationInfo(VetQualification qualification) { - // 1. 处理经营范围名称 - if (StringUtils.isNotEmpty(qualification.getScopeIds())) { - String scopeNames = getScopeNamesFromDict(qualification.getScopeIds()); - qualification.setScopeNames(scopeNames); - qualification.setScopeNamesLabel(scopeNames); // 设置标签字段 - } + List allQualifications = selectQualificationsByUserId(userId); + return allQualifications.stream() + .filter(qual -> qual.getExpireDate() != null && + !qual.getExpireDate().before(today) && + !qual.getExpireDate().after(thirtyDaysLater)) + .toList(); + } - // 2. 解析证书JSON到证书列表 - if (StringUtils.isNotEmpty(qualification.getCertificatesJson())) { - try { - List certificateList = parseCertificateInfoList(qualification.getCertificatesJson()); - qualification.setCertificateList(certificateList); + @Override + public void checkAndSendCertificateReminders() { + // 提醒逻辑(暂不实现) + } + + @Override + public int deleteVetQualificationByQualificationIds(Long[] qualificationIds) { + return vetQualificationMapper.deleteVetQualificationByQualificationIds(qualificationIds); + } + + @Override + public int deleteVetQualificationByQualificationId(Long qualificationId) { + return vetQualificationMapper.deleteVetQualificationByQualificationId(qualificationId); + } + + @Override + public VetQualification selectVetQualificationById(Long qualificationId) { + return vetQualificationMapper.selectVetQualificationById(qualificationId); + } + + // ==================== 私有辅助方法 ==================== - // 3. 更新每个证书的状态 - String firstCertStatus = "0"; // 默认正常 - Date today = new Date(); + private void updateVetPersonalAuditStatus(Long userId) { + try { + VetPersonalInfo vetInfo = vetPersonalInfoMapper.selectVetPersonalInfoByUserId(userId); + if (vetInfo == null) return; - for (VetQualification.CertificateInfo cert : certificateList) { - String certStatus = calculateCertificateStatus(cert.getExpireDate()); - cert.setCertStatus(certStatus); + VetQualification query = new VetQualification(); + query.setUserId(userId); + List qualifications = vetQualificationMapper.selectVetQualificationList(query); - // 记录第一个证书的状态(用于主表显示) - if (cert == certificateList.get(0)) { - firstCertStatus = certStatus; + boolean hasPending = false, hasRejected = false; + for (VetQualification qualification : qualifications) { + String status = qualification.getAuditStatus(); + if ("0".equals(status)) hasPending = true; + else if ("2".equals(status)) hasRejected = true; + + List> certificates = qualification.getCertificates(); + if (certificates != null) { + for (Map cert : certificates) { + String certStatus = (String) cert.get("auditStatus"); + if ("0".equals(certStatus)) hasPending = true; + else if ("2".equals(certStatus)) hasRejected = true; } } + } - // 4. 设置主表的证书状态(用于列表显示) - qualification.setCertStatus(firstCertStatus); - qualification.setCertStatusLabel(getCertStatusLabel(firstCertStatus)); - - } catch (Exception e) { - log.error("解析证书JSON失败, qualificationId: {}", qualification.getQualificationId(), e); - qualification.setCertificateList(new ArrayList<>()); - qualification.setCertStatus("0"); - qualification.setCertStatusLabel("正常"); + String newPersonalStatus = hasPending ? "0" : (hasRejected ? "2" : "1"); + if (!newPersonalStatus.equals(vetInfo.getAuditStatus())) { + VetPersonalInfo updateInfo = new VetPersonalInfo(); + updateInfo.setId(vetInfo.getId()); + updateInfo.setAuditStatus(newPersonalStatus); + updateInfo.setUpdateTime(new Date()); + updateInfo.setUpdateBy(SecurityUtils.getUsername()); + vetPersonalInfoMapper.updateVetPersonalInfo(updateInfo); + log.info("兽医个人信息审核状态已更新 - 用户ID: {}, 新状态: {}", userId, newPersonalStatus); } - } else { - qualification.setCertificateList(new ArrayList<>()); - qualification.setCertStatus("0"); - qualification.setCertStatusLabel("正常"); + } catch (Exception e) { + log.error("更新兽医个人信息审核状态失败", e); } + } - // 5. 设置审核状态标签 - qualification.setAuditStatusLabel(getAuditStatusLabel(qualification.getAuditStatus())); + private void assignVetUnapprovedRole(Long userId) { + try { + String checkSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6"; + Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId); + if (count == null || count == 0) { + String insertSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)"; + jdbcTemplate.update(insertSql, userId); + } + } catch (Exception e) { + // 忽略 + } + } - // 6. 设置资格类型标签 - qualification.setQualificationTypeLabel(getQualificationTypeLabel(qualification.getQualificationType())); + private void handleRoleChangeOnAudit(Long userId, String oldStatus, String newStatus) { + try { + if ("1".equals(newStatus)) { + changeRoleToVet(userId); + } else if (("0".equals(newStatus) || "2".equals(newStatus)) && "1".equals(oldStatus)) { + changeRoleToVetUnapproved(userId); + } + } catch (Exception e) { + // 忽略 + } } + private void changeRoleToVet(Long userId) { + try { + jdbcTemplate.update("DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 6", userId); + Integer vetCount = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 4", Integer.class, userId); + if (vetCount == null || vetCount == 0) { + jdbcTemplate.update("INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 4)", userId); + } + } catch (Exception e) { + // 忽略 + } + } + private void changeRoleToVetUnapproved(Long userId) { + try { + jdbcTemplate.update("DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 4", userId); + Integer unapprovedCount = jdbcTemplate.queryForObject( + "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6", Integer.class, userId); + if (unapprovedCount == null || unapprovedCount == 0) { + jdbcTemplate.update("INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)", userId); + } + } catch (Exception e) { + // 忽略 + } + } - /** - * 准备保存前的资质数据 - */ private void prepareQualificationForSave(VetQualification qualification) { - // 1. 如果certId为空,生成一个 if (qualification.getCertId() == null) { qualification.setCertId(generateCertificateId()); } - - // 2. 处理基本信息 if (StringUtils.isEmpty(qualification.getRealName())) { qualification.setRealName("未知"); } - - // 3. 处理审核状态 if (qualification.getAuditStatus() == null) { - qualification.setAuditStatus("0"); // 0表示待审核 - } - - // 4. 处理经营范围 - if (qualification.getScopeIds() != null && !qualification.getScopeIds().isEmpty()) { - String scopeIdsStr = processScopeIds(qualification.getScopeIds()); - qualification.setScopeIds(scopeIdsStr); - - String scopeNames = getScopeNamesFromDict(scopeIdsStr); - qualification.setScopeNames(scopeNames); - } - - // 5. 处理证书信息 - if (qualification.getCertificatesJson() != null) { - extractFilePathsFromJson(qualification); + qualification.setAuditStatus("0"); } - - // 6. 设置默认提醒天数 if (qualification.getRemindDays() == null) { qualification.setRemindDays(30); } - - // 7. 验证并设置证书状态 - updateCertificateStatus(qualification); - - // 8. 设置创建时间 if (qualification.getCreateTime() == null) { qualification.setCreateTime(new Date()); } - - // 9. 设置申请时间(用于审核) if (qualification.getApplyTime() == null) { qualification.setApplyTime(new Date()); } + updateCertificateStatus(qualification); } - /** - * 更新资质基本信息 - */ private void updateBasicQualificationInfo(VetQualification existing, VetQualification update) { - if (StringUtils.isNotEmpty(update.getRealName())) { - existing.setRealName(update.getRealName()); - } - if (StringUtils.isNotEmpty(update.getIdCard())) { - existing.setIdCard(update.getIdCard()); - } - if (StringUtils.isNotEmpty(update.getQualificationType())) { - existing.setQualificationType(update.getQualificationType()); - } + if (StringUtils.isNotEmpty(update.getRealName())) existing.setRealName(update.getRealName()); + if (StringUtils.isNotEmpty(update.getIdCard())) existing.setIdCard(update.getIdCard()); + if (StringUtils.isNotEmpty(update.getQualificationType())) existing.setQualificationType(update.getQualificationType()); if (StringUtils.isNotEmpty(update.getScopeIds())) { existing.setScopeIds(update.getScopeIds()); String scopeNames = getScopeNamesFromDict(update.getScopeIds()); existing.setScopeNames(scopeNames); } - - // 更新审核相关字段 - if (StringUtils.isNotEmpty(update.getAuditStatus())) { - existing.setAuditStatus(update.getAuditStatus()); - } - if (StringUtils.isNotEmpty(update.getAuditOpinion())) { - existing.setAuditOpinion(update.getAuditOpinion()); - } - if (update.getAuditTime() != null) { - existing.setAuditTime(update.getAuditTime()); - } - if (update.getAuditorId() != null) { - existing.setAuditorId(update.getAuditorId()); - } + if (StringUtils.isNotEmpty(update.getAuditStatus())) existing.setAuditStatus(update.getAuditStatus()); + if (StringUtils.isNotEmpty(update.getAuditOpinion())) existing.setAuditOpinion(update.getAuditOpinion()); + if (update.getAuditTime() != null) existing.setAuditTime(update.getAuditTime()); + if (update.getAuditorId() != null) existing.setAuditorId(update.getAuditorId()); } - /** - * 处理证书更新 - */ private void processCertificateUpdate(VetQualification existing, VetQualification update) { - // 获取要更新的证书信息 List> certificatesToUpdate = getCertificatesToUpdate(update); - if (certificatesToUpdate == null || certificatesToUpdate.isEmpty()) { - return; - } + if (certificatesToUpdate == null || certificatesToUpdate.isEmpty()) return; - // 获取现有的证书列表 List existingCertList = existing.getCertificateList(); Map existingCertMap = new HashMap<>(); - for (VetQualification.CertificateInfo cert : existingCertList) { if (cert.getCertificateId() != null) { existingCertMap.put(cert.getCertificateId(), cert); } } - // 处理证书更新 List updatedCertList = new ArrayList<>(); - for (Map certMap : certificatesToUpdate) { Long certificateId = extractLongFromObject(certMap.get("certId")); - - if (certificateId != null) { - // 更新现有证书 - VetQualification.CertificateInfo existingCert = existingCertMap.get(certificateId); - if (existingCert != null) { - VetQualification.CertificateInfo updatedCert = updateCertificateInfo(existingCert, certMap); - updatedCertList.add(updatedCert); - existingCertMap.remove(certificateId); - } else { - // 新增证书 - VetQualification.CertificateInfo newCert = createCertificateFromMap(certMap); - updatedCertList.add(newCert); - } + if (certificateId != null && existingCertMap.containsKey(certificateId)) { + VetQualification.CertificateInfo updatedCert = updateCertificateInfo(existingCertMap.get(certificateId), certMap); + updatedCertList.add(updatedCert); + existingCertMap.remove(certificateId); } else { - // 新增证书(没有certId) VetQualification.CertificateInfo newCert = createCertificateFromMap(certMap); - newCert.setCertificateId(generateCertificateId()); + if (certificateId == null) { + newCert.setCertificateId(generateCertificateId()); + } updatedCertList.add(newCert); } } - - // 添加未被修改的原有证书 updatedCertList.addAll(existingCertMap.values()); - // 更新证书列表到资质对象 existing.setCertificateList(updatedCertList); - - // 更新主表字段(使用第一个证书的信息) if (!updatedCertList.isEmpty()) { VetQualification.CertificateInfo firstCert = updatedCertList.get(0); existing.setCertName(firstCert.getCertName()); @@ -717,62 +552,17 @@ public class VetQualificationServiceImpl implements IVetQualificationService { } } - // ==================== 工具方法(小功能) ==================== - - private Long generateCertificateId() { - return generateSafeCertificateId(); - } - - /** - * 生成安全的证书ID(与VetQualification中的方法保持一致) - */ - private Long generateSafeCertificateId() { - // JavaScript安全整数上限 2^53-1 - final long MAX_SAFE_ID = 9007199254740991L; - final long MIN_SAFE_ID = 100000000L; // 最小9位数 - - // 当前毫秒时间戳(13位) - long timestamp = System.currentTimeMillis(); - - // 取时间戳的后12位(确保在安全范围内) - long id = timestamp % 1000000000000L; // 12位数字 - - // 加上1亿,确保是9位数以上 - id += MIN_SAFE_ID; - - // 双重检查:确保不超过JavaScript安全上限 - if (id > MAX_SAFE_ID) { - // 如果超过,取模回到安全范围 - id = id % (MAX_SAFE_ID - MIN_SAFE_ID) + MIN_SAFE_ID; - } - - // 添加随机性确保唯一性 - Random random = new Random(); - id = id * 1000L + random.nextInt(1000); - - return id; - } + // ==================== 工具方法 ==================== - /** - * 从字典表根据scope_ids获取scope_names(增强版) - */ private String getScopeNamesFromDict(String scopeIds) { - if (StringUtils.isEmpty(scopeIds)) { - return ""; - } - + if (StringUtils.isEmpty(scopeIds)) return ""; try { - // 处理JSON数组格式 if (scopeIds.trim().startsWith("[")) { try { List scopeIdList = objectMapper.readValue(scopeIds, List.class); scopeIds = String.join(",", scopeIdList); - } catch (Exception e) { - // 忽略,继续处理 - } + } catch (Exception e) { } } - - // 处理逗号分隔的字符串 String[] idArray = scopeIds.split(","); List cleanedIds = new ArrayList<>(); for (String id : idArray) { @@ -780,67 +570,23 @@ public class VetQualificationServiceImpl implements IVetQualificationService { cleanedIds.add("'" + id.trim() + "'"); } } - - if (cleanedIds.isEmpty()) { - return ""; - } - + if (cleanedIds.isEmpty()) return ""; String inCondition = String.join(",", cleanedIds); - String sql = "SELECT dict_label FROM sys_dict_data " + - "WHERE dict_type = 'business_scope' " + - "AND dict_value IN (" + inCondition + ") " + - "AND status = '0' " + - "ORDER BY FIND_IN_SET(dict_value, ?)"; - - List names = jdbcTemplate.query(sql, - (rs, rowNum) -> rs.getString("dict_label"), - scopeIds); - + String sql = "SELECT dict_label FROM sys_dict_data WHERE dict_type = 'business_scope' AND dict_value IN (" + inCondition + ") AND status = '0'"; + List names = jdbcTemplate.query(sql, (rs, rowNum) -> rs.getString("dict_label")); return String.join(",", names); - } catch (Exception e) { - log.error("获取经营范围名称失败, scopeIds: {}", scopeIds, e); + log.error("获取经营范围名称失败", e); return ""; } } - /** - * 从JSON中提取文件路径 - */ private void extractFilePathsFromJson(VetQualification qualification) { - if (StringUtils.isEmpty(qualification.getCertificatesJson())) { - return; - } - - try { - List> certs = parseCertificatesJson(qualification.getCertificatesJson()); - List filePaths = new ArrayList<>(); - - for (Map cert : certs) { - String filePath = (String) cert.get("certificateFiles"); - if (StringUtils.isNotEmpty(filePath)) { - filePaths.add(filePath); - } - } - - if (!filePaths.isEmpty() && - (qualification.getCertificateFiles() == null || qualification.getCertificateFiles().isEmpty())) { - qualification.setCertificateFiles(String.join(",", filePaths)); - } - } catch (Exception e) { - // 忽略异常 - } + // 暂不实现 } - /** - * 处理经营范围IDs(支持数组格式) - */ private String processScopeIds(String scopeIds) { - if (StringUtils.isEmpty(scopeIds)) { - return ""; - } - - // 如果是以 [ 开头,可能是JSON数组格式 + if (StringUtils.isEmpty(scopeIds)) return ""; if (scopeIds.trim().startsWith("[")) { try { List scopeIdList = objectMapper.readValue(scopeIds, List.class); @@ -849,67 +595,37 @@ public class VetQualificationServiceImpl implements IVetQualificationService { return scopeIds; } } - - // 如果是逗号分隔的字符串,直接返回 return scopeIds; } - /** - * 将请求数据转换为VetQualification对象 - */ private VetQualification convertRequestToQualification(Map requestData) { VetQualification qualification = new VetQualification(); - - // 设置基本信息 qualification.setRealName((String) requestData.get("realName")); qualification.setIdCard((String) requestData.get("idCard")); qualification.setQualificationType((String) requestData.get("qualificationType")); - // 处理经营范围 Object scopeIdsObj = requestData.get("scopeIds"); if (scopeIdsObj != null) { - String scopeIdsStr; - if (scopeIdsObj instanceof List) { - @SuppressWarnings("unchecked") - List scopeIdsList = (List) scopeIdsObj; - scopeIdsStr = String.join(",", scopeIdsList); - } else if (scopeIdsObj instanceof String) { - scopeIdsStr = (String) scopeIdsObj; - } else { - scopeIdsStr = scopeIdsObj.toString(); - } + String scopeIdsStr = scopeIdsObj instanceof List ? String.join(",", (List) scopeIdsObj) : scopeIdsObj.toString(); qualification.setScopeIds(scopeIdsStr); } - // 处理证书信息 Object certificatesObj = requestData.get("certificates"); - if (certificatesObj != null && certificatesObj instanceof List) { - @SuppressWarnings("unchecked") - List> certificates = (List>) certificatesObj; - processCertificates(qualification, certificates); + if (certificatesObj instanceof List) { + processCertificates(qualification, (List>) certificatesObj); } - // 处理单独的certId字段 Object certIdObj = requestData.get("certId"); if (certIdObj != null) { Long certId = extractLongFromObject(certIdObj); - if (certId != null) { - qualification.setCertId(certId); - } + if (certId != null) qualification.setCertId(certId); } - return qualification; } - /** - * 处理证书列表 - */ private void processCertificates(VetQualification qualification, List> certificates) { - if (certificates == null || certificates.isEmpty()) { - return; - } + if (certificates == null || certificates.isEmpty()) return; - // 取第一个证书设置到主字段 Map firstCert = certificates.get(0); qualification.setCertName((String) firstCert.get("certName")); qualification.setIssueOrg((String) firstCert.get("issueOrg")); @@ -917,96 +633,57 @@ public class VetQualificationServiceImpl implements IVetQualificationService { qualification.setIssueDate(parseDate(firstCert.get("issueDate"))); qualification.setExpireDate(parseDate(firstCert.get("expireDate"))); - // 确保每个证书都有独立ID List> processedCerts = new ArrayList<>(); for (Map cert : certificates) { Map processedCert = new HashMap<>(cert); - - Object certIdObj = cert.get("certId"); - Long certId = extractLongFromObject(certIdObj); - + Long certId = extractLongFromObject(cert.get("certId")); if (certId == null || certId == 0) { certId = generateCertificateId(); processedCert.put("certId", certId); } - processedCerts.add(processedCert); } - // 设置主表certId为第一个证书的ID - Map firstProcessedCert = processedCerts.get(0); - Long firstCertId = extractLongFromObject(firstProcessedCert.get("certId")); - if (firstCertId != null) { - qualification.setCertId(firstCertId); + if (!processedCerts.isEmpty()) { + Long firstCertId = extractLongFromObject(processedCerts.get(0).get("certId")); + if (firstCertId != null) qualification.setCertId(firstCertId); } - - // 保存所有证书信息 qualification.setCertificatesJson(mergeCertificatesToJson(processedCerts)); } - /** - * 从对象中提取Long值 - */ private Long extractLongFromObject(Object obj) { - if (obj == null) { - return null; - } - + if (obj == null) return null; try { - if (obj instanceof Number) { - return ((Number) obj).longValue(); - } else if (obj instanceof String) { + if (obj instanceof Number) return ((Number) obj).longValue(); + if (obj instanceof String) { String str = ((String) obj).trim(); - if (!str.isEmpty()) { - return Long.parseLong(str); - } + if (!str.isEmpty()) return Long.parseLong(str); } - } catch (Exception e) { - // 忽略解析异常 - } - + } catch (Exception e) { } return null; } - /** - * 解析日期 - */ private Date parseDate(Object dateObj) { - if (dateObj == null) { - return null; - } - + if (dateObj == null) return null; try { - if (dateObj instanceof Date) { - return (Date) dateObj; - } else if (dateObj instanceof String) { - // 尝试解析为时间戳字符串 + if (dateObj instanceof Date) return (Date) dateObj; + if (dateObj instanceof String) { try { long timestamp = Long.parseLong((String) dateObj); return new Date(timestamp); } catch (NumberFormatException e) { - // 按日期格式解析 return dateFormat.parse((String) dateObj); } - } else if (dateObj instanceof Long) { - return new Date((Long) dateObj); - } else if (dateObj instanceof Integer) { - return new Date(((Integer) dateObj).longValue() * 1000L); } - } catch (Exception e) { - // 忽略解析异常 - } - + if (dateObj instanceof Long) return new Date((Long) dateObj); + if (dateObj instanceof Integer) return new Date(((Integer) dateObj).longValue() * 1000L); + } catch (Exception e) { } return null; } - /** - * 合并多个证书为JSON字符串 - */ private String mergeCertificatesToJson(List> certificates) { try { List> certList = new ArrayList<>(); - for (Map cert : certificates) { Map certMap = new HashMap<>(); certMap.put("certName", cert.get("certName")); @@ -1015,91 +692,41 @@ public class VetQualificationServiceImpl implements IVetQualificationService { certMap.put("issueDate", cert.get("issueDate")); certMap.put("expireDate", cert.get("expireDate")); certMap.put("certificateFiles", cert.get("certificateFiles")); - - Object certIdObj = cert.get("certId"); - if (certIdObj != null) { - Long certId = extractLongFromObject(certIdObj); - if (certId != null && certId != 0) { - certMap.put("certId", certId); - } else { - certMap.put("certId", generateCertificateId()); - } - } else { - certMap.put("certId", generateCertificateId()); - } - + Long certId = extractLongFromObject(cert.get("certId")); + certMap.put("certId", certId != null ? certId : generateCertificateId()); certList.add(certMap); } - return objectMapper.writeValueAsString(certList); } catch (Exception e) { return "[]"; } } - /** - * 更新证书信息 - */ - private VetQualification.CertificateInfo updateCertificateInfo(VetQualification.CertificateInfo existingCert, - Map updateMap) { - if (updateMap.containsKey("certName")) { - existingCert.setCertName((String) updateMap.get("certName")); - } - if (updateMap.containsKey("certificateNo")) { - existingCert.setCertificateNo((String) updateMap.get("certificateNo")); - } - if (updateMap.containsKey("issueOrg")) { - existingCert.setIssueOrg((String) updateMap.get("issueOrg")); - } - if (updateMap.containsKey("issueDate")) { - Object issueDateObj = updateMap.get("issueDate"); - existingCert.setIssueDate(parseDate(issueDateObj)); - } - if (updateMap.containsKey("expireDate")) { - Object expireDateObj = updateMap.get("expireDate"); - existingCert.setExpireDate(parseDate(expireDateObj)); - } - if (updateMap.containsKey("certificateFiles")) { - existingCert.setCertificateFiles((String) updateMap.get("certificateFiles")); - } - if (updateMap.containsKey("certStatus")) { - existingCert.setCertStatus((String) updateMap.get("certStatus")); - } - + private VetQualification.CertificateInfo updateCertificateInfo(VetQualification.CertificateInfo existingCert, Map updateMap) { + if (updateMap.containsKey("certName")) existingCert.setCertName((String) updateMap.get("certName")); + if (updateMap.containsKey("certificateNo")) existingCert.setCertificateNo((String) updateMap.get("certificateNo")); + if (updateMap.containsKey("issueOrg")) existingCert.setIssueOrg((String) updateMap.get("issueOrg")); + if (updateMap.containsKey("issueDate")) existingCert.setIssueDate(parseDate(updateMap.get("issueDate"))); + if (updateMap.containsKey("expireDate")) existingCert.setExpireDate(parseDate(updateMap.get("expireDate"))); + if (updateMap.containsKey("certificateFiles")) existingCert.setCertificateFiles((String) updateMap.get("certificateFiles")); + if (updateMap.containsKey("certStatus")) existingCert.setCertStatus((String) updateMap.get("certStatus")); return existingCert; } - /** - * 从Map创建新证书 - */ private VetQualification.CertificateInfo createCertificateFromMap(Map certMap) { VetQualification.CertificateInfo cert = new VetQualification.CertificateInfo(); - cert.setCertName((String) certMap.get("certName")); cert.setCertificateNo((String) certMap.get("certificateNo")); cert.setIssueOrg((String) certMap.get("issueOrg")); - - Object issueDateObj = certMap.get("issueDate"); - cert.setIssueDate(parseDate(issueDateObj)); - - Object expireDateObj = certMap.get("expireDate"); - cert.setExpireDate(parseDate(expireDateObj)); - + cert.setIssueDate(parseDate(certMap.get("issueDate"))); + cert.setExpireDate(parseDate(certMap.get("expireDate"))); cert.setCertificateFiles((String) certMap.get("certificateFiles")); cert.setCertStatus((String) certMap.get("certStatus")); - - // 如果有certId,设置它 Long certId = extractLongFromObject(certMap.get("certId")); - if (certId != null) { - cert.setCertificateId(certId); - } - + if (certId != null) cert.setCertificateId(certId); return cert; } - /** - * 获取要更新的证书列表 - */ private List> getCertificatesToUpdate(VetQualification qualification) { if (qualification.getCertificates() != null && !qualification.getCertificates().isEmpty()) { return qualification.getCertificates(); @@ -1113,25 +740,12 @@ public class VetQualificationServiceImpl implements IVetQualificationService { return null; } - /** - * 解析证书JSON - */ private List> parseCertificatesJson(String certificatesJson) throws Exception { - return objectMapper.readValue( - certificatesJson, - objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class) - ); + return objectMapper.readValue(certificatesJson, objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class)); } - /** - * 构建证书查询结果 - */ - private Map buildCertificateResult(VetQualification qualification, - Map certMap, - Long certId) { + private Map buildCertificateResult(VetQualification qualification, Map certMap, Long certId) { Map result = new HashMap<>(); - - // 资质信息 result.put("qualificationId", qualification.getQualificationId()); result.put("userId", qualification.getUserId()); result.put("realName", qualification.getRealName()); @@ -1145,8 +759,6 @@ public class VetQualificationServiceImpl implements IVetQualificationService { result.put("auditTime", qualification.getAuditTime()); result.put("createTime", qualification.getCreateTime()); result.put("updateTime", qualification.getUpdateTime()); - - // 证书信息 result.put("certId", certId); result.put("certName", certMap.get("certName")); result.put("certificateNo", certMap.get("certificateNo")); @@ -1154,169 +766,75 @@ public class VetQualificationServiceImpl implements IVetQualificationService { result.put("certificateFiles", certMap.get("certificateFiles")); result.put("issueDate", parseDate(certMap.get("issueDate"))); result.put("expireDate", parseDate(certMap.get("expireDate"))); - - // 计算证书状态 - Date expireDate = (Date) result.get("expireDate"); - String certStatus = calculateCertificateStatus(expireDate); - result.put("certStatus", certStatus); - + result.put("certStatus", calculateCertificateStatus((Date) result.get("expireDate"))); return result; } - /** - * 计算证书状态 - */ private String calculateCertificateStatus(Date expireDate) { - if (expireDate == null) { - return "0"; - } - + if (expireDate == null) return "0"; Date today = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(today); calendar.add(Calendar.DAY_OF_YEAR, 30); Date thirtyDaysLater = calendar.getTime(); - - if (expireDate.before(today)) { - return "2"; // 已过期 - } else if (expireDate.before(thirtyDaysLater)) { - return "1"; // 即将过期 - } else { - return "0"; // 正常 - } + if (expireDate.before(today)) return "2"; + if (expireDate.before(thirtyDaysLater)) return "1"; + return "0"; } - /** - * 更新证书状态 - */ private void updateCertificateStatus(VetQualification qualification) { - if (qualification.getExpireDate() == null) { - qualification.setCertStatus("0"); - return; - } - - Date today = new Date(); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(today); - calendar.add(Calendar.DAY_OF_YEAR, 30); - Date thirtyDaysLater = calendar.getTime(); - - if (qualification.getExpireDate().before(today)) { - qualification.setCertStatus("2"); // 已过期 - } else if (qualification.getExpireDate().before(thirtyDaysLater)) { - qualification.setCertStatus("1"); // 即将过期 - } else { - qualification.setCertStatus("0"); // 正常 - } + qualification.setCertStatus(calculateCertificateStatus(qualification.getExpireDate())); } - // 在VetQualificationServiceImpl类中添加以下方法 - - /** - * 获取即将过期的资质证书(30天内) - */ - @Override - public List selectExpiringQualifications(Long userId) { - Date today = new Date(); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(today); - calendar.add(Calendar.DAY_OF_YEAR, 30); - Date thirtyDaysLater = calendar.getTime(); - - // 先获取用户所有资质证书 - List allQualifications = selectQualificationsByUserId(userId); - - // 过滤出即将过期的证书 - return allQualifications.stream() - .filter(qual -> qual.getExpireDate() != null && - !qual.getExpireDate().before(today) && - !qual.getExpireDate().after(thirtyDaysLater)) - .toList(); + private Long generateCertificateId() { + return generateSafeCertificateId(); } - /** - * 检查并发送证书过期提醒 - */ - @Override - public void checkAndSendCertificateReminders() { - Date today = new Date(); - - Calendar calendar = Calendar.getInstance(); - calendar.setTime(today); - calendar.add(Calendar.DAY_OF_YEAR, 30); - Date thresholdDate = calendar.getTime(); // 30天后过期 - - calendar.setTime(today); - calendar.add(Calendar.DAY_OF_YEAR, -7); - Date remindDate = calendar.getTime(); // 7天前提醒过的不再提醒 - - // 查询所有资质证书 - VetQualification query = new VetQualification(); - List allQualifications = vetQualificationMapper.selectVetQualificationList(query); - - for (VetQualification qualification : allQualifications) { - try { - // 获取所有证书,检查每个证书 - List certificateList = qualification.getCertificateList(); - - for (VetQualification.CertificateInfo cert : certificateList) { - if (shouldSendRemindForCertificate(cert, today, thresholdDate, remindDate, qualification)) { - // 更新最后提醒时间(可以记录到证书级别,或保持资质级别) - qualification.setLastRemindTime(new Date()); - vetQualificationMapper.updateVetQualification(qualification); - } - } - } catch (Exception e) { - // 记录错误日志 - // log.error("检查资质证书过期提醒失败,qualificationId={}", qualification.getQualificationId(), e); - } + private Long generateSafeCertificateId() { + final long MAX_SAFE_ID = 9007199254740991L; + final long MIN_SAFE_ID = 100000000L; + long timestamp = System.currentTimeMillis(); + long id = timestamp % 1000000000000L; + id += MIN_SAFE_ID; + if (id > MAX_SAFE_ID) { + id = id % (MAX_SAFE_ID - MIN_SAFE_ID) + MIN_SAFE_ID; } + Random random = new Random(); + id = id * 1000L + random.nextInt(1000); + return id; } - /** - * 判断是否需要发送提醒 - */ - private boolean shouldSendRemindForCertificate(VetQualification.CertificateInfo cert, - Date today, Date thresholdDate, - Date remindDate, VetQualification qualification) { - if (cert.getExpireDate() == null) { - return false; - } - - // 检查是否即将过期(30天内) - if (cert.getExpireDate().after(thresholdDate)) { - return false; + private String getCertStatusLabel(String certStatus) { + if (certStatus == null) return "未知"; + switch (certStatus) { + case "0": return "正常"; + case "1": return "即将过期"; + case "2": return "已过期"; + default: return "未知"; } + } - // 检查是否已提醒过(7天内)- 这里保持资质级别的提醒频率 - if (qualification.getLastRemindTime() != null) { - Calendar cal = Calendar.getInstance(); - cal.setTime(qualification.getLastRemindTime()); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - Date lastRemindDateOnly = cal.getTime(); - - if (!lastRemindDateOnly.before(remindDate)) { - return false; - } + private String getAuditStatusLabel(String auditStatus) { + if (auditStatus == null) return "未知"; + switch (auditStatus) { + case "0": return "待审核"; + case "1": return "审核通过"; + case "2": return "审核不通过"; + default: return "未知"; } - - return true; } - /** - * 计算剩余天数 - */ - private int calculateRemainingDays(Date expireDate) { - if (expireDate == null) return 0; - long diff = expireDate.getTime() - new Date().getTime(); - return (int) (diff / (1000 * 60 * 60 * 24)); + private String getQualificationTypeLabel(String qualificationType) { + if (qualificationType == null) return "未知"; + switch (qualificationType) { + case "1": return "执业兽医师"; + case "2": return "执业助理兽医师"; + case "3": return "乡村兽医"; + default: return "未知"; + } } - @Override - public VetQualification selectVetQualificationById(Long qualificationId) { - return vetQualificationMapper.selectVetQualificationById(qualificationId); + private boolean shouldSendRemindForCertificate(VetQualification.CertificateInfo cert, Date today, Date thresholdDate, Date remindDate, VetQualification qualification) { + return false; } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java index 5ac1183..7eaa96d 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import com.chenhai.common.core.domain.AjaxResult; +import com.chenhai.common.core.domain.entity.SysUser; +import com.chenhai.common.core.domain.model.LoginUser; import com.chenhai.common.utils.SecurityUtils; import org.slf4j.Logger; @@ -28,6 +30,7 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService // 添加 logger private static final Logger logger = LoggerFactory.getLogger(VetTrainingVideoServiceImpl.class); + @Autowired private VetTrainingVideoMapper vetTrainingVideoMapper; @@ -44,15 +47,44 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService } /** - * 查询兽医培训视频列表 - * - * @param vetTrainingVideo 兽医培训视频 - * @return 兽医培训视频 + * 查询兽医培训视频列表(带数据权限过滤) + * 管理员和muhu能看到所有,vet只能看到自己的 */ @Override public List selectVetTrainingVideoList(VetTrainingVideo vetTrainingVideo) { - return vetTrainingVideoMapper.selectVetTrainingVideoList(vetTrainingVideo); + // 获取当前登录用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || loginUser.getUser() == null) { + // 未登录,返回空列表 + return new ArrayList<>(); + } + + SysUser currentUser = loginUser.getUser(); + Long userId = currentUser.getUserId(); + + // 判断角色权限 + boolean isAdmin = SecurityUtils.hasRole("admin"); + boolean isMuhu = SecurityUtils.hasRole("muhu"); + boolean isManger = SecurityUtils.hasRole("manger"); + boolean isVet = SecurityUtils.hasRole("vet"); + + // 管理员、muhu、manger可以看到所有视频(不添加数据过滤) + if (isAdmin || isMuhu || isManger) { + // 直接查询所有,不添加用户过滤条件 + return vetTrainingVideoMapper.selectVetTrainingVideoList(vetTrainingVideo); + } + // vet只能看到自己创建的视频 + else if (isVet) { + // 设置用户ID进行过滤 + if (vetTrainingVideo.getUserId() == null) { + vetTrainingVideo.setUserId(userId); + } + return vetTrainingVideoMapper.selectVetTrainingVideoList(vetTrainingVideo); + } + + // 其他角色返回空列表 + return new ArrayList<>(); } /** @@ -70,9 +102,24 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService throw new RuntimeException("用户未登录"); } + // 获取当前登录用户信息,设置发布者信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser != null && loginUser.getUser() != null) { + SysUser currentUser = loginUser.getUser(); + // 设置发布者姓名(昵称) + String nickName = currentUser.getNickName(); + if (nickName != null && !nickName.isEmpty()) { + vetTrainingVideo.setPublisherName(nickName); + } else { + vetTrainingVideo.setPublisherName(currentUser.getUserName()); + } + // 设置发布者头像 + vetTrainingVideo.setPublisherAvatar(currentUser.getAvatar()); + } + vetTrainingVideo.setUserId(userId); // 确保设置用户ID vetTrainingVideo.setStatus("0"); // 草稿(原私有) - vetTrainingVideo.setAuditStatus("1"); // 待审核 + vetTrainingVideo.setAuditStatus("0"); // 待审核 vetTrainingVideo.setDelFlag("0"); // 正常 vetTrainingVideo.setCreateTime(DateUtils.getNowDate()); @@ -148,14 +195,11 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService continue; } - // 检查是否是自己的视频(通过userId字段判断) - if (!currentUserId.equals(video.getUserId())) { - // 如果不是自己的视频,检查是否是管理员 - if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里 - failedCount++; - failedMessages.add("视频ID " + id + " 不是您发布的视频,无法删除"); - continue; - } + // 检查是否有权限删除 + if (!hasDeletePermission(video, currentUserId)) { + failedCount++; + failedMessages.add("视频ID " + id + " 没有权限删除"); + continue; } // 执行删除 @@ -205,12 +249,9 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService return AjaxResult.error("视频不存在"); } - // 检查是否是自己的视频(通过userId字段判断) - if (!currentUserId.equals(video.getUserId())) { - // 如果不是自己的视频,检查是否是管理员 - if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里 - return AjaxResult.error("不是您发布的视频,无法删除"); - } + // 检查是否有权限删除 + if (!hasDeletePermission(video, currentUserId)) { + return AjaxResult.error("没有权限删除该视频"); } int result = vetTrainingVideoMapper.deleteVetTrainingVideoById(id); @@ -225,6 +266,46 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService } } + /** + * 检查是否有删除权限 + * @param video 视频对象 + * @param currentUserId 当前用户ID + * @return true:有权限 false:无权限 + */ + private boolean hasDeletePermission(VetTrainingVideo video, Long currentUserId) { + // 管理员、muhu、manger可以删除任何视频 + if (SecurityUtils.hasRole("admin") || + SecurityUtils.hasRole("muhu") || + SecurityUtils.hasRole("manger")) { + return true; + } + + // vet只能删除自己的视频 + if (SecurityUtils.hasRole("vet")) { + Long videoUserId = video.getUserId(); + if (videoUserId != null && videoUserId.equals(currentUserId)) { + return true; + } + } + + return false; + } + + /** + * 检查当前用户是否是视频所有者 + */ + private boolean isOwner(VetTrainingVideo video) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || loginUser.getUser() == null) { + return false; + } + + Long currentUserId = loginUser.getUser().getUserId(); + Long videoUserId = video.getUserId(); + + return videoUserId != null && videoUserId.equals(currentUserId); + } + @Override @Transactional(rollbackFor = Exception.class) public int batchSubmitForAudit(List videoIds, Long userId) { @@ -277,6 +358,14 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService @Override @Transactional(rollbackFor = Exception.class) public int batchAuditVideo(List videoIds, String auditStatus, String auditOpinion, Long auditUserId) { + // 检查权限:只有管理员、muhu、manger可以审核 + if (!SecurityUtils.hasRole("admin") && + !SecurityUtils.hasRole("muhu") && + !SecurityUtils.hasRole("manger")) { + logger.warn("用户 {} 没有审核权限", auditUserId); + return 0; + } + int successCount = 0; // 验证审核状态值(2-通过,3-拒绝) @@ -419,6 +508,14 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService @Override public boolean auditVideo(Long videoId, String auditStatus, String auditOpinion, Long auditUserId) { + // 检查权限:只有管理员、muhu、manger可以审核 + if (!SecurityUtils.hasRole("admin") && + !SecurityUtils.hasRole("muhu") && + !SecurityUtils.hasRole("manger")) { + logger.warn("用户 {} 没有审核权限", auditUserId); + return false; + } + try { VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId); @@ -427,7 +524,7 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService } // 只有审核中状态(1)才能审核 - if (!"1".equals(video.getAuditStatus())) { + if (!"0".equals(video.getAuditStatus())) { return false; } @@ -532,10 +629,14 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService return false; } -// // 验证权限:只能操作自己的视频 -// if (!userId.equals(video.getUserId())) { -// return false; -// } + // 检查是否是管理员 + boolean isAdmin = checkUserIsAdmin(userId); + boolean isOwner = userId.equals(video.getUserId()); + + if (!isAdmin && !isOwner) { + logger.warn("下架失败:用户 {} 无权限操作视频 {}", userId, videoId); + return false; + } // 状态验证:只有已发布状态(1)的视频才能下架 if (!"1".equals(video.getStatus())) { @@ -600,6 +701,12 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService return false; } + // 检查权限:管理员或视频所有者 + boolean isAdmin = checkUserIsAdmin(userId); + if (!isAdmin && !userId.equals(video.getUserId())) { + return false; + } + // 状态验证:只有待审核状态才能取消审核 if (!"0".equals(video.getAuditStatus()) && !"1".equals(video.getAuditStatus())) { return false; @@ -624,12 +731,13 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService /** * 查询公开视频列表(已上架且已审核通过) + * 公开接口,不需要权限过滤,所有用户都能看到已上架且审核通过的视频 */ @Override public List selectPublicVideoList(VetTrainingVideo vetTrainingVideo) { // 设置强制条件:已上架且审核通过 vetTrainingVideo.setStatus("1"); // 已上架 - vetTrainingVideo.setAuditStatus("2"); // 审核通过(注意:这里是2) + vetTrainingVideo.setAuditStatus("2"); // 审核通过 vetTrainingVideo.setDelFlag("0"); // 未删除 return vetTrainingVideoMapper.selectPublicVideoList(vetTrainingVideo); @@ -637,14 +745,15 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService /** * 分页查询公开视频列表(已上架且已审核通过) + * 公开接口,不需要权限过滤,所有用户都能看到已上架且审核通过的视频 */ @Override public List selectPublicVideoPageList(VetTrainingVideo vetTrainingVideo) { // 设置强制条件:已上架且审核通过 vetTrainingVideo.setStatus("1"); // 已上架 - vetTrainingVideo.setAuditStatus("2"); // 审核通过(注意:这里是2) + vetTrainingVideo.setAuditStatus("2"); // 审核通过 vetTrainingVideo.setDelFlag("0"); // 未删除 return vetTrainingVideoMapper.selectVetTrainingVideoList(vetTrainingVideo); } -} \ No newline at end of file +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetUnifiedInfoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetUnifiedInfoServiceImpl.java index 2eb11b6..203f2ae 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetUnifiedInfoServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetUnifiedInfoServiceImpl.java @@ -15,6 +15,8 @@ import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.domain.dto.VetUnifiedInfoDTO; import com.chenhai.vet.mapper.VetPersonalInfoMapper; import com.chenhai.vet.mapper.VetQualificationMapper; +import com.chenhai.vet.service.IVetPersonalInfoService; +import com.chenhai.vet.service.IVetQualificationService; import com.chenhai.vet.service.IVetUnifiedInfoService; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; @@ -58,6 +60,12 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { @Autowired private ObjectMapper objectMapper; + @Autowired + private IVetPersonalInfoService vetPersonalInfoService; + + @Autowired + private IVetQualificationService vetQualificationService; + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override @@ -315,16 +323,13 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { VetPersonalInfo personalQuery = new VetPersonalInfo(); if (query != null) { BeanUtils.copyProperties(query, personalQuery); - // 确保 userId 被正确传递 if (query.getUserId() != null) { personalQuery.setUserId(query.getUserId()); } } - // MyBatis 分页插件会自动处理分页 List personalList = vetPersonalInfoMapper.selectVetPersonalInfoList(personalQuery); - // 转换为统一DTO return personalList.stream() .map(info -> { VetUnifiedInfoDTO dto = new VetUnifiedInfoDTO(); @@ -345,11 +350,55 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { dto.setUserType(user.getUserType()); dto.setAreaCode(user.getAreaCode()); dto.setStatus(user.getStatus()); + dto.setLoginDate(user.getLoginDate()); + } else { + // 如果关联对象为空,手动查询用户信息 + try { + user = sysUserService.selectUserById(info.getUserId()); + if (user != null) { + dto.setUserName(user.getUserName()); + dto.setNickName(user.getNickName()); + dto.setPhonenumber(user.getPhonenumber()); + dto.setEmail(user.getEmail()); + dto.setAvatar(user.getAvatar()); + dto.setUserType(user.getUserType()); + dto.setAreaCode(user.getAreaCode()); + dto.setStatus(user.getStatus()); + dto.setLoginDate(user.getLoginDate()); + } + } catch (Exception e) { + log.warn("查询用户信息失败 - userId: {}", info.getUserId(), e); + } } - // 补充资质信息 + // 补充资质信息(包含认证信息) VetQualification qualification = vetQualificationMapper.selectVetQualificationByUserId(info.getUserId()); if (qualification != null) { + // ========== 从资质表获取认证信息 ========== + // 设置真实姓名和身份证(如果个人信息表中没有,则从资质表获取) + if (StringUtils.isEmpty(dto.getRealName()) && StringUtils.isNotEmpty(qualification.getRealName())) { + dto.setRealName(qualification.getRealName()); + } + if (StringUtils.isEmpty(dto.getIdCard()) && StringUtils.isNotEmpty(qualification.getIdCard())) { + dto.setIdCard(qualification.getIdCard()); + } + + // 设置认证状态:如果有真实姓名和身份证,则视为已认证 + if (StringUtils.isNotEmpty(qualification.getRealName()) && StringUtils.isNotEmpty(qualification.getIdCard())) { + dto.setAuthStatus("已认证"); + dto.setAuthTime(qualification.getCreateTime()); // 可以使用创建时间作为认证时间 + + // 身份证脱敏 + String idCard = qualification.getIdCard(); + if (StringUtils.isNotEmpty(idCard) && idCard.length() >= 15) { + String masked = idCard.substring(0, 6) + "********" + idCard.substring(idCard.length() - 4); + dto.setMaskedIdCard(masked); + } + } else { + dto.setAuthStatus("未认证"); + } + + // ========== 资质信息 ========== dto.setQualificationId(qualification.getQualificationId()); dto.setQualificationType(qualification.getQualificationType()); dto.setQualificationTypeLabel(qualification.getQualificationTypeLabel()); @@ -362,15 +411,82 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { dto.setAuditTime(qualification.getAuditTime()); dto.setAuditOpinion(qualification.getAuditOpinion()); + // 补充主证书信息 + dto.setCertName(qualification.getCertName()); + dto.setCertificateNo(qualification.getCertificateNo()); + dto.setIssueOrg(qualification.getIssueOrg()); + dto.setCertificateFiles(qualification.getCertificateFiles()); + dto.setIssueDate(qualification.getIssueDate()); + dto.setExpireDate(qualification.getExpireDate()); + dto.setCertStatus(qualification.getCertStatus()); + dto.setCertStatusLabel(qualification.getCertStatusLabel()); + dto.setCertId(qualification.getCertId()); + dto.setRemindDays(qualification.getRemindDays()); + dto.setCertificatesJson(qualification.getCertificatesJson()); + + // 补充证书统计信息 + List certList = qualification.getCertificateList(); + if (certList != null && !certList.isEmpty()) { + dto.setTotalCertificates(certList.size()); + + Date today = new Date(); + Calendar cal = Calendar.getInstance(); + cal.setTime(today); + cal.add(Calendar.DAY_OF_YEAR, 30); + Date thirtyDaysLater = cal.getTime(); + + int normal = 0, expiring = 0, expired = 0; + for (VetQualification.CertificateInfo cert : certList) { + if (cert.getExpireDate() != null) { + if (cert.getExpireDate().before(today)) { + expired++; + } else if (cert.getExpireDate().before(thirtyDaysLater)) { + expiring++; + } else { + normal++; + } + } else { + normal++; + } + } + + dto.setNormalCount(normal); + dto.setExpiringCount(expiring); + dto.setExpiredCount(expired); + + // 设置警告级别 + if (expired > 0) { + dto.setWarningLevel("DANGER"); + } else if (expiring > 0) { + dto.setWarningLevel("WARNING"); + } else { + dto.setWarningLevel("NORMAL"); + } + } else { + dto.setTotalCertificates(0); + dto.setNormalCount(0); + dto.setExpiringCount(0); + dto.setExpiredCount(0); + dto.setWarningLevel("NORMAL"); + } + dto.setHasQualification(true); dto.setHasCertificates(qualification.getCertificateList() != null && !qualification.getCertificateList().isEmpty()); } else { dto.setHasQualification(false); dto.setHasCertificates(false); + dto.setTotalCertificates(0); + dto.setNormalCount(0); + dto.setExpiringCount(0); + dto.setExpiredCount(0); + dto.setWarningLevel("NORMAL"); + dto.setAuthStatus("未认证"); } - dto.setHasPersonalInfo(true); + // 计算信息完整度 dto.setCompleteness(calculateCompleteness(dto)); + dto.setHasPersonalInfo(true); + dto.setCanSubmitAudit(canSubmitAudit(dto)); return dto; }) @@ -431,22 +547,46 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { VetPersonalInfo personalInfo = vetPersonalInfoMapper.selectVetPersonalInfoByUserId(userId); if (personalInfo != null) { // 使用BeanUtils.copyProperties,但排除nickName和avatar字段 - // 这样就不会覆盖上面从sys_user获取的值 BeanUtils.copyProperties(personalInfo, dto, "nickName", // 排除nickName,使用sys_user的值 "avatar"); // 排除avatar,使用sys_user的值 dto.setPersonalInfoId(personalInfo.getId()); dto.setPersonalEmail(personalInfo.getEmail()); - dto.setPersonalNickName(personalInfo.getNickName()); // 兽医个人表的昵称放到单独字段 + dto.setPersonalNickName(personalInfo.getNickName()); dto.setHasPersonalInfo(true); } else { dto.setHasPersonalInfo(false); } - // 3. 获取资质信息 + // 3. 获取资质信息(包含认证信息) VetQualification qualification = vetQualificationMapper.selectVetQualificationByUserId(userId); if (qualification != null) { + // ========== 从资质表获取认证信息 ========== + // 设置真实姓名和身份证(如果个人信息表中没有,则从资质表获取) + if (StringUtils.isEmpty(dto.getRealName()) && StringUtils.isNotEmpty(qualification.getRealName())) { + dto.setRealName(qualification.getRealName()); + } + if (StringUtils.isEmpty(dto.getIdCard()) && StringUtils.isNotEmpty(qualification.getIdCard())) { + dto.setIdCard(qualification.getIdCard()); + } + + // 设置认证状态:如果有真实姓名和身份证,则视为已认证 + if (StringUtils.isNotEmpty(qualification.getRealName()) && StringUtils.isNotEmpty(qualification.getIdCard())) { + dto.setAuthStatus("已认证"); + dto.setAuthTime(qualification.getCreateTime()); // 使用创建时间作为认证时间 + + // 身份证脱敏(用于显示) + String idCard = qualification.getIdCard(); + if (StringUtils.isNotEmpty(idCard) && idCard.length() >= 15) { + String masked = idCard.substring(0, 6) + "********" + idCard.substring(idCard.length() - 4); + dto.setMaskedIdCard(masked); + } + } else { + dto.setAuthStatus("未认证"); + } + + // ========== 资质信息 ========== dto.setQualificationId(qualification.getQualificationId()); dto.setQualificationType(qualification.getQualificationType()); dto.setQualificationTypeLabel(qualification.getQualificationTypeLabel()); @@ -490,13 +630,17 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { dto.setExpiringCount(0); dto.setExpiredCount(0); dto.setWarningLevel("NORMAL"); + dto.setAuthStatus("未认证"); } - // 4. 获取认证信息 + // 4. 获取认证信息(从sys_muhu_user表,如果存在则覆盖) SysMuhuUser muhuUser = sysMuhuUserService.selectSysMuhuUserByUserId(userId); if (muhuUser != null) { - dto.setAuthStatus(muhuUser.getAuthStatus()); - dto.setAuthTime(muhuUser.getAuthTime()); + // 如果sys_muhu_user表有认证信息,优先使用 + if (StringUtils.isNotEmpty(muhuUser.getAuthStatus())) { + dto.setAuthStatus(muhuUser.getAuthStatus()); + dto.setAuthTime(muhuUser.getAuthTime()); + } // 身份证脱敏 if (StringUtils.isNotEmpty(muhuUser.getIdCard()) && muhuUser.getIdCard().length() >= 15) { @@ -525,8 +669,8 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { } // 添加日志,方便调试 - log.debug("buildUnifiedInfo - userId: {}, nickName: {}, avatar: {}", - userId, dto.getNickName(), dto.getAvatar()); + log.debug("buildUnifiedInfo - userId: {}, nickName: {}, avatar: {}, authStatus: {}", + userId, dto.getNickName(), dto.getAvatar(), dto.getAuthStatus()); return dto; } @@ -644,9 +788,9 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { String idCard = (String) data.get("idCard"); if (idCard != null && !idCard.trim().isEmpty()) { idCard = idCard.trim().toUpperCase(); - if (!isValidIdCard(idCard)) { - throw new ServiceException("身份证号格式不正确"); - } +// if (!isValidIdCard(idCard)) { +// throw new ServiceException("身份证号格式不正确"); +// } } // 手机号校验 @@ -700,6 +844,7 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { personalInfo = vetPersonalInfoMapper.selectVetPersonalInfoByUserId(userId); } + // 4. 检查是否有个人数据需要保存 boolean hasPersonalData = data.containsKey("realName") || data.containsKey("gender") || data.containsKey("birthday") || data.containsKey("idCard") || data.containsKey("specialty") || data.containsKey("workExperience") @@ -714,14 +859,20 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { return; } + // 如果 personalInfo 还是 null,则创建新对象 if (personalInfo == null) { personalInfo = new VetPersonalInfo(); personalInfo.setUserId(userId); personalInfo.setCreateBy(username); + personalInfo.setCreateTime(new Date()); + personalInfo.setAuditStatus("0"); // 新创建时默认为待审核 + log.info("创建新的个人信息 - userId: {}", userId); } - // 更新兽医个人信息表的字段 - if (data.containsKey("realName")) personalInfo.setRealName((String) data.get("realName")); + // 更新所有字段 + if (data.containsKey("realName")) { + personalInfo.setRealName((String) data.get("realName")); + } if (data.containsKey("gender")) { Object genderObj = data.get("gender"); if (genderObj == null || StringUtils.isEmpty(genderObj.toString())) { @@ -745,19 +896,43 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { } catch (Exception e) { log.warn("解析生日日期失败: {}", birthdayObj); } + } else if (birthdayObj instanceof Date) { + personalInfo.setBirthday((Date) birthdayObj); } } - if (data.containsKey("idCard")) personalInfo.setIdCard((String) data.get("idCard")); - if (data.containsKey("specialty")) personalInfo.setSpecialty((String) data.get("specialty")); - if (data.containsKey("workExperience")) personalInfo.setWorkExperience((String) data.get("workExperience")); - if (data.containsKey("hospital")) personalInfo.setHospital((String) data.get("hospital")); - if (data.containsKey("address")) personalInfo.setAddress((String) data.get("address")); - if (data.containsKey("iphone")) personalInfo.setIphone((String) data.get("iphone")); - if (data.containsKey("introduction")) personalInfo.setIntroduction((String) data.get("introduction")); - if (data.containsKey("title")) personalInfo.setTitle((String) data.get("title")); - if (data.containsKey("phone")) personalInfo.setPhone((String) data.get("phone")); - if (data.containsKey("expertType")) personalInfo.setExpertType((String) data.get("expertType")); - if (data.containsKey("personalEmail")) personalInfo.setEmail((String) data.get("personalEmail")); + if (data.containsKey("idCard")) { + personalInfo.setIdCard((String) data.get("idCard")); + } + if (data.containsKey("specialty")) { + personalInfo.setSpecialty((String) data.get("specialty")); + } + if (data.containsKey("workExperience")) { + personalInfo.setWorkExperience((String) data.get("workExperience")); + } + if (data.containsKey("hospital")) { + personalInfo.setHospital((String) data.get("hospital")); + } + if (data.containsKey("address")) { + personalInfo.setAddress((String) data.get("address")); + } + if (data.containsKey("iphone")) { + personalInfo.setIphone((String) data.get("iphone")); + } + if (data.containsKey("introduction")) { + personalInfo.setIntroduction((String) data.get("introduction")); + } + if (data.containsKey("title")) { + personalInfo.setTitle((String) data.get("title")); + } + if (data.containsKey("phone")) { + personalInfo.setPhone((String) data.get("phone")); + } + if (data.containsKey("expertType")) { + personalInfo.setExpertType((String) data.get("expertType")); + } + if (data.containsKey("personalEmail")) { + personalInfo.setEmail((String) data.get("personalEmail")); + } if (data.containsKey("personalNickName")) { personalInfo.setNickName((String) data.get("personalNickName")); } @@ -765,21 +940,30 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { personalInfo.setAvatar((String) data.get("avatar")); } - // 先保存兽医个人信息 + // ⭐ 关键:如果请求中包含 auditStatus,则使用它(由Controller设置) + if (data.containsKey("auditStatus")) { + personalInfo.setAuditStatus((String) data.get("auditStatus")); + log.info("设置审核状态为: {}", personalInfo.getAuditStatus()); + } + personalInfo.setUpdateBy(username); personalInfo.setUpdateTime(new Date()); + if (StringUtils.isEmpty(personalInfo.getAuditStatus())) { + personalInfo.setAuditStatus("0"); + } + if (personalInfo.getId() != null) { - vetPersonalInfoMapper.updateVetPersonalInfo(personalInfo); - log.info("兽医个人信息更新成功 - id: {}, userId: {}", personalInfo.getId(), userId); + int result = vetPersonalInfoMapper.updateVetPersonalInfo(personalInfo); + log.info("个人信息更新结果: {}, userId: {}, auditStatus: {}", + result, userId, personalInfo.getAuditStatus()); } else { - personalInfo.setCreateTime(new Date()); - vetPersonalInfoMapper.insertVetPersonalInfo(personalInfo); - log.info("兽医个人信息新增成功 - id: {}, userId: {}", personalInfo.getId(), userId); + personalInfo.setAuditStatus("0"); + int result = vetPersonalInfoService.insertVetPersonalInfo(personalInfo); + log.info("个人信息新增结果: {}, userId: {}", result, userId); } - // 然后再同步更新用户表的字段(如果有) - // 使用单独的SQL更新,避免触发角色删除 + // 同步更新用户表的字段 if (data.containsKey("nickName")) { String newNickName = (String) data.get("nickName"); updateUserNickNameOnly(userId, newNickName); @@ -793,6 +977,90 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { } } + /** + * 判断个人信息是否发生变化 + */ + private boolean isPersonalInfoChanged(VetPersonalInfo original, VetPersonalInfo newInfo) { + if (original == null || newInfo == null) { + return true; + } + + // 比较所有字段 + if (!StringUtils.equals(original.getRealName(), newInfo.getRealName())) { + log.debug("字段变化 - realName: {} -> {}", original.getRealName(), newInfo.getRealName()); + return true; + } + if (!StringUtils.equals(original.getGender(), newInfo.getGender())) { + log.debug("字段变化 - gender: {} -> {}", original.getGender(), newInfo.getGender()); + return true; + } + if (!StringUtils.equals(original.getIdCard(), newInfo.getIdCard())) { + log.debug("字段变化 - idCard: {} -> {}", original.getIdCard(), newInfo.getIdCard()); + return true; + } + if (!StringUtils.equals(original.getPhone(), newInfo.getPhone())) { + log.debug("字段变化 - phone: {} -> {}", original.getPhone(), newInfo.getPhone()); + return true; + } + if (!StringUtils.equals(original.getIphone(), newInfo.getIphone())) { + log.debug("字段变化 - iphone: {} -> {}", original.getIphone(), newInfo.getIphone()); + return true; + } + if (!StringUtils.equals(original.getEmail(), newInfo.getEmail())) { + log.debug("字段变化 - email: {} -> {}", original.getEmail(), newInfo.getEmail()); + return true; + } + if (!StringUtils.equals(original.getSpecialty(), newInfo.getSpecialty())) { + log.debug("字段变化 - specialty: {} -> {}", original.getSpecialty(), newInfo.getSpecialty()); + return true; + } + if (!StringUtils.equals(original.getWorkExperience(), newInfo.getWorkExperience())) { + log.debug("字段变化 - workExperience: {} -> {}", original.getWorkExperience(), newInfo.getWorkExperience()); + return true; + } + if (!StringUtils.equals(original.getHospital(), newInfo.getHospital())) { + log.debug("字段变化 - hospital: {} -> {}", original.getHospital(), newInfo.getHospital()); + return true; + } + if (!StringUtils.equals(original.getAddress(), newInfo.getAddress())) { + log.debug("字段变化 - address: {} -> {}", original.getAddress(), newInfo.getAddress()); + return true; + } + if (!StringUtils.equals(original.getIntroduction(), newInfo.getIntroduction())) { + log.debug("字段变化 - introduction: {} -> {}", original.getIntroduction(), newInfo.getIntroduction()); + return true; + } + if (!StringUtils.equals(original.getTitle(), newInfo.getTitle())) { + log.debug("字段变化 - title: {} -> {}", original.getTitle(), newInfo.getTitle()); + return true; + } + if (!StringUtils.equals(original.getExpertType(), newInfo.getExpertType())) { + log.debug("字段变化 - expertType: {} -> {}", original.getExpertType(), newInfo.getExpertType()); + return true; + } + if (!StringUtils.equals(original.getNickName(), newInfo.getNickName())) { + log.debug("字段变化 - nickName: {} -> {}", original.getNickName(), newInfo.getNickName()); + return true; + } + if (!StringUtils.equals(original.getAvatar(), newInfo.getAvatar())) { + log.debug("字段变化 - avatar: {} -> {}", original.getAvatar(), newInfo.getAvatar()); + return true; + } + + // 比较日期 + if (original.getBirthday() != null && newInfo.getBirthday() != null) { + if (!original.getBirthday().equals(newInfo.getBirthday())) { + log.debug("字段变化 - birthday: {} -> {}", original.getBirthday(), newInfo.getBirthday()); + return true; + } + } else if (original.getBirthday() != null || newInfo.getBirthday() != null) { + log.debug("字段变化 - birthday: {} -> {}", original.getBirthday(), newInfo.getBirthday()); + return true; + } + + return false; + } + /** * 只更新用户表的昵称,不影响角色 */ @@ -864,44 +1132,86 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { return; // 没有资质数据,不处理 } + // 保存原始数据用于比较 + VetQualification original = null; + if (qualification != null && qualification.getQualificationId() != null) { + original = vetQualificationMapper.selectVetQualificationByQualificationId(qualification.getQualificationId()); + } + if (qualification == null) { qualification = new VetQualification(); qualification.setUserId(userId); qualification.setCreateBy(username); + qualification.setAuditStatus("0"); // 新建时默认为待审核 + qualification.setCreateTime(new Date()); + log.info("创建新的资质信息 - userId: {}", userId); } + // 记录是否有变化 + boolean hasChanges = false; + // 更新基础信息 - if (data.containsKey("realName")) qualification.setRealName((String) data.get("realName")); - if (data.containsKey("idCard")) qualification.setIdCard((String) data.get("idCard")); - if (data.containsKey("qualificationType")) qualification.setQualificationType((String) data.get("qualificationType")); - if (data.containsKey("remindDays")) qualification.setRemindDays((Integer) data.get("remindDays")); + if (data.containsKey("realName")) { + String newValue = (String) data.get("realName"); + if (!StringUtils.equals(qualification.getRealName(), newValue)) { + qualification.setRealName(newValue); + hasChanges = true; + } + } + if (data.containsKey("idCard")) { + String newValue = (String) data.get("idCard"); + if (!StringUtils.equals(qualification.getIdCard(), newValue)) { + qualification.setIdCard(newValue); + hasChanges = true; + } + } + if (data.containsKey("qualificationType")) { + String newValue = (String) data.get("qualificationType"); + if (!StringUtils.equals(qualification.getQualificationType(), newValue)) { + qualification.setQualificationType(newValue); + hasChanges = true; + } + } + if (data.containsKey("remindDays")) { + Integer newValue = (Integer) data.get("remindDays"); + if (qualification.getRemindDays() == null || !qualification.getRemindDays().equals(newValue)) { + qualification.setRemindDays(newValue); + hasChanges = true; + } + } // 处理经营范围 if (data.containsKey("scopeIds")) { Object scopeIdsObj = data.get("scopeIds"); + String newScopeIds = null; if (scopeIdsObj instanceof List) { @SuppressWarnings("unchecked") List scopeIdsList = (List) scopeIdsObj; - qualification.setScopeIds(String.join(",", scopeIdsList)); + newScopeIds = String.join(",", scopeIdsList); } else if (scopeIdsObj instanceof String) { - qualification.setScopeIds((String) scopeIdsObj); + newScopeIds = (String) scopeIdsObj; } - // 获取经营范围名称 - if (StringUtils.isNotEmpty(qualification.getScopeIds())) { - String scopeNames = getScopeNamesFromDict(qualification.getScopeIds()); - qualification.setScopeNames(scopeNames); + if (!StringUtils.equals(qualification.getScopeIds(), newScopeIds)) { + qualification.setScopeIds(newScopeIds); + // 获取经营范围名称 + if (StringUtils.isNotEmpty(qualification.getScopeIds())) { + String scopeNames = getScopeNamesFromDict(qualification.getScopeIds()); + qualification.setScopeNames(scopeNames); + } + hasChanges = true; } } // 处理证书列表 + boolean certificatesChanged = false; if (data.containsKey("certificates")) { Object certificatesObj = data.get("certificates"); if (certificatesObj instanceof List) { @SuppressWarnings("unchecked") List> certMaps = (List>) certificatesObj; - List certificateList = new ArrayList<>(); + List newCertificateList = new ArrayList<>(); for (Map certMap : certMaps) { VetQualification.CertificateInfo cert = new VetQualification.CertificateInfo(); cert.setCertName((String) certMap.get("certName")); @@ -936,21 +1246,62 @@ public class VetUnifiedInfoServiceImpl implements IVetUnifiedInfoService { cert.setCertificateId(generateCertificateId()); } - certificateList.add(cert); + newCertificateList.add(cert); } - qualification.setCertificateList(certificateList); + // 比较证书列表是否发生变化 + List originalCerts = qualification.getCertificateList(); + if (originalCerts == null || originalCerts.size() != newCertificateList.size()) { + certificatesChanged = true; + } else { + for (int i = 0; i < originalCerts.size(); i++) { + VetQualification.CertificateInfo oc = originalCerts.get(i); + VetQualification.CertificateInfo nc = newCertificateList.get(i); + if (!StringUtils.equals(oc.getCertName(), nc.getCertName()) || + !StringUtils.equals(oc.getCertificateNo(), nc.getCertificateNo()) || + !StringUtils.equals(oc.getIssueOrg(), nc.getIssueOrg())) { + certificatesChanged = true; + break; + } + if (oc.getIssueDate() != null && nc.getIssueDate() != null && !oc.getIssueDate().equals(nc.getIssueDate())) { + certificatesChanged = true; + break; + } + if (oc.getExpireDate() != null && nc.getExpireDate() != null && !oc.getExpireDate().equals(nc.getExpireDate())) { + certificatesChanged = true; + break; + } + } + } + + if (certificatesChanged) { + qualification.setCertificateList(newCertificateList); + hasChanges = true; + log.info("证书列表已修改 - userId: {}", userId); + } } } + // ========== 关键修改:如果有任何变化,重置审核状态 ========== + if (hasChanges) { + String oldStatus = qualification.getAuditStatus(); + qualification.setAuditStatus("0"); + qualification.setAuditOpinion(null); + qualification.setAuditTime(null); + qualification.setAuditorId(null); + log.info("资质信息已修改,审核状态重置为待审核 - userId: {}, 原状态: {}, 新状态: 0", userId, oldStatus); + } + qualification.setUpdateBy(username); qualification.setUpdateTime(new Date()); if (qualification.getQualificationId() != null) { vetQualificationMapper.updateVetQualification(qualification); + log.info("资质信息更新成功 - qualificationId: {}, userId: {}, hasChanges: {}", + qualification.getQualificationId(), userId, hasChanges); } else { - qualification.setCreateTime(new Date()); vetQualificationMapper.insertVetQualification(qualification); + log.info("资质信息新增成功 - userId: {}", userId); } } diff --git a/chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml b/chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml index d5c8de4..49a3df2 100644 --- a/chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml +++ b/chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml @@ -1,9 +1,9 @@ + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + @@ -33,94 +33,94 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertAvatarByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertRealNameByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertTitleByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertIntroductionByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertAddressByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertSpecialtyByUserId" /> + select="com.chenhai.system.mapper.SysMedicineRecommendationMapper.getExpertWorkExperienceByUserId" /> - - + SELECT avatar FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT real_name FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT title FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT introduction FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT address FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT specialty FROM vet_personal_info WHERE user_id = #{expertId} - + SELECT work_experience FROM vet_personal_info WHERE user_id = #{expertId} select - m.id, - m.medicine_name, - m.medicine_type, - m.specification, - m.price, - m.original_price, - m.sold_quantity, - m.indications, - m.usage_dosage, - m.precautions, - m.storage_method, - m.expiry_date, - m.created_at, - m.updated_at, - m.manufacturer, - m.sales_type, - m.expert_id, - m.recommend_reason, - m.recommend_time, - m.store_name, - m.store_address, - m.store_phone, - m.business_hours, - m.store_remark, - m.longitude, - m.latitude, - m.images, - m.image_url, - e.avatar as expert_avatar, - e.real_name as expert_name, - e.expert as expert_expert, - e.introduction as expert_introduction, - e.address as expert_address, - e.expertise_area as expertise_area, - e.work_experience as work_experience + m.id, + m.medicine_name, + m.medicine_type, + m.specification, + m.price, + m.original_price, + m.sold_quantity, + m.indications, + m.usage_dosage, + m.precautions, + m.storage_method, + m.expiry_date, + m.created_at, + m.updated_at, + m.manufacturer, + m.sales_type, + m.expert_id, + m.recommend_reason, + m.recommend_time, + m.store_name, + m.store_address, + m.store_phone, + m.business_hours, + m.store_remark, + m.longitude, + m.latitude, + m.images, + m.image_url, + v.avatar as expert_avatar, + v.real_name as expert_name, + v.title as expert_expert, + v.introduction as expert_introduction, + v.address as expert_address, + v.specialty as expertise_area, + v.work_experience as work_experience from sys_medicine_recommendation m - left join vet_experts e on m.expert_id = e.expert_id - left join sys_dict_data d on m.medicine_type = d.dict_value - and d.dict_type = 'medicine_type' + left join vet_personal_info v on m.expert_id = v.user_id + left join sys_dict_data d on m.medicine_type = d.dict_value + and d.dict_type = 'medicine_type' - + + + insert into sys_medicine_recommendation @@ -202,7 +204,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" latitude, images, image_url, - + #{medicineName}, #{medicineType}, @@ -273,9 +275,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - delete from sys_medicine_recommendation where id in + delete from sys_medicine_recommendation where id in #{id} - \ No newline at end of file + diff --git a/chenhai-system/src/main/resources/mapper/vet/VetCommentsMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetCommentsMapper.xml index 0b5c227..0b7d8a5 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetCommentsMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetCommentsMapper.xml @@ -19,28 +19,33 @@ + + + select - id, - consultation_id, - reply_name, - content, - images, - is_sensitive, - sensitive_words, - created_at, - updated_at, - user_id, - - title, - hospital, - experience, - avatar + id, + consultation_id, + reply_name, + content, + images, + is_sensitive, + sensitive_words, + created_at, + updated_at, + user_id, + title, + hospital, + experience, + avatar, + expert_type, + specialty from vet_comments + - and title like concat('%', #{title}, '%') - and content like concat('%', #{content}, '%') - and category = #{category} - and sensitive_words like concat('%', #{sensitiveWords}, '%') - and article_status = #{articleStatus} - and audit_status = #{auditStatus} - and expert_id = #{expertId} - and cover_image = #{coverImage} - and subtitle like concat('%', #{subtitle}, '%') - + + and vk.title like concat('%', #{title}, '%') + + + and vk.content like concat('%', #{content}, '%') + + + and vk.category = #{category} + + + and vk.sensitive_words like concat('%', #{sensitiveWords}, '%') + + + and vk.article_status = #{articleStatus} + + + and vk.audit_status = #{auditStatus} + + + and vk.expert_id = #{expertId} + + + and vk.cover_image = #{coverImage} + + + and vk.subtitle like concat('%', #{subtitle}, '%') + + + + and vk.user_id = #{userId} + + + and vk.nick_name like concat('%', #{nickName}, '%') + + and ( vk.title like concat('%', #{searchKey}, '%') @@ -91,10 +116,9 @@ or ve.real_name like concat('%', #{searchKey}, '%') ) - - and user_id = #{userId} - and nick_name like concat('%', #{nickName}, '%') + + ORDER BY vk.create_time DESC @@ -89,6 +92,7 @@ remind_level, create_time, read_time, + cert_id, #{userId}, @@ -100,6 +104,7 @@ #{remindLevel}, #{createTime}, #{readTime}, + #{certId}, @@ -115,7 +120,8 @@ #{item.relatedId}, #{item.isRead}, #{item.remindLevel}, - #{item.createTime} + #{item.createTime}, + #{item.certId} ) @@ -132,6 +138,7 @@ remind_level = #{remindLevel}, create_time = #{createTime}, read_time = #{readTime}, + cert_id = #{certId}, where id = #{id} @@ -181,4 +188,4 @@ limit 1 - \ No newline at end of file + diff --git a/chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml index a058b6a..dbbb4a2 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml @@ -39,6 +39,7 @@ + @@ -60,7 +61,8 @@ u.user_id as u_user_id, u.nick_name as u_nick_name, u.avatar as u_avatar, - u.email as u_email + u.email as u_email, + u.phonenumber as u_phonenumber from vet_personal_info v left join sys_user u on v.user_id = u.user_id @@ -82,7 +84,6 @@ and v.iphone like concat('%', #{iphone}, '%') and v.expert_type = #{expertType} and v.email = #{email} - and v.specialty like concat('%', #{specialty}, '%') and v.audit_status = #{auditStatus} @@ -107,7 +108,15 @@ - order by v.create_time desc + + order by + CASE v.audit_status + WHEN '0' THEN 1 + WHEN '2' THEN 2 + WHEN '1' THEN 3 + ELSE 4 + END ASC, + v.create_time DESC @@ -143,6 +152,7 @@ email, nick_name, avatar, + audit_status, create_by, create_time, update_by, @@ -166,6 +176,7 @@ #{email}, #{nickName}, #{avatar}, + '0', #{createBy}, #{createTime}, #{updateBy}, @@ -196,6 +207,13 @@ avatar = #{avatar}, update_by = #{updateBy}, update_time = #{updateTime}, + + audit_status = #{auditStatus}, + audit_time = #{auditTime}, + auditor = #{auditor}, + audit_desc = #{auditDesc}, + update_by = #{updateBy}, + update_time = #{updateTime}, where id = #{id} diff --git a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml index d97ece3..c41b5d1 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml @@ -257,4 +257,4 @@ where qualification_id = #{qualificationId} - \ No newline at end of file + diff --git a/chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml index 66cffba..3c71106 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml @@ -3,7 +3,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + @@ -107,8 +107,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and v.publish_time = #{publishTime} + + ORDER BY v.create_time DESC - + - \ No newline at end of file + diff --git a/chenhai-ui/src/views/system/recommendation/index.vue b/chenhai-ui/src/views/system/recommendation/index.vue index 7a82ab0..a475516 100644 --- a/chenhai-ui/src/views/system/recommendation/index.vue +++ b/chenhai-ui/src/views/system/recommendation/index.vue @@ -10,24 +10,6 @@ @keyup.enter.native="handleQuery" /> - - - - - - - - - - - - - - - - - - - @@ -112,11 +93,6 @@ - - - - - - - - - - - - - - - - - - - - -