Files
vue3-element-admin/src/store/modules/tenant.ts
2025-12-26 12:35:37 +08:00

210 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { store } from "@/store";
import TenantAPI from "@/api/system/tenant";
import type { TenantInfo } from "@/types/api";
import { STORAGE_KEYS } from "@/constants";
/**
* 租户 Store
*/
export const useTenantStore = defineStore("tenant", () => {
// 当前租户ID
const currentTenantId = ref<number | null>(null);
// 当前租户信息
const currentTenant = ref<TenantInfo | null>(null);
// 用户可访问的租户列表
const tenantList = ref<TenantInfo[]>([]);
/**
* 恢复租户信息
* 从 localStorage 恢复上次使用的租户
*/
function restoreTenant() {
const savedTenantId = localStorage.getItem(STORAGE_KEYS.TENANT_ID);
const savedTenantInfo = localStorage.getItem(STORAGE_KEYS.TENANT_INFO);
if (savedTenantId) {
currentTenantId.value = Number(savedTenantId);
}
if (savedTenantInfo) {
try {
currentTenant.value = JSON.parse(savedTenantInfo);
} catch (e) {
console.error("解析租户信息失败", e);
}
}
}
/**
* 获取用户租户列表
*/
function fetchTenantList() {
return new Promise<TenantInfo[]>((resolve, reject) => {
TenantAPI.getTenantList()
.then((data) => {
tenantList.value = data || [];
resolve(data || []);
})
.catch((error) => {
reject(error);
});
});
}
/**
* 加载租户
*
* 执行流程:
* 1. 获取用户可访问的租户列表
* 2. 尝试获取后端当前租户
* 3. 如果只有一个租户,自动选中
* 4. 否则等待用户手动选择
*
* @remarks
* 此方法由路由守卫调用,仅在启用多租户时执行
*/
async function loadTenant() {
restoreTenant();
// 1. 获取租户列表
await fetchTenantList();
// 2. 校验本地恢复的租户是否仍然可用(避免 tenantId 不在列表导致无默认选中)
if (
currentTenantId.value &&
tenantList.value.length > 0 &&
!tenantList.value.some((t) => t.id === currentTenantId.value)
) {
console.debug("[Tenant] 本地租户已不可用,清除并重新选择:", currentTenantId.value);
currentTenantId.value = null;
currentTenant.value = null;
localStorage.removeItem(STORAGE_KEYS.TENANT_ID);
localStorage.removeItem(STORAGE_KEYS.TENANT_INFO);
}
// 3. 如果已有租户列表,则保证一定有一个默认租户被选中
if (tenantList.value.length > 0) {
// 3.1 优先后端当前租户
if (!currentTenantId.value) {
try {
const currentTenantInfo = await TenantAPI.getCurrentTenant();
if (currentTenantInfo) {
setCurrentTenant(currentTenantInfo);
return;
}
} catch (error) {
console.debug("[Tenant] 获取当前租户失败,尝试本地/默认选择:", error);
}
}
// 3.2 本地已有 tenantId但 currentTenant 为空时,从列表补全 tenantInfo保持展示名称一致
if (currentTenantId.value && !currentTenant.value) {
const matched = tenantList.value.find((t) => t.id === currentTenantId.value);
if (matched) {
setCurrentTenant(matched);
return;
}
}
// 3.3 兜底:默认选中第一个(即使有多个租户,也保证 TenantSwitcher 有默认选中)
if (!currentTenantId.value) {
setCurrentTenant(tenantList.value[0]);
console.debug("[Tenant] 默认选中第一个租户:", tenantList.value[0].name);
}
}
}
/**
* 设置当前租户
*
* @param tenant 租户信息
*/
function setCurrentTenant(tenant: TenantInfo) {
currentTenantId.value = tenant.id;
currentTenant.value = tenant;
// 保存到 localStorage
localStorage.setItem(STORAGE_KEYS.TENANT_ID, String(tenant.id));
localStorage.setItem(STORAGE_KEYS.TENANT_INFO, JSON.stringify(tenant));
}
/**
* 切换租户
*
* @param tenantId 目标租户ID
*/
async function switchTenant(tenantId: number): Promise<void> {
try {
// 调用后端切换接口
const tenantInfo = await TenantAPI.switchTenant(tenantId);
// 后端返回切换后的租户信息
if (tenantInfo) {
setCurrentTenant(tenantInfo);
} else {
// 如果后端未返回,从租户列表中找到对应的租户信息
const tenant = tenantList.value.find((t) => t.id === tenantId);
if (tenant) {
setCurrentTenant(tenant);
} else {
// 如果列表中没有,重新获取租户信息
try {
const info = await TenantAPI.getCurrentTenant();
if (info) {
setCurrentTenant(info);
} else {
throw new Error("无法获取租户信息");
}
} catch (error) {
console.error("获取租户信息失败:", error);
throw new Error("切换租户后无法获取租户信息");
}
}
}
} catch (error) {
console.error("切换租户失败:", error);
throw error;
}
}
/**
* 清除租户信息
*/
function clearTenant() {
currentTenantId.value = null;
currentTenant.value = null;
tenantList.value = [];
localStorage.removeItem(STORAGE_KEYS.TENANT_ID);
localStorage.removeItem(STORAGE_KEYS.TENANT_INFO);
}
/**
* 设置租户列表
*/
function setTenantList(list: TenantInfo[]) {
tenantList.value = list || [];
}
// 恢复本地租户信息
restoreTenant();
return {
currentTenantId,
currentTenant,
tenantList,
loadTenant,
fetchTenantList,
setTenantList,
setCurrentTenant,
switchTenant,
clearTenant,
};
});
/**
* 在组件外部使用 TenantStore 的钩子函数
*/
export function useTenantStoreHook() {
return useTenantStore(store);
}