init
This commit is contained in:
18
src/main/java/com/example/SpringbootApplication.java
Normal file
18
src/main/java/com/example/SpringbootApplication.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.example;
|
||||
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.example.mapper")
|
||||
@EnableScheduling
|
||||
public class SpringbootApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringbootApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
9
src/main/java/com/example/common/Constants.java
Normal file
9
src/main/java/com/example/common/Constants.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.example.common;
|
||||
|
||||
public interface Constants {
|
||||
|
||||
String TOKEN = "token";
|
||||
|
||||
String USER_DEFAULT_PASSWORD = "123456";
|
||||
|
||||
}
|
||||
72
src/main/java/com/example/common/Result.java
Normal file
72
src/main/java/com/example/common/Result.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.example.common;
|
||||
|
||||
public class Result {
|
||||
private String code;
|
||||
private String msg;
|
||||
private Object data;
|
||||
|
||||
private Result(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
public static Result success() {
|
||||
Result result = new Result();
|
||||
result.setCode("200");
|
||||
result.setMsg("请求成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result success(Object data) {
|
||||
Result result = success();
|
||||
result.setData(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error() {
|
||||
Result result = new Result();
|
||||
result.setCode("500");
|
||||
result.setMsg("请求失败");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error(String code, String msg) {
|
||||
Result result = new Result();
|
||||
result.setCode(code);
|
||||
result.setMsg(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Result error(String msg) {
|
||||
Result result = new Result();
|
||||
result.setCode("500");
|
||||
result.setMsg(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
25
src/main/java/com/example/common/config/CorsConfig.java
Normal file
25
src/main/java/com/example/common/config/CorsConfig.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.example.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
|
||||
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
|
||||
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
|
||||
source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
82
src/main/java/com/example/common/config/JwtInterceptor.java
Normal file
82
src/main/java/com/example/common/config/JwtInterceptor.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package com.example.common.config;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.example.common.Constants;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.*;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.service.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
/**
|
||||
* jwt拦截器
|
||||
*/
|
||||
@Component
|
||||
public class JwtInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(JwtInterceptor.class);
|
||||
|
||||
@Resource
|
||||
private AdminService adminService;
|
||||
@Resource
|
||||
private DoctorService doctorService;
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
// 1. 从http请求的header中获取token
|
||||
String token = request.getHeader(Constants.TOKEN);
|
||||
if (ObjectUtil.isEmpty(token)) {
|
||||
// 如果没拿到,从参数里再拿一次
|
||||
token = request.getParameter(Constants.TOKEN);
|
||||
}
|
||||
// 2. 开始执行认证
|
||||
if (ObjectUtil.isEmpty(token)) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
Account account = null;
|
||||
try {
|
||||
// 解析token获取存储的数据
|
||||
String userRole = JWT.decode(token).getAudience().get(0);
|
||||
String userId = userRole.split("-")[0];
|
||||
String role = userRole.split("-")[1];
|
||||
// 根据userId查询数据库
|
||||
if ("admin".equals(role)) {
|
||||
account = adminService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
if ("doctor".equals(role)) {
|
||||
account = doctorService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
if ("patient".equals(role)) {
|
||||
account = patientService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
if (ObjectUtil.isNull(account)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
try {
|
||||
// 用户密码加签验证 token
|
||||
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build();
|
||||
jwtVerifier.verify(token); // 验证token
|
||||
} catch (JWTVerificationException e) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
88
src/main/java/com/example/common/config/TokenUtils.java
Normal file
88
src/main/java/com/example/common/config/TokenUtils.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package com.example.common.config;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.example.entity.Account;
|
||||
import com.example.service.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class TokenUtils {
|
||||
|
||||
private static AdminService staticAdminService;
|
||||
private static DoctorService staticDoctorService;
|
||||
private static PatientService staticPatientService;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TokenUtils.class);
|
||||
|
||||
@Resource
|
||||
private AdminService adminService;
|
||||
@Resource
|
||||
private DoctorService doctorService;
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
@PostConstruct
|
||||
public void setUserService() {
|
||||
staticAdminService = adminService;
|
||||
staticDoctorService = doctorService;
|
||||
staticPatientService = patientService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
*/
|
||||
public static String genToken(String userRole, String password) {
|
||||
return JWT.create().withAudience(userRole) // 将 userId-role 保存到 token 里面,作为载荷
|
||||
.withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期
|
||||
.sign(Algorithm.HMAC256(password)); // 以 password 作为 token 的密钥
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户信息
|
||||
*/
|
||||
public static Account getCurrentUser() {
|
||||
String token = null;
|
||||
try {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
token = request.getHeader("token");
|
||||
if (StrUtil.isBlank(token)) {
|
||||
token = request.getParameter("token");
|
||||
}
|
||||
if (StrUtil.isBlank(token)) {
|
||||
log.error("获取当前登录的token失败, token: {}", token);
|
||||
return null;
|
||||
}
|
||||
// 解析token,获取用户的id
|
||||
String userRole = JWT.decode(token).getAudience().get(0);
|
||||
String userId = userRole.split("-")[0];
|
||||
String role = userRole.split("-")[1];
|
||||
Account account = null;
|
||||
if ("admin".equals(role)) {
|
||||
account = staticAdminService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
if ("doctor".equals(role)) {
|
||||
account = staticDoctorService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
if ("patient".equals(role)) {
|
||||
account = staticPatientService.selectById(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
return account;
|
||||
} catch (Exception e) {
|
||||
log.error("获取当前登录的管理员信息失败, token={}", token, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/main/java/com/example/common/config/WebConfig.java
Normal file
24
src/main/java/com/example/common/config/WebConfig.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.example.common.config;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Resource
|
||||
private JwtInterceptor jwtInterceptor;
|
||||
|
||||
// 加自定义拦截器JwtInterceptor,设置拦截规则
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(jwtInterceptor).addPathPatterns("/**")
|
||||
.excludePathPatterns("/")
|
||||
.excludePathPatterns("/login", "/register", "/files/**", "/role/selectAll","/institution/selectAll")
|
||||
.excludePathPatterns("/doctor") // 放行医生列表获取接口,用于患者注册时选择医生
|
||||
.excludePathPatterns("/ws/**", "/notification/**") // 放行WebSocket和通知相关的路径
|
||||
.excludePathPatterns("/eventInstitution/checkAndUpdateEventStatus"); // 放行事件状态检查接口
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/example/common/enums/ResultCodeEnum.java
Normal file
27
src/main/java/com/example/common/enums/ResultCodeEnum.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.example.common.enums;
|
||||
|
||||
public enum ResultCodeEnum {
|
||||
SUCCESS("200", "成功"),
|
||||
|
||||
PARAM_ERROR("400", "参数异常"),
|
||||
TOKEN_INVALID_ERROR("401", "无效的token"),
|
||||
TOKEN_CHECK_ERROR("401", "token验证失败,请重新登录"),
|
||||
PARAM_LOST_ERROR("4001", "参数缺失"),
|
||||
NO_AUTH_ERROR("403", "没有操作权限"),
|
||||
|
||||
SYSTEM_ERROR("500", "系统异常"),
|
||||
USER_EXIST_ERROR("5001", "用户名已存在"),
|
||||
USER_NOT_LOGIN("5002", "用户未登录"),
|
||||
USER_ACCOUNT_ERROR("5003", "账号或密码错误"),
|
||||
USER_NOT_EXIST_ERROR("5004", "用户不存在"),
|
||||
PARAM_PASSWORD_ERROR("5005", "原密码输入错误"),
|
||||
;
|
||||
|
||||
public String code;
|
||||
public String msg;
|
||||
|
||||
ResultCodeEnum(String code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/example/config/RestTemplateConfig.java
Normal file
14
src/main/java/com/example/config/RestTemplateConfig.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.example.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
||||
20
src/main/java/com/example/config/WebSocketConfig.java
Normal file
20
src/main/java/com/example/config/WebSocketConfig.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.example.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* WebSocket配置类
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
/**
|
||||
* 注入ServerEndpointExporter,自动注册使用了@ServerEndpoint注解的bean
|
||||
*/
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
||||
56
src/main/java/com/example/controller/AIChatController.java
Normal file
56
src/main/java/com/example/controller/AIChatController.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.service.AIChatService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AI聊天控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/aiChat")
|
||||
public class AIChatController {
|
||||
|
||||
@Resource
|
||||
private AIChatService aiChatService;
|
||||
|
||||
/**
|
||||
* 发送消息到AI并获取回复
|
||||
*/
|
||||
@PostMapping("/sendMessage")
|
||||
public Result sendMessage(@RequestBody Map<String, String> params) {
|
||||
String message = params.get("message");
|
||||
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "请先登录");
|
||||
}
|
||||
|
||||
// 获取AI回复
|
||||
String aiReply = aiChatService.sendMessage(message);
|
||||
|
||||
Map<String, Object> userMessage = new HashMap<>();
|
||||
userMessage.put("content", message);
|
||||
userMessage.put("messageType", "user");
|
||||
userMessage.put("createTime", LocalDateTime.now());
|
||||
|
||||
Map<String, Object> aiMessage = new HashMap<>();
|
||||
aiMessage.put("content", aiReply);
|
||||
aiMessage.put("messageType", "ai");
|
||||
aiMessage.put("createTime", LocalDateTime.now());
|
||||
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("userMessage", userMessage);
|
||||
resultMap.put("aiMessage", aiMessage);
|
||||
|
||||
return Result.success(resultMap);
|
||||
}
|
||||
}
|
||||
48
src/main/java/com/example/controller/AccountController.java
Normal file
48
src/main/java/com/example/controller/AccountController.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.service.PatientService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 账号相关接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/account")
|
||||
public class AccountController {
|
||||
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
/**
|
||||
* 获取所有患者列表(仅管理员可用)
|
||||
*
|
||||
* @param name 可选的患者姓名过滤
|
||||
* @return 患者列表
|
||||
*/
|
||||
@GetMapping("/listPatients")
|
||||
public Result listPatients(@RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"admin".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限,只有管理员可以访问此接口");
|
||||
}
|
||||
|
||||
Patient searchParam = null;
|
||||
if (name != null && !name.isEmpty()) {
|
||||
searchParam = new Patient();
|
||||
searchParam.setName(name);
|
||||
}
|
||||
|
||||
List<Patient> patients = patientService.selectAll(searchParam);
|
||||
return Result.success(patients);
|
||||
}
|
||||
}
|
||||
93
src/main/java/com/example/controller/AdminController.java
Normal file
93
src/main/java/com/example/controller/AdminController.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.Admin;
|
||||
import com.example.service.AdminService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述:管理员相关接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class AdminController {
|
||||
|
||||
@Resource
|
||||
AdminService adminService;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public Result add(@RequestBody Admin admin) {
|
||||
|
||||
adminService.add(admin);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
adminService.deleteById(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
@DeleteMapping("/delete/batch")
|
||||
public Result delete(@RequestBody List<Integer> ids) {
|
||||
adminService.deleteBatch(ids);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
@PutMapping("/update")
|
||||
public Result update(@RequestBody Admin admin) {
|
||||
|
||||
adminService.updateById(admin);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单个
|
||||
*/
|
||||
@GetMapping("/selectById/{id}")
|
||||
public Result selectById(@PathVariable Integer id) {
|
||||
Admin admin = adminService.selectById(id);
|
||||
return Result.success(admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
@GetMapping("/selectAll")
|
||||
public Result selectAll(Admin admin) {
|
||||
List<Admin> list = adminService.selectAll(admin);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(
|
||||
Admin admin,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
PageInfo<Admin> pageInfo = adminService.selectPage(admin, pageNum, pageSize);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
109
src/main/java/com/example/controller/AnnouncementController.java
Normal file
109
src/main/java/com/example/controller/AnnouncementController.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.Announcement;
|
||||
import com.example.service.AnnouncementService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公告控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/announcement")
|
||||
public class AnnouncementController {
|
||||
|
||||
@Resource
|
||||
private AnnouncementService announcementService;
|
||||
|
||||
/**
|
||||
* 添加公告
|
||||
* @param announcement 公告信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody Announcement announcement) {
|
||||
announcementService.add(announcement);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新公告
|
||||
* @param announcement 公告信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody Announcement announcement) {
|
||||
announcementService.update(announcement);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除公告
|
||||
* @param id 公告ID
|
||||
* @return 结果
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
announcementService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公告详情
|
||||
* @param id 公告ID
|
||||
* @return 公告信息
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result getById(@PathVariable Integer id) {
|
||||
Announcement announcement = announcementService.getById(id);
|
||||
return Result.success(announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已发布的公告(分页,所有用户可访问)
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @param title 标题关键字
|
||||
* @return 分页公告列表
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public Result getPublishedPage(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String title) {
|
||||
PageInfo<Announcement> pageInfo = announcementService.getPublishedPage(pageNum, pageSize, title);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有公告(分页,包括草稿,仅管理员可用)
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @param title 标题关键字
|
||||
* @return 分页公告列表
|
||||
*/
|
||||
@GetMapping("/adminPage")
|
||||
public Result getAllForAdmin(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String title) {
|
||||
PageInfo<Announcement> pageInfo = announcementService.getAllForAdmin(pageNum, pageSize, title);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新的几条已发布公告(用于首页展示)
|
||||
* @param limit 限制条数
|
||||
* @return 公告列表
|
||||
*/
|
||||
@GetMapping("/latest")
|
||||
public Result getLatestPublished(
|
||||
@RequestParam(defaultValue = "5") Integer limit) {
|
||||
List<Announcement> list = announcementService.getLatestPublished(limit);
|
||||
return Result.success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.AssessmentReport;
|
||||
import com.example.service.AssessmentReportService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 评估报告控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/assessmentReport")
|
||||
public class AssessmentReportController {
|
||||
|
||||
@Resource
|
||||
private AssessmentReportService assessmentReportService;
|
||||
|
||||
/**
|
||||
* 手动生成评估报告
|
||||
*/
|
||||
@PostMapping("/generate")
|
||||
public Result generate(@RequestBody Map<String, Object> params) {
|
||||
Integer patientId = params.get("patientId") != null ? Integer.valueOf(params.get("patientId").toString()) : null;
|
||||
String reportPeriod = params.get("reportPeriod") != null ? params.get("reportPeriod").toString() : null;
|
||||
|
||||
if (patientId == null) {
|
||||
return Result.error("400", "缺少必要参数patientId");
|
||||
}
|
||||
if (reportPeriod == null) {
|
||||
return Result.error("400", "缺少必要参数reportPeriod");
|
||||
}
|
||||
|
||||
AssessmentReport report = assessmentReportService.generateReport(patientId, reportPeriod);
|
||||
return Result.success(report);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取患者的评估报告列表
|
||||
*/
|
||||
@GetMapping("/patient/{patientId}")
|
||||
public Result getReportsByPatientId(@PathVariable Integer patientId) {
|
||||
List<AssessmentReport> reports = assessmentReportService.getReportsByPatientId(patientId);
|
||||
return Result.success(reports);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取医生负责的患者的评估报告列表
|
||||
*/
|
||||
@GetMapping("/doctor")
|
||||
public Result getReportsByDoctor() {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "未登录");
|
||||
}
|
||||
|
||||
List<AssessmentReport> reports = assessmentReportService.getReportsByDoctorId(currentUser.getId());
|
||||
return Result.success(reports);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有评估报告列表(管理员使用)
|
||||
*/
|
||||
@GetMapping("/admin")
|
||||
public Result getAllReports() {
|
||||
List<AssessmentReport> reports = assessmentReportService.getAllReports();
|
||||
return Result.success(reports);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加医生批注
|
||||
*/
|
||||
@PutMapping("/comment/{reportId}")
|
||||
public Result addComment(@PathVariable Integer reportId, @RequestParam(required = false) String comment) {
|
||||
if (comment == null || comment.isEmpty()) {
|
||||
return Result.error("400", "评论内容不能为空");
|
||||
}
|
||||
assessmentReportService.addDoctorComment(reportId, comment);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新报告状态为已读
|
||||
*/
|
||||
@PutMapping("/read/{reportId}")
|
||||
public Result markAsRead(@PathVariable Integer reportId) {
|
||||
assessmentReportService.markAsRead(reportId);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评估报告详情
|
||||
*/
|
||||
@GetMapping("/{reportId}")
|
||||
public Result getReportById(@PathVariable Integer reportId) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "未登录");
|
||||
}
|
||||
|
||||
// 通过ID获取报告
|
||||
AssessmentReport report = assessmentReportService.getReportById(reportId);
|
||||
|
||||
if (report == null) {
|
||||
return Result.error("404", "报告不存在");
|
||||
}
|
||||
|
||||
return Result.success(report);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.ChatMessage;
|
||||
import com.example.service.ChatMessageService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 聊天消息控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/chat")
|
||||
public class ChatMessageController {
|
||||
|
||||
@Resource
|
||||
private ChatMessageService chatMessageService;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
@PostMapping("/send")
|
||||
public Result send(@RequestBody ChatMessage chatMessage) {
|
||||
ChatMessage message = chatMessageService.sendMessage(chatMessage);
|
||||
return Result.success(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天历史记录
|
||||
*/
|
||||
@GetMapping("/history")
|
||||
public Result getChatHistory(@RequestParam Integer contactId, @RequestParam String contactType) {
|
||||
List<ChatMessage> messages = chatMessageService.getChatHistory(contactId, contactType);
|
||||
return Result.success(messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天联系人列表
|
||||
*/
|
||||
@GetMapping("/contacts")
|
||||
public Result getContactList() {
|
||||
List<Map<String, Object>> contacts = chatMessageService.getContactList();
|
||||
return Result.success(contacts);
|
||||
}
|
||||
}
|
||||
147
src/main/java/com/example/controller/DoctorController.java
Normal file
147
src/main/java/com/example/controller/DoctorController.java
Normal file
@@ -0,0 +1,147 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.Doctor;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.service.DoctorPatientService;
|
||||
import com.example.service.DoctorService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 医生相关接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/doctor")
|
||||
public class DoctorController {
|
||||
|
||||
@Resource
|
||||
private DoctorService doctorService;
|
||||
|
||||
@Resource
|
||||
private DoctorPatientService doctorPatientService;
|
||||
|
||||
/**
|
||||
* 添加医生
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody Doctor doctor) {
|
||||
doctorService.add(doctor);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除医生
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
doctorService.deleteById(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除医生
|
||||
*/
|
||||
@DeleteMapping("/batch")
|
||||
public Result deleteBatch(@RequestBody List<Integer> ids) {
|
||||
doctorService.deleteBatch(ids);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改医生
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody Doctor doctor) {
|
||||
doctorService.updateById(doctor);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询医生
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result getById(@PathVariable Integer id) {
|
||||
Doctor doctor = doctorService.selectById(id);
|
||||
return Result.success(doctor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有医生
|
||||
*/
|
||||
@GetMapping
|
||||
public Result getAll(Doctor doctor) {
|
||||
List<Doctor> list = doctorService.selectAll(doctor);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询医生
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public Result page(Doctor doctor,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
PageInfo<Doctor> page = doctorService.selectPage(doctor, pageNum, pageSize);
|
||||
return Result.success(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询医生(与Admin页面保持一致的接口)
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(
|
||||
Doctor doctor,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
PageInfo<Doctor> pageInfo = doctorService.selectPage(doctor, pageNum, pageSize);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前医生负责的患者列表
|
||||
* 此接口是为了兼容之前的路径
|
||||
* @param name 患者姓名(可选)
|
||||
* @return 患者列表
|
||||
*/
|
||||
@GetMapping("/myPatients")
|
||||
public Result myPatients(@RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"doctor".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
List<DoctorPatient> list = doctorPatientService.selectByDoctorId(currentUser.getId(), name);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新医生个人资料
|
||||
*/
|
||||
@PutMapping("/update")
|
||||
public Result updateProfile(@RequestBody Doctor doctor) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"doctor".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
// 确保只能更新自己的信息
|
||||
if (!currentUser.getId().equals(doctor.getId())) {
|
||||
return Result.error("403", "只能更新自己的信息");
|
||||
}
|
||||
|
||||
// 更新个人资料
|
||||
doctorService.updateById(doctor);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.service.DoctorPatientService;
|
||||
import com.example.service.PatientService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 医生与患者关系控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/doctor-patient")
|
||||
public class DoctorPatientController {
|
||||
|
||||
@Resource
|
||||
private DoctorPatientService doctorPatientService;
|
||||
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
/**
|
||||
* 新增医生患者关系
|
||||
* @param doctorPatient 医生患者关系信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody DoctorPatient doctorPatient) {
|
||||
doctorPatientService.add(doctorPatient);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新医生患者关系
|
||||
* @param doctorPatient 医生患者关系信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody DoctorPatient doctorPatient) {
|
||||
doctorPatientService.update(doctorPatient);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除医生患者关系
|
||||
* @param id 关系ID
|
||||
* @return 结果
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
doctorPatientService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束医生患者关系
|
||||
* @param id 关系ID
|
||||
* @return 结果
|
||||
*/
|
||||
@PutMapping("/end/{id}")
|
||||
public Result endRelationship(@PathVariable Integer id) {
|
||||
doctorPatientService.endRelationship(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前医生的患者列表
|
||||
* @param name 患者姓名(可选)
|
||||
* @return 患者列表
|
||||
*/
|
||||
@GetMapping("/doctor/patients")
|
||||
public Result getPatientsByDoctor(@RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"doctor".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
List<DoctorPatient> list = doctorPatientService.selectByDoctorId(currentUser.getId(), name);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前患者的医生列表
|
||||
* @param name 医生姓名(可选)
|
||||
* @return 医生列表
|
||||
*/
|
||||
@GetMapping("/patient/doctors")
|
||||
public Result getDoctorsByPatient(@RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"patient".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
List<DoctorPatient> list = doctorPatientService.selectByPatientId(currentUser.getId(), name);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据医生ID获取其患者列表(管理员使用)
|
||||
* @param doctorId 医生ID
|
||||
* @param name 患者姓名(可选)
|
||||
* @return 患者列表
|
||||
*/
|
||||
@GetMapping("/admin/doctor/{doctorId}/patients")
|
||||
public Result getPatientsByDoctorForAdmin(@PathVariable Integer doctorId, @RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"admin".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
List<DoctorPatient> list = doctorPatientService.selectByDoctorId(doctorId, name);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID获取其医生列表(管理员使用)
|
||||
* @param patientId 患者ID
|
||||
* @param name 医生姓名(可选)
|
||||
* @return 医生列表
|
||||
*/
|
||||
@GetMapping("/admin/patient/{patientId}/doctors")
|
||||
public Result getDoctorsByPatientForAdmin(@PathVariable Integer patientId, @RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"admin".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
List<DoctorPatient> list = doctorPatientService.selectByPatientId(patientId, name);
|
||||
return Result.success(list);
|
||||
}
|
||||
}
|
||||
102
src/main/java/com/example/controller/FileController.java
Normal file
102
src/main/java/com/example/controller/FileController.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.example.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.example.common.Result;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/files")
|
||||
public class FileController {
|
||||
|
||||
// 文件上传存储路径
|
||||
private static final String filePath = System.getProperty("user.dir") + "/file/";
|
||||
private static final String http = "http://localhost:9090/files/";
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*/
|
||||
@PostMapping("/upload")
|
||||
public Result upload(MultipartFile file) {
|
||||
synchronized (FileController.class) {
|
||||
String flag = System.currentTimeMillis() + "";
|
||||
String fileName = file.getOriginalFilename();
|
||||
try {
|
||||
if (!FileUtil.isDirectory(filePath)) {
|
||||
FileUtil.mkdir(filePath);
|
||||
}
|
||||
// 文件存储形式:时间戳-文件名
|
||||
FileUtil.writeBytes(file.getBytes(), filePath + flag + "-" + fileName);
|
||||
System.out.println(fileName + "--上传成功");
|
||||
Thread.sleep(1L);
|
||||
} catch (Exception e) {
|
||||
System.err.println(fileName + "--文件上传失败");
|
||||
}
|
||||
return Result.success(http + flag + "-" + fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取文件
|
||||
*
|
||||
* @param flag
|
||||
* @param response
|
||||
*/
|
||||
@GetMapping("/{flag}")
|
||||
public void avatarPath(@PathVariable String flag, HttpServletResponse response) {
|
||||
if (!FileUtil.isDirectory(filePath)) {
|
||||
FileUtil.mkdir(filePath);
|
||||
}
|
||||
OutputStream os;
|
||||
List<String> fileNames = FileUtil.listFileNames(filePath);
|
||||
String avatar = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");
|
||||
try {
|
||||
if (StrUtil.isNotEmpty(avatar)) {
|
||||
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(avatar, "UTF-8"));
|
||||
response.setContentType("application/octet-stream");
|
||||
byte[] bytes = FileUtil.readBytes(filePath + avatar);
|
||||
os = response.getOutputStream();
|
||||
os.write(bytes);
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("文件下载失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param flag
|
||||
*/
|
||||
@DeleteMapping("/{flag}")
|
||||
public void delFile(@PathVariable String flag) {
|
||||
if (!FileUtil.isDirectory(filePath)) {
|
||||
FileUtil.mkdir(filePath);
|
||||
}
|
||||
List<String> fileNames = FileUtil.listFileNames(filePath);
|
||||
String filename = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");
|
||||
FileUtil.del(filePath + filename);
|
||||
System.out.println("删除文件" + filename + "成功");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
256
src/main/java/com/example/controller/PatientController.java
Normal file
256
src/main/java/com/example/controller/PatientController.java
Normal file
@@ -0,0 +1,256 @@
|
||||
package com.example.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.Doctor;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.service.DoctorPatientService;
|
||||
import com.example.service.PatientService;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 患者控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/patient")
|
||||
public class PatientController {
|
||||
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
@Resource
|
||||
private DoctorPatientService doctorPatientService;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody Patient patient) {
|
||||
patientService.add(patient);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
patientService.deleteById(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody Patient patient) {
|
||||
patientService.updateById(patient);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result getById(@PathVariable Integer id) {
|
||||
Patient patient = patientService.selectById(id);
|
||||
return Result.success(patient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*/
|
||||
@GetMapping
|
||||
public Result findAll() {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
|
||||
// 管理员可以查看所有患者
|
||||
if (currentUser != null && "admin".equals(currentUser.getRole())) {
|
||||
patients = patientService.selectAll(null);
|
||||
}
|
||||
// 医生只能查看自己的患者
|
||||
else if (currentUser != null && "doctor".equals(currentUser.getRole())) {
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), null);
|
||||
if (!doctorPatients.isEmpty()) {
|
||||
// 提取患者信息
|
||||
patients = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatient)
|
||||
.filter(p -> p != null)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
// 患者只能查看自己的信息
|
||||
else if (currentUser != null && "patient".equals(currentUser.getRole())) {
|
||||
Patient patient = patientService.selectById(currentUser.getId());
|
||||
if (patient != null) {
|
||||
patients.add(patient);
|
||||
}
|
||||
}
|
||||
|
||||
return Result.success(patients);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public Result findPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String name) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
|
||||
// 管理员可以查看所有患者
|
||||
if (currentUser != null && "admin".equals(currentUser.getRole())) {
|
||||
return Result.success(patientService.selectPage(pageNum, pageSize, name));
|
||||
}
|
||||
// 医生只能查看自己的患者
|
||||
else if (currentUser != null && "doctor".equals(currentUser.getRole())) {
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), name);
|
||||
|
||||
if (!doctorPatients.isEmpty()) {
|
||||
// 提取患者信息
|
||||
List<Patient> patients = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatient)
|
||||
.filter(p -> p != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 手动进行分页
|
||||
int total = patients.size();
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
|
||||
if (fromIndex >= total) {
|
||||
patients = new ArrayList<>();
|
||||
} else {
|
||||
patients = patients.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
return Result.success(patients);
|
||||
} else {
|
||||
return Result.success(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
// 患者只能查看自己的信息
|
||||
else if (currentUser != null && "patient".equals(currentUser.getRole())) {
|
||||
Patient patient = patientService.selectById(currentUser.getId());
|
||||
List<Patient> list = new ArrayList<>();
|
||||
if (patient != null) {
|
||||
list.add(patient);
|
||||
}
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询(与Admin页面保持一致的接口)
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(
|
||||
Patient patient,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
|
||||
// 管理员可以查看所有患者
|
||||
if (currentUser != null && "admin".equals(currentUser.getRole())) {
|
||||
// 使用PageHelper手动创建PageInfo
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<Patient> patients = patientService.selectAll(patient);
|
||||
PageInfo<Patient> pageInfo = new PageInfo<>(patients);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
// 医生只能查看自己的患者
|
||||
else if (currentUser != null && "doctor".equals(currentUser.getRole())) {
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), patient.getName());
|
||||
|
||||
if (!doctorPatients.isEmpty()) {
|
||||
// 提取患者信息
|
||||
List<Patient> patients = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatient)
|
||||
.filter(p -> p != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 手动进行分页
|
||||
int total = patients.size();
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
|
||||
if (fromIndex >= total) {
|
||||
patients = new ArrayList<>();
|
||||
} else {
|
||||
patients = patients.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
// 创建PageInfo对象
|
||||
PageInfo<Patient> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(patients);
|
||||
pageInfo.setTotal(total);
|
||||
pageInfo.setPageNum(pageNum);
|
||||
pageInfo.setPageSize(pageSize);
|
||||
pageInfo.setPages((total + pageSize - 1) / pageSize);
|
||||
|
||||
return Result.success(pageInfo);
|
||||
} else {
|
||||
PageInfo<Patient> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(new ArrayList<>());
|
||||
pageInfo.setTotal(0);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
}
|
||||
// 患者只能查看自己的信息
|
||||
else if (currentUser != null && "patient".equals(currentUser.getRole())) {
|
||||
Patient currentPatient = patientService.selectById(currentUser.getId());
|
||||
List<Patient> list = new ArrayList<>();
|
||||
if (currentPatient != null) {
|
||||
list.add(currentPatient);
|
||||
}
|
||||
|
||||
// 创建PageInfo对象
|
||||
PageInfo<Patient> pageInfo = new PageInfo<>();
|
||||
pageInfo.setList(list);
|
||||
pageInfo.setTotal(list.size());
|
||||
pageInfo.setPageNum(1);
|
||||
pageInfo.setPageSize(pageSize);
|
||||
pageInfo.setPages(1);
|
||||
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新患者个人资料
|
||||
*/
|
||||
@PutMapping("/update")
|
||||
public Result updateProfile(@RequestBody Patient patient) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !"patient".equals(currentUser.getRole())) {
|
||||
return Result.error("401", "无权限");
|
||||
}
|
||||
|
||||
// 确保只能更新自己的信息
|
||||
if (!currentUser.getId().equals(patient.getId())) {
|
||||
return Result.error("403", "只能更新自己的信息");
|
||||
}
|
||||
|
||||
// 更新个人资料
|
||||
patientService.updateById(patient);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.service.RecommendationService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 推荐系统控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/recommendation")
|
||||
public class RecommendationController {
|
||||
|
||||
@Resource
|
||||
private RecommendationService recommendationService;
|
||||
|
||||
/**
|
||||
* 获取个性化推荐资源
|
||||
* @param limit 推荐资源数量,默认为4
|
||||
* @return 推荐资源列表
|
||||
*/
|
||||
@GetMapping("/resources")
|
||||
public Result getRecommendedResources(@RequestParam(defaultValue = "4") Integer limit) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "用户未登录");
|
||||
}
|
||||
|
||||
// 验证用户是否为患者
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
return Result.error("403", "只有患者才能获取个性化推荐");
|
||||
}
|
||||
|
||||
// 获取推荐资源
|
||||
List<Map<String, Object>> recommendations =
|
||||
recommendationService.getRecommendationsForUser(currentUser.getId(), limit);
|
||||
|
||||
return Result.success(recommendations);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.ResourceCategory;
|
||||
import com.example.service.ResourceCategoryService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源分类控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/resourceCategory")
|
||||
public class ResourceCategoryController {
|
||||
|
||||
@Resource
|
||||
private ResourceCategoryService resourceCategoryService;
|
||||
|
||||
/**
|
||||
* 获取所有分类
|
||||
*/
|
||||
@GetMapping
|
||||
public Result findAll() {
|
||||
List<ResourceCategory> list = resourceCategoryService.findAll();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据父分类ID获取子分类
|
||||
*/
|
||||
@GetMapping("/parent/{parentId}")
|
||||
public Result findByParentId(@PathVariable Integer parentId) {
|
||||
List<ResourceCategory> list = resourceCategoryService.findByParentId(parentId);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取分类
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result findById(@PathVariable Integer id) {
|
||||
ResourceCategory category = resourceCategoryService.findById(id);
|
||||
return Result.success(category);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分类
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody ResourceCategory category) {
|
||||
resourceCategoryService.add(category);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新分类
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody ResourceCategory category) {
|
||||
resourceCategoryService.update(category);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
resourceCategoryService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
ResourceCategory category) {
|
||||
PageInfo<ResourceCategory> pageInfo = resourceCategoryService.selectPage(category, pageNum, pageSize);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.ResourceRating;
|
||||
import com.example.service.ResourceRatingService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 资源评分控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/resourceRating")
|
||||
public class ResourceRatingController {
|
||||
|
||||
@Resource
|
||||
private ResourceRatingService resourceRatingService;
|
||||
|
||||
/**
|
||||
* 获取资源评分列表(分页)
|
||||
*/
|
||||
@GetMapping("/resource/{resourceId}")
|
||||
public Result findResourceRatingsPage(
|
||||
@PathVariable Integer resourceId,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
|
||||
// 查询评分列表
|
||||
List<ResourceRating> ratings = resourceRatingService.findByResourceId(resourceId);
|
||||
|
||||
// 构建分页结果
|
||||
Map<String, Object> pageResult = new HashMap<>();
|
||||
int start = (pageNum - 1) * pageSize;
|
||||
int end = Math.min(start + pageSize, ratings.size());
|
||||
|
||||
// 截取当前页数据
|
||||
List<ResourceRating> pageRatings = ratings.subList(
|
||||
start < ratings.size() ? start : 0,
|
||||
end < ratings.size() ? end : 0
|
||||
);
|
||||
|
||||
pageResult.put("list", pageRatings);
|
||||
pageResult.put("total", ratings.size());
|
||||
pageResult.put("pageNum", pageNum);
|
||||
pageResult.put("pageSize", pageSize);
|
||||
|
||||
return Result.success(pageResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源平均评分
|
||||
*/
|
||||
@GetMapping("/average/{resourceId}")
|
||||
public Result getAverageRating(@PathVariable Integer resourceId) {
|
||||
Double averageRating = resourceRatingService.getAverageRating(resourceId);
|
||||
return Result.success(averageRating);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源评分数量
|
||||
*/
|
||||
@GetMapping("/count/{resourceId}")
|
||||
public Result getRatingCount(@PathVariable Integer resourceId) {
|
||||
Integer count = resourceRatingService.getRatingCount(resourceId);
|
||||
return Result.success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加或更新评分
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody ResourceRating resourceRating) {
|
||||
resourceRatingService.rateResource(resourceRating);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的所有评分
|
||||
*/
|
||||
@GetMapping("/user")
|
||||
public Result getUserRatings() {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "用户未登录");
|
||||
}
|
||||
|
||||
// 验证用户是否为患者
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
return Result.error("403", "只有患者可以查看自己的评分");
|
||||
}
|
||||
|
||||
// 获取用户评分列表
|
||||
List<ResourceRating> ratings = resourceRatingService.findByPatientId(currentUser.getId());
|
||||
return Result.success(ratings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有评分数据(用于推荐算法)
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public Result getAllRatings() {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "用户未登录");
|
||||
}
|
||||
|
||||
// 验证用户是否为患者
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
return Result.error("403", "只有患者可以访问评分数据");
|
||||
}
|
||||
|
||||
// 获取所有评分列表
|
||||
List<ResourceRating> ratings = resourceRatingService.findAll();
|
||||
return Result.success(ratings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源的平均评分和评分数量
|
||||
*/
|
||||
@GetMapping("/resource/{resourceId}/stats")
|
||||
public Result getResourceRatingStats(@PathVariable Integer resourceId) {
|
||||
Double averageRating = resourceRatingService.getAverageRating(resourceId);
|
||||
Integer count = resourceRatingService.getRatingCount(resourceId);
|
||||
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
stats.put("averageRating", averageRating);
|
||||
stats.put("ratingCount", count);
|
||||
|
||||
return Result.success(stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除评价
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result deleteRating(@PathVariable Integer id) {
|
||||
resourceRatingService.deleteRating(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据资源ID查询评分记录
|
||||
*/
|
||||
@GetMapping("/{resourceId}")
|
||||
public Result findByResourceId(@PathVariable Integer resourceId) {
|
||||
List<ResourceRating> ratings = resourceRatingService.findByResourceId(resourceId);
|
||||
double averageRating = resourceRatingService.getAverageRating(resourceId);
|
||||
Integer count = resourceRatingService.getRatingCount(resourceId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("ratings", ratings);
|
||||
result.put("averageRating", averageRating);
|
||||
result.put("count", count != null ? count : 0);
|
||||
|
||||
return Result.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.SymptomRecord;
|
||||
import com.example.service.SymptomRecordService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 症状记录控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/symptomRecord")
|
||||
public class SymptomRecordController {
|
||||
|
||||
@Resource
|
||||
private SymptomRecordService symptomRecordService;
|
||||
|
||||
/**
|
||||
* 添加症状记录
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody SymptomRecord symptomRecord) {
|
||||
symptomRecordService.add(symptomRecord);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新症状记录
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody SymptomRecord symptomRecord) {
|
||||
symptomRecordService.update(symptomRecord);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除症状记录
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
symptomRecordService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询症状记录
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result getById(@PathVariable Integer id) {
|
||||
SymptomRecord symptomRecord = symptomRecordService.getById(id);
|
||||
return Result.success(symptomRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID查询症状记录
|
||||
*/
|
||||
@GetMapping("/patient/{patientId}")
|
||||
public Result getByPatientId(@PathVariable Integer patientId) {
|
||||
List<SymptomRecord> list = symptomRecordService.getByPatientId(patientId);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录患者的症状记录
|
||||
*/
|
||||
@GetMapping("/my")
|
||||
public Result getMyRecords() {
|
||||
List<SymptomRecord> list = symptomRecordService.getByPatientId(null);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询症状记录
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(
|
||||
@RequestParam(required = false) String patientName,
|
||||
@RequestParam(required = false) String startDate,
|
||||
@RequestParam(required = false) String endDate,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
SymptomRecord symptomRecord = new SymptomRecord();
|
||||
symptomRecord.setPatientName(patientName);
|
||||
com.github.pagehelper.PageInfo<SymptomRecord> pageInfo = symptomRecordService.selectPage(symptomRecord, pageNum, pageSize, startDate, endDate);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.service.SymptomRecordService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 症状记录统计控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/symptomStatistics")
|
||||
public class SymptomStatisticsController {
|
||||
|
||||
@Resource
|
||||
private SymptomRecordService symptomRecordService;
|
||||
|
||||
/**
|
||||
* 获取症状记录统计数据
|
||||
*/
|
||||
@GetMapping
|
||||
public Result getStatistics(
|
||||
@RequestParam(required = false) Integer patientId,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
|
||||
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "请先登录");
|
||||
}
|
||||
|
||||
Map<String, Object> result;
|
||||
|
||||
// 根据用户角色获取不同的统计数据
|
||||
switch (currentUser.getRole()) {
|
||||
case "admin":
|
||||
// 管理员可以查看所有数据或指定患者的数据
|
||||
result = symptomRecordService.getStatisticsData(patientId, startDate, endDate);
|
||||
break;
|
||||
case "doctor":
|
||||
// 如果请求包含patientId且该患者属于当前医生,则返回该患者的数据
|
||||
// 否则返回该医生的所有患者数据
|
||||
if (patientId != null) {
|
||||
result = symptomRecordService.getStatisticsData(patientId, startDate, endDate);
|
||||
} else {
|
||||
result = symptomRecordService.getStatisticsByDoctor(currentUser.getId(), startDate, endDate);
|
||||
}
|
||||
break;
|
||||
case "patient":
|
||||
// 患者只能查看自己的数据
|
||||
result = symptomRecordService.getStatisticsData(currentUser.getId(), startDate, endDate);
|
||||
break;
|
||||
default:
|
||||
return Result.error("403", "无权限访问");
|
||||
}
|
||||
|
||||
return Result.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.Result;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.ResourceCategory;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import com.example.service.ResourceCategoryService;
|
||||
import com.example.service.TreatmentResourceService;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 心理治疗资源控制器
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/treatmentResource")
|
||||
public class TreatmentResourceController {
|
||||
|
||||
@Resource
|
||||
private TreatmentResourceService treatmentResourceService;
|
||||
|
||||
@Resource
|
||||
private ResourceCategoryService resourceCategoryService;
|
||||
|
||||
/**
|
||||
* 分页搜索资源
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public Result search(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(defaultValue = "") String keyword) {
|
||||
|
||||
// 获取当前用户角色
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
String role = currentUser != null ? currentUser.getRole() : "patient";
|
||||
|
||||
Page<TreatmentResource> page = new Page<>(pageNum, pageSize);
|
||||
page = treatmentResourceService.search(page, keyword, role);
|
||||
|
||||
return Result.success(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
@GetMapping("/selectPage")
|
||||
public Result selectPage(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
TreatmentResource resource) {
|
||||
|
||||
PageInfo<TreatmentResource> pageInfo = treatmentResourceService.selectPage(resource, pageNum, pageSize);
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分类获取资源
|
||||
*/
|
||||
@GetMapping("/category/{categoryId}")
|
||||
public Result findByCategoryId(@PathVariable Integer categoryId) {
|
||||
List<TreatmentResource> list = treatmentResourceService.findByCategoryId(categoryId);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取资源
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public Result findById(@PathVariable Integer id) {
|
||||
TreatmentResource resource = treatmentResourceService.findById(id);
|
||||
treatmentResourceService.incrementVisitCount(id);
|
||||
return Result.success(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增资源
|
||||
*/
|
||||
@PostMapping
|
||||
public Result add(@RequestBody TreatmentResource resource) {
|
||||
treatmentResourceService.add(resource);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新资源
|
||||
*/
|
||||
@PutMapping
|
||||
public Result update(@RequestBody TreatmentResource resource) {
|
||||
treatmentResourceService.update(resource);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除资源
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public Result delete(@PathVariable Integer id) {
|
||||
treatmentResourceService.delete(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核资源
|
||||
*/
|
||||
@PutMapping("/audit/{id}")
|
||||
public Result audit(@PathVariable Integer id, @RequestParam String status) {
|
||||
treatmentResourceService.changeAuditStatus(id, status);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载资源
|
||||
*/
|
||||
@GetMapping("/download/{id}")
|
||||
public Result download(@PathVariable Integer id) {
|
||||
TreatmentResource resource = treatmentResourceService.findById(id);
|
||||
if (resource != null) {
|
||||
treatmentResourceService.incrementDownloadCount(id);
|
||||
}
|
||||
return Result.success(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加资源访问次数(新路径)
|
||||
*/
|
||||
@PutMapping("/incrementVisit/{id}")
|
||||
public Result incrementVisit(@PathVariable Integer id) {
|
||||
treatmentResourceService.incrementVisitCount(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加资源下载次数(新路径)
|
||||
*/
|
||||
@PutMapping("/incrementDownload/{id}")
|
||||
public Result incrementDownload(@PathVariable Integer id) {
|
||||
treatmentResourceService.incrementDownloadCount(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询医生自己发布的资源
|
||||
*/
|
||||
@GetMapping("/myResources")
|
||||
public Result myResources(
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
TreatmentResource resource) {
|
||||
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "未登录");
|
||||
}
|
||||
|
||||
// 只有医生可以查询自己发布的资源
|
||||
if (!"doctor".equals(currentUser.getRole())) {
|
||||
return Result.error("403", "无权限查询");
|
||||
}
|
||||
|
||||
// 强制设置发布者ID为当前登录用户
|
||||
resource.setPublisherId(currentUser.getId());
|
||||
|
||||
// 使用PageHelper进行分页
|
||||
PageInfo<TreatmentResource> pageInfo = treatmentResourceService.findByPublisher(resource, pageNum, pageSize);
|
||||
|
||||
return Result.success(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源使用情况统计数据
|
||||
*/
|
||||
@GetMapping("/statistics")
|
||||
public Result getStatistics() {
|
||||
return Result.success(treatmentResourceService.getResourceStatistics());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已审核通过的心理资源
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public Result getAllApprovedResources(@RequestParam(required = false) String auditStatus) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
return Result.error("401", "用户未登录");
|
||||
}
|
||||
|
||||
// 查询关键词为空,表示获取所有资源
|
||||
String keyword = "";
|
||||
|
||||
// 根据审核状态查询资源
|
||||
List<TreatmentResource> resources;
|
||||
|
||||
if (auditStatus != null && !auditStatus.isEmpty()) {
|
||||
// 使用TreatmentResourceService的selectPage方法
|
||||
TreatmentResource queryParam = new TreatmentResource();
|
||||
queryParam.setAuditStatus(auditStatus);
|
||||
// 这里不使用分页,所以传一个很大的pageSize
|
||||
PageInfo<TreatmentResource> pageInfo = treatmentResourceService.selectPage(queryParam, 1, 1000);
|
||||
resources = pageInfo.getList();
|
||||
} else {
|
||||
// 默认只返回已通过审核的资源
|
||||
TreatmentResource queryParam = new TreatmentResource();
|
||||
queryParam.setAuditStatus("已通过");
|
||||
// 这里不使用分页,所以传一个很大的pageSize
|
||||
PageInfo<TreatmentResource> pageInfo = treatmentResourceService.selectPage(queryParam, 1, 1000);
|
||||
resources = pageInfo.getList();
|
||||
}
|
||||
|
||||
return Result.success(resources);
|
||||
}
|
||||
}
|
||||
93
src/main/java/com/example/controller/WebController.java
Normal file
93
src/main/java/com/example/controller/WebController.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.example.controller;
|
||||
|
||||
import com.example.common.config.TokenUtils;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import cn.hutool.poi.excel.ExcelWriter;
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.*;
|
||||
import com.example.service.*;
|
||||
import com.example.exception.CustomException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 描述:系统用户操作相关接口
|
||||
*/
|
||||
@RestController
|
||||
public class WebController {
|
||||
|
||||
@Resource
|
||||
private AdminService adminService;
|
||||
@Resource
|
||||
private DoctorService doctorService;
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
/**
|
||||
* 描述:用户登录接口
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public Result login(@RequestBody Account account) {
|
||||
Account loginAccount = null;
|
||||
if ("admin".equals(account.getRole())) {
|
||||
loginAccount = adminService.login(account);
|
||||
}
|
||||
if ("doctor".equals(account.getRole())) {
|
||||
loginAccount = doctorService.login(account);
|
||||
}
|
||||
if ("patient".equals(account.getRole())) {
|
||||
loginAccount = patientService.login(account);
|
||||
}
|
||||
|
||||
return Result.success(loginAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述:用户注册接口
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public Result register(@RequestBody Account account) {
|
||||
if ("admin".equals(account.getRole())) {
|
||||
adminService.register(account);
|
||||
}
|
||||
if ("doctor".equals(account.getRole())) {
|
||||
doctorService.register(account);
|
||||
}
|
||||
if ("patient".equals(account.getRole())) {
|
||||
patientService.register(account);
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述:更新密码接口
|
||||
*/
|
||||
@PutMapping("/updatePassword")
|
||||
public Result updatePassword(@RequestBody Account account) {
|
||||
if ("admin".equals(account.getRole())) {
|
||||
adminService.updatePassword(account);
|
||||
}
|
||||
if ("doctor".equals(account.getRole())) {
|
||||
doctorService.updatePassword(account);
|
||||
}
|
||||
if ("patient".equals(account.getRole())) {
|
||||
patientService.updatePassword(account);
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
30
src/main/java/com/example/entity/Account.java
Normal file
30
src/main/java/com/example/entity/Account.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Account {
|
||||
private Integer id;
|
||||
/** 账号 */
|
||||
private String username;
|
||||
/** 密码 */
|
||||
private String password;
|
||||
/** 姓名 */
|
||||
private String name;
|
||||
/** 性别 */
|
||||
private String sex;
|
||||
/** 手机号 */
|
||||
private String phone;
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
/** 角色 */
|
||||
private String role;
|
||||
@TableField(exist = false)
|
||||
private String newPassword;
|
||||
@TableField(exist = false)
|
||||
private String token;
|
||||
/** 医生ID (用于患者注册时选择医生) */
|
||||
@TableField(exist = false)
|
||||
private Integer doctorId;
|
||||
}
|
||||
33
src/main/java/com/example/entity/Admin.java
Normal file
33
src/main/java/com/example/entity/Admin.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.example.entity;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 管理员
|
||||
*/
|
||||
@Data
|
||||
@TableName("admin")
|
||||
public class Admin extends Account {
|
||||
|
||||
/** id */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
/** 账号 */
|
||||
private String username;
|
||||
/** 密码 */
|
||||
private String password;
|
||||
/** 名称 */
|
||||
private String name;
|
||||
/** 头像 */
|
||||
private String avatar;
|
||||
/** 性别 */
|
||||
private String sex;
|
||||
/** 手机号 */
|
||||
private String phone;
|
||||
}
|
||||
59
src/main/java/com/example/entity/Announcement.java
Normal file
59
src/main/java/com/example/entity/Announcement.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 公告实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("announcement")
|
||||
public class Announcement {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 是否置顶
|
||||
*/
|
||||
private Boolean isTop;
|
||||
|
||||
/**
|
||||
* 状态(1-发布,0-草稿)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 发布人ID
|
||||
*/
|
||||
private Integer publisherId;
|
||||
|
||||
/**
|
||||
* 发布人姓名
|
||||
*/
|
||||
private String publisherName;
|
||||
}
|
||||
41
src/main/java/com/example/entity/AssessmentReport.java
Normal file
41
src/main/java/com/example/entity/AssessmentReport.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("assessment_report")
|
||||
public class AssessmentReport {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
private Integer patientId;
|
||||
|
||||
private String reportPeriod;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate endDate;
|
||||
|
||||
private String summary;
|
||||
|
||||
private String trendAnalysis;
|
||||
|
||||
private String recommendation;
|
||||
|
||||
private String doctorComment;
|
||||
|
||||
private String status;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// 非数据库字段,用于前端显示
|
||||
private String patientName;
|
||||
private String doctorName;
|
||||
}
|
||||
92
src/main/java/com/example/entity/ChatMessage.java
Normal file
92
src/main/java/com/example/entity/ChatMessage.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 聊天消息实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("chat_message")
|
||||
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未知属性
|
||||
public class ChatMessage {
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 发送者ID
|
||||
*/
|
||||
private Integer senderId;
|
||||
|
||||
/**
|
||||
* 接收者ID
|
||||
*/
|
||||
private Integer receiverId;
|
||||
|
||||
/**
|
||||
* 发送者类型(doctor/patient)
|
||||
*/
|
||||
private String senderType;
|
||||
|
||||
/**
|
||||
* 接收者类型(doctor/patient)
|
||||
*/
|
||||
private String receiverType;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date sendTime;
|
||||
|
||||
/**
|
||||
* 是否已读(0-未读,1-已读)
|
||||
*/
|
||||
private Boolean isRead;
|
||||
|
||||
/**
|
||||
* 阅读时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date readTime;
|
||||
|
||||
/**
|
||||
* 发送者名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String senderName;
|
||||
|
||||
/**
|
||||
* 接收者名称(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 发送者头像(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String senderAvatar;
|
||||
|
||||
/**
|
||||
* 临时消息ID(用于前端标识临时消息,非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String tempId;
|
||||
}
|
||||
41
src/main/java/com/example/entity/Doctor.java
Normal file
41
src/main/java/com/example/entity/Doctor.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.example.entity;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 医生
|
||||
*/
|
||||
@Data
|
||||
@TableName("doctor")
|
||||
public class Doctor extends Account {
|
||||
|
||||
/** id */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
/** 账号 */
|
||||
private String username;
|
||||
/** 密码 */
|
||||
private String password;
|
||||
/** 名称 */
|
||||
private String name;
|
||||
/** 头像 */
|
||||
private String avatar;
|
||||
/** 性别 */
|
||||
private String sex;
|
||||
/** 手机号 */
|
||||
private String phone;
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
/** 执业证书编号 */
|
||||
private String certificateNo;
|
||||
/** 所属医院 */
|
||||
private String hospital;
|
||||
/** 科室 */
|
||||
private String department;
|
||||
}
|
||||
56
src/main/java/com/example/entity/DoctorPatient.java
Normal file
56
src/main/java/com/example/entity/DoctorPatient.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("doctor_patient")
|
||||
@Data
|
||||
public class DoctorPatient {
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 医生ID
|
||||
*/
|
||||
private Integer doctorId;
|
||||
|
||||
/**
|
||||
* 患者ID
|
||||
*/
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 关系建立时间
|
||||
*/
|
||||
private Date relationshipStart;
|
||||
|
||||
/**
|
||||
* 状态(正常/已结束)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 医生信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Doctor doctor;
|
||||
|
||||
/**
|
||||
* 患者信息
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Patient patient;
|
||||
}
|
||||
35
src/main/java/com/example/entity/Patient.java
Normal file
35
src/main/java/com/example/entity/Patient.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.example.entity;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 患者
|
||||
*/
|
||||
@Data
|
||||
@TableName("patient")
|
||||
public class Patient extends Account {
|
||||
|
||||
/** id */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
/** 账号 */
|
||||
private String username;
|
||||
/** 密码 */
|
||||
private String password;
|
||||
/** 名称 */
|
||||
private String name;
|
||||
/** 头像 */
|
||||
private String avatar;
|
||||
/** 性别 */
|
||||
private String sex;
|
||||
/** 手机号 */
|
||||
private String phone;
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
}
|
||||
17
src/main/java/com/example/entity/ResourceCategory.java
Normal file
17
src/main/java/com/example/entity/ResourceCategory.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName("resource_category")
|
||||
public class ResourceCategory {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String description;
|
||||
private Integer parentId;
|
||||
}
|
||||
57
src/main/java/com/example/entity/ResourceRating.java
Normal file
57
src/main/java/com/example/entity/ResourceRating.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.example.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 资源评分实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("resource_rating")
|
||||
public class ResourceRating {
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 资源ID
|
||||
*/
|
||||
private Integer resourceId;
|
||||
|
||||
/**
|
||||
* 患者ID
|
||||
*/
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 评分(1-5)
|
||||
*/
|
||||
private Integer rating;
|
||||
|
||||
/**
|
||||
* 评价内容
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 患者姓名 (非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String patientName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String resourceTitle;
|
||||
}
|
||||
121
src/main/java/com/example/entity/SymptomRecord.java
Normal file
121
src/main/java/com/example/entity/SymptomRecord.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@TableName("symptom_record")
|
||||
@Data
|
||||
public class SymptomRecord {
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 患者ID
|
||||
*/
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 症状描述
|
||||
*/
|
||||
private String symptomDesc;
|
||||
|
||||
/**
|
||||
* 严重程度等级(1-10)
|
||||
*/
|
||||
private Integer severityLevel;
|
||||
|
||||
/**
|
||||
* 情绪基线值(1-10)
|
||||
*/
|
||||
private Integer emotionScore;
|
||||
|
||||
/**
|
||||
* 活力持续时间(小时)
|
||||
*/
|
||||
private Integer energyDuration;
|
||||
|
||||
/**
|
||||
* 兴趣恢复度(百分比)
|
||||
*/
|
||||
private Integer interestRecovery;
|
||||
|
||||
/**
|
||||
* 入睡所需时间(分钟)
|
||||
*/
|
||||
private Integer sleepTime;
|
||||
|
||||
/**
|
||||
* 夜间觉醒次数
|
||||
*/
|
||||
private Integer wakeCount;
|
||||
|
||||
/**
|
||||
* 晨醒时间
|
||||
*/
|
||||
private String morningWake;
|
||||
|
||||
/**
|
||||
* 进食完成度(百分比)
|
||||
*/
|
||||
private Integer mealCompletion;
|
||||
|
||||
/**
|
||||
* 疼痛位置
|
||||
*/
|
||||
private String painLocation;
|
||||
|
||||
/**
|
||||
* 疼痛强度(1-10)
|
||||
*/
|
||||
private Integer painIntensity;
|
||||
|
||||
/**
|
||||
* 短期记忆测试成功数(0-3)
|
||||
*/
|
||||
private Integer memoryTest;
|
||||
|
||||
/**
|
||||
* 决策耗时(分钟)
|
||||
*/
|
||||
private Integer decisionTime;
|
||||
|
||||
/**
|
||||
* 注意力跨度(分钟)
|
||||
*/
|
||||
private Integer attentionSpan;
|
||||
|
||||
/**
|
||||
* 自杀意念频率(次数)
|
||||
*/
|
||||
private Integer suicidalThought;
|
||||
|
||||
/**
|
||||
* 记录时间
|
||||
*/
|
||||
private Date recordTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 患者信息(非数据库字段)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Patient patient;
|
||||
|
||||
/**
|
||||
* 患者名称(非数据库字段,用于搜索)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String patientName;
|
||||
}
|
||||
33
src/main/java/com/example/entity/TreatmentResource.java
Normal file
33
src/main/java/com/example/entity/TreatmentResource.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.example.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("treatment_resource")
|
||||
public class TreatmentResource {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private String title;
|
||||
private Integer categoryId;
|
||||
private String content;
|
||||
private String resourceUrl;
|
||||
private String applicableSymptoms;
|
||||
private Integer visitCount;
|
||||
private Integer downloadCount;
|
||||
private Integer publisherId;
|
||||
private String auditStatus;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String categoryName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String publisherName;
|
||||
}
|
||||
35
src/main/java/com/example/exception/CustomException.java
Normal file
35
src/main/java/com/example/exception/CustomException.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.example.exception;
|
||||
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
|
||||
public class CustomException extends RuntimeException {
|
||||
private String code;
|
||||
private String msg;
|
||||
|
||||
public CustomException(ResultCodeEnum resultCodeEnum) {
|
||||
this.code = resultCodeEnum.code;
|
||||
this.msg = resultCodeEnum.msg;
|
||||
}
|
||||
|
||||
public CustomException(String code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.example.exception;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import cn.hutool.log.LogFactory;
|
||||
import com.example.common.Result;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@ControllerAdvice(basePackages="com.example.controller")
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private static final Log log = LogFactory.get();
|
||||
|
||||
|
||||
//统一异常处理@ExceptionHandler,主要用于Exception
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody//返回json串
|
||||
public Result error(HttpServletRequest request, Exception e){
|
||||
log.error("异常信息:",e);
|
||||
return Result.error();
|
||||
}
|
||||
|
||||
@ExceptionHandler(CustomException.class)
|
||||
@ResponseBody//返回json串
|
||||
public Result customError(HttpServletRequest request, CustomException e){
|
||||
return Result.error(e.getCode(), e.getMsg());
|
||||
}
|
||||
}
|
||||
32
src/main/java/com/example/mapper/AdminMapper.java
Normal file
32
src/main/java/com/example/mapper/AdminMapper.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.example.entity.*;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
|
||||
public interface AdminMapper extends BaseMapper<Admin> {
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
List<Admin> selectAll(Admin admin);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
Admin selectById(Integer id);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
int deleteById(Integer id);
|
||||
|
||||
@Select("select * from admin where `username` = #{name}")
|
||||
Admin selectByUsername(@Param("name") String userName);
|
||||
|
||||
|
||||
|
||||
}
|
||||
41
src/main/java/com/example/mapper/AnnouncementMapper.java
Normal file
41
src/main/java/com/example/mapper/AnnouncementMapper.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.Announcement;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公告Mapper
|
||||
*/
|
||||
public interface AnnouncementMapper extends BaseMapper<Announcement> {
|
||||
|
||||
/**
|
||||
* 查询所有已发布的公告
|
||||
* @return 公告列表
|
||||
*/
|
||||
@Select("SELECT * FROM announcement WHERE status = 1 ORDER BY is_top DESC, create_time DESC")
|
||||
List<Announcement> selectAllPublished();
|
||||
|
||||
/**
|
||||
* 查询所有已发布的公告(分页)
|
||||
* @param title 标题关键字
|
||||
* @return 公告列表
|
||||
*/
|
||||
@Select("<script>SELECT * FROM announcement WHERE status = 1 " +
|
||||
"<if test=\"title != null and title != ''\">AND title LIKE CONCAT('%', #{title}, '%')</if>" +
|
||||
" ORDER BY is_top DESC, create_time DESC</script>")
|
||||
List<Announcement> selectAllPublishedWithKeyword(@Param("title") String title);
|
||||
|
||||
/**
|
||||
* 查询所有公告(包括草稿,仅管理员可用)
|
||||
* @param title 标题关键字
|
||||
* @return 公告列表
|
||||
*/
|
||||
@Select("<script>SELECT * FROM announcement " +
|
||||
"<if test=\"title != null and title != ''\">WHERE title LIKE CONCAT('%', #{title}, '%')</if>" +
|
||||
" ORDER BY is_top DESC, create_time DESC</script>")
|
||||
List<Announcement> selectAllForAdmin(@Param("title") String title);
|
||||
}
|
||||
50
src/main/java/com/example/mapper/AssessmentReportMapper.java
Normal file
50
src/main/java/com/example/mapper/AssessmentReportMapper.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.AssessmentReport;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AssessmentReportMapper extends BaseMapper<AssessmentReport> {
|
||||
|
||||
/**
|
||||
* 查询患者的评估报告列表
|
||||
*/
|
||||
@Select("SELECT ar.*, p.name as patientName " +
|
||||
"FROM assessment_report ar " +
|
||||
"LEFT JOIN patient p ON ar.patient_id = p.id " +
|
||||
"WHERE ar.patient_id = #{patientId} " +
|
||||
"ORDER BY ar.create_time DESC")
|
||||
List<AssessmentReport> selectByPatientId(@Param("patientId") Integer patientId);
|
||||
|
||||
/**
|
||||
* 查询医生负责的患者的评估报告列表
|
||||
*/
|
||||
@Select("SELECT ar.*, p.name as patientName " +
|
||||
"FROM assessment_report ar " +
|
||||
"LEFT JOIN patient p ON ar.patient_id = p.id " +
|
||||
"INNER JOIN doctor_patient dp ON ar.patient_id = dp.patient_id " +
|
||||
"WHERE dp.doctor_id = #{doctorId} " +
|
||||
"ORDER BY ar.create_time DESC")
|
||||
List<AssessmentReport> selectByDoctorId(@Param("doctorId") Integer doctorId);
|
||||
|
||||
/**
|
||||
* 查询所有评估报告(管理员使用)
|
||||
*/
|
||||
@Select("SELECT ar.*, p.name as patientName " +
|
||||
"FROM assessment_report ar " +
|
||||
"LEFT JOIN patient p ON ar.patient_id = p.id " +
|
||||
"ORDER BY ar.create_time DESC")
|
||||
List<AssessmentReport> selectAllReports();
|
||||
|
||||
/**
|
||||
* 根据ID查询评估报告
|
||||
*/
|
||||
@Select("SELECT id, patient_id, report_period, start_date, end_date, summary, trend_analysis, " +
|
||||
"recommendation, doctor_comment, status, create_time " +
|
||||
"FROM assessment_report " +
|
||||
"WHERE id = #{id}")
|
||||
AssessmentReport selectById(@Param("id") Integer id);
|
||||
}
|
||||
51
src/main/java/com/example/mapper/ChatMessageMapper.java
Normal file
51
src/main/java/com/example/mapper/ChatMessageMapper.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.ChatMessage;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ChatMessageMapper extends BaseMapper<ChatMessage> {
|
||||
|
||||
/**
|
||||
* 查询两个用户之间的聊天记录
|
||||
*/
|
||||
@Select("SELECT * FROM chat_message WHERE " +
|
||||
"((sender_id = #{userId1} AND sender_type = #{userType1} AND receiver_id = #{userId2} AND receiver_type = #{userType2}) OR " +
|
||||
"(sender_id = #{userId2} AND sender_type = #{userType2} AND receiver_id = #{userId1} AND receiver_type = #{userType1})) " +
|
||||
"ORDER BY send_time ASC")
|
||||
List<ChatMessage> selectChatHistory(@Param("userId1") Integer userId1, @Param("userType1") String userType1,
|
||||
@Param("userId2") Integer userId2, @Param("userType2") String userType2);
|
||||
|
||||
/**
|
||||
* 将消息标记为已读
|
||||
*/
|
||||
@Update("UPDATE chat_message SET is_read = 1, read_time = NOW() " +
|
||||
"WHERE receiver_id = #{receiverId} AND receiver_type = #{receiverType} " +
|
||||
"AND sender_id = #{senderId} AND sender_type = #{senderType} AND is_read = 0")
|
||||
int markAsRead(@Param("receiverId") Integer receiverId, @Param("receiverType") String receiverType,
|
||||
@Param("senderId") Integer senderId, @Param("senderType") String senderType);
|
||||
|
||||
/**
|
||||
* 查询用户的聊天列表(最近联系人)
|
||||
*/
|
||||
@Select("SELECT DISTINCT " +
|
||||
"CASE WHEN sender_id = #{userId} AND sender_type = #{userType} THEN receiver_id ELSE sender_id END AS contact_id, " +
|
||||
"CASE WHEN sender_id = #{userId} AND sender_type = #{userType} THEN receiver_type ELSE sender_type END AS contact_type " +
|
||||
"FROM chat_message " +
|
||||
"WHERE (sender_id = #{userId} AND sender_type = #{userType}) OR (receiver_id = #{userId} AND receiver_type = #{userType}) " +
|
||||
"ORDER BY MAX(send_time) DESC")
|
||||
List<Object[]> selectChatContacts(@Param("userId") Integer userId, @Param("userType") String userType);
|
||||
|
||||
/**
|
||||
* 统计未读消息数
|
||||
*/
|
||||
@Select("SELECT COUNT(*) FROM chat_message WHERE receiver_id = #{receiverId} AND receiver_type = #{receiverType} AND sender_id = #{senderId} AND sender_type = #{senderType} AND is_read = 0")
|
||||
int countUnreadMessages(@Param("receiverId") Integer receiverId, @Param("receiverType") String receiverType,
|
||||
@Param("senderId") Integer senderId, @Param("senderType") String senderType);
|
||||
}
|
||||
29
src/main/java/com/example/mapper/DoctorMapper.java
Normal file
29
src/main/java/com/example/mapper/DoctorMapper.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.example.entity.*;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
|
||||
public interface DoctorMapper extends BaseMapper<Doctor> {
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
List<Doctor> selectAll(Doctor doctor);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
Doctor selectById(Integer id);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
int deleteById(Integer id);
|
||||
|
||||
@Select("select * from doctor where `username` = #{name}")
|
||||
Doctor selectByUsername(@Param("name") String userName);
|
||||
}
|
||||
28
src/main/java/com/example/mapper/DoctorPatientMapper.java
Normal file
28
src/main/java/com/example/mapper/DoctorPatientMapper.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface DoctorPatientMapper extends BaseMapper<DoctorPatient> {
|
||||
|
||||
/**
|
||||
* 根据医生ID查询关联的患者
|
||||
* @param doctorId 医生ID
|
||||
* @param name 患者姓名(可选)
|
||||
* @return 患者列表
|
||||
*/
|
||||
List<DoctorPatient> selectByDoctorId(@Param("doctorId") Integer doctorId, @Param("name") String name);
|
||||
|
||||
/**
|
||||
* 根据患者ID查询关联的医生
|
||||
* @param patientId 患者ID
|
||||
* @param name 医生姓名(可选)
|
||||
* @return 医生列表
|
||||
*/
|
||||
List<DoctorPatient> selectByPatientId(@Param("patientId") Integer patientId, @Param("name") String name);
|
||||
}
|
||||
29
src/main/java/com/example/mapper/PatientMapper.java
Normal file
29
src/main/java/com/example/mapper/PatientMapper.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.example.entity.*;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
|
||||
public interface PatientMapper extends BaseMapper<Patient> {
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
List<Patient> selectAll(Patient patient);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
Patient selectById(Integer id);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
int deleteById(Integer id);
|
||||
|
||||
@Select("select * from patient where `username` = #{name}")
|
||||
Patient selectByUsername(@Param("name") String userName);
|
||||
}
|
||||
20
src/main/java/com/example/mapper/ResourceCategoryMapper.java
Normal file
20
src/main/java/com/example/mapper/ResourceCategoryMapper.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.ResourceCategory;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ResourceCategoryMapper extends BaseMapper<ResourceCategory> {
|
||||
|
||||
@Select("SELECT * FROM resource_category WHERE parent_id = #{parentId}")
|
||||
List<ResourceCategory> selectByParentId(Integer parentId);
|
||||
|
||||
@Select("SELECT * FROM resource_category ORDER BY parent_id, id")
|
||||
List<ResourceCategory> selectAllCategories();
|
||||
|
||||
@Select("SELECT * FROM resource_category WHERE name LIKE CONCAT('%', #{name}, '%') ORDER BY parent_id, id")
|
||||
List<ResourceCategory> selectPage(@Param("name") String name);
|
||||
}
|
||||
46
src/main/java/com/example/mapper/ResourceRatingMapper.java
Normal file
46
src/main/java/com/example/mapper/ResourceRatingMapper.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.entity.ResourceRating;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ResourceRatingMapper extends BaseMapper<ResourceRating> {
|
||||
|
||||
/**
|
||||
* 根据资源ID查询评分记录,包含用户名信息
|
||||
*/
|
||||
@Select("SELECT r.*, p.name as patient_name " +
|
||||
"FROM resource_rating r " +
|
||||
"LEFT JOIN patient p ON r.patient_id = p.id " +
|
||||
"WHERE r.resource_id = #{resourceId} " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
List<ResourceRating> selectByResourceId(@Param("resourceId") Integer resourceId);
|
||||
|
||||
/**
|
||||
* 查询用户是否已对某资源评分
|
||||
*/
|
||||
@Select("SELECT COUNT(*) FROM resource_rating WHERE resource_id = #{resourceId} AND patient_id = #{patientId}")
|
||||
int countByResourceIdAndPatientId(@Param("resourceId") Integer resourceId, @Param("patientId") Integer patientId);
|
||||
|
||||
/**
|
||||
* 获取资源的平均评分
|
||||
*/
|
||||
@Select("SELECT IFNULL(AVG(rating), 0) FROM resource_rating WHERE resource_id = #{resourceId}")
|
||||
double getAverageRating(@Param("resourceId") Integer resourceId);
|
||||
|
||||
/**
|
||||
* 获取资源的评价数量
|
||||
*/
|
||||
@Select("SELECT COUNT(*) FROM resource_rating WHERE resource_id = #{resourceId}")
|
||||
Integer getRatingCount(@Param("resourceId") Integer resourceId);
|
||||
|
||||
/**
|
||||
* 根据资源ID和患者ID查询评分记录
|
||||
*/
|
||||
@Select("SELECT * FROM resource_rating WHERE resource_id = #{resourceId} AND patient_id = #{patientId} LIMIT 1")
|
||||
ResourceRating findByResourceAndPatient(@Param("resourceId") Integer resourceId, @Param("patientId") Integer patientId);
|
||||
}
|
||||
36
src/main/java/com/example/mapper/SymptomRecordMapper.java
Normal file
36
src/main/java/com/example/mapper/SymptomRecordMapper.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.entity.SymptomRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 症状记录Mapper接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface SymptomRecordMapper extends BaseMapper<SymptomRecord> {
|
||||
|
||||
/**
|
||||
* 查询症状记录并关联患者信息
|
||||
* @param patientId 患者ID (可选)
|
||||
* @return 症状记录列表
|
||||
*/
|
||||
List<SymptomRecord> selectWithPatient(@Param("patientId") Integer patientId);
|
||||
|
||||
/**
|
||||
* 根据患者ID和日期范围查询症状记录
|
||||
*/
|
||||
@Select("SELECT * FROM symptom_record " +
|
||||
"WHERE patient_id = #{patientId} " +
|
||||
"AND record_time BETWEEN #{startDate} AND #{endDate} " +
|
||||
"ORDER BY record_time ASC")
|
||||
List<SymptomRecord> selectByPatientIdAndDateRange(
|
||||
@Param("patientId") Integer patientId,
|
||||
@Param("startDate") LocalDate startDate,
|
||||
@Param("endDate") LocalDate endDate);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.example.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TreatmentResourceMapper extends BaseMapper<TreatmentResource> {
|
||||
|
||||
@Select("SELECT r.*, c.name as category_name " +
|
||||
"FROM treatment_resource r " +
|
||||
"LEFT JOIN resource_category c ON r.category_id = c.id " +
|
||||
"WHERE r.audit_status = '已通过' " +
|
||||
"AND (r.title LIKE CONCAT('%', #{keyword}, '%') " +
|
||||
"OR r.applicable_symptoms LIKE CONCAT('%', #{keyword}, '%')) " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
Page<TreatmentResource> searchResourcesForPatient(Page<TreatmentResource> page, @Param("keyword") String keyword);
|
||||
|
||||
@Select("SELECT r.*, c.name as category_name " +
|
||||
"FROM treatment_resource r " +
|
||||
"LEFT JOIN resource_category c ON r.category_id = c.id " +
|
||||
"WHERE (r.title LIKE CONCAT('%', #{keyword}, '%') " +
|
||||
"OR r.applicable_symptoms LIKE CONCAT('%', #{keyword}, '%')) " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
Page<TreatmentResource> searchResourcesForAdmin(Page<TreatmentResource> page, @Param("keyword") String keyword);
|
||||
|
||||
@Select("SELECT r.*, c.name as category_name " +
|
||||
"FROM treatment_resource r " +
|
||||
"LEFT JOIN resource_category c ON r.category_id = c.id " +
|
||||
"WHERE (r.title LIKE CONCAT('%', #{keyword}, '%') " +
|
||||
"OR r.applicable_symptoms LIKE CONCAT('%', #{keyword}, '%')) " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
List<TreatmentResource> selectAll(@Param("keyword") String keyword);
|
||||
|
||||
@Select("SELECT r.*, c.name as category_name " +
|
||||
"FROM treatment_resource r " +
|
||||
"LEFT JOIN resource_category c ON r.category_id = c.id " +
|
||||
"WHERE r.audit_status = '已通过' " +
|
||||
"AND (r.title LIKE CONCAT('%', #{keyword}, '%') " +
|
||||
"OR r.applicable_symptoms LIKE CONCAT('%', #{keyword}, '%')) " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
List<TreatmentResource> selectAllAudited(@Param("keyword") String keyword);
|
||||
|
||||
@Select("SELECT r.*, c.name as category_name " +
|
||||
"FROM treatment_resource r " +
|
||||
"LEFT JOIN resource_category c ON r.category_id = c.id " +
|
||||
"WHERE r.category_id = #{categoryId} " +
|
||||
"AND r.audit_status = '已通过' " +
|
||||
"ORDER BY r.create_time DESC")
|
||||
List<TreatmentResource> selectByCategoryId(@Param("categoryId") Integer categoryId);
|
||||
|
||||
@Update("UPDATE treatment_resource SET visit_count = visit_count + 1 WHERE id = #{id}")
|
||||
int incrementVisitCount(@Param("id") Integer id);
|
||||
|
||||
@Update("UPDATE treatment_resource SET download_count = download_count + 1 WHERE id = #{id}")
|
||||
int incrementDownloadCount(@Param("id") Integer id);
|
||||
|
||||
/**
|
||||
* 根据发布者ID查询所有资源
|
||||
*/
|
||||
@Select("SELECT * FROM treatment_resource WHERE publisher_id = #{publisherId} AND (title LIKE CONCAT('%', #{keyword}, '%') OR applicable_symptoms LIKE CONCAT('%', #{keyword}, '%'))")
|
||||
List<TreatmentResource> selectByPublisher(@Param("publisherId") Integer publisherId, @Param("keyword") String keyword);
|
||||
}
|
||||
171
src/main/java/com/example/service/AIChatService.java
Normal file
171
src/main/java/com/example/service/AIChatService.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.exception.CustomException;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Service
|
||||
public class AIChatService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AIChatService.class);
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Value("${dashscope.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${dashscope.model}")
|
||||
private String model;
|
||||
|
||||
private final String API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";
|
||||
|
||||
/**
|
||||
* 发送消息到通义千问API并获取回复
|
||||
*/
|
||||
public String sendMessage(String message) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
log.info("准备发送消息到通义千问API,用户ID: {}, 消息内容: {}", currentUser.getId(), message);
|
||||
|
||||
// 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", "Bearer " + apiKey);
|
||||
|
||||
// 构建请求体
|
||||
Map<String, Object> requestBody = new HashMap<>();
|
||||
requestBody.put("model", model);
|
||||
|
||||
// 添加参数
|
||||
Map<String, Object> parameters = new HashMap<>();
|
||||
parameters.put("temperature", 0.7);
|
||||
parameters.put("top_p", 0.8);
|
||||
parameters.put("result_format", "message");
|
||||
requestBody.put("parameters", parameters);
|
||||
|
||||
// 添加用户消息
|
||||
Map<String, Object> input = new HashMap<>();
|
||||
List<Map<String, Object>> messages = new ArrayList<>();
|
||||
|
||||
Map<String, Object> userMessage = new HashMap<>();
|
||||
userMessage.put("role", "user");
|
||||
userMessage.put("content", message);
|
||||
messages.add(userMessage);
|
||||
|
||||
input.put("messages", messages);
|
||||
requestBody.put("input", input);
|
||||
|
||||
try {
|
||||
// 记录完整请求
|
||||
log.info("发送请求到API: {}", API_URL);
|
||||
log.info("请求体: {}", requestBody);
|
||||
|
||||
// 发送请求
|
||||
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
|
||||
ResponseEntity<Map> response = restTemplate.exchange(API_URL, HttpMethod.POST, requestEntity, Map.class);
|
||||
|
||||
// 记录响应
|
||||
log.info("API响应状态码: {}", response.getStatusCode());
|
||||
log.debug("API响应内容: {}", response.getBody());
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
Map<String, Object> responseBody = response.getBody();
|
||||
if (responseBody != null) {
|
||||
// 检查错误字段
|
||||
if (responseBody.containsKey("code") && !responseBody.get("code").equals(200) && responseBody.containsKey("message")) {
|
||||
String errorMessage = (String) responseBody.get("message");
|
||||
log.error("API返回错误: {}", errorMessage);
|
||||
return "API错误: " + errorMessage;
|
||||
}
|
||||
|
||||
// 尝试多种可能的响应格式
|
||||
String content = extractContentFromResponse(responseBody);
|
||||
if (content != null) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("无法从API响应中提取内容: {}", responseBody);
|
||||
return "抱歉,我无法理解您的问题。";
|
||||
} else {
|
||||
log.error("API响应错误状态码: {}", response.getStatusCode());
|
||||
throw new CustomException(ResultCodeEnum.SYSTEM_ERROR.code, "AI服务异常,请稍后再试");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("调用通义千问API出错: ", e);
|
||||
throw new CustomException(ResultCodeEnum.SYSTEM_ERROR.code, "AI服务异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试从不同格式的响应中提取内容
|
||||
*/
|
||||
private String extractContentFromResponse(Map<String, Object> responseBody) {
|
||||
// 格式1: output.choices[0].message.content
|
||||
try {
|
||||
if (responseBody.containsKey("output")) {
|
||||
Map<String, Object> output = (Map<String, Object>) responseBody.get("output");
|
||||
if (output.containsKey("choices")) {
|
||||
List<Map<String, Object>> choices = (List<Map<String, Object>>) output.get("choices");
|
||||
if (choices != null && !choices.isEmpty()) {
|
||||
Map<String, Object> choice = choices.get(0);
|
||||
if (choice.containsKey("message")) {
|
||||
Map<String, Object> message = (Map<String, Object>) choice.get("message");
|
||||
if (message.containsKey("content")) {
|
||||
return (String) message.get("content");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("尝试格式1提取内容失败: ", e);
|
||||
}
|
||||
|
||||
// 格式2: data.choices[0].content
|
||||
try {
|
||||
if (responseBody.containsKey("data")) {
|
||||
Map<String, Object> data = (Map<String, Object>) responseBody.get("data");
|
||||
if (data.containsKey("choices")) {
|
||||
List<Map<String, Object>> choices = (List<Map<String, Object>>) data.get("choices");
|
||||
if (choices != null && !choices.isEmpty()) {
|
||||
Map<String, Object> choice = choices.get(0);
|
||||
if (choice.containsKey("content")) {
|
||||
return (String) choice.get("content");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("尝试格式2提取内容失败: ", e);
|
||||
}
|
||||
|
||||
// 格式3: result
|
||||
try {
|
||||
if (responseBody.containsKey("result")) {
|
||||
return (String) responseBody.get("result");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("尝试格式3提取内容失败: ", e);
|
||||
}
|
||||
|
||||
// 记录完整响应,便于调试
|
||||
log.info("响应体解析失败,完整响应: {}", responseBody);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
134
src/main/java/com/example/service/AdminService.java
Normal file
134
src/main/java/com/example/service/AdminService.java
Normal file
@@ -0,0 +1,134 @@
|
||||
package com.example.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.example.common.Constants;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.*;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.*;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AdminService {
|
||||
|
||||
@Resource
|
||||
private AdminMapper adminMapper;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
public void add(Admin admin) {
|
||||
// 唯一校验
|
||||
Admin dbAdmin = adminMapper.selectByUsername(admin.getUsername());
|
||||
if (ObjectUtil.isNotNull(dbAdmin)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
|
||||
}
|
||||
if (ObjectUtil.isEmpty(admin.getPassword())) {
|
||||
admin.setPassword(Constants.USER_DEFAULT_PASSWORD);
|
||||
}
|
||||
if (ObjectUtil.isEmpty(admin.getName())) {
|
||||
admin.setName(admin.getUsername());
|
||||
}
|
||||
admin.setRole("admin");
|
||||
adminMapper.insert(admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public void deleteById(Integer id) {
|
||||
adminMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
public void deleteBatch(List<Integer> ids) {
|
||||
for (Integer id : ids) {
|
||||
adminMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
public void updateById(Admin admin) {
|
||||
adminMapper.updateById(admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
public Admin selectById(Integer id) {
|
||||
return adminMapper.selectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
public List<Admin> selectAll(Admin admin) {
|
||||
return adminMapper.selectAll(admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageInfo<Admin> selectPage(Admin admin, Integer pageNum, Integer pageSize) {
|
||||
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<Admin> list = adminMapper.selectAll(admin);
|
||||
|
||||
return PageInfo.of(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
public void register(Account account) {
|
||||
Admin admin = new Admin();
|
||||
admin.setUsername(account.getUsername());
|
||||
admin.setPassword(account.getPassword());
|
||||
this.add(admin);
|
||||
}
|
||||
|
||||
public Admin login(Account account) {
|
||||
Admin dbAdmin = adminMapper.selectByUsername(account.getUsername());
|
||||
if (ObjectUtil.isNull(dbAdmin)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
if (!account.getPassword().equals(dbAdmin.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
|
||||
}
|
||||
// 生成token
|
||||
String tokenData = dbAdmin.getId() + "-admin";
|
||||
String token = TokenUtils.genToken(tokenData, dbAdmin.getPassword());
|
||||
dbAdmin.setToken(token);
|
||||
|
||||
|
||||
return dbAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public void updatePassword(Account account) {
|
||||
Admin dbAdmin = adminMapper.selectByUsername(account.getUsername());
|
||||
if (ObjectUtil.isNull(dbAdmin)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
if (!account.getPassword().equals(dbAdmin.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
|
||||
}
|
||||
dbAdmin.setPassword(account.getNewPassword());
|
||||
adminMapper.updateById(dbAdmin);
|
||||
}
|
||||
|
||||
}
|
||||
164
src/main/java/com/example/service/AnnouncementService.java
Normal file
164
src/main/java/com/example/service/AnnouncementService.java
Normal file
@@ -0,0 +1,164 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.Announcement;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.AnnouncementMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公告服务类
|
||||
*/
|
||||
@Service
|
||||
public class AnnouncementService {
|
||||
|
||||
@Resource
|
||||
private AnnouncementMapper announcementMapper;
|
||||
|
||||
/**
|
||||
* 添加公告
|
||||
* @param announcement 公告信息
|
||||
*/
|
||||
public void add(Announcement announcement) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有管理员可以发布公告");
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (announcement.getIsTop() == null) {
|
||||
announcement.setIsTop(false);
|
||||
}
|
||||
|
||||
if (announcement.getStatus() == null) {
|
||||
announcement.setStatus(0); // 默认为草稿状态
|
||||
}
|
||||
|
||||
announcement.setCreateTime(new Date());
|
||||
announcement.setPublisherId(currentUser.getId());
|
||||
announcement.setPublisherName(currentUser.getName());
|
||||
|
||||
announcementMapper.insert(announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新公告
|
||||
* @param announcement 公告信息
|
||||
*/
|
||||
public void update(Announcement announcement) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有管理员可以修改公告");
|
||||
}
|
||||
|
||||
// 获取原公告
|
||||
Announcement dbAnnouncement = announcementMapper.selectById(announcement.getId());
|
||||
if (dbAnnouncement == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "公告不存在");
|
||||
}
|
||||
|
||||
// 只更新部分字段,保留创建时间等信息
|
||||
dbAnnouncement.setTitle(announcement.getTitle());
|
||||
dbAnnouncement.setContent(announcement.getContent());
|
||||
dbAnnouncement.setIsTop(announcement.getIsTop());
|
||||
dbAnnouncement.setStatus(announcement.getStatus());
|
||||
|
||||
announcementMapper.updateById(dbAnnouncement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除公告
|
||||
* @param id 公告ID
|
||||
*/
|
||||
public void delete(Integer id) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有管理员可以删除公告");
|
||||
}
|
||||
|
||||
announcementMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公告详情
|
||||
* @param id 公告ID
|
||||
* @return 公告信息
|
||||
*/
|
||||
public Announcement getById(Integer id) {
|
||||
return announcementMapper.selectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已发布的公告(分页,所有用户可访问)
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @param title 标题关键字
|
||||
* @return 分页公告列表
|
||||
*/
|
||||
public PageInfo<Announcement> getPublishedPage(Integer pageNum, Integer pageSize, String title) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<Announcement> list = announcementMapper.selectAllPublishedWithKeyword(title);
|
||||
return new PageInfo<>(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有公告(分页,包括草稿,仅管理员可用)
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @param title 标题关键字
|
||||
* @return 分页公告列表
|
||||
*/
|
||||
public PageInfo<Announcement> getAllForAdmin(Integer pageNum, Integer pageSize, String title) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有管理员可以查看所有公告");
|
||||
}
|
||||
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<Announcement> list = announcementMapper.selectAllForAdmin(title);
|
||||
return new PageInfo<>(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新的几条已发布公告(用于首页展示)
|
||||
* @param limit 限制条数
|
||||
* @return 公告列表
|
||||
*/
|
||||
public List<Announcement> getLatestPublished(Integer limit) {
|
||||
PageHelper.startPage(1, limit);
|
||||
return announcementMapper.selectAllPublished();
|
||||
}
|
||||
}
|
||||
530
src/main/java/com/example/service/AssessmentReportService.java
Normal file
530
src/main/java/com/example/service/AssessmentReportService.java
Normal file
@@ -0,0 +1,530 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.AssessmentReport;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.entity.SymptomRecord;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.AssessmentReportMapper;
|
||||
import com.example.mapper.SymptomRecordMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Service
|
||||
public class AssessmentReportService {
|
||||
|
||||
@Resource
|
||||
private AssessmentReportMapper assessmentReportMapper;
|
||||
|
||||
@Resource
|
||||
private SymptomRecordMapper symptomRecordMapper;
|
||||
|
||||
@Resource
|
||||
private PatientService patientService;
|
||||
|
||||
/**
|
||||
* 生成评估报告
|
||||
* @param patientId 患者ID
|
||||
* @param reportPeriod 报告周期类型("week"/"month")
|
||||
* @return 生成的评估报告
|
||||
*/
|
||||
public AssessmentReport generateReport(Integer patientId, String reportPeriod) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
String role = currentUser.getRole();
|
||||
if (!"admin".equals(role) && !"doctor".equals(role) &&
|
||||
(!"patient".equals(role) || !currentUser.getId().equals(patientId))) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权生成该患者的评估报告");
|
||||
}
|
||||
|
||||
// 设置报告时间范围
|
||||
LocalDate endDate = LocalDate.now();
|
||||
LocalDate startDate;
|
||||
|
||||
if ("week".equals(reportPeriod)) {
|
||||
startDate = endDate.minusWeeks(1);
|
||||
} else if ("month".equals(reportPeriod)) {
|
||||
startDate = endDate.minusMonths(1);
|
||||
} else {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无效的报告周期类型");
|
||||
}
|
||||
|
||||
// 获取时间范围内的症状记录
|
||||
List<SymptomRecord> records = symptomRecordMapper.selectByPatientIdAndDateRange(
|
||||
patientId, startDate, endDate);
|
||||
|
||||
if (records.isEmpty()) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "所选时间范围内没有症状记录");
|
||||
}
|
||||
|
||||
// 创建评估报告
|
||||
AssessmentReport report = new AssessmentReport();
|
||||
report.setPatientId(patientId);
|
||||
report.setReportPeriod("week".equals(reportPeriod) ? "周报" : "月报");
|
||||
report.setStartDate(startDate);
|
||||
report.setEndDate(endDate);
|
||||
report.setStatus("未读");
|
||||
report.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 生成报告内容
|
||||
generateReportContent(report, records);
|
||||
|
||||
// 保存报告
|
||||
assessmentReportMapper.insert(report);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成报告内容
|
||||
*/
|
||||
private void generateReportContent(AssessmentReport report, List<SymptomRecord> records) {
|
||||
// 计算统计数据
|
||||
DoubleSummaryStatistics severityStats = records.stream()
|
||||
.map(SymptomRecord::getSeverityLevel)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics emotionStats = records.stream()
|
||||
.map(SymptomRecord::getEmotionScore)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics sleepStats = records.stream()
|
||||
.map(SymptomRecord::getSleepTime)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.summaryStatistics();
|
||||
|
||||
// 生成总体评估
|
||||
StringBuilder summary = new StringBuilder();
|
||||
summary.append("本")
|
||||
.append(report.getReportPeriod())
|
||||
.append("期间(")
|
||||
.append(report.getStartDate().format(DateTimeFormatter.ISO_LOCAL_DATE))
|
||||
.append(" 至 ")
|
||||
.append(report.getEndDate().format(DateTimeFormatter.ISO_LOCAL_DATE))
|
||||
.append("),共记录了 ")
|
||||
.append(records.size())
|
||||
.append(" 条症状数据。\n\n");
|
||||
|
||||
summary.append("严重程度评分:平均 ")
|
||||
.append(String.format("%.1f", severityStats.getAverage()))
|
||||
.append(",最高 ")
|
||||
.append((int)severityStats.getMax())
|
||||
.append(",最低 ")
|
||||
.append((int)severityStats.getMin())
|
||||
.append("。\n");
|
||||
|
||||
summary.append("情绪基线评分:平均 ")
|
||||
.append(String.format("%.1f", emotionStats.getAverage()))
|
||||
.append(",最高 ")
|
||||
.append((int)emotionStats.getMax())
|
||||
.append(",最低 ")
|
||||
.append((int)emotionStats.getMin())
|
||||
.append("。\n");
|
||||
|
||||
summary.append("入睡时间:平均 ")
|
||||
.append(String.format("%.1f", sleepStats.getAverage()))
|
||||
.append(" 分钟,最长 ")
|
||||
.append((int)sleepStats.getMax())
|
||||
.append(" 分钟,最短 ")
|
||||
.append((int)sleepStats.getMin())
|
||||
.append(" 分钟。\n");
|
||||
|
||||
// 设置总体评估
|
||||
report.setSummary(summary.toString());
|
||||
|
||||
// 生成趋势分析
|
||||
StringBuilder trend = new StringBuilder();
|
||||
|
||||
// 按记录时间转换为LocalDate进行分组
|
||||
Map<LocalDate, List<SymptomRecord>> recordsByDate = new HashMap<>();
|
||||
for (SymptomRecord record : records) {
|
||||
Date recordTime = record.getRecordTime();
|
||||
if (recordTime != null) {
|
||||
LocalDate recordDate = new java.sql.Date(recordTime.getTime()).toLocalDate();
|
||||
if (!recordsByDate.containsKey(recordDate)) {
|
||||
recordsByDate.put(recordDate, new ArrayList<>());
|
||||
}
|
||||
recordsByDate.get(recordDate).add(record);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取排序后的日期列表
|
||||
List<LocalDate> dates = new ArrayList<>(recordsByDate.keySet());
|
||||
dates.sort(LocalDate::compareTo);
|
||||
|
||||
if (dates.size() > 1) {
|
||||
// 计算首尾日期的平均严重程度
|
||||
double firstDaySeverity = recordsByDate.get(dates.get(0)).stream()
|
||||
.map(SymptomRecord::getSeverityLevel)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.average()
|
||||
.orElse(0);
|
||||
|
||||
double lastDaySeverity = recordsByDate.get(dates.get(dates.size() - 1)).stream()
|
||||
.map(SymptomRecord::getSeverityLevel)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.average()
|
||||
.orElse(0);
|
||||
|
||||
// 趋势分析
|
||||
trend.append("症状严重程度:");
|
||||
if (lastDaySeverity < firstDaySeverity) {
|
||||
trend.append("整体呈下降趋势,相比初始记录降低了 ")
|
||||
.append(String.format("%.1f", firstDaySeverity - lastDaySeverity))
|
||||
.append(" 点,病情有所好转。");
|
||||
} else if (lastDaySeverity > firstDaySeverity) {
|
||||
trend.append("整体呈上升趋势,相比初始记录增加了 ")
|
||||
.append(String.format("%.1f", lastDaySeverity - firstDaySeverity))
|
||||
.append(" 点,病情有所加重。");
|
||||
} else {
|
||||
trend.append("整体保持稳定,症状严重程度变化不明显。");
|
||||
}
|
||||
trend.append("\n\n");
|
||||
|
||||
// 情绪基线趋势分析
|
||||
double firstDayEmotion = recordsByDate.get(dates.get(0)).stream()
|
||||
.map(SymptomRecord::getEmotionScore)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.average()
|
||||
.orElse(0);
|
||||
|
||||
double lastDayEmotion = recordsByDate.get(dates.get(dates.size() - 1)).stream()
|
||||
.map(SymptomRecord::getEmotionScore)
|
||||
.filter(val -> val != null)
|
||||
.mapToDouble(Integer::doubleValue)
|
||||
.average()
|
||||
.orElse(0);
|
||||
|
||||
trend.append("情绪状态:");
|
||||
if (lastDayEmotion > firstDayEmotion) {
|
||||
trend.append("呈积极改善趋势,情绪基线提高了 ")
|
||||
.append(String.format("%.1f", lastDayEmotion - firstDayEmotion))
|
||||
.append(" 点。");
|
||||
} else if (lastDayEmotion < firstDayEmotion) {
|
||||
trend.append("呈下降趋势,情绪基线降低了 ")
|
||||
.append(String.format("%.1f", firstDayEmotion - lastDayEmotion))
|
||||
.append(" 点,需要关注情绪变化。");
|
||||
} else {
|
||||
trend.append("情绪基线保持稳定。");
|
||||
}
|
||||
} else {
|
||||
trend.append("记录天数不足,无法进行趋势分析。建议持续记录症状,以便更准确地评估病情变化。");
|
||||
}
|
||||
|
||||
// 设置趋势分析
|
||||
report.setTrendAnalysis(trend.toString());
|
||||
|
||||
// 生成建议
|
||||
StringBuilder recommendation = new StringBuilder();
|
||||
|
||||
// 基于严重程度的建议
|
||||
double avgSeverity = severityStats.getAverage();
|
||||
if (avgSeverity >= 7) {
|
||||
recommendation.append("● 症状严重程度较高,建议及时就医或保持与医生的密切沟通。\n");
|
||||
recommendation.append("● 注意休息,避免过度劳累和压力。\n");
|
||||
} else if (avgSeverity >= 4) {
|
||||
recommendation.append("● 症状处于中等程度,建议遵循医嘱进行调整。\n");
|
||||
recommendation.append("● 可以尝试适当的放松训练和心理调适方法。\n");
|
||||
} else {
|
||||
recommendation.append("● 症状程度较轻,建议继续保持良好的生活习惯。\n");
|
||||
}
|
||||
|
||||
// 基于情绪状态的建议
|
||||
double avgEmotion = emotionStats.getAverage();
|
||||
if (avgEmotion <= 4) {
|
||||
recommendation.append("● 情绪基线较低,建议尝试以下方法改善情绪:\n");
|
||||
recommendation.append(" - 每天进行至少30分钟的适当运动\n");
|
||||
recommendation.append(" - 学习简单的冥想或深呼吸放松技巧\n");
|
||||
recommendation.append(" - 与亲友多交流,分享感受\n");
|
||||
}
|
||||
|
||||
// 基于睡眠情况的建议
|
||||
double avgSleep = sleepStats.getAverage();
|
||||
if (avgSleep > 30) {
|
||||
recommendation.append("● 入睡时间较长,建议改善睡眠习惯:\n");
|
||||
recommendation.append(" - 保持规律的睡眠时间表\n");
|
||||
recommendation.append(" - 睡前一小时避免使用电子设备\n");
|
||||
recommendation.append(" - 睡前可以喝杯温热的牛奶或进行轻度放松活动\n");
|
||||
}
|
||||
|
||||
// 一般性建议
|
||||
recommendation.append("\n持续记录症状变化,这将帮助您和医生更好地了解病情发展,制定更适合的治疗方案。");
|
||||
|
||||
// 设置建议
|
||||
report.setRecommendation(recommendation.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 每周一凌晨2点自动生成周报
|
||||
*/
|
||||
@Scheduled(cron = "0 0 2 ? * MON")
|
||||
public void generateWeeklyReports() {
|
||||
List<Account> patients = getPatients();
|
||||
for (Account patient : patients) {
|
||||
try {
|
||||
generateReportForPatient(patient.getId(), "week");
|
||||
} catch (Exception e) {
|
||||
// 记录错误但不中断流程
|
||||
System.err.println("为患者 " + patient.getId() + " 生成周报失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 每月1日凌晨3点自动生成月报
|
||||
*/
|
||||
@Scheduled(cron = "0 0 3 1 * ?")
|
||||
public void generateMonthlyReports() {
|
||||
List<Account> patients = getPatients();
|
||||
for (Account patient : patients) {
|
||||
try {
|
||||
generateReportForPatient(patient.getId(), "month");
|
||||
} catch (Exception e) {
|
||||
// 记录错误但不中断流程
|
||||
System.err.println("为患者 " + patient.getId() + " 生成月报失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为患者生成报告(内部方法,用于定时任务)
|
||||
*/
|
||||
private AssessmentReport generateReportForPatient(Integer patientId, String reportPeriod) {
|
||||
LocalDate endDate = LocalDate.now();
|
||||
LocalDate startDate;
|
||||
|
||||
if ("week".equals(reportPeriod)) {
|
||||
startDate = endDate.minusWeeks(1);
|
||||
} else {
|
||||
startDate = endDate.minusMonths(1);
|
||||
}
|
||||
|
||||
// 获取时间范围内的症状记录
|
||||
List<SymptomRecord> records = symptomRecordMapper.selectByPatientIdAndDateRange(
|
||||
patientId, startDate, endDate);
|
||||
|
||||
// 如果没有记录,则不生成报告
|
||||
if (records.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建评估报告
|
||||
AssessmentReport report = new AssessmentReport();
|
||||
report.setPatientId(patientId);
|
||||
report.setReportPeriod("week".equals(reportPeriod) ? "周报" : "月报");
|
||||
report.setStartDate(startDate);
|
||||
report.setEndDate(endDate);
|
||||
report.setStatus("未读");
|
||||
report.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 生成报告内容
|
||||
generateReportContent(report, records);
|
||||
|
||||
// 保存报告
|
||||
assessmentReportMapper.insert(report);
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有患者列表
|
||||
*/
|
||||
private List<Account> getPatients() {
|
||||
// 使用PatientService获取所有患者
|
||||
Patient queryPatient = new Patient();
|
||||
return new ArrayList<>(patientService.selectAll(queryPatient));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取患者的评估报告列表
|
||||
*/
|
||||
public List<AssessmentReport> getReportsByPatientId(Integer patientId) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
String role = currentUser.getRole();
|
||||
if (!"admin".equals(role) && !"doctor".equals(role) &&
|
||||
(!"patient".equals(role) || !currentUser.getId().equals(patientId))) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权查看该患者的评估报告");
|
||||
}
|
||||
|
||||
return assessmentReportMapper.selectByPatientId(patientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取医生负责的患者的评估报告列表
|
||||
*/
|
||||
public List<AssessmentReport> getReportsByDoctorId(Integer doctorId) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
String role = currentUser.getRole();
|
||||
if (!"admin".equals(role) &&
|
||||
(!"doctor".equals(role) || !currentUser.getId().equals(doctorId))) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权查看该医生负责的评估报告");
|
||||
}
|
||||
|
||||
return assessmentReportMapper.selectByDoctorId(doctorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有评估报告列表(管理员使用)
|
||||
*/
|
||||
public List<AssessmentReport> getAllReports() {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权查看所有评估报告");
|
||||
}
|
||||
|
||||
return assessmentReportMapper.selectAllReports();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加医生批注
|
||||
*/
|
||||
public void addDoctorComment(Integer reportId, String comment) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"doctor".equals(currentUser.getRole()) && !"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权添加批注");
|
||||
}
|
||||
|
||||
// 获取报告
|
||||
AssessmentReport report = assessmentReportMapper.selectById(reportId);
|
||||
if (report == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "报告不存在");
|
||||
}
|
||||
|
||||
// 更新批注
|
||||
report.setDoctorComment(comment);
|
||||
assessmentReportMapper.updateById(report);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新报告状态为已读
|
||||
*/
|
||||
public void markAsRead(Integer reportId) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 获取报告
|
||||
AssessmentReport report = assessmentReportMapper.selectById(reportId);
|
||||
if (report == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "报告不存在");
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!"admin".equals(currentUser.getRole()) &&
|
||||
!"doctor".equals(currentUser.getRole()) &&
|
||||
(!"patient".equals(currentUser.getRole()) || !currentUser.getId().equals(report.getPatientId()))) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权操作该报告");
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
report.setStatus("已读");
|
||||
assessmentReportMapper.updateById(report);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ID获取单个报告
|
||||
* @param reportId 报告ID
|
||||
* @return 评估报告对象
|
||||
*/
|
||||
public AssessmentReport getReportById(Integer reportId) {
|
||||
if (reportId == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "报告ID不能为空");
|
||||
}
|
||||
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 查询报告
|
||||
AssessmentReport report = assessmentReportMapper.selectById(reportId);
|
||||
|
||||
if (report == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
String role = currentUser.getRole();
|
||||
Integer userId = currentUser.getId();
|
||||
|
||||
// 管理员可以查看所有报告
|
||||
if ("admin".equals(role)) {
|
||||
return report;
|
||||
}
|
||||
|
||||
// 医生可以查看自己负责的患者的报告
|
||||
if ("doctor".equals(role)) {
|
||||
List<AssessmentReport> doctorReports = getReportsByDoctorId(userId);
|
||||
boolean hasAccess = doctorReports.stream()
|
||||
.anyMatch(r -> r.getId().equals(reportId));
|
||||
|
||||
if (hasAccess) {
|
||||
return report;
|
||||
}
|
||||
}
|
||||
|
||||
// 患者只能查看自己的报告
|
||||
if ("patient".equals(role) && userId.equals(report.getPatientId())) {
|
||||
return report;
|
||||
}
|
||||
|
||||
// 无权限访问
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权访问该报告");
|
||||
}
|
||||
}
|
||||
221
src/main/java/com/example/service/ChatMessageService.java
Normal file
221
src/main/java/com/example/service/ChatMessageService.java
Normal file
@@ -0,0 +1,221 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.ChatMessage;
|
||||
import com.example.entity.Doctor;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.ChatMessageMapper;
|
||||
import com.example.mapper.DoctorMapper;
|
||||
import com.example.mapper.PatientMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ChatMessageService {
|
||||
|
||||
@Resource
|
||||
private ChatMessageMapper chatMessageMapper;
|
||||
|
||||
@Resource
|
||||
private DoctorPatientService doctorPatientService;
|
||||
|
||||
@Resource
|
||||
private DoctorMapper doctorMapper;
|
||||
|
||||
@Resource
|
||||
private PatientMapper patientMapper;
|
||||
|
||||
/**
|
||||
* 发送消息 - 通过HTTP接口调用
|
||||
*/
|
||||
public ChatMessage sendMessage(ChatMessage chatMessage) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 根据当前用户角色设置发送者信息
|
||||
chatMessage.setSenderId(currentUser.getId());
|
||||
chatMessage.setSenderType(currentUser.getRole());
|
||||
|
||||
// 检查发送者和接收者是否有关联关系
|
||||
checkRelationship(chatMessage.getSenderId(), chatMessage.getSenderType(),
|
||||
chatMessage.getReceiverId(), chatMessage.getReceiverType());
|
||||
|
||||
// 设置消息状态
|
||||
chatMessage.setSendTime(new Date());
|
||||
chatMessage.setIsRead(false);
|
||||
|
||||
// 保存消息
|
||||
chatMessageMapper.insert(chatMessage);
|
||||
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接保存消息 - 通过WebSocket调用,不依赖TokenUtils
|
||||
*/
|
||||
public ChatMessage directSaveMessage(ChatMessage chatMessage) {
|
||||
// 检查发送者和接收者是否有关联关系
|
||||
checkRelationship(chatMessage.getSenderId(), chatMessage.getSenderType(),
|
||||
chatMessage.getReceiverId(), chatMessage.getReceiverType());
|
||||
|
||||
// 保存消息
|
||||
chatMessageMapper.insert(chatMessage);
|
||||
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天历史记录
|
||||
*/
|
||||
public List<ChatMessage> getChatHistory(Integer contactId, String contactType) {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 检查关系
|
||||
checkRelationship(currentUser.getId(), currentUser.getRole(), contactId, contactType);
|
||||
|
||||
// 查询聊天记录
|
||||
List<ChatMessage> messages = chatMessageMapper.selectChatHistory(
|
||||
currentUser.getId(), currentUser.getRole(), contactId, contactType);
|
||||
|
||||
// 将对方发送的未读消息标记为已读
|
||||
chatMessageMapper.markAsRead(currentUser.getId(), currentUser.getRole(), contactId, contactType);
|
||||
|
||||
// 填充发送者和接收者的名称
|
||||
fillUserInfo(messages);
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取联系人列表
|
||||
*/
|
||||
public List<Map<String, Object>> getContactList() {
|
||||
// 获取当前用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
|
||||
// 根据用户角色获取联系人
|
||||
if ("doctor".equals(currentUser.getRole())) {
|
||||
// 医生获取其患者列表
|
||||
List<DoctorPatient> relations = doctorPatientService.selectByDoctorId(currentUser.getId(), null);
|
||||
for (DoctorPatient relation : relations) {
|
||||
if ("正常".equals(relation.getStatus()) && relation.getPatient() != null) {
|
||||
Map<String, Object> contact = new HashMap<>();
|
||||
contact.put("contactId", relation.getPatientId());
|
||||
contact.put("contactType", "patient");
|
||||
contact.put("contactName", relation.getPatient().getName());
|
||||
contact.put("contactAvatar", relation.getPatient().getAvatar());
|
||||
// 查询未读消息数
|
||||
int unread = chatMessageMapper.countUnreadMessages(
|
||||
currentUser.getId(), currentUser.getRole(), relation.getPatientId(), "patient");
|
||||
contact.put("unreadCount", unread);
|
||||
|
||||
// 查询最新一条消息
|
||||
List<ChatMessage> lastMessages = chatMessageMapper.selectChatHistory(
|
||||
currentUser.getId(), currentUser.getRole(), relation.getPatientId(), "patient");
|
||||
if (!lastMessages.isEmpty()) {
|
||||
contact.put("lastMessage", lastMessages.get(lastMessages.size() - 1));
|
||||
}
|
||||
|
||||
result.add(contact);
|
||||
}
|
||||
}
|
||||
} else if ("patient".equals(currentUser.getRole())) {
|
||||
// 患者获取其医生列表
|
||||
List<DoctorPatient> relations = doctorPatientService.selectByPatientId(currentUser.getId(), null);
|
||||
for (DoctorPatient relation : relations) {
|
||||
if ("正常".equals(relation.getStatus()) && relation.getDoctor() != null) {
|
||||
Map<String, Object> contact = new HashMap<>();
|
||||
contact.put("contactId", relation.getDoctorId());
|
||||
contact.put("contactType", "doctor");
|
||||
contact.put("contactName", relation.getDoctor().getName());
|
||||
contact.put("contactAvatar", relation.getDoctor().getAvatar());
|
||||
// 查询未读消息数
|
||||
int unread = chatMessageMapper.countUnreadMessages(
|
||||
currentUser.getId(), currentUser.getRole(), relation.getDoctorId(), "doctor");
|
||||
contact.put("unreadCount", unread);
|
||||
|
||||
// 查询最新一条消息
|
||||
List<ChatMessage> lastMessages = chatMessageMapper.selectChatHistory(
|
||||
currentUser.getId(), currentUser.getRole(), relation.getDoctorId(), "doctor");
|
||||
if (!lastMessages.isEmpty()) {
|
||||
contact.put("lastMessage", lastMessages.get(lastMessages.size() - 1));
|
||||
}
|
||||
|
||||
result.add(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户关系
|
||||
*/
|
||||
private void checkRelationship(Integer senderId, String senderType, Integer receiverId, String receiverType) {
|
||||
// 检查医生和患者是否存在关联关系
|
||||
if ("doctor".equals(senderType) && "patient".equals(receiverType)) {
|
||||
List<DoctorPatient> relations = doctorPatientService.selectByDoctorId(senderId, null);
|
||||
boolean hasRelation = relations.stream()
|
||||
.anyMatch(dp -> dp.getPatientId().equals(receiverId) && "正常".equals(dp.getStatus()));
|
||||
|
||||
if (!hasRelation) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "您与该患者没有关联关系");
|
||||
}
|
||||
} else if ("patient".equals(senderType) && "doctor".equals(receiverType)) {
|
||||
List<DoctorPatient> relations = doctorPatientService.selectByPatientId(senderId, null);
|
||||
boolean hasRelation = relations.stream()
|
||||
.anyMatch(dp -> dp.getDoctorId().equals(receiverId) && "正常".equals(dp.getStatus()));
|
||||
|
||||
if (!hasRelation) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "您与该医生没有关联关系");
|
||||
}
|
||||
} else {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无效的聊天关系");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充用户信息
|
||||
*/
|
||||
private void fillUserInfo(List<ChatMessage> messages) {
|
||||
for (ChatMessage message : messages) {
|
||||
// 填充发送者信息
|
||||
if ("doctor".equals(message.getSenderType())) {
|
||||
Doctor doctor = doctorMapper.selectById(message.getSenderId());
|
||||
if (doctor != null) {
|
||||
message.setSenderName(doctor.getName());
|
||||
message.setSenderAvatar(doctor.getAvatar());
|
||||
}
|
||||
} else if ("patient".equals(message.getSenderType())) {
|
||||
Patient patient = patientMapper.selectById(message.getSenderId());
|
||||
if (patient != null) {
|
||||
message.setSenderName(patient.getName());
|
||||
message.setSenderAvatar(patient.getAvatar());
|
||||
}
|
||||
}
|
||||
|
||||
// 可以根据需要填充接收者信息
|
||||
}
|
||||
}
|
||||
}
|
||||
121
src/main/java/com/example/service/DoctorPatientService.java
Normal file
121
src/main/java/com/example/service/DoctorPatientService.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package com.example.service;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.Result;
|
||||
import com.example.entity.Doctor;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.entity.Patient;
|
||||
import com.example.mapper.DoctorMapper;
|
||||
import com.example.mapper.DoctorPatientMapper;
|
||||
import com.example.mapper.PatientMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class DoctorPatientService {
|
||||
|
||||
@Resource
|
||||
private DoctorPatientMapper doctorPatientMapper;
|
||||
|
||||
@Resource
|
||||
private DoctorMapper doctorMapper;
|
||||
|
||||
@Resource
|
||||
private PatientMapper patientMapper;
|
||||
|
||||
/**
|
||||
* 新增医生患者关系
|
||||
* @param doctorPatient 关系信息
|
||||
*/
|
||||
public void add(DoctorPatient doctorPatient) {
|
||||
// 检查医生ID是否存在
|
||||
Doctor doctor = doctorMapper.selectById(doctorPatient.getDoctorId());
|
||||
if (ObjectUtil.isEmpty(doctor)) {
|
||||
throw new RuntimeException("医生不存在");
|
||||
}
|
||||
|
||||
// 检查患者ID是否存在
|
||||
Patient patient = patientMapper.selectById(doctorPatient.getPatientId());
|
||||
if (ObjectUtil.isEmpty(patient)) {
|
||||
throw new RuntimeException("患者不存在");
|
||||
}
|
||||
|
||||
// 检查关系是否已存在
|
||||
LambdaQueryWrapper<DoctorPatient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DoctorPatient::getDoctorId, doctorPatient.getDoctorId())
|
||||
.eq(DoctorPatient::getPatientId, doctorPatient.getPatientId())
|
||||
.eq(DoctorPatient::getStatus, "正常");
|
||||
|
||||
if (doctorPatientMapper.selectCount(queryWrapper) > 0) {
|
||||
throw new RuntimeException("医生和患者关系已存在");
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
doctorPatient.setRelationshipStart(new Date());
|
||||
doctorPatient.setStatus("正常");
|
||||
doctorPatient.setCreateTime(new Date());
|
||||
|
||||
doctorPatientMapper.insert(doctorPatient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新医生患者关系
|
||||
* @param doctorPatient 关系信息
|
||||
*/
|
||||
public void update(DoctorPatient doctorPatient) {
|
||||
DoctorPatient dbDoctorPatient = doctorPatientMapper.selectById(doctorPatient.getId());
|
||||
if (ObjectUtil.isEmpty(dbDoctorPatient)) {
|
||||
throw new RuntimeException("关系不存在");
|
||||
}
|
||||
|
||||
doctorPatientMapper.updateById(doctorPatient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除医生患者关系
|
||||
* @param id 关系ID
|
||||
*/
|
||||
public void delete(Integer id) {
|
||||
doctorPatientMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束医生患者关系
|
||||
* @param id 关系ID
|
||||
*/
|
||||
public void endRelationship(Integer id) {
|
||||
DoctorPatient doctorPatient = doctorPatientMapper.selectById(id);
|
||||
if (ObjectUtil.isEmpty(doctorPatient)) {
|
||||
throw new RuntimeException("关系不存在");
|
||||
}
|
||||
|
||||
doctorPatient.setStatus("已结束");
|
||||
doctorPatientMapper.updateById(doctorPatient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据医生ID查询患者
|
||||
* @param doctorId 医生ID
|
||||
* @param name 患者姓名(可选)
|
||||
* @return 患者列表
|
||||
*/
|
||||
public List<DoctorPatient> selectByDoctorId(Integer doctorId, String name) {
|
||||
return doctorPatientMapper.selectByDoctorId(doctorId, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID查询医生
|
||||
* @param patientId 患者ID
|
||||
* @param name 医生姓名(可选)
|
||||
* @return 医生列表
|
||||
*/
|
||||
public List<DoctorPatient> selectByPatientId(Integer patientId, String name) {
|
||||
return doctorPatientMapper.selectByPatientId(patientId, name);
|
||||
}
|
||||
}
|
||||
132
src/main/java/com/example/service/DoctorService.java
Normal file
132
src/main/java/com/example/service/DoctorService.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package com.example.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.example.common.Constants;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.*;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.*;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class DoctorService {
|
||||
|
||||
@Resource
|
||||
private DoctorMapper doctorMapper;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
public void add(Doctor doctor) {
|
||||
// 唯一校验
|
||||
Doctor dbDoctor = doctorMapper.selectByUsername(doctor.getUsername());
|
||||
if (ObjectUtil.isNotNull(dbDoctor)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
|
||||
}
|
||||
if (ObjectUtil.isEmpty(doctor.getPassword())) {
|
||||
doctor.setPassword(Constants.USER_DEFAULT_PASSWORD);
|
||||
}
|
||||
if (ObjectUtil.isEmpty(doctor.getName())) {
|
||||
doctor.setName(doctor.getUsername());
|
||||
}
|
||||
doctor.setRole("doctor");
|
||||
doctorMapper.insert(doctor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public void deleteById(Integer id) {
|
||||
doctorMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
public void deleteBatch(List<Integer> ids) {
|
||||
for (Integer id : ids) {
|
||||
doctorMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
public void updateById(Doctor doctor) {
|
||||
doctorMapper.updateById(doctor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
*/
|
||||
public Doctor selectById(Integer id) {
|
||||
return doctorMapper.selectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
public List<Doctor> selectAll(Doctor doctor) {
|
||||
return doctorMapper.selectAll(doctor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageInfo<Doctor> selectPage(Doctor doctor, Integer pageNum, Integer pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<Doctor> list = doctorMapper.selectAll(doctor);
|
||||
return PageInfo.of(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
public void register(Account account) {
|
||||
Doctor doctor = new Doctor();
|
||||
doctor.setUsername(account.getUsername());
|
||||
doctor.setPassword(account.getPassword());
|
||||
doctor.setSex(account.getSex());
|
||||
doctor.setName(account.getName());
|
||||
doctor.setPhone(account.getPhone());
|
||||
this.add(doctor);
|
||||
}
|
||||
|
||||
public Doctor login(Account account) {
|
||||
Doctor dbDoctor = doctorMapper.selectByUsername(account.getUsername());
|
||||
if (ObjectUtil.isNull(dbDoctor)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
if (!account.getPassword().equals(dbDoctor.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
|
||||
}
|
||||
// 生成token
|
||||
String tokenData = dbDoctor.getId() + "-doctor";
|
||||
String token = TokenUtils.genToken(tokenData, dbDoctor.getPassword());
|
||||
dbDoctor.setToken(token);
|
||||
return dbDoctor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public void updatePassword(Account account) {
|
||||
Doctor dbDoctor = doctorMapper.selectByUsername(account.getUsername());
|
||||
if (ObjectUtil.isNull(dbDoctor)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
if (!account.getPassword().equals(dbDoctor.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
|
||||
}
|
||||
dbDoctor.setPassword(account.getNewPassword());
|
||||
doctorMapper.updateById(dbDoctor);
|
||||
}
|
||||
}
|
||||
200
src/main/java/com/example/service/PatientService.java
Normal file
200
src/main/java/com/example/service/PatientService.java
Normal file
@@ -0,0 +1,200 @@
|
||||
package com.example.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.Constants;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.*;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.*;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PatientService {
|
||||
|
||||
@Resource
|
||||
private PatientMapper patientMapper;
|
||||
|
||||
@Resource
|
||||
private DoctorPatientMapper doctorPatientMapper;
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
public void add(Patient patient) {
|
||||
// 校验数据
|
||||
if (ObjectUtil.isEmpty(patient.getUsername()) || ObjectUtil.isEmpty(patient.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_LOST_ERROR);
|
||||
}
|
||||
|
||||
// 检查用户名是否存在
|
||||
Patient dbPatient = selectByUsername(patient.getUsername());
|
||||
if (dbPatient != null) {
|
||||
throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (ObjectUtil.isEmpty(patient.getName())) {
|
||||
patient.setName(patient.getUsername());
|
||||
}
|
||||
patient.setRole("patient");
|
||||
|
||||
patientMapper.insert(patient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ID删除
|
||||
*/
|
||||
public void deleteById(Integer id) {
|
||||
patientMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*/
|
||||
public void deleteBatch(List<Integer> ids) {
|
||||
for (Integer id : ids) {
|
||||
patientMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
*/
|
||||
public void updateById(Patient patient) {
|
||||
patientMapper.updateById(patient);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ID查询
|
||||
*/
|
||||
public Patient selectById(Integer id) {
|
||||
return patientMapper.selectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名查询
|
||||
*/
|
||||
public Patient selectByUsername(String username) {
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Patient::getUsername, username);
|
||||
return patientMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*/
|
||||
public List<Patient> selectAll(Patient patient) {
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
return patientMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询 - 按患者信息查询
|
||||
*/
|
||||
public Page<Patient> selectPage(Patient patient, Integer pageNum, Integer pageSize) {
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (ObjectUtil.isNotEmpty(patient.getName())) {
|
||||
queryWrapper.like(Patient::getName, patient.getName());
|
||||
}
|
||||
|
||||
return patientMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询 - 按患者姓名查询
|
||||
*/
|
||||
public Page<Patient> selectPage(Integer pageNum, Integer pageSize, String name) {
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (ObjectUtil.isNotEmpty(name)) {
|
||||
queryWrapper.like(Patient::getName, name);
|
||||
}
|
||||
|
||||
return patientMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*/
|
||||
public Account login(Account account) {
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Patient::getUsername, account.getUsername());
|
||||
queryWrapper.eq(Patient::getPassword, account.getPassword());
|
||||
Patient patient = patientMapper.selectOne(queryWrapper);
|
||||
|
||||
if (ObjectUtil.isEmpty(patient)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
|
||||
}
|
||||
|
||||
// 生成token
|
||||
String tokenData = patient.getId() + "-" + patient.getRole();
|
||||
String token = TokenUtils.genToken(tokenData, patient.getPassword());
|
||||
patient.setToken(token);
|
||||
|
||||
return patient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
public void register(Account account) {
|
||||
// 检查用户名是否已存在
|
||||
LambdaQueryWrapper<Patient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Patient::getUsername, account.getUsername());
|
||||
if (patientMapper.selectCount(queryWrapper) > 0) {
|
||||
throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
|
||||
}
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setUsername(account.getUsername());
|
||||
patient.setPassword(account.getPassword());
|
||||
patient.setName(account.getName());
|
||||
patient.setSex(account.getSex());
|
||||
patient.setPhone(account.getPhone());
|
||||
patient.setEmail(account.getEmail());
|
||||
patient.setRole("patient");
|
||||
add(patient);
|
||||
|
||||
// 如果选择了医生,则建立医患关系
|
||||
if (account.getDoctorId() != null) {
|
||||
DoctorPatient doctorPatient = new DoctorPatient();
|
||||
doctorPatient.setDoctorId(account.getDoctorId());
|
||||
doctorPatient.setPatientId(patient.getId());
|
||||
doctorPatient.setRelationshipStart(new Date());
|
||||
doctorPatient.setStatus("正常");
|
||||
doctorPatient.setCreateTime(new Date());
|
||||
|
||||
doctorPatientMapper.insert(doctorPatient);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public void updatePassword(Account account) {
|
||||
Patient dbPatient = selectById(account.getId());
|
||||
if (ObjectUtil.isEmpty(dbPatient)) {
|
||||
throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
|
||||
}
|
||||
|
||||
if (!account.getPassword().equals(dbPatient.getPassword())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
|
||||
}
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId(account.getId());
|
||||
patient.setPassword(account.getNewPassword());
|
||||
|
||||
updateById(patient);
|
||||
}
|
||||
}
|
||||
385
src/main/java/com/example/service/RecommendationService.java
Normal file
385
src/main/java/com/example/service/RecommendationService.java
Normal file
@@ -0,0 +1,385 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.ResourceRating;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.ResourceCategoryMapper;
|
||||
import com.example.mapper.ResourceRatingMapper;
|
||||
import com.example.mapper.TreatmentResourceMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 基于协同过滤的推荐服务
|
||||
*/
|
||||
@Service
|
||||
public class RecommendationService {
|
||||
|
||||
@Resource
|
||||
private ResourceRatingMapper resourceRatingMapper;
|
||||
|
||||
@Resource
|
||||
private TreatmentResourceMapper treatmentResourceMapper;
|
||||
|
||||
@Resource
|
||||
private ResourceCategoryMapper resourceCategoryMapper;
|
||||
|
||||
/**
|
||||
* 获取针对特定用户的资源推荐
|
||||
* @param userId 用户ID
|
||||
* @param limit 推荐数量限制
|
||||
* @return 推荐资源列表
|
||||
*/
|
||||
public List<Map<String, Object>> getRecommendationsForUser(Integer userId, Integer limit) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null || !userId.equals(currentUser.getId())) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 只有患者才能获取推荐
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有患者才能获取推荐");
|
||||
}
|
||||
|
||||
// 获取所有评分数据
|
||||
List<ResourceRating> allRatings = resourceRatingMapper.selectList(null);
|
||||
|
||||
// 获取目标用户的评分记录
|
||||
List<ResourceRating> userRatings = allRatings.stream()
|
||||
.filter(r -> r.getPatientId().equals(userId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 如果用户没有评分记录,返回热门资源
|
||||
if (userRatings.isEmpty()) {
|
||||
return getPopularResources(limit);
|
||||
}
|
||||
|
||||
// 计算用户相似度
|
||||
List<Map<String, Object>> userSimilarities = calculateUserSimilarity(userId, allRatings);
|
||||
|
||||
// 获取用户已评分的资源ID
|
||||
Set<Integer> userRatedResourceIds = userRatings.stream()
|
||||
.map(ResourceRating::getResourceId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 获取所有已审核通过的资源
|
||||
List<TreatmentResource> allResources = treatmentResourceMapper.selectAllAudited("");
|
||||
|
||||
// 获取用户未评分的资源
|
||||
List<TreatmentResource> unratedResources = allResources.stream()
|
||||
.filter(resource -> !userRatedResourceIds.contains(resource.getId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 对每个未评分资源预测评分并生成推荐
|
||||
List<Map<String, Object>> recommendationsWithScores = new ArrayList<>();
|
||||
|
||||
for (TreatmentResource resource : unratedResources) {
|
||||
double predictedRating = predictRating(resource.getId(), userSimilarities, allRatings);
|
||||
|
||||
// 只推荐预测评分大于0的资源
|
||||
if (predictedRating > 0) {
|
||||
Map<String, Object> recommendation = new HashMap<>();
|
||||
recommendation.put("resource", resource);
|
||||
recommendation.put("predictedRating", predictedRating);
|
||||
recommendation.put("similarityScore", Math.min(100, predictedRating * 20)); // 将5分制转换为100分制
|
||||
recommendation.put("reason", getRecommendationReason(resource, userSimilarities, allRatings, userRatings, allResources));
|
||||
|
||||
// 添加分类名称
|
||||
com.example.entity.ResourceCategory category = resourceCategoryMapper.selectById(resource.getCategoryId());
|
||||
if (category != null) {
|
||||
recommendation.put("categoryName", category.getName());
|
||||
}
|
||||
|
||||
recommendationsWithScores.add(recommendation);
|
||||
}
|
||||
}
|
||||
|
||||
// 按预测评分降序排序,取前几个作为推荐
|
||||
recommendationsWithScores.sort((a, b) ->
|
||||
Double.compare((Double) b.get("predictedRating"), (Double) a.get("predictedRating")));
|
||||
|
||||
// 限制推荐数量
|
||||
int resultLimit = Math.min(limit, recommendationsWithScores.size());
|
||||
return recommendationsWithScores.subList(0, resultLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取热门资源作为推荐(用于冷启动问题)
|
||||
*/
|
||||
private List<Map<String, Object>> getPopularResources(Integer limit) {
|
||||
// 获取所有已审核通过的资源
|
||||
List<TreatmentResource> allResources = treatmentResourceMapper.selectAllAudited("");
|
||||
|
||||
// 按照访问次数和下载次数之和排序
|
||||
allResources.sort((a, b) -> {
|
||||
int aPopularity = (a.getVisitCount() != null ? a.getVisitCount() : 0) +
|
||||
(a.getDownloadCount() != null ? a.getDownloadCount() : 0);
|
||||
int bPopularity = (b.getVisitCount() != null ? b.getVisitCount() : 0) +
|
||||
(b.getDownloadCount() != null ? b.getDownloadCount() : 0);
|
||||
return Integer.compare(bPopularity, aPopularity);
|
||||
});
|
||||
|
||||
// 转换为推荐格式
|
||||
List<Map<String, Object>> recommendations = new ArrayList<>();
|
||||
int resultLimit = Math.min(limit, allResources.size());
|
||||
|
||||
for (int i = 0; i < resultLimit; i++) {
|
||||
TreatmentResource resource = allResources.get(i);
|
||||
Map<String, Object> recommendation = new HashMap<>();
|
||||
recommendation.put("resource", resource);
|
||||
recommendation.put("predictedRating", 4.0); // 默认预测评分
|
||||
recommendation.put("similarityScore", 80.0); // 默认相似度分数
|
||||
recommendation.put("reason", "系统热门资源推荐");
|
||||
|
||||
// 添加分类名称
|
||||
com.example.entity.ResourceCategory category = resourceCategoryMapper.selectById(resource.getCategoryId());
|
||||
if (category != null) {
|
||||
recommendation.put("categoryName", category.getName());
|
||||
}
|
||||
|
||||
recommendations.add(recommendation);
|
||||
}
|
||||
|
||||
return recommendations;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算用户相似度 - 使用余弦相似度
|
||||
*/
|
||||
private List<Map<String, Object>> calculateUserSimilarity(Integer targetUserId, List<ResourceRating> allRatings) {
|
||||
// 获取目标用户的评分记录
|
||||
List<ResourceRating> targetUserRatings = allRatings.stream()
|
||||
.filter(r -> r.getPatientId().equals(targetUserId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (targetUserRatings.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 用户ID列表(去除目标用户)
|
||||
List<Integer> userIds = allRatings.stream()
|
||||
.map(ResourceRating::getPatientId)
|
||||
.distinct()
|
||||
.filter(id -> !id.equals(targetUserId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 计算每个用户与目标用户的相似度
|
||||
List<Map<String, Object>> similarities = new ArrayList<>();
|
||||
|
||||
for (Integer userId : userIds) {
|
||||
// 获取当前用户的评分记录
|
||||
List<ResourceRating> userRatings = allRatings.stream()
|
||||
.filter(r -> r.getPatientId().equals(userId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (userRatings.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 找出两个用户共同评分的资源
|
||||
Set<Integer> targetResourceIds = targetUserRatings.stream()
|
||||
.map(ResourceRating::getResourceId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Integer> userResourceIds = userRatings.stream()
|
||||
.map(ResourceRating::getResourceId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Integer> commonResourceIds = new HashSet<>(targetResourceIds);
|
||||
commonResourceIds.retainAll(userResourceIds);
|
||||
|
||||
// 如果没有共同评分的资源,相似度为0
|
||||
if (commonResourceIds.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 提取两个用户对共同资源的评分向量
|
||||
double[] targetVector = new double[commonResourceIds.size()];
|
||||
double[] userVector = new double[commonResourceIds.size()];
|
||||
|
||||
int index = 0;
|
||||
for (Integer resourceId : commonResourceIds) {
|
||||
double targetRating = targetUserRatings.stream()
|
||||
.filter(r -> r.getResourceId().equals(resourceId))
|
||||
.findFirst()
|
||||
.map(r -> (double) r.getRating())
|
||||
.orElse(0.0);
|
||||
|
||||
double userRating = userRatings.stream()
|
||||
.filter(r -> r.getResourceId().equals(resourceId))
|
||||
.findFirst()
|
||||
.map(r -> (double) r.getRating())
|
||||
.orElse(0.0);
|
||||
|
||||
targetVector[index] = targetRating;
|
||||
userVector[index] = userRating;
|
||||
index++;
|
||||
}
|
||||
|
||||
// 计算余弦相似度
|
||||
// 余弦相似度 = (A·B) / (||A|| * ||B||)
|
||||
double dotProduct = 0.0;
|
||||
double targetMagnitude = 0.0;
|
||||
double userMagnitude = 0.0;
|
||||
|
||||
for (int i = 0; i < targetVector.length; i++) {
|
||||
dotProduct += targetVector[i] * userVector[i];
|
||||
targetMagnitude += targetVector[i] * targetVector[i];
|
||||
userMagnitude += userVector[i] * userVector[i];
|
||||
}
|
||||
|
||||
targetMagnitude = Math.sqrt(targetMagnitude);
|
||||
userMagnitude = Math.sqrt(userMagnitude);
|
||||
|
||||
// 避免除以零
|
||||
double similarity = (targetMagnitude > 0 && userMagnitude > 0)
|
||||
? dotProduct / (targetMagnitude * userMagnitude)
|
||||
: 0;
|
||||
|
||||
Map<String, Object> userSimilarity = new HashMap<>();
|
||||
userSimilarity.put("userId", userId);
|
||||
userSimilarity.put("similarity", similarity);
|
||||
similarities.add(userSimilarity);
|
||||
}
|
||||
|
||||
// 按相似度降序排序
|
||||
similarities.sort((a, b) -> Double.compare(
|
||||
(Double) b.get("similarity"),
|
||||
(Double) a.get("similarity")
|
||||
));
|
||||
|
||||
return similarities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预测用户对资源的评分
|
||||
*/
|
||||
private double predictRating(Integer resourceId, List<Map<String, Object>> userSimilarities,
|
||||
List<ResourceRating> allRatings) {
|
||||
// 获取已对该资源评分的相似用户
|
||||
List<Map<String, Object>> similarUsersWithRating = userSimilarities.stream()
|
||||
.filter(s -> allRatings.stream()
|
||||
.anyMatch(r -> r.getPatientId().equals(s.get("userId")) &&
|
||||
r.getResourceId().equals(resourceId)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 如果没有相似用户对该资源评分,返回默认预测值
|
||||
if (similarUsersWithRating.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 计算加权评分和
|
||||
double weightedSum = 0.0;
|
||||
double similaritySum = 0.0;
|
||||
|
||||
for (Map<String, Object> user : similarUsersWithRating) {
|
||||
Integer userId = (Integer) user.get("userId");
|
||||
double similarity = (Double) user.get("similarity");
|
||||
|
||||
// 找到该用户对该资源的评分
|
||||
double rating = allRatings.stream()
|
||||
.filter(r -> r.getPatientId().equals(userId) && r.getResourceId().equals(resourceId))
|
||||
.findFirst()
|
||||
.map(r -> (double) r.getRating())
|
||||
.orElse(0.0);
|
||||
|
||||
// 加权和
|
||||
weightedSum += similarity * rating;
|
||||
similaritySum += similarity;
|
||||
}
|
||||
|
||||
// 计算加权平均
|
||||
return similaritySum > 0 ? weightedSum / similaritySum : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推荐理由
|
||||
*/
|
||||
private String getRecommendationReason(TreatmentResource resource,
|
||||
List<Map<String, Object>> userSimilarities,
|
||||
List<ResourceRating> allRatings,
|
||||
List<ResourceRating> userRatings,
|
||||
List<TreatmentResource> allResources) {
|
||||
// 找出评分最高的相似用户对该资源的评价
|
||||
List<Map<String, Object>> topSimilarUsers = userSimilarities.stream()
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 找出这些用户中有对该资源评分的用户
|
||||
List<Map<String, Object>> usersWithRating = topSimilarUsers.stream()
|
||||
.filter(s -> allRatings.stream()
|
||||
.anyMatch(r -> r.getPatientId().equals(s.get("userId")) &&
|
||||
r.getResourceId().equals(resource.getId())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (usersWithRating.isEmpty()) {
|
||||
// 基于内容的推荐理由
|
||||
if (!userRatings.isEmpty()) {
|
||||
// 查找用户评分最高的资源
|
||||
ResourceRating topRatedRating = userRatings.stream()
|
||||
.max(Comparator.comparing(ResourceRating::getRating))
|
||||
.orElse(null);
|
||||
|
||||
if (topRatedRating != null) {
|
||||
// 获取用户最喜欢的资源详情
|
||||
Integer topRatedResourceId = topRatedRating.getResourceId();
|
||||
TreatmentResource topRatedResource = allResources.stream()
|
||||
.filter(r -> r.getId().equals(topRatedResourceId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
// 如果当前资源与用户最喜欢的资源属于同一分类
|
||||
if (topRatedResource != null && resource.getCategoryId().equals(topRatedResource.getCategoryId())) {
|
||||
return "根据您对同类资源的偏好推荐";
|
||||
}
|
||||
|
||||
// 如果当前资源适用的症状与用户评分高的资源相似
|
||||
List<String> userPreferredSymptoms = userRatings.stream()
|
||||
.filter(r -> r.getRating() >= 4)
|
||||
.map(r -> {
|
||||
// 获取资源详情
|
||||
Optional<TreatmentResource> res = allResources.stream()
|
||||
.filter(tr -> tr.getId().equals(r.getResourceId()))
|
||||
.findFirst();
|
||||
return res.map(TreatmentResource::getApplicableSymptoms).orElse("");
|
||||
})
|
||||
.flatMap(s -> Arrays.stream(s.split("[,、]")))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> resourceSymptoms = Arrays.stream(
|
||||
resource.getApplicableSymptoms() != null
|
||||
? resource.getApplicableSymptoms().split("[,、]")
|
||||
: new String[0])
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
boolean hasCommonSymptoms = resourceSymptoms.stream()
|
||||
.anyMatch(userPreferredSymptoms::contains);
|
||||
|
||||
if (hasCommonSymptoms) {
|
||||
return "包含您可能关注的症状";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "基于系统热门资源推荐";
|
||||
}
|
||||
|
||||
// 基于相似用户的推荐理由
|
||||
if (usersWithRating.size() == 1) {
|
||||
return "与您兴趣相似的用户喜欢此资源";
|
||||
}
|
||||
|
||||
return usersWithRating.size() + "位与您兴趣相似的用户喜欢此资源";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.ResourceCategory;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.ResourceCategoryMapper;
|
||||
import com.example.mapper.TreatmentResourceMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ResourceCategoryService {
|
||||
|
||||
@Resource
|
||||
private ResourceCategoryMapper resourceCategoryMapper;
|
||||
|
||||
@Resource
|
||||
private TreatmentResourceMapper treatmentResourceMapper;
|
||||
|
||||
public List<ResourceCategory> findAll() {
|
||||
return resourceCategoryMapper.selectAllCategories();
|
||||
}
|
||||
|
||||
public List<ResourceCategory> findByParentId(Integer parentId) {
|
||||
return resourceCategoryMapper.selectByParentId(parentId);
|
||||
}
|
||||
|
||||
public ResourceCategory findById(Integer id) {
|
||||
return resourceCategoryMapper.selectById(id);
|
||||
}
|
||||
|
||||
public void add(ResourceCategory category) {
|
||||
// 检查是否存在同名分类
|
||||
LambdaQueryWrapper<ResourceCategory> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ResourceCategory::getName, category.getName())
|
||||
.eq(ResourceCategory::getParentId, category.getParentId());
|
||||
|
||||
if (resourceCategoryMapper.selectCount(wrapper) > 0) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "已存在同名分类");
|
||||
}
|
||||
|
||||
resourceCategoryMapper.insert(category);
|
||||
}
|
||||
|
||||
public void update(ResourceCategory category) {
|
||||
// 检查是否存在同名分类(排除自身)
|
||||
LambdaQueryWrapper<ResourceCategory> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ResourceCategory::getName, category.getName())
|
||||
.eq(ResourceCategory::getParentId, category.getParentId())
|
||||
.ne(ResourceCategory::getId, category.getId());
|
||||
|
||||
if (resourceCategoryMapper.selectCount(wrapper) > 0) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "已存在同名分类");
|
||||
}
|
||||
|
||||
resourceCategoryMapper.updateById(category);
|
||||
}
|
||||
|
||||
public void delete(Integer id) {
|
||||
// 检查是否有子分类
|
||||
LambdaQueryWrapper<ResourceCategory> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(ResourceCategory::getParentId, id);
|
||||
|
||||
if (resourceCategoryMapper.selectCount(wrapper) > 0) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "该分类下存在子分类,无法删除");
|
||||
}
|
||||
|
||||
// 检查是否有关联的资源
|
||||
List<TreatmentResource> resources = treatmentResourceMapper.selectByCategoryId(id);
|
||||
if (resources != null && !resources.isEmpty()) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "该分类下存在资源,无法删除");
|
||||
}
|
||||
|
||||
resourceCategoryMapper.deleteById(id);
|
||||
}
|
||||
|
||||
public PageInfo<ResourceCategory> selectPage(ResourceCategory category, Integer pageNum, Integer pageSize) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<ResourceCategory> list = resourceCategoryMapper.selectPage(category.getName() != null ? category.getName() : "");
|
||||
return new PageInfo<>(list);
|
||||
}
|
||||
}
|
||||
161
src/main/java/com/example/service/ResourceRatingService.java
Normal file
161
src/main/java/com/example/service/ResourceRatingService.java
Normal file
@@ -0,0 +1,161 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.ResourceRating;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.ResourceRatingMapper;
|
||||
import com.example.mapper.TreatmentResourceMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ResourceRatingService {
|
||||
|
||||
@Resource
|
||||
private ResourceRatingMapper resourceRatingMapper;
|
||||
|
||||
@Resource
|
||||
private TreatmentResourceMapper treatmentResourceMapper;
|
||||
|
||||
/**
|
||||
* 添加评分
|
||||
*/
|
||||
public void add(ResourceRating resourceRating) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 只有患者可以添加评分
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有患者可以评分");
|
||||
}
|
||||
|
||||
// 设置患者ID
|
||||
resourceRating.setPatientId(currentUser.getId());
|
||||
|
||||
// 检查评分是否有效
|
||||
if (resourceRating.getRating() == null || resourceRating.getRating() < 1 || resourceRating.getRating() > 5) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "评分必须在1-5之间");
|
||||
}
|
||||
|
||||
// 检查是否已经评分过
|
||||
int count = resourceRatingMapper.countByResourceIdAndPatientId(resourceRating.getResourceId(), currentUser.getId());
|
||||
if (count > 0) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "您已经评价过该资源");
|
||||
}
|
||||
|
||||
// 设置创建时间
|
||||
resourceRating.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 保存评分
|
||||
resourceRatingMapper.insert(resourceRating);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据资源ID查询评分记录
|
||||
*/
|
||||
public List<ResourceRating> findByResourceId(Integer resourceId) {
|
||||
return resourceRatingMapper.selectByResourceId(resourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源的平均评分
|
||||
*/
|
||||
public double getAverageRating(Integer resourceId) {
|
||||
return resourceRatingMapper.getAverageRating(resourceId);
|
||||
}
|
||||
|
||||
public Integer getRatingCount(Integer resourceId) {
|
||||
return resourceRatingMapper.getRatingCount(resourceId);
|
||||
}
|
||||
|
||||
public void rateResource(ResourceRating rating) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 只有患者才能评价资源
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "只有患者才能评价资源");
|
||||
}
|
||||
|
||||
// 检查资源是否存在
|
||||
TreatmentResource resource = treatmentResourceMapper.selectById(rating.getResourceId());
|
||||
if (resource == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "资源不存在");
|
||||
}
|
||||
|
||||
// 检查资源是否已通过审核
|
||||
if (!"已通过".equals(resource.getAuditStatus())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "资源未通过审核,无法评价");
|
||||
}
|
||||
|
||||
// 检查患者是否已经评价过该资源
|
||||
ResourceRating existingRating = resourceRatingMapper.findByResourceAndPatient(
|
||||
rating.getResourceId(), currentUser.getId());
|
||||
|
||||
if (existingRating != null) {
|
||||
// 更新评价
|
||||
existingRating.setRating(rating.getRating());
|
||||
existingRating.setComment(rating.getComment());
|
||||
resourceRatingMapper.updateById(existingRating);
|
||||
} else {
|
||||
// 新增评价
|
||||
rating.setPatientId(currentUser.getId());
|
||||
rating.setCreateTime(LocalDateTime.now());
|
||||
resourceRatingMapper.insert(rating);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRating(Integer id) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 查询评价
|
||||
ResourceRating rating = resourceRatingMapper.selectById(id);
|
||||
if (rating == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "评价不存在");
|
||||
}
|
||||
|
||||
// 只有评价的患者本人或管理员才能删除评价
|
||||
if (!currentUser.getId().equals(rating.getPatientId()) && !"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权限删除该评价");
|
||||
}
|
||||
|
||||
resourceRatingMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID查询评分记录
|
||||
*/
|
||||
public List<ResourceRating> findByPatientId(Integer patientId) {
|
||||
LambdaQueryWrapper<ResourceRating> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ResourceRating::getPatientId, patientId);
|
||||
queryWrapper.orderByDesc(ResourceRating::getCreateTime);
|
||||
return resourceRatingMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有评分记录
|
||||
*/
|
||||
public List<ResourceRating> findAll() {
|
||||
LambdaQueryWrapper<ResourceRating> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.orderByDesc(ResourceRating::getCreateTime);
|
||||
return resourceRatingMapper.selectList(queryWrapper);
|
||||
}
|
||||
}
|
||||
735
src/main/java/com/example/service/SymptomRecordService.java
Normal file
735
src/main/java/com/example/service/SymptomRecordService.java
Normal file
@@ -0,0 +1,735 @@
|
||||
package com.example.service;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.DoctorPatient;
|
||||
import com.example.entity.SymptomRecord;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.SymptomRecordMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* 症状记录服务类
|
||||
*/
|
||||
@Service
|
||||
public class SymptomRecordService {
|
||||
|
||||
@Resource
|
||||
private SymptomRecordMapper symptomRecordMapper;
|
||||
|
||||
@Resource
|
||||
private DoctorPatientService doctorPatientService;
|
||||
|
||||
/**
|
||||
* 添加症状记录
|
||||
*/
|
||||
public void add(SymptomRecord symptomRecord) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 只有患者可以添加症状记录
|
||||
if (!"patient".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.NO_AUTH_ERROR);
|
||||
}
|
||||
|
||||
// 设置患者ID
|
||||
symptomRecord.setPatientId(currentUser.getId());
|
||||
|
||||
// 设置记录时间和创建时间
|
||||
if (symptomRecord.getRecordTime() == null) {
|
||||
symptomRecord.setRecordTime(new Date());
|
||||
}
|
||||
symptomRecord.setCreateTime(new Date());
|
||||
|
||||
symptomRecordMapper.insert(symptomRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新症状记录
|
||||
*/
|
||||
public void update(SymptomRecord symptomRecord) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 检查记录是否存在
|
||||
SymptomRecord existRecord = symptomRecordMapper.selectById(symptomRecord.getId());
|
||||
if (existRecord == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR);
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
checkPermission(currentUser, existRecord.getPatientId());
|
||||
|
||||
// 更新记录
|
||||
symptomRecordMapper.updateById(symptomRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除症状记录
|
||||
*/
|
||||
public void delete(Integer id) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 检查记录是否存在
|
||||
SymptomRecord existRecord = symptomRecordMapper.selectById(id);
|
||||
if (existRecord == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR);
|
||||
}
|
||||
|
||||
// 权限检查:患者只能删除自己的记录,医生不能删除记录,管理员可以删除所有记录
|
||||
if ("patient".equals(currentUser.getRole())) {
|
||||
if (!currentUser.getId().equals(existRecord.getPatientId())) {
|
||||
throw new CustomException(ResultCodeEnum.NO_AUTH_ERROR);
|
||||
}
|
||||
} else if ("doctor".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.NO_AUTH_ERROR);
|
||||
}
|
||||
|
||||
symptomRecordMapper.deleteById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询症状记录
|
||||
*/
|
||||
public SymptomRecord getById(Integer id) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
SymptomRecord record = symptomRecordMapper.selectById(id);
|
||||
if (record == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR);
|
||||
}
|
||||
|
||||
// 权限检查
|
||||
checkPermission(currentUser, record.getPatientId());
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID查询所有症状记录
|
||||
*/
|
||||
public List<SymptomRecord> getByPatientId(Integer patientId) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 根据角色处理
|
||||
if ("patient".equals(currentUser.getRole())) {
|
||||
// 患者只能查看自己的记录
|
||||
patientId = currentUser.getId();
|
||||
} else if ("doctor".equals(currentUser.getRole())) {
|
||||
// 医生只能查看自己负责的患者记录
|
||||
if (patientId != null) {
|
||||
// 检查该患者是否是该医生负责的
|
||||
checkDoctorPatientRelationship(currentUser.getId(), patientId);
|
||||
} else {
|
||||
// 获取医生负责的所有患者
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), null);
|
||||
List<Integer> patientIds = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatientId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (patientIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 查询这些患者的所有记录
|
||||
LambdaQueryWrapper<SymptomRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(SymptomRecord::getPatientId, patientIds);
|
||||
queryWrapper.orderByDesc(SymptomRecord::getRecordTime);
|
||||
return symptomRecordMapper.selectList(queryWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
// 查询记录
|
||||
return symptomRecordMapper.selectWithPatient(patientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询症状记录
|
||||
*/
|
||||
public Page<SymptomRecord> getPage(Integer pageNum, Integer pageSize, String startDate, String endDate) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 创建查询条件
|
||||
LambdaQueryWrapper<SymptomRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 根据角色设置查询条件
|
||||
if ("patient".equals(currentUser.getRole())) {
|
||||
// 患者只能查看自己的记录
|
||||
queryWrapper.eq(SymptomRecord::getPatientId, currentUser.getId());
|
||||
} else if ("doctor".equals(currentUser.getRole())) {
|
||||
// 医生只能查看自己负责的患者记录
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), null);
|
||||
List<Integer> patientIds = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatientId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (patientIds.isEmpty()) {
|
||||
// 没有负责的患者,返回空结果
|
||||
return new Page<>(pageNum, pageSize);
|
||||
}
|
||||
|
||||
queryWrapper.in(SymptomRecord::getPatientId, patientIds);
|
||||
}
|
||||
|
||||
// 添加日期条件
|
||||
if (ObjectUtil.isNotEmpty(startDate) && ObjectUtil.isNotEmpty(endDate)) {
|
||||
Date start = DateUtil.parseDate(startDate);
|
||||
Date end = DateUtil.parseDate(endDate);
|
||||
queryWrapper.between(SymptomRecord::getRecordTime, start, end);
|
||||
}
|
||||
|
||||
// 按记录时间降序排序
|
||||
queryWrapper.orderByDesc(SymptomRecord::getRecordTime);
|
||||
|
||||
// 执行分页查询
|
||||
return symptomRecordMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否有权限操作指定患者的记录
|
||||
*/
|
||||
private void checkPermission(Account currentUser, Integer patientId) {
|
||||
if ("patient".equals(currentUser.getRole())) {
|
||||
// 患者只能操作自己的记录
|
||||
if (!currentUser.getId().equals(patientId)) {
|
||||
throw new CustomException(ResultCodeEnum.NO_AUTH_ERROR);
|
||||
}
|
||||
} else if ("doctor".equals(currentUser.getRole())) {
|
||||
// 医生只能操作自己负责的患者的记录
|
||||
checkDoctorPatientRelationship(currentUser.getId(), patientId);
|
||||
}
|
||||
// 管理员可以操作所有记录
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查医生与患者是否存在关联关系
|
||||
*/
|
||||
private void checkDoctorPatientRelationship(Integer doctorId, Integer patientId) {
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(doctorId, null);
|
||||
boolean isResponsible = doctorPatients.stream()
|
||||
.anyMatch(dp -> dp.getPatientId().equals(patientId));
|
||||
|
||||
if (!isResponsible) {
|
||||
throw new CustomException(ResultCodeEnum.NO_AUTH_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询症状记录关联的患者信息
|
||||
*/
|
||||
public List<SymptomRecord> getRecordsWithPatient(List<SymptomRecord> records) {
|
||||
if (records == null || records.isEmpty()) {
|
||||
return records;
|
||||
}
|
||||
|
||||
// 从记录中提取所有患者ID
|
||||
List<Integer> patientIds = records.stream()
|
||||
.map(SymptomRecord::getPatientId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 这里利用Mapper中已有的selectWithPatient方法,查询所有关联患者信息的记录
|
||||
List<SymptomRecord> recordsWithPatient = new ArrayList<>();
|
||||
for (Integer patientId : patientIds) {
|
||||
List<SymptomRecord> patientRecords = symptomRecordMapper.selectWithPatient(patientId);
|
||||
recordsWithPatient.addAll(patientRecords);
|
||||
}
|
||||
|
||||
// 根据原记录ID匹配,返回带患者信息的记录
|
||||
Map<Integer, SymptomRecord> recordMap = recordsWithPatient.stream()
|
||||
.collect(Collectors.toMap(SymptomRecord::getId, record -> record, (a, b) -> a));
|
||||
|
||||
return records.stream()
|
||||
.map(record -> {
|
||||
SymptomRecord recordWithPatient = recordMap.get(record.getId());
|
||||
return recordWithPatient != null ? recordWithPatient : record;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询症状记录(使用PageHelper)
|
||||
*/
|
||||
public com.github.pagehelper.PageInfo<SymptomRecord> selectPage(SymptomRecord symptomRecord, Integer pageNum, Integer pageSize, String startDate, String endDate) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_INVALID_ERROR);
|
||||
}
|
||||
|
||||
// 构建查询条件获取所有符合条件的记录
|
||||
List<SymptomRecord> allRecords = new ArrayList<>();
|
||||
|
||||
// 获取患者名称搜索条件
|
||||
final String patientName;
|
||||
if (symptomRecord != null && ObjectUtil.isNotEmpty(symptomRecord.getPatientName())) {
|
||||
patientName = symptomRecord.getPatientName().trim().toLowerCase();
|
||||
} else {
|
||||
patientName = "";
|
||||
}
|
||||
|
||||
// 根据角色设置查询条件
|
||||
if ("patient".equals(currentUser.getRole())) {
|
||||
// 患者只能查看自己的记录
|
||||
symptomRecord = symptomRecord == null ? new SymptomRecord() : symptomRecord;
|
||||
symptomRecord.setPatientId(currentUser.getId());
|
||||
allRecords = symptomRecordMapper.selectWithPatient(currentUser.getId());
|
||||
} else if ("doctor".equals(currentUser.getRole())) {
|
||||
// 医生只能查看自己负责的患者记录
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(currentUser.getId(), null);
|
||||
List<Integer> patientIds = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatientId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (patientIds.isEmpty()) {
|
||||
// 没有负责的患者,返回空结果
|
||||
return new com.github.pagehelper.PageInfo<>(new ArrayList<>());
|
||||
}
|
||||
|
||||
// 查询患者ID在列表中的记录,并带上患者信息
|
||||
for (Integer patientId : patientIds) {
|
||||
List<SymptomRecord> patientRecords = symptomRecordMapper.selectWithPatient(patientId);
|
||||
allRecords.addAll(patientRecords);
|
||||
}
|
||||
} else {
|
||||
// 管理员可以查看所有记录
|
||||
// 这里需要查询所有带有患者信息的记录,但由于没有查询全部的接口,我们先查询所有患者ID
|
||||
List<SymptomRecord> tempRecords = symptomRecordMapper.selectList(null);
|
||||
List<Integer> allPatientIds = tempRecords.stream()
|
||||
.map(SymptomRecord::getPatientId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 查询每个患者的记录并带上患者信息
|
||||
for (Integer patientId : allPatientIds) {
|
||||
List<SymptomRecord> patientRecords = symptomRecordMapper.selectWithPatient(patientId);
|
||||
allRecords.addAll(patientRecords);
|
||||
}
|
||||
}
|
||||
|
||||
// 根据患者名称过滤
|
||||
if (ObjectUtil.isNotEmpty(patientName)) {
|
||||
allRecords = allRecords.stream()
|
||||
.filter(record -> {
|
||||
if (record.getPatient() != null && ObjectUtil.isNotEmpty(record.getPatient().getName())) {
|
||||
return record.getPatient().getName().toLowerCase().contains(patientName);
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 根据日期过滤
|
||||
if (ObjectUtil.isNotEmpty(startDate) && ObjectUtil.isNotEmpty(endDate)) {
|
||||
Date start = DateUtil.parseDate(startDate);
|
||||
Date end = DateUtil.parseDate(endDate);
|
||||
allRecords = allRecords.stream()
|
||||
.filter(record -> {
|
||||
Date recordTime = record.getRecordTime();
|
||||
return recordTime != null && !recordTime.before(start) && !recordTime.after(end);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 按记录时间降序排序
|
||||
allRecords.sort((a, b) -> {
|
||||
if (a.getRecordTime() == null || b.getRecordTime() == null) {
|
||||
return 0;
|
||||
}
|
||||
return b.getRecordTime().compareTo(a.getRecordTime());
|
||||
});
|
||||
|
||||
// 在内存中执行分页
|
||||
int start = (pageNum - 1) * pageSize;
|
||||
int end = Math.min(start + pageSize, allRecords.size());
|
||||
|
||||
List<SymptomRecord> pagedRecords;
|
||||
if (start < allRecords.size()) {
|
||||
pagedRecords = allRecords.subList(start, end);
|
||||
} else {
|
||||
pagedRecords = new ArrayList<>();
|
||||
}
|
||||
|
||||
// 创建PageInfo对象
|
||||
com.github.pagehelper.PageInfo<SymptomRecord> pageInfo = new com.github.pagehelper.PageInfo<>(pagedRecords);
|
||||
// 手动设置分页信息
|
||||
pageInfo.setPageNum(pageNum);
|
||||
pageInfo.setPageSize(pageSize);
|
||||
pageInfo.setTotal(allRecords.size());
|
||||
pageInfo.setPages((int) Math.ceil((double) allRecords.size() / pageSize));
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取症状记录统计数据
|
||||
* @param patientId 患者ID(可选,为null表示查询所有)
|
||||
* @param startDate 开始日期(可选)
|
||||
* @param endDate 结束日期(可选)
|
||||
* @return 统计数据
|
||||
*/
|
||||
public Map<String, Object> getStatisticsData(Integer patientId, Date startDate, Date endDate) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
try {
|
||||
// 构建查询条件
|
||||
LambdaQueryWrapper<SymptomRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (patientId != null) {
|
||||
queryWrapper.eq(SymptomRecord::getPatientId, patientId);
|
||||
}
|
||||
|
||||
if (startDate != null) {
|
||||
queryWrapper.ge(SymptomRecord::getRecordTime, startDate);
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
queryWrapper.le(SymptomRecord::getRecordTime, endDate);
|
||||
}
|
||||
|
||||
// 获取所有符合条件的记录
|
||||
List<SymptomRecord> records = symptomRecordMapper.selectList(queryWrapper);
|
||||
|
||||
// 按日期分组的严重程度平均值
|
||||
Map<String, Double> severityByDate = new LinkedHashMap<>();
|
||||
Map<String, Double> emotionByDate = new LinkedHashMap<>();
|
||||
Map<String, Double> sleepByDate = new LinkedHashMap<>();
|
||||
|
||||
// 过去7天的日期
|
||||
List<String> last7Days = new ArrayList<>();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
for (int i = 6; i >= 0; i--) {
|
||||
calendar.setTime(new Date());
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -i);
|
||||
String dateStr = dateFormat.format(calendar.getTime());
|
||||
last7Days.add(dateStr);
|
||||
|
||||
// 初始化数据
|
||||
severityByDate.put(dateStr, 0.0);
|
||||
emotionByDate.put(dateStr, 0.0);
|
||||
sleepByDate.put(dateStr, 0.0);
|
||||
}
|
||||
|
||||
// 记录每个日期的记录数量
|
||||
Map<String, Integer> countByDate = new HashMap<>();
|
||||
for (String date : last7Days) {
|
||||
countByDate.put(date, 0);
|
||||
}
|
||||
|
||||
// 处理记录
|
||||
for (SymptomRecord record : records) {
|
||||
if (record.getRecordTime() != null) {
|
||||
String recordDate = dateFormat.format(record.getRecordTime());
|
||||
|
||||
// 只处理过去7天的数据
|
||||
if (last7Days.contains(recordDate)) {
|
||||
// 更新计数
|
||||
countByDate.put(recordDate, countByDate.getOrDefault(recordDate, 0) + 1);
|
||||
|
||||
// 更新严重程度总和
|
||||
if (record.getSeverityLevel() != null) {
|
||||
severityByDate.put(recordDate, severityByDate.getOrDefault(recordDate, 0.0) + record.getSeverityLevel());
|
||||
}
|
||||
|
||||
// 更新情绪评分总和
|
||||
if (record.getEmotionScore() != null) {
|
||||
emotionByDate.put(recordDate, emotionByDate.getOrDefault(recordDate, 0.0) + record.getEmotionScore());
|
||||
}
|
||||
|
||||
// 更新入睡时间总和
|
||||
if (record.getSleepTime() != null) {
|
||||
sleepByDate.put(recordDate, sleepByDate.getOrDefault(recordDate, 0.0) + record.getSleepTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算每日平均值
|
||||
for (String date : last7Days) {
|
||||
int count = countByDate.get(date);
|
||||
if (count > 0) {
|
||||
severityByDate.put(date, severityByDate.get(date) / count);
|
||||
emotionByDate.put(date, emotionByDate.get(date) / count);
|
||||
sleepByDate.put(date, sleepByDate.get(date) / count);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
result.put("dates", last7Days);
|
||||
result.put("severityData", last7Days.stream().map(severityByDate::get).collect(Collectors.toList()));
|
||||
result.put("emotionData", last7Days.stream().map(emotionByDate::get).collect(Collectors.toList()));
|
||||
result.put("sleepData", last7Days.stream().map(sleepByDate::get).collect(Collectors.toList()));
|
||||
|
||||
// 计算总体统计数据
|
||||
DoubleSummaryStatistics severityStats = records.stream()
|
||||
.filter(r -> r.getSeverityLevel() != null)
|
||||
.mapToDouble(SymptomRecord::getSeverityLevel)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics emotionStats = records.stream()
|
||||
.filter(r -> r.getEmotionScore() != null)
|
||||
.mapToDouble(SymptomRecord::getEmotionScore)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics sleepStats = records.stream()
|
||||
.filter(r -> r.getSleepTime() != null)
|
||||
.mapToDouble(SymptomRecord::getSleepTime)
|
||||
.summaryStatistics();
|
||||
|
||||
// 添加总体统计
|
||||
Map<String, Object> summaryStats = new HashMap<>();
|
||||
summaryStats.put("recordCount", records.size());
|
||||
summaryStats.put("avgSeverity", severityStats.getAverage());
|
||||
summaryStats.put("avgEmotion", emotionStats.getAverage());
|
||||
summaryStats.put("avgSleepTime", sleepStats.getAverage());
|
||||
|
||||
result.put("summary", summaryStats);
|
||||
|
||||
// 计算各项分布
|
||||
Map<Integer, Long> severityDistribution = records.stream()
|
||||
.filter(r -> r.getSeverityLevel() != null)
|
||||
.collect(Collectors.groupingBy(SymptomRecord::getSeverityLevel, Collectors.counting()));
|
||||
|
||||
Map<Integer, Long> emotionDistribution = records.stream()
|
||||
.filter(r -> r.getEmotionScore() != null)
|
||||
.collect(Collectors.groupingBy(SymptomRecord::getEmotionScore, Collectors.counting()));
|
||||
|
||||
result.put("severityDistribution", severityDistribution);
|
||||
result.put("emotionDistribution", emotionDistribution);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据医生ID获取其患者的症状记录统计数据
|
||||
* @param doctorId 医生ID
|
||||
* @param startDate 开始日期(可选)
|
||||
* @param endDate 结束日期(可选)
|
||||
* @return 统计数据
|
||||
*/
|
||||
public Map<String, Object> getStatisticsByDoctor(Integer doctorId, Date startDate, Date endDate) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 获取医生的所有患者
|
||||
List<Integer> patientIds = new ArrayList<>();
|
||||
try {
|
||||
LambdaQueryWrapper<DoctorPatient> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DoctorPatient::getDoctorId, doctorId);
|
||||
queryWrapper.eq(DoctorPatient::getStatus, "正常");
|
||||
|
||||
List<DoctorPatient> doctorPatients = doctorPatientService.selectByDoctorId(doctorId, null);
|
||||
patientIds = doctorPatients.stream()
|
||||
.map(DoctorPatient::getPatientId)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (patientIds.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建查询条件
|
||||
LambdaQueryWrapper<SymptomRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(SymptomRecord::getPatientId, patientIds);
|
||||
|
||||
if (startDate != null) {
|
||||
queryWrapper.ge(SymptomRecord::getRecordTime, startDate);
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
queryWrapper.le(SymptomRecord::getRecordTime, endDate);
|
||||
}
|
||||
|
||||
// 获取所有符合条件的记录
|
||||
List<SymptomRecord> records = symptomRecordMapper.selectList(queryWrapper);
|
||||
|
||||
// 处理和上面的方法相同...(后续统计处理逻辑与上面的方法相同)
|
||||
// 按日期分组的严重程度平均值
|
||||
Map<String, Double> severityByDate = new LinkedHashMap<>();
|
||||
Map<String, Double> emotionByDate = new LinkedHashMap<>();
|
||||
Map<String, Double> sleepByDate = new LinkedHashMap<>();
|
||||
|
||||
// 过去7天的日期
|
||||
List<String> last7Days = new ArrayList<>();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
for (int i = 6; i >= 0; i--) {
|
||||
calendar.setTime(new Date());
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -i);
|
||||
String dateStr = dateFormat.format(calendar.getTime());
|
||||
last7Days.add(dateStr);
|
||||
|
||||
// 初始化数据
|
||||
severityByDate.put(dateStr, 0.0);
|
||||
emotionByDate.put(dateStr, 0.0);
|
||||
sleepByDate.put(dateStr, 0.0);
|
||||
}
|
||||
|
||||
// 记录每个日期的记录数量
|
||||
Map<String, Integer> countByDate = new HashMap<>();
|
||||
for (String date : last7Days) {
|
||||
countByDate.put(date, 0);
|
||||
}
|
||||
|
||||
// 处理记录
|
||||
for (SymptomRecord record : records) {
|
||||
if (record.getRecordTime() != null) {
|
||||
String recordDate = dateFormat.format(record.getRecordTime());
|
||||
|
||||
// 只处理过去7天的数据
|
||||
if (last7Days.contains(recordDate)) {
|
||||
// 更新计数
|
||||
countByDate.put(recordDate, countByDate.getOrDefault(recordDate, 0) + 1);
|
||||
|
||||
// 更新严重程度总和
|
||||
if (record.getSeverityLevel() != null) {
|
||||
severityByDate.put(recordDate, severityByDate.getOrDefault(recordDate, 0.0) + record.getSeverityLevel());
|
||||
}
|
||||
|
||||
// 更新情绪评分总和
|
||||
if (record.getEmotionScore() != null) {
|
||||
emotionByDate.put(recordDate, emotionByDate.getOrDefault(recordDate, 0.0) + record.getEmotionScore());
|
||||
}
|
||||
|
||||
// 更新入睡时间总和
|
||||
if (record.getSleepTime() != null) {
|
||||
sleepByDate.put(recordDate, sleepByDate.getOrDefault(recordDate, 0.0) + record.getSleepTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算每日平均值
|
||||
for (String date : last7Days) {
|
||||
int count = countByDate.get(date);
|
||||
if (count > 0) {
|
||||
severityByDate.put(date, severityByDate.get(date) / count);
|
||||
emotionByDate.put(date, emotionByDate.get(date) / count);
|
||||
sleepByDate.put(date, sleepByDate.get(date) / count);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
result.put("dates", last7Days);
|
||||
result.put("severityData", last7Days.stream().map(severityByDate::get).collect(Collectors.toList()));
|
||||
result.put("emotionData", last7Days.stream().map(emotionByDate::get).collect(Collectors.toList()));
|
||||
result.put("sleepData", last7Days.stream().map(sleepByDate::get).collect(Collectors.toList()));
|
||||
|
||||
// 计算总体统计数据
|
||||
DoubleSummaryStatistics severityStats = records.stream()
|
||||
.filter(r -> r.getSeverityLevel() != null)
|
||||
.mapToDouble(SymptomRecord::getSeverityLevel)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics emotionStats = records.stream()
|
||||
.filter(r -> r.getEmotionScore() != null)
|
||||
.mapToDouble(SymptomRecord::getEmotionScore)
|
||||
.summaryStatistics();
|
||||
|
||||
DoubleSummaryStatistics sleepStats = records.stream()
|
||||
.filter(r -> r.getSleepTime() != null)
|
||||
.mapToDouble(SymptomRecord::getSleepTime)
|
||||
.summaryStatistics();
|
||||
|
||||
// 添加总体统计
|
||||
Map<String, Object> summaryStats = new HashMap<>();
|
||||
summaryStats.put("recordCount", records.size());
|
||||
summaryStats.put("avgSeverity", severityStats.getAverage());
|
||||
summaryStats.put("avgEmotion", emotionStats.getAverage());
|
||||
summaryStats.put("avgSleepTime", sleepStats.getAverage());
|
||||
summaryStats.put("patientCount", patientIds.size());
|
||||
|
||||
result.put("summary", summaryStats);
|
||||
|
||||
// 计算各项分布
|
||||
Map<Integer, Long> severityDistribution = records.stream()
|
||||
.filter(r -> r.getSeverityLevel() != null)
|
||||
.collect(Collectors.groupingBy(SymptomRecord::getSeverityLevel, Collectors.counting()));
|
||||
|
||||
Map<Integer, Long> emotionDistribution = records.stream()
|
||||
.filter(r -> r.getEmotionScore() != null)
|
||||
.collect(Collectors.groupingBy(SymptomRecord::getEmotionScore, Collectors.counting()));
|
||||
|
||||
result.put("severityDistribution", severityDistribution);
|
||||
result.put("emotionDistribution", emotionDistribution);
|
||||
|
||||
// 按患者分组的数据
|
||||
Map<Integer, List<SymptomRecord>> recordsByPatient = records.stream()
|
||||
.collect(Collectors.groupingBy(SymptomRecord::getPatientId));
|
||||
|
||||
Map<Integer, Object> patientStats = new HashMap<>();
|
||||
for (Map.Entry<Integer, List<SymptomRecord>> entry : recordsByPatient.entrySet()) {
|
||||
Integer pid = entry.getKey();
|
||||
List<SymptomRecord> patientRecords = entry.getValue();
|
||||
|
||||
DoubleSummaryStatistics patientSeverityStats = patientRecords.stream()
|
||||
.filter(r -> r.getSeverityLevel() != null)
|
||||
.mapToDouble(SymptomRecord::getSeverityLevel)
|
||||
.summaryStatistics();
|
||||
|
||||
Map<String, Object> pStats = new HashMap<>();
|
||||
pStats.put("recordCount", patientRecords.size());
|
||||
pStats.put("avgSeverity", patientSeverityStats.getAverage());
|
||||
pStats.put("maxSeverity", patientSeverityStats.getMax());
|
||||
|
||||
patientStats.put(pid, pStats);
|
||||
}
|
||||
|
||||
result.put("patientStats", patientStats);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
256
src/main/java/com/example/service/TreatmentResourceService.java
Normal file
256
src/main/java/com/example/service/TreatmentResourceService.java
Normal file
@@ -0,0 +1,256 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.example.common.config.TokenUtils;
|
||||
import com.example.common.enums.ResultCodeEnum;
|
||||
import com.example.entity.Account;
|
||||
import com.example.entity.TreatmentResource;
|
||||
import com.example.exception.CustomException;
|
||||
import com.example.mapper.TreatmentResourceMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class TreatmentResourceService {
|
||||
|
||||
@Resource
|
||||
private TreatmentResourceMapper treatmentResourceMapper;
|
||||
|
||||
public Page<TreatmentResource> search(Page<TreatmentResource> page, String keyword, String role) {
|
||||
if ("admin".equals(role)) {
|
||||
return treatmentResourceMapper.searchResourcesForAdmin(page, keyword);
|
||||
} else {
|
||||
return treatmentResourceMapper.searchResourcesForPatient(page, keyword);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TreatmentResource> findByCategoryId(Integer categoryId) {
|
||||
return treatmentResourceMapper.selectByCategoryId(categoryId);
|
||||
}
|
||||
|
||||
public TreatmentResource findById(Integer id) {
|
||||
return treatmentResourceMapper.selectById(id);
|
||||
}
|
||||
|
||||
public void add(TreatmentResource resource) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 允许管理员和医生添加资源
|
||||
if (!"admin".equals(currentUser.getRole()) && !"doctor".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权限添加资源");
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
resource.setPublisherId(currentUser.getId());
|
||||
resource.setVisitCount(0);
|
||||
resource.setDownloadCount(0);
|
||||
|
||||
// 如果是医生添加,则默认为待审核状态
|
||||
if ("doctor".equals(currentUser.getRole())) {
|
||||
resource.setAuditStatus("待审核");
|
||||
} else {
|
||||
// 管理员添加的资源默认已审核
|
||||
resource.setAuditStatus("已通过");
|
||||
}
|
||||
|
||||
resource.setCreateTime(LocalDateTime.now());
|
||||
|
||||
treatmentResourceMapper.insert(resource);
|
||||
}
|
||||
|
||||
public void update(TreatmentResource resource) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 仅允许管理员修改资源
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权限修改资源");
|
||||
}
|
||||
|
||||
// 检查资源是否存在
|
||||
TreatmentResource dbResource = treatmentResourceMapper.selectById(resource.getId());
|
||||
if (dbResource == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "资源不存在");
|
||||
}
|
||||
|
||||
treatmentResourceMapper.updateById(resource);
|
||||
}
|
||||
|
||||
public void delete(Integer id) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 仅允许管理员删除资源
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权限删除资源");
|
||||
}
|
||||
|
||||
// 检查资源是否存在
|
||||
TreatmentResource dbResource = treatmentResourceMapper.selectById(id);
|
||||
if (dbResource == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "资源不存在");
|
||||
}
|
||||
|
||||
treatmentResourceMapper.deleteById(id);
|
||||
}
|
||||
|
||||
public void changeAuditStatus(Integer id, String status) {
|
||||
// 获取当前登录用户
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
throw new CustomException(ResultCodeEnum.TOKEN_CHECK_ERROR);
|
||||
}
|
||||
|
||||
// 仅允许管理员审核资源
|
||||
if (!"admin".equals(currentUser.getRole())) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "无权限审核资源");
|
||||
}
|
||||
|
||||
// 检查资源是否存在
|
||||
TreatmentResource dbResource = treatmentResourceMapper.selectById(id);
|
||||
if (dbResource == null) {
|
||||
throw new CustomException(ResultCodeEnum.PARAM_ERROR.code, "资源不存在");
|
||||
}
|
||||
|
||||
// 更新审核状态
|
||||
TreatmentResource resource = new TreatmentResource();
|
||||
resource.setId(id);
|
||||
resource.setAuditStatus(status);
|
||||
|
||||
treatmentResourceMapper.updateById(resource);
|
||||
}
|
||||
|
||||
public void incrementVisitCount(Integer id) {
|
||||
treatmentResourceMapper.incrementVisitCount(id);
|
||||
}
|
||||
|
||||
public void incrementDownloadCount(Integer id) {
|
||||
treatmentResourceMapper.incrementDownloadCount(id);
|
||||
}
|
||||
|
||||
public PageInfo<TreatmentResource> selectPage(TreatmentResource resource, Integer pageNum, Integer pageSize) {
|
||||
// 获取当前用户角色
|
||||
Account currentUser = TokenUtils.getCurrentUser();
|
||||
String role = currentUser != null ? currentUser.getRole() : "patient";
|
||||
|
||||
// 使用PageHelper进行分页,与Admin页面一致
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
// 获取查询关键词
|
||||
String keyword = resource.getTitle() != null ? resource.getTitle() : "";
|
||||
|
||||
// 直接使用Mapper的查询方法
|
||||
List<TreatmentResource> list;
|
||||
if ("admin".equals(role)) {
|
||||
list = treatmentResourceMapper.selectAll(keyword);
|
||||
} else {
|
||||
list = treatmentResourceMapper.selectAllAudited(keyword);
|
||||
}
|
||||
|
||||
// 创建PageInfo对象
|
||||
return new PageInfo<>(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询特定发布者的资源
|
||||
*/
|
||||
public PageInfo<TreatmentResource> findByPublisher(TreatmentResource resource, Integer pageNum, Integer pageSize) {
|
||||
// 使用PageHelper进行分页,与Admin页面一致
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
|
||||
// 获取查询关键词
|
||||
String keyword = resource.getTitle() != null ? resource.getTitle() : "";
|
||||
|
||||
// 调用Mapper查询方法,需要添加对应的Mapper方法
|
||||
List<TreatmentResource> list = treatmentResourceMapper.selectByPublisher(resource.getPublisherId(), keyword);
|
||||
|
||||
// 创建PageInfo对象
|
||||
return new PageInfo<>(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源使用情况统计数据
|
||||
* @return 资源使用情况统计数据
|
||||
*/
|
||||
public Map<String, Object> getResourceStatistics() {
|
||||
Map<String, Object> statistics = new HashMap<>();
|
||||
|
||||
try {
|
||||
// 查询所有资源
|
||||
List<TreatmentResource> resources = treatmentResourceMapper.selectList(null);
|
||||
|
||||
// 按分类统计资源数量
|
||||
Map<Integer, Long> countByCategory = resources.stream()
|
||||
.collect(Collectors.groupingBy(TreatmentResource::getCategoryId, Collectors.counting()));
|
||||
|
||||
// 统计总访问次数和总下载次数
|
||||
int totalVisits = resources.stream()
|
||||
.mapToInt(r -> r.getVisitCount() != null ? r.getVisitCount() : 0)
|
||||
.sum();
|
||||
|
||||
int totalDownloads = resources.stream()
|
||||
.mapToInt(r -> r.getDownloadCount() != null ? r.getDownloadCount() : 0)
|
||||
.sum();
|
||||
|
||||
// 访问次数最多的资源TOP5
|
||||
List<TreatmentResource> topVisitResources = resources.stream()
|
||||
.sorted(Comparator.comparing(r -> r.getVisitCount() != null ? -r.getVisitCount() : 0))
|
||||
.limit(5)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 下载次数最多的资源TOP5
|
||||
List<TreatmentResource> topDownloadResources = resources.stream()
|
||||
.sorted(Comparator.comparing(r -> r.getDownloadCount() != null ? -r.getDownloadCount() : 0))
|
||||
.limit(5)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 按资源分类统计访问次数和下载次数
|
||||
Map<Integer, Integer> visitsByCategory = new HashMap<>();
|
||||
Map<Integer, Integer> downloadsByCategory = new HashMap<>();
|
||||
|
||||
for (TreatmentResource resource : resources) {
|
||||
Integer categoryId = resource.getCategoryId();
|
||||
Integer visitCount = resource.getVisitCount() != null ? resource.getVisitCount() : 0;
|
||||
Integer downloadCount = resource.getDownloadCount() != null ? resource.getDownloadCount() : 0;
|
||||
|
||||
visitsByCategory.put(categoryId, visitsByCategory.getOrDefault(categoryId, 0) + visitCount);
|
||||
downloadsByCategory.put(categoryId, downloadsByCategory.getOrDefault(categoryId, 0) + downloadCount);
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
statistics.put("totalResources", resources.size());
|
||||
statistics.put("totalVisits", totalVisits);
|
||||
statistics.put("totalDownloads", totalDownloads);
|
||||
statistics.put("countByCategory", countByCategory);
|
||||
statistics.put("visitsByCategory", visitsByCategory);
|
||||
statistics.put("downloadsByCategory", downloadsByCategory);
|
||||
statistics.put("topVisitResources", topVisitResources);
|
||||
statistics.put("topDownloadResources", topDownloadResources);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return statistics;
|
||||
}
|
||||
}
|
||||
195
src/main/java/com/example/websocket/ChatWebSocket.java
Normal file
195
src/main/java/com/example/websocket/ChatWebSocket.java
Normal file
@@ -0,0 +1,195 @@
|
||||
package com.example.websocket;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.example.entity.ChatMessage;
|
||||
import com.example.service.ChatMessageService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ServerEndpoint("/ws/chat/{userId}/{userType}")
|
||||
@Component
|
||||
public class ChatWebSocket {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ChatWebSocket.class);
|
||||
|
||||
// 静态变量,用来记录当前在线连接数
|
||||
private static int onlineCount = 0;
|
||||
|
||||
// 用户ID和WebSocket的映射关系
|
||||
private static Map<String, ChatWebSocket> clients = new ConcurrentHashMap<>();
|
||||
|
||||
// 与某个客户端的连接会话,用于发送数据
|
||||
private Session session;
|
||||
|
||||
// 当前连接用户ID
|
||||
private Integer userId;
|
||||
|
||||
// 当前连接用户类型
|
||||
private String userType;
|
||||
|
||||
// 注入Service,因为@ServerEndpoint不支持直接注入,需要通过静态变量
|
||||
private static ChatMessageService chatMessageService;
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Resource
|
||||
public void setChatMessageService(ChatMessageService chatMessageService) {
|
||||
ChatWebSocket.chatMessageService = chatMessageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("userId") Integer userId, @PathParam("userType") String userType) {
|
||||
this.session = session;
|
||||
this.userId = userId;
|
||||
this.userType = userType;
|
||||
|
||||
// 将当前WebSocket对象加入到Map中
|
||||
String key = userId + ":" + userType;
|
||||
clients.put(key, this);
|
||||
|
||||
addOnlineCount();
|
||||
log.info("有新连接加入,当前在线人数为:{}", getOnlineCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
// 从Map中移除
|
||||
String key = userId + ":" + userType;
|
||||
clients.remove(key);
|
||||
|
||||
subOnlineCount();
|
||||
log.info("有一连接关闭,当前在线人数为:{}", getOnlineCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("收到来自用户{}:{}的消息:{}", userId, userType, message);
|
||||
|
||||
try {
|
||||
// 解析消息
|
||||
ChatMessage chatMessage = objectMapper.readValue(message, ChatMessage.class);
|
||||
|
||||
// 直接设置发送者信息,不再通过TokenUtils获取
|
||||
chatMessage.setSenderId(userId);
|
||||
chatMessage.setSenderType(userType);
|
||||
chatMessage.setSendTime(new Date());
|
||||
chatMessage.setIsRead(false);
|
||||
|
||||
// 保存临时ID,用于前端识别消息
|
||||
String tempId = null;
|
||||
try {
|
||||
// 从消息中提取tempId字段
|
||||
Map<String, Object> messageMap = objectMapper.readValue(message, Map.class);
|
||||
if (messageMap.containsKey("tempId")) {
|
||||
tempId = messageMap.get("tempId").toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("提取tempId失败", e);
|
||||
}
|
||||
|
||||
// 保存消息到数据库
|
||||
try {
|
||||
// 检查发送者和接收者是否有关联关系并保存消息
|
||||
chatMessageService.directSaveMessage(chatMessage);
|
||||
|
||||
// 将保存后的消息转为Map,以便添加tempId
|
||||
Map<String, Object> responseMap = objectMapper.convertValue(chatMessage, Map.class);
|
||||
if (tempId != null) {
|
||||
responseMap.put("tempId", tempId);
|
||||
}
|
||||
String responseJson = objectMapper.writeValueAsString(responseMap);
|
||||
|
||||
// 转发消息给接收者
|
||||
String receiverKey = chatMessage.getReceiverId() + ":" + chatMessage.getReceiverType();
|
||||
ChatWebSocket receiverSocket = clients.get(receiverKey);
|
||||
if (receiverSocket != null) {
|
||||
// 接收者在线,发送消息
|
||||
receiverSocket.sendMessage(responseJson);
|
||||
}
|
||||
|
||||
// 同时也返回给发送者
|
||||
sendMessage(responseJson);
|
||||
} catch (Exception e) {
|
||||
log.error("处理消息时发生错误", e);
|
||||
// 发送错误消息给客户端
|
||||
ChatMessage errorMessage = new ChatMessage();
|
||||
errorMessage.setSenderId(0);
|
||||
errorMessage.setSenderType("system");
|
||||
errorMessage.setReceiverId(userId);
|
||||
errorMessage.setReceiverType(userType);
|
||||
errorMessage.setContent("发送消息失败:" + e.getMessage());
|
||||
errorMessage.setSendTime(new Date());
|
||||
|
||||
// 将错误消息转为Map,以便添加tempId
|
||||
Map<String, Object> errorMap = objectMapper.convertValue(errorMessage, Map.class);
|
||||
if (tempId != null) {
|
||||
errorMap.put("tempId", tempId);
|
||||
}
|
||||
sendMessage(objectMapper.writeValueAsString(errorMap));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理消息时发生错误", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发生错误时调用
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
log.error("发生错误", error);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
public void sendMessage(String message) {
|
||||
try {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
} catch (IOException e) {
|
||||
log.error("发送消息失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端主动推送消息
|
||||
*/
|
||||
public static void sendMessage(Integer userId, String userType, String message) {
|
||||
String key = userId + ":" + userType;
|
||||
ChatWebSocket socket = clients.get(key);
|
||||
if (socket != null) {
|
||||
socket.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized int getOnlineCount() {
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public static synchronized void addOnlineCount() {
|
||||
ChatWebSocket.onlineCount++;
|
||||
}
|
||||
|
||||
public static synchronized void subOnlineCount() {
|
||||
ChatWebSocket.onlineCount--;
|
||||
}
|
||||
}
|
||||
28
src/main/resources/application.yml
Normal file
28
src/main/resources/application.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: 9090
|
||||
|
||||
# 数据库配置
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
username: root
|
||||
password: 123456
|
||||
url: jdbc:mysql://localhost:3306/psychologicaltreatment?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=true
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 100MB
|
||||
max-request-size: 100MB
|
||||
|
||||
# 配置mybatis实体和xml映射
|
||||
mybatis:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
map-underscore-to-camel-case: true
|
||||
mapper-locations: classpath:mapper/*.xml
|
||||
|
||||
fileBaseUrl: http://localhost:${server.port}
|
||||
|
||||
# 通义千问API配置
|
||||
dashscope:
|
||||
api-key: sk-0b1b6c3287364c2d8b8e1f656bfafece
|
||||
model: qwen-turbo
|
||||
26
src/main/resources/mapper/AdminMapper.xml
Normal file
26
src/main/resources/mapper/AdminMapper.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.mapper.AdminMapper">
|
||||
|
||||
<select id="selectAll" resultType="com.example.entity.Admin">
|
||||
select `admin`.* from `admin`
|
||||
|
||||
<where>
|
||||
<if test="username != null and username != ''">
|
||||
and `admin`.`username` like concat ('%', #{username}, '%')
|
||||
</if>
|
||||
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.example.entity.Admin">
|
||||
select * from admin where id = #{id}
|
||||
</select>
|
||||
|
||||
<delete id="deleteById">
|
||||
delete from admin where id = #{id}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
25
src/main/resources/mapper/DoctorMapper.xml
Normal file
25
src/main/resources/mapper/DoctorMapper.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.mapper.DoctorMapper">
|
||||
|
||||
<select id="selectAll" resultType="com.example.entity.Doctor">
|
||||
select `doctor`.* from `doctor`
|
||||
|
||||
<where>
|
||||
<if test="name != null and name != ''">
|
||||
and `doctor`.`name` like concat ('%', #{name}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.example.entity.Doctor">
|
||||
select * from doctor where id = #{id}
|
||||
</select>
|
||||
|
||||
<delete id="deleteById">
|
||||
delete from doctor where id = #{id}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
91
src/main/resources/mapper/DoctorPatientMapper.xml
Normal file
91
src/main/resources/mapper/DoctorPatientMapper.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.mapper.DoctorPatientMapper">
|
||||
|
||||
<resultMap id="doctorPatientMap" type="com.example.entity.DoctorPatient">
|
||||
<id property="id" column="id"/>
|
||||
<result property="doctorId" column="doctor_id"/>
|
||||
<result property="patientId" column="patient_id"/>
|
||||
<result property="relationshipStart" column="relationship_start"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<association property="doctor" javaType="com.example.entity.Doctor">
|
||||
<id property="id" column="d_id"/>
|
||||
<result property="username" column="d_username"/>
|
||||
<result property="name" column="d_name"/>
|
||||
<result property="sex" column="d_sex"/>
|
||||
<result property="phone" column="d_phone"/>
|
||||
<result property="email" column="d_email"/>
|
||||
<result property="certificateNo" column="d_certificate_no"/>
|
||||
<result property="hospital" column="d_hospital"/>
|
||||
<result property="department" column="d_department"/>
|
||||
</association>
|
||||
<association property="patient" javaType="com.example.entity.Patient">
|
||||
<id property="id" column="p_id"/>
|
||||
<result property="username" column="p_username"/>
|
||||
<result property="name" column="p_name"/>
|
||||
<result property="sex" column="p_sex"/>
|
||||
<result property="phone" column="p_phone"/>
|
||||
<result property="email" column="p_email"/>
|
||||
</association>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByDoctorId" resultMap="doctorPatientMap">
|
||||
SELECT
|
||||
dp.*,
|
||||
p.id AS p_id,
|
||||
p.username AS p_username,
|
||||
p.name AS p_name,
|
||||
p.sex AS p_sex,
|
||||
p.phone AS p_phone,
|
||||
p.email AS p_email,
|
||||
d.id AS d_id,
|
||||
d.username AS d_username,
|
||||
d.name AS d_name
|
||||
FROM
|
||||
doctor_patient dp
|
||||
LEFT JOIN patient p ON dp.patient_id = p.id
|
||||
LEFT JOIN doctor d ON dp.doctor_id = d.id
|
||||
WHERE
|
||||
dp.doctor_id = #{doctorId}
|
||||
<if test="name != null and name != ''">
|
||||
AND p.name LIKE CONCAT('%', #{name}, '%')
|
||||
</if>
|
||||
ORDER BY
|
||||
dp.create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectByPatientId" resultMap="doctorPatientMap">
|
||||
SELECT
|
||||
dp.*,
|
||||
p.id AS p_id,
|
||||
p.username AS p_username,
|
||||
p.name AS p_name,
|
||||
p.sex AS p_sex,
|
||||
p.phone AS p_phone,
|
||||
p.email AS p_email,
|
||||
d.id AS d_id,
|
||||
d.username AS d_username,
|
||||
d.name AS d_name,
|
||||
d.sex AS d_sex,
|
||||
d.phone AS d_phone,
|
||||
d.email AS d_email,
|
||||
d.certificate_no AS d_certificate_no,
|
||||
d.hospital AS d_hospital,
|
||||
d.department AS d_department
|
||||
FROM
|
||||
doctor_patient dp
|
||||
LEFT JOIN patient p ON dp.patient_id = p.id
|
||||
LEFT JOIN doctor d ON dp.doctor_id = d.id
|
||||
WHERE
|
||||
dp.patient_id = #{patientId}
|
||||
<if test="name != null and name != ''">
|
||||
AND d.name LIKE CONCAT('%', #{name}, '%')
|
||||
</if>
|
||||
ORDER BY
|
||||
dp.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
25
src/main/resources/mapper/PatientMapper.xml
Normal file
25
src/main/resources/mapper/PatientMapper.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.mapper.PatientMapper">
|
||||
|
||||
<select id="selectAll" resultType="com.example.entity.Patient">
|
||||
select `patient`.* from `patient`
|
||||
|
||||
<where>
|
||||
<if test="name != null and name != ''">
|
||||
and `patient`.`name` like concat ('%', #{name}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.example.entity.Patient">
|
||||
select * from patient where id = #{id}
|
||||
</select>
|
||||
|
||||
<delete id="deleteById">
|
||||
delete from patient where id = #{id}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
61
src/main/resources/mapper/SymptomRecordMapper.xml
Normal file
61
src/main/resources/mapper/SymptomRecordMapper.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.mapper.SymptomRecordMapper">
|
||||
|
||||
<resultMap id="symptomRecordMap" type="com.example.entity.SymptomRecord">
|
||||
<id property="id" column="id"/>
|
||||
<result property="patientId" column="patient_id"/>
|
||||
<result property="symptomDesc" column="symptom_desc"/>
|
||||
<result property="severityLevel" column="severity_level"/>
|
||||
<result property="emotionScore" column="emotion_score"/>
|
||||
<result property="energyDuration" column="energy_duration"/>
|
||||
<result property="interestRecovery" column="interest_recovery"/>
|
||||
<result property="sleepTime" column="sleep_time"/>
|
||||
<result property="wakeCount" column="wake_count"/>
|
||||
<result property="morningWake" column="morning_wake"/>
|
||||
<result property="mealCompletion" column="meal_completion"/>
|
||||
<result property="painLocation" column="pain_location"/>
|
||||
<result property="painIntensity" column="pain_intensity"/>
|
||||
<result property="memoryTest" column="memory_test"/>
|
||||
<result property="decisionTime" column="decision_time"/>
|
||||
<result property="attentionSpan" column="attention_span"/>
|
||||
<result property="suicidalThought" column="suicidal_thought"/>
|
||||
<result property="recordTime" column="record_time"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
|
||||
<!-- 关联患者信息 -->
|
||||
<association property="patient" javaType="com.example.entity.Patient">
|
||||
<id property="id" column="p_id"/>
|
||||
<result property="username" column="p_username"/>
|
||||
<result property="name" column="p_name"/>
|
||||
<result property="avatar" column="p_avatar"/>
|
||||
<result property="sex" column="p_sex"/>
|
||||
<result property="phone" column="p_phone"/>
|
||||
<result property="email" column="p_email"/>
|
||||
</association>
|
||||
</resultMap>
|
||||
|
||||
<!-- 查询记录并带患者信息 -->
|
||||
<select id="selectWithPatient" resultMap="symptomRecordMap">
|
||||
SELECT
|
||||
sr.*,
|
||||
p.id AS p_id,
|
||||
p.username AS p_username,
|
||||
p.name AS p_name,
|
||||
p.avatar AS p_avatar,
|
||||
p.sex AS p_sex,
|
||||
p.phone AS p_phone,
|
||||
p.email AS p_email
|
||||
FROM
|
||||
symptom_record sr
|
||||
LEFT JOIN
|
||||
patient p ON sr.patient_id = p.id
|
||||
<where>
|
||||
<if test="patientId != null">
|
||||
AND sr.patient_id = #{patientId}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY
|
||||
sr.record_time DESC
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user