feat:knowledge ui upgrade
This commit is contained in:
26
web/src/assets/images/CloudUploadOutlined.svg
Normal file
26
web/src/assets/images/CloudUploadOutlined.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 12</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-知识库-创建数据集-本地文件" transform="translate(-816, -184)">
|
||||
<g id="上传" transform="translate(252, 148)">
|
||||
<g id="编组-13" transform="translate(16, 16)">
|
||||
<g id="编组-12" transform="translate(548, 20)">
|
||||
<g id="编组-55" transform="translate(5, 2)">
|
||||
<path d="M4,0 L18.9462071,0 L18.9462071,0 L29,10 L29,34 C29,36.209139 27.209139,38 25,38 L4,38 C1.790861,38 0,36.209139 0,34 L0,4 C0,1.790861 1.790861,4.4408921e-16 4,0 Z" id="矩形" fill="#EBEBEB"></path>
|
||||
<path d="M19,0 L29,10 L21,10 C19.8954305,10 19,9.1045695 19,8 L19,0 L19,0 Z" id="矩形" fill="#A8A9AA"></path>
|
||||
<g id="编组-56" transform="translate(18, 23)">
|
||||
<circle id="椭圆形" fill="#171719" cx="11" cy="11" r="11"></circle>
|
||||
<g id="编组-54" transform="translate(6, 6)" stroke="#FFFFFF" stroke-linecap="round">
|
||||
<path d="M10,6 L10,7.5 C10,8.88071187 8.88071187,10 7.5,10 L2.5,10 C1.11928813,10 0,8.88071187 0,7.5 L0,6 L0,6" id="路径"></path>
|
||||
<line x1="5" y1="0.08499952" x2="5" y2="6.99635859" id="路径-24"></line>
|
||||
<polyline id="路径-25" stroke-linejoin="round" points="2 3 4.98005548 6.08298138e-18 8 3"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -240,10 +240,10 @@ const UploadFiles = forwardRef<UploadFilesRef, UploadFilesProps>(({
|
||||
|
||||
if (isCanDrag) {
|
||||
return (
|
||||
<div className="rb:mb-6 rb:w-full">
|
||||
<div className="rb:mb-6 rb:w-full rb:border rb:border-dashed rb:border-gray-900 rb:rounded-xl">
|
||||
<Dragger {...uploadProps} style={{ height: '270px' }}>
|
||||
<div className="rb:flex rb:justify-center rb:flex-col rb:items-center">
|
||||
<div className="rb:size-12 rb:bg-cover rb:bg-[url('@/assets/images/CloudUploadOutlined.png')]"></div>
|
||||
<div className="rb:size-12 rb:bg-cover rb:bg-[url('@/assets/images/CloudUploadOutlined.svg')]"></div>
|
||||
{(!isAutoUpload || !hasProgress && (!fileList || !fileList.length)) &&
|
||||
<>
|
||||
<div className="rb:text-base rb:text-[14px] rb:font-medium rb:flex rb:items-center rb:mt-2 rb:leading-5">
|
||||
|
||||
@@ -630,6 +630,7 @@ export const en = {
|
||||
documentInfo: 'Document Information',
|
||||
documentPreview:'Document Preview',
|
||||
type: 'Type',
|
||||
viewBasicInfo: 'View Basic Information',
|
||||
permission_id: 'Permission',
|
||||
status: 'Status',
|
||||
created_at: 'Created At',
|
||||
|
||||
@@ -133,6 +133,7 @@ export const zh = {
|
||||
documentInfo: '文档信息',
|
||||
documentPreview: '文档预览',
|
||||
type: '类型',
|
||||
viewBasicInfo:'查看基本信息',
|
||||
permission_id: '权限',
|
||||
status: '状态',
|
||||
created_at: '创建时间',
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useMemo,useRef, useState, useEffect } from 'react';
|
||||
import { Button, Flex, Radio, Steps, Modal, Input, Spin, message, Checkbox, Select, Form, Progress} from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import './Private.css';
|
||||
import Table, { type TableRef } from '@/components/Table'
|
||||
import type { AnyObject } from 'antd/es/_util/type';
|
||||
import type { UploadFileResponse,KnowledgeBaseDocumentData } from '@/views/KnowledgeBase/types';
|
||||
@@ -32,7 +33,7 @@ const { TextArea } = Input;
|
||||
};
|
||||
const getActiveRadioStyle = (active: boolean): React.CSSProperties => ({
|
||||
...radioWrapperBaseStyle,
|
||||
border: active ? '1px solid #1677ff' : radioWrapperBaseStyle.border,
|
||||
border: active ? '1px solid #171719' : radioWrapperBaseStyle.border,
|
||||
});
|
||||
|
||||
|
||||
@@ -549,7 +550,7 @@ const CreateDataset = () => {
|
||||
<>
|
||||
{contextHolder}
|
||||
|
||||
<div className='rb:p-6 rb:pt-2 rb:h-full'>
|
||||
<div className='rb:p-3 rb:pt-2 rb:h-full rb:flex rb:flex-col'>
|
||||
{/* <Typography.Title level={4} className='rb:!m-0 rb:!mb-4'>
|
||||
{t('knowledgeBase.createA') + ' ' + t('knowledgeBase.dataset')}
|
||||
</Typography.Title> */}
|
||||
@@ -557,298 +558,299 @@ const CreateDataset = () => {
|
||||
<img src={exitIcon} alt='exit' className='rb:w-4 rb:h-4' />
|
||||
<span className='rb:text-gray-500 rb:text-sm'>{t('common.exit')}</span>
|
||||
</div>
|
||||
<div className='rb:px-24 rb:py-5 rb:bg-[#FBFDFF] rb:rounded-lg rb:border rb:border-[#DFE4ED]'>
|
||||
<Steps current={current} items={steps} />
|
||||
<div className='rb:px-24 rb:py-5 rb:bg-white rb:rounded-lg'>
|
||||
<Steps current={current} items={steps} className="custom-steps" />
|
||||
</div>
|
||||
|
||||
<div className='rb:bg-white rb:rounded-lg rb:flex-1 rb:mt-3'>
|
||||
|
||||
{current === 0 && (
|
||||
<div className='rb:flex rb:w-full rb:mt-10'>
|
||||
{source && source === 'local' && (
|
||||
<UploadFiles
|
||||
ref={uploadRef}
|
||||
isCanDrag={true}
|
||||
fileSize={100}
|
||||
multiple={true}
|
||||
maxCount={99}
|
||||
fileType={fileType}
|
||||
customRequest={handleUpload}
|
||||
onChange={(fileList) => {
|
||||
console.log('File list changed:', fileList);
|
||||
}}
|
||||
onRemove={async (file) => {
|
||||
// 如果文件正在上传,取消上传
|
||||
const fileUid = file.uid;
|
||||
const abortController = abortControllersRef.current.get(fileUid);
|
||||
if (abortController) {
|
||||
abortController.abort();
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
console.log('Upload cancelled:', (file as any).name);
|
||||
// 取消上传后直接返回 true,允许移除文件
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only delete server file when file upload was successful (has response.id)
|
||||
if (file.response?.id) {
|
||||
try {
|
||||
await deleteDocument(file.response.id);
|
||||
setRechunkFileIds(prev => prev.filter(id => id !== file.response.id));
|
||||
console.log('Server file deleted:', file.response.id);
|
||||
{current === 0 && (
|
||||
<div className='rb:flex rb:w-full rb:p-6'>
|
||||
{source && source === 'local' && (
|
||||
<UploadFiles
|
||||
ref={uploadRef}
|
||||
isCanDrag={true}
|
||||
fileSize={100}
|
||||
multiple={true}
|
||||
maxCount={99}
|
||||
fileType={fileType}
|
||||
customRequest={handleUpload}
|
||||
onChange={(fileList) => {
|
||||
console.log('File list changed:', fileList);
|
||||
}}
|
||||
onRemove={async (file) => {
|
||||
// 如果文件正在上传,取消上传
|
||||
const fileUid = file.uid;
|
||||
const abortController = abortControllersRef.current.get(fileUid);
|
||||
if (abortController) {
|
||||
abortController.abort();
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
console.log('Upload cancelled:', (file as any).name);
|
||||
// 取消上传后直接返回 true,允许移除文件
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to delete file:', error);
|
||||
messageApi.error(t('common.deleteFailed') || 'Failed to delete file');
|
||||
return false; // Don't remove file when deletion fails
|
||||
}
|
||||
}
|
||||
|
||||
// Also allow removal in other cases (such as failed uploads)
|
||||
return true;
|
||||
}} />
|
||||
)}
|
||||
{source && source === 'link' && (
|
||||
<div className='rb:flex rb:w-full rb:flex-col rb:mt-10 rb:px-40'>
|
||||
|
||||
// Only delete server file when file upload was successful (has response.id)
|
||||
if (file.response?.id) {
|
||||
try {
|
||||
await deleteDocument(file.response.id);
|
||||
setRechunkFileIds(prev => prev.filter(id => id !== file.response.id));
|
||||
console.log('Server file deleted:', file.response.id);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to delete file:', error);
|
||||
messageApi.error(t('common.deleteFailed') || 'Failed to delete file');
|
||||
return false; // Don't remove file when deletion fails
|
||||
}
|
||||
}
|
||||
|
||||
// Also allow removal in other cases (such as failed uploads)
|
||||
return true;
|
||||
}} />
|
||||
)}
|
||||
{source && source === 'link' && (
|
||||
<div className='rb:flex rb:w-full rb:flex-col rb:mt-10 rb:px-40'>
|
||||
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.webLink')}
|
||||
</div>
|
||||
<TextArea rows={6} placeholder={t('knowledgeBase.webLinkPlaceholder')} />
|
||||
<div className='rb:text-sm rb:text-gray-500 rb:mt-3'>
|
||||
{t('knowledgeBase.webLinkDesc',{count: 5})}
|
||||
</div>
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mt-10 rb:mb-3'>
|
||||
{t('knowledgeBase.selectorTutorial')}
|
||||
</div>
|
||||
<Input className='rb:w-full' placeholder={t('knowledgeBase.webLinkPlaceholder')}/>
|
||||
</div>
|
||||
)}
|
||||
{source && source === 'text' && (
|
||||
<div className='rb:flex rb:w-full rb:flex-col rb:mt-10 rb:px-40'>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="title"
|
||||
label={t('knowledgeBase.title')}
|
||||
rules={[{ required: true, message: t('knowledgeBase.pleaseEnterTitle') }]}
|
||||
>
|
||||
<Input placeholder={t('knowledgeBase.pleaseEnterTitle')} />
|
||||
</Form.Item>
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.webLink')}
|
||||
</div>
|
||||
<TextArea rows={6} placeholder={t('knowledgeBase.webLinkPlaceholder')} />
|
||||
<div className='rb:text-sm rb:text-gray-500 rb:mt-3'>
|
||||
{t('knowledgeBase.webLinkDesc',{count: 5})}
|
||||
</div>
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mt-10 rb:mb-3'>
|
||||
{t('knowledgeBase.selectorTutorial')}
|
||||
</div>
|
||||
<Input className='rb:w-full' placeholder={t('knowledgeBase.webLinkPlaceholder')}/>
|
||||
</div>
|
||||
)}
|
||||
{source && source === 'text' && (
|
||||
<div className='rb:flex rb:w-full rb:flex-col rb:mt-10 rb:px-40'>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="title"
|
||||
label={t('knowledgeBase.title')}
|
||||
rules={[{ required: true, message: t('knowledgeBase.pleaseEnterTitle') }]}
|
||||
>
|
||||
<Input placeholder={t('knowledgeBase.pleaseEnterTitle')} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="content"
|
||||
label={t('knowledgeBase.customContent')}
|
||||
rules={[{ required: true, message: t('knowledgeBase.pleaseEnterContent') }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder={t('knowledgeBase.pleaseEnterContent')}
|
||||
rows={8}
|
||||
showCount
|
||||
maxLength={5000}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
{/* <div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.customText')}
|
||||
</div>
|
||||
<Input className='rb:w-full' placeholder={t('knowledgeBase.webLinkPlaceholder')}/>
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mt-10 rb:mb-3'>
|
||||
{t('knowledgeBase.customContent')}
|
||||
</div>
|
||||
<TextArea rows={6} placeholder={t('knowledgeBase.webLinkPlaceholder')} /> */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Form.Item
|
||||
name="content"
|
||||
label={t('knowledgeBase.customContent')}
|
||||
rules={[{ required: true, message: t('knowledgeBase.pleaseEnterContent') }]}
|
||||
>
|
||||
<Input.TextArea
|
||||
placeholder={t('knowledgeBase.pleaseEnterContent')}
|
||||
rows={8}
|
||||
showCount
|
||||
maxLength={5000}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
{/* <div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.customText')}
|
||||
</div>
|
||||
<Input className='rb:w-full' placeholder={t('knowledgeBase.webLinkPlaceholder')}/>
|
||||
<div className='rb:text-sm rb:font-medium rb:text-gray-800 rb:mt-10 rb:mb-3'>
|
||||
{t('knowledgeBase.customContent')}
|
||||
</div>
|
||||
<TextArea rows={6} placeholder={t('knowledgeBase.webLinkPlaceholder')} /> */}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{current === 1 && (
|
||||
<div className='rb:flex rb:flex-col rb:mt-10 rb:px-40'>
|
||||
{rechunkFileIds.length > 0 && (
|
||||
<div className='rb:bg-[#F0F3F8] rb:border rb:border-[#DFE4ED] rb:rounded rb:px-3 rb:py-2 rb:mb-4 rb:text-xs rb:text-gray-600 rb:flex rb:flex-wrap rb:gap-2'>
|
||||
<span className='rb:text-gray-700 rb:font-medium'>{t('knowledgeBase.rechunking')}:</span>
|
||||
{rechunkFileIds.map((id) => (
|
||||
<span key={id} className='rb:px-2 rb:py-0.5 rb:bg-white rb:border rb:border-[#DFE4ED] rb:rounded'>{id}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className='rb:text-base rb:font-medium rb:text-gray-800 rb:mt-4'>
|
||||
{t('knowledgeBase.fileParsingSettings')}
|
||||
</div>
|
||||
<div className='rb:mt-4'>
|
||||
<div
|
||||
className={`rb:flex rb:items-center rb:w-full rb:border rb:rounded-lg rb:p-4 rb:cursor-pointer ${
|
||||
pdfEnhancementEnabled ? 'rb:border-blue-500' : 'rb:border-gray-300'
|
||||
}`}
|
||||
// onClick={() => setPdfEnhancementEnabled(!pdfEnhancementEnabled)}
|
||||
>
|
||||
<Checkbox
|
||||
checked={pdfEnhancementEnabled}
|
||||
onChange={(e) => setPdfEnhancementEnabled(e.target.checked)}
|
||||
className='rb:mr-3'
|
||||
/>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800 rb:pl-[22px]'>
|
||||
{t('knowledgeBase.pdfEnhancementAnalysis')}
|
||||
</span>
|
||||
{pdfEnhancementEnabled && (
|
||||
<div className='rb:ml-10'>
|
||||
<Select
|
||||
value={pdfEnhancementMethod}
|
||||
onChange={(value) => setPdfEnhancementMethod(value)}
|
||||
className='rb:w-48'
|
||||
options={[
|
||||
{ value: 'deepdoc', label: 'DeepDoc' },
|
||||
{ value: 'mineru', label: 'MinerU' },
|
||||
{ value: 'textln', label: 'TextLN' }
|
||||
]}
|
||||
/>
|
||||
{current === 1 && (
|
||||
<div className='rb:flex rb:flex-col rb:py-6 rb:px-40'>
|
||||
{rechunkFileIds.length > 0 && (
|
||||
<div className='rb:bg-[#F0F3F8] rb:border rb:border-[#DFE4ED] rb:rounded rb:px-3 rb:py-2 rb:mb-4 rb:text-xs rb:text-gray-600 rb:flex rb:flex-wrap rb:gap-2'>
|
||||
<span className='rb:text-gray-700 rb:font-medium'>{t('knowledgeBase.rechunking')}:</span>
|
||||
{rechunkFileIds.map((id) => (
|
||||
<span key={id} className='rb:px-2 rb:py-0.5 rb:bg-white rb:border rb:border-[#DFE4ED] rb:rounded'>{id}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className='rb:text-base rb:font-medium rb:text-gray-800 rb:mt-4'>
|
||||
{t('knowledgeBase.fileParsingSettings')}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className='rb:text-base rb:font-medium rb:text-gray-800 rb:mt-6'>
|
||||
{t('knowledgeBase.dataProcessingSettings')}
|
||||
</div>
|
||||
<div className='rb:font-medium rb:text-gray-500 rb:mt-4 rb:mb-3'>
|
||||
{t('knowledgeBase.processingMethod')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
value={processingMethod}
|
||||
onChange={(e) => setProcessingMethod(e.target.value)}
|
||||
style={style}
|
||||
>
|
||||
<Radio value='directBlock' style={getActiveRadioStyle(processingMethod === 'directBlock')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.directBlock')}
|
||||
</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
<Radio value='qaExtract' style={getActiveRadioStyle(processingMethod === 'qaExtract')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.qaExtract')}
|
||||
</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
<div className='rb:font-medium rb:text-gray-500 rb:mt-4 rb:mb-3'>
|
||||
{t('knowledgeBase.parameterSettings')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
value={parameterSettings}
|
||||
onChange={(e) => setParameterSettings(e.target.value)}
|
||||
style={style}
|
||||
>
|
||||
<Radio value='defaultSettings' style={getActiveRadioStyle(parameterSettings === 'defaultSettings')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.default')}
|
||||
</span>
|
||||
<span className='rb:text-3 rb:text-gray-500'>{t('knowledgeBase.defaultSettings')}</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
<Radio value='customSettings' style={getActiveRadioStyle(parameterSettings === 'customSettings')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.customize')}
|
||||
</span>
|
||||
<span className='rb:text-3 rb:text-gray-500'>{t('knowledgeBase.customSettings')}</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
{parameterSettings === 'customSettings' && (
|
||||
<div className='rb:flex rb:flex-col rb:mt-5'>
|
||||
<div className='rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.delimiter')}
|
||||
<div className='rb:mt-4'>
|
||||
<div
|
||||
className={`rb:flex rb:items-center rb:w-full rb:border rb:rounded-lg rb:p-4 rb:cursor-pointer ${
|
||||
pdfEnhancementEnabled ? 'rb:border-gray-900' : 'rb:border-gray-300'
|
||||
}`}
|
||||
// onClick={() => setPdfEnhancementEnabled(!pdfEnhancementEnabled)}
|
||||
>
|
||||
<Checkbox
|
||||
checked={pdfEnhancementEnabled}
|
||||
onChange={(e) => setPdfEnhancementEnabled(e.target.checked)}
|
||||
className='rb:mr-3'
|
||||
/>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800 rb:pl-[22px]'>
|
||||
{t('knowledgeBase.pdfEnhancementAnalysis')}
|
||||
</span>
|
||||
{pdfEnhancementEnabled && (
|
||||
<div className='rb:ml-10'>
|
||||
<Select
|
||||
value={pdfEnhancementMethod}
|
||||
onChange={(value) => setPdfEnhancementMethod(value)}
|
||||
className='rb:w-48'
|
||||
options={[
|
||||
{ value: 'deepdoc', label: 'DeepDoc' },
|
||||
{ value: 'mineru', label: 'MinerU' },
|
||||
{ value: 'textln', label: 'TextLN' }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<DelimiterSelector value={delimiter} onChange={setDelimiter} className='rb:mb-5'/>
|
||||
<SliderInput label={t('knowledgeBase.suggestedBlockSize')} max={1024} min={1} step={1} value={blockSize} onChange={handleChange} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 暂时隐藏第三步:数据预览 */}
|
||||
{/* {current === stepIndexMap.dataPreview && (
|
||||
<div className='rb:grid rb:grid-cols-2 rb:rounded-xl rb:border rb:border-[#DFE4ED] rb:h-[calc(100%-160px)] rb:bg-[#FBFDFF] rb:mt-4'>
|
||||
<div className='rb:border-r rb:h-full rb:overflow-hidden rb:border-[#DFE4ED]'>
|
||||
<div className='rb:h-11 rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:px-4 rb:py-3 rb:border-b rb:border-[#DFE4ED]'>
|
||||
{t('knowledgeBase.fileList')}
|
||||
</div>
|
||||
<div className='rb:flex rb:flex-col rb:h-[calc(100%-44px)] rb:overflow-y-auto'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className={`rb:h-11 rb:w-full rb:text-sm rb:text-gray-800 rb:px-4 rb:py-3 rb:hover:text-[#155EEF] rb:cursor-pointer ${curSelectedFileId === index ? styles.textBg + ' ' + styles.active : ''}`}
|
||||
onClick={() => handlePreview(item, index)}>
|
||||
{item.file_name}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='rb:h-full rb:overflow-hidden'>
|
||||
<div className='rb:flex rb:items-center rb:justify-between rb:h-11 rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:px-4 rb:py-3 rb:border-b rb:border-[#DFE4ED]'>
|
||||
{t('knowledgeBase.dataPreview')}
|
||||
<span className='rb:text-sm rb:text-gray-500'>{t('knowledgeBase.maxPreviewChunks', {count: total, max: chunkData.length})}</span>
|
||||
</div>
|
||||
<Spin spinning={previewLoading}>
|
||||
<div className='rb:flex rb:flex-col rb:h-[calc(100%-44px)] rb:overflow-y-auto'>
|
||||
{chunkData.length > 0 ? (
|
||||
chunkData.map((item, index) => (
|
||||
<div key={index} className='rb:text-sm rb:text-gray-800 rb:px-4 rb:py-3'
|
||||
dangerouslySetInnerHTML={{ __html: item.page_content }}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<NoData title={t('knowledgeBase.noChunksToPreview')}
|
||||
subTitle={t('knowledgeBase.clickToPreview')}
|
||||
image={noDataIcon}
|
||||
/>
|
||||
)}
|
||||
<div className='rb:text-base rb:font-medium rb:text-gray-800 rb:mt-6'>
|
||||
{t('knowledgeBase.dataProcessingSettings')}
|
||||
</div>
|
||||
<div className='rb:font-medium rb:text-gray-500 rb:mt-4 rb:mb-3'>
|
||||
{t('knowledgeBase.processingMethod')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
value={processingMethod}
|
||||
onChange={(e) => setProcessingMethod(e.target.value)}
|
||||
style={style}
|
||||
>
|
||||
<Radio value='directBlock' style={getActiveRadioStyle(processingMethod === 'directBlock')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.directBlock')}
|
||||
</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
<Radio value='qaExtract' style={getActiveRadioStyle(processingMethod === 'qaExtract')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.qaExtract')}
|
||||
</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
<div className='rb:font-medium rb:text-gray-500 rb:mt-4 rb:mb-3'>
|
||||
{t('knowledgeBase.parameterSettings')}
|
||||
</div>
|
||||
<Radio.Group
|
||||
value={parameterSettings}
|
||||
onChange={(e) => setParameterSettings(e.target.value)}
|
||||
style={style}
|
||||
>
|
||||
<Radio value='defaultSettings' style={getActiveRadioStyle(parameterSettings === 'defaultSettings')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.default')}
|
||||
</span>
|
||||
<span className='rb:text-3 rb:text-gray-500'>{t('knowledgeBase.defaultSettings')}</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
<Radio value='customSettings' style={getActiveRadioStyle(parameterSettings === 'customSettings')}>
|
||||
<Flex gap='small' vertical>
|
||||
<span className='rb:text-base rb:font-medium rb:text-gray-800'>
|
||||
{t('knowledgeBase.customize')}
|
||||
</span>
|
||||
<span className='rb:text-3 rb:text-gray-500'>{t('knowledgeBase.customSettings')}</span>
|
||||
</Flex>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
{parameterSettings === 'customSettings' && (
|
||||
<div className='rb:flex rb:flex-col rb:mt-5'>
|
||||
<div className='rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:mb-3'>
|
||||
{t('knowledgeBase.delimiter')}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
{current === 2 && (
|
||||
// <Spin spinning={pollingLoading} tip={t('knowledgeBase.processingDocuments') || '正在处理文档...'}>
|
||||
<div className='rb:text-sm rb:text-gray-500 rb:mt-4 rb:h-[calc(100%-160px)] rb:overflow-y-auto'>
|
||||
{rechunkFileIds.length > 0 ? (
|
||||
<Table
|
||||
ref={tableRef}
|
||||
apiUrl={`/documents/${knowledgeBaseId}/documents`}
|
||||
apiParams={{
|
||||
document_ids: rechunkFileIds.join(','),
|
||||
}}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
/>
|
||||
) : (
|
||||
<Table
|
||||
ref={tableRef}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
initialData={[]}
|
||||
/>
|
||||
)}
|
||||
<DelimiterSelector value={delimiter} onChange={setDelimiter} className='rb:mb-5'/>
|
||||
<SliderInput label={t('knowledgeBase.suggestedBlockSize')} max={1024} min={1} step={1} value={blockSize} onChange={handleChange} />
|
||||
</div>
|
||||
|
||||
)}
|
||||
</div>
|
||||
// </Spin>
|
||||
)}
|
||||
|
||||
<div className={`rb:flex rb:gap-3 rb:mt-6 ${current === 1 || (source == 'link' && current === 0) || (source == 'text' && current === 0) ? 'rb:pl-40 rb:mt-10' : ''}`}>
|
||||
{current !== 0 && (
|
||||
<Button onClick={handlePrev} disabled={current === 0 || pollingLoading}>
|
||||
{t('common.previous') || 'Prev'}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type='primary'
|
||||
onClick={current === 2 ? handleStartUpload : handleNext}
|
||||
disabled={pollingLoading || (current === 0 && rechunkFileIds.length === 0)}
|
||||
>
|
||||
{current === 2 ? t('knowledgeBase.startUploading') || 'Start Upload' : t('common.next') || 'Next'}
|
||||
</Button>
|
||||
|
||||
{/* 暂时隐藏第三步:数据预览 */}
|
||||
{/* {current === stepIndexMap.dataPreview && (
|
||||
<div className='rb:grid rb:grid-cols-2 rb:rounded-xl rb:border rb:border-[#DFE4ED] rb:h-[calc(100%-160px)] rb:bg-[#FBFDFF] rb:mt-4'>
|
||||
<div className='rb:border-r rb:h-full rb:overflow-hidden rb:border-[#DFE4ED]'>
|
||||
<div className='rb:h-11 rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:px-4 rb:py-3 rb:border-b rb:border-[#DFE4ED]'>
|
||||
{t('knowledgeBase.fileList')}
|
||||
</div>
|
||||
<div className='rb:flex rb:flex-col rb:h-[calc(100%-44px)] rb:overflow-y-auto'>
|
||||
{data.map((item, index) => (
|
||||
<div key={index} className={`rb:h-11 rb:w-full rb:text-sm rb:text-gray-800 rb:px-4 rb:py-3 rb:hover:text-[#155EEF] rb:cursor-pointer ${curSelectedFileId === index ? styles.textBg + ' ' + styles.active : ''}`}
|
||||
onClick={() => handlePreview(item, index)}>
|
||||
{item.file_name}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='rb:h-full rb:overflow-hidden'>
|
||||
<div className='rb:flex rb:items-center rb:justify-between rb:h-11 rb:w-full rb:text-sm rb:font-medium rb:text-gray-800 rb:px-4 rb:py-3 rb:border-b rb:border-[#DFE4ED]'>
|
||||
{t('knowledgeBase.dataPreview')}
|
||||
<span className='rb:text-sm rb:text-gray-500'>{t('knowledgeBase.maxPreviewChunks', {count: total, max: chunkData.length})}</span>
|
||||
</div>
|
||||
<Spin spinning={previewLoading}>
|
||||
<div className='rb:flex rb:flex-col rb:h-[calc(100%-44px)] rb:overflow-y-auto'>
|
||||
{chunkData.length > 0 ? (
|
||||
chunkData.map((item, index) => (
|
||||
<div key={index} className='rb:text-sm rb:text-gray-800 rb:px-4 rb:py-3'
|
||||
dangerouslySetInnerHTML={{ __html: item.page_content }}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<NoData title={t('knowledgeBase.noChunksToPreview')}
|
||||
subTitle={t('knowledgeBase.clickToPreview')}
|
||||
image={noDataIcon}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</div>
|
||||
)} */}
|
||||
|
||||
{current === 2 && (
|
||||
// <Spin spinning={pollingLoading} tip={t('knowledgeBase.processingDocuments') || '正在处理文档...'}>
|
||||
<div className='rb:text-sm rb:text-gray-500 rb:mt-4 rb:h-[calc(100%-160px)] rb:overflow-y-auto rb:px-6 rb:py-6'>
|
||||
{rechunkFileIds.length > 0 ? (
|
||||
<Table
|
||||
ref={tableRef}
|
||||
apiUrl={`/documents/${knowledgeBaseId}/documents`}
|
||||
apiParams={{
|
||||
document_ids: rechunkFileIds.join(','),
|
||||
}}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
/>
|
||||
) : (
|
||||
<Table
|
||||
ref={tableRef}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
initialData={[]}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
// </Spin>
|
||||
)}
|
||||
|
||||
<div className={`rb:flex rb:p-6 rb:gap-3 rb:mt-6 ${current === 1 || (source == 'link' && current === 0) || (source == 'text' && current === 0) ? 'rb:pl-40 rb:mt-10' : ''}`}>
|
||||
{current !== 0 && (
|
||||
<Button onClick={handlePrev} disabled={current === 0 || pollingLoading}>
|
||||
{t('common.previous') || 'Prev'}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type='primary'
|
||||
onClick={current === 2 ? handleStartUpload : handleNext}
|
||||
disabled={pollingLoading || (current === 0 && rechunkFileIds.length === 0)}
|
||||
>
|
||||
{current === 2 ? t('knowledgeBase.startUploading') || 'Start Upload' : t('common.next') || 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
.customTree .ant-tree-node-content-wrapper {
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
color: #171719 !important;
|
||||
height: 40px !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
@@ -28,15 +29,18 @@
|
||||
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper:before,
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper:hover:before {
|
||||
background: #FFFFFF !important;
|
||||
background: #171719 !important;
|
||||
}
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper,
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper:hover{
|
||||
color: #000 !important;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher,
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-draggable-icon{
|
||||
color: #000;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.customTree.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher img {
|
||||
filter: brightness(0) invert(1) !important;
|
||||
}
|
||||
.customTree .ant-tree-switcher {
|
||||
display: flex !important;
|
||||
@@ -111,3 +115,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/* Steps 已完成步骤圆内字体颜色 */
|
||||
.custom-steps .ant-steps-item-finish .ant-steps-item-icon .ant-steps-icon {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
@@ -530,7 +530,7 @@ const Private: FC = () => {
|
||||
const document = record as KnowledgeBaseDocumentData;
|
||||
return (
|
||||
<span
|
||||
className="rb:text-blue-600 rb:cursor-pointer rb:hover:underline"
|
||||
className="rb:text-gray-900 rb:font-medium rb:cursor-pointer rb:hover:underline"
|
||||
onClick={() => {
|
||||
if (knowledgeBaseId && document.id) {
|
||||
navigate(`/knowledge-base/${knowledgeBaseId}/DocumentDetails`,{
|
||||
@@ -765,9 +765,9 @@ const Private: FC = () => {
|
||||
return (
|
||||
<>
|
||||
{contextHolder}
|
||||
<div className="rb:flex rb:h-full rb:gap-4">
|
||||
<div className="rb:flex rb:h-full rb:bg-white rb:rounded-xl">
|
||||
{folder && (
|
||||
<div className="rb:w-64 rb:flex-shrink-0 rb:h-[calc(100%+40px)] rb:mt-[-16px] rb:border-r rb:border-[#EAECEE] rb:p-4 rb:bg-transparent">
|
||||
<div className="rb:w-64 rb:py-4 rb:flex-shrink-0 rb:h-[calc(100%+40px)] rb:border-r rb:border-[#EAECEE] rb:p-4 rb:bg-transparent">
|
||||
<FolderTree
|
||||
multiple
|
||||
className="customTree"
|
||||
@@ -783,7 +783,7 @@ const Private: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className='rb:flex-1 rb:min-w-0'>
|
||||
<div className='rb:flex-1 rb:min-w-0 rb:p-4'>
|
||||
<div className="rb:flex rb:items-center rb:justify-between rb:mb-4">
|
||||
|
||||
<div className="rb:flex-col">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState, useRef, type FC } from 'react';
|
||||
import { useParams, useLocation } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Popover } from 'antd';
|
||||
import type { KnowledgeBaseListItem, RecallTestDrawerRef } from '@/views/KnowledgeBase/types';
|
||||
import RecallTest from '../components/RecallTest';
|
||||
import InfoPanel, { type InfoItem } from '../components/InfoPanel';
|
||||
@@ -27,7 +28,7 @@ const Share: FC = () => {
|
||||
const recallTestRef = useRef<RecallTestDrawerRef>(null);
|
||||
const [infoItems, setInfoItems] = useState<InfoItem[]>([]);
|
||||
const [knowledgeBaseFolderPath, setKnowledgeBaseFolderPath] = useState<BreadcrumbItem[]>([]);
|
||||
|
||||
const [viewInfo,setViewInfo] = useState<boolean>(false);
|
||||
const { updateBreadcrumbs } = useBreadcrumbManager({
|
||||
breadcrumbType: 'detail'
|
||||
});
|
||||
@@ -160,7 +161,17 @@ const Share: FC = () => {
|
||||
<span className='rb:text-gray-500 rb:text-sm rb:ml-2 rb:font-normal'>(ID: {knowledgeBase.id})</span></h1>
|
||||
|
||||
{/* <p className="rb:text-gray-600 rb:mt-2">{knowledgeBase.description || t('knowledgeBase.noDescription')}</p> */}
|
||||
<span className='rb:text-gray-800 rb:text-xs rb:border rb:border-[#369F21] rb:bg-[rgba(54,159,33,0.2)] rb:px-1 rb:py-[2px] rb:rounded'>{knowledgeBase.permission_id}</span>
|
||||
<span className='rb:text-white rb:text-xs rb:bg-blue-500 rb:px-1 rb:py-[2px] rb:rounded'>{knowledgeBase.permission_id}</span>
|
||||
<Popover
|
||||
content={<InfoPanel title={t('knowledgeBase.knowledgeBaseInfo')} items={infoItems} />}
|
||||
trigger="hover"
|
||||
placement="bottomLeft"
|
||||
arrow={false}
|
||||
>
|
||||
<span
|
||||
className='rb:border rb:border-[#171719] rb:px-1 rb:py-[2px] rb:rounded rb:text-gray-900 rb:text-xs rb:cursor-pointer'
|
||||
>{t('knowledgeBase.viewBasicInfo')}</span>
|
||||
</Popover>
|
||||
</div>
|
||||
<div className="rb:flex rb:w-full rb:items-center rb:mb-5 rb:gap-2">
|
||||
<img src={shareUserIcon} className='rb:size-4 rb:ml-2' />
|
||||
@@ -178,15 +189,11 @@ const Share: FC = () => {
|
||||
<RecallTest ref={recallTestRef} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='rb:w-80 rb:border rb:overflow-y-auto rb:border-[#DFE4ED] rb:bg-white rb:rounded-xl rb:p-4'>
|
||||
<InfoPanel
|
||||
title={t('knowledgeBase.knowledgeBaseInfo')}
|
||||
items={infoItems}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className='rb:w-80 rb:border rb:overflow-y-auto rb:border-[#DFE4ED] rb:bg-white rb:rounded-xl rb:p-4'>
|
||||
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -270,8 +270,8 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
<Col span={24}>
|
||||
<RbCard
|
||||
title={t('knowledgeBase.knowledgeGraph')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:text-[18px]! rb:leading-[24px]"
|
||||
variant="outlined"
|
||||
headerClassName="rb:text-sm! rb:leading-11 rb:bg-[#FAFAFA]! rb:w-full rb:ml-0! rb:px-3!"
|
||||
>
|
||||
<div className="rb:h-124 rb:relative">
|
||||
{loading ? (
|
||||
@@ -435,7 +435,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="rb:bg-[#F0F3F8] rb:flex rb:items-center rb:gap-6 rb:rounded-[0px_0px_12px_12px] rb:p-[14px_40px] rb:m-[0_-20px_-16px_-16px]">
|
||||
<div className="rb:bg-[#FAFAFA] rb:border-box rb:border-t rb:border-gray-200 rb:flex rb:items-center rb:justify-between rb:gap-6 rb:rounded-[0px_0px_12px_12px] rb:p-[14px_40px] rb:m-[0_-16px_-20px_-16px]">
|
||||
{operations.map((item) => (
|
||||
<div key={item.name} className="rb:flex rb:items-center rb:text-[#5B6167] rb:leading-5">
|
||||
<img src={item.icon} className="rb:w-5 rb:h-5 rb:mr-1" />
|
||||
|
||||
@@ -108,11 +108,11 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
<span className='rb:text-[#155eef]'>{ t('knowledgeBase.loadSampleQuestions')}</span>
|
||||
</div> */}
|
||||
</div>
|
||||
<Form form={form} >
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item name="query">
|
||||
<TextArea rows={4} placeholder={t('knowledgeBase.testQuestionPlaceholder')}/>
|
||||
</Form.Item>
|
||||
<div className='rb:grid rb:grid-cols-2 rb:gap-x-4'>
|
||||
<div className='rb:grid rb:grid-cols-5 rb:gap-x-4'>
|
||||
<Form.Item
|
||||
name="retrieve_type"
|
||||
label={t('knowledgeBase.retrieveMode')}
|
||||
@@ -179,7 +179,7 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
{/* <Form.Item name="hybrid" valuePropName="checked" initialValue={true} label={t('knowledgeBase.hybrid') || 'Hybrid'}>
|
||||
<Switch checkedChildren={t('common.yes') || 'Yes'} unCheckedChildren={t('common.no') || 'No'} />
|
||||
</Form.Item> */}
|
||||
<Form.Item>
|
||||
<Form.Item className="rb:flex rb:items-end rb:justify-end">
|
||||
<Button type="primary" onClick={handleStartTest} loading={loading}>{ t('knowledgeBase.startTesting')}</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import { forwardRef, useImperativeHandle, useState, useRef, useLayoutEffect, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import RbDrawer from '@/components/RbDrawer';
|
||||
@@ -51,6 +50,7 @@ const RecallTestDrawer = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
title={t('knowledgeBase.recallTest')}
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
width={1000}
|
||||
>
|
||||
<RecallTest ref={setRecallTestRef} />
|
||||
</RbDrawer>
|
||||
|
||||
@@ -169,7 +169,7 @@ const RecallTestResult = ({
|
||||
return (
|
||||
<div
|
||||
key={`${item.metadata?.sort_id || index}-${index}`}
|
||||
className={`rb:flex rb:flex-col rb:mb-4 rb:rounded-lg rb:border rb:border-[#DFE4ED] rb:bg-[#FBFDFF] rb:p-4 rb:pt-2 rb:pb-3 rb:relative rb:group ${editable ? 'rb:cursor-pointer rb:transition-all hover:rb:border-[#155EEF] hover:rb:shadow-md' : ''}`}
|
||||
className={`rb:flex rb:flex-col rb:mb-4 rb:rounded-xl rb:bg-[#F6F6F6] rb:p-4 rb:pt-2 rb:pb-3 rb:relative rb:group ${editable ? 'rb:cursor-pointer rb:transition-all hover:rb:border-[#155EEF] hover:rb:shadow-md' : ''}`}
|
||||
onClick={(e) => handleItemClick(e, item, index)}
|
||||
>
|
||||
{editable && (
|
||||
@@ -183,16 +183,16 @@ const RecallTestResult = ({
|
||||
{scorePercentage.toFixed(1)}% {t('knowledgeBase.similarity')}
|
||||
</span>
|
||||
)}
|
||||
<div className={`rb:flex rb:mt-2 rb:flex-col rb:items-end rb:justify-end rb:gap-1 ${!showScore ? 'rb:w-full' : ''}`}>
|
||||
<div className={`rb:flex rb:mt-2 rb:flex rb:items-end rb:justify-end rb:gap-4 ${!showScore ? 'rb:w-full' : ''}`}>
|
||||
<span className='rb:text-gray-800'>
|
||||
<FileOutlined /> {item.metadata?.file_name || '-'}
|
||||
</span>
|
||||
<span className='rb:text-gray-500 rb:text-xs rb:bg-[#F0F3F8] rb:px-1 rb:py-[2px] rb:rounded'>
|
||||
<span className='rb:text-gray-500 rb:text-xs rb:bg-[#DFDFDF] rb:px-1 rb:py-[2px] rb:rounded'>
|
||||
chunk_{item.metadata?.sort_id || index}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='rb:flex rb:text-left rb:px-4 rb:py-3 rb:bg-[#F0F3F8] rb:rounded-lg rb:mt-2'>
|
||||
<div className='rb:flex rb:text-left rb:px-4 rb:py-3 rb:bg-white rb:rounded-lg rb:mt-2'>
|
||||
<div className='rb:text-gray-800 rb:text-sm rb:whitespace-pre-wrap rb:break-words rb:w-full'>
|
||||
{(() => {
|
||||
const qaContent = parseQAContent(item.page_content);
|
||||
|
||||
Reference in New Issue
Block a user