Przeglądaj źródła

Update 租户tenantId获取优先从请求头获取

YueYunyun 1 rok temu
rodzic
commit
e2d28d3532

+ 1 - 0
SERVER/VberAdminPlusV3/vber-common/vber-common-core/src/main/java/com/vber/common/core/constant/GlobalConstants.java

@@ -36,4 +36,5 @@ public interface GlobalConstants {
      * 三方认证 redis key
      */
     String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
+    String TENANT_ID_HEADER = "TenantId";
 }

+ 13 - 2
SERVER/VberAdminPlusV3/vber-common/vber-common-tenant/src/main/java/com/vber/common/tenant/helper/TenantHelper.java

@@ -7,10 +7,12 @@ import com.alibaba.ttl.TransmittableThreadLocal;
 import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.vber.common.core.constant.GlobalConstants;
+import com.vber.common.core.utils.ServletUtils;
 import com.vber.common.core.utils.SpringUtils;
 import com.vber.common.core.utils.StringUtils;
 import com.vber.common.redis.utils.RedisUtils;
 import com.vber.common.satoken.utils.LoginHelper;
+import jakarta.servlet.http.HttpServletRequest;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -164,13 +166,22 @@ public class TenantHelper {
     }
 
     /**
-     * 获取当前租户id(动态租户优先)
+     * 获取当前租户id(请求头优先,其次动态租户优先)
      */
     public static String getTenantId() {
         if (!isEnable()) {
             return null;
         }
-        String tenantId = TenantHelper.getDynamic();
+        String tenantId = "";
+        // 请求头获取的租户id优先级最高
+        HttpServletRequest request = ServletUtils.getRequest();
+        if (request != null) {
+            tenantId = request.getHeader(GlobalConstants.TENANT_ID_HEADER);
+        }
+        // 其次动态租户优先
+        if (StringUtils.isBlank(tenantId)) {
+            tenantId = TenantHelper.getDynamic();
+        }
         if (StringUtils.isBlank(tenantId)) {
             tenantId = LoginHelper.getTenantId();
         }

+ 1 - 0
UI/VAP_V3.VUE/src/core/services/RequestService.ts

@@ -49,6 +49,7 @@ Rs.interceptors.request.use(
 	(config) => {
 		config = Object.assign({}, defaultOption, config)
 		config.headers["Content-Language"] = getLanguage()
+		config.headers["TenantId"] = appStore.tenantStore.getTenantId()
 		if (!config.url) {
 			console.log("请求URL不能为空", config)
 			throw new Error("请求URL不能为空")

+ 1 - 0
UI/VAP_V3.VUE/src/layouts/main/content/Content.vue

@@ -16,6 +16,7 @@ const cachedViews = appStore.tagViewStore.getCachedViews()
 			}">
 			<router-view v-slot="{ Component, route }">
 				<transition name="vb-fade-router" mode="out-in">
+					<!-- 在同一页面打开路由组件,缓存组件会与切换租户冲突 -->
 					<keep-alive :include="cachedViews">
 						<component v-if="!route.meta.link" :is="Component" :key="route.path" />
 					</keep-alive>

+ 41 - 21
UI/VAP_V3.VUE/src/layouts/main/header/navbar/DynamicTenant.vue

@@ -2,41 +2,61 @@
 import apis from "@a"
 import router from "@r"
 import appStore from "@s"
+const route = useRoute()
 
-const tenantEnabled = ref(true)
 const tenantId = ref("")
+const tenantEnabled = ref(true)
 const tenantOptions = ref<any>([])
 const show = computed(() => {
-	return appStore.authStore.canChangeTenant()
+	return appStore.tenantStore.canChangeTenant()
+})
+const companyName = computed(() => {
+	return (
+		tenantOptions.value.find((item: any) => {
+			return item.tenantId === tenantId.value
+		})?.companyName ?? ""
+	)
 })
-
-const initTenant = async () => {
-	apis.loginApi.getTenantList().then((res: any) => {
-		tenantEnabled.value = res.data.tenantEnabled === undefined ? true : res.data.tenantEnabled
-		if (tenantEnabled.value) {
-			tenantOptions.value = res.data.voList
-		}
-	})
-}
 
 function onDynamicTenant() {
 	if (tenantId.value != null && tenantId.value !== "") {
-		apis.system.tenantApi.dynamicTenant(tenantId.value).then((res: any) => {
-			appStore.authStore.setDynamic(true)
-			appStore.tagViewStore.delAllViews()
-			router.push({ path: "/" })
-		})
+		window.open("/redirect-tenant/" + tenantId.value + "/" + route.path)
+		// appStore.tenantStore.setDynamicTenant(tenantId.value).then(() => {
+		// 	router.push({
+		// 		//path: "/redirect-tenant/" + tenantId.value + "/" + route.path,
+		// 		name: "redirect-tenant",
+		// 		params: {
+		// 			tenant: tenantId.value,
+		// 			path: route.path
+		// 		},
+		// 		query: route.query
+		// 	})
+		// })
 	}
 }
 function onDynamicClear() {
-	apis.system.tenantApi.dynamicClear().then((res: any) => {
-		appStore.authStore.setDynamic(false)
-		appStore.tagViewStore.delAllViews()
-		router.push({ path: "/" })
+	appStore.tenantStore.clearDynamicTenant().then(() => {
+		// router.push({
+		// 	name: "redirect-tenant",
+		// 	params: {
+		// 		tenant: "0",
+		// 		path: route.path
+		// 	},
+		// 	query: route.query
+		// })
 	})
 }
 function init() {
-	initTenant()
+	appStore.tenantStore
+		.initTenant()
+		.then((res: any) => {
+			tenantEnabled.value = true
+			tenantOptions.value = res
+		})
+		.catch(() => {
+			tenantOptions.value = []
+			tenantEnabled.value = false
+		})
 }
 
 onMounted(init)

+ 1 - 1
UI/VAP_V3.VUE/src/layouts/main/header/navbar/UserAccountMenu.vue

@@ -4,7 +4,7 @@ import apis from "@a"
 const router = useRouter()
 const user = appStore.authStore.user
 const dynamic = computed(() => {
-	return appStore.authStore.isDynamic()
+	return appStore.tenantStore.isDynamic()
 })
 function clearCache() {
 	appStore.dictStore.cleanDict().then(() => {

+ 1 - 1
UI/VAP_V3.VUE/src/layouts/main/toolbar/tag-view/Index.vue

@@ -84,7 +84,7 @@ function initTags() {
 }
 function addTags() {
 	const { name } = route
-	if (name) {
+	if (name && name !== "redirect" && name !== "redirect-tenant") {
 		tagViewStore.addView(route)
 		if (route.meta.link) {
 			tagViewStore.addIframeView(route)

+ 12 - 1
UI/VAP_V3.VUE/src/router/index.ts

@@ -42,10 +42,21 @@ export const constantRoutes: RouteRecordRaw[] = [
 				}
 			},
 			{
+				name: "redirect",
 				path: "/redirect/:path(.*)",
 				component: () => import("@/views/redirect/index.vue"),
 				meta: {
-					title: "加载中..."
+					title: "加载中...",
+					noCache: true
+				}
+			},
+			{
+				name: "redirect-tenant",
+				path: "/redirect-tenant/:tenant/:path(.*)",
+				component: () => import("@/views/redirect/tenant.vue"),
+				meta: {
+					title: "加载中...",
+					noCache: true
 				}
 			}
 		]

+ 3 - 28
UI/VAP_V3.VUE/src/stores/_auth.ts

@@ -17,7 +17,7 @@ export const useAuthStore = defineStore("auth", () => {
 	const setUser = (data: any) => {
 		const u = data.user
 		user.value.tenantId = u.tenantId
-		setTenantId(u.tenantId)
+		appStore.tenantStore.setTenantId(u.tenantId)
 		user.value.userId = u.userId
 		user.value.userName = u.userName
 		user.value.nickName = u.nickName
@@ -50,6 +50,7 @@ export const useAuthStore = defineStore("auth", () => {
 		isAuthenticated.value = false
 		appStore.tagViewStore.delAllViews()
 		appStore.bodyConfigStore.resetLayoutConfig()
+		appStore.tenantStore.setTenantId("")
 		user.value = {} as User
 		localCache.remove("tenantId")
 		JwtService.destroyToken()
@@ -114,27 +115,6 @@ export const useAuthStore = defineStore("auth", () => {
 		})
 	}
 
-	function setTenantId(tenantId: string) {
-		localCache.set("tenantId", tenantId)
-	}
-	function getTenantId() {
-		return localCache.get("tenantId") || "000000"
-	}
-
-	function canChangeTenant() {
-		return (
-			user.value.roles.includes("super_admin") || user.value.permissions.includes("system:tenant")
-		)
-	}
-
-	const dynamic = ref(false)
-	function setDynamic(isDynamic: boolean) {
-		dynamic.value = isDynamic
-	}
-	function isDynamic() {
-		return dynamic.value
-	}
-
 	return {
 		errors,
 		user,
@@ -144,11 +124,6 @@ export const useAuthStore = defineStore("auth", () => {
 		callback,
 		logout,
 		getInfo,
-		changeAvatar,
-		setTenantId,
-		getTenantId,
-		canChangeTenant,
-		setDynamic,
-		isDynamic
+		changeAvatar
 	}
 })

+ 8 - 8
UI/VAP_V3.VUE/src/stores/_tagView.ts

@@ -82,15 +82,15 @@ export const useTagViewStore = defineStore("tagView", () => {
 	}
 	function delOthersViews(view: RouteLocationNormalizedLoaded) {
 		return new Promise((resolve) => {
-			delOthersvisitedViews(view)
-			delOtherscachedViews(view)
+			delOthersVisitedViews(view)
+			delOthersCachedViews(view)
 			resolve({
 				visitedViews: [...visitedViews.value],
 				cachedViews: [...cachedViews.value]
 			})
 		})
 	}
-	function delOthersvisitedViews(view: RouteLocationNormalizedLoaded) {
+	function delOthersVisitedViews(view: RouteLocationNormalizedLoaded) {
 		return new Promise((resolve) => {
 			visitedViews.value = visitedViews.value.filter((v) => {
 				return v.meta?.affix || v.path === view.path
@@ -99,7 +99,7 @@ export const useTagViewStore = defineStore("tagView", () => {
 			resolve([...visitedViews.value])
 		})
 	}
-	function delOtherscachedViews(view: RouteLocationNormalizedLoaded) {
+	function delOthersCachedViews(view: RouteLocationNormalizedLoaded) {
 		return new Promise((resolve) => {
 			const index = cachedViews.value.indexOf(view.name as string)
 			if (index > -1) {
@@ -112,15 +112,15 @@ export const useTagViewStore = defineStore("tagView", () => {
 	}
 	function delAllViews() {
 		return new Promise((resolve) => {
-			delAllvisitedViews()
-			delAllcachedViews()
+			delAllVisitedViews()
+			delAllCachedViews()
 			resolve({
 				visitedViews: [...visitedViews.value],
 				cachedViews: [...cachedViews.value]
 			})
 		})
 	}
-	function delAllvisitedViews() {
+	function delAllVisitedViews() {
 		return new Promise((resolve) => {
 			const affixTags = visitedViews.value.filter((tag) => tag.meta?.affix)
 			visitedViews.value = affixTags
@@ -128,7 +128,7 @@ export const useTagViewStore = defineStore("tagView", () => {
 			resolve([...visitedViews.value])
 		})
 	}
-	function delAllcachedViews() {
+	function delAllCachedViews() {
 		return new Promise((resolve) => {
 			cachedViews.value = []
 			resolve([...cachedViews.value])

+ 105 - 0
UI/VAP_V3.VUE/src/stores/_tenant.ts

@@ -0,0 +1,105 @@
+import apis from "@a"
+import appStore from "@s"
+
+export const useTenantStore = defineStore("tenant", () => {
+	const dynamicTenant = ref("")
+	const isNewPage = ref(false)
+	const tenantEnabled = ref(true)
+	const tenantList = ref<any>([])
+
+	const getCompanyName = () => {
+		return (
+			tenantList.value.find((item: any) => {
+				return item.tenantId === getTenantId()
+			})?.companyName ?? ""
+		)
+	}
+	const initTenant = async () => {
+		return new Promise((resolve, reject) => {
+			apis.loginApi.getTenantList().then((res: any) => {
+				tenantEnabled.value = res.data.tenantEnabled === undefined ? true : res.data.tenantEnabled
+				if (tenantEnabled.value) {
+					tenantList.value = res.data.voList
+					resolve(res.data.voList)
+				} else {
+					reject(false)
+				}
+			})
+		})
+	}
+	function getTenantList() {
+		return tenantList.value
+	}
+	function enable() {
+		return tenantEnabled.value
+	}
+	function setTenantId(tenantId: string) {
+		localCache.set("tenantId", tenantId)
+	}
+	function setTenantNewPage(tenantId: string) {
+		return new Promise((resolve, reject) => {
+			dynamicTenant.value = tenantId
+			isNewPage.value = true
+			appStore.tagViewStore.delAllViews().then(() => {
+				resolve(tenantId)
+			})
+		})
+	}
+
+	function setDynamicTenant(tenantId: string) {
+		return new Promise((resolve, reject) => {
+			dynamicTenant.value = tenantId
+			appStore.tagViewStore.delAllViews().then(() => {
+				resolve(tenantId)
+			})
+		})
+	}
+	function getTenantId() {
+		return dynamicTenant.value || localCache.get("tenantId")
+	}
+	function getTenantName() {
+		return getCompanyName() || ""
+	}
+
+	function canChangeTenant() {
+		return (
+			!isNewPage.value &&
+			(appStore.authStore.user.roles.includes("super_admin") ||
+				appStore.authStore.user.permissions.includes("system:tenant"))
+		)
+	}
+
+	function isDynamic() {
+		return getTenantId() != appStore.authStore.user.tenantId
+	}
+
+	function clearDynamicTenant() {
+		return new Promise((resolve, reject) => {
+			apis.system.tenantApi
+				.dynamicClear()
+				.then((res: any) => {
+					setDynamicTenant("")
+					appStore.tagViewStore.delAllViews().then(() => {
+						resolve(res)
+					})
+				})
+				.catch((err) => {
+					reject(err)
+				})
+		})
+	}
+
+	return {
+		initTenant,
+		getTenantList,
+		enable,
+		canChangeTenant,
+		setDynamicTenant,
+		setTenantNewPage,
+		clearDynamicTenant,
+		setTenantId,
+		getTenantId,
+		getTenantName,
+		isDynamic
+	}
+})

+ 3 - 0
UI/VAP_V3.VUE/src/stores/index.ts

@@ -3,6 +3,7 @@ import { createPinia } from "pinia"
 
 import { useBodyConfigStore } from "./_bodyConfig"
 import { useAuthStore } from "./_auth"
+import { useTenantStore } from "./_tenant"
 import { useMenuStore } from "./_menu"
 import { useDictStore } from "./_dict"
 import { useTagViewStore } from "./_tagView"
@@ -12,6 +13,7 @@ const store = createPinia()
 export interface IAppStore {
 	bodyConfigStore: ReturnType<typeof useBodyConfigStore>
 	authStore: ReturnType<typeof useAuthStore>
+	tenantStore: ReturnType<typeof useTenantStore>
 	menuStore: ReturnType<typeof useMenuStore>
 	dictStore: ReturnType<typeof useDictStore>
 	tagViewStore: ReturnType<typeof useTagViewStore>
@@ -24,6 +26,7 @@ export const appStore: IAppStore = {} as IAppStore
 export const registerStore = () => {
 	appStore.bodyConfigStore = useBodyConfigStore()
 	appStore.authStore = useAuthStore()
+	appStore.tenantStore = useTenantStore()
 	appStore.menuStore = useMenuStore()
 	appStore.dictStore = useDictStore()
 	appStore.tagViewStore = useTagViewStore()

+ 11 - 7
UI/VAP_V3.VUE/src/views/account/login.vue

@@ -80,7 +80,7 @@ const doSocialLogin = (type: string) => {
 		message.msgError("请选择租户")
 		return
 	}
-	appStore.authStore.setTenantId(loginForm.value.tenantId)
+	appStore.tenantStore.setTenantId(loginForm.value.tenantId)
 	appStore.authStore.socialLogin(type).then((res: any) => {
 		if (res.code === HttpStatus.SUCCESS) {
 			// 获取授权地址跳转
@@ -121,15 +121,19 @@ function getCookie() {
 }
 
 const initTenant = async () => {
-	apis.loginApi.getTenantList().then((res: any) => {
-		tenantEnabled.value = res.data.tenantEnabled === undefined ? true : res.data.tenantEnabled
-		if (tenantEnabled.value) {
-			tenantOptions.value = res.data.voList
+	appStore.tenantStore
+		.initTenant()
+		.then((res: any) => {
+			tenantEnabled.value = true
+			tenantOptions.value = res
 			if (tenantOptions.value != null && tenantOptions.value.length !== 0) {
 				loginForm.value.tenantId = tenantOptions.value[0].tenantId
 			}
-		}
-	})
+		})
+		.catch(() => {
+			tenantOptions.value = []
+			tenantEnabled.value = false
+		})
 }
 function init() {
 	getCode()

+ 2 - 2
UI/VAP_V3.VUE/src/views/account/social/callback.vue

@@ -9,7 +9,7 @@ const loading = ref(true)
 const code = route.query.code as string
 const state = route.query.state as string
 const source = route.query.source as string
-const tenantId = appStore.authStore.getTenantId()
+const tenantId = appStore.tenantStore.getTenantId()
 
 const callbackByCode = async (data: LoginData) => {
 	appStore.authStore
@@ -39,7 +39,7 @@ function init() {
 	const data: LoginData = {
 		socialCode: code,
 		socialState: state,
-		tenantId: tenantId,
+		tenantId: tenantId || "",
 		source: source,
 		clientId: import.meta.env.VITE_APP_CLIENT_ID,
 		grantType: "social"

+ 1 - 2
UI/VAP_V3.VUE/src/views/redirect/index.vue

@@ -7,6 +7,5 @@ const route = useRoute()
 const router = useRouter()
 const { params, query } = route
 const { path } = params
-// console.log("PATH", path)
-router.replace({ path: "/" + path, query })
+router.replace({ path: "" + path, query })
 </script>

+ 15 - 0
UI/VAP_V3.VUE/src/views/redirect/tenant.vue

@@ -0,0 +1,15 @@
+<template>
+	<div></div>
+</template>
+
+<script setup lang="ts">
+import appStore from "@s"
+
+const route = useRoute()
+const router = useRouter()
+const { params, query } = route
+const { path, tenant } = params
+const tenantId = tenant == "0" ? "" : tenant + ""
+appStore.tenantStore.setTenantNewPage(tenantId)
+router.replace({ path: "" + path, query })
+</script>