Browse Source

优化功能

master
ChaiNingQi 1 week ago
parent
commit
ddacefaf55
  1. 2
      chenhai-admin/pom.xml
  2. 12
      chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java
  3. 8
      chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/DisasterWarningController.java
  4. 131
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java
  5. 4
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCommentsController.java
  6. 3
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java
  7. 3
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExpertsController.java
  8. 28
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
  9. 203
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java
  10. 37
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java
  11. 567
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java
  12. 68
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java
  13. 46
      chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java
  14. 119
      chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
  15. 14
      chenhai-system/src/main/java/com/chenhai/vet/domain/VetPersonalInfo.java
  16. 13
      chenhai-system/src/main/java/com/chenhai/vet/domain/VetProduct.java
  17. 39
      chenhai-system/src/main/java/com/chenhai/vet/domain/dto/BatchSubmitAuditDTO.java
  18. 55
      chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java
  19. 5
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java
  20. 18
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java
  21. 11
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java
  22. 199
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java
  23. 391
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCommentsServiceImpl.java
  24. 103
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java
  25. 120
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetPersonalInfoServiceImpl.java
  26. 279
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
  27. 36
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java
  28. 358
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java
  29. 10
      chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml
  30. 18
      chenhai-system/src/main/resources/mapper/system/SysUserMapper.xml
  31. 41
      chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml
  32. 8
      chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml
  33. 7
      chenhai-system/src/main/resources/mapper/vet/VetProductMapper.xml
  34. 2
      chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml
  35. 108
      chenhai-ui/src/views/vet/info/index.vue

2
chenhai-admin/pom.xml

@ -60,6 +60,8 @@
<optional>true</optional>
</dependency>
</dependencies>
<build>

12
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)

8
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)

131
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<MerchantInfo> 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<MerchantInfo> list = merchantInfoService.selectMerchantInfoList(merchantInfo);
ExcelUtil<MerchantInfo> util = new ExcelUtil<MerchantInfo>(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));
}
}

4
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

3
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

3
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

28
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("文章不存在或未发布");
}
}

203
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<VetPersonalInfo> 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<String, Object> result = new HashMap<>();
// 1. 获取兽医个人信息
VetPersonalInfo info = vetPersonalInfoService.selectVetPersonalInfoByUserId(userId);
// 2. 获取资质信息
List<VetQualification> 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);
}
}

37
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<VetProduct> 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<VetProduct> 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));
}
}

567
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<VetQualification> 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<String, Object> 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<String, Object> requestData = (Map<String, Object>) 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<VetQualification> 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<String, Object> requestData = mapper.convertValue(requestBody, Map.class);
for (int i = 0; i < certificatesList.size(); i++) {
Object certObj = certificatesList.get(i);
Map<String, Object> certMap;
if (certObj instanceof Map) {
certMap = (Map<String, Object>) 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<VetQualification> 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<String> scopeIdsList = (List<String>) 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<VetQualification> idCardUsers = vetQualificationService.selectVetQualificationList(query);
if (!idCardUsers.isEmpty()) {
for (VetQualification user : idCardUsers) {
if (!user.getUserId().equals(sysUserId)) {
return error("该身份证号已被其他用户使用");
}
}
}
// 证书列表校验
List<VetQualification.CertificateInfo> 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<VetQualification> 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<String, Object> 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<VetQualification.CertificateInfo> 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) {

68
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<Long> 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<String, Object> 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<Long> 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<Long> 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<String, String> 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());
}
}
}

46
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<VetQualification> qualifications = vetQualificationMapper.selectVetQualificationList(new VetQualification());
// 1. 检查并发送提醒
vetQualificationService.checkAndSendCertificateReminders();
for (VetQualification qualification : qualifications) {
try {
// 检查该资质下的所有证书包括JSON中的
checkAllCertificates(qualification);
} catch (Exception e) {
// 静默处理单个资质检查失败
}
// 2. 查询即将过期的证书并发送通知
List<VetQualification> 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("【证书过期检查】定时任务执行结束");*/
}
/**

119
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();
}
}

14
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();
}

13
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();
}
}

39
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;
}
}

55
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);
}

5
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

18
chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java

@ -110,4 +110,22 @@ public interface IVetProductService
*/
public List<VetProduct> selectAllVetProductList(VetProduct vetProduct);
/**
* 批量提交产品审核按商家
*
* @param shopId 商家ID
* @return 结果
*/
public int batchSubmitProductsForAudit(Long shopId);
// IVetProductService 接口中添加以下方法
/**
* 重新提交审核审核不通过后重新提交
*
* @param id 产品ID
* @return 结果
*/
int resubmitForAudit(Long id);
}

