fix: fix enhance app mode check (#30758)

This commit is contained in:
wangxiaolei 2026-01-09 14:07:40 +08:00 committed by GitHub
parent 7843afc91c
commit 77f097ce76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 2 deletions

View File

@ -10,6 +10,7 @@ const mockReplace = vi.fn()
const mockRouter = { replace: mockReplace }
vi.mock('next/navigation', () => ({
useRouter: () => mockRouter,
useSearchParams: () => new URLSearchParams(''),
}))
// Mock app context

View File

@ -12,6 +12,7 @@ import { useDebounceFn } from 'ahooks'
import dynamic from 'next/dynamic'
import {
useRouter,
useSearchParams,
} from 'next/navigation'
import { parseAsString, useQueryState } from 'nuqs'
import { useCallback, useEffect, useRef, useState } from 'react'
@ -36,6 +37,16 @@ import useAppsQueryState from './hooks/use-apps-query-state'
import { useDSLDragDrop } from './hooks/use-dsl-drag-drop'
import NewAppCard from './new-app-card'
// Define valid tabs at module scope to avoid re-creation on each render and stale closures
const validTabs = new Set<string | AppModeEnum>([
'all',
AppModeEnum.WORKFLOW,
AppModeEnum.ADVANCED_CHAT,
AppModeEnum.CHAT,
AppModeEnum.AGENT_CHAT,
AppModeEnum.COMPLETION,
])
const TagManagementModal = dynamic(() => import('@/app/components/base/tag-management'), {
ssr: false,
})
@ -47,12 +58,41 @@ const List = () => {
const { t } = useTranslation()
const { systemFeatures } = useGlobalPublicStore()
const router = useRouter()
const searchParams = useSearchParams()
const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator, isLoadingCurrentWorkspace } = useAppContext()
const showTagManagementModal = useTagStore(s => s.showTagManagementModal)
const [activeTab, setActiveTab] = useQueryState(
'category',
parseAsString.withDefault('all').withOptions({ history: 'push' }),
)
// valid tabs for apps list; anything else should fallback to 'all'
// 1) Normalize legacy/incorrect query params like ?mode=discover -> ?category=all
useEffect(() => {
// avoid running on server
if (typeof window === 'undefined')
return
const mode = searchParams.get('mode')
if (!mode)
return
const url = new URL(window.location.href)
url.searchParams.delete('mode')
if (validTabs.has(mode)) {
// migrate to category key
url.searchParams.set('category', mode)
}
else {
url.searchParams.set('category', 'all')
}
router.replace(url.pathname + url.search)
}, [router, searchParams])
// 2) If category has an invalid value (e.g., 'discover'), reset to 'all'
useEffect(() => {
if (!validTabs.has(activeTab))
setActiveTab('all')
}, [activeTab, setActiveTab])
const { query: { tagIDs = [], keywords = '', isCreatedByMe: queryIsCreatedByMe = false }, setQuery } = useAppsQueryState()
const [isCreatedByMe, setIsCreatedByMe] = useState(queryIsCreatedByMe)
const [tagFilterValue, setTagFilterValue] = useState<string[]>(tagIDs)

View File

@ -10,13 +10,14 @@ import type {
AppVoicesListResponse,
WorkflowDailyConversationsResponse,
} from '@/models/app'
import type { App, AppModeEnum } from '@/types/app'
import type { App } from '@/types/app'
import {
keepPreviousData,
useInfiniteQuery,
useQuery,
useQueryClient,
} from '@tanstack/react-query'
import { AppModeEnum } from '@/types/app'
import { get, post } from './base'
import { useInvalid } from './use-base'
@ -36,6 +37,16 @@ type DateRangeParams = {
end?: string
}
// Allowed app modes for filtering; defined at module scope to avoid re-creating on every call
const allowedModes = new Set<AppModeEnum | 'all'>([
'all',
AppModeEnum.WORKFLOW,
AppModeEnum.ADVANCED_CHAT,
AppModeEnum.CHAT,
AppModeEnum.AGENT_CHAT,
AppModeEnum.COMPLETION,
])
const normalizeAppListParams = (params: AppListParams) => {
const {
page = 1,
@ -46,11 +57,13 @@ const normalizeAppListParams = (params: AppListParams) => {
is_created_by_me,
} = params
const safeMode = allowedModes.has((mode as any)) ? mode : undefined
return {
page,
limit,
name,
...(mode && mode !== 'all' ? { mode } : {}),
...(safeMode && safeMode !== 'all' ? { mode: safeMode } : {}),
...(tag_ids?.length ? { tag_ids } : {}),
...(is_created_by_me ? { is_created_by_me } : {}),
}