From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001 From: wwf <yearningwang@iqtogether.com> Date: 星期三, 04 六月 2025 15:17:49 +0800 Subject: [PATCH] 初始化 --- app/components/datasets/documents/list.tsx | 291 +++++++++++++++++++++++++-------------------------------- 1 files changed, 128 insertions(+), 163 deletions(-) diff --git a/app/components/datasets/documents/list.tsx b/app/components/datasets/documents/list.tsx index cb349ee..00ccdfd 100644 --- a/app/components/datasets/documents/list.tsx +++ b/app/components/datasets/documents/list.tsx @@ -16,6 +16,7 @@ import { useRouter } from 'next/navigation' import { useTranslation } from 'react-i18next' import dayjs from 'dayjs' +import { Edit03 } from '../../base/icons/src/vender/solid/general' import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel' import ChunkingModeLabel from '../common/chunking-mode-label' import FileTypeIcon from '../../base/file-uploader/file-type-icon' @@ -44,9 +45,6 @@ import Checkbox from '@/app/components/base/checkbox' import { useDocumentArchive, useDocumentDelete, useDocumentDisable, useDocumentEnable, useDocumentUnArchive, useSyncDocument, useSyncWebsite } from '@/service/knowledge/use-document' import { extensionToFileType } from '@/app/components/datasets/hit-testing/utils/extension-to-file-type' -import useBatchEditDocumentMetadata from '../metadata/hooks/use-batch-edit-document-metadata' -import EditMetadataBatchModal from '@/app/components/datasets/metadata/edit-metadata-batch/modal' -import { noop } from 'lodash-es' export const useIndexStatus = () => { const { t } = useTranslation() @@ -109,8 +107,7 @@ const [e] = await asyncRunSafe<CommonResponse>(opApi({ datasetId, documentId: id }) as Promise<CommonResponse>) if (!e) { notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) - onUpdate?.() - // onUpdate?.(operationName) + onUpdate?.(operationName) } else { notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) } } @@ -148,7 +145,7 @@ } { scene === 'detail' && ( - <div className='ml-1.5 flex items-center justify-between'> + <div className='flex justify-between items-center ml-1.5'> <Tooltip popupContent={t('datasetDocuments.list.action.enableWarning')} popupClassName='text-text-secondary system-xs-medium' @@ -202,7 +199,7 @@ const isListScene = scene === 'list' const onOperate = async (operationName: OperationName) => { - let opApi + let opApi = deleteDocument switch (operationName) { case 'archive': opApi = archiveDocument @@ -266,7 +263,7 @@ return <div className='flex items-center' onClick={e => e.stopPropagation()}> {isListScene && !embeddingAvailable && ( - <Switch defaultValue={false} onChange={noop} disabled={true} size='md' /> + <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' /> )} {isListScene && embeddingAvailable && ( <> @@ -277,7 +274,7 @@ needsDelay > <div> - <Switch defaultValue={false} onChange={noop} disabled={true} size='md' /> + <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' /> </div> </Tooltip> : <Switch defaultValue={enabled} onChange={v => handleSwitch(v ? 'enable' : 'disable')} size='md' /> @@ -292,12 +289,12 @@ popupClassName='text-text-secondary system-xs-medium' > <button - className={cn('mr-2 cursor-pointer rounded-lg', + className={cn('rounded-lg mr-2 cursor-pointer', !isListScene - ? 'border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg p-2 shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px] hover:border-components-button-secondary-border-hover hover:bg-components-button-secondary-bg-hover' + ? 'p-2 bg-components-button-secondary-bg hover:bg-components-button-secondary-bg-hover border-[0.5px] border-components-button-secondary-border hover:border-components-button-secondary-border-hover shadow-xs shadow-shadow-shadow-3 backdrop-blur-[5px]' : 'p-0.5 hover:bg-state-base-hover')} onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}> - <RiEqualizer2Line className='h-4 w-4 text-components-button-secondary-text' /> + <RiEqualizer2Line className='w-4 h-4 text-components-button-secondary-text' /> </button> </Tooltip> <Popover @@ -311,12 +308,12 @@ name: detail.name, }) }}> - <RiEditLine className='h-4 w-4 text-text-tertiary' /> + <RiEditLine className='w-4 h-4 text-text-tertiary' /> <span className={s.actionName}>{t('datasetDocuments.list.table.rename')}</span> </div> {['notion_import', DataSourceType.WEB].includes(data_source_type) && ( <div className={s.actionItem} onClick={() => onOperate('sync')}> - <RiLoopLeftLine className='h-4 w-4 text-text-tertiary' /> + <RiLoopLeftLine className='w-4 h-4 text-text-tertiary' /> <span className={s.actionName}>{t('datasetDocuments.list.action.sync')}</span> </div> )} @@ -324,17 +321,17 @@ </> )} {!archived && <div className={s.actionItem} onClick={() => onOperate('archive')}> - <RiArchive2Line className='h-4 w-4 text-text-tertiary' /> + <RiArchive2Line className='w-4 h-4 text-text-tertiary' /> <span className={s.actionName}>{t('datasetDocuments.list.action.archive')}</span> </div>} {archived && ( <div className={s.actionItem} onClick={() => onOperate('un_archive')}> - <RiArchive2Line className='h-4 w-4 text-text-tertiary' /> + <RiArchive2Line className='w-4 h-4 text-text-tertiary' /> <span className={s.actionName}>{t('datasetDocuments.list.action.unarchive')}</span> </div> )} <div className={cn(s.actionItem, s.deleteActionItem, 'group')} onClick={() => setShowModal(true)}> - <RiDeleteBinLine className={'h-4 w-4 text-text-tertiary group-hover:text-text-destructive'} /> + <RiDeleteBinLine className={'w-4 h-4 text-text-tertiary group-hover:text-text-destructive'} /> <span className={cn(s.actionName, 'group-hover:text-text-destructive')}>{t('datasetDocuments.list.action.delete')}</span> </div> </div> @@ -343,12 +340,12 @@ position='br' btnElement={ <div className={cn(s.commonIcon)}> - <RiMoreFill className='h-4 w-4 text-components-button-secondary-text' /> + <RiMoreFill className='w-4 h-4 text-text-components-button-secondary-text' /> </div> } btnClassName={open => cn(isListScene ? s.actionIconWrapperList : s.actionIconWrapperDetail, open ? '!hover:bg-state-base-hover !shadow-none' : '!bg-transparent')} popupClassName='!w-full' - className={`!z-20 flex h-fit !w-[200px] justify-end ${className}`} + className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`} /> </> )} @@ -404,7 +401,6 @@ datasetId: string pagination: PaginationProps onUpdate: () => void - onManageMetadata: () => void } /** @@ -418,7 +414,6 @@ datasetId, pagination, onUpdate, - onManageMetadata, }) => { const { t } = useTranslation() const { formatTime } = useTimestamp() @@ -429,17 +424,6 @@ const isQAMode = chunkingMode === ChunkingMode.qa const [localDocs, setLocalDocs] = useState<LocalDoc[]>(documents) const [enableSort, setEnableSort] = useState(true) - const { - isShowEditModal, - showEditModal, - hideEditModal, - originalList, - handleSave, - } = useBatchEditDocumentMetadata({ - datasetId, - docList: documents.filter(item => selectedIds.includes(item.id)), - onUpdate, - }) useEffect(() => { setLocalDocs(documents) @@ -490,7 +474,7 @@ const handleAction = (actionName: DocumentActionType) => { return async () => { - let opApi + let opApi = deleteDocument switch (actionName) { case DocumentActionType.archive: opApi = archiveDocument @@ -516,144 +500,139 @@ } return ( - <div className='relative flex h-full w-full flex-col'> - <div className='relative grow overflow-x-auto'> - <table className={`mt-3 w-full min-w-[700px] max-w-full border-collapse border-0 text-sm ${s.documentTable}`}> - <thead className="h-8 border-b border-divider-subtle text-xs font-medium uppercase leading-8 text-text-tertiary"> - <tr> - <td className='w-12'> + <div className='relative w-full h-full overflow-x-auto'> + <table className={`min-w-[700px] max-w-full w-full border-collapse border-0 text-sm mt-3 ${s.documentTable}`}> + <thead className="h-8 leading-8 border-b border-divider-subtle text-text-tertiary font-medium text-xs uppercase"> + <tr> + <td className='w-12'> + <div className='flex items-center' onClick={e => e.stopPropagation()}> + <Checkbox + className='shrink-0 mr-2' + checked={isAllSelected} + mixed={!isAllSelected && isSomeSelected} + onCheck={onSelectedAll} + /> + # + </div> + </td> + <td> + <div className='flex'> + {t('datasetDocuments.list.table.header.fileName')} + </div> + </td> + <td className='w-[130px]'>{t('datasetDocuments.list.table.header.chunkingMode')}</td> + <td className='w-24'>{t('datasetDocuments.list.table.header.words')}</td> + <td className='w-44'>{t('datasetDocuments.list.table.header.hitCount')}</td> + <td className='w-44'> + <div className='flex items-center' onClick={onClickSort}> + {t('datasetDocuments.list.table.header.uploadTime')} + <ArrowDownIcon className={cn('ml-0.5 h-3 w-3 stroke-current stroke-2 cursor-pointer', enableSort ? 'text-text-tertiary' : 'text-text-disabled')} /> + </div> + </td> + <td className='w-40'>{t('datasetDocuments.list.table.header.status')}</td> + <td className='w-20'>{t('datasetDocuments.list.table.header.action')}</td> + </tr> + </thead> + <tbody className="text-text-secondary"> + {localDocs.map((doc, index) => { + const isFile = doc.data_source_type === DataSourceType.FILE + const fileType = isFile ? doc.data_source_detail_dict?.upload_file?.extension : '' + return <tr + key={doc.id} + className={'border-b border-divider-subtle h-8 hover:bg-background-default-hover cursor-pointer'} + onClick={() => { + router.push(`/datasets/${datasetId}/documents/${doc.id}`) + }}> + <td className='text-left align-middle text-text-tertiary text-xs'> <div className='flex items-center' onClick={e => e.stopPropagation()}> - {embeddingAvailable && ( - <Checkbox - className='mr-2 shrink-0' - checked={isAllSelected} - indeterminate={!isAllSelected && isSomeSelected} - onCheck={onSelectedAll} - /> - )} - # + <Checkbox + className='shrink-0 mr-2' + checked={selectedIds.includes(doc.id)} + onCheck={() => { + onSelectedIdChange( + selectedIds.includes(doc.id) + ? selectedIds.filter(id => id !== doc.id) + : [...selectedIds, doc.id], + ) + }} + /> + {/* {doc.position} */} + {index + 1} </div> </td> <td> - <div className='flex'> - {t('datasetDocuments.list.table.header.fileName')} - </div> - </td> - <td className='w-[130px]'>{t('datasetDocuments.list.table.header.chunkingMode')}</td> - <td className='w-24'>{t('datasetDocuments.list.table.header.words')}</td> - <td className='w-44'>{t('datasetDocuments.list.table.header.hitCount')}</td> - <td className='w-44'> - <div className='flex items-center' onClick={onClickSort}> - {t('datasetDocuments.list.table.header.uploadTime')} - <ArrowDownIcon className={cn('ml-0.5 h-3 w-3 cursor-pointer stroke-current stroke-2', enableSort ? 'text-text-tertiary' : 'text-text-disabled')} /> - </div> - </td> - <td className='w-40'>{t('datasetDocuments.list.table.header.status')}</td> - <td className='w-20'>{t('datasetDocuments.list.table.header.action')}</td> - </tr> - </thead> - <tbody className="text-text-secondary"> - {localDocs.map((doc, index) => { - const isFile = doc.data_source_type === DataSourceType.FILE - const fileType = isFile ? doc.data_source_detail_dict?.upload_file?.extension : '' - return <tr - key={doc.id} - className={'h-8 cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover'} - onClick={() => { - router.push(`/datasets/${datasetId}/documents/${doc.id}`) - }}> - <td className='text-left align-middle text-xs text-text-tertiary'> - <div className='flex items-center' onClick={e => e.stopPropagation()}> - <Checkbox - className='mr-2 shrink-0' - checked={selectedIds.includes(doc.id)} - onCheck={() => { - onSelectedIdChange( - selectedIds.includes(doc.id) - ? selectedIds.filter(id => id !== doc.id) - : [...selectedIds, doc.id], - ) - }} - /> - {/* {doc.position} */} - {index + 1} + <div className={'group flex items-center mr-6 hover:mr-0 max-w-[460px]'}> + <div className='shrink-0'> + {doc?.data_source_type === DataSourceType.NOTION && <NotionIcon className='inline-flex -mt-[3px] mr-1.5 align-middle' type='page' src={doc.data_source_info.notion_page_icon} />} + {doc?.data_source_type === DataSourceType.FILE && <FileTypeIcon type={extensionToFileType(doc?.data_source_info?.upload_file?.extension ?? fileType)} className='mr-1.5' />} + {doc?.data_source_type === DataSourceType.WEB && <Globe01 className='inline-flex -mt-[3px] mr-1.5 align-middle' />} </div> - </td> - <td> - <div className={'group mr-6 flex max-w-[460px] items-center hover:mr-0'}> - <div className='shrink-0'> - {doc?.data_source_type === DataSourceType.NOTION && <NotionIcon className='mr-1.5 mt-[-3px] inline-flex align-middle' type='page' src={doc.data_source_info.notion_page_icon} />} - {doc?.data_source_type === DataSourceType.FILE && <FileTypeIcon type={extensionToFileType(doc?.data_source_info?.upload_file?.extension ?? fileType)} className='mr-1.5' />} - {doc?.data_source_type === DataSourceType.WEB && <Globe01 className='mr-1.5 mt-[-3px] inline-flex align-middle' />} - </div> - <span className='grow-1 truncate text-sm'>{doc.name}</span> - <div className='hidden shrink-0 group-hover:ml-auto group-hover:flex'> - <Tooltip - popupContent={t('datasetDocuments.list.table.rename')} + <span className='text-sm truncate grow-1'>{doc.name}</span> + <div className='group-hover:flex group-hover:ml-auto hidden shrink-0'> + <Tooltip + popupContent={t('datasetDocuments.list.table.rename')} + > + <div + className='p-1 rounded-md cursor-pointer hover:bg-state-base-hover' + onClick={(e) => { + e.stopPropagation() + handleShowRenameModal(doc) + }} > - <div - className='cursor-pointer rounded-md p-1 hover:bg-state-base-hover' - onClick={(e) => { - e.stopPropagation() - handleShowRenameModal(doc) - }} - > - <RiEditLine className='h-4 w-4 text-text-tertiary' /> - </div> - </Tooltip> - </div> + <Edit03 className='w-4 h-4 text-text-tertiary' /> + </div> + </Tooltip> </div> - </td> - <td> - <ChunkingModeLabel - isGeneralMode={isGeneralMode} - isQAMode={isQAMode} - /> - </td> - <td>{renderCount(doc.word_count)}</td> - <td>{renderCount(doc.hit_count)}</td> - <td className='text-[13px] text-text-secondary'> - {formatTime(doc.created_at, t('datasetHitTesting.dateTimeFormat') as string)} - </td> - <td> - { - (['indexing', 'splitting', 'parsing', 'cleaning'].includes(doc.indexing_status) && doc?.data_source_type === DataSourceType.NOTION) - ? <ProgressBar percent={doc.percent || 0} /> - : <StatusItem status={doc.display_status} /> - } - </td> - <td> - <OperationAction - embeddingAvailable={embeddingAvailable} - datasetId={datasetId} - detail={pick(doc, ['name', 'enabled', 'archived', 'id', 'data_source_type', 'doc_form'])} - onUpdate={onUpdate} - /> - </td> - </tr> - })} - </tbody> - </table> - </div> + </div> + </td> + <td> + <ChunkingModeLabel + isGeneralMode={isGeneralMode} + isQAMode={isQAMode} + /> + </td> + <td>{renderCount(doc.word_count)}</td> + <td>{renderCount(doc.hit_count)}</td> + <td className='text-text-secondary text-[13px]'> + {formatTime(doc.created_at, t('datasetHitTesting.dateTimeFormat') as string)} + </td> + <td> + { + (['indexing', 'splitting', 'parsing', 'cleaning'].includes(doc.indexing_status) && doc?.data_source_type === DataSourceType.NOTION) + ? <ProgressBar percent={doc.percent || 0} /> + : <StatusItem status={doc.display_status} /> + } + </td> + <td> + <OperationAction + embeddingAvailable={embeddingAvailable} + datasetId={datasetId} + detail={pick(doc, ['name', 'enabled', 'archived', 'id', 'data_source_type', 'doc_form'])} + onUpdate={onUpdate} + /> + </td> + </tr> + })} + </tbody> + </table> {(selectedIds.length > 0) && ( <BatchAction - className='absolute bottom-16 left-0 z-20' + className='absolute left-0 bottom-16 z-20' selectedIds={selectedIds} onArchive={handleAction(DocumentActionType.archive)} onBatchEnable={handleAction(DocumentActionType.enable)} onBatchDisable={handleAction(DocumentActionType.disable)} onBatchDelete={handleAction(DocumentActionType.delete)} - onEditMetadata={showEditModal} onCancel={() => { onSelectedIdChange([]) }} /> )} {/* Show Pagination only if the total is more than the limit */} - {pagination.total && ( + {pagination.total && pagination.total > (pagination.limit || 10) && ( <Pagination {...pagination} - className='w-full shrink-0 px-0 pb-0' + className='absolute bottom-0 left-0 w-full px-0 pb-0' /> )} @@ -664,20 +643,6 @@ name={currDocument.name} onClose={setShowRenameModalFalse} onSaved={handleRenamed} - /> - )} - - {isShowEditModal && ( - <EditMetadataBatchModal - datasetId={datasetId} - documentNum={selectedIds.length} - list={originalList} - onSave={handleSave} - onHide={hideEditModal} - onShowManage={() => { - hideEditModal() - onManageMetadata() - }} /> )} </div> -- Gitblit v1.8.0