feat: scope articles by brand

This commit is contained in:
2026-05-20 15:37:25 +08:00
parent 5fb9d0b0dd
commit dd082e2ed1
72 changed files with 3213 additions and 432 deletions
+49 -2
View File
@@ -2,8 +2,31 @@ import { createRouter, createWebHistory } from 'vue-router'
import { isChunkLoadError, reloadForStaleChunk } from '@/lib/chunk-reload'
import { useAuthStore } from '@/stores/auth'
import { useCompanyStore } from '@/stores/company'
import { pinia } from '@/stores/pinia'
let brandRefreshPromise: Promise<unknown> | null = null
async function ensureBrandsInitialized(): Promise<boolean> {
const companyStore = useCompanyStore(pinia)
if (companyStore.initialized) {
return true
}
if (!brandRefreshPromise) {
brandRefreshPromise = companyStore.refreshBrands().finally(() => {
brandRefreshPromise = null
})
}
try {
await brandRefreshPromise
return true
} catch {
return false
}
}
const router = createRouter({
history: createWebHistory(),
routes: [
@@ -24,6 +47,17 @@ const router = createRouter({
requiresAuth: true,
},
},
{
path: '/onboarding/brand',
name: 'brand-onboarding',
component: () => import('@/views/BrandOnboardingView.vue'),
meta: {
requiresAuth: true,
onboarding: true,
titleKey: 'route.brandOnboarding.title',
descriptionKey: 'route.brandOnboarding.description',
},
},
{
path: '/',
component: () => import('@/layouts/AppShell.vue'),
@@ -279,6 +313,7 @@ const router = createRouter({
router.beforeEach(async (to) => {
const authStore = useAuthStore(pinia)
const companyStore = useCompanyStore(pinia)
if (!authStore.initialized) {
await authStore.bootstrap()
@@ -292,11 +327,23 @@ router.beforeEach(async (to) => {
}
}
if (to.meta.requiresKol && !authStore.isActiveKol) {
if (to.name === 'login' && authStore.isAuthenticated) {
return { name: 'workspace' }
}
if (to.name === 'login' && authStore.isAuthenticated) {
if (requiresAuth && authStore.isAuthenticated && !authStore.isMembershipBlocked) {
const brandsInitialized = await ensureBrandsInitialized()
if (brandsInitialized && !companyStore.hasBrands && !to.meta.onboarding) {
return { name: 'brand-onboarding' }
}
if (brandsInitialized && companyStore.hasBrands && to.meta.onboarding) {
return { name: 'workspace' }
}
}
if (to.meta.requiresKol && !authStore.isActiveKol) {
return { name: 'workspace' }
}
+1
View File
@@ -8,6 +8,7 @@ declare module 'vue-router' {
descriptionKey?: string
requiresAuth?: boolean
requiresKol?: boolean
onboarding?: boolean
navKey?: string | null
}
}