Pārlūkot izejas kodu

add
账号医院切换

lifang 1 mēnesi atpakaļ
vecāks
revīzija
aec8f6f8c8

+ 1 - 1
nb-admin/src/main/resources/application.yml

@@ -7,7 +7,7 @@ spring:
   application:
     name: nb
   profiles:
-    active: prod
+    active: dev
   jackson:
     time-zone: GMT+8
 

+ 18 - 0
nb-common/config-common/src/main/java/com/nb/common/config/annotation/TenantIgnore.java

@@ -0,0 +1,18 @@
+package com.nb.common.config.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 忽略租户,标记指定方法不进行租户的自动过滤
+ *
+ * 注意,只有 DB 的场景会过滤,其它场景暂时不过滤:
+ * 1、Redis 场景:因为是基于 Key 实现多租户的能力,所以忽略没有意义,不像 DB 是一个 column 实现的
+ * 2、MQ 场景:有点难以抉择,目前可以通过 Consumer 手动在消费的方法上,添加 @TenantIgnore 进行忽略
+ *
+ * @author 芋道源码
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface TenantIgnore {
+}

+ 36 - 0
nb-common/config-common/src/main/java/com/nb/common/config/aspect/TenantIgnoreAspect.java

@@ -0,0 +1,36 @@
+package com.nb.common.config.aspect;
+
+import com.nb.common.config.annotation.TenantIgnore;
+import com.nb.common.config.context.TenantContextHolder;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+/**
+ * 忽略多租户的 Aspect,基于 {@link TenantIgnore} 注解实现,用于一些全局的逻辑。
+ * 例如说,一个定时任务,读取所有数据,进行处理。
+ * 又例如说,读取所有数据,进行缓存。
+ *
+ *
+ * @author tr
+ */
+@Aspect
+@Slf4j
+@Component
+public class TenantIgnoreAspect {
+
+    @Around("@annotation(tenantIgnore)")
+    public Object around(ProceedingJoinPoint joinPoint, TenantIgnore tenantIgnore) throws Throwable {
+        Boolean oldIgnore = TenantContextHolder.isIgnore();
+        try {
+            TenantContextHolder.setIgnore(true);
+            // 执行逻辑
+            return joinPoint.proceed();
+        } finally {
+            TenantContextHolder.setIgnore(oldIgnore);
+        }
+    }
+
+}

+ 59 - 0
nb-common/config-common/src/main/java/com/nb/common/config/context/TenantContextHolder.java

@@ -0,0 +1,59 @@
+package com.nb.common.config.context;
+
+/**
+ * 多租户上下文 Holder
+ *
+ * @author tr
+ */
+public class TenantContextHolder {
+
+    private static final ThreadLocal<String> TENANT_ID_HOLDER = new ThreadLocal<>();
+    private static final ThreadLocal<Boolean> IGNORE_HOLDER = new ThreadLocal<>();
+
+    /**
+     * 获得租户编号。
+     *
+     * @return 租户编号
+     */
+    public static String getTenantId() {
+        return TENANT_ID_HOLDER.get();
+    }
+
+    /**
+     * 获得租户编号。如果不存在,则抛出 NullPointerException 异常
+     *
+     * @return 租户编号
+     */
+    public static String getRequiredTenantId() {
+        String tenantId = getTenantId();
+        if (tenantId == null) {
+            throw new NullPointerException("TenantContextHolder 不存在租户编号!");
+        }
+        return tenantId;
+    }
+
+    public static void setTenantId(String tenantId) {
+        TENANT_ID_HOLDER.set(tenantId);
+    }
+
+    public static void setIgnore(boolean ignore) {
+        IGNORE_HOLDER.set(ignore);
+    }
+
+    /**
+     * 当前是否忽略租户
+     *
+     * @return 是否忽略
+     */
+    public static Boolean isIgnore() {
+        return IGNORE_HOLDER.get();
+    }
+    
+    /**
+     * 清除当前线程的租户上下文信息
+     */
+    public static void clear() {
+        TENANT_ID_HOLDER.remove();
+        IGNORE_HOLDER.remove();
+    }
+}

