diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCertificateController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCertificateController.java index 939b7b5..4cf303a 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCertificateController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetCertificateController.java @@ -70,6 +70,18 @@ public class VetCertificateController extends BaseController public TableDataInfo list(VetCertificate vetCertificate) { startPage(); + Long currentUserId = getCurrentUserId(); + if (currentUserId == null) { + return getDataTable(List.of()); + } + + // 如果是管理员,可以查看所有证书(不过滤用户ID) + if (!isAdmin()) { + // 普通用户:只查询自己的证书 + vetCertificate.setUserId(currentUserId); + } + // 管理员:不设置userId,查询所有证书 + List list = vetCertificateService.selectVetCertificateList(vetCertificate); return getDataTable(list); } 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 6ae6e45..3d5c083 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 @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; import java.util.*; /** - * 兽医经验文章Controller + * 兽医经验分享Controller */ @RestController @RequestMapping("/vet/article") 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 new file mode 100644 index 0000000..b40b221 --- /dev/null +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java @@ -0,0 +1,125 @@ +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.VetKnowledge; +import com.chenhai.vet.service.IVetKnowledgeService; +import com.chenhai.common.utils.poi.ExcelUtil; +import com.chenhai.common.core.page.TableDataInfo; + +/** + * 兽医文章Controller + * + * @author ruoyi + * @date 2026-01-08 + */ +@RestController +@RequestMapping("/vet/knowledge") +public class VetKnowledgeController extends BaseController +{ + @Autowired + private IVetKnowledgeService vetKnowledgeService; + + /** + * 查询兽医文章列表 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:list')") + @GetMapping("/list") + public TableDataInfo list(VetKnowledge vetKnowledge) + { + startPage(); + List list = vetKnowledgeService.selectVetKnowledgeList(vetKnowledge); + return getDataTable(list); + } + + /** + * 导出兽医文章列表 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:export')") + @Log(title = "兽医文章", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, VetKnowledge vetKnowledge) + { + List list = vetKnowledgeService.selectVetKnowledgeList(vetKnowledge); + ExcelUtil util = new ExcelUtil(VetKnowledge.class); + util.exportExcel(response, list, "兽医文章数据"); + } + + /** + * 获取兽医文章详细信息 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(vetKnowledgeService.selectVetKnowledgeById(id)); + } + + /** + * 新增兽医文章 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:add')") + @Log(title = "兽医文章", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody VetKnowledge vetKnowledge) + { + vetKnowledge.setStatus("0"); + return toAjax(vetKnowledgeService.insertVetKnowledge(vetKnowledge)); + } + + /** + * 修改兽医文章 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:edit')") + @Log(title = "兽医文章", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody VetKnowledge vetKnowledge) + { + return toAjax(vetKnowledgeService.updateVetKnowledge(vetKnowledge)); + } + + /** + * 删除兽医文章 + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:remove')") + @Log(title = "兽医文章", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(vetKnowledgeService.deleteVetKnowledgeByIds(ids)); + } + + /** + * 上传文章(待审核) + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:upload')") + @Log(title = "兽医文章", businessType = BusinessType.INSERT) + @PostMapping("/upload") + public AjaxResult upload(@RequestBody VetKnowledge vetKnowledge) { + return vetKnowledgeService.uploadVetKnowledge(vetKnowledge); + } + + /** + * 发布文章(更新状态) + */ + @PreAuthorize("@ss.hasPermi('vet:knowledge:publish')") + @Log(title = "兽医文章", businessType = BusinessType.UPDATE) + @PutMapping("/publish/{id}") + public AjaxResult publish(@PathVariable Long id) { + return vetKnowledgeService.publishVetKnowledge(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 2a998c7..1165216 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 @@ -1,7 +1,9 @@ package com.chenhai.web.controller.vet; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.chenhai.common.utils.SecurityUtils; import org.springframework.security.access.prepost.PreAuthorize; @@ -37,7 +39,7 @@ public class VetNotificationController extends BaseController private VetNotificationService vetNotificationService; /** - * 获取当前用户ID + * 获取当前用户ID(私有方法) */ private Long getCurrentUserId() { return SecurityUtils.getUserId(); @@ -47,7 +49,8 @@ public class VetNotificationController extends BaseController * 检查是否为管理员 */ private boolean isAdmin() { - return SecurityUtils.isAdmin(getCurrentUserId()); + Long userId = getCurrentUserId(); + return userId != null && SecurityUtils.isAdmin(userId); } /** @@ -67,6 +70,64 @@ public class VetNotificationController extends BaseController return notification != null && currentUserId.equals(notification.getUserId()); } + /** + * 获取通知统计信息(用于首页卡片) + */ + @PreAuthorize("@ss.hasPermi('vet:notification:query')") + @GetMapping("/stats/card") + public AjaxResult getNotificationCardStats() { + Long currentUserId = getCurrentUserId(); + if (currentUserId == null) { + return success(Map.of( + "unreadCount", 0, + "readCount", 0, + "totalCount", 0 + )); + } + + Map stats; + if (isAdmin()) { + // 管理员:查询所有通知 + stats = getAllNotificationStats(); + } else { + // 普通用户:调用 Service 方法 + stats = vetNotificationService.getNotificationStats(currentUserId); + } + + // 为前端卡片准备数据 + Map result = new HashMap<>(); + result.put("unreadCount", stats.get("unread")); + result.put("readCount", stats.get("read")); + result.put("totalCount", stats.get("unread") + stats.get("read")); + + return success(result); + } + + /** + * 管理员获取所有通知统计(私有方法) + */ + private Map getAllNotificationStats() { + try { + // 查询所有通知 + VetNotification query = new VetNotification(); + List allNotifications = vetNotificationService.selectVetNotificationList(query); + int total = allNotifications != null ? allNotifications.size() : 0; + + // 查询所有未读通知 + VetNotification unreadQuery = new VetNotification(); + unreadQuery.setIsRead(0); + List unreadList = vetNotificationService.selectVetNotificationList(unreadQuery); + int unread = unreadList != null ? unreadList.size() : 0; + int read = total - unread; + + return Map.of("unread", unread, "read", read); + } catch (Exception e) { + // 出错时返回0 + return Map.of("unread", 0, "read", 0); + } + } + + /** * 查询兽医通知列表 */ @@ -139,9 +200,16 @@ public class VetNotificationController extends BaseController @PutMapping public AjaxResult edit(@RequestBody VetNotification vetNotification) { + Long currentUserId = getCurrentUserId(); + if (currentUserId == null) { + return error("用户未登录"); + } + vetNotification.setUserId(currentUserId); + vetNotification.setCreateBy(SecurityUtils.getUsername()); return toAjax(vetNotificationService.updateVetNotification(vetNotification)); } + /** * 删除兽医通知 */ @@ -153,63 +221,15 @@ public class VetNotificationController extends BaseController return toAjax(vetNotificationService.deleteVetNotificationByIds(ids)); } - - /** - * 获取当前用户的未读通知数量 - */ - @PreAuthorize("@ss.hasPermi('vet:notification:query')") - @GetMapping("/user/unread/count") - public AjaxResult getUnreadCount() - { - Long currentUserId = getUserId(); - if (currentUserId == null) { - return success(0); - } - - int unreadCount = vetNotificationService.getUnreadCount(currentUserId); - return success(unreadCount); - } - - /** - * 标记单个通知为已读 - */ - @PreAuthorize("@ss.hasPermi('vet:notification:edit')") - @Log(title = "标记通知已读", businessType = BusinessType.UPDATE) - @PutMapping("/{id}/read") - public AjaxResult markAsRead(@PathVariable Long id) - { - boolean result = vetNotificationService.markAsRead(id); - return toAjax(result ? 1 : 0); - } - - /** - * 标记所有通知为已读 - */ - @PreAuthorize("@ss.hasPermi('vet:notification:edit')") - @Log(title = "标记所有通知已读", businessType = BusinessType.UPDATE) - @PutMapping("/user/mark-all-read") - public AjaxResult markAllAsRead() - { - Long currentUserId = getUserId(); - if (currentUserId == null) { - return error("用户未登录"); + /** + * 标记单个通知为已读 + */ + @PreAuthorize("@ss.hasPermi('vet:notification:edit')") + @Log(title = "标记通知已读", businessType = BusinessType.UPDATE) + @PutMapping("/{id}/read") + public AjaxResult markAsRead (@PathVariable Long id) + { + boolean result = vetNotificationService.markAsRead(id); + return toAjax(result ? 1 : 0); } - - boolean result = vetNotificationService.markAllAsRead(currentUserId); - return toAjax(result ? 1 : 0); - } - - /** - * 根据指定用户ID查询通知列表(管理员功能) - */ - @PreAuthorize("@ss.hasPermi('vet:notification:list')") - @GetMapping("/list/user/{userId}") - public TableDataInfo listByUserId(@PathVariable Long userId) - { - startPage(); - VetNotification query = new VetNotification(); - query.setUserId(userId); - List list = vetNotificationService.selectVetNotificationList(query); - return getDataTable(list); - } } \ No newline at end of file diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetQualificationController.java index 05fa7fd..b1d2603 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 @@ -6,24 +6,32 @@ import com.chenhai.common.core.domain.AjaxResult; import com.chenhai.common.core.page.TableDataInfo; import com.chenhai.common.enums.BusinessType; import com.chenhai.common.utils.SecurityUtils; +import com.chenhai.common.utils.file.FileUtils; import com.chenhai.common.utils.poi.ExcelUtil; import com.chenhai.vet.domain.BusinessScopeConstants; -import com.chenhai.vet.domain.VetCertificate; import com.chenhai.vet.domain.VetQualification; -import com.chenhai.vet.mapper.VetQualificationMapper; import com.chenhai.vet.service.IVetQualificationService; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; import java.util.*; +import static com.chenhai.framework.datasource.DynamicDataSourceContextHolder.log; + /** - * 兽医资质Controller - * - * @author ruoyi - * @date 2025-12-26 + * 兽医资质控制器 + * + * @author 自定义 */ @RestController @RequestMapping("/vet/qualification") @@ -31,8 +39,124 @@ public class VetQualificationController extends BaseController { @Autowired private IVetQualificationService vetQualificationService; + @Autowired - private VetQualificationMapper vetQualificationMapper; + private JdbcTemplate jdbcTemplate; + + // 注入若依配置的文件上传根路径(需在application.yml配置:ruoyi.profile=D:/ruoyi/uploadPath) + @Value("${chenhai.profile}") + private String uploadRootPath; + + // 资质文件存储子路径(便于分类管理) + private static final String QUALIFICATION_FILE_PATH = "/vet/qualification/"; + + /** + * 获取资质类型选项(下拉框用) + */ + @GetMapping("/type/options") + public AjaxResult getQualificationTypeOptions() { + String sql = "SELECT dict_value as value, dict_label as label " + + "FROM sys_dict_data " + + "WHERE dict_type = 'qualification_type' AND status = '0' " + + "ORDER BY dict_sort"; + + List> options = jdbcTemplate.query(sql, (rs, rowNum) -> { + Map option = new HashMap<>(); + option.put("value", rs.getString("value")); + option.put("label", rs.getString("label")); + return option; + }); + + return AjaxResult.success(options); + } + + /** + * 获取经营范围选项(下拉框用) + */ + @GetMapping("/scope/options") + public AjaxResult getScopeOptions() { + String sql = "SELECT dict_value as value, dict_label as label " + + "FROM sys_dict_data " + + "WHERE dict_type = 'scope_names' AND status = '0' " + + "ORDER BY dict_sort"; + + List> options = jdbcTemplate.query(sql, (rs, rowNum) -> { + Map option = new HashMap<>(); + option.put("value", rs.getString("value")); + option.put("label", rs.getString("label")); + return option; + }); + + return AjaxResult.success(options); + } + + /** + * 上传资质文件(关联兽医资质ID) + * @param file 上传的文件 + * @return 文件上传结果(包含访问路径、存储路径等) + */ + @PreAuthorize("@ss.hasPermi('vet:qualification:edit')") + @Log(title = "兽医资质文件上传", businessType = BusinessType.UPDATE) + @PostMapping("/upload") + public AjaxResult uploadQualificationFile(@RequestParam("file") MultipartFile file) { + try { + if (file.isEmpty()) { + return AjaxResult.error("文件不能为空"); + } + + String originalFileName = file.getOriginalFilename(); + String ext = FileUtils.getExtension(originalFileName).toLowerCase(); + + // 文件类型验证 + String[] allowedExts = {"jpg", "png", "pdf", "doc", "docx", "xls", "xlsx"}; + boolean isAllowed = FileUtils.isAllowedExtension(originalFileName, allowedExts); + if (!isAllowed) { + return AjaxResult.error("文件类型不允许"); + } + + // 🔥 关键:使用配置的路径 + String basePath = uploadRootPath; // D:/ymtx/uploadPath + String subPath = "vet/qualification"; + String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date()); + String fullPath = basePath + File.separator + subPath + File.separator + datePath; + + // 创建目录 + File destDir = new File(fullPath); + if (!destDir.exists()) { + destDir.mkdirs(); + } + + // 生成唯一文件名 + String uuid = UUID.randomUUID().toString().replace("-", ""); + String fileName = uuid + "_" + originalFileName; + String filePath = fullPath + File.separator + fileName; + + // 保存文件 + File destFile = new File(filePath); + file.transferTo(destFile); + + // 🔥 返回可访问的URL(注意路径格式) + // 前端访问路径:/profile/vet/qualification/yyyy/MM/dd/xxx.jpg + String fileUrl = "/" + subPath + "/" + datePath + "/" + fileName; + // 下载链接:Spring有默认的下载控制器 /common/download?fileName=xxx + String downloadUrl = "/common/download?fileName=" + URLEncoder.encode(fileUrl, "UTF-8"); + + Map data = new HashMap<>(); + data.put("fileName", originalFileName); + data.put("fileUrl", fileUrl); // 前端显示用 + data.put("downloadUrl", downloadUrl); // 下载用 + data.put("filePath", fileUrl); // 提交到资质表用(存储相对路径) + data.put("fileSize", file.getSize()); + data.put("uuid", uuid); + + return AjaxResult.success("上传成功", data); + + } catch (Exception e) { + log.error("文件上传失败", e); + return AjaxResult.error("上传失败: " + e.getMessage()); + } + } + @@ -42,36 +166,32 @@ public class VetQualificationController extends BaseController @PreAuthorize("@ss.hasPermi('vet:qualification:list')") @GetMapping("/list") public TableDataInfo list(VetQualification vetQualification) - { startPage(); - + { + startPage(); Long userId = SecurityUtils.getUserId(); if (!SecurityUtils.isAdmin(userId)) { - vetQualification.setVetId(userId); + vetQualification.setUserId(userId); } - List list = vetQualificationService.selectVetQualificationList(vetQualification); return getDataTable(list); } /** - * 登录后检查是否需要填写资质(弹窗用) + * 登录后检查是否需要填写资质 */ @GetMapping("/checkNeedQualification") public AjaxResult checkNeedQualification() { Long userId = SecurityUtils.getUserId(); VetQualification query = new VetQualification(); - query.setVetId(userId); + query.setUserId(userId); List list = vetQualificationService.selectVetQualificationList(query); Map result = new HashMap<>(); - if (list.isEmpty()) { - // 没有资质记录,需要弹窗填写 result.put("needPopup", true); result.put("message", "请先填写兽医资质信息"); } else { VetQualification qualification = list.get(0); - // 检查资质状态 if ("0".equals(qualification.getAuditStatus())) { result.put("needPopup", false); result.put("message", "您的资质正在审核中,请耐心等待"); @@ -90,68 +210,9 @@ public class VetQualificationController extends BaseController result.put("status", "needSubmit"); } } - return AjaxResult.success(result); } - /** - * 快速提交资质(弹窗用) - */ - @Log(title = "快速提交资质", businessType = BusinessType.INSERT) - @PostMapping("/quickSubmit") - public AjaxResult quickSubmit(@RequestBody VetQualification vetQualification) { - Long userId = SecurityUtils.getUserId(); - String username = SecurityUtils.getUsername(); - - // 设置当前用户信息 - vetQualification.setVetId(userId); - vetQualification.setCreateBy(username); - - // 处理经营范围名称 - if (vetQualification.getScopeIds() != null && !vetQualification.getScopeIds().isEmpty()) { - String[] scopeIds = vetQualification.getScopeIds().split(","); - List scopeNames = new ArrayList<>(); - for (String scopeId : scopeIds) { - String name = BusinessScopeConstants.getScopeName(scopeId.trim()); - if (name != null) { - scopeNames.add(name); - } - } - vetQualification.setScopeNames(String.join(",", scopeNames)); - } - - // 设置为待审核状态 - vetQualification.setAuditStatus("0"); - - int result; - if (vetQualification.getQualificationId() != null) { - // 更新 - vetQualification.setUpdateBy(username); - result = vetQualificationService.updateVetQualification(vetQualification); - } else { - // 新增 - result = vetQualificationService.insertVetQualification(vetQualification); - } - - return toAjax(result); - } - - /** - * 获取简单的经营范围列表(下拉框用) - */ - @GetMapping("/scope/options") - public AjaxResult getScopeOptions() { - List> options = new ArrayList<>(); - - for (Map.Entry entry : BusinessScopeConstants.SCOPE_MAP.entrySet()) { - Map option = new HashMap<>(); - option.put("value", entry.getKey()); - option.put("label", entry.getValue()); - options.add(option); - } - - return AjaxResult.success(options); - } /** * 获取经营范围详情 @@ -162,40 +223,8 @@ public class VetQualificationController extends BaseController detail.put("scopeId", scopeId); detail.put("scopeName", BusinessScopeConstants.getScopeName(scopeId)); detail.put("requiredQualifications", BusinessScopeConstants.getRequiredQualifications(scopeId)); - return AjaxResult.success(detail); } - /** - * 获取我的资质信息 - */ - @GetMapping("/my") - public AjaxResult getMyQualification() { - Long userId = SecurityUtils.getUserId(); - VetQualification query = new VetQualification(); - query.setVetId(userId); - List list = vetQualificationService.selectVetQualificationList(query); - if (!list.isEmpty()) { - VetQualification qualification = list.get(0); - - // 处理经营范围名称 - if (qualification.getScopeIds() != null && !qualification.getScopeIds().isEmpty() - && (qualification.getScopeNames() == null || qualification.getScopeNames().isEmpty())) { - - String[] scopeIds = qualification.getScopeIds().split(","); - List scopeNames = new ArrayList<>(); - for (String scopeId : scopeIds) { - String name = BusinessScopeConstants.getScopeName(scopeId.trim()); - if (name != null) { - scopeNames.add(name); - } - } - qualification.setScopeNames(String.join(",", scopeNames)); - } - - return success(qualification); - } - return AjaxResult.error("暂无资质信息"); - } /** * 导出兽医资质列表 @@ -228,14 +257,28 @@ public class VetQualificationController extends BaseController @PostMapping public AjaxResult add(@RequestBody VetQualification vetQualification) { - // 自动获取当前用户信息 - Long userId = SecurityUtils.getUserId(); + Long sysUserId = SecurityUtils.getUserId(); String username = SecurityUtils.getUsername(); + try { + vetQualification.setUserId(sysUserId); + vetQualification.setCreateBy(username); + return toAjax(vetQualificationService.insertVetQualification(vetQualification)); + } catch (DataIntegrityViolationException e) { + if (e.getMessage().contains("foreign key constraint")) { + createSimpleVetUser(sysUserId, username); + return toAjax(vetQualificationService.insertVetQualification(vetQualification)); + } + throw e; + } + } - vetQualification.setVetId(userId); - vetQualification.setCreateBy(username); - - return toAjax(vetQualificationService.insertVetQualification(vetQualification)); + private void createSimpleVetUser(Long sysUserId, String username) { + try { + String sql = "INSERT IGNORE INTO vet_user (sys_user_id, username, create_time) VALUES (?, ?, NOW())"; + jdbcTemplate.update(sql, sysUserId, username); + } catch (Exception e) { + // 忽略异常 + } } /** @@ -254,7 +297,7 @@ public class VetQualificationController extends BaseController */ @PreAuthorize("@ss.hasPermi('vet:qualification:remove')") @Log(title = "兽医资质", businessType = BusinessType.DELETE) - @DeleteMapping("/{qualificationIds}") + @DeleteMapping("/{qualificationIds}") public AjaxResult remove(@PathVariable Long[] qualificationIds) { return toAjax(vetQualificationService.deleteVetQualificationByQualificationIds(qualificationIds)); @@ -263,29 +306,48 @@ public class VetQualificationController extends BaseController /** * 提交审核 */ - /*@PreAuthorize("@ss.hasPermi('vet:qualification:audit')")*/ @Log(title = "兽医资质", businessType = BusinessType.UPDATE) - @PostMapping("/submitAudit/{qualificationId}") - public AjaxResult submitAudit(@PathVariable("qualificationId") Long qualificationId) { - VetQualification vetQualification = new VetQualification(); - vetQualification.setQualificationId(qualificationId); - vetQualification.setAuditStatus("0"); // 设置为待审核状态 - vetQualification.setApplyTime(new Date()); // 设置申请时间为当前时间 + @PostMapping("/submit") + public AjaxResult submitQualification(@RequestBody VetQualification vetQualification) { + try { + Long userId = SecurityUtils.getUserId(); + String username = SecurityUtils.getUsername(); + + // 设置必要字段 + vetQualification.setUserId(userId); + vetQualification.setCreateBy(username); + vetQualification.setAuditStatus("0"); // 设置为待审核状态 + vetQualification.setApplyTime(new Date()); // 设置申请时间 + + int result; + // 如果已有资质ID,则为更新操作(重新提交审核) + if (vetQualification.getQualificationId() != null) { + vetQualification.setUpdateBy(username); + result = vetQualificationService.updateVetQualification(vetQualification); + } else { + // 新增资质记录并提交审核 + result = vetQualificationService.insertVetQualification(vetQualification); + } - return toAjax(vetQualificationService.updateVetQualification(vetQualification)); + if (result > 0) { + return AjaxResult.success("资质提交成功,等待审核", vetQualification); + } else { + return AjaxResult.error("资质提交失败"); + } + + } catch (Exception e) { + log.error("提交资质失败", e); + return AjaxResult.error("提交失败:" + e.getMessage()); + } } /** * 审核操作 */ - /*@PreAuthorize("@ss.hasPermi('vet:qualification:audit')")*/ @Log(title = "兽医资质", businessType = BusinessType.UPDATE) @PostMapping("/audit") public AjaxResult audit(@RequestBody VetQualification vetQualification) { - // 设置审核时间为当前时间 vetQualification.setAuditTime(new Date()); - // 这里可以从SecurityContextHolder获取当前登录用户ID作为审核人ID - // vetQualification.setAuditorId(getUserId()); return toAjax(vetQualificationService.updateVetQualification(vetQualification)); } -} +} \ 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 new file mode 100644 index 0000000..7ac6859 --- /dev/null +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetTrainingVideoController.java @@ -0,0 +1,194 @@ +package com.chenhai.web.controller.vet; + +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.utils.SecurityUtils; +import com.chenhai.vet.domain.VetTrainingVideo; +import com.chenhai.vet.service.IVetTrainingVideoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("/vet/training") +public class VetTrainingVideoController extends BaseController { + + @Autowired + private IVetTrainingVideoService trainingVideoService; + + /** + * 获取当前用户ID + */ + private Long getCurrentUserId() { + return SecurityUtils.getUserId(); + } + + /** + * 上传培训视频 + */ + @PostMapping("/upload") + public AjaxResult uploadVideo( + @RequestParam String title, + @RequestParam MultipartFile videoFile, + @RequestParam(required = false) String description, + @RequestParam(required = false) String category, + @RequestParam(required = false) String tags, + @RequestParam(required = false, defaultValue = "1") String status, + @RequestParam(required = false) MultipartFile coverImage) { + + Long userId = getCurrentUserId(); + + try { + VetTrainingVideo video = new VetTrainingVideo(); + video.setUserId(userId); // 修正变量名 + video.setTitle(title); + video.setDescription(description); + video.setCategory(category); + video.setTags(tags); + video.setStatus(status); + + // 上传并保存视频 + String result = trainingVideoService.uploadAndSave(video, videoFile, coverImage); + return success(result); + } catch (Exception e) { + return error("上传失败:" + e.getMessage()); + } + } + + /** + * 批量上传视频(可选功能) + */ + @PostMapping("/upload/batch") + public AjaxResult uploadBatch( + @RequestParam String[] titles, + @RequestParam MultipartFile[] videoFiles, + @RequestParam(required = false) String[] categories) { + + Long userId = getCurrentUserId(); + + try { + int successCount = 0; + for (int i = 0; i < videoFiles.length; i++) { + if (i < titles.length) { + VetTrainingVideo video = new VetTrainingVideo(); + video.setUserId(userId); // 修正变量名 + video.setTitle(titles[i]); + video.setCategory(categories != null && i < categories.length ? categories[i] : null); + video.setStatus("1"); + + trainingVideoService.uploadAndSave(video, videoFiles[i], null); + successCount++; + } + } + return success("成功上传 " + successCount + " 个视频"); + } catch (Exception e) { + return error("批量上传失败:" + e.getMessage()); + } + } + + /** + * 查看我上传的视频 + */ + @GetMapping("/my-videos") + public TableDataInfo getMyVideos( + @RequestParam(required = false) String title, + @RequestParam(required = false) String category, + @RequestParam(required = false) String status) { + + startPage(); + Long userId = getCurrentUserId(); // 修正变量名 + List list = trainingVideoService.getMyVideos(userId, title, category, status); + return getDataTable(list); + } + + /** + * 查看所有公开的视频 + */ + @GetMapping("/public-videos") + public TableDataInfo getPublicVideos( + @RequestParam(required = false) String title, + @RequestParam(required = false) String category, + @RequestParam(required = false) String userName) { // 参数名改为userName + + startPage(); + List list = trainingVideoService.getPublicVideos(title, category, userName); + return getDataTable(list); + } + + /** + * 查看视频详情 + */ + @GetMapping("/video/{videoId}") + public AjaxResult getVideoDetail(@PathVariable Long videoId) { + Long userId = getCurrentUserId(); // 修正变量名 + VetTrainingVideo video = trainingVideoService.getVideoDetail(videoId, userId); + + if (video == null) { + return error("视频不存在或无权限查看"); + } + + // 如果是公开视频或自己的视频,增加观看次数 + if ("1".equals(video.getStatus()) || userId.equals(video.getUserId())) { + trainingVideoService.incrementViewCount(videoId); + video.setViewCount(video.getViewCount() + 1); + } + + return success(video); + } + + /** + * 获取视频播放地址(带权限校验)- 可选功能 + */ + @GetMapping("/video/play/{videoId}") + public AjaxResult getPlayUrl(@PathVariable Long videoId) { + Long userId = getCurrentUserId(); // 修正变量名 + String playUrl = trainingVideoService.getVideoPlayUrl(videoId, userId); + + if (playUrl == null) { + return error("无权限播放此视频"); + } + + return success(playUrl); + } + + /** + * 获取热门视频(按观看次数排序) + */ + @GetMapping("/hot-videos") + public AjaxResult getHotVideos(@RequestParam(defaultValue = "10") Integer limit) { + List list = trainingVideoService.getHotVideos(limit); + return success(list); + } + + /** + * 搜索视频 + */ + @GetMapping("/search") + public TableDataInfo searchVideos(@RequestParam String keyword) { + startPage(); + List list = trainingVideoService.searchVideos(keyword); + return getDataTable(list); + } + + /** + * 删除我的视频 + */ + @DeleteMapping("/{videoId}") + public AjaxResult deleteVideo(@PathVariable Long videoId) { + Long userId = getCurrentUserId(); // 修正变量名 + VetTrainingVideo video = trainingVideoService.getVideoDetail(videoId, userId); + + if (video == null) { + return error("视频不存在"); + } + + if (!userId.equals(video.getUserId())) { + return error("无权删除此视频"); + } + + return toAjax(trainingVideoService.deleteVideoById(videoId)); + } +} \ No newline at end of file diff --git a/chenhai-common/src/main/java/com/chenhai/common/utils/file/FileUtils.java b/chenhai-common/src/main/java/com/chenhai/common/utils/file/FileUtils.java index b9f6d7d..d5a030d 100644 --- a/chenhai-common/src/main/java/com/chenhai/common/utils/file/FileUtils.java +++ b/chenhai-common/src/main/java/com/chenhai/common/utils/file/FileUtils.java @@ -300,4 +300,38 @@ public class FileUtils String baseName = FilenameUtils.getBaseName(fileName); return baseName; } + + public static String getExtension(String fileName) { + if (fileName == null) return ""; + // 第一步:提取纯文件名(去掉路径,比如 D:/upload/简历.doc → 简历.doc) + String pureFileName = getName(fileName); + if (pureFileName == null || !pureFileName.contains(".")) return ""; + // 第二步:去空格 + 取最后一个.后的扩展名 + String ext = pureFileName.substring(pureFileName.lastIndexOf(".") + 1).trim(); + return ext; + } + + // 2. 修复isAllowedExtension:补充空值/空字符串校验 + public static boolean isAllowedExtension(String fileName, String[] allowedExts) { + if (fileName == null || allowedExts == null || allowedExts.length == 0) return false; + // 获取扩展名并转小写(统一匹配规则) + String ext = getExtension(fileName).toLowerCase(); + // 排除空扩展名情况 + if (ext.isEmpty()) return false; + // 遍历允许的扩展名,也转小写匹配 + for (String allowedExt : allowedExts) { + if (ext.equals(allowedExt.toLowerCase().trim())) { + return true; + } + } + return false; + } + + + public static boolean mkdirs(String dirPath) { + if (dirPath == null) return false; + File dir = new File(dirPath); + // 目录不存在则创建,存在则返回true + return dir.exists() || dir.mkdirs(); + } } diff --git a/chenhai-system/pom.xml b/chenhai-system/pom.xml index 629ee65..3b5f048 100644 --- a/chenhai-system/pom.xml +++ b/chenhai-system/pom.xml @@ -61,6 +61,20 @@ jackson-databind + + + org.springframework.boot + spring-boot-starter-web + + + + + commons-io + commons-io + 2.11.0 + + + \ No newline at end of file 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 c1a9b48..7e86f8d 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/CertificateRemindTask.java @@ -1,55 +1,285 @@ package com.chenhai.vet; import com.chenhai.vet.domain.VetCertificate; -import com.chenhai.vet.service.IVetCertificateService; +import com.chenhai.vet.domain.VetNotification; +import com.chenhai.vet.mapper.VetCertificateMapper; +import com.chenhai.vet.mapper.VetNotificationMapper; 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; -/** - * 证书提醒定时任务 - * - * @author ruoyi - */ +import java.util.Calendar; +import java.util.Date; +import java.util.List; + @Component @EnableScheduling @Slf4j public class CertificateRemindTask { @Autowired - private IVetCertificateService vetCertificateService; + private VetCertificateMapper vetCertificateMapper; + @Autowired + private VetNotificationMapper vetNotificationMapper; + + // 测试:每分钟执行 | 正式:每天上午9点 @Scheduled(cron = "0 0 9 * * ?") + //@Scheduled(cron = "0 */1 * * * ?") + @Scheduled(cron = "0 0 9 * * ?") + public void dailyCertificateCheck() { + /* log.info("开始检查证书过期情况...");*/ + try { + List certificates = vetCertificateMapper.selectVetCertificateList(new VetCertificate()); + certificates.forEach(this::checkAndSendReminder); + /* log.info("证书检查完成,共检查{}个证书", certificates.size());*/ + } catch (Exception e) { + /*log.error("证书检查任务执行失败", e);*/ + } + } /** - * 每天凌晨2点检查证书过期情况 + * 检查单个证书并发送提醒 */ - /* @Scheduled(cron = "0 0 2 * * ?")*/ - @Scheduled(cron = "0 */1 * * * ?") - public void dailyCertificateCheck() { - /*log.info("开始执行每日证书检查任务...");*/ + private void checkAndSendReminder(VetCertificate certificate) { + if (certificate == null || certificate.getExpireDate() == null) { + return; + } + + long daysRemaining = calculateDayDifference(new Date(), certificate.getExpireDate()); + + updateCertificateStatus(certificate, daysRemaining); + + if (!shouldSendReminder(certificate, daysRemaining) || hasRecentReminder(certificate, daysRemaining)) { + return; + } + + sendReminder(certificate, daysRemaining); + } + + /** + * 发送提醒 + */ + private void sendReminder(VetCertificate certificate, long daysRemaining) { + VetNotification notification = createBaseNotification(certificate); + + if (daysRemaining <= 0) { + // 只发送过期当天的提醒 + if (daysRemaining == 0) { + setExpiredContent(notification, certificate, 0); + notification.setRemindLevel(3); // 最高级别 + vetNotificationMapper.insertVetNotification(notification); + } + // 过期后不再提醒 + return; + } else if (daysRemaining <= 7) { + setCountdownContent(notification, certificate, daysRemaining); + notification.setRemindLevel(daysRemaining <= 3 ? 3 : 2); + } else if (daysRemaining == 15 || daysRemaining == 30) { + setPreExpireContent(notification, certificate, daysRemaining); + notification.setRemindLevel(daysRemaining == 30 ? 1 : 2); + } else { + return; + } + + vetNotificationMapper.insertVetNotification(notification); + } + + /** + * 创建基础通知对象 + */ + private VetNotification createBaseNotification(VetCertificate certificate) { + VetNotification notification = new VetNotification(); + notification.setUserId(certificate.getUserId()); + notification.setRelatedId(certificate.getId().toString()); + notification.setType("CERT_EXPIRE_REMIND"); + notification.setIsRead(0); + notification.setCreateTime(new Date()); + return notification; + } + + /** + * 设置过期内容 + */ + private void setExpiredContent(VetNotification notification, VetCertificate certificate, long daysExpired) { + if (daysExpired == 0) { + notification.setTitle("🚨 证书今天过期!"); + notification.setContent(String.format("您的《%s》证书今天已过期!请立即更新。", certificate.getCertName())); + } + // 移除过期多天的提醒 + } + /** + * 设置倒计时内容 + */ + private void setCountdownContent(VetNotification notification, VetCertificate certificate, long daysRemaining) { + notification.setTitle("⚠️ 证书还剩" + daysRemaining + "天过期"); + notification.setContent(String.format("您的《%s》证书还剩%d天过期,请及时更新。", certificate.getCertName(), daysRemaining)); + } + + /** + * 设置预过期内容 + */ + private void setPreExpireContent(VetNotification notification, VetCertificate certificate, long daysRemaining) { + String timeText = daysRemaining == 30 ? "30天" : "15天"; + notification.setTitle("📅 证书还剩" + timeText + "过期"); + notification.setContent(String.format("您的《%s》证书将在%s后过期,请提前准备更新。", certificate.getCertName(), timeText)); + } + + /** + * 判断是否需要发送提醒 + */ + private boolean shouldSendReminder(VetCertificate certificate, long daysRemaining) { + String status = certificate.getStatus(); + + 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 hasRecentReminder(VetCertificate certificate, long daysRemaining) { try { - vetCertificateService.checkAndSendCertificateReminders(); - /* log.info("每日证书检查任务执行完成");*/ + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + Date startOfDay = cal.getTime(); + + cal.add(Calendar.DAY_OF_MONTH, 1); + Date endOfDay = cal.getTime(); + + // 检查今天是否已发送 + VetNotification query = new VetNotification(); + query.setRelatedId(certificate.getId().toString()); + 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(certificate, daysRemaining); + + // 检查今天是否已有相同标题的通知 + boolean hasSameTitleToday = todayNotifications.stream() + .anyMatch(n -> expectedTitle.equals(n.getTitle())); + + if (hasSameTitleToday) { + // 如果今天已有相同标题的通知,跳过 + /*log.debug("今天已发送过相同提醒,跳过: 证书ID={}, 标题={}", + certificate.getId(), expectedTitle);*/ + 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) { + /*log.debug("最近7天内已发送过相同提醒,跳过: 证书ID={}", certificate.getId());*/ + return true; + } + } + + return false; } catch (Exception e) { - log.error("每日证书检查任务执行失败", e); + /*log.warn("检查近期提醒失败: {}", e.getMessage());*/ + return false; } } - /* *//** - * 每小时检查一次(可选,用于及时更新状态) - *//* - @Scheduled(cron = "0 0 * * * ?") - public void hourlyCertificateCheck() { - log.debug("执行每小时证书状态检查..."); + /** + * 生成预期的通知标题 + */ + private String generateExpectedTitle(VetCertificate certificate, long daysRemaining) { + if (daysRemaining <= 0) { + long daysExpired = -daysRemaining; + if (daysExpired == 0) { + return "🚨 证书今天过期!"; + } else { + return "🚨 证书已过期" + daysExpired + "天"; + } + } else if (daysRemaining <= 7) { + return "⚠️ 证书还剩" + daysRemaining + "天过期"; + } else if (daysRemaining == 15 || daysRemaining == 30) { + return "📅 证书还剩" + daysRemaining + "天过期"; + } else { + return ""; // 其他情况不发送 + } + } + + /** + * 更新证书状态 + */ + private void updateCertificateStatus(VetCertificate certificate, long daysRemaining) { try { - // 更新所有证书状态 - vetCertificateService.selectVetCertificateList(new VetCertificate()) - .forEach(cert -> { - // 这里可以调用更新状态的方法 - }); + String newStatus = daysRemaining <= 0 ? "2" : + daysRemaining <= 30 ? "1" : "0"; + + if (!newStatus.equals(certificate.getStatus())) { + certificate.setStatus(newStatus); + /*log.debug("更新证书状态: 证书ID={}, 新状态={}", certificate.getId(), newStatus);*/ + } } catch (Exception e) { - log.error("每小时证书检查失败", e); + /*log.warn("更新证书状态失败: {}", e.getMessage());*/ } - }*/ + } + + /** + * 计算天数差(忽略时间部分) + */ + private long calculateDayDifference(Date startDate, Date endDate) { + Calendar startCal = Calendar.getInstance(); + startCal.setTime(startDate); + resetTime(startCal); + + Calendar endCal = Calendar.getInstance(); + endCal.setTime(endDate); + resetTime(endCal); + + return (endCal.getTimeInMillis() - startCal.getTimeInMillis()) / (1000 * 60 * 60 * 24); + } + + /** + * 重置时间为00:00:00 + */ + private void resetTime(Calendar cal) { + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + } } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetKnowledge.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetKnowledge.java new file mode 100644 index 0000000..33cb0bf --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetKnowledge.java @@ -0,0 +1,117 @@ +package com.chenhai.vet.domain; + +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; + +/** + * 兽医文章对象 vet_knowledge + * + * @author ruoyi + * @date 2026-01-08 + */ +public class VetKnowledge extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键 */ + private Long id; + + /** 文章标题 */ + @Excel(name = "文章标题") + private String title; + + /** 文章内容 */ + @Excel(name = "文章内容") + private String content; + + /** 文章分类(治疗防治/饲养管理/其他) */ + @Excel(name = "文章分类", readConverterExp = "治=疗防治/饲养管理/其他") + private String category; + + /** 检测出的敏感词 */ + @Excel(name = "检测出的敏感词") + private String sensitiveWords; + + /** 状态(0-待审核 1-已发布 2-敏感内容驳回) */ + @Excel(name = "状态", readConverterExp = "0=-待审核,1=-已发布,2=-敏感内容驳回") + private String status; + + public void setId(Long id) + { + this.id = id; + } + + public Long getId() + { + return id; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + + public void setContent(String content) + { + this.content = content; + } + + public String getContent() + { + return content; + } + + public void setCategory(String category) + { + this.category = category; + } + + public String getCategory() + { + return category; + } + + public void setSensitiveWords(String sensitiveWords) + { + this.sensitiveWords = sensitiveWords; + } + + public String getSensitiveWords() + { + return sensitiveWords; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("title", getTitle()) + .append("content", getContent()) + .append("category", getCategory()) + .append("sensitiveWords", getSensitiveWords()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java index 92d5577..697ac6b 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetNotification.java @@ -33,7 +33,7 @@ public class VetNotification extends BaseEntity private String content; /** 通知类型 */ - @Excel(name = "通知类型") + @Excel(name = "通知类型" , dictType = "notification_type") private String type; /** 关联ID */ diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java index a0e6c18..fbcc4f4 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetQualification.java @@ -3,14 +3,19 @@ package com.chenhai.vet.domain; import com.chenhai.common.annotation.Excel; import com.chenhai.common.core.domain.BaseEntity; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +import java.util.Arrays; import java.util.Date; +import java.util.List; +import java.util.ArrayList; /** * 兽医资质对象 vet_qualification - * + * * @author ruoyi * @date 2025-12-26 */ @@ -23,7 +28,7 @@ public class VetQualification extends BaseEntity /** 兽医ID */ @Excel(name = "兽医ID") - private Long vetId; + private Long userId; /** 真实姓名 */ @Excel(name = "真实姓名") @@ -33,8 +38,8 @@ public class VetQualification extends BaseEntity @Excel(name = "身份证号") private String idCard; - /** 资质类型(veterinarian兽医资格证/pharmacist兽药师资格证) */ - @Excel(name = "资质类型", readConverterExp = "v=eterinarian兽医资格证/pharmacist兽药师资格证") + /** 资质类型 */ + @Excel(name = "资质类型", dictType = "qualification_type") private String qualificationType; /** 证书编号 */ @@ -56,7 +61,7 @@ public class VetQualification extends BaseEntity private Date auditTime; /** 审核状态(0待审核 1通过 2拒绝) */ - @Excel(name = "审核状态", readConverterExp = "0=待审核,1=通过,2=拒绝") + @Excel(name = "审核状态", dictType = "qualification_shenhe") private String auditStatus; /** 审核意见 */ @@ -67,142 +72,179 @@ public class VetQualification extends BaseEntity @Excel(name = "审核人ID") private Long auditorId; - /** 经营范围ID列表(逗号分隔) */ - @Excel(name = "经营范围ID") + /** 经营范围IDs(存储到数据库的逗号分隔字符串) */ private String scopeIds; /** 经营范围名称列表(逗号分隔) */ - @Excel(name = "经营范围名称") + @Excel(name = "经营范围名称", dictType = "scope_names") private String scopeNames; - public void setQualificationId(Long qualificationId) + private String qualificationTypeLabel; + private String auditStatusLabel; + private String scopeNamesLabel; + + // 从 JSON 反序列化时使用的方法 + @JsonProperty("scopeIds") + public void setScopeIdsFromJson(List scopeIdList) { + // 自动转换为逗号分隔的字符串 + if (scopeIdList != null && !scopeIdList.isEmpty()) { + this.scopeIds = String.join(",", scopeIdList); + } else { + this.scopeIds = null; + } + } + + // 序列化为 JSON 时使用的方法 + @JsonProperty("scopeIds") + public List getScopeIdsAsList() { + if (scopeIds != null && !scopeIds.trim().isEmpty()) { + return new ArrayList<>(Arrays.asList(scopeIds.split(","))); + } + return new ArrayList<>(); + } + + // 数据库操作的 getter(Jackson 忽略) + @JsonIgnore + public String getScopeIds() { + return scopeIds; + } + + // 数据库操作的 setter + public void setScopeIds(String scopeIds) { + this.scopeIds = scopeIds; + } + + // 为了方便,添加一个获取列表的方法(不映射到 JSON) + @JsonIgnore + public List getScopeIdList() { + return getScopeIdsAsList(); + } + + // 为了方便,添加一个设置列表的方法(不映射到 JSON) + public void setScopeIdList(List scopeIdList) { + setScopeIdsFromJson(scopeIdList); + } + + public void setQualificationId(Long qualificationId) { this.qualificationId = qualificationId; } - public Long getQualificationId() + public Long getQualificationId() { return qualificationId; } - public void setVetId(Long vetId) + public void setUserId(Long userId) { - this.vetId = vetId; + this.userId = userId; } - public Long getVetId() + public Long getUserId() { - return vetId; + return userId; } - public void setRealName(String realName) + public void setRealName(String realName) { this.realName = realName; } - public String getRealName() + public String getRealName() { return realName; } - public void setIdCard(String idCard) + public void setIdCard(String idCard) { this.idCard = idCard; } - public String getIdCard() + public String getIdCard() { return idCard; } - public void setQualificationType(String qualificationType) + public void setQualificationType(String qualificationType) { this.qualificationType = qualificationType; } - public String getQualificationType() + public String getQualificationType() { return qualificationType; } - public void setCertificateNo(String certificateNo) + public void setCertificateNo(String certificateNo) { this.certificateNo = certificateNo; } - public String getCertificateNo() + public String getCertificateNo() { return certificateNo; } - public void setCertificateFiles(String certificateFiles) + public void setCertificateFiles(String certificateFiles) { this.certificateFiles = certificateFiles; } - public String getCertificateFiles() + public String getCertificateFiles() { return certificateFiles; } - public void setApplyTime(Date applyTime) + public void setApplyTime(Date applyTime) { this.applyTime = applyTime; } - public Date getApplyTime() + public Date getApplyTime() { return applyTime; } - public void setAuditTime(Date auditTime) + public void setAuditTime(Date auditTime) { this.auditTime = auditTime; } - public Date getAuditTime() + public Date getAuditTime() { return auditTime; } - public void setAuditStatus(String auditStatus) + public void setAuditStatus(String auditStatus) { this.auditStatus = auditStatus; } - public String getAuditStatus() + public String getAuditStatus() { return auditStatus; } - public void setAuditOpinion(String auditOpinion) + public void setAuditOpinion(String auditOpinion) { this.auditOpinion = auditOpinion; } - public String getAuditOpinion() + public String getAuditOpinion() { return auditOpinion; } - public void setAuditorId(Long auditorId) + public void setAuditorId(Long auditorId) { this.auditorId = auditorId; } - public Long getAuditorId() + public Long getAuditorId() { return auditorId; } - public String getScopeIds() { - return scopeIds; - } - - public void setScopeIds(String scopeIds) { - this.scopeIds = scopeIds; - } - public String getScopeNames() { return scopeNames; } @@ -211,28 +253,52 @@ public class VetQualification extends BaseEntity this.scopeNames = scopeNames; } + public String getQualificationTypeLabel() { + return qualificationTypeLabel; + } + + public void setQualificationTypeLabel(String qualificationTypeLabel) { + this.qualificationTypeLabel = qualificationTypeLabel; + } + + public String getAuditStatusLabel() { + return auditStatusLabel; + } + + public void setAuditStatusLabel(String auditStatusLabel) { + this.auditStatusLabel = auditStatusLabel; + } + + public String getScopeNamesLabel() { + return scopeNamesLabel; + } + + public void setScopeNamesLabel(String scopeNamesLabel) { + this.scopeNamesLabel = scopeNamesLabel; + } + @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("qualificationId", getQualificationId()) - .append("vetId", getVetId()) - .append("realName", getRealName()) - .append("idCard", getIdCard()) - .append("qualificationType", getQualificationType()) - .append("certificateNo", getCertificateNo()) - .append("certificateFiles", getCertificateFiles()) - .append("applyTime", getApplyTime()) - .append("auditTime", getAuditTime()) - .append("auditStatus", getAuditStatus()) - .append("auditOpinion", getAuditOpinion()) - .append("auditorId", getAuditorId()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) + .append("qualificationId", getQualificationId()) + .append("userId", getUserId()) + .append("realName", getRealName()) + .append("idCard", getIdCard()) + .append("qualificationType", getQualificationType()) + .append("certificateNo", getCertificateNo()) + .append("certificateFiles", getCertificateFiles()) + .append("applyTime", getApplyTime()) + .append("auditTime", getAuditTime()) + .append("auditStatus", getAuditStatus()) + .append("auditOpinion", getAuditOpinion()) + .append("auditorId", getAuditorId()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) .append("scopeIds", getScopeIds()) .append("scopeNames", getScopeNames()) - .toString(); + .toString(); } -} +} \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/domain/VetTrainingVideo.java b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetTrainingVideo.java new file mode 100644 index 0000000..a7aaf47 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/domain/VetTrainingVideo.java @@ -0,0 +1,26 @@ +package com.chenhai.vet.domain; + +import lombok.Data; +import java.util.Date; + +@Data +public class VetTrainingVideo { + private Long id; + private Long userId; + private String title; + private String description; + private String videoUrl; + private String coverImage; + private String category; + private String tags; + private Integer duration; // 视频时长(秒) + private Long fileSize; // 文件大小(字节) + private Integer viewCount; + private String status; // 0-私有 1-公开 + private Date createTime; + private Date updateTime; + + // 非数据库字段 + private String userName; // 兽医姓名 + private String durationStr; // 格式化后的时长(如:12:30) +} \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetKnowledgeMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetKnowledgeMapper.java new file mode 100644 index 0000000..edbbe76 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetKnowledgeMapper.java @@ -0,0 +1,61 @@ +package com.chenhai.vet.mapper; + +import java.util.List; +import com.chenhai.vet.domain.VetKnowledge; + +/** + * 兽医文章Mapper接口 + * + * @author ruoyi + * @date 2026-01-08 + */ +public interface VetKnowledgeMapper +{ + /** + * 查询兽医文章 + * + * @param id 兽医文章主键 + * @return 兽医文章 + */ + public VetKnowledge selectVetKnowledgeById(Long id); + + /** + * 查询兽医文章列表 + * + * @param vetKnowledge 兽医文章 + * @return 兽医文章集合 + */ + public List selectVetKnowledgeList(VetKnowledge vetKnowledge); + + /** + * 新增兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + public int insertVetKnowledge(VetKnowledge vetKnowledge); + + /** + * 修改兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + public int updateVetKnowledge(VetKnowledge vetKnowledge); + + /** + * 删除兽医文章 + * + * @param id 兽医文章主键 + * @return 结果 + */ + public int deleteVetKnowledgeById(Long id); + + /** + * 批量删除兽医文章 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteVetKnowledgeByIds(Long[] ids); +} diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetNotificationMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetNotificationMapper.java index 7f8216b..14fb902 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetNotificationMapper.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetNotificationMapper.java @@ -4,7 +4,10 @@ package com.chenhai.vet.mapper; import com.chenhai.vet.domain.VetNotification; import org.apache.ibatis.annotations.Param; + +import java.util.Date; import java.util.List; +import java.util.Map; /** * 兽医通知Mapper接口 @@ -94,14 +97,6 @@ public interface VetNotificationMapper */ public int markAllNotificationsAsRead(Long userId); - /** - * 查询用户未读通知数量 - * - * @param userId 用户ID - * @return 未读通知数量 - */ - public Integer countUnreadNotificationsByUserId(Long userId); - /** * 批量插入通知 * @@ -110,13 +105,21 @@ public interface VetNotificationMapper */ public int batchInsertVetNotifications(@Param("list") List notifications); + + List selectVetNotificationByUserId(Long userId); + /** - * 清理过期通知 + * 获取用户通知统计(已读和未读数量) * - * @param days 过期天数 - * @return 清理数量 + * @param userId 用户ID + * @return 统计结果 */ - public int cleanExpiredNotifications(@Param("days") Integer days); + public Map selectNotificationStatsByUserId(Long userId); + + List selectNotificationsByDate( + @Param("userId") Long userId, + @Param("certificateId") Long certificateId, + @Param("date") Date date + ); - List selectVetNotificationByUserId(Long userId); } \ No newline at end of file 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 1f14477..906317b 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 @@ -2,6 +2,7 @@ package com.chenhai.vet.mapper; import com.chenhai.vet.domain.VetQualification; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Update; import java.util.List; @@ -62,5 +63,5 @@ public interface VetQualificationMapper */ public int deleteVetQualificationByQualificationIds(Long[] qualificationIds); - public int submitAudit(Long qualificationId); + public int submit(Long qualificationId); } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetTrainingVideoMapper.java b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetTrainingVideoMapper.java new file mode 100644 index 0000000..4171069 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/mapper/VetTrainingVideoMapper.java @@ -0,0 +1,28 @@ +package com.chenhai.vet.mapper; + +import com.chenhai.vet.domain.VetTrainingVideo; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +public interface VetTrainingVideoMapper { + + int insertVideo(VetTrainingVideo video); + + List selectMyVideos(@Param("userId") Long userId, + @Param("title") String title, + @Param("category") String category, + @Param("status") String status); + + List selectPublicVideos(@Param("title") String title, + @Param("category") String category, + @Param("userName") String userName); + + VetTrainingVideo selectVideoById(Long id); + + void incrementViewCount(Long id); + + List selectHotVideos(@Param("limit") Integer limit); + + List searchVideos(@Param("keyword") String keyword); + int deleteVideoById(@Param("id") Long id); +} \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetCertificateService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetCertificateService.java index c733031..1faf105 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetCertificateService.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetCertificateService.java @@ -63,4 +63,10 @@ public interface IVetCertificateService * 获取证书统计信息 */ Map getCertificateStatistics(Long userId); + + + + + + } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java new file mode 100644 index 0000000..4997780 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetKnowledgeService.java @@ -0,0 +1,74 @@ +package com.chenhai.vet.service; + +import java.util.List; + +import com.chenhai.common.core.domain.AjaxResult; +import com.chenhai.vet.domain.VetKnowledge; + +/** + * 兽医文章Service接口 + * + * @author ruoyi + * @date 2026-01-08 + */ +public interface IVetKnowledgeService +{ + /** + * 查询兽医文章 + * + * @param id 兽医文章主键 + * @return 兽医文章 + */ + public VetKnowledge selectVetKnowledgeById(Long id); + + /** + * 查询兽医文章列表 + * + * @param vetKnowledge 兽医文章 + * @return 兽医文章集合 + */ + public List selectVetKnowledgeList(VetKnowledge vetKnowledge); + + /** + * 新增兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + public int insertVetKnowledge(VetKnowledge vetKnowledge); + + /** + * 修改兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + public int updateVetKnowledge(VetKnowledge vetKnowledge); + + /** + * 批量删除兽医文章 + * + * @param ids 需要删除的兽医文章主键集合 + * @return 结果 + */ + public int deleteVetKnowledgeByIds(Long[] ids); + + /** + * 删除兽医文章信息 + * + * @param id 兽医文章主键 + * @return 结果 + */ + public int deleteVetKnowledgeById(Long id); + + /** + * 上传文章(待审核) + */ + AjaxResult uploadVetKnowledge(VetKnowledge vetKnowledge); + + /** + * 发布文章(更新状态为已发布) + */ + AjaxResult publishVetKnowledge(Long id); + +} 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 82ea1e3..28c594c 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 @@ -60,5 +60,4 @@ public interface IVetQualificationService */ public int deleteVetQualificationByQualificationId(Long qualificationId); - public int submitAudit(Long qualificationId); } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java new file mode 100644 index 0000000..f40b611 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/IVetTrainingVideoService.java @@ -0,0 +1,51 @@ +package com.chenhai.vet.service; + +import com.chenhai.vet.domain.VetTrainingVideo; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface IVetTrainingVideoService { + + /** + * 上传并保存视频 + */ + String uploadAndSave(VetTrainingVideo video, MultipartFile videoFile, MultipartFile coverImage); + + /** + * 获取我的视频列表 + */ + List getMyVideos(Long userId, String title, String category, String status); + + /** + * 获取公开视频列表 + */ + List getPublicVideos(String title, String category, String vetName); + + /** + * 获取视频详情(带权限校验) + */ + VetTrainingVideo getVideoDetail(Long videoId, Long currentVetId); + + /** + * 获取视频播放地址(带权限校验) + */ + String getVideoPlayUrl(Long videoId, Long currentVetId); + + /** + * 增加观看次数 + */ + void incrementViewCount(Long videoId); + + /** + * 获取热门视频 + */ + List getHotVideos(Integer limit); + + /** + * 搜索视频 + */ + List searchVideos(String keyword); + + int deleteVideoById(Long videoId); +} \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/VetNotificationService.java b/chenhai-system/src/main/java/com/chenhai/vet/service/VetNotificationService.java index 3606cb1..7a65796 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/VetNotificationService.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/VetNotificationService.java @@ -4,6 +4,7 @@ package com.chenhai.vet.service; import com.chenhai.vet.domain.VetCertificate; import com.chenhai.vet.domain.VetNotification; import java.util.List; +import java.util.Map; public interface VetNotificationService { @@ -42,11 +43,6 @@ public interface VetNotificationService { */ List getNotificationsByUserId(Long userId); - /** - * 获取未读通知数量 - */ - int getUnreadCount(Long userId); - /** * 发送证书过期提醒通知 */ @@ -57,10 +53,9 @@ public interface VetNotificationService { */ boolean markAsRead(Long notificationId); - /** - * 标记所有通知为已读 - */ - boolean markAllAsRead(Long userId); - List selectByUserId(Long userId); + + Map getNotificationStats(Long userId); + + } diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCertificateServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCertificateServiceImpl.java index 184ae7e..a93936b 100644 --- a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCertificateServiceImpl.java +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetCertificateServiceImpl.java @@ -344,4 +344,6 @@ public class VetCertificateServiceImpl implements IVetCertificateService return statistics; } + + } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java new file mode 100644 index 0000000..83e285c --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java @@ -0,0 +1,134 @@ +package com.chenhai.vet.service.impl; + +import java.util.List; + +import com.chenhai.common.core.domain.AjaxResult; +import com.chenhai.common.utils.DateUtils; +import com.chenhai.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.chenhai.vet.mapper.VetKnowledgeMapper; +import com.chenhai.vet.domain.VetKnowledge; +import com.chenhai.vet.service.IVetKnowledgeService; + +/** + * 兽医文章Service业务层处理 + * + * @author ruoyi + * @date 2026-01-08 + */ +@Service +public class VetKnowledgeServiceImpl implements IVetKnowledgeService +{ + @Autowired + private VetKnowledgeMapper vetKnowledgeMapper; + + /** + * 查询兽医文章 + * + * @param id 兽医文章主键 + * @return 兽医文章 + */ + @Override + public VetKnowledge selectVetKnowledgeById(Long id) + { + return vetKnowledgeMapper.selectVetKnowledgeById(id); + } + + /** + * 查询兽医文章列表 + * + * @param vetKnowledge 兽医文章 + * @return 兽医文章 + */ + @Override + public List selectVetKnowledgeList(VetKnowledge vetKnowledge) + { + return vetKnowledgeMapper.selectVetKnowledgeList(vetKnowledge); + } + + /** + * 新增兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + @Override + public int insertVetKnowledge(VetKnowledge vetKnowledge) + { + vetKnowledge.setCreateTime(DateUtils.getNowDate()); + return vetKnowledgeMapper.insertVetKnowledge(vetKnowledge); + } + + /** + * 修改兽医文章 + * + * @param vetKnowledge 兽医文章 + * @return 结果 + */ + @Override + public int updateVetKnowledge(VetKnowledge vetKnowledge) + { + vetKnowledge.setUpdateTime(DateUtils.getNowDate()); + return vetKnowledgeMapper.updateVetKnowledge(vetKnowledge); + } + + /** + * 批量删除兽医文章 + * + * @param ids 需要删除的兽医文章主键 + * @return 结果 + */ + @Override + public int deleteVetKnowledgeByIds(Long[] ids) + { + return vetKnowledgeMapper.deleteVetKnowledgeByIds(ids); + } + + /** + * 删除兽医文章信息 + * + * @param id 兽医文章主键 + * @return 结果 + */ + @Override + public int deleteVetKnowledgeById(Long id) + { + return vetKnowledgeMapper.deleteVetKnowledgeById(id); + } + + /** + * 上传文章:默认状态为0-待审核 + */ + @Override + public AjaxResult uploadVetKnowledge(VetKnowledge vetKnowledge) { + // 填充基础信息 + vetKnowledge.setCreateBy(SecurityUtils.getUsername()); + vetKnowledge.setCreateTime(DateUtils.getNowDate()); + vetKnowledge.setStatus("0"); // 固定为待审核 + + int result = vetKnowledgeMapper.insertVetKnowledge(vetKnowledge); + if (result > 0) { + return AjaxResult.success("文章上传成功,等待审核"); + } + return AjaxResult.error("文章上传失败"); + } + + /** + * 发布文章:更新状态为1-已发布 + */ + @Override + public AjaxResult publishVetKnowledge(Long id) { + VetKnowledge vetKnowledge = new VetKnowledge(); + vetKnowledge.setId(id); + vetKnowledge.setStatus("1"); // 已发布 + vetKnowledge.setUpdateBy(SecurityUtils.getUsername()); + vetKnowledge.setUpdateTime(DateUtils.getNowDate()); + + int result = vetKnowledgeMapper.updateVetKnowledge(vetKnowledge); + if (result > 0) { + return AjaxResult.success("文章发布成功"); + } + return AjaxResult.error("文章发布失败"); + } +} 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 657286f..7889b07 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 @@ -13,6 +13,7 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Map; @Service @RequiredArgsConstructor @@ -59,57 +60,14 @@ public class VetNotificationServiceImpl implements VetNotificationService { } @Override - public int getUnreadCount(Long userId) { - VetNotification query = new VetNotification(); - query.setUserId(userId); - query.setIsRead(0); - List list = vetNotificationMapper.selectVetNotificationList(query); - return list != null ? list.size() : 0; + public void sendCertificateExpireRemind(VetCertificate certificate) { + log.info("证书提醒记录: 证书ID={}, 名称={}, 过期时间={}", + certificate.getId(), certificate.getCertName(), + formatDate(certificate.getExpireDate())); } - @Override - public void sendCertificateExpireRemind(VetCertificate certificate) { - if (certificate == null || certificate.getExpireDate() == null) { - return; - } - Date now = new Date(); - Date expireDate = certificate.getExpireDate(); - - // 计算距离过期的天数 - long daysBetween = calculateDayDifference(now, expireDate); - - VetNotification notification = new VetNotification(); - notification.setUserId(certificate.getUserId()); - notification.setRelatedId(certificate.getId().toString()); - notification.setType("CERT_EXPIRE_REMIND"); - notification.setIsRead(0); - notification.setCreateTime(now); // 直接使用 Date - - if (daysBetween <= 0) { - notification.setTitle(" ⚠️ 证书已过期"); - notification.setContent(String.format("您的《%s》证书已于%s过期!请立即更新证书以继续提供服务。", - certificate.getCertName(), formatDate(expireDate))); - notification.setRemindLevel(3); - } else if (daysBetween <= 7) { - notification.setTitle("⚠️ 证书即将过期(7天内)"); - notification.setContent(String.format("您的《%s》证书将在%d天后过期,请尽快完成更新!", - certificate.getCertName(), daysBetween)); - notification.setRemindLevel(3); - } else if (daysBetween <= 30) { - notification.setTitle("⚠️ 证书即将过期(30天内)"); - notification.setContent(String.format("您的《%s》证书将在%d天后过期,请及时安排更新。", - certificate.getCertName(), daysBetween)); - notification.setRemindLevel(2); - } else { - // 超过30天,不发送常规提醒 - return; - } - vetNotificationMapper.insertVetNotification(notification); - log.info("发送证书提醒通知:用户ID={}, 证书ID={}, 天数={}", - certificate.getUserId(), certificate.getId(), daysBetween); - } @Override public boolean markAsRead(Long notificationId) { @@ -123,21 +81,6 @@ public class VetNotificationServiceImpl implements VetNotificationService { return false; } - @Override - public boolean markAllAsRead(Long userId) { - List unreadNotifications = getNotificationsByUserId(userId); - int count = 0; - for (VetNotification notification : unreadNotifications) { - if (notification.getIsRead() == 0) { - notification.setIsRead(1); - notification.setReadTime(new Date()); - vetNotificationMapper.updateVetNotification(notification); - count++; - } - } - log.info("标记所有通知为已读:用户ID={}, 标记数量={}", userId, count); - return count > 0; - } /** * 计算两个日期之间的天数差(忽略时间部分) @@ -180,4 +123,15 @@ public class VetNotificationServiceImpl implements VetNotificationService { public List selectByUserId(Long userId) { return vetNotificationMapper.selectVetNotificationByUserId(userId); } + + @Override + public Map getNotificationStats(Long userId) { + // 查询统计信息 + Map stats = vetNotificationMapper.selectNotificationStatsByUserId(userId); + + return Map.of( + "unread", ((Number) stats.getOrDefault("unread", 0)).intValue(), + "read", ((Number) stats.getOrDefault("read", 0)).intValue() + ); + } } \ No newline at end of file diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetQualificationServiceImpl.java index bf707fd..0d71667 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 @@ -1,30 +1,24 @@ package com.chenhai.vet.service.impl; -import com.chenhai.common.utils.DateUtils; +import com.chenhai.common.utils.StringUtils; import com.chenhai.vet.domain.VetQualification; import com.chenhai.vet.mapper.VetQualificationMapper; import com.chenhai.vet.service.IVetQualificationService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Date; import java.util.List; -import com.chenhai.vet.domain.BusinessScopeConstants; - -/** - * 兽医资质Service业务层处理 - * - * @author ruoyi - * @date 2025-12-26 - */ @Service -public class VetQualificationServiceImpl implements IVetQualificationService -{ +public class VetQualificationServiceImpl implements IVetQualificationService { @Autowired private VetQualificationMapper vetQualificationMapper; - + // 修复2:给JdbcTemplate加注入注解 + @Autowired + private JdbcTemplate jdbcTemplate; /** @@ -33,79 +27,85 @@ public class VetQualificationServiceImpl implements IVetQualificationService @Override public List selectVetQualificationList(VetQualification vetQualification) { List list = vetQualificationMapper.selectVetQualificationList(vetQualification); - - // 处理经营范围名称(如果数据库中没有存储scope_names) + // 处理经营范围名称(scope_ids转scope_names) for (VetQualification qualification : list) { - if (qualification.getScopeIds() != null && !qualification.getScopeIds().isEmpty() - && (qualification.getScopeNames() == null || qualification.getScopeNames().isEmpty())) { - - // 处理经营范围名称 - processScopeNames(qualification); + if ((qualification.getScopeNames() == null || qualification.getScopeNames().isEmpty()) + && qualification.getScopeIds() != null && !qualification.getScopeIds().isEmpty()) { + String scopeNames = getScopeNamesFromDict(qualification.getScopeIds()); + qualification.setScopeNames(scopeNames); } } return list; } + /** - * 处理经营范围名称 + * 从字典表根据scope_ids获取scope_names */ - private void processScopeNames(VetQualification qualification) { - if (qualification.getScopeIds() != null && !qualification.getScopeIds().isEmpty()) { - String[] scopeIds = qualification.getScopeIds().split(","); - List scopeNames = new ArrayList<>(); - for (String scopeId : scopeIds) { - String name = BusinessScopeConstants.getScopeName(scopeId.trim()); - if (name != null) { - scopeNames.add(name); - } - } - if (!scopeNames.isEmpty()) { - qualification.setScopeNames(String.join(",", scopeNames)); + private String getScopeNamesFromDict(String scopeIds) { + if (scopeIds == null || scopeIds.isEmpty()) { + return ""; + } + String[] idArray = scopeIds.split(","); + List cleanedIds = new ArrayList<>(); + for (String id : idArray) { + cleanedIds.add("'" + id.trim() + "'"); + } + String inCondition = String.join(",", cleanedIds); + + String sql = "SELECT dict_label FROM sys_dict_data " + + "WHERE dict_type = 'business_scope' " + + "AND dict_value IN (" + inCondition + ") " + + "AND status = '0' " + + "ORDER BY FIND_IN_SET(dict_value, ?)"; + + List names = jdbcTemplate.query(sql, + (rs, rowNum) -> rs.getString("dict_label"), + scopeIds); + + return String.join(",", names); + } + + /** + * 处理资质文件路径 + */ + private String processCertificateFiles(String certificateFilesJson) { + try { + if (StringUtils.isEmpty(certificateFilesJson)) { + return ""; } + + // 如果certificateFiles是JSON数组字符串,这里可以根据需要处理 + // 简单处理:直接存储为字符串,或解析JSON后存储 + return certificateFilesJson; + } catch (Exception e) { + return certificateFilesJson; } } /** * 查询兽医资质 - * - * @param qualificationId 兽医资质主键 - * @return 兽医资质 */ @Override - public VetQualification selectVetQualificationByQualificationId(Long qualificationId) - { + public VetQualification selectVetQualificationByQualificationId(Long qualificationId) { return vetQualificationMapper.selectVetQualificationByQualificationId(qualificationId); } - /** - * 查询兽医资质列表 - * - * @param vetQualification 兽医资质 - * @return 兽医资质 - */ - /*@Override - public List selectVetQualificationList(VetQualification vetQualification) - { - return vetQualificationMapper.selectVetQualificationList(vetQualification); - } -*/ /** * 新增兽医资质 - * - * @param vetQualification 兽医资质 - * @return 结果 */ @Override - public int insertVetQualification(VetQualification vetQualification) - { - // 确保审核状态默认为"2"(未提交) + public int insertVetQualification(VetQualification vetQualification) { if (vetQualification.getAuditStatus() == null) { vetQualification.setAuditStatus("2"); } + if (vetQualification.getCertificateFiles() == null || + vetQualification.getCertificateFiles().isEmpty()) { + vetQualification.setCertificateFiles("default.pdf"); // 默认值 + } - // 如果传入了scopeIds但未设置scopeNames,自动处理 - if (vetQualification.getScopeIds() != null && !vetQualification.getScopeIds().isEmpty() - && (vetQualification.getScopeNames() == null || vetQualification.getScopeNames().isEmpty())) { - processScopeNames(vetQualification); + if (vetQualification.getScopeIds() != null && !vetQualification.getScopeIds().isEmpty()) { + String scopeNames = getScopeNamesFromDict(vetQualification.getScopeIds()); + vetQualification.setScopeNames(scopeNames); } return vetQualificationMapper.insertVetQualification(vetQualification); @@ -113,47 +113,71 @@ public class VetQualificationServiceImpl implements IVetQualificationService /** * 修改兽医资质 - * - * @param vetQualification 兽医资质 - * @return 结果 */ @Override - public int updateVetQualification(VetQualification vetQualification) - { - vetQualification.setUpdateTime(DateUtils.getNowDate()); + public int updateVetQualification(VetQualification vetQualification) { + // 处理资质文件路径 + if (vetQualification.getCertificateFiles() != null) { + vetQualification.setCertificateFiles(processCertificateFiles(vetQualification.getCertificateFiles())); + } + + if (vetQualification.getScopeIds() != null) { + String scopeNames = getScopeNamesFromDict(vetQualification.getScopeIds()); + vetQualification.setScopeNames(scopeNames); + } + return vetQualificationMapper.updateVetQualification(vetQualification); } /** * 批量删除兽医资质 - * - * @param qualificationIds 需要删除的兽医资质主键 - * @return 结果 */ @Override - public int deleteVetQualificationByQualificationIds(Long[] qualificationIds) - { + public int deleteVetQualificationByQualificationIds(Long[] qualificationIds) { return vetQualificationMapper.deleteVetQualificationByQualificationIds(qualificationIds); } /** * 删除兽医资质信息 - * - * @param qualificationId 兽医资质主键 - * @return 结果 */ @Override - public int deleteVetQualificationByQualificationId(Long qualificationId) - { + public int deleteVetQualificationByQualificationId(Long qualificationId) { return vetQualificationMapper.deleteVetQualificationByQualificationId(qualificationId); } - @Override - public int submitAudit(Long qualificationId) { - VetQualification vetQualification = new VetQualification(); - vetQualification.setQualificationId(qualificationId); - vetQualification.setAuditStatus("0"); // 待审核 - vetQualification.setApplyTime(new Date()); - return vetQualificationMapper.updateVetQualification(vetQualification); + private void createCertificateFromQualification(VetQualification qualification) { + try { + // 检查是否已存在证书 + String checkSql = "SELECT COUNT(*) FROM vet_certificate WHERE qualification_id = ?"; + Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, + qualification.getQualificationId()); + + if (count != null && count > 0) { + System.out.println("资质ID " + qualification.getQualificationId() + " 已存在证书,跳过创建"); + return; + } + + + String sql = "INSERT INTO vet_certificate (" + + "user_id, cert_number, " + + "create_by, create_time, " + + "qualification_id" + + ") VALUES (?, ?, ?, NOW(), ?)"; + + jdbcTemplate.update(sql, + qualification.getUserId(), + qualification.getCertificateNo(), + qualification.getCreateBy(), + qualification.getQualificationId() + ); + + System.out.println("✅ 审核通过,已创建证书编号:" + qualification.getCertificateNo()); + System.out.println("ℹ️ 证书名称、类型、发证机构等信息请在证书管理页面完善"); + + } catch (Exception e) { + System.err.println("❌ 创建证书失败:" + e.getMessage()); + e.printStackTrace(); + } } } + diff --git a/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java new file mode 100644 index 0000000..ab531d4 --- /dev/null +++ b/chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetTrainingVideoServiceImpl.java @@ -0,0 +1,146 @@ +package com.chenhai.vet.service.impl; + +import com.chenhai.vet.domain.VetTrainingVideo; +import com.chenhai.vet.mapper.VetTrainingVideoMapper; +import com.chenhai.vet.service.IVetTrainingVideoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Service +public class VetTrainingVideoServiceImpl implements IVetTrainingVideoService { + + @Autowired + private VetTrainingVideoMapper videoMapper; + + @Value("${file.upload.path:/uploads}") + private String uploadPath; + + @Override + public String uploadAndSave(VetTrainingVideo video, MultipartFile videoFile, MultipartFile coverImage) { + try { + // 1. 创建上传目录 + File uploadDir = new File(uploadPath); + if (!uploadDir.exists()) { + uploadDir.mkdirs(); + } + + // 2. 生成唯一文件名 + String originalFileName = videoFile.getOriginalFilename(); + String fileExtension = getFileExtension(originalFileName); + String uniqueFileName = UUID.randomUUID().toString() + "." + fileExtension; + + // 3. 保存视频文件 + Path videoPath = Paths.get(uploadPath, uniqueFileName); + Files.write(videoPath, videoFile.getBytes()); + + // 4. 保存封面图(如果有) + String coverImageUrl = null; + if (coverImage != null && !coverImage.isEmpty()) { + String coverExtension = getFileExtension(coverImage.getOriginalFilename()); + String coverFileName = "cover_" + UUID.randomUUID().toString() + "." + coverExtension; + Path coverPath = Paths.get(uploadPath, coverFileName); + Files.write(coverPath, coverImage.getBytes()); + coverImageUrl = "/uploads/" + coverFileName; + } + + // 5. 计算视频时长和大小 + int duration = getVideoDuration(videoFile); // 需要实现这个方法 + long fileSize = videoFile.getSize(); + + // 6. 保存到数据库 + video.setVideoUrl("/uploads/" + uniqueFileName); + video.setCoverImage(coverImageUrl); + video.setDuration(duration); + video.setFileSize(fileSize); + video.setViewCount(0); + video.setCreateTime(new Date()); + video.setUpdateTime(new Date()); + + videoMapper.insertVideo(video); + + return "上传成功!视频ID:" + video.getId(); + + } catch (IOException e) { + throw new RuntimeException("文件保存失败", e); + } + } + + @Override + public List getMyVideos(Long userId, String title, String category, String status) { + return videoMapper.selectMyVideos(userId, title, category, status); + } + + @Override + public List getPublicVideos(String title, String category, String vetName) { + return videoMapper.selectPublicVideos(title, category, vetName); + } + + @Override + public VetTrainingVideo getVideoDetail(Long videoId, Long currentVetId) { + VetTrainingVideo video = videoMapper.selectVideoById(videoId); + + if (video == null) { + return null; + } + + // 权限校验:只能查看公开视频或自己的视频 + boolean canView = "1".equals(video.getStatus()) || currentVetId.equals(video.getUserId()); + return canView ? video : null; + } + + @Override + public String getVideoPlayUrl(Long videoId, Long currentVetId) { + VetTrainingVideo video = videoMapper.selectVideoById(videoId); + + if (video == null) { + return null; + } + + // 权限校验 + boolean canPlay = "1".equals(video.getStatus()) || currentVetId.equals(video.getUserId()); + return canPlay ? video.getVideoUrl() : null; + } + + @Override + public void incrementViewCount(Long videoId) { + videoMapper.incrementViewCount(videoId); + } + + @Override + public List getHotVideos(Integer limit) { + return videoMapper.selectHotVideos(limit); + } + + @Override + public List searchVideos(String keyword) { + return videoMapper.searchVideos(keyword); + } + + private String getFileExtension(String fileName) { + return fileName.substring(fileName.lastIndexOf(".") + 1); + } + + private int getVideoDuration(MultipartFile videoFile) { + // 这里需要实现获取视频时长的方法 + // 可以使用 FFmpeg 或 Java 的库来获取 + // 暂时返回一个默认值 + return 60; // 默认60秒 + } + + @Override + public int deleteVideoById(Long videoId) { + // 逻辑删除,设置 del_flag = '1' + return videoMapper.deleteVideoById(videoId); + } +} \ No newline at end of file diff --git a/chenhai-system/src/main/resources/mapper/vet/VetKnowledgeMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetKnowledgeMapper.xml new file mode 100644 index 0000000..bbfaef6 --- /dev/null +++ b/chenhai-system/src/main/resources/mapper/vet/VetKnowledgeMapper.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + select id, title, content, category, sensitive_words, status, create_by, create_time, update_by, update_time, remark from vet_knowledge + + + + + + + + insert into vet_knowledge + + title, + content, + category, + sensitive_words, + status, + create_by, + create_time, + update_by, + update_time, + remark, + + + #{title}, + #{content}, + #{category}, + #{sensitiveWords}, + #{status}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{remark}, + + + + + update vet_knowledge + + title = #{title}, + content = #{content}, + category = #{category}, + sensitive_words = #{sensitiveWords}, + status = #{status}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + remark = #{remark}, + + where id = #{id} + + + + delete from vet_knowledge where id = #{id} + + + + delete from vet_knowledge where id in + + #{id} + + + \ No newline at end of file diff --git a/chenhai-system/src/main/resources/mapper/vet/VetNotificationMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetNotificationMapper.xml index ccaba6d..6a8442c 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetNotificationMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetNotificationMapper.xml @@ -76,12 +76,6 @@ order by create_time desc - insert into vet_notification @@ -158,32 +152,6 @@ and is_read = 0 - - - - - - - - - - delete from vet_notification where id = #{id} @@ -194,4 +162,23 @@ #{id} + + + + + \ No newline at end of file diff --git a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml index 15c1267..46855f5 100644 --- a/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml +++ b/chenhai-system/src/main/resources/mapper/vet/VetQualificationMapper.xml @@ -6,10 +6,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + + @@ -26,14 +27,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - + + + select + vq.*, + + sd1.dict_label as qualification_type_label, + + + vq.scope_names as scope_names + from vet_qualification vq + left join sys_dict_data sd1 on sd1.dict_value = vq.qualification_type + and sd1.dict_type = 'qualification_type' + + SELECT v.*, u.nick_name as user_name + FROM vet_training_video v + LEFT JOIN sys_user u ON v.user_id = u.user_id + WHERE v.user_id = #{userId} + + AND v.title LIKE CONCAT('%', #{title}, '%') + + + AND v.category = #{category} + + + AND v.status = #{status} + + ORDER BY v.create_time DESC + + + + + + + + UPDATE vet_training_video + SET view_count = view_count + 1 + WHERE id = #{id} + + + + + + + + UPDATE vet_training_video + SET del_flag = '1' + WHERE id = #{id} + + \ No newline at end of file diff --git a/chenhai-ui/package.json b/chenhai-ui/package.json index a2212d3..d113430 100644 --- a/chenhai-ui/package.json +++ b/chenhai-ui/package.json @@ -29,7 +29,7 @@ "clipboard": "2.0.8", "core-js": "3.37.1", "echarts": "5.4.0", - "element-ui": "2.15.14", + "element-ui": "^2.15.14", "file-saver": "2.0.5", "fuse.js": "6.4.3", "highlight.js": "9.18.5", @@ -41,7 +41,7 @@ "screenfull": "5.0.2", "sortablejs": "1.10.2", "splitpanes": "2.4.1", - "vue": "2.6.12", + "vue": "^2.6.12", "vue-count-to": "1.0.13", "vue-cropper": "0.5.5", "vue-router": "3.4.9", diff --git a/chenhai-ui/src/api/vet/knowledge.js b/chenhai-ui/src/api/vet/knowledge.js new file mode 100644 index 0000000..f85a202 --- /dev/null +++ b/chenhai-ui/src/api/vet/knowledge.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询兽医文章列表 +export function listKnowledge(query) { + return request({ + url: '/vet/knowledge/list', + method: 'get', + params: query + }) +} + +// 查询兽医文章详细 +export function getKnowledge(id) { + return request({ + url: '/vet/knowledge/' + id, + method: 'get' + }) +} + +// 新增兽医文章 +export function addKnowledge(data) { + return request({ + url: '/vet/knowledge', + method: 'post', + data: data + }) +} + +// 修改兽医文章 +export function updateKnowledge(data) { + return request({ + url: '/vet/knowledge', + method: 'put', + data: data + }) +} + +// 删除兽医文章 +export function delKnowledge(id) { + return request({ + url: '/vet/knowledge/' + id, + method: 'delete' + }) +} +// 上传文章(待审核) +export function uploadKnowledge(data) { + return request({ + url: '/vet/knowledge/upload', + method: 'post', + data: data + }) +} + +// 发布文章 +export function publishKnowledge(id) { + return request({ + url: '/vet/knowledge/publish/' + id, + method: 'put' + }) +} diff --git a/chenhai-ui/src/api/vet/training.js b/chenhai-ui/src/api/vet/training.js new file mode 100644 index 0000000..10d1ee3 --- /dev/null +++ b/chenhai-ui/src/api/vet/training.js @@ -0,0 +1,95 @@ +// src/api/vet/training.js +import request from '@/utils/request' + +// 兽医培训视频相关接口 +export default { + // 上传视频 + uploadVideo(data) { + const formData = new FormData() + Object.keys(data).forEach(key => { + if (data[key] !== undefined && data[key] !== null) { + if (key === 'videoFile' || key === 'coverImage') { + formData.append(key, data[key]) + } else { + formData.append(key, data[key]) + } + } + }) + + return request({ + url: '/vet/training/upload', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + }, + timeout: 300000 // 5分钟超时,视频上传需要时间 + }) + }, + + // 获取公开视频列表 + getPublicVideos(params) { + return request({ + url: '/vet/training/public-videos', + method: 'get', + params + }) + }, + + // 获取我的视频 + getMyVideos(params = {}) { + return request({ + url: '/vet/training/my-videos', + method: 'get', + params: { + pageNum: params.pageNum || 1, + pageSize: params.pageSize || 10, + title: params.title || '', + category: params.category || '', + status: params.status || '' + } + }) + }, + + // 获取视频详情 + getVideoDetail(id) { + return request({ + url: `/vet/training/video/${id}`, + method: 'get' + }) + }, + + // 获取播放地址(可选) + getPlayUrl(id) { + return request({ + url: `/vet/training/video/play/${id}`, + method: 'get' + }) + }, + + // 删除视频 + deleteVideo(id) { + return request({ + url: `/vet/training/${id}`, + method: 'delete' + }) + }, + + // 搜索视频 + searchVideos(keyword) { + return request({ + url: '/vet/training/search', + method: 'get', + params: { keyword } + }) + }, + + // 获取热门视频 + getHotVideos(limit = 10) { + return request({ + url: '/vet/training/hot-videos', + method: 'get', + params: { limit } + }) + } +} diff --git a/chenhai-ui/src/views/vet/certificate/index.vue b/chenhai-ui/src/views/vet/certificate/index.vue index c321c7d..8796977 100644 --- a/chenhai-ui/src/views/vet/certificate/index.vue +++ b/chenhai-ui/src/views/vet/certificate/index.vue @@ -299,11 +299,11 @@ export default { /** 查询兽医执业证书列表 */ getList() { this.loading = false - // listCertificate(this.queryParams).then(response => { - // this.certificateList = response.rows - // this.total = response.total - // this.loading = false - // }) + listCertificate(this.queryParams).then(response => { + this.certificateList = response.rows + this.total = response.total + this.loading = false + }) }, // 取消按钮 cancel() { diff --git a/chenhai-ui/src/views/vet/knowledge/index.vue b/chenhai-ui/src/views/vet/knowledge/index.vue new file mode 100644 index 0000000..a924fa5 --- /dev/null +++ b/chenhai-ui/src/views/vet/knowledge/index.vue @@ -0,0 +1,356 @@ + + + diff --git a/chenhai-ui/src/views/vet/training/TrainingHome.vue b/chenhai-ui/src/views/vet/training/TrainingHome.vue new file mode 100644 index 0000000..2dac1d3 --- /dev/null +++ b/chenhai-ui/src/views/vet/training/TrainingHome.vue @@ -0,0 +1,960 @@ + + + + + +