From 0c0f0c239f950f9efa2c173336ec1d0f11e4e849 Mon Sep 17 00:00:00 2001 From: ChaiNingQi <2032830459@qq.com> Date: Thu, 5 Feb 2026 10:53:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=AE=B6=E4=BF=A1=E6=81=AF=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=92=8C=E7=BB=8F=E9=AA=8C=E5=88=86=E4=BA=AB=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vet/MerchantInfoController.java | 104 +++++ .../vet/VetExperienceArticleController.java | 307 ++++++++++++- .../vet/VetKnowledgeController.java | 6 +- .../vet/VetNotificationController.java | 3 + .../vet/VetPersonalInfoController.java | 6 + .../controller/vet/VetProductController.java | 31 +- .../vet/VetQualificationController.java | 77 +++- .../vet/VetTrainingVideoController.java | 1 + .../chenhai/vet/CertificateRemindTask.java | 406 ++++++++++++------ .../com/chenhai/vet/domain/MerchantInfo.java | 146 +++++++ .../vet/domain/VetExperienceArticle.java | 236 ++++++---- .../vet/mapper/MerchantInfoMapper.java | 61 +++ .../mapper/VetExperienceArticleMapper.java | 2 +- .../vet/mapper/VetQualificationMapper.java | 2 + .../vet/service/IMerchantInfoService.java | 61 +++ .../service/IVetExperienceArticleService.java | 10 +- .../vet/service/IVetProductService.java | 8 + .../vet/service/IVetQualificationService.java | 2 + .../service/impl/MerchantInfoServiceImpl.java | 93 ++++ .../impl/VetExperienceArticleServiceImpl.java | 51 +-- .../service/impl/VetKnowledgeServiceImpl.java | 1 + .../impl/VetNotificationServiceImpl.java | 186 +++++--- .../service/impl/VetProductServiceImpl.java | 23 + .../impl/VetQualificationServiceImpl.java | 150 ++++++- .../mapper/vet/MerchantInfoMapper.xml | 86 ++++ .../mapper/vet/VetExperienceArticleMapper.xml | 137 ++++-- .../mapper/vet/VetQualificationMapper.xml | 5 + chenhai-ui/src/api/vet/merchant.js | 44 ++ chenhai-ui/src/views/vet/merchant/index.vue | 362 ++++++++++++++++ 29 files changed, 2233 insertions(+), 374 deletions(-) create mode 100644 chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java create mode 100644 chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java create mode 100644 chenhai-system/src/main/java/com/chenhai/vet/mapper/MerchantInfoMapper.java create mode 100644 chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java create mode 100644 chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java create mode 100644 chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml create mode 100644 chenhai-ui/src/api/vet/merchant.js create mode 100644 chenhai-ui/src/views/vet/merchant/index.vue diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/MerchantInfoController.java new file mode 100644 index 0000000..fa9284c --- /dev/null +++ b/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 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 list = merchantInfoService.selectMerchantInfoList(merchantInfo); + ExcelUtil util = new ExcelUtil(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)); + } +} diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java index cffcff9..2d07c16 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetExperienceArticleController.java @@ -8,15 +8,17 @@ import com.chenhai.common.enums.BusinessType; import com.chenhai.common.utils.SecurityUtils; import com.chenhai.vet.domain.VetExperienceArticle; import com.chenhai.vet.service.IVetExperienceArticleService; +import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** - * 兽医经验文章论坛Controller(列表样式) + * 兽医经验文章论坛Controller */ @RestController @RequestMapping("/vet/article") @@ -31,9 +33,41 @@ public class VetExperienceArticleController extends BaseController { // 简单收藏管理 private static final Map> 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") 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") public TableDataInfo myList(VetExperienceArticle vetExperienceArticle) { 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}") public AjaxResult getInfo(@PathVariable("id") Long id) { - // 增加浏览数 - vetExperienceArticleService.incrementViewCount(id); - + // 1. 先获取文章信息 VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id); if (article == null) { return error("文章不存在"); } - // 获取相关文章(同一分类的其他文章) - List relatedArticles = vetExperienceArticleService.selectRelatedArticles( - id, article.getCategoryId(), 4); + // 2. 增加观看次数(在文章表中直接更新) + if (article.getViewCount() == null) { + article.setViewCount(0L); + } + article.setViewCount(article.getViewCount() + 1); - // 获取作者其他文章 - List authorArticles = vetExperienceArticleService.selectArticlesByUserId( - article.getUserId(), 5); + // 3. 更新文章浏览量 + vetExperienceArticleService.updateVetExperienceArticle(article); - Map 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 getArticleViewStats(Long articleId) { + Map 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 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 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 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) @PostMapping public AjaxResult add(@RequestBody VetExperienceArticle article) { @@ -123,11 +310,37 @@ public class VetExperienceArticleController extends BaseController { // 设置作者信息 article.setUserId(currentUserId); 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) { 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())) { @@ -135,12 +348,25 @@ public class VetExperienceArticleController extends BaseController { } int result = vetExperienceArticleService.insertVetExperienceArticle(article); - return toAjax(result).put("articleId", article.getId()); + VetExperienceArticle savedArticle = vetExperienceArticleService.selectVetExperienceArticleById(article.getId()); + + Map 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) @PutMapping 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) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { @@ -170,13 +397,13 @@ public class VetExperienceArticleController extends BaseController { return error("没有权限删除他人文章"); } } - return toAjax(vetExperienceArticleService.deleteVetExperienceArticleByIds(ids)); } /** * 点赞文章 */ + @PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('vet')") @Log(title = "点赞文章", businessType = BusinessType.UPDATE) @PostMapping("/{id}/like") 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") public AjaxResult collectArticle(@PathVariable Long id) { Long currentUserId = SecurityUtils.getUserId(); if (currentUserId == null) { return error("请先登录"); } - // 检查文章是否存在 VetExperienceArticle article = vetExperienceArticleService.selectVetExperienceArticleById(id); 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") public TableDataInfo getMyCollections() { 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") public AjaxResult getStatistics() { 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") public AjaxResult getLatestArticles(@RequestParam(defaultValue = "10") Integer limit) { List 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") 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") public AjaxResult getTagOptions() { List> options = new ArrayList<>(); @@ -316,4 +554,27 @@ public class VetExperienceArticleController extends BaseController { 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 drafts = vetExperienceArticleService.selectVetExperienceArticleList(query); + return getDataTable(drafts); + } + } \ No newline at end of file diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java index f94b921..54f2a4a 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java @@ -1,6 +1,8 @@ package com.chenhai.web.controller.vet; import java.util.List; + +import com.chenhai.common.utils.SecurityUtils; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; 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") 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) @PutMapping("/submit/{id}") public AjaxResult submitForAudit(@PathVariable Long id) { diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java index 1165216..9eb5821 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetNotificationController.java @@ -73,6 +73,7 @@ public class VetNotificationController extends BaseController /** * 获取通知统计信息(用于首页卡片) */ + @Log(title = "兽医通知", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:notification:query')") @GetMapping("/stats/card") public AjaxResult getNotificationCardStats() { @@ -131,6 +132,7 @@ public class VetNotificationController extends BaseController /** * 查询兽医通知列表 */ + @Log(title = "兽医通知", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:notification:list')") @GetMapping("/list") 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')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java index 3594165..441dd1a 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetPersonalInfoController.java @@ -66,6 +66,7 @@ public class VetPersonalInfoController extends BaseController /** * 查询兽医个人信息列表 */ + @Log(title = "兽医个人信息", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:info:list')") @GetMapping("/list") 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')") @GetMapping("/full/{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')") @GetMapping("/full/current") public AjaxResult getCurrentFullInfo() @@ -171,6 +174,7 @@ public class VetPersonalInfoController extends BaseController /** * 获取兽医个人信息详细信息(带用户信息) */ + @Log(title = "兽医个人信息", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:info:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) @@ -191,6 +195,7 @@ public class VetPersonalInfoController extends BaseController /** * 根据用户ID获取兽医信息 */ + @Log(title = "兽医个人信息", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:info:query')") @GetMapping(value = "/byUserId/{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')") @GetMapping("/current") public AjaxResult getCurrentInfo() diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java index c5a1fdd..a10e72b 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetProductController.java @@ -39,11 +39,24 @@ public class VetProductController extends BaseController /** * 查询兽医产品信息列表 */ + @Log(title = "兽医产品信息", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:product:list')") @GetMapping("/list") public TableDataInfo list(VetProduct vetProduct) { startPage(); + + /* // 如果是普通用户,只查看自己的产品 + if (!SecurityUtils.isAdmin()) { + try { + Long userId = SecurityUtils.getUserId(); + vetProduct.setUserId(userId); + } catch (Exception e) { + // 如果获取不到用户ID,设置一个不存在的ID + vetProduct.setUserId(-1L); + } + }*/ + List list = vetProductService.selectVetProductList(vetProduct); return getDataTable(list); } @@ -64,6 +77,7 @@ public class VetProductController extends BaseController /** * 获取兽医产品信息详细信息 */ + @Log(title = "兽医产品信息", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:product:query')") @GetMapping(value = "/{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) @PostMapping("/cancelAudit/{id}") public AjaxResult cancelAudit(@PathVariable("id") Long 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 list = vetProductService.selectAllVetProductList(vetProduct); + return getDataTable(list); + } } diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java index 9c63c5c..b8c2442 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java @@ -5,6 +5,7 @@ import com.chenhai.common.core.controller.BaseController; import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.page.TableDataInfo; import com.chenhai.common.enums.BusinessType; +import com.chenhai.common.exception.ServiceException; import com.chenhai.common.utils.SecurityUtils; import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.service.IVetQualificationService; @@ -39,6 +40,7 @@ public class VetQualificationController extends BaseController /** * 获取资质类型选项(下拉框用) */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/type/options") public AjaxResult getQualificationTypeOptions() { 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") public AjaxResult getScopeOptions() { 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')") @GetMapping("/list") 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')") @GetMapping("/listExpiring") 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')") @GetMapping("/certificate/list") public TableDataInfo getCertificateList(VetQualification vetQualification) @@ -156,10 +162,74 @@ public class VetQualificationController extends BaseController 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 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> certificateList = new ArrayList<>(); + List certList = qualification.getCertificateList(); + if (certList != null && !certList.isEmpty()) { + for (VetQualification.CertificateInfo cert : certList) { + Map certMap = new HashMap<>(); + certMap.put("qualificationId", qualification.getQualificationId()); + certMap.put("realName", qualification.getRealName()); + + certMap.put("certName", cert.getCertName()); + certMap.put("certificateNo", cert.getCertificateNo()); + certMap.put("issueDate", cert.getIssueDate()); + 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查询证书详细信息 * 证书信息存储在资质的certificatesJson字段中,通过数据库JSON查询获取 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/certificate/{certId}") public AjaxResult getCertificateByCertId(@PathVariable("certId") Long certId) { @@ -217,6 +287,7 @@ public class VetQualificationController extends BaseController /** * 登录后检查是否需要填写资质 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/checkNeedQualification") public AjaxResult checkNeedQualification() { Long userId = SecurityUtils.getUserId(); @@ -270,6 +341,7 @@ public class VetQualificationController extends BaseController /** * 获取兽医资质详细信息 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @PreAuthorize("@ss.hasPermi('vet:qualification:query')") @GetMapping(value = "/{qualificationId}") public AjaxResult getInfo(@PathVariable("qualificationId") Long qualificationId) @@ -297,6 +369,7 @@ public class VetQualificationController extends BaseController { Long sysUserId = SecurityUtils.getUserId(); String username = SecurityUtils.getUsername(); + try { vetQualification.setUserId(sysUserId); vetQualification.setCreateBy(username); @@ -445,6 +518,7 @@ public class VetQualificationController extends BaseController /** * 根据用户ID获取资质证书列表 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/user/{userId}") public AjaxResult getByUserId(@PathVariable Long userId) { Long currentUserId = SecurityUtils.getUserId(); @@ -460,6 +534,7 @@ public class VetQualificationController extends BaseController /** * 获取证书统计信息 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @GetMapping("/statistics/{userId}") public AjaxResult getStatistics(@PathVariable Long userId) { Long currentUserId = SecurityUtils.getUserId(); @@ -475,6 +550,7 @@ public class VetQualificationController extends BaseController /** * 手动触发证书检查 */ + @Log(title = "兽医资质", businessType = BusinessType.OTHER) @PostMapping("/manual-check/{userId}") public AjaxResult manualCheck(@PathVariable Long userId) { Long currentUserId = SecurityUtils.getUserId(); @@ -741,7 +817,6 @@ public class VetQualificationController extends BaseController } catch (Exception e) { log.warn("提取Long值失败: {}", obj, e); } - return null; } } \ No newline at end of file diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java index 27f2f53..7e10b65 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java @@ -51,6 +51,7 @@ public class VetTrainingVideoController extends BaseController /** * 查询兽医培训视频列表 */ + @PreAuthorize("@ss.hasPermi('vet:training:list') or @ss.hasRole('muhu')") @GetMapping("/list") public TableDataInfo list(VetTrainingVideo vetTrainingVideo) diff --git a/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java b/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java index 2feef6d..b05d72f 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java +++ b/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.mapper.VetQualificationMapper; import com.chenhai.vet.mapper.VetNotificationMapper; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; 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 @EnableScheduling @@ -25,69 +25,197 @@ public class CertificateRemindTask { @Autowired private VetNotificationMapper vetNotificationMapper; + private final ObjectMapper objectMapper = new ObjectMapper(); + // 每天上午9点执行 - @Scheduled(cron = "0 0 9 * * ?")/* - @Scheduled(cron = "0 * * * * ?")*/ + /*@Scheduled(cron = "0 0 9 * * ?")*/ + @Scheduled(cron = "0 */1 * * * ?") public void dailyCertificateCheck() { try { - // 查询所有包含证书信息的资质 - VetQualification query = new VetQualification(); - query.setCertName(""); - List qualifications = vetQualificationMapper.selectVetQualificationList(query); - - // 过滤出有证书信息的记录 - List certificates = qualifications.stream() - .filter(q -> q.getCertName() != null && !q.getCertName().isEmpty()) - .toList(); - - certificates.forEach(this::checkAndSendReminder); + // 查询所有资质记录 + List qualifications = vetQualificationMapper.selectVetQualificationList(new VetQualification()); + + for (VetQualification qualification : qualifications) { + try { + // 检查该资质下的所有证书(包括JSON中的) + checkAllCertificates(qualification); + } 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; } - 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; } - 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> certificates = parseCertificatesJson(qualification.getCertificatesJson()); + + for (Map 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 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> 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) { - setExpiredContent(notification, qualification, 0); - notification.setRemindLevel(3); // 最高级别 + setExpiredContent(notification, certName, certificateNo, expireDate, 0); + notification.setRemindLevel(3); vetNotificationMapper.insertVetNotification(notification); } - // 过期后不再提醒 return; } else if (daysRemaining <= 7) { - setCountdownContent(notification, qualification, daysRemaining); + // 7天内过期 + setCountdownContent(notification, certName, certificateNo, expireDate, daysRemaining); notification.setRemindLevel(daysRemaining <= 3 ? 3 : 2); } else if (daysRemaining == 15 || daysRemaining == 30) { - setPreExpireContent(notification, qualification, daysRemaining); + // 15天或30天提醒 + setPreExpireContent(notification, certName, certificateNo, expireDate, daysRemaining); notification.setRemindLevel(daysRemaining == 30 ? 1 : 2); } else { return; @@ -97,12 +225,19 @@ public class CertificateRemindTask { } /** - * 创建基础通知对象 + * 创建证书通知 */ - private VetNotification createBaseNotification(VetQualification qualification) { + private VetNotification createCertificateNotification(VetQualification qualification, Long certId) { VetNotification notification = new VetNotification(); 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.setIsRead(0); 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) { 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.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天"; 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 { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); @@ -174,102 +311,125 @@ public class CertificateRemindTask { cal.add(Calendar.DAY_OF_MONTH, 1); Date endOfDay = cal.getTime(); - // 检查今天是否已发送 + // 构建查询条件 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"); List notifications = vetNotificationMapper.selectVetNotificationList(query); - // 获取今天的所有通知 List todayNotifications = notifications.stream() .filter(n -> n.getCreateTime() != null && n.getCreateTime().after(startOfDay) && n.getCreateTime().before(endOfDay)) .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 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) { 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 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 { - 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) { - e.printStackTrace(); + // 静默处理解析失败 } + + return null; } /** * 计算天数差(忽略时间部分) */ private long calculateDayDifference(Date startDate, Date endDate) { + if (startDate == null || endDate == null) { + return 0; + } + Calendar startCal = Calendar.getInstance(); startCal.setTime(startDate); resetTime(startCal); diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java new file mode 100644 index 0000000..e88765f --- /dev/null +++ b/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(); + } +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java index 62c5ddd..a780679 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetExperienceArticle.java @@ -1,7 +1,10 @@ package com.chenhai.vet.domain; import java.util.Date; +import java.util.Map; 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.ToStringStyle; import com.chenhai.common.annotation.Excel; @@ -9,7 +12,7 @@ import com.chenhai.common.core.domain.BaseEntity; /** * 兽医经验文章对象 vet_experience_article - * + * * @author ruoyi * @date 2026-01-06 */ @@ -80,6 +83,9 @@ public class VetExperienceArticle extends BaseEntity @Excel(name = "状态", dictType = "article_status") private String status; + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + private String searchKey; + /** 审核状态(0待审核 1审核中 2审核通过 3审核驳回 4敏感内容驳回) */ private String auditStatus; @@ -96,7 +102,6 @@ public class VetExperienceArticle extends BaseEntity /** 审核人姓名 */ private String auditorName; - /** 是否包含敏感词(0否 1是) */ @Excel(name = "是否包含敏感词", readConverterExp = "0=否,1=是") private String isSensitive; @@ -112,7 +117,7 @@ public class VetExperienceArticle extends BaseEntity /** 浏览次数 */ @Excel(name = "浏览次数") - private Integer viewCount; + private Long viewCount; /** 点赞数 */ @Excel(name = "点赞数") @@ -122,17 +127,37 @@ public class VetExperienceArticle extends BaseEntity @Excel(name = "收藏数") 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 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() { - return likeCount; + return likeCount != null ? likeCount : 0; } public void setLikeCount(Integer likeCount) { @@ -140,69 +165,69 @@ public class VetExperienceArticle extends BaseEntity } public Integer getCollectCount() { - return collectCount; + return collectCount != null ? collectCount : 0; } public void setCollectCount(Integer collectCount) { this.collectCount = collectCount; } - public void setId(Long id) + public void setId(Long id) { this.id = id; } - public Long getId() + public Long getId() { return id; } - public void setTitle(String title) + public void setTitle(String title) { this.title = title; } - public String getTitle() + public String getTitle() { return title; } - public void setContent(String content) + public void setContent(String content) { this.content = content; } - public String getContent() + public String getContent() { return content; } - public void setSummary(String summary) + public void setSummary(String summary) { this.summary = summary; } - public String getSummary() + public String getSummary() { return summary; } - public void setCoverImage(String coverImage) + public void setCoverImage(String coverImage) { this.coverImage = coverImage; } - public String getCoverImage() + public String getCoverImage() { return coverImage; } - public void setImages(String images) + public void setImages(String images) { this.images = images; } - public String getImages() + public String getImages() { return images; } @@ -217,152 +242,219 @@ public class VetExperienceArticle extends BaseEntity return userId; } - public void setVetName(String vetName) + public void setVetName(String vetName) { this.vetName = vetName; } - public String getVetName() + public String getVetName() { return vetName; } - public void setVetAvatar(String vetAvatar) + public void setVetAvatar(String vetAvatar) { this.vetAvatar = vetAvatar; } - public String getVetAvatar() + public String getVetAvatar() { return vetAvatar; } - public void setVetTitle(String vetTitle) + public void setVetTitle(String vetTitle) { this.vetTitle = vetTitle; } - public String getVetTitle() + public String getVetTitle() { return vetTitle; } - public void setCategoryId(Long categoryId) + public void setCategoryId(Long categoryId) { this.categoryId = categoryId; } - public Long getCategoryId() + public Long getCategoryId() { return categoryId; } - public void setCategoryName(String categoryName) + public void setCategoryName(String categoryName) { this.categoryName = categoryName; } - public String getCategoryName() + public String getCategoryName() { return categoryName; } - public void setTags(String tags) + public void setTags(String tags) { this.tags = tags; } - public String getTags() + public String getTags() { return tags; } - public void setIsTop(String isTop) + public void setIsTop(String isTop) { this.isTop = isTop; } - public String getIsTop() + public String getIsTop() { return isTop; } - public void setIsFeatured(String isFeatured) + public void setIsFeatured(String isFeatured) { this.isFeatured = isFeatured; } - public String getIsFeatured() + public String getIsFeatured() { return isFeatured; } - public void setStatus(String status) + public void setStatus(String status) { this.status = status; } - public String getStatus() + public String getStatus() { return status; } - public void setIsSensitive(String isSensitive) + public void setIsSensitive(String isSensitive) { this.isSensitive = isSensitive; } - public String getIsSensitive() + public String getIsSensitive() { return isSensitive; } - public void setSensitiveWords(String sensitiveWords) + public void setSensitiveWords(String sensitiveWords) { this.sensitiveWords = sensitiveWords; } - public String getSensitiveWords() + public String getSensitiveWords() { return sensitiveWords; } - public void setPublishTime(Date publishTime) + public void setPublishTime(Date publishTime) { this.publishTime = publishTime; } - public Date getPublishTime() + public Date getPublishTime() { return publishTime; } + // 修复:添加返回语句 + public Long getViewCount() { + return viewCount != null ? viewCount : 0L; + } + + public void setViewCount(Long viewCount) { + this.viewCount = viewCount; + } + + public Map getViewStats() { + return viewStats; + } + + public void setViewStats(Map 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 public String toString() { 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(); + } +} \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/MerchantInfoMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/MerchantInfoMapper.java new file mode 100644 index 0000000..c769f77 --- /dev/null +++ b/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 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); +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java index 7bac1ed..eb9d9de 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetExperienceArticleMapper.java @@ -75,7 +75,7 @@ public interface VetExperienceArticleMapper * @param id 文章主键 * @return 结果 */ - public int incrementViewCount(Long id); + /* public int incrementViewCount(Long id);*/ /** * 增加点赞数 diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java index a68da06..d6e5a45 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetQualificationMapper.java @@ -71,4 +71,6 @@ public interface VetQualificationMapper Map selectCertificateByCertId(@Param("certId") Long certId, @Param("userId") Long userId); + VetQualification selectVetQualificationById(Long qualificationId); + } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IMerchantInfoService.java new file mode 100644 index 0000000..edca552 --- /dev/null +++ b/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 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); +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java index 20e49bd..3ee52ef 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetExperienceArticleService.java @@ -68,13 +68,6 @@ public interface IVetExperienceArticleService */ List selectLatestArticles(Integer limit); - /** - * 获取热门文章(按浏览数排序) - * - * @param limit 限制数量 - * @return 文章集合 - */ - List selectHotArticles(Integer limit); /** * 根据用户ID获取文章 @@ -101,7 +94,7 @@ public interface IVetExperienceArticleService * @param id 文章ID * @return 结果 */ - int incrementViewCount(Long id); +/* int incrementViewCount(Long id);*/ /** * 增加点赞数 @@ -132,4 +125,5 @@ public interface IVetExperienceArticleService * @return 文章集合 */ List searchArticles(String keyword); + } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java index 2eaf006..06a99d7 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetProductService.java @@ -102,4 +102,12 @@ public interface IVetProductService */ public int cancelAudit(Long id); + /** + * 管理员查询所有兽医产品信息列表(用于审核) + * + * @param vetProduct 兽医产品信息 + * @return 兽医产品信息集合 + */ + public List selectAllVetProductList(VetProduct vetProduct); + } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java index 265ec06..f3cff37 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetQualificationService.java @@ -98,4 +98,6 @@ public interface IVetQualificationService */ Map selectCertificateWithQualificationByCertId(Long certId, Long userId); + VetQualification selectVetQualificationById(Long qualificationId); + } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/MerchantInfoServiceImpl.java new file mode 100644 index 0000000..9e93fa1 --- /dev/null +++ b/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 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); + } +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetExperienceArticleServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetExperienceArticleServiceImpl.java index 4e5f5d5..3ce2535 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetExperienceArticleServiceImpl.java +++ b/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.github.pagehelper.PageHelper; 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 com.chenhai.vet.mapper.VetExperienceArticleMapper; import com.chenhai.vet.domain.VetExperienceArticle; import com.chenhai.vet.service.IVetExperienceArticleService; +import org.springframework.transaction.annotation.Transactional; /** * 兽医经验文章Service业务层处理 @@ -20,6 +23,8 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer { @Autowired private VetExperienceArticleMapper vetExperienceArticleMapper; + @Autowired + private JdbcTemplate jdbcTemplate; /** * 查询兽医经验文章 @@ -28,11 +33,9 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer * @return 兽医经验文章 */ @Override - public VetExperienceArticle selectVetExperienceArticleById(Long id) - { + public VetExperienceArticle selectVetExperienceArticleById(Long id) { return vetExperienceArticleMapper.selectVetExperienceArticleById(id); } - /** * 查询兽医经验文章列表 * @@ -112,23 +115,6 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer return vetExperienceArticleMapper.selectArticlesByCondition(params); } - /** - * 获取热门文章(按浏览数排序) - * - * @param limit 限制数量 - * @return 文章集合 - */ - @Override - public List selectHotArticles(Integer limit) { - PageHelper.clearPage(); - Map 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获取文章 * @@ -169,16 +155,6 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer 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 * @return 结果 */ - @Override + @Override public int incrementCollectCount(Long id) { return vetExperienceArticleMapper.incrementCollectCount(id); } @@ -229,11 +205,14 @@ public class VetExperienceArticleServiceImpl implements IVetExperienceArticleSer 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; diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java index 6726d67..481d170 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java @@ -1,5 +1,6 @@ package com.chenhai.vet.service.impl; +import java.util.ArrayList; import java.util.List; import com.chenhai.common.core.domain.AjaxResult; diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java index 0f9651f..f98a55b 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetNotificationServiceImpl.java @@ -1,4 +1,3 @@ -// 更简单的版本,完全使用 Date package com.chenhai.vet.service.impl; import com.chenhai.vet.domain.VetNotification; @@ -66,57 +65,64 @@ public class VetNotificationServiceImpl implements VetNotificationService { 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 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; } + // 添加 markAllAsRead 方法 /*@Override - public void markAllAsRead(Long userId) { - VetNotification query = new VetNotification(); - query.setUserId(userId); - List 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 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); + } + } /** * 计算两个日期之间的天数差(忽略时间部分) diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java index 7364865..a43ced1 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java @@ -45,6 +45,15 @@ public class VetProductServiceImpl implements IVetProductService @Override public List selectVetProductList(VetProduct vetProduct) { + // 获取当前登录用户ID + try { + Long userId = SecurityUtils.getUserId(); + // 设置查询条件,只查询当前用户的产品 + vetProduct.setUserId(userId); + } catch (Exception e) { + // 如果获取不到用户ID,设置一个不存在的ID,确保查询不到数据 + vetProduct.setUserId(-1L); + } return vetProductMapper.selectVetProductList(vetProduct); } @@ -249,4 +258,18 @@ public class VetProductServiceImpl implements IVetProductService return vetProductMapper.insertVetProduct(vetProduct); } + + /** + * 管理员查询所有兽医产品信息列表(用于审核) + */ + @Override + public List selectAllVetProductList(VetProduct vetProduct) + { + // 管理员查询时不清除用户ID,但可以查询所有数据 + // 这里不设置用户ID,让SQL查询所有产品 + if (vetProduct != null) { + vetProduct.setUserId(null); // 清除用户ID条件 + } + return vetProductMapper.selectVetProductList(vetProduct); + } } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java index d86f7cf..0911286 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java @@ -70,12 +70,23 @@ public class VetQualificationServiceImpl implements IVetQualificationService { */ @Override public int insertVetQualification(VetQualification vetQualification) { + // 准备保存前的处理 prepareQualificationForSave(vetQualification); - return vetQualificationMapper.insertVetQualification(vetQualification); + + // 执行插入 + int result = vetQualificationMapper.insertVetQualification(vetQualification); + + // 成功插入后,为用户分配兽医未审核角色 + if (result > 0 && vetQualification.getUserId() != null) { + assignVetUnapprovedRole(vetQualification.getUserId()); + } + + return result; } + /** - * 修改兽医资质 + * 修改兽医资质 - 处理审核状态变更时的角色切换 */ @Override public int updateVetQualification(VetQualification vetQualification) { @@ -83,11 +94,18 @@ public class VetQualificationServiceImpl implements IVetQualificationService { throw new ServiceException("资质ID不能为空"); } - VetQualification existing = vetQualificationMapper.selectVetQualificationByQualificationId(vetQualification.getQualificationId()); + // 获取更新前的资质信息 + VetQualification existing = vetQualificationMapper.selectVetQualificationByQualificationId( + vetQualification.getQualificationId() + ); if (existing == null) { throw new ServiceException("资质信息不存在"); } + String oldStatus = existing.getAuditStatus(); + String newStatus = vetQualification.getAuditStatus(); + Long userId = existing.getUserId(); + // 更新基本信息 updateBasicQualificationInfo(existing, vetQualification); @@ -101,9 +119,128 @@ public class VetQualificationServiceImpl implements IVetQualificationService { // 更新证书状态 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(); return (int) (diff / (1000 * 60 * 60 * 24)); } + + @Override + public VetQualification selectVetQualificationById(Long qualificationId) { + return vetQualificationMapper.selectVetQualificationById(qualificationId); + } } \ No newline at end of file diff --git a/chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml b/chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml new file mode 100644 index 0000000..caf3b42 --- /dev/null +++ b/chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + select shop_id, shop_name, shop_address, phone, user_id, created_at, updated_at, is_active from merchant_info + + + + + + + + insert into merchant_info + + shop_name, + shop_address, + phone, + user_id, + created_at, + updated_at, + is_active, + + + #{shopName}, + #{shopAddress}, + #{phone}, + #{userId}, + #{createdAt}, + #{updatedAt}, + #{isActive}, + + + + + update merchant_info + + shop_name = #{shopName}, + shop_address = #{shopAddress}, + phone = #{phone}, + user_id = #{userId}, + created_at = #{createdAt}, + updated_at = #{updatedAt}, + is_active = #{isActive}, + + where shop_id = #{shopId} + + + + delete from merchant_info where shop_id = #{shopId} + + + + delete from merchant_info where shop_id in + + #{shopId} + + + \ No newline at end of file diff --git a/chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml index 84f15a0..c90aeed 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetExperienceArticleMapper.xml @@ -29,95 +29,137 @@ + + + - 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 + - - + @@ -160,7 +202,9 @@ is_sensitive, sensitive_words, publish_time, - create_time, + user_role, + user_type, + create_time, update_time, @@ -185,7 +229,9 @@ #{isSensitive}, #{sensitiveWords}, #{publishTime}, - now(), + #{userRole}, + #{userType}, + now(), #{updateTime}, @@ -215,11 +261,12 @@ is_sensitive = #{isSensitive}, sensitive_words = #{sensitiveWords}, publish_time = #{publishTime}, + user_role = #{userRole}, + user_type = #{userType}, update_time = now(), where id = #{id} - delete from vet_experience_article where id = #{id} diff --git a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml index 2468953..48b4d61 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml @@ -246,4 +246,9 @@ LIMIT 1 + + \ No newline at end of file diff --git a/chenhai-ui/src/api/vet/merchant.js b/chenhai-ui/src/api/vet/merchant.js new file mode 100644 index 0000000..cc774f9 --- /dev/null +++ b/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' + }) +} diff --git a/chenhai-ui/src/views/vet/merchant/index.vue b/chenhai-ui/src/views/vet/merchant/index.vue new file mode 100644 index 0000000..60d81a6 --- /dev/null +++ b/chenhai-ui/src/views/vet/merchant/index.vue @@ -0,0 +1,362 @@ + + +