+ 4 - 0
nb-common/config-common/src/main/java/com/nb/common/config/mybatisplus/interceptor/DefaultTenantLineInnerInterceptor.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerIntercept
 import com.nb.auth.bean.LoginUser;
 import com.nb.auth.enums.StpTypeEnum;
 import com.nb.auth.utils.SecurityUtil;
+import com.nb.common.config.context.TenantContextHolder;
 import com.nb.core.entity.TenantGenericEntity;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.StringValue;
@@ -83,6 +84,9 @@ public class DefaultTenantLineInnerInterceptor {
 
             @Override
             public boolean ignoreTable(String tableName) {
+                if (Boolean.TRUE.equals(TenantContextHolder.isIgnore())) {
+                    return Boolean.TRUE;
+                }
                 ServletRequestAttributes request = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                 //非用户请求,即来自程序自身,则忽略
                 if(request==null||request.getRequest() instanceof MockHttpServletRequest){

+ 3 - 0
nb-service-api/web-service-api/src/main/java/com/nb/web/api/feign/IHospitalClient.java

@@ -1,5 +1,6 @@
 package com.nb.web.api.feign;
 
+import com.nb.web.api.feign.result.AppHospitalVO;
 import com.nb.web.api.feign.result.HospitalResult;
 import java.util.*;
 /**
@@ -18,4 +19,6 @@ public interface IHospitalClient {
      * @return List<HospitalResult>
      */
     List<HospitalResult> selectAll();
+
+    List<AppHospitalVO> selectUserHospitalList(String username);
 }

+ 15 - 0
nb-service-api/web-service-api/src/main/java/com/nb/web/api/feign/result/AppHospitalVO.java

@@ -0,0 +1,15 @@
+package com.nb.web.api.feign.result;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class AppHospitalVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty("医院id")
+    private String id;
+    @ApiModelProperty("医院名称")
+    private String name;
+}

+ 30 - 3
nb-service/app-doctor/src/main/java/com/nb/app/doctor/controller/UserController.java

@@ -1,18 +1,24 @@
 package com.nb.app.doctor.controller;
 
+import cn.dev33.satoken.session.SaSession;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.nb.app.doctor.api.entity.AppDoctorUserEntity;
 import com.nb.app.doctor.api.entity.AppUserConsultConfigEntity;
+import com.nb.app.doctor.service.dto.UserShiftHospitalDTO;
+import com.nb.auth.bean.LoginUser;
+import com.nb.common.config.annotation.TenantIgnore;
+import com.nb.web.api.feign.result.AppHospitalVO;
 import com.nb.app.doctor.service.LocalUserConsultConfigService;
+import com.nb.auth.utils.SecurityUtil;
 import com.nb.core.entity.GenericEntity;
 import com.nb.core.result.R;
+import com.nb.web.api.feign.IHospitalClient;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
-
+import java.util.*;
 /**
  * @author lifang
  * @version 1.0.0
@@ -27,7 +33,7 @@ import org.springframework.web.bind.annotation.*;
 @Slf4j
 public class UserController {
     private final LocalUserConsultConfigService consultConfigService;
-
+    private final IHospitalClient hospitalClient;
 
     @PostMapping("/consult/{userId}")
     @ApiOperation("查询医生咨询设置")
@@ -42,4 +48,25 @@ public class UserController {
         return R.success(consultConfigService.updateById(source));
     }
 
+
+    @GetMapping("/hospitalList")
+    @ApiOperation("查询当前用户所在的医院列表")
+    @TenantIgnore
+    public R<List<AppHospitalVO>> hospitalList(){
+        return R.success(hospitalClient.selectUserHospitalList(SecurityUtil.getUsername()));
+    }
+
+    @PostMapping("/shiftHospital")
+    @ApiOperation("切换当前用户所在医院")
+    @TenantIgnore
+    public R<Boolean> shiftHospital(@RequestBody@Validated UserShiftHospitalDTO source){
+        SaSession tokenSession = SecurityUtil.getStpLogic().getTokenSessionByToken(SecurityUtil.getStpLogic().getTokenValue());
+        LoginUser<String> loginUserClass =tokenSession.getModel(SecurityUtil.LOGIN_USER_KEY, LoginUser.class);
+        String hospitalId = source.getHospitalId();
+        loginUserClass.setTenantId(hospitalId);
+        tokenSession.set(SecurityUtil.LOGIN_USER_KEY, loginUserClass);
+        return R.success(Boolean.TRUE);
+    }
+
+
 }

+ 13 - 0
nb-service/app-doctor/src/main/java/com/nb/app/doctor/service/dto/UserShiftHospitalDTO.java

@@ -0,0 +1,13 @@
+package com.nb.app.doctor.service.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class UserShiftHospitalDTO {
+    @ApiModelProperty("医院id")
+    @NotBlank(message = "医院id不能为空")
+    private String hospitalId;
+}

+ 1 - 1
nb-service/web-service/src/main/java/com/nb/web/service/bus/hospital/HospitalHisDataPullJob.java

@@ -69,7 +69,7 @@ public class HospitalHisDataPullJob implements Job {
                 log.warn("[定时拉取病人数据]未找到医院管理器,hospitalId:{}", hospitalId);
                 return;
             }
-            if (hospitalManager.getScriptSession().isOnline()) {
+            if (!hospitalManager.getScriptSession().isOnline()) {
                 log.warn("[定时拉取病人数据]医院不在线,hospitalId:{}", hospitalId);
                 return;
             }

+ 12 - 1
nb-service/web-service/src/main/java/com/nb/web/service/bus/mapper/BusHospitalMapper.java

@@ -1,8 +1,13 @@
 package com.nb.web.service.bus.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.nb.web.api.feign.result.AppHospitalVO;
 import com.nb.web.service.bus.entity.BusHospitalEntity;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
 
 /**
  * @author lifang
@@ -13,4 +18,10 @@ import org.apache.ibatis.annotations.Mapper;
  */
 @Mapper
 public interface BusHospitalMapper extends BaseMapper<BusHospitalEntity> {
-}
+    /**
+     * 根据用户名查询用户所拥有的医院列表
+     * @param username
+     * @return
+     */
+    List<AppHospitalVO> selectUserHospitalListByUsername(@Param("username") String username);
+}

