fix: fetchAppWithTags may return empty when apps is over 100 (#23350)

This commit is contained in:
NeatGuyCoding 2025-08-04 20:20:43 +08:00 committed by GitHub
parent 60c7663a80
commit a724f35672
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 13 additions and 31 deletions

View File

@ -59,6 +59,8 @@ model_config_fields = {
"updated_at": TimestampField, "updated_at": TimestampField,
} }
tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String}
app_detail_fields = { app_detail_fields = {
"id": fields.String, "id": fields.String,
"name": fields.String, "name": fields.String,
@ -77,6 +79,7 @@ app_detail_fields = {
"updated_by": fields.String, "updated_by": fields.String,
"updated_at": TimestampField, "updated_at": TimestampField,
"access_mode": fields.String, "access_mode": fields.String,
"tags": fields.List(fields.Nested(tag_fields)),
} }
prompt_config_fields = { prompt_config_fields = {
@ -92,8 +95,6 @@ model_config_partial_fields = {
"updated_at": TimestampField, "updated_at": TimestampField,
} }
tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String}
app_partial_fields = { app_partial_fields = {
"id": fields.String, "id": fields.String,
"name": fields.String, "name": fields.String,
@ -185,7 +186,6 @@ app_detail_fields_with_site = {
"enable_api": fields.Boolean, "enable_api": fields.Boolean,
"model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True), "model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
"workflow": fields.Nested(workflow_partial_fields, allow_null=True), "workflow": fields.Nested(workflow_partial_fields, allow_null=True),
"site": fields.Nested(site_fields),
"api_base_url": fields.String, "api_base_url": fields.String,
"use_icon_as_answer_icon": fields.Boolean, "use_icon_as_answer_icon": fields.Boolean,
"max_active_requests": fields.Integer, "max_active_requests": fields.Integer,
@ -195,6 +195,8 @@ app_detail_fields_with_site = {
"updated_at": TimestampField, "updated_at": TimestampField,
"deleted_tools": fields.List(fields.Nested(deleted_tool_fields)), "deleted_tools": fields.List(fields.Nested(deleted_tool_fields)),
"access_mode": fields.String, "access_mode": fields.String,
"tags": fields.List(fields.Nested(tag_fields)),
"site": fields.Nested(site_fields),
} }

View File

@ -20,7 +20,7 @@ import cn from '@/utils/classnames'
import { useStore } from '@/app/components/app/store' import { useStore } from '@/app/components/app/store'
import AppSideBar from '@/app/components/app-sidebar' import AppSideBar from '@/app/components/app-sidebar'
import type { NavIcon } from '@/app/components/app-sidebar/navLink' import type { NavIcon } from '@/app/components/app-sidebar/navLink'
import { fetchAppDetail, fetchAppWithTags } from '@/service/apps' import { fetchAppDetailDirect } from '@/service/apps'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
@ -118,17 +118,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
useEffect(() => { useEffect(() => {
setAppDetail() setAppDetail()
setIsLoadingAppDetail(true) setIsLoadingAppDetail(true)
fetchAppDetail({ url: '/apps', id: appId }).then(async (res) => { fetchAppDetailDirect({ url: '/apps', id: appId }).then((res: App) => {
if (!res.tags || res.tags.length === 0) {
try {
const appWithTags = await fetchAppWithTags(appId)
if (appWithTags?.tags)
res.tags = appWithTags.tags
}
catch (error) {
// Fallback failed, continue with empty tags
}
}
setAppDetailRes(res) setAppDetailRes(res)
}).catch((e: any) => { }).catch((e: any) => {
if (e.status === 404) if (e.status === 404)

View File

@ -9,7 +9,12 @@ export const fetchAppList: Fetcher<AppListResponse, { url: string; params?: Reco
return get<AppListResponse>(url, { params }) return get<AppListResponse>(url, { params })
} }
export const fetchAppDetail = ({ url, id }: { url: string; id: string }) => { export const fetchAppDetail: Fetcher<AppDetailResponse, { url: string; id: string }> = ({ url, id }) => {
return get<AppDetailResponse>(`${url}/${id}`)
}
// Direct API call function for non-SWR usage
export const fetchAppDetailDirect = async ({ url, id }: { url: string; id: string }): Promise<AppDetailResponse> => {
return get<AppDetailResponse>(`${url}/${id}`) return get<AppDetailResponse>(`${url}/${id}`)
} }
@ -60,21 +65,6 @@ export const deleteApp: Fetcher<CommonResponse, string> = (appID) => {
return del<CommonResponse>(`apps/${appID}`) return del<CommonResponse>(`apps/${appID}`)
} }
export const fetchAppWithTags = async (appID: string) => {
try {
const appListResponse = await fetchAppList({
url: '/apps',
params: { page: 1, limit: 100 },
})
const appWithTags = appListResponse.data.find(app => app.id === appID)
return appWithTags || null
}
catch (error) {
console.warn('Failed to fetch app with tags:', error)
return null
}
}
export const updateAppSiteStatus: Fetcher<AppDetailResponse, { url: string; body: Record<string, any> }> = ({ url, body }) => { export const updateAppSiteStatus: Fetcher<AppDetailResponse, { url: string; body: Record<string, any> }> = ({ url, body }) => {
return post<AppDetailResponse>(url, { body }) return post<AppDetailResponse>(url, { body })
} }