Co-authored-by: zhuxinliang <zhuxinliang@didiglobal.com>pull/12908/head
parent
9903f1e703
commit
0c6a8a130e
@ -0,0 +1,60 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import ResultItemMeta from './result-item-meta'
|
||||
import ResultItemFooter from './result-item-footer'
|
||||
import type { ExternalKnowledgeBaseHitTesting } from '@/models/datasets'
|
||||
import cn from '@/utils/classnames'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
|
||||
const i18nPrefix = 'datasetHitTesting'
|
||||
type Props = {
|
||||
payload: ExternalKnowledgeBaseHitTesting
|
||||
positionId: number
|
||||
}
|
||||
|
||||
const ResultItemExternal: FC<Props> = ({ payload, positionId }) => {
|
||||
const { t } = useTranslation()
|
||||
const { content, title, score } = payload
|
||||
const [
|
||||
isShowDetailModal,
|
||||
{ setTrue: showDetailModal, setFalse: hideDetailModal },
|
||||
] = useBoolean(false)
|
||||
|
||||
return (
|
||||
<div className={cn('pt-3 bg-chat-bubble-bg rounded-xl hover:shadow-lg cursor-pointer')} onClick={showDetailModal}>
|
||||
{/* Meta info */}
|
||||
<ResultItemMeta className='px-3' labelPrefix={'Chunk'} positionId={positionId} wordCount={content.length} score={score} />
|
||||
|
||||
{/* Main */}
|
||||
<div className='mt-1 px-3'>
|
||||
<div className='line-clamp-2 body-md-regular break-all'>{content}</div>
|
||||
</div>
|
||||
|
||||
{/* Foot */}
|
||||
<ResultItemFooter docType={FileAppearanceTypeEnum.custom} docTitle={title} showDetailModal={showDetailModal} />
|
||||
|
||||
{isShowDetailModal && (
|
||||
<Modal
|
||||
title={t(`${i18nPrefix}.chunkDetail`)}
|
||||
className={'!min-w-[800px]'}
|
||||
closable
|
||||
onClose={hideDetailModal}
|
||||
isShow={isShowDetailModal}
|
||||
>
|
||||
<div className='mt-4 flex-1'>
|
||||
<ResultItemMeta labelPrefix={'Chunk'} positionId={positionId} wordCount={content.length} score={score} />
|
||||
<div className={cn('mt-2 body-md-regular text-text-secondary break-all', 'h-[min(539px,_80vh)] overflow-y-auto')}>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ResultItemExternal)
|
||||
@ -0,0 +1,42 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiArrowRightUpLine } from '@remixicon/react'
|
||||
import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
|
||||
type Props = {
|
||||
docType: FileAppearanceTypeEnum
|
||||
docTitle: string
|
||||
showDetailModal: () => void
|
||||
}
|
||||
const i18nPrefix = 'datasetHitTesting'
|
||||
|
||||
const ResultItemFooter: FC<Props> = ({
|
||||
docType,
|
||||
docTitle,
|
||||
showDetailModal,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="mt-3 flex justify-between items-center h-10 pl-3 pr-2 border-t border-divider-subtle">
|
||||
<div className="grow flex items-center space-x-1">
|
||||
<FileIcon type={docType} size="sm" />
|
||||
<span className="grow w-0 truncate text-text-secondary text-[13px] font-normal">
|
||||
{docTitle}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center space-x-1 cursor-pointer text-text-tertiary"
|
||||
onClick={showDetailModal}
|
||||
>
|
||||
<div className="text-xs uppercase">{t(`${i18nPrefix}.open`)}</div>
|
||||
<RiArrowRightUpLine className="size-3.5" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ResultItemFooter)
|
||||
@ -0,0 +1,45 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
|
||||
import Dot from '../../documents/detail/completed/common/dot'
|
||||
import Score from './score'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
labelPrefix: string
|
||||
positionId: number
|
||||
wordCount: number
|
||||
score: number
|
||||
className?: string
|
||||
}
|
||||
|
||||
const ResultItemMeta: FC<Props> = ({
|
||||
labelPrefix,
|
||||
positionId,
|
||||
wordCount,
|
||||
score,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={cn('flex justify-between items-center', className)}>
|
||||
<div className="flex items-center space-x-2">
|
||||
<SegmentIndexTag
|
||||
labelPrefix={labelPrefix}
|
||||
positionId={positionId}
|
||||
className={cn('w-fit group-hover:opacity-100')}
|
||||
/>
|
||||
<Dot />
|
||||
<div className="system-xs-medium text-text-tertiary">
|
||||
{wordCount} {t('datasetDocuments.segment.characters', { count: wordCount })}
|
||||
</div>
|
||||
</div>
|
||||
<Score value={score} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(ResultItemMeta)
|
||||
Loading…
Reference in New Issue