feat: show publish action for tenant admins
This commit is contained in:
@@ -11,7 +11,7 @@ const { toggleMenu, toggleDarkMode, isDarkTheme } = useLayout();
|
|||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { state: sessionState, isLoggedIn, username, isTenantApproved } = useSession();
|
const { state: sessionState, isLoggedIn, username, isTenantApproved, isTenantAdmin, firstAdminTenantCode } = useSession();
|
||||||
|
|
||||||
const userMenuRef = ref();
|
const userMenuRef = ref();
|
||||||
|
|
||||||
@@ -38,6 +38,12 @@ const tenantApplyAction = computed(() => {
|
|||||||
return { label: '申请创作者', to: '/tenant/apply', icon: 'pi pi-star' };
|
return { label: '申请创作者', to: '/tenant/apply', icon: 'pi pi-star' };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const publishTo = computed(() => {
|
||||||
|
const code = firstAdminTenantCode.value;
|
||||||
|
if (code) return { path: '/management/contents/new', query: { tenantCode: code } };
|
||||||
|
return '/management/contents/new';
|
||||||
|
});
|
||||||
|
|
||||||
const userMenuItems = computed(() => [
|
const userMenuItems = computed(() => [
|
||||||
{ label: '个人中心', icon: 'pi pi-user', command: () => router.push('/me') },
|
{ label: '个人中心', icon: 'pi pi-user', command: () => router.push('/me') },
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
@@ -112,6 +118,10 @@ onMounted(() => {
|
|||||||
<div class="layout-topbar-menu hidden lg:block">
|
<div class="layout-topbar-menu hidden lg:block">
|
||||||
<div class="layout-topbar-menu-content">
|
<div class="layout-topbar-menu-content">
|
||||||
<template v-if="isLoggedIn">
|
<template v-if="isLoggedIn">
|
||||||
|
<router-link v-if="isTenantAdmin" :to="publishTo" class="layout-topbar-action layout-topbar-action-text">
|
||||||
|
<i class="pi pi-plus"></i>
|
||||||
|
<span>发布</span>
|
||||||
|
</router-link>
|
||||||
<router-link v-if="tenantApplyAction" :to="tenantApplyAction.to" class="layout-topbar-action layout-topbar-action-text">
|
<router-link v-if="tenantApplyAction" :to="tenantApplyAction.to" class="layout-topbar-action layout-topbar-action-text">
|
||||||
<i :class="tenantApplyAction.icon"></i>
|
<i :class="tenantApplyAction.icon"></i>
|
||||||
<span>{{ tenantApplyAction.label }}</span>
|
<span>{{ tenantApplyAction.label }}</span>
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ const state = reactive({
|
|||||||
me: null,
|
me: null,
|
||||||
loadingMe: false,
|
loadingMe: false,
|
||||||
tenantApplication: null,
|
tenantApplication: null,
|
||||||
loadingTenantApplication: false
|
loadingTenantApplication: false,
|
||||||
|
myTenants: null,
|
||||||
|
loadingMyTenants: false
|
||||||
});
|
});
|
||||||
|
|
||||||
let initPromise = null;
|
let initPromise = null;
|
||||||
@@ -19,12 +21,23 @@ export function useSession() {
|
|||||||
return String(raw || '').trim();
|
return String(raw || '').trim();
|
||||||
});
|
});
|
||||||
const isTenantApproved = computed(() => state.tenantApplication?.hasApplication && state.tenantApplication?.status === 'verified');
|
const isTenantApproved = computed(() => state.tenantApplication?.hasApplication && state.tenantApplication?.status === 'verified');
|
||||||
|
const isTenantAdmin = computed(() => {
|
||||||
|
const items = Array.isArray(state.myTenants) ? state.myTenants : [];
|
||||||
|
return items.some((item) => item?.is_owner || (Array.isArray(item?.member_roles) && item.member_roles.includes('tenant_admin')));
|
||||||
|
});
|
||||||
|
const firstAdminTenantCode = computed(() => {
|
||||||
|
const items = Array.isArray(state.myTenants) ? state.myTenants : [];
|
||||||
|
const hit = items.find((item) => item?.is_owner || (Array.isArray(item?.member_roles) && item.member_roles.includes('tenant_admin')));
|
||||||
|
return String(hit?.tenant_code || '').trim();
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
isLoggedIn,
|
isLoggedIn,
|
||||||
username,
|
username,
|
||||||
isTenantApproved
|
isTenantApproved,
|
||||||
|
isTenantAdmin,
|
||||||
|
firstAdminTenantCode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +73,22 @@ export async function fetchTenantApplication() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchMyTenants() {
|
||||||
|
if (!state.token) {
|
||||||
|
state.myTenants = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.loadingMyTenants = true;
|
||||||
|
try {
|
||||||
|
const data = await requestJson('/v1/me/tenants', { auth: true });
|
||||||
|
state.myTenants = Array.isArray(data) ? data : [];
|
||||||
|
return state.myTenants;
|
||||||
|
} finally {
|
||||||
|
state.loadingMyTenants = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function setToken(token) {
|
export function setToken(token) {
|
||||||
const normalized = String(token || '').trim();
|
const normalized = String(token || '').trim();
|
||||||
state.token = normalized;
|
state.token = normalized;
|
||||||
@@ -70,6 +99,7 @@ export async function setTokenAndLoadMe(token) {
|
|||||||
setToken(token);
|
setToken(token);
|
||||||
await fetchMe();
|
await fetchMe();
|
||||||
await fetchTenantApplication();
|
await fetchTenantApplication();
|
||||||
|
await fetchMyTenants();
|
||||||
return state.me;
|
return state.me;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +107,7 @@ export function logout() {
|
|||||||
setToken('');
|
setToken('');
|
||||||
state.me = null;
|
state.me = null;
|
||||||
state.tenantApplication = null;
|
state.tenantApplication = null;
|
||||||
|
state.myTenants = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initSession() {
|
export async function initSession() {
|
||||||
@@ -88,6 +119,7 @@ export async function initSession() {
|
|||||||
try {
|
try {
|
||||||
await fetchMe();
|
await fetchMe();
|
||||||
await fetchTenantApplication();
|
await fetchTenantApplication();
|
||||||
|
await fetchMyTenants();
|
||||||
} catch {
|
} catch {
|
||||||
// token 可能过期或无效:清理并让 UI 回到未登录态
|
// token 可能过期或无效:清理并让 UI 回到未登录态
|
||||||
logout();
|
logout();
|
||||||
|
|||||||
@@ -125,6 +125,14 @@ onMounted(async () => {
|
|||||||
if (!isLoggedIn.value) {
|
if (!isLoggedIn.value) {
|
||||||
const redirect = typeof route.fullPath === 'string' ? route.fullPath : '/management/contents/new';
|
const redirect = typeof route.fullPath === 'string' ? route.fullPath : '/management/contents/new';
|
||||||
await router.push(`/auth/login?redirect=${encodeURIComponent(redirect)}`);
|
await router.push(`/auth/login?redirect=${encodeURIComponent(redirect)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String(tenantCode.value || '').trim()) {
|
||||||
|
const q = route.query?.tenantCode;
|
||||||
|
if (typeof q === 'string' && q.trim()) {
|
||||||
|
tenantCode.value = q.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user