11
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<Long> videoIds, Long userId);
int batchAuditVideo(List<Long> videoIds, String auditStatus, String auditOpinion, Long auditUserId);

199
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());
}
}

391
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<VetComments> 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("---");
}
}
}

103
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<String> 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();

120
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<VetPersonalInfo> 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());

279
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<VetProduct> 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<MerchantInfo> 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<VetProduct> 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<Long> getUserShopIds(Long userId) {
List<Long> shopIds = new ArrayList<>();
try {
MerchantInfo merchantQuery = new MerchantInfo();
merchantQuery.setUserId(userId);
List<MerchantInfo> 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<VetProduct> selectProductsByShopIds(VetProduct vetProduct, List<Long> 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<VetProduct> selectProductsByShopIdsMulti(VetProduct vetProduct, List<Long> shopIds) {
List<VetProduct> 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<VetProduct> 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<MerchantInfo> 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<VetProduct> 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);
}
}

36
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java

@ -275,50 +275,50 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
@Override
public Map<String, Object> selectCertificateWithQualificationByCertId(Long certId, Long userId) {
try {
log.debug("开始查询证书,certId={}, userId={}", certId, userId);
// 1. 查询用户有权限查看的所有资质
List<VetQualification> 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<VetQualification> 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<Map<String, Object>> certificates = parseCertificatesJson(qualification.getCertificatesJson());
log.debug("资质ID:{} 解析到证书数量:{}",
qualification.getQualificationId(), certificates.size());
for (Map<String, Object> certMap : certificates) {
Long foundCertId = extractLongFromObject(certMap.get("certId"));
log.debug("检查证书ID:{},目标ID:{}", foundCertId, certId);
if (foundCertId != null && foundCertId.equals(certId)) {
log.debug("找到匹配的证书,资质ID:{},证书ID:{}",
qualification.getQualificationId(), certId);
// 权限验证确保证书属于当前用户
if (!qualification.getUserId().equals(userId)) {
throw new ServiceException("无权查看此证书");
}
return buildCertificateResult(qualification, certMap, foundCertId);
}
}
} catch (Exception e) {
log.error("解析资质证书JSON失败,qualificationId: {}", qualification.getQualificationId(), e);
// 解析JSON失败继续下一个资质
}
}
log.warn("未找到证书,certId={}, userId={}", certId, userId);
return null;
} catch (Exception e) {
log.error("查询证书信息失败:certId={}, userId={}", certId, userId, e);
if (e instanceof ServiceException) {
throw e;
}
throw new ServiceException("查询证书信息失败:" + e.getMessage());
}
}

358
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java

