Browse Source

商家信息功能和经验分享功能

master
ChaiNingQi 2 weeks ago
parent
commit
0c0f0c239f
  1. 104
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java
  2. 307
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java
  3. 6
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
  4. 3
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java
  5. 6
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java
  6. 31
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java
  7. 77
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java
  8. 1
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java
  9. 406
      chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java
  10. 146
      chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
  11. 236
      chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java
  12. 61
      chenhai-system/src/main/java/com/chenhai/vet/mapper/MerchantInfoMapper.java
  13. 2
      chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java
  14. 2
      chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java
  15. 61
      chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java
  16. 10
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java
  17. 8
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java
  18. 2
      chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java
  19. 93
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java
  20. 51
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetExperienceArticleServiceImpl.java
  21. 1
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java
  22. 186
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java
  23. 23
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
  24. 150
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java
  25. 86
      chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml
  26. 137
      chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml
  27. 5
      chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml
  28. 44
      chenhai-ui/src/api/vet/merchant.js
  29. 362
      chenhai-ui/src/views/vet/merchant/index.vue

104
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java

@ -0,0 +1,104 @@
package com.chenhai.web.controller.vet;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.chenhai.common.annotation.Log;
import com.chenhai.common.core.controller.BaseController;
import com.chenhai.common.core.domain.AjaxResult;
import com.chenhai.common.enums.BusinessType;
import com.chenhai.vet.domain.MerchantInfo;
import com.chenhai.vet.service.IMerchantInfoService;
import com.chenhai.common.utils.poi.ExcelUtil;
import com.chenhai.common.core.page.TableDataInfo;
/**
* 商家信息Controller
*
* @author ruoyi
* @date 2026-02-04
*/
@RestController
@RequestMapping("/vet/merchant")
public class MerchantInfoController extends BaseController
{
@Autowired
private IMerchantInfoService merchantInfoService;
/**
* 查询商家信息列表
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:list')")
@GetMapping("/list")
public TableDataInfo list(MerchantInfo merchantInfo)
{
startPage();
List<MerchantInfo> list = merchantInfoService.selectMerchantInfoList(merchantInfo);
return getDataTable(list);
}
/**
* 导出商家信息列表
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:export')")
@Log(title = "商家信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MerchantInfo merchantInfo)
{
List<MerchantInfo> list = merchantInfoService.selectMerchantInfoList(merchantInfo);
ExcelUtil<MerchantInfo> util = new ExcelUtil<MerchantInfo>(MerchantInfo.class);
util.exportExcel(response, list, "商家信息数据");
}
/**
* 获取商家信息详细信息
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:query')")
@GetMapping(value = "/{shopId}")
public AjaxResult getInfo(@PathVariable("shopId") Long shopId)
{
return success(merchantInfoService.selectMerchantInfoByShopId(shopId));
}
/**
* 新增商家信息
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:add')")
@Log(title = "商家信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MerchantInfo merchantInfo)
{
return toAjax(merchantInfoService.insertMerchantInfo(merchantInfo));
}
/**
* 修改商家信息
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:edit')")
@Log(title = "商家信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MerchantInfo merchantInfo)
{
return toAjax(merchantInfoService.updateMerchantInfo(merchantInfo));
}
/**
* 删除商家信息
*/
@PreAuthorize("@ss.hasPermi('vet:merchant:remove')")
@Log(title = "商家信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{shopIds}")
public AjaxResult remove(@PathVariable Long[] shopIds)
{
return toAjax(merchantInfoService.deleteMerchantInfoByShopIds(shopIds));
}
}

307
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java

@ -8,15 +8,17 @@ import com.chenhai.common.enums.BusinessType;
import com.chenhai.common.utils.SecurityUtils; import com.chenhai.common.utils.SecurityUtils;
import com.chenhai.vet.domain.VetExperienceArticle; import com.chenhai.vet.domain.VetExperienceArticle;
import com.chenhai.vet.service.IVetExperienceArticleService; import com.chenhai.vet.service.IVetExperienceArticleService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* 兽医经验文章论坛Controller列表样式
* 兽医经验文章论坛Controller
*/ */
@RestController @RestController
@RequestMapping("/vet/article") @RequestMapping("/vet/article")
@ -31,9 +33,41 @@ public class VetExperienceArticleController extends BaseController {
// 简单收藏管理 // 简单收藏管理
private static final Map<Long, Set<Long>> COLLECTION_STORE = new ConcurrentHashMap<>(); private static final Map<Long, Set<Long>> COLLECTION_STORE = new ConcurrentHashMap<>();
/**
* 初始化浏览记录表
*/
@PostConstruct
public void initViewLogTable() {
try {
String checkSql = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'article_view_log'";
Integer tableExists = jdbcTemplate.queryForObject(checkSql, Integer.class);
if (tableExists == null || tableExists == 0) {
String createTableSql = "CREATE TABLE article_view_log (" +
"id BIGINT AUTO_INCREMENT PRIMARY KEY," +
"article_id BIGINT NOT NULL," +
"user_id BIGINT," +
"view_time DATETIME NOT NULL," +
"INDEX idx_article_id (article_id)," +
"INDEX idx_user_id (user_id)," +
"INDEX idx_view_time (view_time)" +
")";
jdbcTemplate.execute(createTableSql);
System.out.println("文章浏览记录表创建成功");
}
} catch (Exception e) {
System.err.println("初始化浏览记录表失败: " + e.getMessage());
}
}
/** /**
* 查询所有文章列表论坛首页 * 查询所有文章列表论坛首页
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetExperienceArticle vetExperienceArticle) { public TableDataInfo list(VetExperienceArticle vetExperienceArticle) {
// 默认只查询已发布的文章 // 默认只查询已发布的文章
@ -48,6 +82,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 查询我的文章列表个人中心 * 查询我的文章列表个人中心
*/ */
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/myList") @GetMapping("/myList")
public TableDataInfo myList(VetExperienceArticle vetExperienceArticle) { public TableDataInfo myList(VetExperienceArticle vetExperienceArticle) {
Long userId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
@ -79,41 +115,192 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 查看文章详情包含相关文章 * 查看文章详情包含相关文章
*/ */
@PreAuthorize("@ss.hasPermi('vet:article:query') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) { public AjaxResult getInfo(@PathVariable("id") Long id) {
// 增加浏览数
vetExperienceArticleService.incrementViewCount(id);
// 1. 先获取文章信息
VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id); VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id);
if (article == null) { if (article == null) {
return error("文章不存在"); return error("文章不存在");
} }
// 获取相关文章同一分类的其他文章
List<VetExperienceArticle> relatedArticles = vetExperienceArticleService.selectRelatedArticles(
id, article.getCategoryId(), 4);
// 2. 增加观看次数在文章表中直接更新
if (article.getViewCount() == null) {
article.setViewCount(0L);
}
article.setViewCount(article.getViewCount() + 1);
// 获取作者其他文章
List<VetExperienceArticle> authorArticles = vetExperienceArticleService.selectArticlesByUserId(
article.getUserId(), 5);
// 3. 更新文章浏览量
vetExperienceArticleService.updateVetExperienceArticle(article);
Map<String, Object> result = new HashMap<>();
result.put("article", article);
result.put("relatedArticles", relatedArticles);
result.put("authorArticles", authorArticles);
// 4. 重新获取更新后的文章信息确保获取最新的viewCount
VetExperienceArticle updatedArticle = vetExperienceArticleService.selectVetExperienceArticleById(id);
// 判断是否是当前用户
Long currentUserId = SecurityUtils.getUserId();
result.put("isOwner", currentUserId != null && currentUserId.equals(article.getUserId()));
result.put("isCollected", currentUserId != null &&
COLLECTION_STORE.getOrDefault(currentUserId, Collections.emptySet()).contains(id));
return success(updatedArticle);
}
/**
* 记录文章浏览到新表 - 新增方法
*/
private void recordArticleView(Long articleId, Long userId) {
try {
// 通用去重任何用户1小时内只记录一次
String checkSql;
Object[] params;
if (userId != null) {
checkSql = "SELECT COUNT(*) FROM article_view_log WHERE article_id = ? AND user_id = ? AND view_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)";
params = new Object[]{articleId, userId};
} else {
checkSql = "SELECT COUNT(*) FROM article_view_log WHERE article_id = ? AND user_id IS NULL AND view_time > DATE_SUB(NOW(), INTERVAL 1 HOUR)";
params = new Object[]{articleId};
}
Integer recentViews = jdbcTemplate.queryForObject(checkSql, Integer.class, params);
if (recentViews != null && recentViews > 0) {
return; // 1小时内已浏览过
}
// 记录到浏览记录表
String insertSql = "INSERT INTO article_view_log (article_id, user_id, view_time) VALUES (?, ?, NOW())";
jdbcTemplate.update(insertSql, articleId, userId);
} catch (Exception e) {
System.err.println("记录浏览失败: " + e.getMessage());
}
}
/**
* 获取文章详细浏览统计 - 修正版
*/
private Map<String, Object> getArticleViewStats(Long articleId) {
Map<String, Object> stats = new HashMap<>();
try {
// 1. 总浏览量
String totalSql = "SELECT COUNT(*) FROM article_view_log WHERE article_id = ?";
Integer totalViews = jdbcTemplate.queryForObject(totalSql, Integer.class, articleId);
stats.put("totalViews", totalViews != null ? totalViews : 0);
// 2. 独立访客数
String uniqueSql = "SELECT COUNT(DISTINCT user_id) FROM article_view_log WHERE article_id = ? AND user_id IS NOT NULL";
Integer uniqueViewers = jdbcTemplate.queryForObject(uniqueSql, Integer.class, articleId);
stats.put("uniqueViewers", uniqueViewers != null ? uniqueViewers : 0);
// 3. 今日浏览量
String todaySql = "SELECT COUNT(*) FROM article_view_log WHERE article_id = ? AND DATE(view_time) = CURDATE()";
Integer todayViews = jdbcTemplate.queryForObject(todaySql, Integer.class, articleId);
stats.put("todayViews", todayViews != null ? todayViews : 0);
// 4. 本周浏览量
String weekSql = "SELECT COUNT(*) FROM article_view_log WHERE article_id = ? AND YEARWEEK(view_time, 1) = YEARWEEK(CURDATE(), 1)";
Integer weekViews = jdbcTemplate.queryForObject(weekSql, Integer.class, articleId);
stats.put("weekViews", weekViews != null ? weekViews : 0);
// 5. 最近7天浏览趋势简化版只返回近7天总览
String trendSql = "SELECT COUNT(*) as view_count " +
"FROM article_view_log " +
"WHERE article_id = ? AND view_time >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)";
Integer weekTrend = jdbcTemplate.queryForObject(trendSql, Integer.class, articleId);
stats.put("weekTrend", weekTrend != null ? weekTrend : 0);
} catch (Exception e) {
// 出错时返回默认值
stats.put("totalViews", 0);
stats.put("uniqueViewers", 0);
stats.put("todayViews", 0);
stats.put("weekViews", 0);
stats.put("weekTrend", 0);
}
return stats;
}
/**
* 根据用户角色判断身份
*/
private String getUserRoleType(Long userId) {
if (userId == null) {
return "user"; // 默认普通用户
}
try {
// 查询用户拥有的角色ID
String sql = "SELECT role_id FROM sys_user_role WHERE user_id = ?";
List<Long> roleIds = jdbcTemplate.query(sql,
new Object[]{userId},
(rs, rowNum) -> rs.getLong("role_id"));
// 检查是否有兽医角色role_id = 4
for (Long roleId : roleIds) {
if (roleId != null && roleId == 4) {
return "vet"; // 兽医
}
}
return success(result);
// 检查是否有牧户角色role_id = 3
for (Long roleId : roleIds) {
if (roleId != null && roleId == 3) {
return "muhu"; // 牧户
}
}
} catch (Exception e) {
System.err.println("查询用户角色失败: " + e.getMessage());
}
return "user"; // 默认普通用户
}
/**
* 获取用户角色显示名称
*/
private String getUserRoleDisplayName(String roleType) {
switch (roleType) {
case "vet":
return "兽医";
case "muhu":
return "牧户";
default:
return "用户";
}
}
/**
* 获取文章详细浏览统计独立接口- 新增接口
*/
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/{id}/viewStats")
public AjaxResult getViewStats(@PathVariable("id") Long id) {
Map<String, Object> stats = getArticleViewStats(id);
stats.put("articleId", id);
return success(stats);
}
/**
* 修正文章浏览数手动同步- 新增接口
*/
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.UPDATE)
@PostMapping("/{id}/syncViewCount")
public AjaxResult syncViewCount(@PathVariable Long id) {
try {
Map<String, Object> stats = getArticleViewStats(id);
stats.put("articleId", id);
return success("浏览统计信息").put("data", stats);
} catch (Exception e) {
return error("获取统计失败: " + e.getMessage());
}
} }
/** /**
* 发布新文章论坛发布 * 发布新文章论坛发布
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "发布经验文章", businessType = BusinessType.INSERT) @Log(title = "发布经验文章", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@RequestBody VetExperienceArticle article) { public AjaxResult add(@RequestBody VetExperienceArticle article) {
@ -123,11 +310,37 @@ public class VetExperienceArticleController extends BaseController {
// 设置作者信息 // 设置作者信息
article.setUserId(currentUserId); article.setUserId(currentUserId);
article.setVetName(currentUsername); article.setVetName(currentUsername);
try {
String userAvatarSql = "SELECT avatar FROM sys_user WHERE user_id = ?";
String userAvatar = jdbcTemplate.queryForObject(userAvatarSql, String.class, currentUserId);
if (userAvatar != null) {
article.setVetAvatar(userAvatar);
}
// 获取用户昵称作为显示名称
String nickNameSql = "SELECT COALESCE(nick_name, user_name) FROM sys_user WHERE user_id = ?";
String displayName = jdbcTemplate.queryForObject(nickNameSql, String.class, currentUserId);
if (displayName != null) {
article.setVetName(displayName);
}
} catch (Exception e) {
System.err.println("获取用户信息失败: " + e.getMessage());
}
// 默认状态为已发布 // 默认状态为已发布
if (article.getStatus() == null) { if (article.getStatus() == null) {
article.setStatus("1"); article.setStatus("1");
} }
String userRole = getUserRoleType(currentUserId);
article.setUserRole(userRole);
article.setUserType(getUserRoleDisplayName(userRole));
// 如果是兽医可以设置更多信息
/* if ("vet".equals(userRole)) {
article.setVetTitle("执业兽医");
// 可以查询兽医的详细信息
}*/
// 设置发布时间 // 设置发布时间
if (article.getPublishTime() == null && "1".equals(article.getStatus())) { if (article.getPublishTime() == null && "1".equals(article.getStatus())) {
@ -135,12 +348,25 @@ public class VetExperienceArticleController extends BaseController {
} }
int result = vetExperienceArticleService.insertVetExperienceArticle(article); int result = vetExperienceArticleService.insertVetExperienceArticle(article);
return toAjax(result).put("articleId", article.getId());
VetExperienceArticle savedArticle = vetExperienceArticleService.selectVetExperienceArticleById(article.getId());
Map<String, Object> response = new HashMap<>();
response.put("articleId", article.getId());
response.put("userRole", savedArticle.getUserRole());
response.put("userType", savedArticle.getUserType());
response.put("title", savedArticle.getTitle());
response.put("status", savedArticle.getStatus());
response.put("publishTime", savedArticle.getPublishTime());
response.put("vetName", savedArticle.getVetName()); // 添加姓名
response.put("vetAvatar", savedArticle.getVetAvatar()); // 添加头像
return success("发布成功").put("data", response);
} }
/** /**
* 修改文章 * 修改文章
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "修改经验文章", businessType = BusinessType.UPDATE) @Log(title = "修改经验文章", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody VetExperienceArticle vetExperienceArticle) { public AjaxResult edit(@RequestBody VetExperienceArticle vetExperienceArticle) {
@ -158,6 +384,7 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 删除文章 * 删除文章
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "删除经验文章", businessType = BusinessType.DELETE) @Log(title = "删除经验文章", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) { public AjaxResult remove(@PathVariable Long[] ids) {
@ -170,13 +397,13 @@ public class VetExperienceArticleController extends BaseController {
return error("没有权限删除他人文章"); return error("没有权限删除他人文章");
} }
} }
return toAjax(vetExperienceArticleService.deleteVetExperienceArticleByIds(ids)); return toAjax(vetExperienceArticleService.deleteVetExperienceArticleByIds(ids));
} }
/** /**
* 点赞文章 * 点赞文章
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "点赞文章", businessType = BusinessType.UPDATE) @Log(title = "点赞文章", businessType = BusinessType.UPDATE)
@PostMapping("/{id}/like") @PostMapping("/{id}/like")
public AjaxResult likeArticle(@PathVariable Long id) { public AjaxResult likeArticle(@PathVariable Long id) {
@ -187,13 +414,14 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 收藏文章 * 收藏文章
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "收藏文章", businessType = BusinessType.OTHER)
@PostMapping("/{id}/collect") @PostMapping("/{id}/collect")
public AjaxResult collectArticle(@PathVariable Long id) { public AjaxResult collectArticle(@PathVariable Long id) {
Long currentUserId = SecurityUtils.getUserId(); Long currentUserId = SecurityUtils.getUserId();
if (currentUserId == null) { if (currentUserId == null) {
return error("请先登录"); return error("请先登录");
} }
// 检查文章是否存在 // 检查文章是否存在
VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id); VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id);
if (article == null) { if (article == null) {
@ -225,6 +453,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 获取我的收藏文章列表 * 获取我的收藏文章列表
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/myCollections") @GetMapping("/myCollections")
public TableDataInfo getMyCollections() { public TableDataInfo getMyCollections() {
Long currentUserId = SecurityUtils.getUserId(); Long currentUserId = SecurityUtils.getUserId();
@ -257,6 +487,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 获取论坛统计信息 * 获取论坛统计信息
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/statistics") @GetMapping("/statistics")
public AjaxResult getStatistics() { public AjaxResult getStatistics() {
return success(vetExperienceArticleService.selectForumStatistics()); return success(vetExperienceArticleService.selectForumStatistics());
@ -266,6 +498,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 获取最新文章 * 获取最新文章
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/latest") @GetMapping("/latest")
public AjaxResult getLatestArticles(@RequestParam(defaultValue = "10") Integer limit) { public AjaxResult getLatestArticles(@RequestParam(defaultValue = "10") Integer limit) {
List<VetExperienceArticle> articles = vetExperienceArticleService.selectLatestArticles(limit); List<VetExperienceArticle> articles = vetExperienceArticleService.selectLatestArticles(limit);
@ -276,6 +510,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 获取分类选项 * 获取分类选项
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/options") @GetMapping("/options")
public AjaxResult getCategoryOptions() { public AjaxResult getCategoryOptions() {
// 直接从字典表查询 // 直接从字典表查询
@ -297,6 +533,8 @@ public class VetExperienceArticleController extends BaseController {
/** /**
* 获取标签选项 * 获取标签选项
*/ */
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/tags/options") @GetMapping("/tags/options")
public AjaxResult getTagOptions() { public AjaxResult getTagOptions() {
List<Map<String, Object>> options = new ArrayList<>(); List<Map<String, Object>> options = new ArrayList<>();
@ -316,4 +554,27 @@ public class VetExperienceArticleController extends BaseController {
return success(options); return success(options);
} }
/**
* 草稿列表接口我的草稿
*/
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医经验文章", businessType = BusinessType.OTHER)
@GetMapping("/draftList")
public TableDataInfo getMyDrafts() {
Long userId = SecurityUtils.getUserId();
if (userId == null) {
throw new RuntimeException("用户未登录");
}
// 创建查询对象只查询草稿状态的文章
VetExperienceArticle query = new VetExperienceArticle();
query.setUserId(userId);
query.setStatus("0"); // 0表示草稿状态
startPage();
List<VetExperienceArticle> drafts = vetExperienceArticleService.selectVetExperienceArticleList(query);
return getDataTable(drafts);
}
} }