+ 9 - 0
nb-service/web-service/src/main/java/com/nb/web/service/bus/service/LocalBusHospitalService.java

@@ -18,6 +18,7 @@ import com.nb.auth.utils.SecurityUtil;
 import com.nb.web.api.bean.GeoPoint;
 import com.nb.web.api.entity.BusHospitalConfigEntity;
 import com.nb.web.api.feign.IHospitalClient;
+import com.nb.web.api.feign.result.AppHospitalVO;
 import com.nb.web.api.feign.result.HospitalResult;
 import com.nb.web.service.bus.entity.*;
 import com.nb.web.service.bus.enums.ConstantMixEnum;
@@ -47,6 +48,7 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.annotation.PostConstruct;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
@@ -88,6 +90,8 @@ public class LocalBusHospitalService extends BaseService<BusHospitalMapper, BusH
     @Autowired
     @Lazy
     private LocalBusHospitalConfigService configService;
+    @Autowired
+    private BusHospitalMapper hospitalMapper;
     @PostConstruct
     public void init(){
         nameCache =configStorageManager.getStorage("hospital_name");
@@ -331,4 +335,9 @@ public class LocalBusHospitalService extends BaseService<BusHospitalMapper, BusH
     public List<HospitalResult> selectAll() {
         return BeanUtil.copyToList(list(),HospitalResult.class);
     }
+
+    @Override
+    public List<AppHospitalVO> selectUserHospitalList(String username) {
+        return hospitalMapper.selectUserHospitalListByUsername(username);
+    }
 }

+ 17 - 0
nb-service/web-service/src/main/resources/mapper/bus/BusHospitalMapper.xml

@@ -0,0 +1,17 @@
+<?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.nb.web.service.bus.mapper.BusHospitalMapper">
+    <resultMap id="hospitalList" type="com.nb.web.api.feign.result.AppHospitalVO">
+        <id property="id" column="id"/>
+        <result property="name" column="name"/>
+    </resultMap>
+
+    <select id="selectUserHospitalListByUsername" resultMap="hospitalList">
+        select
+            bh.tenant_id as id,
+                bh.name as name
+        from app_doctor_user as adu join bus_hospital as bh on bh.tenant_id=adu.tenant_id where adu.username=#{username}
+        order by bh.create_time desc
+    </select>
+
+</mapper>