From ddacefaf559527af27dc28ff51b4ce3f02458bbb Mon Sep 17 00:00:00 2001
From: ChaiNingQi <2032830459@qq.com>
Date: Thu, 12 Feb 2026 11:43:52 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
chenhai-admin/pom.xml | 2 +
.../muhu/CarouselAdsController.java | 12 +-
.../muhu/DisasterWarningController.java | 8 +-
.../vet/MerchantInfoController.java | 131 +++-
.../controller/vet/VetCommentsController.java | 4 +
.../vet/VetExperienceArticleController.java | 3 +
.../controller/vet/VetExpertsController.java | 3 +
.../vet/VetKnowledgeController.java | 28 +-
.../vet/VetPersonalInfoController.java | 203 ++++++-
.../controller/vet/VetProductController.java | 37 ++
.../vet/VetQualificationController.java | 567 +++++++++++++++++-
.../vet/VetTrainingVideoController.java | 68 ++-
.../chenhai/vet/CertificateRemindTask.java | 46 +-
.../com/chenhai/vet/domain/MerchantInfo.java | 119 ++++
.../chenhai/vet/domain/VetPersonalInfo.java | 14 +
.../com/chenhai/vet/domain/VetProduct.java | 13 +
.../vet/domain/dto/BatchSubmitAuditDTO.java | 39 ++
.../vet/service/IMerchantInfoService.java | 55 ++
.../vet/service/IVetKnowledgeService.java | 5 +-
.../vet/service/IVetProductService.java | 18 +
.../vet/service/IVetTrainingVideoService.java | 11 +-
.../service/impl/MerchantInfoServiceImpl.java | 199 +++++-
.../service/impl/VetCommentsServiceImpl.java | 391 ++++++++++--
.../service/impl/VetKnowledgeServiceImpl.java | 103 +++-
.../impl/VetPersonalInfoServiceImpl.java | 120 +++-
.../service/impl/VetProductServiceImpl.java | 279 ++++++++-
.../impl/VetQualificationServiceImpl.java | 36 +-
.../impl/VetTrainingVideoServiceImpl.java | 358 +++++++----
.../SysMedicineRecommendationMapper.xml | 10 +-
.../resources/mapper/system/SysUserMapper.xml | 18 +-
.../mapper/vet/MerchantInfoMapper.xml | 41 +-
.../mapper/vet/VetPersonalInfoMapper.xml | 8 +
.../resources/mapper/vet/VetProductMapper.xml | 7 +-
.../mapper/vet/VetTrainingVideoMapper.xml | 2 +-
chenhai-ui/src/views/vet/info/index.vue | 108 ++++
35 files changed, 2684 insertions(+), 382 deletions(-)
create mode 100644 chenhai-system/src/main/java/com/chenhai/vet/domain/dto/BatchSubmitAuditDTO.java
diff --git a/chenhai-admin/pom.xml b/chenhai-admin/pom.xml
index c48e98b..2c8b99a 100644
--- a/chenhai-admin/pom.xml
+++ b/chenhai-admin/pom.xml
@@ -60,6 +60,8 @@
true
+
+
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java
index 98ddcb4..0d2d30e 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java
@@ -32,7 +32,7 @@ public class CarouselAdsController extends BaseController
* 查询轮播广告列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:list')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@GetMapping("/list")
public TableDataInfo list(CarouselAds carouselAds)
{
@@ -45,7 +45,7 @@ public class CarouselAdsController extends BaseController
* 导出轮播广告列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:export')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@Log(title = "轮播广告", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, CarouselAds carouselAds)
@@ -59,7 +59,7 @@ public class CarouselAdsController extends BaseController
* 获取轮播广告详细信息
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:query')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@GetMapping(value = "/{carouselId}")
public AjaxResult getInfo(@PathVariable("carouselId") Long carouselId)
{
@@ -70,7 +70,7 @@ public class CarouselAdsController extends BaseController
* 新增轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:add')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@Log(title = "轮播广告", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody CarouselAds carouselAds)
@@ -82,7 +82,7 @@ public class CarouselAdsController extends BaseController
* 修改轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:edit')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "轮播广告", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody CarouselAds carouselAds)
@@ -94,7 +94,7 @@ public class CarouselAdsController extends BaseController
* 删除轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:remove')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "轮播广告", businessType = BusinessType.DELETE)
@DeleteMapping("/{carouselIds}")
public AjaxResult remove(@PathVariable Long[] carouselIds)
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/DisasterWarningController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/DisasterWarningController.java
index c41e76d..9630c7f 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/DisasterWarningController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/DisasterWarningController.java
@@ -38,7 +38,7 @@ public class DisasterWarningController extends BaseController
* 查询灾害预警信息列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:warning:list')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@GetMapping("/list")
public TableDataInfo list(DisasterWarning disasterWarning)
{
@@ -51,7 +51,7 @@ public class DisasterWarningController extends BaseController
* 导出灾害预警信息列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:warning:export')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@Log(title = "灾害预警信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DisasterWarning disasterWarning)
@@ -65,7 +65,7 @@ public class DisasterWarningController extends BaseController
* 获取灾害预警信息详细信息
*/
// @PreAuthorize("@ss.hasPermi('muhu:warning:query')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
@@ -76,7 +76,7 @@ public class DisasterWarningController extends BaseController
* 新增灾害预警信息
*/
// @PreAuthorize("@ss.hasPermi('muhu:warning:add')")
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "灾害预警信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DisasterWarning disasterWarning)
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java
index fa9284c..50cd5e3 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java
@@ -1,6 +1,9 @@
package com.chenhai.web.controller.vet;
import java.util.List;
+
+import com.chenhai.common.utils.SecurityUtils;
+import com.chenhai.system.service.ISysUserService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +37,9 @@ public class MerchantInfoController extends BaseController
@Autowired
private IMerchantInfoService merchantInfoService;
+ @Autowired
+ private ISysUserService sysUserService; // 需要注入用户服务
+
/**
* 查询商家信息列表
*/
@@ -42,10 +48,28 @@ public class MerchantInfoController extends BaseController
public TableDataInfo list(MerchantInfo merchantInfo)
{
startPage();
+
+ // 获取当前用户ID
+ Long currentUserId = SecurityUtils.getUserId();
+
+ // 判断是否为管理员或管理员
+ boolean isAdmin = SecurityUtils.isAdmin(currentUserId);
+ boolean isManager = false; // 需要根据你的系统实现判断
+
+ // 如果你有判断manager的方法
+ // boolean isManager = SecurityUtils.isManager(currentUserId);
+
+ // 如果你有用户服务,可以通过用户信息判断
+ // boolean isManager = sysUserService.isManagerRole(currentUserId);
+
+ // 如果不是管理员或管理员,则只能查询自己的店铺
+ if (!isAdmin && !isManager) {
+ merchantInfo.setUserId(currentUserId);
+ }
+
List list = merchantInfoService.selectMerchantInfoList(merchantInfo);
return getDataTable(list);
}
-
/**
* 导出商家信息列表
*/
@@ -54,11 +78,28 @@ public class MerchantInfoController extends BaseController
@PostMapping("/export")
public void export(HttpServletResponse response, MerchantInfo merchantInfo)
{
+ // 获取当前用户ID
+ Long currentUserId = SecurityUtils.getUserId();
+
+ // 判断是否为管理员或管理员
+ boolean isAdmin = SecurityUtils.isAdmin(currentUserId);
+ boolean isManager = false; // 需要根据你的系统实现判断
+
+ // 如果你有判断manager的方法
+ // boolean isManager = SecurityUtils.isManager(currentUserId);
+
+ // 如果你有用户服务,可以通过用户信息判断
+ // boolean isManager = sysUserService.isManagerRole(currentUserId);
+
+ // 如果不是管理员或管理员,则只能导出自己的店铺
+ if (!isAdmin && !isManager) {
+ merchantInfo.setUserId(currentUserId);
+ }
+
List list = merchantInfoService.selectMerchantInfoList(merchantInfo);
ExcelUtil util = new ExcelUtil(MerchantInfo.class);
util.exportExcel(response, list, "商家信息数据");
}
-
/**
* 获取商家信息详细信息
*/
@@ -77,6 +118,13 @@ public class MerchantInfoController extends BaseController
@PostMapping
public AjaxResult add(@RequestBody MerchantInfo merchantInfo)
{
+ Long currentUserId = SecurityUtils.getUserId();
+ merchantInfo.setUserId(currentUserId);
+
+ // 设置默认审核状态
+ merchantInfo.setAuditStatus("0"); // 未审核
+ merchantInfo.setShopStatus("0"); // 未上架
+
return toAjax(merchantInfoService.insertMerchantInfo(merchantInfo));
}
@@ -88,6 +136,13 @@ public class MerchantInfoController extends BaseController
@PutMapping
public AjaxResult edit(@RequestBody MerchantInfo merchantInfo)
{
+ Long currentUserId = SecurityUtils.getUserId();
+ /* if (!SecurityUtils.isAdmin()) {
+ MerchantInfo existingMerchant = merchantInfoService.selectMerchantInfoByShopId(merchantInfo.getShopId());
+ if (existingMerchant == null || !currentUserId.equals(existingMerchant.getUserId())) {
+ return error("只能修改自己的商家信息");
+ }
+ }*/
return toAjax(merchantInfoService.updateMerchantInfo(merchantInfo));
}
@@ -101,4 +156,76 @@ public class MerchantInfoController extends BaseController
{
return toAjax(merchantInfoService.deleteMerchantInfoByShopIds(shopIds));
}
+
+
+ /**
+ * 提交商家审核
+ */
+ @PreAuthorize("@ss.hasPermi('vet:merchant:submit')")
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/submitAudit/{shopId}")
+ public AjaxResult submitMerchantForAudit(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(merchantInfoService.submitMerchantForAudit(shopId));
+ }
+
+ /**
+ * 审核商家
+ */
+ /* @PreAuthorize("@ss.hasPermi('vet:merchant:audit')")*/
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/audit")
+ public AjaxResult auditMerchant(@RequestBody MerchantInfo merchantInfo)
+ {
+ Long auditUserId = SecurityUtils.getUserId();
+ return toAjax(merchantInfoService.auditMerchant(
+ merchantInfo.getShopId(),
+ merchantInfo.getAuditStatus(),
+ merchantInfo.getAuditOpinion(),
+ auditUserId
+ ));
+ }
+
+ /**
+ * 上架商家
+ */
+ @PreAuthorize("@ss.hasPermi('vet:merchant:publish')")
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/publish/{shopId}")
+ public AjaxResult publishMerchant(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(merchantInfoService.publishMerchant(shopId));
+ }
+
+ /**
+ * 下架商家
+ */
+ @PreAuthorize("@ss.hasPermi('vet:merchant:offline')")
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/offline/{shopId}")
+ public AjaxResult offlineMerchant(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(merchantInfoService.offlineMerchant(shopId));
+ }
+
+ /**
+ * 取消商家审核
+ */
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/cancelAudit/{shopId}")
+ public AjaxResult cancelMerchantAudit(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(merchantInfoService.cancelMerchantAudit(shopId));
+ }
+
+ /**
+ * 重新提交商家审核(审核不通过后重新提交)
+ */
+ @PreAuthorize("@ss.hasPermi('vet:merchant:resubmit')")
+ @Log(title = "商家信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/resubmitAudit/{shopId}")
+ public AjaxResult resubmitMerchantForAudit(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(merchantInfoService.resubmitMerchantForAudit(shopId));
+ }
}
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCommentsController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCommentsController.java
index c728617..419b074 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCommentsController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCommentsController.java
@@ -1,6 +1,8 @@
package com.chenhai.web.controller.vet;
import java.util.List;
+
+import com.chenhai.common.annotation.SensitiveCheck;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -72,6 +74,7 @@ public class VetCommentsController extends BaseController
/**
* 新增兽医回复
*/
+ @SensitiveCheck
@PreAuthorize("@ss.hasPermi('vet:comments:add') or @ss.hasRole('vetnotshenhe') or @ss.hasRole('vet')")
@Log(title = "兽医回复", businessType = BusinessType.INSERT)
@PostMapping
@@ -83,6 +86,7 @@ public class VetCommentsController extends BaseController
/**
* 修改兽医回复
*/
+ @SensitiveCheck
@PreAuthorize("@ss.hasPermi('vet:comments:edit') or @ss.hasRole('vetnotshenhe') or @ss.hasRole('vet')")
@Log(title = "兽医回复", businessType = BusinessType.UPDATE)
@PutMapping
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java
index 2d07c16..86cce7b 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java
@@ -1,6 +1,7 @@
package com.chenhai.web.controller.vet;
import com.chenhai.common.annotation.Log;
+import com.chenhai.common.annotation.SensitiveCheck;
import com.chenhai.common.core.controller.BaseController;
import com.chenhai.common.core.domain.AjaxResult;
import com.chenhai.common.core.page.TableDataInfo;
@@ -300,6 +301,7 @@ public class VetExperienceArticleController extends BaseController {
/**
* 发布新文章(论坛发布)
*/
+ @SensitiveCheck
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "发布经验文章", businessType = BusinessType.INSERT)
@PostMapping
@@ -366,6 +368,7 @@ public class VetExperienceArticleController extends BaseController {
/**
* 修改文章
*/
+ @SensitiveCheck
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "修改经验文章", businessType = BusinessType.UPDATE)
@PutMapping
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExpertsController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExpertsController.java
index 652a16f..0b9300b 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExpertsController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExpertsController.java
@@ -1,6 +1,8 @@
package com.chenhai.web.controller.vet;
import java.util.List;
+
+import com.chenhai.common.annotation.SensitiveCheck;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -65,6 +67,7 @@ public class VetExpertsController extends BaseController
/**
* 新增专家信息
*/
+ @SensitiveCheck
@PreAuthorize("@ss.hasPermi('vet:experts:add') or @ss.hasRole('muhu')")
@Log(title = "专家信息", businessType = BusinessType.INSERT)
@PostMapping
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
index 54f2a4a..3085cac 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
@@ -2,6 +2,7 @@ package com.chenhai.web.controller.vet;
import java.util.List;
+import com.chenhai.common.annotation.SensitiveCheck;
import com.chenhai.common.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -24,6 +25,7 @@ import com.chenhai.vet.service.IVetKnowledgeService;
import com.chenhai.common.utils.poi.ExcelUtil;
import com.chenhai.common.core.page.TableDataInfo;
+
/**
* 兽医文章Controller
*
@@ -40,7 +42,8 @@ public class VetKnowledgeController extends BaseController
/**
* 查询兽医文章列表
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')")
+
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')or @ss.hasRole('manger')")
@GetMapping("/list")
public TableDataInfo list(VetKnowledge vetKnowledge)
{
@@ -52,7 +55,8 @@ public class VetKnowledgeController extends BaseController
/**
* 导出兽医文章列表
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:export') or @ss.hasRole('muhu')")
+
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:export') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, VetKnowledge vetKnowledge)
@@ -65,7 +69,7 @@ public class VetKnowledgeController extends BaseController
/**
* 获取兽医文章详细信息
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:query') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:query') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
@@ -75,7 +79,8 @@ public class VetKnowledgeController extends BaseController
/**
* 新增兽医文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:add') or @ss.hasRole('muhu')")
+ @SensitiveCheck
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:add') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody VetKnowledge vetKnowledge)
@@ -99,12 +104,13 @@ public class VetKnowledgeController extends BaseController
/**
* 删除兽医文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:remove') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:remove')")
@Log(title = "兽医文章", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
- return toAjax(vetKnowledgeService.deleteVetKnowledgeByIds(ids));
+ // 直接调用service方法,返回AjaxResult
+ return vetKnowledgeService.deleteVetKnowledgeByIds(ids);
}
/**
@@ -120,7 +126,7 @@ public class VetKnowledgeController extends BaseController
/**
* 审核文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:audit') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:audit') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/audit/{id}")
public AjaxResult audit(@PathVariable Long id,
@@ -135,7 +141,7 @@ public class VetKnowledgeController extends BaseController
/**
* 发布文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/publish/{id}")
public AjaxResult publish(@PathVariable Long id) {
@@ -145,7 +151,7 @@ public class VetKnowledgeController extends BaseController
/**
* 上架文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/online/{id}")
public AjaxResult online(@PathVariable Long id) {
@@ -155,7 +161,7 @@ public class VetKnowledgeController extends BaseController
/**
* 下架文章
*/
- @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/offline/{id}")
public AjaxResult offline(@PathVariable Long id, @RequestParam(required = false) String auditComment) {
@@ -178,6 +184,7 @@ public class VetKnowledgeController extends BaseController
return getDataTable(list);
}
+
/**
* 获取已发布文章的详细信息(公开接口)
*/
@@ -196,5 +203,4 @@ public class VetKnowledgeController extends BaseController
}
return error("文章不存在或未发布");
}
-
}
\ No newline at end of file
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java
index 441dd1a..00dad2e 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java
@@ -7,17 +7,24 @@ import com.chenhai.common.core.domain.model.LoginUser;
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.system.service.ISysUserService;
import com.chenhai.vet.domain.VetPersonalInfo;
+import com.chenhai.vet.domain.VetQualification;
+import com.chenhai.vet.mapper.VetQualificationMapper;
import com.chenhai.vet.service.IVetPersonalInfoService;
+import com.chenhai.vet.service.IVetQualificationService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Comparator;
+import java.util.stream.Collectors;
/**
* 兽医个人信息Controller
@@ -34,6 +41,8 @@ public class VetPersonalInfoController extends BaseController
@Autowired
private ISysUserService userService;
+ @Autowired
+ private IVetQualificationService vetQualificationService;
/**
* 获取当前登录用户ID
@@ -215,30 +224,139 @@ public class VetPersonalInfoController extends BaseController
/**
* 新增兽医个人信息
*/
+ /**
+ * 新增兽医个人信息(带完整校验)
+ */
@PreAuthorize("@ss.hasPermi('vet:info:add')")
@Log(title = "兽医个人信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody VetPersonalInfo vetPersonalInfo)
{
- // 自动设置当前用户ID
- Long currentUserId = getCurrentUserId();
- if (currentUserId == null) {
- return error("用户未登录");
- }
+ try {
+ // 1. 自动设置当前用户ID
+ Long currentUserId = getCurrentUserId();
+ if (currentUserId == null) {
+ return error("用户未登录");
+ }
+
+ // 2. 检查是否已存在该用户的个人信息
+ VetPersonalInfo existing = vetPersonalInfoService.selectVetPersonalInfoByUserId(currentUserId);
+ if (existing != null) {
+ return error("您已经创建了个人信息,请使用修改功能");
+ }
+
+ // 3. 姓名校验(2-20个汉字)
+ String realName = vetPersonalInfo.getRealName();
+ if (realName == null || realName.trim().isEmpty()) {
+ return error("真实姓名不能为空");
+ }
+
+ realName = realName.trim();
+ if (!realName.matches("^[\\u4e00-\\u9fa5]{2,20}$")) {
+ return error("姓名必须是2-20个汉字");
+ }
+ vetPersonalInfo.setRealName(realName);
+
+ // 4. 身份证校验
+ String idCard = vetPersonalInfo.getIdCard();
+ if (StringUtils.isNotEmpty(idCard)) {
+ idCard = idCard.trim().toUpperCase();
+
+ // 身份证格式校验
+ if (!isValidIdCard(idCard)) {
+ return error("身份证号格式不正确");
+ }
+
+ // 检查身份证是否已被使用
+ VetPersonalInfo query = new VetPersonalInfo();
+ query.setIdCard(idCard);
+ List idCardUsers = vetPersonalInfoService.selectVetPersonalInfoList(query);
+ if (!idCardUsers.isEmpty()) {
+ for (VetPersonalInfo user : idCardUsers) {
+ if (!user.getUserId().equals(currentUserId)) {
+ return error("该身份证号已被其他用户使用");
+ }
+ }
+ }
+
+ vetPersonalInfo.setIdCard(idCard);
+ }
+
+ // 5. 电话校验
+ String phone = vetPersonalInfo.getPhone();
+ if (StringUtils.isNotEmpty(phone)) {
+ phone = phone.trim();
+ if (!isValidPhone(phone)) {
+ return error("手机号格式不正确");
+ }
+ vetPersonalInfo.setPhone(phone);
+ }
+
+ // 6. 联系方式校验
+ String iphone = vetPersonalInfo.getIphone();
+ if (StringUtils.isNotEmpty(iphone)) {
+ iphone = iphone.trim();
+ if (!isValidPhone(iphone)) {
+ return error("联系方式格式不正确");
+ }
+ vetPersonalInfo.setIphone(iphone);
+ }
+
+ // 7. 邮箱校验
+ String email = vetPersonalInfo.getEmail();
+ if (StringUtils.isNotEmpty(email)) {
+ email = email.trim();
+ if (!isValidEmail(email)) {
+ return error("邮箱格式不正确");
+ }
+ vetPersonalInfo.setEmail(email);
+ }
+
+ // 8. 自动设置用户ID和创建者
+ vetPersonalInfo.setUserId(currentUserId);
+ vetPersonalInfo.setCreateBy(getCurrentUsername());
- // 检查是否已存在该用户的个人信息
- VetPersonalInfo existing = vetPersonalInfoService.selectVetPersonalInfoByUserId(currentUserId);
- if (existing != null) {
- return error("您已经创建了个人信息,请使用修改功能");
+ return toAjax(vetPersonalInfoService.insertVetPersonalInfo(vetPersonalInfo));
+
+ } catch (RuntimeException e) {
+ return error(e.getMessage());
}
+ }
- // 自动设置用户ID和创建者
- vetPersonalInfo.setUserId(currentUserId);
- vetPersonalInfo.setCreateBy(getCurrentUsername());
+ /**
+ * 验证身份证号格式(18位)
+ */
+ private boolean isValidIdCard(String idCard) {
+ if (StringUtils.isEmpty(idCard)) {
+ return false;
+ }
+ // 18位身份证正则
+ String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9X]$";
+ return idCard.matches(regex);
+ }
- return toAjax(vetPersonalInfoService.insertVetPersonalInfo(vetPersonalInfo));
+ /**
+ * 验证手机号格式
+ */
+ 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);
+ }
/**
* 修改兽医个人信息
*/
@@ -254,7 +372,6 @@ public class VetPersonalInfoController extends BaseController
return error("无权修改他人信息");
}
}
-
return toAjax(vetPersonalInfoService.updateVetPersonalInfo(vetPersonalInfo));
}
@@ -296,8 +413,9 @@ public class VetPersonalInfoController extends BaseController
util.exportExcel(response, list, "兽医个人信息数据");
}
+
/**
- * 获取当前登录用户的兽医信息(快捷方法)
+ * 获取当前用户的兽医信息(包含资质信息)
*/
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:query')")
@@ -309,10 +427,61 @@ public class VetPersonalInfoController extends BaseController
return error("用户未登录");
}
+ Map result = new HashMap<>();
+
+ // 1. 获取兽医个人信息
VetPersonalInfo info = vetPersonalInfoService.selectVetPersonalInfoByUserId(userId);
+
+ // 2. 获取资质信息
+ List qualifications = vetQualificationService.selectQualificationsByUserId(userId);
+
+ // 3. 如果没有个人信息记录,创建空对象
if (info == null) {
- return error("您还没有创建兽医个人信息");
+ info = new VetPersonalInfo();
+ info.setUserId(userId);
+ }
+
+ // 4. 如果有资质信息,填充到个人信息中
+ VetQualification latestQualification = null;
+ if (qualifications != null && !qualifications.isEmpty()) {
+ latestQualification = qualifications.get(0);
+
+ // 填充真实姓名
+ if (StringUtils.isNotEmpty(latestQualification.getRealName()) &&
+ StringUtils.isEmpty(info.getRealName())) {
+ info.setRealName(latestQualification.getRealName());
+ }
+
+ // 填充身份证号
+ if (StringUtils.isNotEmpty(latestQualification.getIdCard()) &&
+ StringUtils.isEmpty(info.getIdCard())) {
+ info.setIdCard(latestQualification.getIdCard());
+ }
+ }
+
+ result.put("personalInfo", info);
+ result.put("qualification", latestQualification);
+ result.put("hasQualifications", latestQualification != null);
+
+ return success(result);
+ }
+
+ /**
+ * 从资质信息填充个人信息
+ */
+ private void fillPersonalInfoFromQualification(VetPersonalInfo personalInfo, VetQualification qualification) {
+ if (qualification == null) return;
+
+ // 填充真实姓名
+ if (StringUtils.isNotEmpty(qualification.getRealName()) &&
+ StringUtils.isEmpty(personalInfo.getRealName())) {
+ personalInfo.setRealName(qualification.getRealName());
+ }
+
+ // 填充身份证号
+ if (StringUtils.isNotEmpty(qualification.getIdCard()) &&
+ StringUtils.isEmpty(personalInfo.getIdCard())) {
+ personalInfo.setIdCard(qualification.getIdCard());
}
- return success(info);
}
}
\ No newline at end of file
diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java
index a10e72b..66904ff 100644
--- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java
+++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java
@@ -3,6 +3,7 @@ package com.chenhai.web.controller.vet;
import java.util.List;
import com.chenhai.common.utils.SecurityUtils;
+import com.chenhai.vet.domain.dto.BatchSubmitAuditDTO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -195,4 +196,40 @@ public class VetProductController extends BaseController
List list = vetProductService.selectAllVetProductList(vetProduct);
return getDataTable(list);
}
+
+ /**
+ * 批量提交产品审核(按商家)
+ */
+ @PreAuthorize("@ss.hasPermi('vet:product:batch:submit')")
+ @Log(title = "兽医产品信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/batchSubmitAudit/{shopId}")
+ public AjaxResult batchSubmitProductsForAudit(@PathVariable("shopId") Long shopId)
+ {
+ return toAjax(vetProductService.batchSubmitProductsForAudit(shopId));
+ }
+ /**
+ * 根据商家ID查询产品列表
+ */
+ @Log(title = "兽医产品信息", businessType = BusinessType.OTHER)
+ @PreAuthorize("@ss.hasPermi('vet:product:list')")
+ @GetMapping("/shop/{shopId}")
+ public TableDataInfo getProductsByShopId(@PathVariable("shopId") Long shopId, VetProduct vetProduct)
+ {
+ startPage();
+ // 设置商家ID
+ vetProduct.setShopId(shopId);
+ List list = vetProductService.selectVetProductList(vetProduct);
+ return getDataTable(list);
+ }
+
+ /**
+ * 重新提交产品审核(审核不通过后重新提交)
+ */
+ @PreAuthorize("@ss.hasPermi('vet:product:resubmit')")
+ @Log(title = "兽医产品信息", businessType = BusinessType.UPDATE)
+ @PostMapping("/resubmitAudit/{id}")
+ public AjaxResult resubmitForAudit(@PathVariable("id") Long id)
+ {
+ return toAjax(vetProductService.resubmitForAudit(id));
+ }
}
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 b8c2442..ab6941d 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
@@ -7,6 +7,7 @@ import com.chenhai.common.core.page.TableDataInfo;
import com.chenhai.common.enums.BusinessType;
import com.chenhai.common.exception.ServiceException;
import com.chenhai.common.utils.SecurityUtils;
+import com.chenhai.common.utils.StringUtils;
import com.chenhai.vet.domain.VetQualification;
import com.chenhai.vet.service.IVetQualificationService;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -176,6 +177,11 @@ public class VetQualificationController extends BaseController
VetQualification query = new VetQualification();
query.setQualificationId(qualificationId);
+ // 非管理员只能查询自己的资质
+ if (!SecurityUtils.isAdmin(userId)) {
+ query.setUserId(userId);
+ }
+
// 查询指定资质
List qualifications = vetQualificationService.selectVetQualificationList(query);
if (qualifications == null || qualifications.isEmpty()) {
@@ -184,11 +190,6 @@ public class VetQualificationController extends BaseController
VetQualification qualification = qualifications.get(0);
- // 权限验证:非管理员只能查看自己的资质
- if (!SecurityUtils.isAdmin(userId) && !qualification.getUserId().equals(userId)) {
- throw new ServiceException("无权查看此资质的证书");
- }
-
// 处理分页
startPage();
@@ -235,15 +236,21 @@ public class VetQualificationController extends BaseController
{
try {
Long currentUserId = SecurityUtils.getUserId();
- boolean isAdmin = SecurityUtils.isAdmin(currentUserId);
+ // 权限检查:只有管理员和证书所有者可以查看
Map certificateInfo = vetQualificationService
- .selectCertificateWithQualificationByCertId(certId, isAdmin ? null : currentUserId);
+ .selectCertificateWithQualificationByCertId(certId, currentUserId);
if (certificateInfo == null || certificateInfo.isEmpty()) {
return AjaxResult.error("证书不存在或没有权限查看");
}
+ // 再次权限验证(双重保险)
+ Long certOwnerId = (Long) certificateInfo.get("userId");
+ if (!SecurityUtils.isAdmin(currentUserId) && !currentUserId.equals(certOwnerId)) {
+ return AjaxResult.error("无权查看此证书");
+ }
+
Object expireDateObj = certificateInfo.get("expireDate");
if (expireDateObj instanceof Date) {
Date expireDate = (Date) expireDateObj;
@@ -257,6 +264,7 @@ public class VetQualificationController extends BaseController
return AjaxResult.success(certificateInfo);
} catch (Exception e) {
+ log.error("查询证书失败,certId: {}", certId, e);
return AjaxResult.error("查询证书失败:" + e.getMessage());
}
}
@@ -439,29 +447,536 @@ public class VetQualificationController extends BaseController
/**
* 提交审核
*/
+ /**
+ * 提交审核(带完整校验,不改变原有逻辑)
+ */
@Log(title = "兽医资质", businessType = BusinessType.UPDATE)
@PostMapping("/submit")
public AjaxResult submitQualification(@RequestBody Object requestBody) {
try {
+ Long sysUserId = SecurityUtils.getUserId();
+ String username = SecurityUtils.getUsername();
+
+ if (sysUserId == null) {
+ return error("用户未登录");
+ }
+
+ // 1. 提取数据并进行校验(不改变原有数据结构)
if (requestBody instanceof Map) {
@SuppressWarnings("unchecked")
Map requestData = (Map) requestBody;
- return processNewFormat(requestData);
- } else {
+
+ // 姓名校验
+ 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();
- Map requestData = mapper.convertValue(requestBody, Map.class);
+ 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) + "个证书的编号不能为空");
+ }
- if (requestData.containsKey("realName") && requestData.containsKey("certificates")) {
- return processNewFormat(requestData);
+ 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 {
- return processOldFormat(requestBody);
+ 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) {
+ return error(e.getMessage());
} catch (Exception e) {
+ log.error("提交审核失败", e);
return AjaxResult.error("提交失败:" + e.getMessage());
}
}
+ /**
+ * 验证身份证号格式和合法性(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);
@@ -573,7 +1088,6 @@ public class VetQualificationController extends BaseController
else return "未知";
}
-
/**
* 修改单个证书信息并提交审核(根据证书ID修改单个证书)
*/
@@ -584,7 +1098,6 @@ public class VetQualificationController extends BaseController
log.info("修改单个证书并提交审核请求数据: {}", requestData);
// 1. 获取证书ID(要修改的证书)
- // 1. 获取字符串格式的ID
String certIdStr = null;
Object certIdObj = requestData.get("certId");
if (certIdObj != null) {
@@ -604,31 +1117,31 @@ public class VetQualificationController extends BaseController
return AjaxResult.error("证书ID格式错误");
}
- // 3. 继续原有逻辑(使用Long类型的certId)
+ // 3. 获取资质ID
Long qualificationId = extractLongFromObject(requestData.get("qualificationId"));
if (qualificationId == null) {
return AjaxResult.error("资质ID不能为空");
}
- // 3. 查询整个资质信息
+ // 4. 查询整个资质信息
VetQualification existingQualification = vetQualificationService.selectVetQualificationByQualificationId(qualificationId);
if (existingQualification == null) {
return AjaxResult.error("资质信息不存在");
}
- // 4. 权限检查
+ // 5. 权限检查
Long currentUserId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(currentUserId) && !existingQualification.getUserId().equals(currentUserId)) {
return AjaxResult.error("无权操作此证书");
}
- // 5. 获取现有证书列表
+ // 6. 获取现有证书列表
List certificateList = existingQualification.getCertificateList();
if (certificateList == null || certificateList.isEmpty()) {
return AjaxResult.error("该资质没有证书信息");
}
- // 6. 查找并更新指定证书
+ // 7. 查找并更新指定证书
boolean certificateFound = false;
for (VetQualification.CertificateInfo cert : certificateList) {
if (cert.getCertificateId() != null && cert.getCertificateId().equals(certId)) {
@@ -643,17 +1156,17 @@ public class VetQualificationController extends BaseController
return AjaxResult.error("未找到要修改的证书");
}
- // 7. 创建更新对象
+ // 8. 创建更新对象
VetQualification updateQualification = new VetQualification();
updateQualification.setQualificationId(qualificationId);
- // 8. 更新基础信息(如果有的话)
+ // 9. 更新基础信息(如果有的话)
updateBasicInfo(requestData, updateQualification);
- // 9. 更新证书列表到JSON
+ // 10. 更新证书列表到JSON
updateCertificatesToJson(certificateList, updateQualification);
- // 10. 更新主表字段(使用第一个证书的信息)
+ // 11. 更新主表字段(使用第一个证书的信息)
if (!certificateList.isEmpty()) {
VetQualification.CertificateInfo firstCert = certificateList.get(0);
updateQualification.setCertName(firstCert.getCertName());
@@ -664,16 +1177,16 @@ public class VetQualificationController extends BaseController
updateQualification.setExpireDate(firstCert.getExpireDate());
}
- // 11. 设置审核状态为"待审核"
+ // 12. 设置审核状态为"待审核"
updateQualification.setAuditStatus("0");
updateQualification.setAuditOpinion(null);
updateQualification.setApplyTime(new Date());
- // 12. 设置更新人信息
+ // 13. 设置更新人信息
updateQualification.setUpdateBy(SecurityUtils.getUsername());
updateQualification.setUpdateTime(new Date());
- // 13. 执行更新
+ // 14. 执行更新
int result = vetQualificationService.updateVetQualification(updateQualification);
if (result > 0) {
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 7e10b65..e1ba181 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
@@ -52,7 +52,7 @@ public class VetTrainingVideoController extends BaseController
* 查询兽医培训视频列表
*/
- @PreAuthorize("@ss.hasPermi('vet:training:list') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')")
@GetMapping("/list")
public TableDataInfo list(VetTrainingVideo vetTrainingVideo)
{
@@ -64,7 +64,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 导出兽医培训视频列表
*/
- @PreAuthorize("@ss.hasPermi('vet:training:export') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:export') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医培训视频", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, VetTrainingVideo vetTrainingVideo)
@@ -77,7 +77,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 获取兽医培训视频详细信息
*/
- @PreAuthorize("@ss.hasPermi('vet:training:query') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:query') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
@@ -87,7 +87,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 新增兽医培训视频
*/
- @PreAuthorize("@ss.hasPermi('vet:training:add') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:add') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医培训视频", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody VetTrainingVideo vetTrainingVideo)
@@ -98,7 +98,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 修改兽医培训视频
*/
- @PreAuthorize("@ss.hasPermi('vet:training:edit') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:edit') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医培训视频", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody VetTrainingVideo vetTrainingVideo)
@@ -109,18 +109,18 @@ public class VetTrainingVideoController extends BaseController
/**
* 删除兽医培训视频
*/
- @PreAuthorize("@ss.hasPermi('vet:training:remove') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:remove') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医培训视频", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
- return toAjax(vetTrainingVideoService.deleteVetTrainingVideoByIds(ids));
+ return vetTrainingVideoService.deleteVetTrainingVideoByIds(ids);
}
/**
* 上传培训视频
*/
- @PreAuthorize("@ss.hasPermi('vet:training:add') or @ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:add') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医培训视频", businessType = BusinessType.OTHER)
@PostMapping("/uploadVideo")
public AjaxResult uploadVideo(@RequestParam("file") MultipartFile file)
@@ -206,7 +206,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 批量提交审核
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@PostMapping("/batch-submit-audit")
public AjaxResult batchSubmitForAudit(@RequestBody List videoIds) {
Long userId = getCurrentUserId();
@@ -217,7 +217,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 批量审核(管理员接口)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:audit') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PostMapping("/batch-audit")
public AjaxResult batchAuditVideo(@RequestBody Map batchAuditData) {
@SuppressWarnings("unchecked")
@@ -241,7 +241,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 批量上架
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@PostMapping("/batch-publish")
public AjaxResult batchPublishVideo(@RequestBody List videoIds) {
Long userId = getCurrentUserId();
@@ -252,7 +252,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 批量下架
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@PostMapping("/batch-offline")
public AjaxResult batchOfflineVideo(@RequestBody List videoIds) {
Long userId = getCurrentUserId();
@@ -263,7 +263,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 审核单个视频(管理员接口)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:audit') or@ss.hasRole('muhu')")
@PostMapping("/audit/{videoId}")
public AjaxResult auditVideo(@PathVariable Long videoId,
@RequestBody Map auditData) {
@@ -289,7 +289,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 上架单个视频(审核通过后才能上架)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@PostMapping("/publish/{videoId}")
public AjaxResult publishVideo(@PathVariable Long videoId) {
Long userId = getCurrentUserId();
@@ -304,7 +304,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 下架单个视频
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@PostMapping("/offline/{videoId}")
public AjaxResult offlineVideo(@PathVariable Long videoId) {
Long userId = getCurrentUserId();
@@ -319,7 +319,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 提交审核(单个视频)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@PostMapping("/submit-audit/{videoId}")
public AjaxResult submitForAudit(@PathVariable Long videoId) {
Long userId = getCurrentUserId();
@@ -334,7 +334,7 @@ public class VetTrainingVideoController extends BaseController
/**
* 取消审核(单个视频)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasPermi('vet:training:cancelaudit') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@PostMapping("/cancel-audit/{videoId}")
public AjaxResult cancelAudit(@PathVariable Long videoId) {
Long userId = getCurrentUserId();
@@ -363,7 +363,7 @@ public class VetTrainingVideoController extends BaseController
* 查询公开视频列表(无需登录)
* 已上架(status=1)且已审核通过(audit_status=1)
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@GetMapping("/public/list")
public TableDataInfo publicList(VetTrainingVideo vetTrainingVideo)
{
@@ -377,7 +377,7 @@ public class VetTrainingVideoController extends BaseController
* 获取公开视频详情(无需登录)
* 只能查看已上架且审核通过的视频
*/
- @PreAuthorize("@ss.hasRole('muhu')")
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
@GetMapping("/public/{id}")
public AjaxResult getPublicInfo(@PathVariable("id") Long id)
{
@@ -388,7 +388,7 @@ public class VetTrainingVideoController extends BaseController
}
// 检查视频状态:必须已上架且审核通过
- if (!"1".equals(video.getStatus()) || !"1".equals(video.getAuditStatus())) {
+ if (!"1".equals(video.getStatus()) || !"2".equals(video.getAuditStatus())) { // 注意:审核通过是"2"
return error("视频不可访问");
}
@@ -401,5 +401,33 @@ public class VetTrainingVideoController extends BaseController
return success(video);
}
+ /**
+ * 重新提交审核(审核被拒绝后重新提交)
+ */
+ @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')or @ss.hasRole('manger')")
+ @PostMapping("/resubmit-audit/{videoId}")
+ public AjaxResult resubmitForAudit(@PathVariable Long videoId) {
+ Long userId = getCurrentUserId();
+ try {
+ // 查询视频信息
+ VetTrainingVideo video = vetTrainingVideoService.selectVetTrainingVideoById(videoId);
+ if (video == null) {
+ return error("视频不存在");
+ }
+
+ // 检查权限:管理员或视频所有者
+ boolean isAdmin = SecurityUtils.getLoginUser().getUser().isAdmin();
+ if (!isAdmin && !userId.equals(video.getUserId())) {
+ return error("无权操作此视频");
+ }
+
+ boolean success = vetTrainingVideoService.resubmitForAudit(videoId, userId);
+ return success ? success("重新提交审核成功") : error("重新提交审核失败,请确保视频处于审核拒绝状态");
+ } catch (Exception e) {
+ return error("重新提交审核失败: " + e.getMessage());
+ }
+ }
+
+
}
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java b/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java
index b05d72f..6eb6db4 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java
@@ -4,6 +4,8 @@ import com.chenhai.vet.domain.VetQualification;
import com.chenhai.vet.domain.VetNotification;
import com.chenhai.vet.mapper.VetQualificationMapper;
import com.chenhai.vet.mapper.VetNotificationMapper;
+import com.chenhai.vet.service.IVetQualificationService;
+import com.chenhai.vet.service.VetNotificationService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,27 +27,45 @@ public class CertificateRemindTask {
@Autowired
private VetNotificationMapper vetNotificationMapper;
+ @Autowired
+ private IVetQualificationService vetQualificationService;
+
+ @Autowired
+ private VetNotificationService vetNotificationService;
+
private final ObjectMapper objectMapper = new ObjectMapper();
+
// 每天上午9点执行
- /*@Scheduled(cron = "0 0 9 * * ?")*/
- @Scheduled(cron = "0 */1 * * * ?")
- public void dailyCertificateCheck() {
+ @Scheduled(cron = "0 0 9 * * ?")
+// @Scheduled(cron = "0 */1 * * * ?")
+ public void checkExpiringCertificates() {
+ /* log.info("【证书过期检查】定时任务开始执行");*/
+
try {
- // 查询所有资质记录
- List qualifications = vetQualificationMapper.selectVetQualificationList(new VetQualification());
+ // 1. 检查并发送提醒
+ vetQualificationService.checkAndSendCertificateReminders();
- for (VetQualification qualification : qualifications) {
- try {
- // 检查该资质下的所有证书(包括JSON中的)
- checkAllCertificates(qualification);
- } catch (Exception e) {
- // 静默处理单个资质检查失败
- }
+ // 2. 查询即将过期的证书并发送通知
+ List expiringQualifications =
+ vetQualificationService.selectExpiringQualifications(null);
+
+ /*log.info("【证书过期检查】找到 {} 个即将过期的资质证书", expiringQualifications.size());*/
+
+ for (VetQualification qualification : expiringQualifications) {
+ // 发送通知
+ vetNotificationService.sendCertificateExpireRemind(qualification);
+
+ /*log.info("已发送提醒:资质ID={}, 用户ID={}, 证书名称={}",
+ qualification.getQualificationId(),
+ qualification.getUserId(),
+ qualification.getCertName());*/
}
+
} catch (Exception e) {
- // 静默处理整体任务失败
+ /*log.error("【证书过期检查】执行失败:", e);*/
}
+ /*log.info("【证书过期检查】定时任务执行结束");*/
}
/**
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
index e88765f..ae5b80f 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
@@ -50,6 +50,43 @@ public class MerchantInfo extends BaseEntity
@Excel(name = "是否启用", readConverterExp = "1=启用,0禁用")
private Integer isActive;
+ /** 审核状态(字典:audit_status) */
+ @Excel(name = "审核状态", dictType = "audit_status")
+ private String auditStatus;
+
+ /** 审核意见 */
+ @Excel(name = "审核意见")
+ private String auditOpinion;
+
+ /** 店铺logo */
+ @Excel(name = "店铺logo")
+ private String shopLogo;
+
+ /** 营业执照图片 */
+ @Excel(name = "营业执照图片")
+ private String businessLicenseImage;
+
+ /** 审核人ID */
+ private Long auditUserId;
+
+ /** 审核时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date auditTime;
+
+ /** 店铺状态(字典:merchant_status) */
+ @Excel(name = "店铺状态", dictType = "sys_publish_status")
+ private String shopStatus;
+
+ /** 上架时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date publishTime;
+
+ /** 下架时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date offlineTime;
+
+
+
public void setShopId(Long shopId)
{
this.shopId = shopId;
@@ -130,6 +167,79 @@ public class MerchantInfo extends BaseEntity
return isActive;
}
+ public String getAuditStatus() {
+ return auditStatus;
+ }
+
+ public void setAuditStatus(String auditStatus) {
+ this.auditStatus = auditStatus;
+ }
+
+ public String getAuditOpinion() {
+ return auditOpinion;
+ }
+
+ public void setAuditOpinion(String auditOpinion) {
+ this.auditOpinion = auditOpinion;
+ }
+
+ public Long getAuditUserId() {
+ return auditUserId;
+ }
+
+ public void setAuditUserId(Long auditUserId) {
+ this.auditUserId = auditUserId;
+ }
+
+ public Date getAuditTime() {
+ return auditTime;
+ }
+
+ public void setAuditTime(Date auditTime) {
+ this.auditTime = auditTime;
+ }
+
+ public String getShopStatus() {
+ return shopStatus;
+ }
+
+ public void setShopStatus(String shopStatus) {
+ this.shopStatus = shopStatus;
+ }
+
+ public Date getPublishTime() {
+ return publishTime;
+ }
+
+ public void setPublishTime(Date publishTime) {
+ this.publishTime = publishTime;
+ }
+
+ public Date getOfflineTime() {
+ return offlineTime;
+ }
+
+ public void setOfflineTime(Date offlineTime) {
+ this.offlineTime = offlineTime;
+ }
+ public String getShopLogo() {
+ return shopLogo;
+ }
+
+ public void setShopLogo(String shopLogo) {
+ this.shopLogo = shopLogo;
+ }
+
+ public String getBusinessLicenseImage() {
+ return businessLicenseImage;
+ }
+
+ public void setBusinessLicenseImage(String businessLicenseImage) {
+ this.businessLicenseImage = businessLicenseImage;
+ }
+
+
+
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -141,6 +251,15 @@ public class MerchantInfo extends BaseEntity
.append("createdAt", getCreatedAt())
.append("updatedAt", getUpdatedAt())
.append("isActive", getIsActive())
+ .append("auditStatus", getAuditStatus())
+ .append("auditOpinion", getAuditOpinion())
+ .append("auditUserId", getAuditUserId())
+ .append("auditTime", getAuditTime())
+ .append("shopStatus", getShopStatus())
+ .append("publishTime", getPublishTime())
+ .append("offlineTime", getOfflineTime())
+ .append("shopLogo", getShopLogo())
+ .append("businessLicenseImage", getBusinessLicenseImage())
.toString();
}
}
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 0b6f76e..9d420bc 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
@@ -107,6 +107,10 @@ public class VetPersonalInfo extends BaseEntity
@Excel(name = "审核描述")
private String auditDesc;
+ /** 头像路径 */
+ @Excel(name = "头像路径")
+ private String avatar;
+
// 添加getter和setter
public void setId(Long id)
{
@@ -318,6 +322,15 @@ public class VetPersonalInfo extends BaseEntity
this.auditDesc = auditDesc;
}
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -342,6 +355,7 @@ public class VetPersonalInfo extends BaseEntity
.append("expertType", getExpertType())
.append("email", getEmail())
.append("nickName", getNickName())
+ .append("avatar", getAvatar())
.append("user", getUser())
.toString();
}
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetProduct.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetProduct.java
index f302c0f..4470d4d 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetProduct.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetProduct.java
@@ -147,6 +147,10 @@ public class VetProduct extends BaseEntity
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
+ /** 店铺ID */
+ @Excel(name = "店铺ID")
+ private Long shopId;
+
public void setId(Long id)
{
this.id = id;
@@ -459,6 +463,14 @@ public class VetProduct extends BaseEntity
this.auditTime = auditTime;
}
+ public Long getShopId() {
+ return shopId;
+ }
+
+ public void setShopId(Long shopId) {
+ this.shopId = shopId;
+ }
+
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -494,6 +506,7 @@ public class VetProduct extends BaseEntity
.append("auditOpinion", getAuditOpinion())
.append("auditUserId", getAuditUserId())
.append("auditTime", getAuditTime())
+ .append("shopId", getShopId())
.toString();
}
}
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/BatchSubmitAuditDTO.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/BatchSubmitAuditDTO.java
new file mode 100644
index 0000000..74454bb
--- /dev/null
+++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/dto/BatchSubmitAuditDTO.java
@@ -0,0 +1,39 @@
+// BatchSubmitAuditDTO.java
+package com.chenhai.vet.domain.dto;
+
+public class BatchSubmitAuditDTO {
+
+ /** 商家ID */
+ private Long shopId;
+
+ /** 产品ID列表 */
+ private Long[] productIds;
+
+ /** 提交人ID */
+ private Long submitUserId;
+
+ // getter和setter方法
+ public Long getShopId() {
+ return shopId;
+ }
+
+ public void setShopId(Long shopId) {
+ this.shopId = shopId;
+ }
+
+ public Long[] getProductIds() {
+ return productIds;
+ }
+
+ public void setProductIds(Long[] productIds) {
+ this.productIds = productIds;
+ }
+
+ public Long getSubmitUserId() {
+ return submitUserId;
+ }
+
+ public void setSubmitUserId(Long submitUserId) {
+ this.submitUserId = submitUserId;
+ }
+}
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java
index edca552..a2a5ca0 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java
@@ -58,4 +58,59 @@ public interface IMerchantInfoService
* @return 结果
*/
public int deleteMerchantInfoByShopId(Long shopId);
+
+ /**
+ * 提交商家审核
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ public int submitMerchantForAudit(Long shopId);
+
+ /**
+ * 审核商家
+ *
+ * @param shopId 商家ID
+ * @param auditStatus 审核状态
+ * @param auditOpinion 审核意见
+ * @param auditUserId 审核人ID
+ * @return 结果
+ */
+ public int auditMerchant(Long shopId, String auditStatus, String auditOpinion, Long auditUserId);
+
+ /**
+ * 上架商家
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ public int publishMerchant(Long shopId);
+
+ /**
+ * 下架商家
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ public int offlineMerchant(Long shopId);
+
+ /**
+ * 取消商家审核
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ public int cancelMerchantAudit(Long shopId);
+
+ // 在 IMerchantInfoService 接口中添加以下方法
+ /**
+ * 重新提交商家审核(审核不通过后重新提交)
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ int resubmitMerchantForAudit(Long shopId);
+
+
}
+
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java
index 778a741..e5aa95e 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java
@@ -51,7 +51,7 @@ public interface IVetKnowledgeService
* @param ids 需要删除的兽医文章主键集合
* @return 结果
*/
- public int deleteVetKnowledgeByIds(Long[] ids);
+ public AjaxResult deleteVetKnowledgeByIds(Long[] ids);
/**
* 删除兽医文章信息
@@ -59,8 +59,7 @@ public interface IVetKnowledgeService
* @param id 兽医文章主键
* @return 结果
*/
- public int deleteVetKnowledgeById(Long id);
-
+ public AjaxResult deleteVetKnowledgeById(Long id);
/**
* 提交审核
* @param id 文章ID
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java
index 06a99d7..e81639b 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java
@@ -110,4 +110,22 @@ public interface IVetProductService
*/
public List selectAllVetProductList(VetProduct vetProduct);
+ /**
+ * 批量提交产品审核(按商家)
+ *
+ * @param shopId 商家ID
+ * @return 结果
+ */
+ public int batchSubmitProductsForAudit(Long shopId);
+ // 在 IVetProductService 接口中添加以下方法
+ /**
+ * 重新提交审核(审核不通过后重新提交)
+ *
+ * @param id 产品ID
+ * @return 结果
+ */
+ int resubmitForAudit(Long id);
+
+
+
}
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java
index 88969bf..9b0a499 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java
@@ -1,6 +1,8 @@
package com.chenhai.vet.service;
import java.util.List;
+
+import com.chenhai.common.core.domain.AjaxResult;
import com.chenhai.vet.domain.VetTrainingVideo;
/**
@@ -45,20 +47,19 @@ public interface IVetTrainingVideoService
/**
* 批量删除兽医培训视频
- *
+ *
* @param ids 需要删除的兽医培训视频主键集合
* @return 结果
*/
- public int deleteVetTrainingVideoByIds(Long[] ids);
+ public AjaxResult deleteVetTrainingVideoByIds(Long[] ids);
/**
* 删除兽医培训视频信息
- *
+ *
* @param id 兽医培训视频主键
* @return 结果
*/
- public int deleteVetTrainingVideoById(Long id);
-
+ public AjaxResult deleteVetTrainingVideoById(Long id);
// 批量操作
int batchSubmitForAudit(List videoIds, Long userId);
int batchAuditVideo(List videoIds, String auditStatus, String auditOpinion, Long auditUserId);
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java
index 9e93fa1..b0aa0d9 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java
@@ -1,6 +1,7 @@
package com.chenhai.vet.service.impl;
import java.util.List;
+import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chenhai.vet.mapper.MerchantInfoMapper;
@@ -44,50 +45,204 @@ public class MerchantInfoServiceImpl implements IMerchantInfoService
}
/**
- * 新增商家信息
+ * 批量删除商家信息
*
- * @param merchantInfo 商家信息
+ * @param shopIds 需要删除的商家信息主键
* @return 结果
*/
@Override
- public int insertMerchantInfo(MerchantInfo merchantInfo)
+ public int deleteMerchantInfoByShopIds(Long[] shopIds)
{
- return merchantInfoMapper.insertMerchantInfo(merchantInfo);
+ return merchantInfoMapper.deleteMerchantInfoByShopIds(shopIds);
}
/**
- * 修改商家信息
+ * 删除商家信息信息
*
- * @param merchantInfo 商家信息
+ * @param shopId 商家信息主键
* @return 结果
*/
@Override
- public int updateMerchantInfo(MerchantInfo merchantInfo)
+ public int deleteMerchantInfoByShopId(Long shopId)
{
- return merchantInfoMapper.updateMerchantInfo(merchantInfo);
+ return merchantInfoMapper.deleteMerchantInfoByShopId(shopId);
}
/**
- * 批量删除商家信息
- *
- * @param shopIds 需要删除的商家信息主键
- * @return 结果
+ * 提交商家审核
*/
@Override
- public int deleteMerchantInfoByShopIds(Long[] shopIds)
- {
- return merchantInfoMapper.deleteMerchantInfoByShopIds(shopIds);
+ public int submitMerchantForAudit(Long shopId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ // 检查是否已提交审核
+ if (canSubmitForAudit(merchant)) {
+ merchant.setAuditStatus("1"); // 审核中
+ merchant.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ return 0;
}
/**
- * 删除商家信息信息
- *
- * @param shopId 商家信息主键
- * @return 结果
+ * 审核商家
*/
@Override
- public int deleteMerchantInfoByShopId(Long shopId)
- {
- return merchantInfoMapper.deleteMerchantInfoByShopId(shopId);
+ public int auditMerchant(Long shopId, String auditStatus, String auditOpinion, Long auditUserId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ merchant.setAuditStatus(auditStatus);
+ merchant.setAuditOpinion(auditOpinion);
+ merchant.setAuditUserId(auditUserId);
+ merchant.setAuditTime(new Date());
+ merchant.setUpdatedAt(new Date());
+
+ // 如果审核通过,自动将店铺状态设为待上架
+ if ("2".equals(auditStatus)) { // 审核通过
+ if ("0".equals(merchant.getShopStatus())) { // 如果当前是未上架状态
+ merchant.setShopStatus("0"); // 设为待上架状态
+ }
+ }
+
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ /**
+ * 上架商家
+ */
+ @Override
+ public int publishMerchant(Long shopId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ // 检查是否可以上架:需要审核通过且当前状态为待上架
+ if ("2".equals(merchant.getAuditStatus()) && "1".equals(merchant.getShopStatus())) {
+ merchant.setShopStatus("1"); // 已上架
+ merchant.setPublishTime(new Date());
+ merchant.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ return 0;
+ }
+
+ /**
+ * 下架商家
+ */
+ @Override
+ public int offlineMerchant(Long shopId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ // 只有已上架的商家才能下架
+ if ("2".equals(merchant.getShopStatus())) { // 已上架状态
+ merchant.setShopStatus("0"); // 已下架
+ merchant.setOfflineTime(new Date());
+ merchant.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ return 0;
+ }
+
+ /**
+ * 取消商家审核
+ */
+ @Override
+ public int cancelMerchantAudit(Long shopId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ // 只有审核中的状态才能取消
+ if ("1".equals(merchant.getAuditStatus())) { // 审核中
+ merchant.setAuditStatus("0"); // 设为未审核
+ merchant.setAuditOpinion(null);
+ merchant.setAuditUserId(null);
+ merchant.setAuditTime(null);
+ merchant.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ return 0;
+ }
+
+ /**
+ * 检查商家是否可以提交审核
+ */
+ private boolean canSubmitForAudit(MerchantInfo merchant) {
+ // 只有未审核状态才能提交
+ return "0".equals(merchant.getAuditStatus()) ||
+ (merchant.getAuditStatus() == null);
}
+
+
+
+ @Override
+ public int insertMerchantInfo(MerchantInfo merchantInfo) {
+ // 设置默认值
+ if (merchantInfo.getAuditStatus() == null) {
+ merchantInfo.setAuditStatus("0"); // 未审核
+ }
+ if (merchantInfo.getShopStatus() == null) {
+ merchantInfo.setShopStatus("0"); // 未上架
+ }
+ if (merchantInfo.getCreatedAt() == null) {
+ merchantInfo.setCreatedAt(new Date());
+ }
+ if (merchantInfo.getUpdatedAt() == null) {
+ merchantInfo.setUpdatedAt(new Date());
+ }
+ return merchantInfoMapper.insertMerchantInfo(merchantInfo);
+ }
+
+ @Override
+ public int updateMerchantInfo(MerchantInfo merchantInfo) {
+ merchantInfo.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchantInfo);
+ }
+
+ /**
+ * 重新提交商家审核(审核不通过后重新提交)
+ */
+ @Override
+ public int resubmitMerchantForAudit(Long shopId) {
+ MerchantInfo merchant = merchantInfoMapper.selectMerchantInfoByShopId(shopId);
+ if (merchant == null) {
+ return 0;
+ }
+
+ // 检查是否可以重新提交审核:只有审核不通过状态才能重新提交
+ if (canResubmitForAudit(merchant)) {
+ merchant.setAuditStatus("1"); // 审核中
+ merchant.setAuditOpinion(null); // 清空之前的审核意见
+ merchant.setAuditUserId(null); // 清空审核人
+ merchant.setAuditTime(null); // 清空审核时间
+ merchant.setUpdatedAt(new Date());
+ return merchantInfoMapper.updateMerchantInfo(merchant);
+ }
+
+ return 0;
+ }
+
+ /**
+ * 检查商家是否可以重新提交审核
+ */
+ private boolean canResubmitForAudit(MerchantInfo merchant) {
+ // 只有审核不通过状态才能重新提交
+ return "3".equals(merchant.getAuditStatus());
+ }
+
}
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 41ddb89..4c42a00 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
@@ -18,6 +18,8 @@ import com.chenhai.vet.service.IVetCommentsService;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.JsonNode;
/**
* 兽医回复Service业务层处理
@@ -39,6 +41,8 @@ public class VetCommentsServiceImpl implements IVetCommentsService
@Autowired
private IVetPersonalInfoService vetPersonalInfoService;
+ // 创建Jackson ObjectMapper实例
+ private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 查询兽医回复
@@ -50,6 +54,12 @@ public class VetCommentsServiceImpl implements IVetCommentsService
public VetComments selectVetCommentsById(Long id)
{
VetComments comment = vetCommentsMapper.selectVetCommentsById(id);
+
+ // 处理images字段:如果是JSON字符串,解析为普通字符串
+ if (comment != null && StringUtils.isNotEmpty(comment.getImages())) {
+ comment.setImages(parseImagesFromJsonString(comment.getImages()));
+ }
+
// 如果查询时字段为空,尝试填充兽医信息
if (comment != null && (StringUtils.isEmpty(comment.getTitle()) ||
StringUtils.isEmpty(comment.getHospital()) ||
@@ -71,7 +81,13 @@ public class VetCommentsServiceImpl implements IVetCommentsService
List list = vetCommentsMapper.selectVetCommentsList(vetComments);
// 为每个记录填充兽医信息
if (list != null) {
- list.forEach(this::fillVetInfoToComment);
+ list.forEach(comment -> {
+ // 处理images字段
+ if (StringUtils.isNotEmpty(comment.getImages())) {
+ comment.setImages(parseImagesFromJsonString(comment.getImages()));
+ }
+ fillVetInfoToComment(comment);
+ });
}
return list;
}
@@ -86,6 +102,9 @@ public class VetCommentsServiceImpl implements IVetCommentsService
@Transactional
public int insertVetComments(VetComments vetComments)
{
+ log.info("开始插入兽医回复,consultationId: {}", vetComments.getConsultationId());
+ log.info("原始images值: {}", vetComments.getImages());
+
// 获取当前登录用户信息
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser currentUser = null;
@@ -108,7 +127,6 @@ public class VetCommentsServiceImpl implements IVetCommentsService
// 自动填充兽医职称、医院和经验信息到数据库字段中
vetComments = autoFillVetInfoToFields(vetComments, loginUser.getUserId());
-
}
// 设置默认值
@@ -116,6 +134,11 @@ public class VetCommentsServiceImpl implements IVetCommentsService
vetComments.setIsSensitive(0);
}
+ // ========== 核心修复:确保images是有效的JSON字符串 ==========
+ String processedImages = ensureValidJsonStringForImages(vetComments.getImages());
+ log.info("处理后的images值: {}", processedImages);
+ vetComments.setImages(processedImages);
+
int result = vetCommentsMapper.insertVetComments(vetComments);
// 更新问诊单的回复数量和状态
@@ -126,8 +149,7 @@ public class VetCommentsServiceImpl implements IVetCommentsService
consultation.setStatus("已回复");
consultationFormsService.updateMuhuConsultationForms(consultation);
- // 如果是首次回复,可以记录回复兽医信息(如果有相应字段)
- // 注意:这里需要根据实际问诊单结构来调整
+ // 记录回复兽医信息到问诊单
recordVetInfoToConsultation(consultation, vetComments);
}
} catch (Exception e) {
@@ -137,6 +159,201 @@ public class VetCommentsServiceImpl implements IVetCommentsService
return result;
}
+ /**
+ * 确保images字段是有效的JSON字符串(存储为逗号分隔的字符串)
+ */
+ private String ensureValidJsonStringForImages(String input) {
+ // 1. 如果为空,返回空字符串的JSON
+ if (StringUtils.isEmpty(input)) {
+ return "\"\""; // 空字符串的JSON表示
+ }
+
+ String trimmed = input.trim();
+ log.debug("原始images输入: {}", trimmed);
+
+ // 2. 如果已经是有效的JSON字符串,直接返回
+ if (isValidJson(trimmed) && trimmed.startsWith("\"") && trimmed.endsWith("\"")) {
+ log.debug("已是有效JSON字符串,直接返回");
+ return trimmed;
+ }
+
+ // 3. 处理各种格式的输入
+ try {
+ // 3.1 如果是逗号分隔的字符串,直接转为JSON字符串
+ if (trimmed.contains(",")) {
+ return convertToJsonString(trimmed);
+ }
+
+ // 3.2 如果是JSON数组,提取内容转为字符串
+ if (trimmed.startsWith("[")) {
+ return extractFromJsonArray(trimmed);
+ }
+
+ // 3.3 单个图片路径,直接包装为JSON字符串
+ return wrapAsJsonString(trimmed);
+ } catch (Exception e) {
+ log.error("处理images字段失败,使用空字符串: {}", trimmed, e);
+ return "\"\"";
+ }
+ }
+
+ /**
+ * 将普通字符串转为JSON字符串
+ */
+ private String convertToJsonString(String plainText) {
+ String cleaned = cleanImageText(plainText);
+ String escaped = escapeForJson(cleaned);
+ String result = "\"" + escaped + "\"";
+ log.debug("普通文本转JSON字符串结果: {}", result);
+ return result;
+ }
+
+ /**
+ * 从JSON数组中提取内容转为字符串
+ */
+ private String extractFromJsonArray(String jsonArray) {
+ try {
+ // 解析JSON数组
+ JsonNode arrayNode = objectMapper.readTree(jsonArray);
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < arrayNode.size(); i++) {
+ String path = arrayNode.get(i).asText();
+ sb.append(cleanImagePath(path));
+ if (i < arrayNode.size() - 1) {
+ sb.append(",");
+ }
+ }
+
+ String result = "\"" + escapeForJson(sb.toString()) + "\"";
+ log.debug("JSON数组转字符串结果: {}", result);
+ return result;
+ } catch (Exception e) {
+ log.warn("解析JSON数组失败,直接处理原始字符串: {}", jsonArray, e);
+ return convertToJsonString(jsonArray);
+ }
+ }
+
+ /**
+ * 包装单个路径为JSON字符串
+ */
+ private String wrapAsJsonString(String imagePath) {
+ String cleanedPath = cleanImagePath(imagePath);
+ String escapedPath = escapeForJson(cleanedPath);
+ String result = "\"" + escapedPath + "\"";
+ log.debug("单个图片转JSON字符串结果: {}", result);
+ return result;
+ }
+
+ /**
+ * 解析数据库中的JSON字符串为普通字符串
+ */
+ private String parseImagesFromJsonString(String jsonString) {
+ if (StringUtils.isEmpty(jsonString)) {
+ return "";
+ }
+
+ String trimmed = jsonString.trim();
+
+ // 如果是JSON字符串(以双引号开头结尾),提取内容
+ if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) {
+ try {
+ // 解析JSON字符串
+ String parsed = objectMapper.readValue(trimmed, String.class);
+ return parsed;
+ } catch (Exception e) {
+ log.warn("解析images JSON字符串失败: {}", trimmed, e);
+ // 尝试直接提取内容
+ return trimmed.substring(1, trimmed.length() - 1);
+ }
+ }
+
+ // 如果不是JSON字符串,直接返回
+ return trimmed;
+ }
+
+ /**
+ * 清理图片文本(处理带冒号的情况)
+ */
+ private String cleanImageText(String text) {
+ if (StringUtils.isEmpty(text)) {
+ return "";
+ }
+
+ String cleaned = text.trim();
+
+ // 移除开头的冒号和空格
+ if (cleaned.startsWith(":")) {
+ cleaned = cleaned.substring(1).trim();
+ }
+
+ // 移除多余的引号
+ if (cleaned.startsWith("\"") && cleaned.endsWith("\"")) {
+ cleaned = cleaned.substring(1, cleaned.length() - 1);
+ }
+ if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
+ cleaned = cleaned.substring(1, cleaned.length() - 1);
+ }
+
+ // 如果是数组形式,移除方括号
+ if (cleaned.startsWith("[") && cleaned.endsWith("]")) {
+ cleaned = cleaned.substring(1, cleaned.length() - 1);
+ }
+
+ return cleaned;
+ }
+
+ /**
+ * 清理图片路径
+ */
+ private String cleanImagePath(String path) {
+ if (StringUtils.isEmpty(path)) {
+ return "";
+ }
+
+ String cleaned = path.trim();
+
+ // 移除多余的引号
+ if (cleaned.startsWith("\"") && cleaned.endsWith("\"")) {
+ cleaned = cleaned.substring(1, cleaned.length() - 1);
+ }
+ if (cleaned.startsWith("'") && cleaned.endsWith("'")) {
+ cleaned = cleaned.substring(1, cleaned.length() - 1);
+ }
+
+ return cleaned;
+ }
+
+ /**
+ * JSON转义
+ */
+ private String escapeForJson(String str) {
+ if (str == null) {
+ return "";
+ }
+ return str.replace("\\", "\\\\")
+ .replace("\"", "\\\"")
+ .replace("\n", "\\n")
+ .replace("\r", "\\r")
+ .replace("\t", "\\t");
+ }
+
+ /**
+ * 检查字符串是否为有效的JSON
+ */
+ private boolean isValidJson(String jsonStr) {
+ if (StringUtils.isEmpty(jsonStr)) {
+ return false;
+ }
+ try {
+ objectMapper.readTree(jsonStr);
+ return true;
+ } catch (Exception e) {
+ log.debug("JSON验证失败: {}, 错误: {}", jsonStr, e.getMessage());
+ return false;
+ }
+ }
+
/**
* 记录兽医信息到问诊单(可选)
*/
@@ -198,8 +415,6 @@ public class VetCommentsServiceImpl implements IVetCommentsService
log.info("已自动填充兽医信息到字段:职称={}, 医院={}, 经验={}",
vetInfo.getTitle(), vetInfo.getHospital(), vetInfo.getWorkExperience());
- // 可选:同时在内容中追加兽医信息
- vetComments = appendVetInfoToContent(vetComments, vetInfo);
} else {
log.warn("用户ID:{} 未找到兽医个人信息", userId);
@@ -212,53 +427,6 @@ public class VetCommentsServiceImpl implements IVetCommentsService
return vetComments;
}
- /**
- * 可选方法:将兽医信息追加到回复内容末尾(如果需要)
- */
- private VetComments appendVetInfoToContent(VetComments vetComments, VetPersonalInfo vetInfo) {
- // 是否需要在内容中显示兽医信息的配置
- boolean showVetInfoInContent = true; // 可以从配置读取
-
- if (showVetInfoInContent) {
- StringBuilder vetSignature = new StringBuilder();
-
- // 构建兽医信息签名
- if (StringUtils.isNotEmpty(vetInfo.getTitle())) {
- vetSignature.append(vetInfo.getTitle());
- }
-
- if (StringUtils.isNotEmpty(vetInfo.getHospital())) {
- if (vetSignature.length() > 0) {
- vetSignature.append(" · ");
- }
- vetSignature.append(vetInfo.getHospital());
- }
-
- if (StringUtils.isNotEmpty(vetInfo.getWorkExperience())) {
- if (vetSignature.length() > 0) {
- vetSignature.append(" · ");
- }
- vetSignature.append("执业经验:").append(vetInfo.getWorkExperience());
- }
-
- // 如果有兽医信息,则添加到回复内容中
- if (vetSignature.length() > 0) {
- String originalContent = vetComments.getContent();
- String vetInfoStr = "\n\n---\n" + vetSignature.toString();
-
- // 检查是否已经包含兽医信息,避免重复添加
- if (originalContent != null && !originalContent.contains("---\n")) {
- vetComments.setContent(originalContent + vetInfoStr);
- log.info("已在回复内容中追加兽医信息:{}", vetSignature.toString());
- } else if (originalContent == null) {
- vetComments.setContent(vetInfoStr.substring(2)); // 去掉开头的换行符
- }
- }
- }
-
- return vetComments;
- }
-
/**
* 为已有的评论记录填充兽医信息
* 用于查询时,如果发现字段为空,从兽医表补充信息
@@ -382,6 +550,9 @@ public class VetCommentsServiceImpl implements IVetCommentsService
@Override
public int updateVetComments(VetComments vetComments)
{
+ log.info("开始修改兽医回复,ID: {}", vetComments.getId());
+ log.info("修改前原始images值: {}", vetComments.getImages());
+
boolean isAdmin = SecurityUtils.hasRole("admin") || SecurityUtils.hasPermi("*:*:*");
if (SecurityUtils.hasRole("vetnotshenhe") && !isAdmin) {
@@ -395,9 +566,100 @@ public class VetCommentsServiceImpl implements IVetCommentsService
}
}
+ // ========== 关键修改:直接处理images字段 ==========
+ if (vetComments.getImages() != null) {
+ String images = vetComments.getImages().trim();
+ log.info("修改接口收到的images值: {}", images);
+
+ // 如果前端传的是JSON数组格式
+ if (images.startsWith("[") && images.endsWith("]")) {
+ try {
+ // 解析JSON数组
+ JsonNode arrayNode = objectMapper.readTree(images);
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < arrayNode.size(); i++) {
+ String path = arrayNode.get(i).asText();
+ sb.append(path);
+ if (i < arrayNode.size() - 1) {
+ sb.append(",");
+ }
+ }
+
+ // 包装为JSON字符串
+ String result = "\"" + sb.toString() + "\"";
+ vetComments.setImages(result);
+ log.info("修改后images值: {}", result);
+ } catch (Exception e) {
+ log.error("解析images JSON数组失败,使用空字符串", e);
+ vetComments.setImages("\"\"");
+ }
+ }
+ // 如果已经是JSON字符串格式,直接使用
+ else if (images.startsWith("\"") && images.endsWith("\"")) {
+ log.info("images已是JSON字符串格式,直接使用");
+ }
+ // 如果是普通字符串,包装为JSON字符串
+ else {
+ String result = "\"" + escapeForJson(images) + "\"";
+ vetComments.setImages(result);
+ log.info("普通字符串包装为JSON字符串: {}", result);
+ }
+ }
+
+ // 如果用户信息变更,更新相关字段
+ updateUserInfoIfChanged(vetComments);
+
return vetCommentsMapper.updateVetComments(vetComments);
}
+
+ /**
+ * 如果用户信息变更,更新相关字段
+ */
+ private void updateUserInfoIfChanged(VetComments vetComments) {
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (loginUser == null) {
+ return;
+ }
+
+ Long currentUserId = loginUser.getUserId();
+ SysUser currentUser = loginUser.getUser();
+
+ try {
+ VetComments originalComment = vetCommentsMapper.selectVetCommentsById(vetComments.getId());
+ if (originalComment != null) {
+ // 检查用户是否变更(理论上不应该变,但做保护)
+ if (!currentUserId.equals(originalComment.getUserId())) {
+ log.warn("用户尝试修改他人回复,用户ID: {}, 原用户ID: {}",
+ currentUserId, originalComment.getUserId());
+ throw new RuntimeException("只能修改自己的回复");
+ }
+
+ // 更新头像和回复名称(如果相关字段被修改)
+ if (StringUtils.isNotEmpty(currentUser.getNickName()) &&
+ (vetComments.getReplyName() == null || vetComments.getReplyName().isEmpty())) {
+ vetComments.setReplyName(currentUser.getNickName());
+ }
+
+ if (StringUtils.isNotEmpty(currentUser.getAvatar()) &&
+ (vetComments.getAvatar() == null || vetComments.getAvatar().isEmpty())) {
+ vetComments.setAvatar(currentUser.getAvatar());
+ }
+
+ // 自动填充兽医信息(如果字段为空)
+ if (StringUtils.isEmpty(vetComments.getTitle()) ||
+ StringUtils.isEmpty(vetComments.getHospital()) ||
+ StringUtils.isEmpty(vetComments.getExperience())) {
+ autoFillVetInfoToFields(vetComments, currentUserId);
+ }
+ }
+ } catch (Exception e) {
+ log.error("更新用户信息时发生错误", e);
+ // 不中断主流程
+ }
+ }
+
/**
* 批量删除兽医回复
*
@@ -447,4 +709,27 @@ public class VetCommentsServiceImpl implements IVetCommentsService
return vetCommentsMapper.deleteVetCommentsById(id);
}
+
+ /**
+ * 测试方法:验证图片格式转换
+ */
+ public void testImagesConversion() {
+ String[] testCases = {
+ "",
+ "/profile/upload/2026/02/10/image1.png",
+ "/path1.png,/path2.png",
+ "[\"/path1.png\",\"/path2.png\"]",
+ ": \"/path1.png,/path2.png",
+ "'/path1.png','/path2.png'",
+ "/005 10/01a/2026/02/05/tnp 00820:0097160397100254-0590i -60879231 da451 20260205181217028.3p,/pr061/0108/2026/02/10/3.20260210105754030.p2"
+ };
+
+ for (String testCase : testCases) {
+ String result = ensureValidJsonStringForImages(testCase);
+ log.info("测试输入: {}", testCase);
+ log.info("数据库存储: {}", result);
+ log.info("查询解析: {}", parseImagesFromJsonString(result));
+ 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 481d170..d1110c9 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
@@ -74,20 +74,108 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService
* 批量删除兽医文章
*/
@Override
- public int deleteVetKnowledgeByIds(Long[] ids)
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult deleteVetKnowledgeByIds(Long[] ids)
{
- return vetKnowledgeMapper.deleteVetKnowledgeByIds(ids);
+ try {
+ Long currentUserId = SecurityUtils.getUserId();
+ if (currentUserId == null) {
+ return AjaxResult.error("用户未登录");
+ }
+
+ int successCount = 0;
+ int failedCount = 0;
+ List failedMessages = new ArrayList<>();
+
+ for (Long id : ids) {
+ try {
+ // 查询文章信息
+ VetKnowledge article = vetKnowledgeMapper.selectVetKnowledgeById(id);
+ if (article == null) {
+ failedCount++;
+ failedMessages.add("文章ID " + id + " 不存在");
+ 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;
+ }
+ }
+
+ // 执行删除
+ int result = vetKnowledgeMapper.deleteVetKnowledgeById(id);
+ if (result > 0) {
+ successCount++;
+ } else {
+ failedCount++;
+ failedMessages.add("文章ID " + id + " 删除失败");
+ }
+ } catch (Exception e) {
+ failedCount++;
+ failedMessages.add("文章ID " + id + " 删除异常: " + e.getMessage());
+ }
+ }
+
+ if (failedCount == 0) {
+ return AjaxResult.success("成功删除 " + successCount + " 篇文章");
+ } else {
+ return AjaxResult.warn("成功删除 " + successCount + " 篇,失败 " + failedCount + " 篇", failedMessages);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return AjaxResult.error("批量删除失败: " + e.getMessage());
+ }
}
/**
* 删除兽医文章信息
*/
@Override
- public int deleteVetKnowledgeById(Long id)
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult deleteVetKnowledgeById(Long id)
{
- return vetKnowledgeMapper.deleteVetKnowledgeById(id);
- }
+ try {
+ Long currentUserId = SecurityUtils.getUserId();
+ if (currentUserId == null) {
+ return AjaxResult.error("用户未登录");
+ }
+ // 查询文章信息
+ VetKnowledge article = vetKnowledgeMapper.selectVetKnowledgeById(id);
+ if (article == null) {
+ return AjaxResult.error("文章不存在");
+ }
+
+ // 检查是否是自己的文章(通过创建者判断)
+ String createBy = article.getCreateBy();
+ String currentUsername = SecurityUtils.getUsername();
+
+ if (createBy == null || !createBy.equals(currentUsername)) {
+ // 如果不是自己的文章,检查是否是管理员
+ if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里
+ return AjaxResult.error("不是您发布的文章,无法删除");
+ }
+ }
+
+ int result = vetKnowledgeMapper.deleteVetKnowledgeById(id);
+ if (result > 0) {
+ return AjaxResult.success("文章删除成功");
+ } else {
+ return AjaxResult.error("文章删除失败");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return AjaxResult.error("删除失败: " + e.getMessage());
+ }
+ }
/**
* 提交审核:将审核状态改为审核中
*/
@@ -230,8 +318,6 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService
if (current == null) {
return AjaxResult.error("文章不存在");
}
-
-
// 只有已下架状态(2)的文章才能上架
if (!"2".equals(current.getArticleStatus())) {
return AjaxResult.error("只有已下架的文章可以上架");
@@ -287,7 +373,8 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService
VetKnowledge vetKnowledge = new VetKnowledge();
vetKnowledge.setId(id);
- vetKnowledge.setArticleStatus("2"); // 已下架
+ vetKnowledge.setAuditStatus("0");
+ vetKnowledge.setArticleStatus("0"); // 草稿
vetKnowledge.setAuditComment(auditComment.trim()); // 存储下架原因到审核意见字段
String username = SecurityUtils.getUsername();
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 224a5a3..e5bb352 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
@@ -4,6 +4,7 @@ import com.chenhai.common.core.domain.entity.SysUser;
import com.chenhai.common.core.domain.model.LoginUser;
import com.chenhai.common.utils.DateUtils;
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;
@@ -105,11 +106,12 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
return list;
}
-
-
/**
* 新增兽医个人信息
*/
+ /**
+ * 新增兽医个人信息(Service层校验)
+ */
@Override
@Transactional
public int insertVetPersonalInfo(VetPersonalInfo vetPersonalInfo) {
@@ -120,48 +122,64 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
// 1. 强制绑定当前登录用户ID
vetPersonalInfo.setUserId(loginUser.getUserId());
- // 2. 设置创建者和更新者
+ // 2. 检查是否已存在该用户的兽医信息
+ VetPersonalInfo existing = vetPersonalInfoMapper.selectVetPersonalInfoByUserId(vetPersonalInfo.getUserId());
+ if (existing != null) {
+ throw new RuntimeException("该用户已存在兽医信息,请使用更新操作");
+ }
+
+ // 3. 身份证唯一性检查
+ if (StringUtils.isNotEmpty(vetPersonalInfo.getIdCard())) {
+ VetPersonalInfo query = new VetPersonalInfo();
+ query.setIdCard(vetPersonalInfo.getIdCard());
+ List list = vetPersonalInfoMapper.selectVetPersonalInfoList(query);
+ if (!list.isEmpty()) {
+ for (VetPersonalInfo info : list) {
+ if (!info.getUserId().equals(vetPersonalInfo.getUserId())) {
+ throw new RuntimeException("该身份证号已被其他用户使用");
+ }
+ }
+ }
+ }
+
+ // 4. 设置创建者和更新者
vetPersonalInfo.setCreateBy(loginUser.getUsername());
vetPersonalInfo.setUpdateBy(loginUser.getUsername());
- // 3. 从用户表获取其他信息
+ // 5. 从用户表获取其他信息
SysUser currentUser = sysUserService.selectUserById(loginUser.getUserId());
if (currentUser != null) {
+ // 如果头像为空,使用用户头像
+ if (StringUtils.isEmpty(vetPersonalInfo.getAvatar())
+ && StringUtils.isNotEmpty(currentUser.getAvatar())) {
+ vetPersonalInfo.setAvatar(currentUser.getAvatar());
+ }
// 如果昵称为空,使用用户昵称
- if ((vetPersonalInfo.getNickName() == null || vetPersonalInfo.getNickName().isEmpty())
- && currentUser.getNickName() != null) {
+ if (StringUtils.isEmpty(vetPersonalInfo.getNickName())
+ && StringUtils.isNotEmpty(currentUser.getNickName())) {
vetPersonalInfo.setNickName(currentUser.getNickName());
}
-
// 如果性别为空,使用用户性别
- if ((vetPersonalInfo.getGender() == null || vetPersonalInfo.getGender().isEmpty())
- && currentUser.getSex() != null) {
+ if (StringUtils.isEmpty(vetPersonalInfo.getGender())
+ && StringUtils.isNotEmpty(currentUser.getSex())) {
vetPersonalInfo.setGender(currentUser.getSex());
}
-
// 如果邮箱为空,使用用户邮箱
- if ((vetPersonalInfo.getEmail() == null || vetPersonalInfo.getEmail().isEmpty())
- && currentUser.getEmail() != null) {
+ if (StringUtils.isEmpty(vetPersonalInfo.getEmail())
+ && StringUtils.isNotEmpty(currentUser.getEmail())) {
vetPersonalInfo.setEmail(currentUser.getEmail());
}
-
// 如果电话为空,使用用户手机号
- if ((vetPersonalInfo.getPhone() == null || vetPersonalInfo.getPhone().isEmpty())
- && currentUser.getPhonenumber() != null) {
+ if (StringUtils.isEmpty(vetPersonalInfo.getPhone())
+ && StringUtils.isNotEmpty(currentUser.getPhonenumber())) {
vetPersonalInfo.setPhone(currentUser.getPhonenumber());
}
}
- // 4. 设置创建时间和更新时间
+ // 6. 设置创建时间和更新时间
vetPersonalInfo.setCreateTime(DateUtils.getNowDate());
vetPersonalInfo.setUpdateTime(DateUtils.getNowDate());
- // 5. 检查是否已存在该用户的兽医信息
- VetPersonalInfo existing = vetPersonalInfoMapper.selectVetPersonalInfoByUserId(vetPersonalInfo.getUserId());
- if (existing != null) {
- throw new RuntimeException("该用户已存在兽医信息,请使用更新操作");
- }
-
return vetPersonalInfoMapper.insertVetPersonalInfo(vetPersonalInfo);
} else {
throw new RuntimeException("用户未登录");
@@ -169,7 +187,7 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
}
/**
- * 修改兽医个人信息
+ * 修改兽医个人信息(双向同步)
*/
@Override
@Transactional
@@ -183,21 +201,59 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
throw new RuntimeException("无权限修改其他用户的兽医信息");
}
- // 2. 强制绑定当前登录用户ID
+ // 2. 检查头像是否变化
+ String newAvatar = vetPersonalInfo.getAvatar();
+ String oldAvatar = existing != null ? existing.getAvatar() : null;
+ boolean avatarChanged = newAvatar != null && !newAvatar.equals(oldAvatar);
+
+ // 3. 强制绑定当前登录用户ID
vetPersonalInfo.setUserId(loginUser.getUserId());
- // 3. 设置更新者
+ // 4. 设置更新者
vetPersonalInfo.setUpdateBy(loginUser.getUsername());
- // 4. 设置更新时间
+ // 5. 设置更新时间
vetPersonalInfo.setUpdateTime(DateUtils.getNowDate());
- return vetPersonalInfoMapper.updateVetPersonalInfo(vetPersonalInfo);
+ // 6. 更新兽医信息
+ int result = vetPersonalInfoMapper.updateVetPersonalInfo(vetPersonalInfo);
+
+ // 7. 如果头像有变化,同步到用户表
+ if (result > 0 && avatarChanged && newAvatar != null && !newAvatar.isEmpty()) {
+ syncAvatarToUserTable(loginUser.getUserId(), newAvatar);
+ }
+
+ return result;
} else {
throw new RuntimeException("用户未登录");
}
}
+ /**
+ * 同步头像到用户表
+ */
+ private void syncAvatarToUserTable(Long userId, String avatar) {
+ try {
+ SysUser user = sysUserService.selectUserById(userId);
+ if (user != null) {
+ // 检查是否需要更新
+ if (!avatar.equals(user.getAvatar())) {
+ // 调用正确的方法签名
+ boolean success = sysUserService.updateUserAvatar(userId, avatar);
+
+ if (success) {
+ System.out.println("头像同步到用户表成功,用户ID: " + userId);
+ } else {
+ System.err.println("头像同步到用户表失败,用户ID: " + userId);
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("双向同步头像失败: " + e.getMessage());
+ }
+ }
+
+
@Override
public int auditVetPersonalInfo(VetPersonalInfo vetPersonalInfo) {
return vetPersonalInfoMapper.auditVetPersonalInfo(vetPersonalInfo);
@@ -399,6 +455,12 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
vetInfo.setNickName(user.getNickName());
needUpdate = true;
}
+ // 同步头像 - 新增
+ if ((vetInfo.getAvatar() == null || vetInfo.getAvatar().isEmpty())
+ && user.getAvatar() != null && !user.getAvatar().isEmpty()) {
+ vetInfo.setAvatar(user.getAvatar());
+ needUpdate = true;
+ }
// 如果邮箱为空,使用用户邮箱
if ((vetInfo.getEmail() == null || vetInfo.getEmail().isEmpty()) && user.getEmail() != null) {
@@ -445,6 +507,10 @@ public class VetPersonalInfoServiceImpl implements IVetPersonalInfoService {
if (vetInfo.getPhone() != null) {
updateInfo.setPhone(vetInfo.getPhone());
}
+ // 同步头像
+ if (vetInfo.getAvatar() != null) {
+ updateInfo.setAvatar(vetInfo.getAvatar());
+ }
// 设置更新时间
updateInfo.setUpdateTime(DateUtils.getNowDate());
diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
index a43ced1..31407b8 100644
--- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
+++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
@@ -1,11 +1,20 @@
package com.chenhai.vet.service.impl;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.List;
+import com.chenhai.common.core.domain.model.LoginUser;
import com.chenhai.common.utils.SecurityUtils;
+import com.chenhai.vet.domain.MerchantInfo;
import com.chenhai.vet.domain.VetTrainingVideo;
+import com.chenhai.vet.domain.dto.BatchSubmitAuditDTO;
+import com.chenhai.vet.mapper.MerchantInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import com.chenhai.vet.mapper.VetProductMapper;
import com.chenhai.vet.domain.VetProduct;
@@ -19,10 +28,12 @@ import org.springframework.transaction.annotation.Transactional;
* @date 2026-01-15
*/
@Service
-public class VetProductServiceImpl implements IVetProductService
+public class VetProductServiceImpl implements IVetProductService
{
@Autowired
private VetProductMapper vetProductMapper;
+ @Autowired
+ private MerchantInfoMapper merchantInfoMapper;
/**
* 查询兽医产品信息
@@ -45,25 +56,151 @@ public class VetProductServiceImpl implements IVetProductService
@Override
public List selectVetProductList(VetProduct vetProduct)
{
- // 获取当前登录用户ID
try {
- Long userId = SecurityUtils.getUserId();
- // 设置查询条件,只查询当前用户的产品
- vetProduct.setUserId(userId);
+ // 1. 获取当前用户ID
+ Long currentUserId = SecurityUtils.getUserId();
+
+ // 2. 判断是否为管理员(传入用户ID作为参数)
+ boolean isAdmin = SecurityUtils.isAdmin(currentUserId);
+
+ System.out.println("用户ID: " + currentUserId + ", 是否是管理员: " + isAdmin);
+
+ // 3. 如果不是管理员,只查看自己店铺的产品
+ if (!isAdmin) {
+ // 查询用户的店铺
+ MerchantInfo merchantQuery = new MerchantInfo();
+ merchantQuery.setUserId(currentUserId);
+ List merchantList = merchantInfoMapper.selectMerchantInfoList(merchantQuery);
+
+ if (merchantList != null && !merchantList.isEmpty()) {
+ // 获取店铺ID
+ Long shopId = merchantList.get(0).getShopId();
+ System.out.println("用户店铺ID: " + shopId);
+
+ // 只查询该店铺的产品
+ vetProduct.setShopId(shopId);
+ } else {
+ // 用户没有店铺,设置一个不存在的ID,确保查不到数据
+ System.out.println("用户没有关联的店铺");
+ vetProduct.setShopId(-1L);
+ }
+ }
+ // 如果是管理员,不设置shopId,可以查看所有产品
+
+ // 4. 执行查询
+ List result = vetProductMapper.selectVetProductList(vetProduct);
+ System.out.println("查询到产品数量: " + (result != null ? result.size() : 0));
+
+ return result;
+
} catch (Exception e) {
- // 如果获取不到用户ID,设置一个不存在的ID,确保查询不到数据
- vetProduct.setUserId(-1L);
+ System.out.println("查询异常: " + e.getMessage());
+ e.printStackTrace();
+ // 出错时返回空列表
+ return new ArrayList<>();
}
- return vetProductMapper.selectVetProductList(vetProduct);
}
+/* *//**
+ * 判断用户是否为管理员
+ *//*
+ private boolean isUserAdmin(Long userId) {
+ try {
+ return SecurityUtils.isAdmin();
+ } catch (Exception e) {
+ try {
+ return SecurityUtils.isAdmin(userId);
+ } catch (Exception e2) {
+ return false;
+ }
+ }
+ }*/
+
+ /* *//**
+ * 获取用户的所有店铺ID
+ *//*
+ private List getUserShopIds(Long userId) {
+ List shopIds = new ArrayList<>();
+ try {
+ MerchantInfo merchantQuery = new MerchantInfo();
+ merchantQuery.setUserId(userId);
+ List merchantList = merchantInfoMapper.selectMerchantInfoList(merchantQuery);
+
+ if (merchantList != null) {
+ for (MerchantInfo merchant : merchantList) {
+ shopIds.add(merchant.getShopId());
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return shopIds;
+ }
+
+ *//**
+ * 根据店铺ID列表查询产品
+ *//*
+ private List selectProductsByShopIds(VetProduct vetProduct, List shopIds) {
+ // 创建一个新的查询对象,避免修改原参数
+ VetProduct query = new VetProduct();
+
+ // 复制查询条件
+ if (vetProduct != null) {
+ query.setName(vetProduct.getName());
+ query.setType(vetProduct.getType());
+ query.setCategory(vetProduct.getCategory());
+ query.setStatus(vetProduct.getStatus());
+ query.setAuditStatus(vetProduct.getAuditStatus());
+ // ... 复制其他查询条件
+ }
+
+ // 如果只有一个店铺ID,直接设置
+ if (shopIds.size() == 1) {
+ query.setShopId(shopIds.get(0));
+ return vetProductMapper.selectVetProductList(query);
+ } else {
+ // 多个店铺ID,需要特殊处理
+ // 方法1:修改Mapper支持IN查询
+ // 方法2:循环查询合并结果
+ return selectProductsByShopIdsMulti(vetProduct, shopIds);
+ }
+ }*/
+
+ /**
+ * 多店铺ID查询产品(循环查询方式)
+ */
+ private List selectProductsByShopIdsMulti(VetProduct vetProduct, List shopIds) {
+ List allProducts = new ArrayList<>();
+
+ for (Long shopId : shopIds) {
+ VetProduct query = new VetProduct();
+ if (vetProduct != null) {
+ query.setName(vetProduct.getName());
+ query.setType(vetProduct.getType());
+ query.setCategory(vetProduct.getCategory());
+ query.setStatus(vetProduct.getStatus());
+ query.setAuditStatus(vetProduct.getAuditStatus());
+ // ... 复制其他条件
+ }
+ query.setShopId(shopId);
+
+ List shopProducts = vetProductMapper.selectVetProductList(query);
+ if (shopProducts != null) {
+ allProducts.addAll(shopProducts);
+ }
+ }
+
+ return allProducts;
+ }
+
+
/**
* 新增兽医产品信息
*
* @param vetProduct 兽医产品信息
* @return 结果
*/
- /* @Override
+ /* @Override
public int insertVetProduct(VetProduct vetProduct)
{
return vetProductMapper.insertVetProduct(vetProduct);
@@ -241,19 +378,34 @@ public class VetProductServiceImpl implements IVetProductService
@Transactional
public int insertVetProduct(VetProduct vetProduct)
{
- // 设置默认值
- vetProduct.setStatus("0"); // 默认草稿状态
- vetProduct.setAuditStatus("0"); // 新增产品默认待审核状态
- vetProduct.setIsDeleted(0);
- vetProduct.setCreatedAt(new Date());
- vetProduct.setUpdatedAt(new Date());
-
- // 设置当前用户ID
- try {
- Long userId = SecurityUtils.getUserId();
- vetProduct.setUserId(userId);
- } catch (Exception e) {
- vetProduct.setUserId(1L);
+ // 如果已经传入了shopId,就不需要查询
+ if (vetProduct.getShopId() == null) {
+ // 设置默认值
+ vetProduct.setStatus("0");
+ vetProduct.setAuditStatus("0");
+ vetProduct.setIsDeleted(0);
+ vetProduct.setCreatedAt(new Date());
+ vetProduct.setUpdatedAt(new Date());
+
+ // 设置当前用户ID并查询店铺ID
+ try {
+ Long userId = SecurityUtils.getUserId();
+ vetProduct.setUserId(userId);
+
+ // 查询用户的店铺
+ MerchantInfo merchantQuery = new MerchantInfo();
+ merchantQuery.setUserId(userId); // 这里直接调用setter方法
+ List merchantList = merchantInfoMapper.selectMerchantInfoList(merchantQuery);
+
+ if (merchantList != null && !merchantList.isEmpty()) {
+ vetProduct.setShopId(merchantList.get(0).getShopId());
+ } else {
+ throw new RuntimeException("用户未关联任何店铺,无法创建产品");
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException("获取用户店铺信息失败:" + e.getMessage());
+ }
}
return vetProductMapper.insertVetProduct(vetProduct);
@@ -272,4 +424,87 @@ public class VetProductServiceImpl implements IVetProductService
}
return vetProductMapper.selectVetProductList(vetProduct);
}
+
+
+ /**
+ * 批量提交产品审核(按商家)
+ */
+ @Override
+ public int batchSubmitProductsForAudit(Long shopId) {
+ int successCount = 0;
+
+ // 创建查询条件
+ VetProduct example = new VetProduct();
+ example.setShopId(shopId);
+
+ // 只查询未删除、未在审核中的产品
+ example.setIsDeleted(0);
+ example.setAuditStatus("0"); // 未审核状态
+
+ List products = vetProductMapper.selectVetProductList(example);
+
+ for (VetProduct product : products) {
+ // 检查是否可以提交审核
+ if (canSubmitForAudit(product)) {
+ // 提交审核
+ product.setAuditStatus("1"); // 审核中
+ product.setUpdatedAt(new Date());
+ vetProductMapper.updateVetProduct(product);
+ successCount++;
+ }
+ }
+
+ return successCount;
+ }
+
+ /**
+ * 检查产品是否可以提交审核
+ */
+ private boolean canSubmitForAudit(VetProduct product) {
+ // 检查状态:已删除、已在审核中或已审核完成的不允许提交
+ if (product.getIsDeleted() != null && product.getIsDeleted() == 1) {
+ return false;
+ }
+
+ // 审核状态:0-未审核,1-审核中,2-审核通过,3-审核不通过
+ String auditStatus = product.getAuditStatus();
+ if (auditStatus == null) {
+ auditStatus = "0";
+ }
+
+ // 只有未审核状态才能提交
+ return "0".equals(auditStatus);
+ }
+
+ /**
+ * 重新提交审核(审核不通过后重新提交)
+ */
+ @Override
+ @Transactional
+ public int resubmitForAudit(Long id) {
+ VetProduct product = vetProductMapper.selectVetProductById(id);
+ if (product == null) {
+ throw new RuntimeException("产品不存在");
+ }
+
+ // 只有审核不通过状态可以重新提交
+ if (!"3".equals(product.getAuditStatus())) {
+ throw new RuntimeException("只有审核不通过状态的产品可以重新提交");
+ }
+
+ // 检查产品状态,必须是草稿状态
+ if (!"0".equals(product.getStatus())) {
+ throw new RuntimeException("产品状态不正确,只有草稿状态的产品可以重新提交审核");
+ }
+
+ // 重置审核信息
+ product.setAuditStatus("1"); // 设置为审核中状态
+ product.setAuditOpinion(null); // 清空审核意见
+ product.setAuditUserId(null); // 清空审核人
+ product.setAuditTime(null); // 清空审核时间
+ product.setUpdatedAt(new Date());
+
+ return vetProductMapper.updateVetProduct(product);
+ }
}
+
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 0911286..6da6408 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
@@ -275,50 +275,50 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
@Override
public Map selectCertificateWithQualificationByCertId(Long certId, Long userId) {
try {
- log.debug("开始查询证书,certId={}, userId={}", certId, userId);
+ // 1. 查询用户有权限查看的所有资质
+ List qualifications;
- VetQualification query = new VetQualification();
- if (userId != null) {
+ if (userId == null) {
+ // userId为null时表示管理员查询,但这里应该传入实际用户ID
+ throw new ServiceException("用户ID不能为空");
+ } else {
+ // 普通用户只查询自己的资质
+ VetQualification query = new VetQualification();
query.setUserId(userId);
+ qualifications = vetQualificationMapper.selectVetQualificationList(query);
}
- List qualifications = selectVetQualificationList(query);
- log.debug("查询到资质数量:{}", qualifications.size());
-
for (VetQualification qualification : qualifications) {
- log.debug("检查资质ID:{},用户ID:{}",
- qualification.getQualificationId(), qualification.getUserId());
-
if (StringUtils.isEmpty(qualification.getCertificatesJson())) {
- log.debug("资质ID:{} 没有证书JSON数据", qualification.getQualificationId());
continue;
}
try {
List