修复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 () => { onMounted(async () => {
if (!menuStore.loadedFromBackend) { await menuStore.loadFromBackend()
await menuStore.loadFromBackend()
}
syncEditableWorkspaces() syncEditableWorkspaces()
}) })

View File

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

View File

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