修复get_workspace_sidebar_items重复执行多次的问题

This commit is contained in:
jingrow 2026-03-15 23:10:44 +08:00
parent 0161eee59f
commit 484c116c4a
3 changed files with 56 additions and 36 deletions

View File

@ -122,9 +122,7 @@ const parentWorkspaceOptions = computed(() => {
})
onMounted(async () => {
if (!menuStore.loadedFromBackend) {
await menuStore.loadFromBackend()
}
await menuStore.loadFromBackend()
syncEditableWorkspaces()
})

View File

@ -54,10 +54,17 @@ function getDefaultMenus(): AppMenuItem[] {
export const useMenuStore = defineStore('menu', () => {
// 标记是否已从后端加载过
const loadedFromBackend = ref(false)
// Loading promise to prevent duplicate calls
let loadingPromise: Promise<any> | null = null
// Workspace dictionary for quick lookup (like jingrow.workspaces in old frontend)
// Key: slug(workspace.name), Value: workspace data
const workspaces = ref<Record<string, WorkspacePage>>({})
// Access flags from backend
const hasWorkspaceAccess = ref(false)
const hasCreateWorkspaceAccess = ref(false)
// 正确初始化为数组,而不是函数
const initItems = () => {
@ -155,29 +162,44 @@ export const useMenuStore = defineStore('menu', () => {
*
*/
async function loadFromBackend() {
try {
const response = await getWorkspaceSidebarItems()
const workspaceMenuItems = transformWorkspacePages(response.pages)
// Build workspace dictionary (key: slug(workspace.name))
const dict: Record<string, WorkspacePage> = {}
for (const page of response.pages) {
const slugKey = pageTypeToSlug(page.name)
dict[slugKey] = page
// Return existing promise if already loading (prevent duplicate calls)
if (loadingPromise) return loadingPromise
// Already loaded
if (loadedFromBackend.value) return { success: true, count: items.value.length }
loadingPromise = (async () => {
try {
const response = await getWorkspaceSidebarItems()
const workspaceMenuItems = transformWorkspacePages(response.pages)
// Build workspace dictionary (key: slug(workspace.name))
const dict: Record<string, WorkspacePage> = {}
for (const page of response.pages) {
const slugKey = pageTypeToSlug(page.name)
dict[slugKey] = page
}
workspaces.value = dict
// Store access flags
hasWorkspaceAccess.value = response.has_access || false
hasCreateWorkspaceAccess.value = response.has_create_access || false
// 直接使用后端返回的菜单数据
items.value = workspaceMenuItems
persist()
loadedFromBackend.value = true
return { success: true, count: workspaceMenuItems.length }
} catch (error: any) {
console.error('Failed to load menu from backend:', error)
return { success: false, error: error.message }
} finally {
loadingPromise = null
}
workspaces.value = dict
// 直接使用后端返回的菜单数据
items.value = workspaceMenuItems
persist()
loadedFromBackend.value = true
return { success: true, count: workspaceMenuItems.length }
} catch (error: any) {
console.error('Failed to load menu from backend:', error)
return { success: false, error: error.message }
}
})()
return loadingPromise
}
/**
@ -185,6 +207,7 @@ export const useMenuStore = defineStore('menu', () => {
*/
async function reloadFromBackend() {
loadedFromBackend.value = false
loadingPromise = null
return loadFromBackend()
}
@ -212,6 +235,8 @@ export const useMenuStore = defineStore('menu', () => {
visibleItems,
loadedFromBackend,
workspaces,
hasWorkspaceAccess,
hasCreateWorkspaceAccess,
addMenu,
updateMenu,
removeMenu,

View File

@ -259,7 +259,7 @@ import { usePermissionStore } from '@/shared/stores/permissions'
import { useAuthStore } from '@/shared/stores/auth'
import { useMenuStore } from '@/shared/stores/menu'
import { useWorkspaceEditStore } from '@/shared/stores/workspaceEdit'
import { getWorkspaceSidebarItems, getDesktopPage } from '@/shared/api/workspace'
import { getDesktopPage } from '@/shared/api/workspace'
import draggable from 'vuedraggable'
import IconPicker from '@/core/components/IconPicker.vue'
import OnboardingBlock from '@/core/features/workspace_builder/blocks/OnboardingBlock.vue'
@ -376,8 +376,8 @@ function handleAddBlock(key: string) {
async function loadWorkspaceSidebarMeta(force = false) {
if (workspaceSidebarMeta.value.loaded && !force) return
try {
const resp = await getWorkspaceSidebarItems()
const pages = Array.isArray(resp.pages) ? resp.pages : []
await menuStore.loadFromBackend()
const pages = Object.values(menuStore.workspaces)
const uniq = (arr: string[]) => Array.from(new Set(arr.filter(Boolean)))
const publicParents = uniq(
@ -393,8 +393,8 @@ async function loadWorkspaceSidebarMeta(force = false) {
workspaceSidebarMeta.value = {
loaded: true,
has_access: Boolean(resp.has_access),
has_create_access: Boolean(resp.has_create_access),
has_access: menuStore.hasWorkspaceAccess,
has_create_access: menuStore.hasCreateWorkspaceAccess,
publicParents,
privateParents
}
@ -405,11 +405,8 @@ async function loadWorkspaceSidebarMeta(force = false) {
}
async function load() {
// Ensure menu is loaded first
if (!menuStore.loadedFromBackend) {
await menuStore.loadFromBackend()
}
await menuStore.loadFromBackend()
// If workspace not found in dictionary, it doesn't exist
if (!workspaceName.value) {
message.error(t('Workspace not found'))