@ -1,7 +1,9 @@
package com.chenhai.vet.service.impl;
import java.util.ArrayList;
import java.util.List;
import com.chenhai.common.core.domain.AjaxResult;
import com.chenhai.common.utils.SecurityUtils;
import org.slf4j.Logger;
@ -69,7 +71,7 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
}
vetTrainingVideo.setUserId(userId); // 确保设置用户ID
vetTrainingVideo.setStatus("0"); // 私有
vetTrainingVideo.setStatus("0"); // 草稿私有
vetTrainingVideo.setAuditStatus("0"); // 待审核
vetTrainingVideo.setDelFlag("0"); // 正常
@ -123,9 +125,62 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
* @return 结果
*/
@Override
public int deleteVetTrainingVideoByIds(Long[] ids)
@Transactional(rollbackFor = Exception.class)
public AjaxResult deleteVetTrainingVideoByIds(Long[] ids)
{
return vetTrainingVideoMapper.deleteVetTrainingVideoByIds(ids);
try {
Long currentUserId = SecurityUtils.getUserId();
if (currentUserId == null) {
return AjaxResult.error("用户未登录");
}
int successCount = 0;
int failedCount = 0;
List<String> failedMessages = new ArrayList<>();
for (Long id : ids) {
try {
// 查询视频信息
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(id);
if (video == null) {
failedCount++;
failedMessages.add("视频ID " + id + " 不存在");
continue;
}
// 检查是否是自己的视频通过userId字段判断
if (!currentUserId.equals(video.getUserId())) {
// 如果不是自己的视频检查是否是管理员
if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里
failedCount++;
failedMessages.add("视频ID " + id + " 不是您发布的视频,无法删除");
continue;
}
}
// 执行删除
int result = vetTrainingVideoMapper.deleteVetTrainingVideoById(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) {
logger.error("批量删除视频失败", e);
return AjaxResult.error("批量删除失败: " + e.getMessage());
}
}
/**
@ -135,9 +190,39 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
* @return 结果
*/
@Override
public int deleteVetTrainingVideoById(Long id)
@Transactional(rollbackFor = Exception.class)
public AjaxResult deleteVetTrainingVideoById(Long id)
{
return vetTrainingVideoMapper.deleteVetTrainingVideoById(id);
try {
Long currentUserId = SecurityUtils.getUserId();
if (currentUserId == null) {
return AjaxResult.error("用户未登录");
}
// 查询视频信息
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(id);
if (video == null) {
return AjaxResult.error("视频不存在");
}
// 检查是否是自己的视频通过userId字段判断
if (!currentUserId.equals(video.getUserId())) {
// 如果不是自己的视频检查是否是管理员
if (!SecurityUtils.isAdmin(currentUserId)) { // 修改这里
return AjaxResult.error("不是您发布的视频,无法删除");
}
}
int result = vetTrainingVideoMapper.deleteVetTrainingVideoById(id);
if (result > 0) {
return AjaxResult.success("视频删除成功");
} else {
return AjaxResult.error("视频删除失败");
}
} catch (Exception e) {
logger.error("删除视频失败,ID: {}", id, e);
return AjaxResult.error("删除失败: " + e.getMessage());
}
}
@Override
@ -160,15 +245,19 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
continue;
}
// 状态验证只有审核拒绝或无需审核状态才能重新提交审核
String auditStatus = video.getAuditStatus();
if (!"2".equals(auditStatus) && !"3".equals(auditStatus)) {
logger.warn("视频 {} 当前状态 {} 不能提交审核", videoId, auditStatus);
// 状态验证只有草稿状态(0)且待审核状态(0)的视频才能提交审核
if (!"0".equals(video.getStatus())) {
logger.warn("视频 {} 不是草稿状态,不能提交审核", videoId);
continue;
}
// 修改为允许待审核(0)和审核拒绝(3)状态重新提交
if (!"0".equals(video.getAuditStatus()) && !"3".equals(video.getAuditStatus())) {
logger.warn("视频 {} 当前状态 {} 不能提交审核", videoId, video.getAuditStatus());
continue;
}
// 更新为待审核状态
video.setAuditStatus("0"); // 审核
// 更新为审核状态
video.setAuditStatus("1"); // 审核
video.setUpdateTime(DateUtils.getNowDate());
int result = vetTrainingVideoMapper.updateVetTrainingVideo(video);
@ -190,8 +279,13 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
public int batchAuditVideo(List<Long> videoIds, String auditStatus, String auditOpinion, Long auditUserId) {
int successCount = 0;
// 验证审核状态值2-通过3-拒绝
if (!"2".equals(auditStatus) && !"3".equals(auditStatus)) {
throw new RuntimeException("无效的审核状态值");
}
// 如果是拒绝审核必须填写意见
if ("2".equals(auditStatus) && (auditOpinion == null || auditOpinion.trim().isEmpty())) {
if ("3".equals(auditStatus) && (auditOpinion == null || auditOpinion.trim().isEmpty())) {
throw new RuntimeException("审核拒绝时必须填写审核意见");
}
@ -204,14 +298,13 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
continue;
}
// 状态验证只有待审核状态才能审核
if (!"0".equals(video.getAuditStatus())) {
if (!"1".equals(video.getAuditStatus())) {
logger.warn("视频 {} 当前状态 {} 不能审核", videoId, video.getAuditStatus());
continue;
}
// 更新审核信息
video.setAuditStatus(auditStatus);
video.setAuditStatus(auditStatus); // 2-通过3-拒绝
video.setAuditOpinion(auditOpinion);
video.setAuditUserId(auditUserId);
video.setAuditTime(DateUtils.getNowDate());
@ -251,19 +344,19 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
continue;
}
// 状态验证只有审核通过且未上架的视频才能上架
// 状态验证只有审核通过(2)且为草稿状态(0)的视频才能发布
if (!"2".equals(video.getAuditStatus())) {
logger.warn("视频 {} 未通过审核,当前审核状态: {}", videoId, video.getAuditStatus());
continue;
}
if ("1".equals(video.getStatus())) {
logger.warn("视频 {} 已上架", videoId);
if (!"0".equals(video.getStatus())) {
logger.warn("视频 {} 当前状态不能发布", videoId);
continue;
}
// 更新为上架状态
video.setStatus("1"); // 已上架
// 更新为已发布状态
video.setStatus("1"); // 已发布
video.setPublishTime(DateUtils.getNowDate());
video.setUpdateTime(DateUtils.getNowDate());
int result = vetTrainingVideoMapper.updateVetTrainingVideo(video);
@ -272,7 +365,7 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
}
} catch (Exception e) {
logger.error("批量上架失败,视频ID: {}", videoId, e);
logger.error("批量发布失败,视频ID: {}", videoId, e);
// 继续处理下一个不中断批量操作
}
}
@ -300,13 +393,13 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
continue;
}
// 状态验证只有已上架的视频才能下架
// 状态验证只有已发布状态(1)的视频才能下架
if (!"1".equals(video.getStatus())) {
logger.warn("视频 {} 未上架,当前状态: {}", videoId, video.getStatus());
logger.warn("视频 {} 未发布,当前状态: {}", videoId, video.getStatus());
continue;
}
// 更新为下架状态
// 更新为下架状态
video.setStatus("0"); // 已下架
video.setUpdateTime(DateUtils.getNowDate());
@ -326,133 +419,170 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
@Override
public boolean auditVideo(Long videoId, String auditStatus, String auditOpinion, Long auditUserId) {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
try {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
if (video == null) {
throw new RuntimeException("视频不存在");
}
if (video == null) {
return false;
}
// 只有审核状态才能审核
if (!"0".equals(video.getAuditStatus())) {
throw new RuntimeException("当前状态不能审核");
}
// 只有审核状态(1)才能审核
if (!"1".equals(video.getAuditStatus())) {
return false;
}
// 审核拒绝时必须填写审核意见
if ("2".equals(auditStatus) && (auditOpinion == null || auditOpinion.trim().isEmpty())) {
throw new RuntimeException("审核拒绝时必须填写审核意见");
}
// 审核状态验证只能是2通过或3拒绝
if (!"2".equals(auditStatus) && !"3".equals(auditStatus)) {
return false;
}
// 更新审核信息
video.setAuditStatus(auditStatus);
video.setAuditOpinion(auditOpinion);
video.setAuditUserId(auditUserId);
video.setAuditTime(DateUtils.getNowDate());
video.setUpdateTime(DateUtils.getNowDate());
// 审核拒绝时必须填写审核意见
if ("3".equals(auditStatus) && (auditOpinion == null || auditOpinion.trim().isEmpty())) {
return false;
}
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
// 更新审核信息
video.setAuditStatus(auditStatus);
video.setAuditOpinion(auditOpinion);
video.setAuditUserId(auditUserId);
video.setAuditTime(DateUtils.getNowDate());
video.setUpdateTime(DateUtils.getNowDate());
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
} catch (Exception e) {
logger.error("审核视频失败,视频ID: {}", videoId, e);
return false;
}
}
/**
* 发布单个视频
*/
@Override
public boolean publishVideo(Long videoId, Long userId) {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
try {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
if (video == null) {
throw new RuntimeException("视频不存在");
}
// // 验证权限只能操作自己的视频
// if (!userId.equals(video.getUserId())) {
// throw new RuntimeException("无权操作此视频");
// }
if (video == null) {
return false;
}
// 状态验证有审核通过且未上架的视频才能上架
if (!"1".equals(video.getAuditStatus())) {
throw new RuntimeException("只有审核通过的视频才能上架");
}
// 验证权限只能操作自己的视频
if (!userId.equals(video.getUserId())) {
return false;
}
if ("1".equals(video.getStatus())) {
throw new RuntimeException("视频已上架");
}
// 状态验证只有审核通过(2)且为草稿状态(0)的视频才能发布
if (!"2".equals(video.getAuditStatus())) {
return false;
}
if (!"0".equals(video.getStatus())) {
return false;
}
// 更新为上架状态
video.setStatus("1"); // 已上架
video.setUpdateTime(DateUtils.getNowDate());
// 更新为已发布状态
video.setStatus("1"); // 已发布
video.setPublishTime(DateUtils.getNowDate());
video.setUpdateTime(DateUtils.getNowDate());
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
} catch (Exception e) {
logger.error("发布视频失败,视频ID: {}", videoId, e);
return false;
}
}
@Override
public boolean offlineVideo(Long videoId, Long userId) {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
try {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
if (video == null) {
throw new RuntimeException("视频不存在");
}
if (video == null) {
return false;
}
// 验证权限只能操作自己的视频
if (!userId.equals(video.getUserId())) {
throw new RuntimeException("无权操作此视频");
}
// 验证权限只能操作自己的视频
if (!userId.equals(video.getUserId())) {
return false;
}
// 状态验证只有已上架的视频才能下架
if (!"1".equals(video.getStatus())) {
throw new RuntimeException("只有已上架的视频才能下架");
}
// 状态验证只有已发布状态(1)的视频才能下架
if (!"1".equals(video.getStatus())) {
return false;
}
// 更新为下架状态
video.setStatus("0"); // 已下架
video.setUpdateTime(DateUtils.getNowDate());
// 更新为下架状态
video.setStatus("0");// 已下架
video.setUpdateTime(DateUtils.getNowDate());
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
} catch (Exception e) {
logger.error("下架视频失败,视频ID: {}", videoId, e);
return false;
}
}
/**
* 提交审核单个视频
*/
@Override
public boolean submitForAudit(Long videoId, Long userId) {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
try {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
if (video == null) {
throw new RuntimeException("视频不存在");
}
if (video == null) {
return false;
}
// ============ 注意这里移除了权限检查 ============
// 原来的权限检查代码删除了
// if (!userId.equals(video.getUserId())) {
// throw new RuntimeException("无权操作此视频");
// }
// =================================================
// 验证权限只能操作自己的视频
if (!userId.equals(video.getUserId())) {
return false;
}
// 状态验证只有审核拒绝或无需审核状态才能提交审核
String auditStatus = video.getAuditStatus();
if (!"2".equals(auditStatus) && !"3".equals(auditStatus)) {
throw new RuntimeException("当前状态不能提交审核");
}
// 只有草稿状态(0)且待审核状态(0)的视频才能提交审核
if (!"0".equals(video.getStatus())) {
return false;
}
if (!"0".equals(video.getAuditStatus()) && !"3".equals(video.getAuditStatus())) {
return false;
}
// 更新为待审核状态
video.setAuditStatus("0"); // 审核
video.setUpdateTime(DateUtils.getNowDate());
// 更新为审核状态
video.setAuditStatus("1"); // 审核
video.setUpdateTime(DateUtils.getNowDate());
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
int result = vetTrainingVideoMapper.updateVetTrainingVideo(video);
return result > 0;
} catch (Exception e) {
logger.error("提交审核失败,视频ID: {}", videoId, e);
return false;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean cancelAudit(Long videoId, Long userId) {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
try {
VetTrainingVideo video = vetTrainingVideoMapper.selectVetTrainingVideoById(videoId);
if (video == null) {
throw new RuntimeException("视频不存在");
}
if (video == null) {
return false;
}
// 状态验证只有待审核状态才能取消审核
if (!"0".equals(video.getAuditStatus())) {
throw new RuntimeException("只有待审核状态才能取消审核");
}
// 状态验证只有待审核状态才能取消审核
if (!"0".equals(video.getAuditStatus()) && !"1".equals(video.getAuditStatus())) {
return false;
}
// 更新为无需审核状态
video.setAuditStatus("3"); // 无需审核
video.setUpdateTime(DateUtils.getNowDate());
// 更新为无需审核状态
video.setAuditStatus("0"); // 无需审核
video.setUpdateTime(DateUtils.getNowDate());
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
return vetTrainingVideoMapper.updateVetTrainingVideo(video) > 0;
} catch (Exception e) {
logger.error("取消审核失败,视频ID: {}", videoId, e);
return false;
}
}
/**
@ -478,7 +608,7 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
public List<VetTrainingVideo> selectPublicVideoList(VetTrainingVideo vetTrainingVideo) {
// 设置强制条件已上架且审核通过
vetTrainingVideo.setStatus("1"); // 已上架
vetTrainingVideo.setAuditStatus("1"); // 审核通过
vetTrainingVideo.setAuditStatus("2"); // 审核通过注意这里是2
vetTrainingVideo.setDelFlag("0"); // 未删除
return vetTrainingVideoMapper.selectPublicVideoList(vetTrainingVideo);
@ -491,9 +621,9 @@ public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService
public List<VetTrainingVideo> selectPublicVideoPageList(VetTrainingVideo vetTrainingVideo) {
// 设置强制条件已上架且审核通过
vetTrainingVideo.setStatus("1"); // 已上架
vetTrainingVideo.setAuditStatus("1"); // 审核通过
vetTrainingVideo.setAuditStatus("2"); // 审核通过注意这里是2
vetTrainingVideo.setDelFlag("0"); // 未删除
return vetTrainingVideoMapper.selectVetTrainingVideoList(vetTrainingVideo);
}
}
}

10
chenhai-system/src/main/resources/mapper/system/SysMedicineRecommendationMapper.xml

@ -125,7 +125,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectSysMedicineRecommendationList" parameterType="SysMedicineRecommendation" resultMap="SysMedicineRecommendationResult">
<include refid="selectSysMedicineRecommendationVo"/>
<where>
<where>
<!-- 原有的条件保持不变 -->
<if test="medicineName != null and medicineName != ''"> and medicine_name like concat('%', #{medicineName}, '%')</if>
<if test="medicineType != null and medicineType != ''"> and medicine_type = #{medicineType}</if>
<if test="specification != null and specification != ''"> and specification = #{specification}</if>
@ -161,6 +162,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
)
</if>
</where>
<!-- 动态排序,默认按更新时间降序 -->
<if test="orderByColumn != null and orderByColumn != ''">
ORDER BY ${orderByColumn} ${orderDirection}
</if>
<if test="orderByColumn == null or orderByColumn == ''">
ORDER BY updated_at DESC
</if>
</select>
<select id="selectSysMedicineRecommendationById" parameterType="Long" resultMap="SysMedicineRecommendationResult">

18
chenhai-system/src/main/resources/mapper/system/SysUserMapper.xml

@ -62,14 +62,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="codePath" column="code_path" />
<result property="deleted" column="deleted" />
</resultMap>
<sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.nick_name, u.user_type,
u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag,
u.login_ip, u.login_date, u.pwd_update_date, u.area_code, u.create_by, u.create_time, u.remark,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,
a.id as sys_area_id, a.name as sys_area_name, a.code as sys_area_code
a.id as sys_area_id, a.name as sys_area_name, a.code as sys_area_code,
a.parent_code, a.type, a.sort, a.status, a.name_path, a.code_path, a.deleted
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
@ -111,7 +113,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectUserListByAreaCode" parameterType="SysUser" resultMap="SysUserResult">
select u.user_id, u.dept_id, u.nick_name, u.user_type, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date,u.area_code, u.create_by, u.create_time, u.remark, a.id as sys_area_id, a.name as sys_area_name, a.code as sys_area_code from sys_user u
select u.user_id, u.dept_id, u.nick_name, u.user_type, u.user_name, u.email, u.avatar,
u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.area_code,
u.create_by, u.create_time, u.remark,
a.id as sys_area_id, a.name as sys_area_name, a.code as sys_area_code,
a.parent_code, a.type, a.sort, a.status, a.name_path, a.code_path, a.deleted
from sys_user u
left join sys_area a on u.area_code = a.code
where u.del_flag = '0'
<if test="userId != null and userId != 0">
@ -126,16 +133,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
<if test="params.beginTime != null and params.beginTime != ''">
AND date_format(u.create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
<if test="params.endTime != null and params.endTime != ''">
AND date_format(u.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
<if test="areaCode != null and areaCode != ''">
AND (u.area_code = #{areaCode} OR u.area_code IN ( SELECT a.code FROM sys_area a WHERE find_in_set(#{areaCode}, code_path) ))
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>

41
chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml

@ -13,10 +13,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="createdAt" column="created_at" />
<result property="updatedAt" column="updated_at" />
<result property="isActive" column="is_active" />
<result property="shopLogo" column="shop_logo" />
<result property="businessLicenseImage" column="business_license_image" />
<result property="auditStatus" column="audit_status" />
<result property="auditOpinion" column="audit_opinion" />
<result property="auditUserId" column="audit_user_id" />
<result property="auditTime" column="audit_time" />
<result property="shopStatus" column="shop_status" />
<result property="publishTime" column="publish_time" />
<result property="offlineTime" column="offline_time" />
</resultMap>
<sql id="selectMerchantInfoVo">
select shop_id, shop_name, shop_address, phone, user_id, created_at, updated_at, is_active from merchant_info
select shop_id, shop_name, shop_address, phone, user_id, created_at, updated_at, is_active ,shop_logo, business_license_image, audit_status, audit_opinion, audit_user_id, audit_time, shop_status, publish_time, offline_time from merchant_info
</sql>
<select id="selectMerchantInfoList" parameterType="MerchantInfo" resultMap="MerchantInfoResult">
@ -29,6 +38,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null "> and created_at = #{createdAt}</if>
<if test="updatedAt != null "> and updated_at = #{updatedAt}</if>
<if test="isActive != null "> and is_active = #{isActive}</if>
<if test="shopLogo != null and shopLogo != ''"> and shop_logo = #{shopLogo}</if>
<if test="auditStatus != null and auditStatus != ''"> and audit_status = #{auditStatus}</if>
<if test="shopStatus != null and shopStatus != ''"> and shop_status = #{shopStatus}</if>
</where>
</select>
@ -47,6 +59,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">created_at,</if>
<if test="updatedAt != null">updated_at,</if>
<if test="isActive != null">is_active,</if>
<if test="shopLogo != null">shop_logo,</if>
<if test="businessLicenseImage != null">business_license_image,</if>
<if test="auditStatus != null">audit_status,</if>
<if test="auditOpinion != null">audit_opinion,</if>
<if test="auditUserId != null">audit_user_id,</if>
<if test="auditTime != null">audit_time,</if>
<if test="shopStatus != null">shop_status,</if>
<if test="publishTime != null">publish_time,</if>
<if test="offlineTime != null">offline_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="shopName != null and shopName != ''">#{shopName},</if>
@ -56,6 +77,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">#{createdAt},</if>
<if test="updatedAt != null">#{updatedAt},</if>
<if test="isActive != null">#{isActive},</if>
<if test="shopLogo != null">#{shopLogo},</if>
<if test="businessLicenseImage != null">#{businessLicenseImage},</if>
<if test="auditStatus != null">#{auditStatus},</if>
<if test="auditOpinion != null">#{auditOpinion},</if>
<if test="auditUserId != null">#{auditUserId},</if>
<if test="auditTime != null">#{auditTime},</if>
<if test="shopStatus != null">#{shopStatus},</if>
<if test="publishTime != null">#{publishTime},</if>
<if test="offlineTime != null">#{offlineTime},</if>
</trim>
</insert>
@ -69,6 +99,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">created_at = #{createdAt},</if>
<if test="updatedAt != null">updated_at = #{updatedAt},</if>
<if test="isActive != null">is_active = #{isActive},</if>
<if test="shopLogo != null">shop_logo = #{shopLogo},</if>
<if test="businessLicenseImage != null">business_license_image = #{businessLicenseImage},</if>
<if test="auditStatus != null">audit_status = #{auditStatus},</if>
<if test="auditOpinion != null">audit_opinion = #{auditOpinion},</if>
<if test="auditUserId != null">audit_user_id = #{auditUserId},</if>
<if test="auditTime != null">audit_time = #{auditTime},</if>
<if test="shopStatus != null">shop_status = #{shopStatus},</if>
<if test="publishTime != null">publish_time = #{publishTime},</if>
<if test="offlineTime != null">offline_time = #{offlineTime},</if>
</trim>
where shop_id = #{shopId}
</update>

8
chenhai-system/src/main/resources/mapper/vet/VetPersonalInfoMapper.xml

@ -23,6 +23,7 @@
<result property="expertType" column="expert_type"/>
<result property="email" column="email"/>
<result property="nickName" column="nick_name"/>
<result property="avatar" column="avatar"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@ -37,6 +38,7 @@
<result property="userId" column="u_user_id"/>
<result property="nickName" column="u_nick_name"/>
<result property="email" column="u_email"/>
<result property="avatar" column="u_avatar"/>
</association>
</resultMap>
@ -57,11 +59,13 @@
v.audit_status, v.audit_time, v.auditor, v.audit_desc,
u.user_id as u_user_id,
u.nick_name as u_nick_name,
u.avatar as u_avatar,
u.email as u_email
from vet_personal_info v
left join sys_user u on v.user_id = u.user_id
</sql>
<!-- 列表查询(带用户信息) -->
<select id="selectVetPersonalInfoList" parameterType="VetPersonalInfo" resultMap="VetPersonalInfoResult">
<include refid="selectVetPersonalInfoWithUserVo"/>
@ -79,6 +83,7 @@
<if test="expertType != null and expertType != ''"> and v.expert_type = #{expertType}</if>
<if test="email != null and email != ''"> and v.email = #{email}</if>
<!-- 用户表条件 -->
<if test="user != null">
<if test="user.userName != null and user.userName != ''">
@ -133,6 +138,7 @@
<if test="expertType != null and expertType != ''">expert_type,</if>
<if test="email != null and email != ''">email,</if>
<if test="nickName != null and nickName != ''">nick_name,</if>
<if test="avatar != null and avatar != ''">avatar,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
@ -155,6 +161,7 @@
<if test="expertType != null and expertType != ''">#{expertType},</if>
<if test="email != null and email != ''">#{email},</if>
<if test="nickName != null and nickName != ''">#{nickName},</if>
<if test="avatar != null and avatar != ''">#{avatar},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
@ -182,6 +189,7 @@
<if test="expertType != null and expertType != ''">expert_type = #{expertType},</if>
<if test="email != null and email != ''">email = #{email},</if>
<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>

7
chenhai-system/src/main/resources/mapper/vet/VetProductMapper.xml

@ -37,10 +37,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="auditOpinion" column="audit_opinion" />
<result property="auditUserId" column="audit_user_id" />
<result property="auditTime" column="audit_time" />
<result property="shopId" column="shop_id" />
</resultMap>
<sql id="selectVetProductVo">
select id, name, type, category, specification, unit, manufacturer, approval_number, ingredients, indications, usage_dosage, price, cost_price, stock, min_stock, main_image, images, treat_animals, treat_diseases, treatment_content, treatment_duration, precautions, status, is_deleted, clinic_id, user_id, created_at, updated_at,audit_status, audit_opinion, audit_user_id, audit_time from vet_product
select id, name, type, category, specification, unit, manufacturer, approval_number, ingredients, indications, usage_dosage, price, cost_price, stock, min_stock, main_image, images, treat_animals, treat_diseases, treatment_content, treatment_duration, precautions, status, is_deleted, clinic_id, user_id, created_at, updated_at,audit_status, audit_opinion, audit_user_id, audit_time ,shop_id from vet_product
</sql>
<select id="selectVetProductList" parameterType="VetProduct" resultMap="VetProductResult">
@ -74,6 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null "> and created_at = #{createdAt}</if>
<if test="updatedAt != null "> and updated_at = #{updatedAt}</if>
<if test="auditStatus != null and auditStatus != ''"> and audit_status = #{auditStatus}</if>
<if test="shopId != null "> and shop_id = #{shopId}</if>
</where>
</select>
@ -116,6 +118,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="auditOpinion != null">audit_opinion,</if>
<if test="auditUserId != null">audit_user_id,</if>
<if test="auditTime != null">audit_time,</if>
<if test="shopId != null">shop_id,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null and name != ''">#{name},</if>
@ -149,6 +152,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="auditOpinion != null">#{auditOpinion},</if>
<if test="auditUserId != null">#{auditUserId},</if>
<if test="auditTime != null">#{auditTime},</if>
<if test="shopId != null">#{shopId},</if>
</trim>
</insert>
@ -186,6 +190,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="auditOpinion != null">audit_opinion = #{auditOpinion},</if>
<if test="auditUserId != null">audit_user_id = #{auditUserId},</if>
<if test="auditTime != null">audit_time = #{auditTime},</if>
<if test="shopId != null">shop_id = #{shopId},</if>
</trim>
where id = #{id}
</update>

2
chenhai-system/src/main/resources/mapper/vet/VetTrainingVideoMapper.xml

@ -203,7 +203,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where>
<!-- 强制条件:已上架、审核通过、未删除 -->
and v.status = '1'
and v.audit_status = '1'
and v.audit_status = '2'
and v.del_flag = '0'
<!-- 可选查询条件 -->

108
chenhai-ui/src/views/vet/info/index.vue

@ -278,6 +278,7 @@
<script>
import { listInfo, getInfo, getfull, delInfo, addInfo, updateInfo } from "@/api/vet/info"
import request from '@/utils/request'
export default {
name: "Info",
@ -457,6 +458,113 @@ export default {
this.reset()
this.open = true
this.title = "添加兽医个人信息"
// 使
this.loadCurrentUserInfo()
},
/** 加载当前用户信息 */
loadCurrentUserInfo() {
// 1使API
// listInfo 仿
// 2使request
// request
request({
url: '/vet/info/current',
method: 'get',
headers: {
'Authorization': 'Bearer ' + this.getToken() // token
}
}).then(response => {
console.log('获取用户信息成功:', response)
if (response.code === 200) {
this.fillFormFromResponse(response.data)
if (!this.form.phone) {
this.fetchUserProfileForPhone()
}
}
}).catch(error => {
console.error('获取用户信息失败:', error)
this.$message.warning('请先完善资质信息,或联系管理员')
})
},
/** 从用户个人资料获取手机号(注册时的手机号) */
fetchUserProfileForPhone() {
//
request({
url: '/system/user/profile', // RuoYi
method: 'get'
}).then(response => {
console.log('获取用户资料成功:', response)
if (response.code === 200 && response.data) {
//
if (response.data.phonenumber) {
this.form.phone = response.data.phonenumber
console.log('从用户资料设置手机号:', this.form.phone)
}
//
if (response.data.nickName && !this.form.nickName) {
this.form.nickName = response.data.nickName
}
if (response.data.email && !this.form.email) {
this.form.email = response.data.email
}
if (response.data.sex && !this.form.gender) {
this.form.gender = response.data.sex
}
}
}).catch(error => {
console.error('获取用户资料失败:', error)
})
},
/** 获取token */
getToken() {
// token
return localStorage.getItem('token') ||
sessionStorage.getItem('token') ||
this.$store.state.token ||
''
},
/** 填充表单 */
fillFormFromResponse(data) {
if (!data || !data.personalInfo) {
return
}
const personalInfo = data.personalInfo
//
if (personalInfo.realName) {
this.form.realName = personalInfo.realName
}
if (personalInfo.idCard) {
this.form.idCard = personalInfo.idCard
}
if (personalInfo.nickName) {
this.form.nickName = personalInfo.nickName
}
if (personalInfo.email) {
this.form.email = personalInfo.email
}
if (personalInfo.phone) {
this.form.phone = personalInfo.phone
}
if (personalInfo.gender) {
this.form.gender = personalInfo.gender
}
//
if (data.hasQualifications) {
this.$message.success('信息已从资质自动填充')
}
},
/** 修改按钮操作 */
handleUpdate(row) {

Loading…
Cancel
Save