zjk
2026-09-29 54dcf0a82e7490fa58b1c056d5c0b9cb739c2931
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/member/service/UserAppService.java
@@ -7,7 +7,6 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tcm.training.admin.common.DateTimes;
import com.tcm.training.admin.common.PageResponse;
import com.tcm.training.admin.common.PhoneMasker;
import com.tcm.training.admin.live.entity.Clinic;
import com.tcm.training.admin.live.mapper.ClinicMapper;
import com.tcm.training.admin.member.dto.UserBatchClinicUpdateRequest;
@@ -147,12 +146,8 @@
    /** 更新用户信息。 */
    public UserDetailVO update(Long id, UserUpdateRequest req) {
        AppUser user = requireUser(id);
        if (req.getClinicId() != null) {
            Clinic clinic = clinicMapper.selectById(req.getClinicId());
            if (clinic == null || (clinic.getDeleted() != null && clinic.getDeleted() == 1)) {
                throw new IllegalArgumentException("绑定诊所不存在");
            }
        }
        boolean personalUser = Integer.valueOf(0).equals(user.getType());
        Long clinicUserId = personalUser ? resolveClinicUserId(req.getClinicId()) : null;
        AppUser phoneConflict = userMapper.selectOne(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getPhone, req.getPhone().trim())
                .ne(AppUser::getId, id)
@@ -166,9 +161,11 @@
        user.setPhone(req.getPhone().trim());
        user.setAvatar(trimToNull(req.getAvatar()));
        user.setStatus(req.getStatus());
        user.setClinicId(req.getClinicId());
        user.setMemberExpireAt(req.getMemberExpireAt());
        userMapper.updateById(user);
        if (personalUser) {
            updateClinicBinding(java.util.Collections.singletonList(id), req.getClinicId(), clinicUserId);
        }
        return detail(id);
    }
@@ -216,20 +213,48 @@
    @Transactional(rollbackFor = Exception.class)
    /** 批量更新用户诊所归属。 */
    public void batchUpdateClinic(UserBatchClinicUpdateRequest req) {
        Clinic clinic = clinicMapper.selectById(req.getClinicId());
        if (clinic == null || Integer.valueOf(1).equals(clinic.getDeleted())) {
            throw new IllegalArgumentException("诊所不存在");
        }
        Long clinicUserId = resolveClinicUserId(req.getClinicId());
        Long userCount = userMapper.selectCount(new LambdaQueryWrapper<AppUser>()
                .in(AppUser::getId, req.getUserIds())
                .eq(AppUser::getType, 0)
                .eq(AppUser::getDeleted, 0));
        if (userCount != req.getUserIds().size()) {
            throw new IllegalArgumentException("部分用户不存在");
            throw new IllegalArgumentException("部分用户不存在或不是普通用户");
        }
        userMapper.update(null, new LambdaUpdateWrapper<AppUser>()
                .in(AppUser::getId, req.getUserIds())
        updateClinicBinding(req.getUserIds(), req.getClinicId(), clinicUserId);
    }
    /** 诊所 ID 与诊所账号用户 ID 不同,患者查询依赖后者。 */
    private Long resolveClinicUserId(Long clinicId) {
        if (clinicId == null) {
            return null;
        }
        Clinic clinic = clinicMapper.selectById(clinicId);
        if (clinic == null || Integer.valueOf(1).equals(clinic.getDeleted())) {
            throw new IllegalArgumentException("绑定诊所不存在");
        }
        List<AppUser> clinicUsers = userMapper.selectList(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getClinicId, clinicId)
                .eq(AppUser::getType, 1)
                .eq(AppUser::getDeleted, 0)
                .set(AppUser::getClinicId, req.getClinicId()));
                .last("limit 2"));
        if (clinicUsers.isEmpty()) {
            throw new IllegalArgumentException("目标诊所尚未关联诊所账号,无法绑定患者");
        }
        if (clinicUsers.size() > 1) {
            throw new IllegalArgumentException("目标诊所关联多个账号,请先确认患者归属");
        }
        return clinicUsers.get(0).getId();
    }
    /** 同步两个归属字段;显式 set 确保解除绑定时 null 也能写入。 */
    private void updateClinicBinding(List<Long> userIds, Long clinicId, Long clinicUserId) {
        userMapper.update(null, new LambdaUpdateWrapper<AppUser>()
                .in(AppUser::getId, userIds)
                .eq(AppUser::getType, 0)
                .eq(AppUser::getDeleted, 0)
                .set(AppUser::getClinicId, clinicId)
                .set(AppUser::getSuperiorClinicUserId, clinicUserId));
    }
    /** 查询诊所选项。 */
@@ -281,7 +306,7 @@
                MemberUserExcelRow excel = new MemberUserExcelRow();
                excel.setId(row.getId());
                excel.setNickname(row.getNickname());
                excel.setPhone(PhoneMasker.mask(row.getPhone()));
                excel.setPhone(row.getPhone());
                excel.setMemberStatus(row.getIsMember() != null && row.getIsMember() == 1 ? "生效中" : "已失效");
                excel.setMemberExpireAt(DateTimes.format(row.getMemberExpireAt()));
                memberExcelRows.add(excel);
@@ -297,7 +322,7 @@
            excel.setId(row.getId());
            excel.setNickname(row.getNickname());
            excel.setType(typeText(row.getType()));
            excel.setPhone(PhoneMasker.mask(row.getPhone()));
            excel.setPhone(row.getPhone());
            excel.setClinicName(row.getClinicName() == null ? "-" : row.getClinicName());
            excel.setAge(row.getAge());
            excel.setGender(genderText(row.getGender()));