feat: update translation files and improve segment index tag component

This commit is contained in:
twwu 2024-12-11 18:15:30 +08:00
parent 4017c65c1f
commit 51f6a87aef
18 changed files with 147 additions and 85 deletions

View File

@ -8,7 +8,7 @@ import {
import { StatusItem } from '../../list' import { StatusItem } from '../../list'
import style from '../../style.module.css' import style from '../../style.module.css'
import s from './style.module.css' import s from './style.module.css'
import { SegmentIndexTag } from './index' import { SegmentIndexTag } from './common/segment-index-tag'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import Switch from '@/app/components/base/switch' import Switch from '@/app/components/base/switch'

View File

@ -1,6 +1,7 @@
import React, { type FC, useEffect, useRef, useState } from 'react' import React, { type FC, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { RiLoader2Line } from '@remixicon/react' import { RiLoader2Line } from '@remixicon/react'
import { useCountDown } from 'ahooks'
import Modal from '@/app/components/base/modal' import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
@ -18,15 +19,15 @@ const DefaultContent: FC<IDefaultContentProps> = React.memo(({
return ( return (
<> <>
<div className='p-6 pb-4'> <div className='pb-4'>
<span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regenerationConfirm')}</span> <span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regenerationConfirmTitle')}</span>
<p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regenerationWarning')}</p> <p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regenerationConfirmMessage')}</p>
</div> </div>
<div className='flex justify-end gap-x-2 p-6'> <div className='flex justify-end gap-x-2 pt-6'>
<Button onClick={onCancel}> <Button onClick={onCancel}>
{t('common.operation.cancel')} {t('common.operation.cancel')}
</Button> </Button>
<Button destructive onClick={onConfirm}> <Button variant='warning' destructive onClick={onConfirm}>
{t('common.operation.regenerate')} {t('common.operation.regenerate')}
</Button> </Button>
</div> </div>
@ -34,18 +35,20 @@ const DefaultContent: FC<IDefaultContentProps> = React.memo(({
) )
}) })
DefaultContent.displayName = 'DefaultContent'
const RegeneratingContent: FC = React.memo(() => { const RegeneratingContent: FC = React.memo(() => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<> <>
<div className='p-6 pb-4'> <div className='pb-4'>
<span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regeneratingTitle')}</span> <span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regeneratingTitle')}</span>
<p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regeneratingMessage')}</p> <p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regeneratingMessage')}</p>
</div> </div>
<div className='flex justify-end p-6'> <div className='flex justify-end pt-6'>
<Button destructive disabled className='inline-flex items-center gap-x-0.5'> <Button variant='warning' destructive disabled className='inline-flex items-center gap-x-0.5'>
<RiLoader2Line className='w-4 h-4 text-components-button-destructive-primary-text-disabled' /> <RiLoader2Line className='w-4 h-4 text-components-button-destructive-primary-text-disabled animate-spin' />
<span>{t('common.operation.regenerate')}</span> <span>{t('common.operation.regenerate')}</span>
</Button> </Button>
</div> </div>
@ -53,6 +56,8 @@ const RegeneratingContent: FC = React.memo(() => {
) )
}) })
RegeneratingContent.displayName = 'RegeneratingContent'
type IRegenerationCompletedContentProps = { type IRegenerationCompletedContentProps = {
onClose: () => void onClose: () => void
} }
@ -61,67 +66,64 @@ const RegenerationCompletedContent: FC<IRegenerationCompletedContentProps> = Rea
onClose, onClose,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [countDown, setCountDown] = useState(5) const targetTime = useRef(Date.now() + 5000)
const timerRef = useRef<any>(null) const [countdown] = useCountDown({
targetDate: targetTime.current,
useEffect(() => { onEnd: () => {
timerRef.current = setInterval(() => { onClose()
if (countDown > 0) },
setCountDown(countDown - 1) })
else
clearInterval(timerRef.current)
}, 1000)
return () => {
clearInterval(timerRef.current)
}
}, [])
return ( return (
<> <>
<div className='p-6 pb-4'> <div className='pb-4'>
<span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regenerationSuccessTitle')}</span> <span className='text-text-primary title-2xl-semi-bold'>{t('datasetDocuments.segment.regenerationSuccessTitle')}</span>
<p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regenerationSuccessMessage')}</p> <p className='text-text-secondary system-md-regular'>{t('datasetDocuments.segment.regenerationSuccessMessage')}</p>
</div> </div>
<div className='flex justify-end p-6'> <div className='flex justify-end pt-6'>
<Button variant='primary' onClick={onClose}> <Button variant='primary' onClick={onClose}>
{`${t('common.operation.close')}(${countDown})`} {`${t('common.operation.close')}${countdown === 0 ? '' : `(${Math.round(countdown / 1000)})`}`}
</Button> </Button>
</div> </div>
</> </>
) )
}) })
RegenerationCompletedContent.displayName = 'RegenerationCompletedContent'
type IRegenerationModalProps = { type IRegenerationModalProps = {
isShow: boolean isShow: boolean
onConfirm: () => void onConfirm: () => void
onCancel: () => void onCancel: () => void
onClose: () => void
} }
const RegenerationModal: FC<IRegenerationModalProps> = ({ const RegenerationModal: FC<IRegenerationModalProps> = ({
isShow, isShow,
onConfirm, onConfirm,
onCancel, onCancel,
onClose,
}) => { }) => {
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [updateSuccess, setUpdateSuccess] = useState(false) const [updateSucceeded, setUpdateSucceeded] = useState(false)
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()
eventEmitter?.useSubscription((v) => { eventEmitter?.useSubscription((v) => {
if (v === 'update-segment') { if (v === 'update-segment') {
setLoading(true) setLoading(true)
setUpdateSuccess(false) setUpdateSucceeded(false)
} }
if (v === 'update-segment-success') if (v === 'update-segment-success')
setUpdateSuccess(true) setUpdateSucceeded(true)
if (v === 'update-segment-done') if (v === 'update-segment-done')
setLoading(false) setLoading(false)
}) })
return ( return (
<Modal isShow={isShow} onClose={() => {}} className='!max-w-[480px] !rounded-2xl'> <Modal isShow={isShow} onClose={() => {}} className='!max-w-[480px] !rounded-2xl'>
{(!loading && !updateSuccess) && <DefaultContent onCancel={onCancel} onConfirm={onConfirm} />} {!loading && !updateSucceeded && <DefaultContent onCancel={onCancel} onConfirm={onConfirm} />}
{(loading && !updateSuccess) && <RegeneratingContent />} {loading && !updateSucceeded && <RegeneratingContent />}
{!loading && updateSuccess && <RegenerationCompletedContent onClose={onCancel} />} {!loading && updateSucceeded && <RegenerationCompletedContent onClose={onClose} />}
</Modal> </Modal>
) )
} }