6
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java

@ -1,6 +1,8 @@
package com.chenhai.web.controller.vet; package com.chenhai.web.controller.vet;
import java.util.List; import java.util.List;
import com.chenhai.common.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -38,7 +40,7 @@ public class VetKnowledgeController extends BaseController
/** /**
* 查询兽医文章列表 * 查询兽医文章列表
*/ */
@PreAuthorize("@ss.hasPermi('vet:knowledge:list') or @ss.hasRole('muhu')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:list') or @ss.hasRole('muhu') or @ss.hasRole('vet')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetKnowledge vetKnowledge) public TableDataInfo list(VetKnowledge vetKnowledge)
{ {
@ -108,7 +110,7 @@ public class VetKnowledgeController extends BaseController
/** /**
* 提交审核 * 提交审核
*/ */
@PreAuthorize("@ss.hasPermi('vet:knowledge:submit') or @ss.hasRole('muhu')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:submit') or @ss.hasRole('muhu')or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE) @Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/submit/{id}") @PutMapping("/submit/{id}")
public AjaxResult submitForAudit(@PathVariable Long id) { public AjaxResult submitForAudit(@PathVariable Long id) {

3
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java

@ -73,6 +73,7 @@ public class VetNotificationController extends BaseController
/** /**
* 获取通知统计信息用于首页卡片 * 获取通知统计信息用于首页卡片
*/ */
@Log(title = "兽医通知", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:notification:query')") @PreAuthorize("@ss.hasPermi('vet:notification:query')")
@GetMapping("/stats/card") @GetMapping("/stats/card")
public AjaxResult getNotificationCardStats() { public AjaxResult getNotificationCardStats() {
@ -131,6 +132,7 @@ public class VetNotificationController extends BaseController
/** /**
* 查询兽医通知列表 * 查询兽医通知列表
*/ */
@Log(title = "兽医通知", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:notification:list')") @PreAuthorize("@ss.hasPermi('vet:notification:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetNotification vetNotification) public TableDataInfo list(VetNotification vetNotification)
@ -167,6 +169,7 @@ public class VetNotificationController extends BaseController
/** /**
* 获取兽医通知详细信息 * 获取兽医通知详细信息
*/ */
@Log(title = "兽医通知", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:notification:query')") @PreAuthorize("@ss.hasPermi('vet:notification:query')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) public AjaxResult getInfo(@PathVariable("id") Long id)

6
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java

@ -66,6 +66,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 查询兽医个人信息列表 * 查询兽医个人信息列表
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:list')") @PreAuthorize("@ss.hasPermi('vet:info:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetPersonalInfo vetPersonalInfo) public TableDataInfo list(VetPersonalInfo vetPersonalInfo)
@ -85,6 +86,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 获取兽医完整信息包含证书详情和用户信息 * 获取兽医完整信息包含证书详情和用户信息
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:view')") @PreAuthorize("@ss.hasPermi('vet:info:view')")
@GetMapping("/full/{id}") @GetMapping("/full/{id}")
public AjaxResult getFullInfo(@PathVariable("id") Long id) public AjaxResult getFullInfo(@PathVariable("id") Long id)
@ -126,6 +128,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 获取当前登录用户的兽医完整信息 * 获取当前登录用户的兽医完整信息
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:query')") @PreAuthorize("@ss.hasPermi('vet:info:query')")
@GetMapping("/full/current") @GetMapping("/full/current")
public AjaxResult getCurrentFullInfo() public AjaxResult getCurrentFullInfo()
@ -171,6 +174,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 获取兽医个人信息详细信息带用户信息 * 获取兽医个人信息详细信息带用户信息
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:query')") @PreAuthorize("@ss.hasPermi('vet:info:query')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) public AjaxResult getInfo(@PathVariable("id") Long id)
@ -191,6 +195,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 根据用户ID获取兽医信息 * 根据用户ID获取兽医信息
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:query')") @PreAuthorize("@ss.hasPermi('vet:info:query')")
@GetMapping(value = "/byUserId/{userId}") @GetMapping(value = "/byUserId/{userId}")
public AjaxResult getInfoByUserId(@PathVariable("userId") Long userId) public AjaxResult getInfoByUserId(@PathVariable("userId") Long userId)
@ -294,6 +299,7 @@ public class VetPersonalInfoController extends BaseController
/** /**
* 获取当前登录用户的兽医信息快捷方法 * 获取当前登录用户的兽医信息快捷方法
*/ */
@Log(title = "兽医个人信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:info:query')") @PreAuthorize("@ss.hasPermi('vet:info:query')")
@GetMapping("/current") @GetMapping("/current")
public AjaxResult getCurrentInfo() public AjaxResult getCurrentInfo()

31
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java

@ -39,11 +39,24 @@ public class VetProductController extends BaseController
/** /**
* 查询兽医产品信息列表 * 查询兽医产品信息列表
*/ */
@Log(title = "兽医产品信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:product:list')") @PreAuthorize("@ss.hasPermi('vet:product:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetProduct vetProduct) public TableDataInfo list(VetProduct vetProduct)
{ {
startPage(); startPage();
/* // 如果是普通用户只查看自己的产品
if (!SecurityUtils.isAdmin()) {
try {
Long userId = SecurityUtils.getUserId();
vetProduct.setUserId(userId);
} catch (Exception e) {
// 如果获取不到用户ID设置一个不存在的ID
vetProduct.setUserId(-1L);
}
}*/
List<VetProduct> list = vetProductService.selectVetProductList(vetProduct); List<VetProduct> list = vetProductService.selectVetProductList(vetProduct);
return getDataTable(list); return getDataTable(list);
} }
@ -64,6 +77,7 @@ public class VetProductController extends BaseController
/** /**
* 获取兽医产品信息详细信息 * 获取兽医产品信息详细信息
*/ */
@Log(title = "兽医产品信息", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:product:query')") @PreAuthorize("@ss.hasPermi('vet:product:query')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) public AjaxResult getInfo(@PathVariable("id") Long id)
@ -159,11 +173,26 @@ public class VetProductController extends BaseController
/** /**
* 取消审核 * 取消审核
*/ */
@PreAuthorize("@ss.hasPermi('vet:product:edit')")
/* @PreAuthorize("@ss.hasPermi('vet:product:edit')")*/
@Log(title = "兽医产品信息", businessType = BusinessType.UPDATE) @Log(title = "兽医产品信息", businessType = BusinessType.UPDATE)
@PostMapping("/cancelAudit/{id}") @PostMapping("/cancelAudit/{id}")
public AjaxResult cancelAudit(@PathVariable("id") Long id) public AjaxResult cancelAudit(@PathVariable("id") Long id)
{ {
return toAjax(vetProductService.cancelAudit(id)); return toAjax(vetProductService.cancelAudit(id));
} }
/**
* 管理员查询所有产品信息列表用于审核
*/
@Log(title = "产品审核", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:product:audit:list')")
@GetMapping("/audit/list")
public TableDataInfo auditList(VetProduct vetProduct)
{
startPage();
// 管理员查看所有产品列表用于审核
List<VetProduct> list = vetProductService.selectAllVetProductList(vetProduct);
return getDataTable(list);
}
} }

77
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java

@ -5,6 +5,7 @@ import com.chenhai.common.core.controller.BaseController;
import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.domain.AjaxResult;
import com.chenhai.common.core.page.TableDataInfo; import com.chenhai.common.core.page.TableDataInfo;
import com.chenhai.common.enums.BusinessType; import com.chenhai.common.enums.BusinessType;
import com.chenhai.common.exception.ServiceException;
import com.chenhai.common.utils.SecurityUtils; import com.chenhai.common.utils.SecurityUtils;
import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.domain.VetQualification;
import com.chenhai.vet.service.IVetQualificationService; import com.chenhai.vet.service.IVetQualificationService;
@ -39,6 +40,7 @@ public class VetQualificationController extends BaseController
/** /**
* 获取资质类型选项下拉框用 * 获取资质类型选项下拉框用
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/type/options") @GetMapping("/type/options")
public AjaxResult getQualificationTypeOptions() { public AjaxResult getQualificationTypeOptions() {
String sql = "SELECT dict_value as value, dict_label as label " + String sql = "SELECT dict_value as value, dict_label as label " +
@ -59,6 +61,7 @@ public class VetQualificationController extends BaseController
/** /**
* 获取经营范围选项下拉框用 * 获取经营范围选项下拉框用
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/scope/options") @GetMapping("/scope/options")
public AjaxResult getScopeOptions() { public AjaxResult getScopeOptions() {
String sql = "SELECT dict_value as value, dict_label as label " + String sql = "SELECT dict_value as value, dict_label as label " +
@ -79,6 +82,7 @@ public class VetQualificationController extends BaseController
/** /**
* 查询兽医资质列表含证书信息 * 查询兽医资质列表含证书信息
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:qualification:list')") @PreAuthorize("@ss.hasPermi('vet:qualification:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetQualification vetQualification) public TableDataInfo list(VetQualification vetQualification)
@ -95,6 +99,7 @@ public class VetQualificationController extends BaseController
/** /**
* 查询即将过期的资质证书 * 查询即将过期的资质证书
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:qualification:list')") @PreAuthorize("@ss.hasPermi('vet:qualification:list')")
@GetMapping("/listExpiring") @GetMapping("/listExpiring")
public TableDataInfo listExpiring(VetQualification vetQualification) public TableDataInfo listExpiring(VetQualification vetQualification)
@ -112,6 +117,7 @@ public class VetQualificationController extends BaseController
/** /**
* 查询用户的证书列表展开每个证书 * 查询用户的证书列表展开每个证书
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:qualification:list')") @PreAuthorize("@ss.hasPermi('vet:qualification:list')")
@GetMapping("/certificate/list") @GetMapping("/certificate/list")
public TableDataInfo getCertificateList(VetQualification vetQualification) public TableDataInfo getCertificateList(VetQualification vetQualification)
@ -156,10 +162,74 @@ public class VetQualificationController extends BaseController
return getDataTable(certificateList); return getDataTable(certificateList);
} }
/**
* 查看指定资质的证书列表
*/
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:qualification:list')")
@GetMapping("/certificate/{qualificationId}/list")
public TableDataInfo getCertificateByQualificationId(@PathVariable Long qualificationId)
{
Long userId = SecurityUtils.getUserId();
// 创建查询条件
VetQualification query = new VetQualification();
query.setQualificationId(qualificationId);
// 查询指定资质
List<VetQualification> qualifications = vetQualificationService.selectVetQualificationList(query);
if (qualifications == null || qualifications.isEmpty()) {
return getDataTable(new ArrayList<>());
}
VetQualification qualification = qualifications.get(0);
// 权限验证非管理员只能查看自己的资质
if (!SecurityUtils.isAdmin(userId) && !qualification.getUserId().equals(userId)) {
throw new ServiceException("无权查看此资质的证书");
}
// 处理分页
startPage();
// 只处理当前资质的证书
List<Map<String, Object>> certificateList = new ArrayList<>();
List<VetQualification.CertificateInfo> certList = qualification.getCertificateList();
if (certList != null && !certList.isEmpty()) {
for (VetQualification.CertificateInfo cert : certList) {
Map<String, Object> certMap = new HashMap<>();
certMap.put("qualificationId", qualification.getQualificationId());
certMap.put("realName", qualification.getRealName());
certMap.put("certName", cert.getCertName());
certMap.put("certificateNo", cert.getCertificateNo());
certMap.put("issueDate", cert.getIssueDate());
certMap.put("expireDate", cert.getExpireDate());
certMap.put("issueOrg", cert.getIssueOrg());
certMap.put("certificateFiles", cert.getCertificateFiles());
certMap.put("certStatus", cert.getCertStatus());
certMap.put("certStatusLabel", getCertStatusLabel(cert.getCertStatus()));
if (cert.getCertId() != null) {
certMap.put("certId", String.valueOf(cert.getCertId()));
}
else if (qualification.getCertId() != null) {
certMap.put("certId", String.valueOf(qualification.getCertId()));
}
certificateList.add(certMap);
}
}
// 手动分页处理
return getDataTable(certificateList);
}
/** /**
* 根据证书ID查询证书详细信息 * 根据证书ID查询证书详细信息
* 证书信息存储在资质的certificatesJson字段中通过数据库JSON查询获取 * 证书信息存储在资质的certificatesJson字段中通过数据库JSON查询获取
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/certificate/{certId}") @GetMapping("/certificate/{certId}")
public AjaxResult getCertificateByCertId(@PathVariable("certId") Long certId) public AjaxResult getCertificateByCertId(@PathVariable("certId") Long certId)
{ {
@ -217,6 +287,7 @@ public class VetQualificationController extends BaseController
/** /**
* 登录后检查是否需要填写资质 * 登录后检查是否需要填写资质
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/checkNeedQualification") @GetMapping("/checkNeedQualification")
public AjaxResult checkNeedQualification() { public AjaxResult checkNeedQualification() {
Long userId = SecurityUtils.getUserId(); Long userId = SecurityUtils.getUserId();
@ -270,6 +341,7 @@ public class VetQualificationController extends BaseController
/** /**
* 获取兽医资质详细信息 * 获取兽医资质详细信息
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PreAuthorize("@ss.hasPermi('vet:qualification:query')") @PreAuthorize("@ss.hasPermi('vet:qualification:query')")
@GetMapping(value = "/{qualificationId}") @GetMapping(value = "/{qualificationId}")
public AjaxResult getInfo(@PathVariable("qualificationId") Long qualificationId) public AjaxResult getInfo(@PathVariable("qualificationId") Long qualificationId)
@ -297,6 +369,7 @@ public class VetQualificationController extends BaseController
{ {
Long sysUserId = SecurityUtils.getUserId(); Long sysUserId = SecurityUtils.getUserId();
String username = SecurityUtils.getUsername(); String username = SecurityUtils.getUsername();
try { try {
vetQualification.setUserId(sysUserId); vetQualification.setUserId(sysUserId);
vetQualification.setCreateBy(username); vetQualification.setCreateBy(username);
@ -445,6 +518,7 @@ public class VetQualificationController extends BaseController
/** /**
* 根据用户ID获取资质证书列表 * 根据用户ID获取资质证书列表
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/user/{userId}") @GetMapping("/user/{userId}")
public AjaxResult getByUserId(@PathVariable Long userId) { public AjaxResult getByUserId(@PathVariable Long userId) {
Long currentUserId = SecurityUtils.getUserId(); Long currentUserId = SecurityUtils.getUserId();
@ -460,6 +534,7 @@ public class VetQualificationController extends BaseController
/** /**
* 获取证书统计信息 * 获取证书统计信息
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@GetMapping("/statistics/{userId}") @GetMapping("/statistics/{userId}")
public AjaxResult getStatistics(@PathVariable Long userId) { public AjaxResult getStatistics(@PathVariable Long userId) {
Long currentUserId = SecurityUtils.getUserId(); Long currentUserId = SecurityUtils.getUserId();
@ -475,6 +550,7 @@ public class VetQualificationController extends BaseController
/** /**
* 手动触发证书检查 * 手动触发证书检查
*/ */
@Log(title = "兽医资质", businessType = BusinessType.OTHER)
@PostMapping("/manual-check/{userId}") @PostMapping("/manual-check/{userId}")
public AjaxResult manualCheck(@PathVariable Long userId) { public AjaxResult manualCheck(@PathVariable Long userId) {
Long currentUserId = SecurityUtils.getUserId(); Long currentUserId = SecurityUtils.getUserId();
@ -741,7 +817,6 @@ public class VetQualificationController extends BaseController
} catch (Exception e) { } catch (Exception e) {
log.warn("提取Long值失败: {}", obj, e); log.warn("提取Long值失败: {}", obj, e);
} }
return null; return null;
} }
} }

1
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java

@ -51,6 +51,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')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(VetTrainingVideo vetTrainingVideo) public TableDataInfo list(VetTrainingVideo vetTrainingVideo)

406
chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java

@ -4,15 +4,15 @@ import com.chenhai.vet.domain.VetQualification;
import com.chenhai.vet.domain.VetNotification; import com.chenhai.vet.domain.VetNotification;
import com.chenhai.vet.mapper.VetQualificationMapper; import com.chenhai.vet.mapper.VetQualificationMapper;
import com.chenhai.vet.mapper.VetNotificationMapper; import com.chenhai.vet.mapper.VetNotificationMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.*;
@Component @Component
@EnableScheduling @EnableScheduling
@ -25,69 +25,197 @@ public class CertificateRemindTask {
@Autowired @Autowired
private VetNotificationMapper vetNotificationMapper; private VetNotificationMapper vetNotificationMapper;
private final ObjectMapper objectMapper = new ObjectMapper();
// 每天上午9点执行 // 每天上午9点执行
@Scheduled(cron = "0 0 9 * * ?")/*
@Scheduled(cron = "0 * * * * ?")*/
/*@Scheduled(cron = "0 0 9 * * ?")*/
@Scheduled(cron = "0 */1 * * * ?")
public void dailyCertificateCheck() { public void dailyCertificateCheck() {
try { try {
// 查询所有包含证书信息的资质
VetQualification query = new VetQualification();
query.setCertName("");
List<VetQualification> qualifications = vetQualificationMapper.selectVetQualificationList(query);
// 过滤出有证书信息的记录
List<VetQualification> certificates = qualifications.stream()
.filter(q -> q.getCertName() != null && !q.getCertName().isEmpty())
.toList();
certificates.forEach(this::checkAndSendReminder);
// 查询所有资质记录
List<VetQualification> qualifications = vetQualificationMapper.selectVetQualificationList(new VetQualification());
for (VetQualification qualification : qualifications) {
try {
// 检查该资质下的所有证书包括JSON中的
checkAllCertificates(qualification);
} catch (Exception e) {
// 静默处理单个资质检查失败
}
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
// 静默处理整体任务失败
} }
} }
/** /**
* 检查单个证书并发送提醒
* 检查所有证书主表字段 + JSON字段
*/ */
private void checkAndSendReminder(VetQualification qualification) {
if (qualification == null || qualification.getExpireDate() == null) {
private void checkAllCertificates(VetQualification qualification) {
if (qualification == null) {
return; return;
} }
long daysRemaining = calculateDayDifference(new Date(), qualification.getExpireDate());
// 1. 先检查主表字段的证书
checkMainCertificate(qualification);
updateCertificateStatus(qualification, daysRemaining);
// 2. 再检查JSON字段中的证书
checkJsonCertificates(qualification);
}
if (!shouldSendReminder(qualification, daysRemaining) || hasRecentReminder(qualification, daysRemaining)) {
/**
* 检查主表字段中的证书信息
*/
private void checkMainCertificate(VetQualification qualification) {
if (qualification.getExpireDate() == null ||
qualification.getCertName() == null ||
qualification.getCertName().isEmpty()) {
return; return;
} }
sendReminder(qualification, daysRemaining);
Date expireDate = qualification.getExpireDate();
long daysRemaining = calculateDayDifference(new Date(), expireDate);
// 检查是否需要发送提醒
if (shouldSendReminder(daysRemaining) &&
!hasRecentReminderForCertificate(qualification, null, daysRemaining)) {
sendReminderForCertificate(qualification,
qualification.getCertName(),
qualification.getCertificateNo(),
expireDate,
null, // 主表证书没有单独的certId
daysRemaining);
}
} }
/** /**
* 发送提醒
* 检查JSON字段中的证书
*/ */
private void checkJsonCertificates(VetQualification qualification) {
if (qualification.getCertificatesJson() == null ||
qualification.getCertificatesJson().isEmpty() ||
"[]".equals(qualification.getCertificatesJson().trim())) {
return;
}
try {
// 尝试解析JSON
List<Map<String, Object>> certificates = parseCertificatesJson(qualification.getCertificatesJson());
for (Map<String, Object> certMap : certificates) {
try {
checkSingleJsonCertificate(qualification, certMap);
} catch (Exception e) {
// 继续检查下一个证书
}
}
} catch (Exception e) {
// JSON解析失败静默处理
}
}
/** /**
* 发送提醒
* 检查单个JSON证书
*/ */
private void sendReminder(VetQualification qualification, long daysRemaining) {
VetNotification notification = createBaseNotification(qualification);
private void checkSingleJsonCertificate(VetQualification qualification, Map<String, Object> certMap) {
try {
// 获取证书基本信息
String certName = getStringValue(certMap, "certName");
String certificateNo = getStringValue(certMap, "certificateNo");
Object expireDateObj = certMap.get("expireDate");
Object certIdObj = certMap.get("certId");
if (certName == null || certName.isEmpty() || expireDateObj == null) {
return;
}
// 解析过期日期
Date expireDate = parseDate(expireDateObj);
if (expireDate == null) {
return;
}
// 解析证书ID
Long certId = parseLong(certIdObj);
long daysRemaining = calculateDayDifference(new Date(), expireDate);
// 检查是否需要发送提醒
if (shouldSendReminder(daysRemaining) &&
!hasRecentReminderForCertificate(qualification, certId, daysRemaining)) {
sendReminderForCertificate(qualification, certName, certificateNo, expireDate, certId, daysRemaining);
}
} catch (Exception e) {
// 单个证书检查失败继续下一个
}
}
/**
* 解析证书JSON
*/
private List<Map<String, Object>> parseCertificatesJson(String certificatesJson) throws Exception {
if (certificatesJson == null || certificatesJson.isEmpty()) {
return new ArrayList<>();
}
// 先尝试清理JSON
String cleanedJson = cleanJsonString(certificatesJson);
return objectMapper.readValue(
cleanedJson,
objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class)
);
}
/**
* 清理JSON字符串
*/
private String cleanJsonString(String json) {
if (json == null || json.isEmpty()) {
return "[]";
}
String cleaned = json.trim();
// 确保是数组格式
if (!cleaned.startsWith("[") && cleaned.startsWith("{")) {
cleaned = "[" + cleaned + "]";
}
// 修复常见的JSON格式问题
cleaned = cleaned.replace("'", "\"");
cleaned = cleaned.replace("\\", "\\\\");
cleaned = cleaned.replace("\n", "").replace("\r", "").replace("\t", "");
return cleaned;
}
/**
* 发送单个证书提醒
*/
private void sendReminderForCertificate(VetQualification qualification,
String certName,
String certificateNo,
Date expireDate,
Long certId,
long daysRemaining) {
VetNotification notification = createCertificateNotification(qualification, certId);
if (daysRemaining <= 0) { if (daysRemaining <= 0) {
// 只发送过期当天的提醒
// 过期提醒
if (daysRemaining == 0) { if (daysRemaining == 0) {
setExpiredContent(notification, qualification, 0);
notification.setRemindLevel(3); // 最高级别
setExpiredContent(notification, certName, certificateNo, expireDate, 0);
notification.setRemindLevel(3);
vetNotificationMapper.insertVetNotification(notification); vetNotificationMapper.insertVetNotification(notification);
} }
// 过期后不再提醒
return; return;
} else if (daysRemaining <= 7) { } else if (daysRemaining <= 7) {
setCountdownContent(notification, qualification, daysRemaining);
// 7天内过期
setCountdownContent(notification, certName, certificateNo, expireDate, daysRemaining);
notification.setRemindLevel(daysRemaining <= 3 ? 3 : 2); notification.setRemindLevel(daysRemaining <= 3 ? 3 : 2);
} else if (daysRemaining == 15 || daysRemaining == 30) { } else if (daysRemaining == 15 || daysRemaining == 30) {
setPreExpireContent(notification, qualification, daysRemaining);
// 15天或30天提醒
setPreExpireContent(notification, certName, certificateNo, expireDate, daysRemaining);
notification.setRemindLevel(daysRemaining == 30 ? 1 : 2); notification.setRemindLevel(daysRemaining == 30 ? 1 : 2);
} else { } else {
return; return;
@ -97,12 +225,19 @@ public class CertificateRemindTask {
} }
/** /**
* 创建基础通知对象
* 创建证书通知
*/ */
private VetNotification createBaseNotification(VetQualification qualification) {
private VetNotification createCertificateNotification(VetQualification qualification, Long certId) {
VetNotification notification = new VetNotification(); VetNotification notification = new VetNotification();
notification.setUserId(qualification.getUserId()); notification.setUserId(qualification.getUserId());
notification.setRelatedId(qualification.getQualificationId().toString());
// 构建关联ID资质ID:证书ID如果证书ID为空只使用资质ID
String relatedId = qualification.getQualificationId().toString();
if (certId != null && certId != 0) {
relatedId = qualification.getQualificationId() + ":" + certId;
}
notification.setRelatedId(relatedId);
notification.setType("CERT_EXPIRE_REMIND"); notification.setType("CERT_EXPIRE_REMIND");
notification.setIsRead(0); notification.setIsRead(0);
notification.setCreateTime(new Date()); notification.setCreateTime(new Date());
@ -112,57 +247,59 @@ public class CertificateRemindTask {
/** /**
* 设置过期内容 * 设置过期内容
*/ */
private void setExpiredContent(VetNotification notification, VetQualification qualification, long daysExpired) {
private void setExpiredContent(VetNotification notification, String certName, String certificateNo, Date expireDate, long daysExpired) {
if (daysExpired == 0) { if (daysExpired == 0) {
notification.setTitle("🚨 证书今天过期!"); notification.setTitle("🚨 证书今天过期!");
notification.setContent(String.format("您的《%s》证书今天已过期!请立即更新。", qualification.getCertName()));
String content = String.format("您的《%s》证书今天已过期!请立即更新。", certName);
if (certificateNo != null && !certificateNo.isEmpty()) {
content = String.format("您的《%s》证书(编号:%s)今天已过期!请立即更新。", certName, certificateNo);
}
notification.setContent(content);
} }
// 移除过期多天的提醒
} }
/** /**
* 设置倒计时内容 * 设置倒计时内容
*/ */
private void setCountdownContent(VetNotification notification, VetQualification qualification, long daysRemaining) {
private void setCountdownContent(VetNotification notification, String certName, String certificateNo, Date expireDate, long daysRemaining) {
notification.setTitle("⚠️ 证书还剩" + daysRemaining + "天过期"); notification.setTitle("⚠️ 证书还剩" + daysRemaining + "天过期");
notification.setContent(String.format("您的《%s》证书还剩%d天过期,请及时更新。", qualification.getCertName(), daysRemaining));
String content = String.format("您的《%s》证书还剩%d天过期,请及时更新。", certName, daysRemaining);
if (certificateNo != null && !certificateNo.isEmpty()) {
content = String.format("您的《%s》证书(编号:%s)还剩%d天过期,请及时更新。", certName, certificateNo, daysRemaining);
}
notification.setContent(content);
} }
/** /**
* 设置预过期内容 * 设置预过期内容
*/ */
private void setPreExpireContent(VetNotification notification, VetQualification qualification, long daysRemaining) {
private void setPreExpireContent(VetNotification notification, String certName, String certificateNo, Date expireDate, long daysRemaining) {
String timeText = daysRemaining == 30 ? "30天" : "15天"; String timeText = daysRemaining == 30 ? "30天" : "15天";
notification.setTitle("📅 证书还剩" + timeText + "过期"); notification.setTitle("📅 证书还剩" + timeText + "过期");
notification.setContent(String.format("您的《%s》证书将在%s后过期,请提前准备更新。", qualification.getCertName(), timeText));
String content = String.format("您的《%s》证书将在%s后过期,请提前准备更新。", certName, timeText);
if (certificateNo != null && !certificateNo.isEmpty()) {
content = String.format("您的《%s》证书(编号:%s)将在%s后过期,请提前准备更新。", certName, certificateNo, timeText);
}
notification.setContent(content);
} }
/** /**
* 判断是否需要发送提醒 * 判断是否需要发送提醒
*/ */
private boolean shouldSendReminder(VetQualification qualification, long daysRemaining) {
String status = qualification.getCertStatus();
if ("2".equals(status)) { // 已过期
// 只在过期的第一天提醒daysRemaining = 0 刚刚过期时
return daysRemaining == 0; // 只提醒过期当天
}
if ("1".equals(status)) { // 即将过期
return daysRemaining == 30 || daysRemaining == 15 || (daysRemaining >= 1 && daysRemaining <= 7);
}
if ("0".equals(status)) { // 正常
return daysRemaining == 30 || daysRemaining == 15;
}
return false;
private boolean shouldSendReminder(long daysRemaining) {
// 只在这些天数发送提醒
return daysRemaining == 0 ||
daysRemaining == 7 ||
daysRemaining == 3 ||
daysRemaining == 1 ||
daysRemaining == 15 ||
daysRemaining == 30;
} }
/** /**
* 检查最近是否已发送过提醒 * 检查最近是否已发送过提醒
*/ */
private boolean hasRecentReminder(VetQualification qualification, long daysRemaining) {
private boolean hasRecentReminderForCertificate(VetQualification qualification, Long certId, long daysRemaining) {
try { try {
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
@ -174,102 +311,125 @@ public class CertificateRemindTask {
cal.add(Calendar.DAY_OF_MONTH, 1); cal.add(Calendar.DAY_OF_MONTH, 1);
Date endOfDay = cal.getTime(); Date endOfDay = cal.getTime();
// 检查今天是否已发送
// 构建查询条件
VetNotification query = new VetNotification(); VetNotification query = new VetNotification();
query.setRelatedId(qualification.getQualificationId().toString());
// 构建关联ID
String relatedId = qualification.getQualificationId().toString();
if (certId != null && certId != 0) {
relatedId = qualification.getQualificationId() + ":" + certId;
}
query.setRelatedId(relatedId);
query.setType("CERT_EXPIRE_REMIND"); query.setType("CERT_EXPIRE_REMIND");
List<VetNotification> notifications = vetNotificationMapper.selectVetNotificationList(query); List<VetNotification> notifications = vetNotificationMapper.selectVetNotificationList(query);
// 获取今天的所有通知
List<VetNotification> todayNotifications = notifications.stream() List<VetNotification> todayNotifications = notifications.stream()
.filter(n -> n.getCreateTime() != null && .filter(n -> n.getCreateTime() != null &&
n.getCreateTime().after(startOfDay) && n.getCreateTime().after(startOfDay) &&
n.getCreateTime().before(endOfDay)) n.getCreateTime().before(endOfDay))
.toList(); .toList();
// 如果没有今天的通知直接返回
if (todayNotifications.isEmpty()) {
return false;
}
// 生成当前应该发送的通知标题
String expectedTitle = generateExpectedTitle(qualification, daysRemaining);
// 检查今天是否已有相同标题的通知
boolean hasSameTitleToday = todayNotifications.stream()
.anyMatch(n -> expectedTitle.equals(n.getTitle()));
if (hasSameTitleToday) {
return true;
}
// 已过期证书检查最近7天是否有相同标题的通知
if (daysRemaining <= 0) {
cal.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysAgo = cal.getTime();
List<VetNotification> recentNotifications = notifications.stream()
.filter(n -> n.getCreateTime() != null &&
n.getCreateTime().after(sevenDaysAgo))
.toList();
boolean hasSameTitleRecent = recentNotifications.stream()
.anyMatch(n -> expectedTitle.equals(n.getTitle()));
if (hasSameTitleRecent) {
return true;
}
}
return false;
return !todayNotifications.isEmpty();
} catch (Exception e) { } catch (Exception e) {
return false; return false;
} }
} }
/** /**
* 生成预期的通知标题
* 从Map获取字符串值
*/ */
private String generateExpectedTitle(VetQualification qualification, long daysRemaining) {
if (daysRemaining <= 0) {
long daysExpired = -daysRemaining;
if (daysExpired == 0) {
return "🚨 证书今天过期!";
} else {
return "🚨 证书已过期" + daysExpired + "天";
private String getStringValue(Map<String, Object> map, String key) {
Object value = map.get(key);
return value != null ? value.toString() : null;
}
/**
* 解析Long值
*/
private Long parseLong(Object obj) {
if (obj == null) {
return null;
}
try {
if (obj instanceof Number) {
return ((Number) obj).longValue();
} else if (obj instanceof String) {
String str = ((String) obj).trim();
if (str.isEmpty()) {
return null;
}
// 处理包含下划线的ID
if (str.contains("_")) {
str = str.split("_")[0];
}
return Long.parseLong(str);
} }
} else if (daysRemaining <= 7) {
return "⚠️ 证书还剩" + daysRemaining + "天过期";
} else if (daysRemaining == 15 || daysRemaining == 30) {
return "📅 证书还剩" + daysRemaining + "天过期";
} else {
return ""; // 其他情况不发送
} catch (Exception e) {
// 静默处理解析失败
} }
return null;
} }
/** /**
* 更新证书状态
* 解析日期
*/ */
private void updateCertificateStatus(VetQualification qualification, long daysRemaining) {
private Date parseDate(Object dateObj) {
if (dateObj == null) {
return null;
}
try { try {
String newStatus = daysRemaining <= 0 ? "2" :
daysRemaining <= 30 ? "1" : "0";
if (dateObj instanceof Date) {
return (Date) dateObj;
} else if (dateObj instanceof String) {
String dateStr = ((String) dateObj).trim();
// 尝试常见格式
SimpleDateFormat[] formats = {
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyy/MM/dd"),
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
};
for (SimpleDateFormat sdf : formats) {
try {
return sdf.parse(dateStr);
} catch (Exception e) {
// 继续尝试下一个格式
}
}
if (!newStatus.equals(qualification.getCertStatus())) {
qualification.setCertStatus(newStatus);
// 更新数据库中的状态
vetQualificationMapper.updateVetQualification(qualification);
// 尝试解析为时间戳
try {
long timestamp = Long.parseLong(dateStr);
return new Date(timestamp);
} catch (NumberFormatException e) {
// 不是时间戳格式
}
} else if (dateObj instanceof Long) {
return new Date((Long) dateObj);
} else if (dateObj instanceof Integer) {
return new Date(((Integer) dateObj).longValue() * 1000L);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
// 静默处理解析失败
} }
return null;
} }
/** /**
* 计算天数差忽略时间部分 * 计算天数差忽略时间部分
*/ */
private long calculateDayDifference(Date startDate, Date endDate) { private long calculateDayDifference(Date startDate, Date endDate) {
if (startDate == null || endDate == null) {
return 0;
}
Calendar startCal = Calendar.getInstance(); Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate); startCal.setTime(startDate);
resetTime(startCal); resetTime(startCal);

146
chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java

@ -0,0 +1,146 @@
package com.chenhai.vet.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.chenhai.common.annotation.Excel;
import com.chenhai.common.core.domain.BaseEntity;
/**
* 商家信息对象 merchant_info
*
* @author ruoyi
* @date 2026-02-04
*/
public class MerchantInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 店铺ID,主键 */
private Long shopId;
/** 店铺名称 */
@Excel(name = "店铺名称")
private String shopName;
/** 店铺地址 */
@Excel(name = "店铺地址")
private String shopAddress;
/** 联系电话 */
@Excel(name = "联系电话")
private String phone;
/** 关联用户ID(店主) */
@Excel(name = "关联用户ID", readConverterExp = "店=主")
private Long userId;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date createdAt;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date updatedAt;
/** 是否启用(1启用,0禁用) */
@Excel(name = "是否启用", readConverterExp = "1=启用,0禁用")
private Integer isActive;
public void setShopId(Long shopId)
{
this.shopId = shopId;
}
public Long getShopId()
{
return shopId;
}
public void setShopName(String shopName)
{
this.shopName = shopName;
}
public String getShopName()
{
return shopName;
}
public void setShopAddress(String shopAddress)
{
this.shopAddress = shopAddress;
}
public String getShopAddress()
{
return shopAddress;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getPhone()
{
return phone;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public Long getUserId()
{
return userId;
}
public void setCreatedAt(Date createdAt)
{
this.createdAt = createdAt;
}
public Date getCreatedAt()
{
return createdAt;
}
public void setUpdatedAt(Date updatedAt)
{
this.updatedAt = updatedAt;
}
public Date getUpdatedAt()
{
return updatedAt;
}
public void setIsActive(Integer isActive)
{
this.isActive = isActive;
}
public Integer getIsActive()
{
return isActive;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("shopId", getShopId())
.append("shopName", getShopName())
.append("shopAddress", getShopAddress())
.append("phone", getPhone())
.append("userId", getUserId())
.append("createdAt", getCreatedAt())
.append("updatedAt", getUpdatedAt())
.append("isActive", getIsActive())
.toString();
}
}

236
chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java

@ -1,7 +1,10 @@
package com.chenhai.vet.domain; package com.chenhai.vet.domain;
import java.util.Date; import java.util.Date;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import com.chenhai.common.annotation.Excel; import com.chenhai.common.annotation.Excel;
@ -9,7 +12,7 @@ import com.chenhai.common.core.domain.BaseEntity;
/** /**
* 兽医经验文章对象 vet_experience_article * 兽医经验文章对象 vet_experience_article
*
*
* @author ruoyi * @author ruoyi
* @date 2026-01-06 * @date 2026-01-06
*/ */
@ -80,6 +83,9 @@ public class VetExperienceArticle extends BaseEntity
@Excel(name = "状态", dictType = "article_status") @Excel(name = "状态", dictType = "article_status")
private String status; private String status;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String searchKey;
/** 审核状态(0待审核 1审核中 2审核通过 3审核驳回 4敏感内容驳回) */ /** 审核状态(0待审核 1审核中 2审核通过 3审核驳回 4敏感内容驳回) */
private String auditStatus; private String auditStatus;
@ -96,7 +102,6 @@ public class VetExperienceArticle extends BaseEntity
/** 审核人姓名 */ /** 审核人姓名 */
private String auditorName; private String auditorName;
/** 是否包含敏感词(0否 1是) */ /** 是否包含敏感词(0否 1是) */
@Excel(name = "是否包含敏感词", readConverterExp = "0=否,1=是") @Excel(name = "是否包含敏感词", readConverterExp = "0=否,1=是")
private String isSensitive; private String isSensitive;
@ -112,7 +117,7 @@ public class VetExperienceArticle extends BaseEntity
/** 浏览次数 */ /** 浏览次数 */
@Excel(name = "浏览次数") @Excel(name = "浏览次数")
private Integer viewCount;
private Long viewCount;
/** 点赞数 */ /** 点赞数 */
@Excel(name = "点赞数") @Excel(name = "点赞数")
@ -122,17 +127,37 @@ public class VetExperienceArticle extends BaseEntity
@Excel(name = "收藏数") @Excel(name = "收藏数")
private Integer collectCount; private Integer collectCount;
// 确保有对应的getter和setter
public Integer getViewCount() {
return viewCount;
/** 用户角色 */
private String userRole;
/** 用户类型(显示用) */
private String userType;
/** 浏览统计信息(从article_view_log表查询) */
@JsonInclude(JsonInclude.Include.NON_NULL)
private Map<String, Object> viewStats;
/** 今日浏览量(计算字段) */
private Integer todayViewCount;
public String getUserRole() {
return userRole;
} }
public void setViewCount(Integer viewCount) {
this.viewCount = viewCount;
public void setUserRole(String userRole) {
this.userRole = userRole;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
} }
public Integer getLikeCount() { public Integer getLikeCount() {
return likeCount;
return likeCount != null ? likeCount : 0;
} }
public void setLikeCount(Integer likeCount) { public void setLikeCount(Integer likeCount) {
@ -140,69 +165,69 @@ public class VetExperienceArticle extends BaseEntity
} }
public Integer getCollectCount() { public Integer getCollectCount() {
return collectCount;
return collectCount != null ? collectCount : 0;
} }
public void setCollectCount(Integer collectCount) { public void setCollectCount(Integer collectCount) {
this.collectCount = collectCount; this.collectCount = collectCount;
} }
public void setId(Long id)
public void setId(Long id)
{ {
this.id = id; this.id = id;
} }
public Long getId()
public Long getId()
{ {
return id; return id;
} }
public void setTitle(String title)
public void setTitle(String title)
{ {
this.title = title; this.title = title;
} }
public String getTitle()
public String getTitle()
{ {
return title; return title;
} }
public void setContent(String content)
public void setContent(String content)
{ {
this.content = content; this.content = content;
} }
public String getContent()
public String getContent()
{ {
return content; return content;
} }
public void setSummary(String summary)
public void setSummary(String summary)
{ {
this.summary = summary; this.summary = summary;
} }
public String getSummary()
public String getSummary()
{ {
return summary; return summary;
} }
public void setCoverImage(String coverImage)
public void setCoverImage(String coverImage)
{ {
this.coverImage = coverImage; this.coverImage = coverImage;
} }
public String getCoverImage()
public String getCoverImage()
{ {
return coverImage; return coverImage;
} }
public void setImages(String images)
public void setImages(String images)
{ {
this.images = images; this.images = images;
} }
public String getImages()
public String getImages()
{ {
return images; return images;
} }
@ -217,152 +242,219 @@ public class VetExperienceArticle extends BaseEntity
return userId; return userId;
} }
public void setVetName(String vetName)
public void setVetName(String vetName)
{ {
this.vetName = vetName; this.vetName = vetName;
} }
public String getVetName()
public String getVetName()
{ {
return vetName; return vetName;
} }
public void setVetAvatar(String vetAvatar)
public void setVetAvatar(String vetAvatar)
{ {
this.vetAvatar = vetAvatar; this.vetAvatar = vetAvatar;
} }
public String getVetAvatar()
public String getVetAvatar()
{ {
return vetAvatar; return vetAvatar;
} }
public void setVetTitle(String vetTitle)
public void setVetTitle(String vetTitle)
{ {
this.vetTitle = vetTitle; this.vetTitle = vetTitle;
} }
public String getVetTitle()
public String getVetTitle()
{ {
return vetTitle; return vetTitle;
} }
public void setCategoryId(Long categoryId)
public void setCategoryId(Long categoryId)
{ {
this.categoryId = categoryId; this.categoryId = categoryId;
} }
public Long getCategoryId()
public Long getCategoryId()
{ {
return categoryId; return categoryId;
} }
public void setCategoryName(String categoryName)
public void setCategoryName(String categoryName)
{ {
this.categoryName = categoryName; this.categoryName = categoryName;
} }
public String getCategoryName()
public String getCategoryName()
{ {
return categoryName; return categoryName;
} }
public void setTags(String tags)
public void setTags(String tags)
{ {
this.tags = tags; this.tags = tags;
} }
public String getTags()
public String getTags()
{ {
return tags; return tags;
} }
public void setIsTop(String isTop)
public void setIsTop(String isTop)
{ {
this.isTop = isTop; this.isTop = isTop;
} }
public String getIsTop()
public String getIsTop()
{ {
return isTop; return isTop;
} }
public void setIsFeatured(String isFeatured)
public void setIsFeatured(String isFeatured)
{ {
this.isFeatured = isFeatured; this.isFeatured = isFeatured;
} }
public String getIsFeatured()
public String getIsFeatured()
{ {
return isFeatured; return isFeatured;
} }
public void setStatus(String status)
public void setStatus(String status)
{ {
this.status = status; this.status = status;
} }
public String getStatus()
public String getStatus()
{ {
return status; return status;
} }
public void setIsSensitive(String isSensitive)
public void setIsSensitive(String isSensitive)
{ {
this.isSensitive = isSensitive; this.isSensitive = isSensitive;
} }
public String getIsSensitive()
public String getIsSensitive()
{ {
return isSensitive; return isSensitive;
} }
public void setSensitiveWords(String sensitiveWords)
public void setSensitiveWords(String sensitiveWords)
{ {
this.sensitiveWords = sensitiveWords; this.sensitiveWords = sensitiveWords;
} }
public String getSensitiveWords()
public String getSensitiveWords()
{ {
return sensitiveWords; return sensitiveWords;
} }
public void setPublishTime(Date publishTime)
public void setPublishTime(Date publishTime)
{ {
this.publishTime = publishTime; this.publishTime = publishTime;
} }
public Date getPublishTime()
public Date getPublishTime()
{ {
return publishTime; return publishTime;
} }
// 修复添加返回语句
public Long getViewCount() {
return viewCount != null ? viewCount : 0L;
}
public void setViewCount(Long viewCount) {
this.viewCount = viewCount;
}
public Map<String, Object> getViewStats() {
return viewStats;
}
public void setViewStats(Map<String, Object> viewStats) {
this.viewStats = viewStats;
}
public Integer getTodayViewCount() {
return todayViewCount != null ? todayViewCount : 0;
}
public void setTodayViewCount(Integer todayViewCount) {
this.todayViewCount = todayViewCount;
}
public String getSearchKey() {
return searchKey;
}
public void setSearchKey(String searchKey) {
this.searchKey = searchKey;
}
/**
* 获取总浏览数从viewStats中获取
*/
public Integer getTotalViewCount() {
if (viewStats != null && viewStats.containsKey("totalViews")) {
Object total = viewStats.get("totalViews");
if (total instanceof Integer) {
return (Integer) total;
} else if (total instanceof Long) {
return ((Long) total).intValue();
}
}
return getViewCount() != null ? getViewCount().intValue() : 0;
}
/**
* 获取今日浏览数从viewStats中获取
*/
public Integer getTodayViews() {
if (viewStats != null && viewStats.containsKey("todayViews")) {
Object today = viewStats.get("todayViews");
if (today instanceof Integer) {
return (Integer) today;
}
}
return getTodayViewCount() != null ? getTodayViewCount() : 0;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("title", getTitle())
.append("content", getContent())
.append("summary", getSummary())
.append("coverImage", getCoverImage())
.append("images", getImages())
.append("userId", getUserId())
.append("vetName", getVetName())
.append("vetAvatar", getVetAvatar())
.append("vetTitle", getVetTitle())
.append("categoryId", getCategoryId())
.append("categoryName", getCategoryName())
.append("tags", getTags())
.append("isTop", getIsTop())
.append("isFeatured", getIsFeatured())
.append("status", getStatus())
.append("isSensitive", getIsSensitive())
.append("sensitiveWords", getSensitiveWords())
.append("publishTime", getPublishTime())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}
.append("id", getId())
.append("title", getTitle())
.append("content", getContent())
.append("summary", getSummary())
.append("coverImage", getCoverImage())
.append("images", getImages())
.append("userId", getUserId())
.append("vetName", getVetName())
.append("vetAvatar", getVetAvatar())
.append("vetTitle", getVetTitle())
.append("categoryId", getCategoryId())
.append("categoryName", getCategoryName())
.append("tags", getTags())
.append("isTop", getIsTop())
.append("isFeatured", getIsFeatured())
.append("status", getStatus())
.append("isSensitive", getIsSensitive())
.append("sensitiveWords", getSensitiveWords())
.append("publishTime", getPublishTime())
.append("viewCount", getViewCount())
.append("likeCount", getLikeCount())
.append("collectCount", getCollectCount())
.append("userRole", getUserRole())
.append("userType", getUserType())
.append("todayViewCount", getTodayViewCount())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

61
chenhai-system/src/main/java/com/chenhai/vet/mapper/MerchantInfoMapper.java

@ -0,0 +1,61 @@
package com.chenhai.vet.mapper;
import java.util.List;
import com.chenhai.vet.domain.MerchantInfo;
/**
* 商家信息Mapper接口
*
* @author ruoyi
* @date 2026-02-04
*/
public interface MerchantInfoMapper
{
/**
* 查询商家信息
*
* @param shopId 商家信息主键
* @return 商家信息
*/
public MerchantInfo selectMerchantInfoByShopId(Long shopId);
/**
* 查询商家信息列表
*
* @param merchantInfo 商家信息
* @return 商家信息集合
*/
public List<MerchantInfo> selectMerchantInfoList(MerchantInfo merchantInfo);
/**
* 新增商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
public int insertMerchantInfo(MerchantInfo merchantInfo);
/**
* 修改商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
public int updateMerchantInfo(MerchantInfo merchantInfo);
/**
* 删除商家信息
*
* @param shopId 商家信息主键
* @return 结果
*/
public int deleteMerchantInfoByShopId(Long shopId);
/**
* 批量删除商家信息
*
* @param shopIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteMerchantInfoByShopIds(Long[] shopIds);
}

2
chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java

@ -75,7 +75,7 @@ public interface VetExperienceArticleMapper
* @param id 文章主键 * @param id 文章主键
* @return 结果 * @return 结果
*/ */
public int incrementViewCount(Long id);
/* public int incrementViewCount(Long id);*/
/** /**
* 增加点赞数 * 增加点赞数

2
chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java

@ -71,4 +71,6 @@ public interface VetQualificationMapper
Map<String, Object> selectCertificateByCertId(@Param("certId") Long certId, @Param("userId") Long userId); Map<String, Object> selectCertificateByCertId(@Param("certId") Long certId, @Param("userId") Long userId);
VetQualification selectVetQualificationById(Long qualificationId);
} }

61
chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java

@ -0,0 +1,61 @@
package com.chenhai.vet.service;
import java.util.List;
import com.chenhai.vet.domain.MerchantInfo;
/**
* 商家信息Service接口
*
* @author ruoyi
* @date 2026-02-04
*/
public interface IMerchantInfoService
{
/**
* 查询商家信息
*
* @param shopId 商家信息主键
* @return 商家信息
*/
public MerchantInfo selectMerchantInfoByShopId(Long shopId);
/**
* 查询商家信息列表
*
* @param merchantInfo 商家信息
* @return 商家信息集合
*/
public List<MerchantInfo> selectMerchantInfoList(MerchantInfo merchantInfo);
/**
* 新增商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
public int insertMerchantInfo(MerchantInfo merchantInfo);
/**
* 修改商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
public int updateMerchantInfo(MerchantInfo merchantInfo);
/**
* 批量删除商家信息
*
* @param shopIds 需要删除的商家信息主键集合
* @return 结果
*/
public int deleteMerchantInfoByShopIds(Long[] shopIds);
/**
* 删除商家信息信息
*
* @param shopId 商家信息主键
* @return 结果
*/
public int deleteMerchantInfoByShopId(Long shopId);
}

10
chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java

@ -68,13 +68,6 @@ public interface IVetExperienceArticleService
*/ */
List<VetExperienceArticle> selectLatestArticles(Integer limit); List<VetExperienceArticle> selectLatestArticles(Integer limit);
/**
* 获取热门文章按浏览数排序
*
* @param limit 限制数量
* @return 文章集合
*/
List<VetExperienceArticle> selectHotArticles(Integer limit);
/** /**
* 根据用户ID获取文章 * 根据用户ID获取文章
@ -101,7 +94,7 @@ public interface IVetExperienceArticleService
* @param id 文章ID * @param id 文章ID
* @return 结果 * @return 结果
*/ */
int incrementViewCount(Long id);
/* int incrementViewCount(Long id);*/
/** /**
* 增加点赞数 * 增加点赞数
@ -132,4 +125,5 @@ public interface IVetExperienceArticleService
* @return 文章集合 * @return 文章集合
*/ */
List<VetExperienceArticle> searchArticles(String keyword); List<VetExperienceArticle> searchArticles(String keyword);
} }

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

@ -102,4 +102,12 @@ public interface IVetProductService
*/ */
public int cancelAudit(Long id); public int cancelAudit(Long id);
/**
* 管理员查询所有兽医产品信息列表用于审核
*
* @param vetProduct 兽医产品信息
* @return 兽医产品信息集合
*/
public List<VetProduct> selectAllVetProductList(VetProduct vetProduct);
} }

2
chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java

@ -98,4 +98,6 @@ public interface IVetQualificationService
*/ */
Map<String, Object> selectCertificateWithQualificationByCertId(Long certId, Long userId); Map<String, Object> selectCertificateWithQualificationByCertId(Long certId, Long userId);
VetQualification selectVetQualificationById(Long qualificationId);
} }

93
chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java

@ -0,0 +1,93 @@
package com.chenhai.vet.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chenhai.vet.mapper.MerchantInfoMapper;
import com.chenhai.vet.domain.MerchantInfo;
import com.chenhai.vet.service.IMerchantInfoService;
/**
* 商家信息Service业务层处理
*
* @author ruoyi
* @date 2026-02-04
*/
@Service
public class MerchantInfoServiceImpl implements IMerchantInfoService
{
@Autowired
private MerchantInfoMapper merchantInfoMapper;
/**
* 查询商家信息
*
* @param shopId 商家信息主键
* @return 商家信息
*/
@Override
public MerchantInfo selectMerchantInfoByShopId(Long shopId)
{
return merchantInfoMapper.selectMerchantInfoByShopId(shopId);
}
/**
* 查询商家信息列表
*
* @param merchantInfo 商家信息
* @return 商家信息
*/
@Override
public List<MerchantInfo> selectMerchantInfoList(MerchantInfo merchantInfo)
{
return merchantInfoMapper.selectMerchantInfoList(merchantInfo);
}
/**
* 新增商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
@Override
public int insertMerchantInfo(MerchantInfo merchantInfo)
{
return merchantInfoMapper.insertMerchantInfo(merchantInfo);
}
/**
* 修改商家信息
*
* @param merchantInfo 商家信息
* @return 结果
*/
@Override
public int updateMerchantInfo(MerchantInfo merchantInfo)
{
return merchantInfoMapper.updateMerchantInfo(merchantInfo);
}
/**
* 批量删除商家信息
*
* @param shopIds 需要删除的商家信息主键
* @return 结果
*/
@Override
public int deleteMerchantInfoByShopIds(Long[] shopIds)
{
return merchantInfoMapper.deleteMerchantInfoByShopIds(shopIds);
}
/**
* 删除商家信息信息
*
* @param shopId 商家信息主键
* @return 结果
*/
@Override
public int deleteMerchantInfoByShopId(Long shopId)
{
return merchantInfoMapper.deleteMerchantInfoByShopId(shopId);
}
}

51
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetExperienceArticleServiceImpl.java

@ -4,10 +4,13 @@ import java.util.*;
import com.chenhai.common.utils.DateUtils; import com.chenhai.common.utils.DateUtils;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.chenhai.vet.mapper.VetExperienceArticleMapper; import com.chenhai.vet.mapper.VetExperienceArticleMapper;
import com.chenhai.vet.domain.VetExperienceArticle; import com.chenhai.vet.domain.VetExperienceArticle;
import com.chenhai.vet.service.IVetExperienceArticleService; import com.chenhai.vet.service.IVetExperienceArticleService;
import org.springframework.transaction.annotation.Transactional;
/** /**
* 兽医经验文章Service业务层处理 * 兽医经验文章Service业务层处理
@ -20,6 +23,8 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
{ {
@Autowired @Autowired
private VetExperienceArticleMapper vetExperienceArticleMapper; private VetExperienceArticleMapper vetExperienceArticleMapper;
@Autowired
private JdbcTemplate jdbcTemplate;
/** /**
* 查询兽医经验文章 * 查询兽医经验文章
@ -28,11 +33,9 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
* @return 兽医经验文章 * @return 兽医经验文章
*/ */
@Override @Override
public VetExperienceArticle selectVetExperienceArticleById(Long id)
{
public VetExperienceArticle selectVetExperienceArticleById(Long id) {
return vetExperienceArticleMapper.selectVetExperienceArticleById(id); return vetExperienceArticleMapper.selectVetExperienceArticleById(id);
} }
/** /**
* 查询兽医经验文章列表 * 查询兽医经验文章列表
* *
@ -112,23 +115,6 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
return vetExperienceArticleMapper.selectArticlesByCondition(params); return vetExperienceArticleMapper.selectArticlesByCondition(params);
} }
/**
* 获取热门文章按浏览数排序
*
* @param limit 限制数量
* @return 文章集合
*/
@Override
public List<VetExperienceArticle> selectHotArticles(Integer limit) {
PageHelper.clearPage();
Map<String, Object> params = new HashMap<>();
params.put("status", "1");
params.put("orderBy", "view_count");
params.put("orderType", "desc");
params.put("limit", limit != null ? limit : 10);
return vetExperienceArticleMapper.selectArticlesByCondition(params);
}
/** /**
* 根据用户ID获取文章 * 根据用户ID获取文章
* *
@ -169,16 +155,6 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
return vetExperienceArticleMapper.selectArticlesByCondition(params); return vetExperienceArticleMapper.selectArticlesByCondition(params);
} }
/**
* 增加浏览数
*
* @param id 文章ID
* @return 结果
*/
@Override
public int incrementViewCount(Long id) {
return vetExperienceArticleMapper.incrementViewCount(id);
}
/** /**
* 增加点赞数 * 增加点赞数
@ -197,7 +173,7 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
* @param id 文章ID * @param id 文章ID
* @return 结果 * @return 结果
*/ */
@Override
@Override
public int incrementCollectCount(Long id) { public int incrementCollectCount(Long id) {
return vetExperienceArticleMapper.incrementCollectCount(id); return vetExperienceArticleMapper.incrementCollectCount(id);
} }
@ -229,11 +205,14 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer
statistics.put("totalAuthors", authorIds.size()); statistics.put("totalAuthors", authorIds.size());
// 统计总浏览数 // 统计总浏览数
int totalViews = 0;
for (VetExperienceArticle article : allArticles) {
totalViews += article.getViewCount() != null ? article.getViewCount() : 0;
}
statistics.put("totalViews", totalViews);
String totalViewsSql = "SELECT COUNT(*) FROM article_view_log";
Integer totalViews = jdbcTemplate.queryForObject(totalViewsSql, Integer.class);
statistics.put("totalViews", totalViews != null ? totalViews : 0);
// 今日浏览量
String todaySql = "SELECT COUNT(*) FROM article_view_log WHERE DATE(view_time) = CURDATE()";
Integer todayViews = jdbcTemplate.queryForObject(todaySql, Integer.class);
statistics.put("todayViews", todayViews != null ? todayViews : 0);
// 统计总点赞数 // 统计总点赞数
int totalLikes = 0; int totalLikes = 0;

1
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java

@ -1,5 +1,6 @@
package com.chenhai.vet.service.impl; package com.chenhai.vet.service.impl;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.domain.AjaxResult;

186
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java

@ -1,4 +1,3 @@
// 更简单的版本完全使用 Date
package com.chenhai.vet.service.impl; package com.chenhai.vet.service.impl;
import com.chenhai.vet.domain.VetNotification; import com.chenhai.vet.domain.VetNotification;
@ -66,57 +65,64 @@ public class VetNotificationServiceImpl implements VetNotificationService {
return; return;
} }
log.info("证书提醒记录: 资质ID={}, 证书名称={}, 过期时间={}",
qualification.getQualificationId(), qualification.getCertName(),
formatDate(qualification.getExpireDate()));
// 计算剩余天数
long daysRemaining = calculateDayDifference(new Date(), qualification.getExpireDate());
// 根据剩余天数设置提醒内容和级别
String title;
String content;
int remindLevel;
if (daysRemaining <= 0) {
title = "证书已过期";
content = String.format("您的《%s》证书已于%s过期!请立即更新证书。",
qualification.getCertName(), formatDate(qualification.getExpireDate()));
remindLevel = 3;
} else if (daysRemaining <= 7) {
title = "证书即将过期(7天内)";
content = String.format("您的《%s》证书将在%d天后过期,请尽快更新!",
qualification.getCertName(), daysRemaining);
remindLevel = 3;
} else {
title = "证书即将过期(30天内)";
content = String.format("您的《%s》证书将在%d天后过期,请及时更新。",
qualification.getCertName(), daysRemaining);
remindLevel = 2;
log.info("证书提醒记录: 资质ID={}, 证书数量={}",
qualification.getQualificationId(),
qualification.getCertificateList() != null ? qualification.getCertificateList().size() : 0);
// 获取所有证书
List<VetQualification.CertificateInfo> certificates = qualification.getCertificateList();
if (certificates == null || certificates.isEmpty()) {
log.warn("资质ID={} 没有证书信息", qualification.getQualificationId());
return;
} }
// 创建通知
VetNotification notification = new VetNotification();
notification.setUserId(qualification.getUserId());
notification.setRelatedId(qualification.getQualificationId().toString());
notification.setType("CERT_EXPIRE_REMIND");
notification.setTitle(title);
notification.setContent(content);
notification.setRemindLevel(remindLevel);
notification.setIsRead(0);
notification.setCreateTime(new Date());
notification.setCreateBy("system");
// 对每个证书发送提醒
for (VetQualification.CertificateInfo certificate : certificates) {
if (certificate.getExpireDate() == null) {
continue;
}
// 保存通知
try {
int result = vetNotificationMapper.insertVetNotification(notification);
if (result > 0) {
log.info("成功发送证书提醒通知:用户ID={}, 资质ID={}, 标题={}",
qualification.getUserId(), qualification.getQualificationId(), title);
// 计算剩余天数
long daysRemaining = calculateDayDifference(new Date(), certificate.getExpireDate());
// 根据剩余天数设置提醒内容和级别
String title;
String content;
int remindLevel;
if (daysRemaining <= 0) {
// 只发送过期当天的提醒
if (daysRemaining == 0) {
title = "证书已过期";
content = String.format("您的《%s》证书(编号:%s)已于%s过期!请立即更新证书。",
certificate.getCertName(), certificate.getCertificateNo(),
formatDate(certificate.getExpireDate()));
remindLevel = 3;
// 创建通知
VetNotification notification = createCertificateNotification(qualification, certificate,
title, content, remindLevel);
saveNotification(notification);
}
} else if (daysRemaining <= 7) {
title = "证书即将过期(7天内)";
content = String.format("您的《%s》证书(编号:%s)将在%d天后过期,请尽快更新!",
certificate.getCertName(), certificate.getCertificateNo(), daysRemaining);
remindLevel = 3;
VetNotification notification = createCertificateNotification(qualification, certificate,
title, content, remindLevel);
saveNotification(notification);
} else if (daysRemaining <= 30) {
title = "证书即将过期(30天内)";
content = String.format("您的《%s》证书(编号:%s)将在%d天后过期,请及时更新。",
certificate.getCertName(), certificate.getCertificateNo(), daysRemaining);
remindLevel = 2;
VetNotification notification = createCertificateNotification(qualification, certificate,
title, content, remindLevel);
saveNotification(notification);
} }
} catch (Exception e) {
log.error("发送证书提醒通知失败:资质ID={}, 错误信息={}",
qualification.getQualificationId(), e.getMessage(), e);
} }
} }
@ -132,20 +138,84 @@ public class VetNotificationServiceImpl implements VetNotificationService {
return false; return false;
} }
// 添加 markAllAsRead 方法
/*@Override /*@Override
public void markAllAsRead(Long userId) {
VetNotification query = new VetNotification();
query.setUserId(userId);
List<VetNotification> notifications = vetNotificationMapper.selectVetNotificationList(query);
public void markAsRead(Long userId) {
try {
// 使用Mapper提供的方法批量标记为已读
int result = vetNotificationMapper.markAllNotificationsAsRead(userId);
log.info("用户ID={} 已将所有通知标记为已读,影响记录数={}", userId, result);
} catch (Exception e) {
log.error("标记所有通知为已读失败,用户ID={}", userId, e);
// 如果批量操作失败尝试逐条更新
fallbackMarkAllAsRead(userId);
}
}
*/
/**
* 回退方案逐条更新通知为已读
*/
private void fallbackMarkAllAsRead(Long userId) {
try {
VetNotification query = new VetNotification();
query.setUserId(userId);
List<VetNotification> notifications = vetNotificationMapper.selectVetNotificationList(query);
for (VetNotification notification : notifications) {
if (notification.getIsRead() == 0) {
notification.setIsRead(1);
notification.setReadTime(new Date());
vetNotificationMapper.updateVetNotification(notification);
int count = 0;
for (VetNotification notification : notifications) {
if (notification.getIsRead() == 0) {
notification.setIsRead(1);
notification.setReadTime(new Date());
vetNotificationMapper.updateVetNotification(notification);
count++;
}
} }
log.info("回退方案:用户ID={} 已成功标记{}个通知为已读", userId, count);
} catch (Exception e) {
log.error("回退方案标记通知为已读也失败,用户ID={}", userId, e);
} }
}*/
}
/**
* 创建证书通知对象
*/
private VetNotification createCertificateNotification(VetQualification qualification,
VetQualification.CertificateInfo certificate,
String title, String content, int remindLevel) {
VetNotification notification = new VetNotification();
notification.setUserId(qualification.getUserId());
// 关联ID包含资质ID和证书ID
String relatedId = String.format("%d:%d",
qualification.getQualificationId(),
certificate.getCertificateId() != null ? certificate.getCertificateId() : 0L);
notification.setRelatedId(relatedId);
notification.setType("CERT_EXPIRE_REMIND");
notification.setTitle(title);
notification.setContent(content);
notification.setRemindLevel(remindLevel);
notification.setIsRead(0);
notification.setCreateTime(new Date());
notification.setCreateBy("system");
return notification;
}
/**
* 保存通知
*/
private void saveNotification(VetNotification notification) {
try {
int result = vetNotificationMapper.insertVetNotification(notification);
if (result > 0) {
log.info("成功发送证书提醒通知:用户ID={}, 标题={}",
notification.getUserId(), notification.getTitle());
}
} catch (Exception e) {
log.error("发送证书提醒通知失败:错误信息={}", e.getMessage(), e);
}
}
/** /**
* 计算两个日期之间的天数差忽略时间部分 * 计算两个日期之间的天数差忽略时间部分

23
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java

@ -45,6 +45,15 @@ public class VetProductServiceImpl implements IVetProductService
@Override @Override
public List<VetProduct> selectVetProductList(VetProduct vetProduct) public List<VetProduct> selectVetProductList(VetProduct vetProduct)
{ {
// 获取当前登录用户ID
try {
Long userId = SecurityUtils.getUserId();
// 设置查询条件只查询当前用户的产品
vetProduct.setUserId(userId);
} catch (Exception e) {
// 如果获取不到用户ID设置一个不存在的ID确保查询不到数据
vetProduct.setUserId(-1L);
}
return vetProductMapper.selectVetProductList(vetProduct); return vetProductMapper.selectVetProductList(vetProduct);
} }
@ -249,4 +258,18 @@ public class VetProductServiceImpl implements IVetProductService
return vetProductMapper.insertVetProduct(vetProduct); return vetProductMapper.insertVetProduct(vetProduct);
} }
/**
* 管理员查询所有兽医产品信息列表用于审核
*/
@Override
public List<VetProduct> selectAllVetProductList(VetProduct vetProduct)
{
// 管理员查询时不清除用户ID但可以查询所有数据
// 这里不设置用户ID让SQL查询所有产品
if (vetProduct != null) {
vetProduct.setUserId(null); // 清除用户ID条件
}
return vetProductMapper.selectVetProductList(vetProduct);
}
} }

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

@ -70,12 +70,23 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
*/ */
@Override @Override
public int insertVetQualification(VetQualification vetQualification) { public int insertVetQualification(VetQualification vetQualification) {
// 准备保存前的处理
prepareQualificationForSave(vetQualification); prepareQualificationForSave(vetQualification);
return vetQualificationMapper.insertVetQualification(vetQualification);
// 执行插入
int result = vetQualificationMapper.insertVetQualification(vetQualification);
// 成功插入后为用户分配兽医未审核角色
if (result > 0 && vetQualification.getUserId() != null) {
assignVetUnapprovedRole(vetQualification.getUserId());
}
return result;
} }
/** /**
* 修改兽医资质
* 修改兽医资质 - 处理审核状态变更时的角色切换
*/ */
@Override @Override
public int updateVetQualification(VetQualification vetQualification) { public int updateVetQualification(VetQualification vetQualification) {
@ -83,11 +94,18 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
throw new ServiceException("资质ID不能为空"); throw new ServiceException("资质ID不能为空");
} }
VetQualification existing = vetQualificationMapper.selectVetQualificationByQualificationId(vetQualification.getQualificationId());
// 获取更新前的资质信息
VetQualification existing = vetQualificationMapper.selectVetQualificationByQualificationId(
vetQualification.getQualificationId()
);
if (existing == null) { if (existing == null) {
throw new ServiceException("资质信息不存在"); throw new ServiceException("资质信息不存在");
} }
String oldStatus = existing.getAuditStatus();
String newStatus = vetQualification.getAuditStatus();
Long userId = existing.getUserId();
// 更新基本信息 // 更新基本信息
updateBasicQualificationInfo(existing, vetQualification); updateBasicQualificationInfo(existing, vetQualification);
@ -101,9 +119,128 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
// 更新证书状态 // 更新证书状态
updateCertificateStatus(existing); updateCertificateStatus(existing);
return vetQualificationMapper.updateVetQualification(existing);
int result = vetQualificationMapper.updateVetQualification(existing);
// 处理审核通过时的角色变更
if (result > 0 && userId != null && newStatus != null) {
handleRoleChangeOnAudit(userId, oldStatus, newStatus);
}
return result;
}
/**
* 为用户分配兽医未审核角色
*/
private void assignVetUnapprovedRole(Long userId) {
try {
// 检查是否已有兽医未审核角色
String checkSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6";
Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId);
// 如果没有则分配兽医未审核角色
if (count == null || count == 0) {
String insertSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)";
jdbcTemplate.update(insertSql, userId);
}
} catch (Exception e) {
// 忽略异常不影响主要业务
}
}
/**
* 处理审核状态变更时的角色切换
*/
private void handleRoleChangeOnAudit(Long userId, String oldStatus, String newStatus) {
try {
// 1. 审核通过状态变为1
if ("1".equals(newStatus)) {
changeRoleToVet(userId);
}
// 2. 审核不通过或待审核状态变为2或0且之前是通过状态
else if (("0".equals(newStatus) || "2".equals(newStatus)) && "1".equals(oldStatus)) {
changeRoleToVetUnapproved(userId);
}
} catch (Exception e) {
// 角色切换失败不影响主要业务
}
}
/**
* 切换为兽医角色审核通过
*/
private void changeRoleToVet(Long userId) {
try {
// 1. 先删除兽医未审核角色
String deleteUnapprovedSql = "DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 6";
jdbcTemplate.update(deleteUnapprovedSql, userId);
// 2. 检查是否已有兽医角色
String checkVetSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 4";
Integer vetCount = jdbcTemplate.queryForObject(checkVetSql, Integer.class, userId);
// 3. 如果没有兽医角色则添加
if (vetCount == null || vetCount == 0) {
String addVetSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 4)";
jdbcTemplate.update(addVetSql, userId);
}
} catch (Exception e) {
// 忽略异常
}
} }
/* *//**
* 发送重新登录通知
*//*
private void sendReloginNotification(Long userId) {
try {
log.info("用户 {} 角色已变更,建议重新登录以刷新权限", userId);
String message = "您的兽医资质已审核通过,角色已更新为兽医。请重新登录系统以使用新角色的功能。";
log.info("通知消息: {}", message);
} catch (Exception e) {
log.warn("发送通知失败: {}", e.getMessage());
}
}*/
/**
* 清除用户权限缓存可选
*/
private void clearUserAuthorizationCache(Long userId) {
try {
// 根据你的缓存实现来清理
// 例如如果使用Redis清理对应的缓存key
} catch (Exception e) {
// 忽略异常
}
}
/**
* 切换为兽医未审核角色审核不通过或待审核
*/
private void changeRoleToVetUnapproved(Long userId) {
try {
// 1. 先删除兽医角色
String deleteVetSql = "DELETE FROM sys_user_role WHERE user_id = ? AND role_id = 4";
jdbcTemplate.update(deleteVetSql, userId);
// 2. 检查是否已有兽医未审核角色
String checkSql = "SELECT COUNT(*) FROM sys_user_role WHERE user_id = ? AND role_id = 6";
Integer unapprovedCount = jdbcTemplate.queryForObject(checkSql, Integer.class, userId);
// 3. 如果没有兽医未审核角色则添加
if (unapprovedCount == null || unapprovedCount == 0) {
String addSql = "INSERT INTO sys_user_role (user_id, role_id) VALUES (?, 6)";
jdbcTemplate.update(addSql, userId);
}
} catch (Exception e) {
// 忽略异常
}
}
/** /**
* 批量删除兽医资质 * 批量删除兽医资质
*/ */
@ -1019,4 +1156,9 @@ public class VetQualificationServiceImpl implements IVetQualificationService {
long diff = expireDate.getTime() - new Date().getTime(); long diff = expireDate.getTime() - new Date().getTime();
return (int) (diff / (1000 * 60 * 60 * 24)); return (int) (diff / (1000 * 60 * 60 * 24));
} }
@Override
public VetQualification selectVetQualificationById(Long qualificationId) {
return vetQualificationMapper.selectVetQualificationById(qualificationId);
}
} }

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

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chenhai.vet.mapper.MerchantInfoMapper">
<resultMap type="MerchantInfo" id="MerchantInfoResult">
<result property="shopId" column="shop_id" />
<result property="shopName" column="shop_name" />
<result property="shopAddress" column="shop_address" />
<result property="phone" column="phone" />
<result property="userId" column="user_id" />
<result property="createdAt" column="created_at" />
<result property="updatedAt" column="updated_at" />
<result property="isActive" column="is_active" />
</resultMap>
<sql id="selectMerchantInfoVo">
select shop_id, shop_name, shop_address, phone, user_id, created_at, updated_at, is_active from merchant_info
</sql>
<select id="selectMerchantInfoList" parameterType="MerchantInfo" resultMap="MerchantInfoResult">
<include refid="selectMerchantInfoVo"/>
<where>
<if test="shopName != null and shopName != ''"> and shop_name like concat('%', #{shopName}, '%')</if>
<if test="shopAddress != null and shopAddress != ''"> and shop_address = #{shopAddress}</if>
<if test="phone != null and phone != ''"> and phone = #{phone}</if>
<if test="userId != null "> and user_id = #{userId}</if>
<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>
</where>
</select>
<select id="selectMerchantInfoByShopId" parameterType="Long" resultMap="MerchantInfoResult">
<include refid="selectMerchantInfoVo"/>
where shop_id = #{shopId}
</select>
<insert id="insertMerchantInfo" parameterType="MerchantInfo" useGeneratedKeys="true" keyProperty="shopId">
insert into merchant_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="shopName != null and shopName != ''">shop_name,</if>
<if test="shopAddress != null and shopAddress != ''">shop_address,</if>
<if test="phone != null">phone,</if>
<if test="userId != null">user_id,</if>
<if test="createdAt != null">created_at,</if>
<if test="updatedAt != null">updated_at,</if>
<if test="isActive != null">is_active,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="shopName != null and shopName != ''">#{shopName},</if>
<if test="shopAddress != null and shopAddress != ''">#{shopAddress},</if>
<if test="phone != null">#{phone},</if>
<if test="userId != null">#{userId},</if>
<if test="createdAt != null">#{createdAt},</if>
<if test="updatedAt != null">#{updatedAt},</if>
<if test="isActive != null">#{isActive},</if>
</trim>
</insert>
<update id="updateMerchantInfo" parameterType="MerchantInfo">
update merchant_info
<trim prefix="SET" suffixOverrides=",">
<if test="shopName != null and shopName != ''">shop_name = #{shopName},</if>
<if test="shopAddress != null and shopAddress != ''">shop_address = #{shopAddress},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="userId != null">user_id = #{userId},</if>
<if test="createdAt != null">created_at = #{createdAt},</if>
<if test="updatedAt != null">updated_at = #{updatedAt},</if>
<if test="isActive != null">is_active = #{isActive},</if>
</trim>
where shop_id = #{shopId}
</update>
<delete id="deleteMerchantInfoByShopId" parameterType="Long">
delete from merchant_info where shop_id = #{shopId}
</delete>
<delete id="deleteMerchantInfoByShopIds" parameterType="String">
delete from merchant_info where shop_id in
<foreach item="shopId" collection="array" open="(" separator="," close=")">
#{shopId}
</foreach>
</delete>
</mapper>

137
chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml

@ -29,95 +29,137 @@
<result property="publishTime" column="publish_time"/> <result property="publishTime" column="publish_time"/>
<result property="createTime" column="create_time"/> <result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/> <result property="updateTime" column="update_time"/>
<result property="userRole" column="user_role"/>
<result property="userType" column="user_type"/>
</resultMap> </resultMap>
<!-- 修改基础查询语句,始终从用户表获取用户信息 -->
<sql id="selectVetExperienceArticleVo"> <sql id="selectVetExperienceArticleVo">
select id, title, content, summary, cover_image, images, user_id, vet_name, vet_avatar, vet_title,
category_id, category_name, tags, view_count, like_count, collect_count,
is_top, is_featured, status, is_sensitive, sensitive_words, publish_time, create_time, update_time
from vet_experience_article
select
a.id,
a.title,
a.content, <!-- 富文本内容 -->
a.summary,
a.cover_image,
a.images,
a.user_id,
<!-- 始终从用户表获取用户信息 -->
COALESCE(u.nick_name, u.user_name) as vet_name, <!-- 用户姓名 -->
u.avatar as vet_avatar, <!-- 用户头像 -->
a.vet_title,
a.category_id,
a.category_name,
a.tags,
a.view_count,
a.like_count,
a.collect_count,
a.is_top,
a.is_featured,
a.status,
a.is_sensitive,
a.sensitive_words,
a.publish_time,
a.create_time,
a.update_time,
a.user_role,
a.user_type
from vet_experience_article a
left join sys_user u on a.user_id = u.user_id
</sql> </sql>
<!-- 查询兽医经验文章 --> <!-- 查询兽医经验文章 -->
<select id="selectVetExperienceArticleById" parameterType="Long" resultMap="VetExperienceArticleResult"> <select id="selectVetExperienceArticleById" parameterType="Long" resultMap="VetExperienceArticleResult">
<include refid="selectVetExperienceArticleVo"/> <include refid="selectVetExperienceArticleVo"/>
where id = #{id}
where a.id = #{id} <!-- 添加表别名 a. -->
</select> </select>
<!-- 查询兽医经验文章列表 --> <!-- 查询兽医经验文章列表 -->
<!-- 查询兽医经验文章列表(已包含关联用户表) -->
<select id="selectVetExperienceArticleList" parameterType="VetExperienceArticle" resultMap="VetExperienceArticleResult"> <select id="selectVetExperienceArticleList" parameterType="VetExperienceArticle" resultMap="VetExperienceArticleResult">
<include refid="selectVetExperienceArticleVo"/> <include refid="selectVetExperienceArticleVo"/>
<where> <where>
<if test="title != null and title != ''"> and title like concat('%', #{title}, '%')</if>
<if test="userId != null"> and user_id = #{userId}</if>
<if test="vetName != null and vetName != ''"> and vet_name like concat('%', #{vetName}, '%')</if>
<if test="categoryId != null"> and category_id = #{categoryId}</if>
<if test="categoryName != null and categoryName != ''"> and category_name like concat('%', #{categoryName}, '%')</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isTop != null and isTop != ''"> and is_top = #{isTop}</if>
<if test="isFeatured != null and isFeatured != ''"> and is_featured = #{isFeatured}</if>
<if test="isSensitive != null and isSensitive != ''"> and is_sensitive = #{isSensitive}</if>
<if test="title != null and title != ''"> and a.title like concat('%', #{title}, '%')</if>
<if test="userId != null"> and a.user_id = #{userId}</if>
<if test="vetName != null and vetName != ''"> and (a.vet_name like concat('%', #{vetName}, '%') or u.nick_name like concat('%', #{vetName}, '%'))</if>
<if test="categoryId != null"> and a.category_id = #{categoryId}</if>
<if test="categoryName != null and categoryName != ''"> and a.category_name like concat('%', #{categoryName}, '%')</if>
<if test="status != null and status != ''"> and a.status = #{status}</if>
<if test="isTop != null and isTop != ''"> and a.is_top = #{isTop}</if>
<if test="isFeatured != null and isFeatured != ''"> and a.is_featured = #{isFeatured}</if>
<if test="isSensitive != null and isSensitive != ''"> and a.is_sensitive = #{isSensitive}</if>
<if test="tags != null and tags != ''"> <if test="tags != null and tags != ''">
and ( and (
tags = #{tags}
or tags like concat(#{tags}, ',%')
or tags like concat('%,', #{tags}, ',%')
or tags like concat('%,', #{tags})
a.tags = #{tags}
or a.tags like concat(#{tags}, ',%')
or a.tags like concat('%,', #{tags}, ',%')
or a.tags like concat('%,', #{tags})
)
</if>
<if test="searchKey != null and searchKey != ''">
<bind name="searchKeyLike" value="'%' + searchKey + '%'" />
and (
a.title like #{searchKeyLike}
or a.content like #{searchKeyLike}
or a.summary like #{searchKeyLike}
or a.tags like #{searchKeyLike}
or a.category_name like #{searchKeyLike}
or a.vet_name like #{searchKeyLike}
or u.nick_name like #{searchKeyLike}
) )
</if> </if>
<if test="viewCount != null and viewCount != ''"> and a.view_count = #{viewCount}</if>
</where> </where>
order by publish_time desc
order by a.publish_time desc
</select> </select>
<!-- 根据条件查询文章列表(论坛专用) --> <!-- 根据条件查询文章列表(论坛专用) -->
<select id="selectArticlesByCondition" parameterType="map" resultMap="VetExperienceArticleResult"> <select id="selectArticlesByCondition" parameterType="map" resultMap="VetExperienceArticleResult">
<include refid="selectVetExperienceArticleVo"/> <include refid="selectVetExperienceArticleVo"/>
<where> <where>
status = #{status}
a.status = #{status}
<if test="keyword != null and keyword != ''"> <if test="keyword != null and keyword != ''">
and ( and (
title like concat('%', #{keyword}, '%')
or content like concat('%', #{keyword}, '%')
or summary like concat('%', #{keyword}, '%')
or tags like concat('%', #{keyword}, '%')
a.title like concat('%', #{keyword}, '%')
or a.content like concat('%', #{keyword}, '%')
or a.summary like concat('%', #{keyword}, '%')
or a.tags like concat('%', #{keyword}, '%')
) )
</if> </if>
<if test="userId != null"> and user_id = #{userId}</if>
<if test="categoryId != null"> and category_id = #{categoryId}</if>
<if test="excludeId != null"> and id != #{excludeId}</if>
<if test="userId != null"> and a.user_id = #{userId}</if>
<if test="categoryId != null"> and a.category_id = #{categoryId}</if>
<if test="excludeId != null"> and a.id != #{excludeId}</if>
</where> </where>
<!-- 先ORDER BY,后LIMIT -->
order by
<!-- ORDER BY必须在WHERE子句之后,LIMIT之前 -->
<choose> <choose>
<when test="orderBy != null and orderType != null"> <when test="orderBy != null and orderType != null">
${orderBy} ${orderType}
order by a.${orderBy} ${orderType}
</when> </when>
<otherwise> <otherwise>
publish_time desc
order by a.publish_time desc
</otherwise> </otherwise>
</choose> </choose>
<!-- <if test="limit != null and limit > 0">
limit #{limit}
</if>-->
<!-- LIMIT必须在ORDER BY之后 -->
<!-- <if test="limit != null and limit > 0">-->
<!-- limit #{limit}-->
<!-- </if>-->
</select> </select>
<!-- 搜索文章 --> <!-- 搜索文章 -->
<select id="searchArticles" resultMap="VetExperienceArticleResult"> <select id="searchArticles" resultMap="VetExperienceArticleResult">
<include refid="selectVetExperienceArticleVo"/> <include refid="selectVetExperienceArticleVo"/>
where status = #{status}
and (title like concat('%', #{keyword}, '%')
or content like concat('%', #{keyword}, '%')
or summary like concat('%', #{keyword}, '%'))
order by publish_time desc
where a.status = #{status}
and (a.title like concat('%', #{keyword}, '%')
or a.content like concat('%', #{keyword}, '%')
or a.summary like concat('%', #{keyword}, '%'))
order by a.publish_time desc
</select> </select>
<!-- 增加浏览数 -->
<!-- &lt;!&ndash; 增加浏览数 &ndash;&gt;
<update id="incrementViewCount" parameterType="Long"> <update id="incrementViewCount" parameterType="Long">
update vet_experience_article update vet_experience_article
set view_count = ifnull(view_count, 0) + 1, set view_count = ifnull(view_count, 0) + 1,
update_time = now() update_time = now()
where id = #{id} where id = #{id}
</update>
</update>-->
<!-- 增加点赞数 --> <!-- 增加点赞数 -->
<update id="incrementLikeCount" parameterType="Long"> <update id="incrementLikeCount" parameterType="Long">
@ -160,7 +202,9 @@
<if test="isSensitive != null">is_sensitive,</if> <if test="isSensitive != null">is_sensitive,</if>
<if test="sensitiveWords != null">sensitive_words,</if> <if test="sensitiveWords != null">sensitive_words,</if>
<if test="publishTime != null">publish_time,</if> <if test="publishTime != null">publish_time,</if>
create_time,
<if test="userRole != null and userRole != ''">user_role,</if>
<if test="userType != null and userType != ''">user_type,</if>
create_time, <!-- 固定字段放在最后 -->
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
@ -185,7 +229,9 @@
<if test="isSensitive != null">#{isSensitive},</if> <if test="isSensitive != null">#{isSensitive},</if>
<if test="sensitiveWords != null">#{sensitiveWords},</if> <if test="sensitiveWords != null">#{sensitiveWords},</if>
<if test="publishTime != null">#{publishTime},</if> <if test="publishTime != null">#{publishTime},</if>
now(),
<if test="userRole != null and userRole != ''">#{userRole},</if>
<if test="userType != null and userType != ''">#{userType},</if>
now(), <!-- 对应create_time -->
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
</trim> </trim>
</insert> </insert>
@ -215,11 +261,12 @@
<if test="isSensitive != null">is_sensitive = #{isSensitive},</if> <if test="isSensitive != null">is_sensitive = #{isSensitive},</if>
<if test="sensitiveWords != null">sensitive_words = #{sensitiveWords},</if> <if test="sensitiveWords != null">sensitive_words = #{sensitiveWords},</if>
<if test="publishTime != null">publish_time = #{publishTime},</if> <if test="publishTime != null">publish_time = #{publishTime},</if>
<if test="userRole != null and userRole != ''">user_role = #{userRole},</if>
<if test="userType != null and userType != ''">user_type = #{userType},</if>
update_time = now(), update_time = now(),
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>
<!-- 删除兽医经验文章 --> <!-- 删除兽医经验文章 -->
<delete id="deleteVetExperienceArticleById" parameterType="Long"> <delete id="deleteVetExperienceArticleById" parameterType="Long">
delete from vet_experience_article where id = #{id} delete from vet_experience_article where id = #{id}

5
chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml

@ -246,4 +246,9 @@
</if> </if>
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectVetQualificationById" parameterType="Long" resultMap="VetQualificationResult">
<include refid="selectVetQualificationVo"/>
where qualification_id = #{qualificationId}
</select>
</mapper> </mapper>

44
chenhai-ui/src/api/vet/merchant.js

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询商家信息列表
export function listMerchant(query) {
return request({
url: '/vet/merchant/list',
method: 'get',
params: query
})
}
// 查询商家信息详细
export function getMerchant(shopId) {
return request({
url: '/vet/merchant/' + shopId,
method: 'get'
})
}
// 新增商家信息
export function addMerchant(data) {
return request({
url: '/vet/merchant',
method: 'post',
data: data
})
}
// 修改商家信息
export function updateMerchant(data) {
return request({
url: '/vet/merchant',
method: 'put',
data: data
})
}
// 删除商家信息
export function delMerchant(shopId) {
return request({
url: '/vet/merchant/' + shopId,
method: 'delete'
})
}

362
chenhai-ui/src/views/vet/merchant/index.vue

@ -0,0 +1,362 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="店铺名称" prop="shopName">
<el-input
v-model="queryParams.shopName"
placeholder="请输入店铺名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="店铺地址" prop="shopAddress">
<el-input
v-model="queryParams.shopAddress"
placeholder="请输入店铺地址"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="联系电话" prop="phone">
<el-input
v-model="queryParams.phone"
placeholder="请输入联系电话"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="关联用户ID" prop="userId">
<el-input
v-model="queryParams.userId"
placeholder="请输入关联用户ID"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker clearable
v-model="queryParams.createdAt"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="更新时间" prop="updatedAt">
<el-date-picker clearable
v-model="queryParams.updatedAt"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择更新时间">
</el-date-picker>
</el-form-item>
<el-form-item label="是否启用" prop="isActive">
<el-input
v-model="queryParams.isActive"
placeholder="请输入是否启用"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['vet:merchant:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['vet:merchant:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['vet:merchant:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['vet:merchant:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="merchantList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="店铺ID,主键" align="center" prop="shopId" />
<el-table-column label="店铺名称" align="center" prop="shopName" />
<el-table-column label="店铺地址" align="center" prop="shopAddress" />
<el-table-column label="联系电话" align="center" prop="phone" />
<el-table-column label="关联用户ID" align="center" prop="userId" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="updatedAt" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updatedAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="是否启用" align="center" prop="isActive" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['vet:merchant:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['vet:merchant:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改商家信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="店铺名称" prop="shopName">
<el-input v-model="form.shopName" placeholder="请输入店铺名称" />
</el-form-item>
<el-form-item label="店铺地址" prop="shopAddress">
<el-input v-model="form.shopAddress" placeholder="请输入店铺地址" />
</el-form-item>
<el-form-item label="联系电话" prop="phone">
<el-input v-model="form.phone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="关联用户ID" prop="userId">
<el-input v-model="form.userId" placeholder="请输入关联用户ID" />
</el-form-item>
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker clearable
v-model="form.createdAt"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="更新时间" prop="updatedAt">
<el-date-picker clearable
v-model="form.updatedAt"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择更新时间">
</el-date-picker>
</el-form-item>
<el-form-item label="是否启用" prop="isActive">
<el-input v-model="form.isActive" placeholder="请输入是否启用" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listMerchant, getMerchant, delMerchant, addMerchant, updateMerchant } from "@/api/vet/merchant"
export default {
name: "Merchant",
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
merchantList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
shopName: null,
shopAddress: null,
phone: null,
userId: null,
createdAt: null,
updatedAt: null,
isActive: null
},
//
form: {},
//
rules: {
shopName: [
{ required: true, message: "店铺名称不能为空", trigger: "blur" }
],
shopAddress: [
{ required: true, message: "店铺地址不能为空", trigger: "blur" }
],
userId: [
{ required: true, message: "关联用户ID不能为空", trigger: "blur" }
],
createdAt: [
{ required: true, message: "创建时间不能为空", trigger: "blur" }
],
updatedAt: [
{ required: true, message: "更新时间不能为空", trigger: "blur" }
],
}
}
},
created() {
this.getList()
},
methods: {
/** 查询商家信息列表 */
getList() {
this.loading = true
listMerchant(this.queryParams).then(response => {
this.merchantList = response.rows
this.total = response.total
this.loading = false
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
shopId: null,
shopName: null,
shopAddress: null,
phone: null,
userId: null,
createdAt: null,
updatedAt: null,
isActive: null
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.shopId)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加商家信息"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const shopId = row.shopId || this.ids
getMerchant(shopId).then(response => {
this.form = response.data
this.open = true
this.title = "修改商家信息"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.shopId != null) {
updateMerchant(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addMerchant(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
})
}
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const shopIds = row.shopId || this.ids
this.$modal.confirm('是否确认删除商家信息编号为"' + shopIds + '"的数据项?').then(function() {
return delMerchant(shopIds)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导出按钮操作 */
handleExport() {
this.download('vet/merchant/export', {
...this.queryParams
}, `merchant_${new Date().getTime()}.xlsx`)
}
}
}
</script>
Loading…
Cancel
Save