Просмотр исходного кода

feat(user-binding): 增加用户绑定信息查询功能并优化性能

- 为 listByPatient 和 listByBoundUser 接口添加 Swagger 参数注解
- 在 UserBindingResponse 中新增被绑定用户的昵称和手机号字段
- 引入 UserInfoMapper 并在服务层注入
- 在查询绑定列表时批量获取被绑定用户信息,避免 N+1 查询问题
- 修复绑定类型无法自动复制的问题,手动设置 bindingType 字段
- 对空 ID 集合做安全判断,防止数据库异常
- 使用流式操作构建用户信息映射表,提升代码可读性
mcbaiyun 1 месяц назад
Родитель
Сommit
2c6afb6fcf

+ 9 - 2
src/main/java/work/baiyun/chronicdiseaseapp/controller/UserBindingController.java

@@ -2,6 +2,7 @@ package work.baiyun.chronicdiseaseapp.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.media.Content;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -85,7 +86,10 @@ public class UserBindingController {
                 schema = @Schema(implementation = Void.class)))
     })
     @PostMapping(path = "/list-by-patient", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
-    public R<?> listByPatient(Long patientUserId, String bindingType, @RequestBody BaseQueryRequest req) {
+    public R<?> listByPatient(
+            @Parameter(description = "患者用户ID", required = true) Long patientUserId,
+            @Parameter(description = "绑定类型(DOCTOR-医生, FAMILY-家属)", required = false) String bindingType,
+            @RequestBody BaseQueryRequest req) {
         try {
             Page<UserBindingResponse> page = userBindingService.listBindingsByPatient(patientUserId, bindingType, req);
             work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResponse vo = new work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResponse();
@@ -112,7 +116,10 @@ public class UserBindingController {
                 schema = @Schema(implementation = Void.class)))
     })
     @PostMapping(path = "/list-by-bound-user", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
-    public R<?> listByBoundUser(Long boundUserId, String bindingType, @RequestBody BaseQueryRequest req) {
+    public R<?> listByBoundUser(
+            @Parameter(description = "被绑定用户ID(医生或家属)", required = true) Long boundUserId,
+            @Parameter(description = "绑定类型(DOCTOR-医生, FAMILY-家属)", required = false) String bindingType,
+            @RequestBody BaseQueryRequest req) {
         try {
             Page<UserBindingResponse> page = userBindingService.listBindingsByBoundUser(boundUserId, bindingType, req);
             work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResponse vo = new work.baiyun.chronicdiseaseapp.model.vo.UserBindingPageResponse();

+ 6 - 0
src/main/java/work/baiyun/chronicdiseaseapp/model/vo/UserBindingResponse.java

@@ -26,4 +26,10 @@ public class UserBindingResponse {
 
     @Schema(description = "创建时间")
     private LocalDateTime createTime;
+
+    @Schema(description = "被绑定用户昵称(例如医生昵称)")
+    private String boundUserNickname;
+
+    @Schema(description = "被绑定用户手机号(例如医生手机号)")
+    private String boundUserPhone;
 }

+ 51 - 2
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/UserBindingServiceImpl.java

@@ -7,6 +7,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import work.baiyun.chronicdiseaseapp.mapper.UserBindingMapper;
+import work.baiyun.chronicdiseaseapp.mapper.UserInfoMapper;
 import work.baiyun.chronicdiseaseapp.model.po.UserBinding;
 import work.baiyun.chronicdiseaseapp.model.vo.BaseQueryRequest;
 import work.baiyun.chronicdiseaseapp.model.vo.UserBindingResponse;
@@ -17,6 +18,9 @@ import work.baiyun.chronicdiseaseapp.service.UserBindingService;
 import work.baiyun.chronicdiseaseapp.enums.UserBindingType;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
 import java.util.stream.Collectors;
 
 @Service
@@ -24,6 +28,8 @@ public class UserBindingServiceImpl implements UserBindingService {
 
     @Autowired
     private UserBindingMapper userBindingMapper;
+    @Autowired
+    private UserInfoMapper userInfoMapper;
 
     @Override
     public void createUserBinding(CreateUserBindingRequest request) {
@@ -41,6 +47,8 @@ public class UserBindingServiceImpl implements UserBindingService {
             // 如果不存在,则创建新的绑定关系
             UserBinding userBinding = new UserBinding();
             BeanUtils.copyProperties(request, userBinding);
+            // 手动设置绑定类型,因为类型不匹配无法自动复制
+            userBinding.setBindingType(UserBindingType.fromCode(request.getBindingType()));
             userBinding.setStatus(1); // 默认状态为有效
             userBindingMapper.insert(userBinding);
         }
@@ -68,14 +76,27 @@ public class UserBindingServiceImpl implements UserBindingService {
                 .eq(UserBinding::getStatus, 1) // 只查询有效的绑定关系
                 .ge(request.getStartTime() != null, UserBinding::getCreateTime, request.getStartTime())
                 .le(request.getEndTime() != null, UserBinding::getCreateTime, request.getEndTime());
-        
+
         if (bindingType != null && !bindingType.isEmpty()) {
             wrapper.eq(UserBinding::getBindingType, UserBindingType.fromCode(bindingType));
         }
-        
+
         wrapper.orderByDesc(UserBinding::getCreateTime);
 
         Page<UserBinding> result = userBindingMapper.selectPage(page, wrapper);
+        // 批量查询被绑定用户信息,避免 N+1
+        Set<Long> boundUserIds = result.getRecords().stream()
+                .map(UserBinding::getBoundUserId)
+                .filter(id -> id != null)
+                .collect(Collectors.toSet());
+
+        Map<Long, work.baiyun.chronicdiseaseapp.model.po.UserInfo> userInfoMap;
+        if (boundUserIds.isEmpty()) {
+            userInfoMap = new HashMap<>();
+        } else {
+            List<work.baiyun.chronicdiseaseapp.model.po.UserInfo> userInfos = userInfoMapper.selectBatchIds(boundUserIds);
+            userInfoMap = userInfos.stream().collect(Collectors.toMap(work.baiyun.chronicdiseaseapp.model.po.UserInfo::getId, u -> u));
+        }
 
         List<UserBindingResponse> responses = result.getRecords().stream().map(r -> {
             UserBindingResponse resp = new UserBindingResponse();
@@ -84,6 +105,13 @@ public class UserBindingServiceImpl implements UserBindingService {
             if (r.getBindingType() != null) {
                 resp.setBindingType(r.getBindingType().getCode());
             }
+
+            work.baiyun.chronicdiseaseapp.model.po.UserInfo ui = userInfoMap.get(r.getBoundUserId());
+            if (ui != null) {
+                resp.setBoundUserNickname(ui.getNickname());
+                resp.setBoundUserPhone(ui.getPhone());
+            }
+
             return resp;
         }).collect(Collectors.toList());
 
@@ -112,6 +140,20 @@ public class UserBindingServiceImpl implements UserBindingService {
 
         Page<UserBinding> result = userBindingMapper.selectPage(page, wrapper);
 
+        // 批量查询被绑定用户信息,避免 N+1
+        Set<Long> boundUserIds = result.getRecords().stream()
+                .map(UserBinding::getBoundUserId)
+                .filter(id -> id != null)
+                .collect(Collectors.toSet());
+
+        Map<Long, work.baiyun.chronicdiseaseapp.model.po.UserInfo> userInfoMap;
+        if (boundUserIds.isEmpty()) {
+            userInfoMap = new HashMap<>();
+        } else {
+            List<work.baiyun.chronicdiseaseapp.model.po.UserInfo> userInfos = userInfoMapper.selectBatchIds(boundUserIds);
+            userInfoMap = userInfos.stream().collect(Collectors.toMap(work.baiyun.chronicdiseaseapp.model.po.UserInfo::getId, u -> u));
+        }
+
         List<UserBindingResponse> responses = result.getRecords().stream().map(r -> {
             UserBindingResponse resp = new UserBindingResponse();
             BeanUtils.copyProperties(r, resp);
@@ -119,6 +161,13 @@ public class UserBindingServiceImpl implements UserBindingService {
             if (r.getBindingType() != null) {
                 resp.setBindingType(r.getBindingType().getCode());
             }
+
+            work.baiyun.chronicdiseaseapp.model.po.UserInfo ui = userInfoMap.get(r.getBoundUserId());
+            if (ui != null) {
+                resp.setBoundUserNickname(ui.getNickname());
+                resp.setBoundUserPhone(ui.getPhone());
+            }
+
             return resp;
         }).collect(Collectors.toList());