fix(web): fix document detail page status inconsistency with list page (#33740)

Co-authored-by: fisher <1186907891@qq.com>
Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com>
Co-authored-by: Crazywoola <100913391+crazywoola@users.noreply.github.com>
This commit is contained in:
fisherOne1
2026-03-31 10:07:37 +08:00
committed by GitHub
parent 323c51e095
commit a19243068b
2 changed files with 69 additions and 42 deletions

View File

@@ -1,8 +1,8 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import type { DataSourceInfo, FileItem, FullDocumentDetail, LegacyDataSourceInfo } from '@/models/datasets' import type { DataSourceInfo, DocumentDisplayStatus, FileItem, FullDocumentDetail, LegacyDataSourceInfo } from '@/models/datasets'
import * as React from 'react' import * as React from 'react'
import { useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import FloatRightContainer from '@/app/components/base/float-right-container' import FloatRightContainer from '@/app/components/base/float-right-container'
@@ -11,7 +11,7 @@ import Toast from '@/app/components/base/toast'
import Metadata from '@/app/components/datasets/metadata/metadata-document' import Metadata from '@/app/components/datasets/metadata/metadata-document'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { ChunkingMode } from '@/models/datasets' import { ChunkingMode, DisplayStatusList } from '@/models/datasets'
import { useRouter, useSearchParams } from '@/next/navigation' import { useRouter, useSearchParams } from '@/next/navigation'
import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document' import { useDocumentDetail, useDocumentMetadata, useInvalidDocumentList } from '@/service/knowledge/use-document'
import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment' import { useCheckSegmentBatchImportProgress, useChildSegmentListKey, useSegmentBatchImport, useSegmentListKey } from '@/service/knowledge/use-segment'
@@ -32,6 +32,14 @@ type DocumentDetailProps = {
documentId: string documentId: string
} }
const NON_TERMINAL_DISPLAY_STATUSES = new Set<typeof DisplayStatusList[number]>(
DisplayStatusList.filter(s => s === 'queuing' || s === 'indexing' || s === 'paused'),
)
const isLegacyDataSourceInfo = (info?: DataSourceInfo): info is LegacyDataSourceInfo => {
return !!info && 'upload_file' in info
}
const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => { const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()
@@ -89,6 +97,12 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
datasetId, datasetId,
documentId, documentId,
params: { metadata: 'without' }, params: { metadata: 'without' },
refetchInterval: (query) => {
const status = query.state.data?.display_status
if (!status || NON_TERMINAL_DISPLAY_STATUSES.has(status))
return 2500
return false
},
}) })
const { data: documentMetadata } = useDocumentMetadata({ const { data: documentMetadata } = useDocumentMetadata({
@@ -97,19 +111,15 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
params: { metadata: 'only' }, params: { metadata: 'only' },
}) })
const backToPrev = () => { const backToPrev = useCallback(() => {
const queryString = searchParams.toString() const queryString = searchParams.toString()
const backPath = `/datasets/${datasetId}/documents${queryString ? `?${queryString}` : ''}` const backPath = `/datasets/${datasetId}/documents${queryString ? `?${queryString}` : ''}`
router.push(backPath) router.push(backPath)
} }, [searchParams, datasetId, router])
const isDetailLoading = !documentDetail && !error const isDetailLoading = !documentDetail && !error
const embedding = ['queuing', 'indexing', 'paused'].includes((documentDetail?.display_status || '').toLowerCase()) const embedding = NON_TERMINAL_DISPLAY_STATUSES.has(documentDetail?.display_status as DocumentDisplayStatus)
const isLegacyDataSourceInfo = (info?: DataSourceInfo): info is LegacyDataSourceInfo => {
return !!info && 'upload_file' in info
}
const documentUploadFile = useMemo(() => { const documentUploadFile = useMemo(() => {
if (!documentDetail?.data_source_info) if (!documentDetail?.data_source_info)
@@ -123,7 +133,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
const invalidChildChunkList = useInvalid(useChildSegmentListKey) const invalidChildChunkList = useInvalid(useChildSegmentListKey)
const invalidDocumentList = useInvalidDocumentList(datasetId) const invalidDocumentList = useInvalidDocumentList(datasetId)
const handleOperate = (operateName?: string) => { const handleOperate = useCallback((operateName?: string) => {
invalidDocumentList() invalidDocumentList()
if (operateName === 'delete') { if (operateName === 'delete') {
backToPrev() backToPrev()
@@ -138,7 +148,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
}, 5000) }, 5000)
} }
} }
} }, [invalidDocumentList, backToPrev, detailMutate, invalidChunkList, invalidChildChunkList])
const parentMode = useMemo(() => { const parentMode = useMemo(() => {
return documentDetail?.document_process_rule?.rules?.parent_mode || documentDetail?.dataset_process_rule?.rules?.parent_mode || 'paragraph' return documentDetail?.document_process_rule?.rules?.parent_mode || documentDetail?.dataset_process_rule?.rules?.parent_mode || 'paragraph'
@@ -149,19 +159,41 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
return chunkMode === ChunkingMode.parentChild && parentMode === 'full-doc' return chunkMode === ChunkingMode.parentChild && parentMode === 'full-doc'
}, [documentDetail?.doc_form, parentMode]) }, [documentDetail?.doc_form, parentMode])
const contextValue = useMemo(() => ({
datasetId,
documentId,
docForm: documentDetail?.doc_form as ChunkingMode,
parentMode,
}), [datasetId, documentId, documentDetail?.doc_form, parentMode])
const statusDetail = useMemo(() => ({
enabled: documentDetail?.enabled || false,
archived: documentDetail?.archived || false,
id: documentId,
}), [documentDetail?.enabled, documentDetail?.archived, documentId])
const operationsDetail = useMemo(() => ({
name: documentDetail?.name || '',
enabled: documentDetail?.enabled || false,
archived: documentDetail?.archived || false,
id: documentId,
data_source_type: documentDetail?.data_source_type || '',
doc_form: documentDetail?.doc_form || '',
}), [documentDetail?.name, documentDetail?.enabled, documentDetail?.archived, documentId, documentDetail?.data_source_type, documentDetail?.doc_form])
const docDetail = useMemo(() => ({
...documentDetail,
...documentMetadata,
doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type,
} as FullDocumentDetail), [documentDetail, documentMetadata])
const backButtonLabel = t('operation.back', { ns: 'common' }) const backButtonLabel = t('operation.back', { ns: 'common' })
const metadataToggleLabel = `${showMetadata const metadataToggleLabel = `${showMetadata
? t('operation.close', { ns: 'common' }) ? t('operation.close', { ns: 'common' })
: t('operation.view', { ns: 'common' })} ${t('metadata.title', { ns: 'datasetDocuments' })}` : t('operation.view', { ns: 'common' })} ${t('metadata.title', { ns: 'datasetDocuments' })}`
return ( return (
<DocumentContext.Provider value={{ <DocumentContext.Provider value={contextValue}>
datasetId,
documentId,
docForm: documentDetail?.doc_form as ChunkingMode,
parentMode,
}}
>
<div className="flex h-full flex-col bg-background-default"> <div className="flex h-full flex-col bg-background-default">
<div className="flex min-h-16 flex-wrap items-center justify-between border-b border-b-divider-subtle py-2.5 pl-3 pr-4"> <div className="flex min-h-16 flex-wrap items-center justify-between border-b border-b-divider-subtle py-2.5 pl-3 pr-4">
<button <button
@@ -198,30 +230,21 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
<Divider type="vertical" className="!mx-3 !h-[14px] !bg-divider-regular" /> <Divider type="vertical" className="!mx-3 !h-[14px] !bg-divider-regular" />
</> </>
)} )}
<StatusItem {documentDetail && (
status={documentDetail?.display_status || 'available'} <StatusItem
scene="detail" status={documentDetail.display_status || 'available'}
errorMessage={documentDetail?.error || ''} scene="detail"
textCls="font-semibold text-xs uppercase" errorMessage={documentDetail.error || ''}
detail={{ textCls="font-semibold text-xs uppercase"
enabled: documentDetail?.enabled || false, detail={statusDetail}
archived: documentDetail?.archived || false, datasetId={datasetId}
id: documentId, onUpdate={handleOperate}
}} />
datasetId={datasetId} )}
onUpdate={handleOperate}
/>
<Operations <Operations
scene="detail" scene="detail"
embeddingAvailable={embeddingAvailable} embeddingAvailable={embeddingAvailable}
detail={{ detail={operationsDetail}
name: documentDetail?.name || '',
enabled: documentDetail?.enabled || false,
archived: documentDetail?.archived || false,
id: documentId,
data_source_type: documentDetail?.data_source_type || '',
doc_form: documentDetail?.doc_form || '',
}}
datasetId={datasetId} datasetId={datasetId}
onUpdate={handleOperate} onUpdate={handleOperate}
className="!w-[200px]" className="!w-[200px]"
@@ -272,7 +295,7 @@ const DocumentDetail: FC<DocumentDetailProps> = ({ datasetId, documentId }) => {
className="mr-2 mt-3" className="mr-2 mt-3"
datasetId={datasetId} datasetId={datasetId}
documentId={documentId} documentId={documentId}
docDetail={{ ...documentDetail, ...documentMetadata, doc_type: documentMetadata?.doc_type === 'others' ? '' : documentMetadata?.doc_type } as FullDocumentDetail} docDetail={docDetail}
/> />
</FloatRightContainer> </FloatRightContainer>
</div> </div>

View File

@@ -133,15 +133,19 @@ export const useSyncWebsite = () => {
} }
const useDocumentDetailKey = [NAME_SPACE, 'documentDetail', 'withoutMetaData'] const useDocumentDetailKey = [NAME_SPACE, 'documentDetail', 'withoutMetaData']
type DocumentDetailRefetchInterval = UseQueryOptions<DocumentDetailResponse>['refetchInterval']
export const useDocumentDetail = (payload: { export const useDocumentDetail = (payload: {
datasetId: string datasetId: string
documentId: string documentId: string
params: { metadata: MetadataType } params: { metadata: MetadataType }
refetchInterval?: DocumentDetailRefetchInterval
}) => { }) => {
const { datasetId, documentId, params } = payload const { datasetId, documentId, params, refetchInterval } = payload
return useQuery<DocumentDetailResponse>({ return useQuery<DocumentDetailResponse>({
queryKey: [...useDocumentDetailKey, 'withoutMetaData', datasetId, documentId, params], queryKey: [...useDocumentDetailKey, 'withoutMetaData', datasetId, documentId, params],
queryFn: () => get<DocumentDetailResponse>(`/datasets/${datasetId}/documents/${documentId}`, { params }), queryFn: () => get<DocumentDetailResponse>(`/datasets/${datasetId}/documents/${documentId}`, { params }),
refetchInterval,
}) })
} }