View File

@ -0,0 +1,36 @@
import React, { type FC, useMemo } from 'react'
import { Chunk } from '@/app/components/base/icons/src/public/knowledge'
import cn from '@/utils/classnames'
type ISegmentIndexTagProps = {
positionId?: string | number
label?: string
className?: string
labelPrefix?: string
}
export const SegmentIndexTag: FC<ISegmentIndexTagProps> = ({
positionId,
label,
className,
labelPrefix = 'Chunk',
}) => {
const localPositionId = useMemo(() => {
const positionIdStr = String(positionId)
if (positionIdStr.length >= 3)
return `${labelPrefix}-${positionId}`
return `${labelPrefix}-${positionIdStr.padStart(2, '0')}`
}, [positionId, labelPrefix])
return (
<div className={cn('flex items-center', className)}>
<Chunk className='w-3 h-3 p-[1px] text-text-tertiary mr-0.5' />
<div className='text-text-tertiary system-xs-medium'>
{label || localPositionId}
</div>
</div>
)
}
SegmentIndexTag.displayName = 'SegmentIndexTag'
export default React.memo(SegmentIndexTag)

View File

@ -13,7 +13,7 @@ import BatchAction from './batch-action'
import SegmentDetail from './segment-detail' import SegmentDetail from './segment-detail'
import SegmentCard from './segment-card' import SegmentCard from './segment-card'
import ChildSegmentList from './child-segment-list' import ChildSegmentList from './child-segment-list'
import FullScreenDrawer from './full-screen-drawer' import FullScreenDrawer from './common/full-screen-drawer'
import Pagination from '@/app/components/base/pagination' import Pagination from '@/app/components/base/pagination'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { formatNumber } from '@/utils/format' import { formatNumber } from '@/utils/format'
@ -192,7 +192,6 @@ const Completed: FC<ICompletedProps> = ({
} }
const { mutateAsync: enableSegment } = useEnableSegment() const { mutateAsync: enableSegment } = useEnableSegment()
const { mutateAsync: disableSegment } = useDisableSegment() const { mutateAsync: disableSegment } = useDisableSegment()
const onChangeSwitch = useCallback(async (enable: boolean, segId?: string) => { const onChangeSwitch = useCallback(async (enable: boolean, segId?: string) => {
@ -229,18 +228,6 @@ const Completed: FC<ICompletedProps> = ({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [datasetId, documentId, selectedSegmentIds]) }, [datasetId, documentId, selectedSegmentIds])
const onCancelBatchOperation = useCallback(() => {
setSelectedSegmentIds([])
}, [])
const onSelected = useCallback((segId: string) => {
setSelectedSegmentIds(prev =>
prev.includes(segId)
? prev.filter(id => id !== segId)
: [...prev, segId],
)
}, [])
const handleUpdateSegment = async ( const handleUpdateSegment = async (
segmentId: string, segmentId: string,
question: string, question: string,
@ -275,7 +262,8 @@ const Completed: FC<ICompletedProps> = ({
eventEmitter?.emit('update-segment') eventEmitter?.emit('update-segment')
const res = await updateSegment({ datasetId, documentId, segmentId, body: params }) const res = await updateSegment({ datasetId, documentId, segmentId, body: params })
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
onCloseDrawer() if (!needRegenerate)
onCloseDrawer()
for (const seg of segments) { for (const seg of segments) {
if (seg.id === segmentId) { if (seg.id === segmentId) {
seg.answer = res.data.answer seg.answer = res.data.answer
@ -301,6 +289,18 @@ const Completed: FC<ICompletedProps> = ({
resetList() resetList()
}, [importStatus, resetList]) }, [importStatus, resetList])
const onCancelBatchOperation = useCallback(() => {
setSelectedSegmentIds([])
}, [])
const onSelected = useCallback((segId: string) => {
setSelectedSegmentIds(prev =>
prev.includes(segId)
? prev.filter(id => id !== segId)
: [...prev, segId],
)
}, [])
const isAllSelected = useMemo(() => { const isAllSelected = useMemo(() => {
return segments.length > 0 && segments.every(seg => selectedSegmentIds.includes(seg.id)) return segments.length > 0 && segments.every(seg => selectedSegmentIds.includes(seg.id))
}, [segments, selectedSegmentIds]) }, [segments, selectedSegmentIds])

View File

@ -6,7 +6,8 @@ import { useDocumentContext } from '../index'
import ChildSegmentList from './child-segment-list' import ChildSegmentList from './child-segment-list'
import Tag from './common/tag' import Tag from './common/tag'
import Dot from './common/dot' import Dot from './common/dot'
import { SegmentIndexTag, useSegmentListContext } from '.' import { SegmentIndexTag } from './common/segment-index-tag'
import { useSegmentListContext } from './index'
import type { SegmentDetailModel } from '@/models/datasets' import type { SegmentDetailModel } from '@/models/datasets'
import Indicator from '@/app/components/header/indicator' import Indicator from '@/app/components/header/indicator'
import Switch from '@/app/components/base/switch' import Switch from '@/app/components/base/switch'
@ -108,7 +109,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
<div className='h-5 relative flex items-center justify-between'> <div className='h-5 relative flex items-center justify-between'>
<> <>
<div className='flex items-center gap-x-2'> <div className='flex items-center gap-x-2'>
<SegmentIndexTag positionId={position} className={textOpacity} /> <SegmentIndexTag positionId={position} className={textOpacity} labelPrefix={isGeneralMode ? 'Chunk' : 'Parent-Chunk'} />
<Dot /> <Dot />
<div className={cn('text-text-tertiary system-xs-medium', textOpacity)}>{`${formatNumber(word_count)} Characters`}</div> <div className={cn('text-text-tertiary system-xs-medium', textOpacity)}>{`${formatNumber(word_count)} Characters`}</div>
<Dot /> <Dot />
@ -205,7 +206,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
</div>} </div>}
{ {
isFullDocMode isFullDocMode
? <button className='mt-0.5 mb-2 text-text-accent system-xs-semibold-uppercase' onClick={() => onClick?.()}>VIEW MORE</button> ? <button className='mt-0.5 mb-2 text-text-accent system-xs-semibold-uppercase' onClick={() => onClick?.()}>{t('common.operation.viewMore')}</button>
: null : null
} }
{ {

View File

@ -1,4 +1,4 @@
import React, { type FC, useState } from 'react' import React, { type FC, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { import {
RiCloseLine, RiCloseLine,
@ -9,7 +9,8 @@ import ActionButtons from './common/action-buttons'
import ChunkContent from './common/chunk-content' import ChunkContent from './common/chunk-content'
import Keywords from './common/keywords' import Keywords from './common/keywords'
import RegenerationModal from './common/regeneration-modal' import RegenerationModal from './common/regeneration-modal'
import { SegmentIndexTag, useSegmentListContext } from './index' import { SegmentIndexTag } from './common/segment-index-tag'
import { useSegmentListContext } from './index'
import type { SegmentDetailModel } from '@/models/datasets' import type { SegmentDetailModel } from '@/models/datasets'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import { formatNumber } from '@/utils/format' import { formatNumber } from '@/utils/format'
@ -74,13 +75,17 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
onUpdate(segInfo?.id || '', question, answer, keywords, true) onUpdate(segInfo?.id || '', question, answer, keywords, true)
} }
const isParentChildMode = useMemo(() => {
return mode === 'hierarchical'
}, [mode])
return ( return (
<div className={'flex flex-col h-full'}> <div className={'flex flex-col h-full'}>
<div className={classNames('flex items-center justify-between', fullScreen ? 'py-3 pr-4 pl-6 border border-divider-subtle' : 'pt-3 pr-3 pl-4')}> <div className={classNames('flex items-center justify-between', fullScreen ? 'py-3 pr-4 pl-6 border border-divider-subtle' : 'pt-3 pr-3 pl-4')}>
<div className='flex flex-col'> <div className='flex flex-col'>
<div className='text-text-primary system-xl-semibold'>{isEditMode ? 'Edit Chunk' : 'Chunk Detail'}</div> <div className='text-text-primary system-xl-semibold'>{isEditMode ? 'Edit Chunk' : 'Chunk Detail'}</div>
<div className='flex items-center gap-x-2'> <div className='flex items-center gap-x-2'>
<SegmentIndexTag positionId={segInfo?.position || ''} /> <SegmentIndexTag positionId={segInfo?.position || ''} labelPrefix={isParentChildMode ? 'Parent-Chunk' : 'Chunk'} />
<span className='text-text-quaternary system-xs-medium'>·</span> <span className='text-text-quaternary system-xs-medium'>·</span>
<span className='text-text-tertiary system-xs-medium'>{formatNumber(isEditMode ? question.length : segInfo?.word_count as number)} {t('datasetDocuments.segment.characters')}</span> <span className='text-text-tertiary system-xs-medium'>{formatNumber(isEditMode ? question.length : segInfo?.word_count as number)} {t('datasetDocuments.segment.characters')}</span>
</div> </div>
@ -135,11 +140,16 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
/> />
</div> </div>
)} )}
<RegenerationModal {
isShow={showRegenerationModal} showRegenerationModal && (
onConfirm={onConfirmRegeneration} <RegenerationModal
onCancel={onCancelRegeneration} isShow={showRegenerationModal}
/> onConfirm={onConfirmRegeneration}
onCancel={onCancelRegeneration}
onClose={onCancelRegeneration}
/>
)
}
</div> </div>
) )
} }

View File

@ -5,7 +5,8 @@ import { useContext } from 'use-context-selector'
import { useParams } from 'next/navigation' import { useParams } from 'next/navigation'
import { RiCloseLine, RiExpandDiagonalLine } from '@remixicon/react' import { RiCloseLine, RiExpandDiagonalLine } from '@remixicon/react'
import { useShallow } from 'zustand/react/shallow' import { useShallow } from 'zustand/react/shallow'
import { SegmentIndexTag, useSegmentListContext } from './completed' import { useSegmentListContext } from './completed'
import { SegmentIndexTag } from './completed/common/segment-index-tag'
import ActionButtons from './completed/common/action-buttons' import ActionButtons from './completed/common/action-buttons'
import Keywords from './completed/common/keywords' import Keywords from './completed/common/keywords'
import ChunkContent from './completed/common/chunk-content' import ChunkContent from './completed/common/chunk-content'
@ -41,7 +42,7 @@ const NewSegmentModal: FC<NewSegmentModalProps> = ({
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [addAnother, setAddAnother] = useState(true) const [addAnother, setAddAnother] = useState(true)
const [fullScreen, toggleFullScreen] = useSegmentListContext(s => [s.fullScreen, s.toggleFullScreen]) const [fullScreen, toggleFullScreen] = useSegmentListContext(s => [s.fullScreen, s.toggleFullScreen])
const [mode] = useDocumentContext(s => s.mode) const mode = useDocumentContext(s => s.mode)
const { appSidebarExpand } = useAppStore(useShallow(state => ({ const { appSidebarExpand } = useAppStore(useShallow(state => ({
appSidebarExpand: state.appSidebarExpand, appSidebarExpand: state.appSidebarExpand,
}))) })))

View File

@ -70,7 +70,8 @@ export const EditSlice: FC<EditSliceProps> = (props) => {
onMouseLeave={() => setDelBtnHover(false)} onMouseLeave={() => setDelBtnHover(false)}
> >
<ActionButton <ActionButton
onClick={() => { onClick={(e) => {
e.stopPropagation()
onDelete() onDelete()
setDelBtnShow(false) setDelBtnShow(false)
}} }}

View File

@ -2,7 +2,7 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { SegmentIndexTag } from '../../documents/detail/completed' import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
import type { HitTesting } from '@/models/datasets' import type { HitTesting } from '@/models/datasets'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type Props = { type Props = {

View File

@ -1,7 +1,7 @@
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { SegmentIndexTag } from '../documents/detail/completed' import { SegmentIndexTag } from '../documents/detail/completed/common/segment-index-tag'
import s from '../documents/detail/completed/style.module.css' import s from '../documents/detail/completed/style.module.css'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { SegmentDetailModel } from '@/models/datasets' import type { SegmentDetailModel } from '@/models/datasets'

View File

@ -44,6 +44,8 @@ const translation = {
openInNewTab: 'Open in new tab', openInNewTab: 'Open in new tab',
saveAndRegenerate: 'Save & Regenerate Child Chunks', saveAndRegenerate: 'Save & Regenerate Child Chunks',
close: 'Close', close: 'Close',
viewMore: 'VIEW MORE',
regenerate: 'Regenerate',
}, },
errorMsg: { errorMsg: {
fieldRequired: '{{field}} is required', fieldRequired: '{{field}} is required',

View File

@ -349,6 +349,7 @@ const translation = {
newTextSegment: 'New Text Segment', newTextSegment: 'New Text Segment',
newQaSegment: 'New Q&A Segment', newQaSegment: 'New Q&A Segment',
addChunk: 'Add Chunk', addChunk: 'Add Chunk',
addChildChunk: 'Add Child Chunk',
addAnother: 'Add another', addAnother: 'Add another',
delete: 'Delete this chunk ?', delete: 'Delete this chunk ?',
chunkAdded: '1 chunk added', chunkAdded: '1 chunk added',

View File

@ -44,6 +44,8 @@ const translation = {
openInNewTab: '在新标签页打开', openInNewTab: '在新标签页打开',
saveAndRegenerate: '保存并重新生成子分段', saveAndRegenerate: '保存并重新生成子分段',
close: '关闭', close: '关闭',
viewMore: '查看更多',
regenerate: '重新生成',
}, },
errorMsg: { errorMsg: {
fieldRequired: '{{field}} 为必填项', fieldRequired: '{{field}} 为必填项',

View File

@ -347,6 +347,7 @@ const translation = {
newTextSegment: '新文本分段', newTextSegment: '新文本分段',
newQaSegment: '新问答分段', newQaSegment: '新问答分段',
addChunk: '新增分段', addChunk: '新增分段',
addChildChunk: '新增子分段',
addAnother: '连续新增', addAnother: '连续新增',
delete: '删除这个分段?', delete: '删除这个分段?',
chunkAdded: '新增一个分段', chunkAdded: '新增一个分段',

View File

@ -624,7 +624,7 @@ export type ChildChunkDetail = {
type: ChildChunkType type: ChildChunkType
} }
export type ChildSegmentResponse = { export type ChildSegmentsResponse = {
data: ChildChunkDetail[] data: ChildChunkDetail[]
total: number total: number
total_pages: number total_pages: number

View File

@ -25,8 +25,6 @@ import type {
RelatedAppResponse, RelatedAppResponse,
SegmentDetailModel, SegmentDetailModel,
SegmentUpdater, SegmentUpdater,
SegmentsQuery,
SegmentsResponse,
createDocumentResponse, createDocumentResponse,
} from '@/models/datasets' } from '@/models/datasets'
import type { CreateKnowledgeBaseReq } from '@/app/components/datasets/external-knowledge-base/create/declarations' import type { CreateKnowledgeBaseReq } from '@/app/components/datasets/external-knowledge-base/create/declarations'
@ -180,19 +178,6 @@ export const modifyDocMetadata: Fetcher<CommonResponse, CommonDocReq & { body: {
} }
// apis for segments in a document // apis for segments in a document
export const fetchSegments: Fetcher<SegmentsResponse, CommonDocReq & { params: SegmentsQuery }> = ({ datasetId, documentId, params }) => {
return get<SegmentsResponse>(`/datasets/${datasetId}/documents/${documentId}/segments`, { params })
}
export const enableSegment: Fetcher<CommonResponse, { datasetId: string; segmentId: string }> = ({ datasetId, segmentId }) => {
return patch<CommonResponse>(`/datasets/${datasetId}/segments/${segmentId}/enable`)
}
export const disableSegment: Fetcher<CommonResponse, { datasetId: string; segmentId: string }> = ({ datasetId, segmentId }) => {
return patch<CommonResponse>(`/datasets/${datasetId}/segments/${segmentId}/disable`)
}
export const updateSegment: Fetcher<{ data: SegmentDetailModel; doc_form: string }, { datasetId: string; documentId: string; segmentId: string; body: SegmentUpdater }> = ({ datasetId, documentId, segmentId, body }) => { export const updateSegment: Fetcher<{ data: SegmentDetailModel; doc_form: string }, { datasetId: string; documentId: string; segmentId: string; body: SegmentUpdater }> = ({ datasetId, documentId, segmentId, body }) => {
return patch<{ data: SegmentDetailModel; doc_form: string }>(`/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}`, { body }) return patch<{ data: SegmentDetailModel; doc_form: string }>(`/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}`, { body })
} }

View File

@ -1,7 +1,7 @@
import { useMutation, useQuery } from '@tanstack/react-query' import { useMutation, useQuery } from '@tanstack/react-query'
import { del, get, patch } from '../base' import { del, get, patch, post } from '../base'
import type { CommonResponse } from '@/models/common' import type { CommonResponse } from '@/models/common'
import type { ChildSegmentResponse, SegmentsResponse } from '@/models/datasets' import type { ChildChunkDetail, ChildSegmentsResponse, SegmentsResponse } from '@/models/datasets'
const NAME_SPACE = 'segment' const NAME_SPACE = 'segment'
@ -65,7 +65,7 @@ export const useDeleteSegment = () => {
}) })
} }
const useChildSegmentListKey = [NAME_SPACE, 'childChunkList'] export const useChildSegmentListKey = [NAME_SPACE, 'childChunkList']
export const useChildSegmentList = ( export const useChildSegmentList = (
payload: { payload: {
@ -85,9 +85,29 @@ export const useChildSegmentList = (
return useQuery({ return useQuery({
queryKey: [...useChildSegmentListKey, datasetId, documentId, segmentId, page, limit, keyword], queryKey: [...useChildSegmentListKey, datasetId, documentId, segmentId, page, limit, keyword],
queryFn: () => { queryFn: () => {
return get<ChildSegmentResponse>(`/datasets/${datasetId}/documents/${documentId}/segment/${segmentId}/child_chunks`, { params }) return get<ChildSegmentsResponse>(`/datasets/${datasetId}/documents/${documentId}/segment/${segmentId}/child_chunks`, { params })
}, },
enabled: !disable, enabled: !disable,
initialData: disable ? { data: [], total: 0, page: 1, total_pages: 0, limit: 10 } : undefined, initialData: disable ? { data: [], total: 0, page: 1, total_pages: 0, limit: 10 } : undefined,
}) })
} }
export const useDeleteChildSegment = () => {
return useMutation({
mutationKey: [NAME_SPACE, 'childChunk', 'delete'],
mutationFn: (payload: { datasetId: string; documentId: string; segmentId: string; childChunkId: string }) => {
const { datasetId, documentId, segmentId, childChunkId } = payload
return del<CommonResponse>(`/datasets/${datasetId}/documents/${documentId}/segment/${segmentId}/child_chunks/${childChunkId}`)
},
})
}
export const useAddChildSegment = () => {
return useMutation({
mutationKey: [NAME_SPACE, 'childChunk', 'add'],
mutationFn: (payload: { datasetId: string; documentId: string; segmentId: string; body: { content: string } }) => {
const { datasetId, documentId, segmentId, body } = payload
return post<{ data: ChildChunkDetail }>(`/datasets/${datasetId}/documents/${documentId}/segment/${segmentId}/child_chunks`, { body })
},
})
}