feat(web): show ids
This commit is contained in:
@@ -24,6 +24,7 @@ export interface TagProps {
|
|||||||
/** Additional CSS classes */
|
/** Additional CSS classes */
|
||||||
className?: string;
|
className?: string;
|
||||||
variant?: 'outline' | 'borderless'
|
variant?: 'outline' | 'borderless'
|
||||||
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Color theme mappings with text, border, and background colors */
|
/** Color theme mappings with text, border, and background colors */
|
||||||
@@ -38,9 +39,9 @@ const colors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Custom tag component with color themes */
|
/** Custom tag component with color themes */
|
||||||
const Tag: FC<TagProps> = ({ color = 'processing', children, className, variant = 'outline' }) => {
|
const Tag: FC<TagProps> = ({ color = 'processing', children, className, variant = 'outline', onClick }) => {
|
||||||
return (
|
return (
|
||||||
<span className={`rb:inline-block rb:px-1 rb:py-0.5 rb:rounded-sm rb:text-[12px] rb:font-regular! rb:leading-4 rb:border ${colors[color]} ${className || ''} ${variant === 'borderless' ? 'rb:border-none!' : ''}`}>
|
<span onClick={onClick} className={`rb:inline-block rb:px-1 rb:py-0.5 rb:rounded-sm rb:text-[12px] rb:font-regular! rb:leading-4 rb:border ${colors[color]} ${className || ''} ${variant === 'borderless' ? 'rb:border-none!' : ''}`}>
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useEffect, useState, useRef, type FC } from 'react';
|
|||||||
import { useNavigate, useParams, useLocation, useSearchParams } from 'react-router-dom';
|
import { useNavigate, useParams, useLocation, useSearchParams } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBreadcrumbManager, type BreadcrumbPath } from '@/hooks/useBreadcrumbManager';
|
import { useBreadcrumbManager, type BreadcrumbPath } from '@/hooks/useBreadcrumbManager';
|
||||||
import { Button, Spin, message, Switch } from 'antd';
|
import { Button, Spin, message, Switch, App } from 'antd';
|
||||||
import { getDocumentDetail, getDocumentChunkList, downloadFile, updateDocument, updateDocumentChunk, createDocumentChunk, getFileUrl } from '@/api/knowledgeBase';
|
import { getDocumentDetail, getDocumentChunkList, downloadFile, updateDocument, updateDocumentChunk, createDocumentChunk, getFileUrl } from '@/api/knowledgeBase';
|
||||||
import type { KnowledgeBaseDocumentData, RecallTestData } from '@/views/KnowledgeBase/types';
|
import type { KnowledgeBaseDocumentData, RecallTestData } from '@/views/KnowledgeBase/types';
|
||||||
import { formatDateTime } from '@/utils/format';
|
import { formatDateTime } from '@/utils/format';
|
||||||
@@ -21,9 +21,11 @@ import DocumentPreview from '@/components/DocumentPreview';
|
|||||||
import InsertModal, { type InsertModalRef } from '../components/InsertModal';
|
import InsertModal, { type InsertModalRef } from '../components/InsertModal';
|
||||||
import exitIcon from '@/assets/images/knowledgeBase/exit.png';
|
import exitIcon from '@/assets/images/knowledgeBase/exit.png';
|
||||||
const imagePath = 'https://devapi.mem.redbearai.com'
|
const imagePath = 'https://devapi.mem.redbearai.com'
|
||||||
|
import copy from 'copy-to-clipboard'
|
||||||
const DocumentDetails: FC = () => {
|
const DocumentDetails: FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { message: messageApi } = App.useApp()
|
||||||
const { knowledgeBaseId } = useParams<{ knowledgeBaseId: string }>();
|
const { knowledgeBaseId } = useParams<{ knowledgeBaseId: string }>();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { updateBreadcrumbs } = useBreadcrumbManager({
|
const { updateBreadcrumbs } = useBreadcrumbManager({
|
||||||
@@ -100,9 +102,25 @@ const DocumentDetails: FC = () => {
|
|||||||
}, [keywords]);
|
}, [keywords]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleCopy = (value?: string) => {
|
||||||
|
if (!value) return
|
||||||
|
copy(value)
|
||||||
|
messageApi.success(t('common.copySuccess'))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const formatDocumentInfo = (doc: KnowledgeBaseDocumentData): InfoItem[] => {
|
const formatDocumentInfo = (doc: KnowledgeBaseDocumentData): InfoItem[] => {
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
key: 'file_id',
|
||||||
|
label: 'ID',
|
||||||
|
value: <span onClick={() => handleCopy(doc.file_id)}>
|
||||||
|
{doc.file_id}
|
||||||
|
<span
|
||||||
|
className="rb:cursor-pointer rb:-mb-0.5 rb:ml-1 rb:inline-block rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"
|
||||||
|
></span>
|
||||||
|
</span>,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'file_name',
|
key: 'file_name',
|
||||||
label: t('knowledgeBase.fileName') || '文件名',
|
label: t('knowledgeBase.fileName') || '文件名',
|
||||||
@@ -387,7 +405,7 @@ const DocumentDetails: FC = () => {
|
|||||||
<div className="rb:flex rb:h-full rb:flex-1 rb:overflow-hidden rb:bg-white rb:rounded-xl rb:border rb:border-[#DFE4ED]">
|
<div className="rb:flex rb:h-full rb:flex-1 rb:overflow-hidden rb:bg-white rb:rounded-xl rb:border rb:border-[#DFE4ED]">
|
||||||
{/* Left: Document info */}
|
{/* Left: Document info */}
|
||||||
<div className='rb:w-80 rb:h-full rb:flex rb:flex-col rb:gap-4 rb:overflow-hidden'>
|
<div className='rb:w-80 rb:h-full rb:flex rb:flex-col rb:gap-4 rb:overflow-hidden'>
|
||||||
<div className='rb:h-full rb:border-r rb:border-[#DFE4ED] rb:p-4'>
|
<div className='rb:h-full rb:border-r rb:border-[#DFE4ED] rb:p-4 rb:overflow-y-auto'>
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
title={t('knowledgeBase.documentInfo') || '文档信息'}
|
title={t('knowledgeBase.documentInfo') || '文档信息'}
|
||||||
items={infoItems}
|
items={infoItems}
|
||||||
@@ -417,6 +435,7 @@ const DocumentDetails: FC = () => {
|
|||||||
editable={true}
|
editable={true}
|
||||||
onItemClick={handleChunkClick}
|
onItemClick={handleChunkClick}
|
||||||
parserMode={parserMode}
|
parserMode={parserMode}
|
||||||
|
handleCopy={handleCopy}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import { formatDateTime } from '@/utils/format';
|
|||||||
import KnowledgeGraphCard from '../components/KnowledgeGraphCard';
|
import KnowledgeGraphCard from '../components/KnowledgeGraphCard';
|
||||||
import { useBreadcrumbManager, type BreadcrumbItem } from '@/hooks/useBreadcrumbManager';
|
import { useBreadcrumbManager, type BreadcrumbItem } from '@/hooks/useBreadcrumbManager';
|
||||||
import './Private.css'
|
import './Private.css'
|
||||||
|
import Tag from '@/components/Tag'
|
||||||
|
import copy from 'copy-to-clipboard'
|
||||||
// Tree node data type
|
// Tree node data type
|
||||||
|
|
||||||
const Private: FC = () => {
|
const Private: FC = () => {
|
||||||
@@ -570,7 +572,7 @@ const Private: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<span className="rb:text-xs rb:border rb:border-[#DFE4ED] rb:bg-[#FBFDFF] rb:rounded rb:items-center rb:text-[#212332] rb:py-1 rb:px-2">
|
<span className="rb:text-xs rb:border rb:border-[#DFE4ED] rb:bg-[#FBFDFF] rb:rounded rb:items-center rb:text-[#212332] rb:py-1 rb:px-2">
|
||||||
<span
|
<span
|
||||||
className="rb:inline-block rb:w-[5px] rb:h-[5px] rb:mr-2 rb:rounded-full"
|
className="rb:inline-block rb:w-1.25 rb:h-1.25 rb:mr-2 rb:rounded-full"
|
||||||
style={{ backgroundColor: value === 1 ? '#369F21' : value === 0 ? '#FF0000' : '#FF8A4C' }}
|
style={{ backgroundColor: value === 1 ? '#369F21' : value === 0 ? '#FF0000' : '#FF8A4C' }}
|
||||||
></span>
|
></span>
|
||||||
<span>{value === 1 ? t('knowledgeBase.completed') : value === 0 ? t('knowledgeBase.pending') : t('knowledgeBase.processing')}</span>
|
<span>{value === 1 ? t('knowledgeBase.completed') : value === 0 ? t('knowledgeBase.pending') : t('knowledgeBase.processing')}</span>
|
||||||
@@ -613,6 +615,7 @@ const Private: FC = () => {
|
|||||||
title: t('knowledgeBase.processingMode'),
|
title: t('knowledgeBase.processingMode'),
|
||||||
dataIndex: 'parser_id',
|
dataIndex: 'parser_id',
|
||||||
key: 'parser_id',
|
key: 'parser_id',
|
||||||
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('knowledgeBase.dataSize'),
|
title: t('knowledgeBase.dataSize'),
|
||||||
@@ -629,6 +632,11 @@ const Private: FC = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t('common.operation'),
|
title: t('common.operation'),
|
||||||
@@ -762,11 +770,16 @@ const Private: FC = () => {
|
|||||||
setIsSyncing(false);
|
setIsSyncing(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCopy = (value: string) => {
|
||||||
|
copy(value)
|
||||||
|
messageApi.success(t('common.copySuccess'))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="rb:flex rb:h-full rb:bg-white rb:rounded-xl">
|
<div className="rb:flex rb:h-full rb:bg-white rb:rounded-xl">
|
||||||
{folder && (
|
{folder && (
|
||||||
<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">
|
<div className="rb:w-64 rb:py-4 rb:shrink-0 rb:h-[calc(100%+40px)] rb:border-r rb:border-[#EAECEE] rb:p-4 rb:bg-transparent">
|
||||||
<FolderTree
|
<FolderTree
|
||||||
multiple
|
multiple
|
||||||
className="customTree"
|
className="customTree"
|
||||||
@@ -791,11 +804,15 @@ const Private: FC = () => {
|
|||||||
<div className="rb:flex rb:items-center rb:border rb:border-[rgba(33, 35, 50, 0.17)] rb:text-gray-500 rb:cursor-pointer rb:px-1 rb:py-0.5 rb:rounded"
|
<div className="rb:flex rb:items-center rb:border rb:border-[rgba(33, 35, 50, 0.17)] rb:text-gray-500 rb:cursor-pointer rb:px-1 rb:py-0.5 rb:rounded"
|
||||||
onClick={handleEditFolder}
|
onClick={handleEditFolder}
|
||||||
>
|
>
|
||||||
<img src={editIcon} alt="edit" className="rb:w-[14px] rb:h-[14px" />
|
<img src={editIcon} alt="edit" className="rb:w-3.5 rb:h-[14px" />
|
||||||
<span className='rb:text-[12px]'>{t('knowledgeBase.edit')} {t('knowledgeBase.name')}</span>
|
<span className='rb:text-[12px]'>{t('knowledgeBase.edit')} {t('knowledgeBase.name')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='rb:flex rb:items-center rb:gap-6 rb:text-gray-500 rb:mt-2 rb:text-xs'>
|
<div className='rb:flex rb:items-center rb:gap-6 rb:text-gray-500 rb:mt-2 rb:text-xs'>
|
||||||
|
<Tag variant="borderless" color="default" className="rb:cursor-pointer" onClick={() => handleCopy(knowledgeBase.id)}>
|
||||||
|
ID: {knowledgeBase.id}
|
||||||
|
<span className="rb:-mb-0.5 rb:ml-1 rb:inline-block rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"></span>
|
||||||
|
</Tag>
|
||||||
<span className='rb:text-[12px]'>{t('knowledgeBase.created')} {t('knowledgeBase.time')}: {formatDateTime(knowledgeBase.created_at) || '-'}</span>
|
<span className='rb:text-[12px]'>{t('knowledgeBase.created')} {t('knowledgeBase.time')}: {formatDateTime(knowledgeBase.created_at) || '-'}</span>
|
||||||
<span className='rb:text-[12px]'>{t('knowledgeBase.updated')} {t('knowledgeBase.time')}: {formatDateTime(knowledgeBase.updated_at) || '-'}</span>
|
<span className='rb:text-[12px]'>{t('knowledgeBase.updated')} {t('knowledgeBase.time')}: {formatDateTime(knowledgeBase.updated_at) || '-'}</span>
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
* @LastEditTime: 2025-11-19 19:59:36
|
* @LastEditTime: 2025-11-19 19:59:36
|
||||||
*/
|
*/
|
||||||
import { Divider } from 'antd';
|
import { Divider } from 'antd';
|
||||||
|
import type { ReactElement } from 'react';
|
||||||
|
|
||||||
export interface InfoItem {
|
export interface InfoItem {
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
value: string | number | undefined;
|
value: string | number | undefined | ReactElement;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,8 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
|||||||
}
|
}
|
||||||
}, [nodes])
|
}, [nodes])
|
||||||
|
|
||||||
|
console.log('selectedNode', selectedNode)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<RbCard
|
<RbCard
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* @LastEditTime: 2025-12-22 13:47:53
|
* @LastEditTime: 2025-12-22 13:47:53
|
||||||
*/
|
*/
|
||||||
import { FileOutlined, FieldTimeOutlined, EditOutlined } from '@ant-design/icons';
|
import { FileOutlined, FieldTimeOutlined, EditOutlined } from '@ant-design/icons';
|
||||||
import { Skeleton } from 'antd';
|
import { Skeleton, Flex, Space } from 'antd';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { RecallTestData } from '@/views/KnowledgeBase/types';
|
import type { RecallTestData } from '@/views/KnowledgeBase/types';
|
||||||
import { NoData } from './noData';
|
import { NoData } from './noData';
|
||||||
@@ -26,6 +26,7 @@ interface RecallTestResultProps {
|
|||||||
editable?: boolean; // Whether editable
|
editable?: boolean; // Whether editable
|
||||||
onItemClick?: (item: RecallTestData, index: number) => void; // Click item callback
|
onItemClick?: (item: RecallTestData, index: number) => void; // Click item callback
|
||||||
parserMode?: number; // Parser mode, 1 means QA format
|
parserMode?: number; // Parser mode, 1 means QA format
|
||||||
|
handleCopy?: (text?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RecallTestResult = ({
|
const RecallTestResult = ({
|
||||||
@@ -38,8 +39,10 @@ const RecallTestResult = ({
|
|||||||
editable = false,
|
editable = false,
|
||||||
onItemClick,
|
onItemClick,
|
||||||
parserMode = 0,
|
parserMode = 0,
|
||||||
|
handleCopy,
|
||||||
}: RecallTestResultProps) => {
|
}: RecallTestResultProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
console.log('chunk data', data)
|
||||||
|
|
||||||
// Parse QA format content
|
// Parse QA format content
|
||||||
const parseQAContent = (content: string) => {
|
const parseQAContent = (content: string) => {
|
||||||
@@ -204,13 +207,21 @@ const RecallTestResult = ({
|
|||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{item.metadata?.file_created_at && (
|
<Flex align="center" justify={item.metadata?.file_created_at ? 'space-between' : 'end'} className="rb:mt-3!">
|
||||||
<div className='rb:flex rb:items-center rb:justify-start rb:mt-3'>
|
{item.metadata?.file_created_at && (
|
||||||
<span className='rb:text-gray-500 rb:text-xs'>
|
<div className='rb:flex rb:items-center rb:justify-start'>
|
||||||
<FieldTimeOutlined /> {formatDateTime(item.metadata.file_created_at)}
|
<span className='rb:text-gray-500 rb:text-xs'>
|
||||||
</span>
|
<FieldTimeOutlined /> {formatDateTime(item.metadata.file_created_at)}
|
||||||
</div>
|
</span>
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
|
<Space align="center" className='rb:text-gray-500 rb:text-xs' onClick={() => handleCopy?.(item.metadata?.doc_id)}>
|
||||||
|
ID: {item.metadata?.doc_id}
|
||||||
|
<span
|
||||||
|
className="rb:cursor-pointer rb:inline-block rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/copy_dark.svg')]"
|
||||||
|
></span>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -245,6 +256,7 @@ const RecallTestResult = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Otherwise use normal rendering
|
// Otherwise use normal rendering
|
||||||
return (
|
return (
|
||||||
<div className='rb:flex rb:flex-col'>
|
<div className='rb:flex rb:flex-col'>
|
||||||
|
|||||||
@@ -574,6 +574,8 @@ const KnowledgeBaseManagement: FC = () => {
|
|||||||
title={item.name}
|
title={item.name}
|
||||||
headerType="borderless"
|
headerType="borderless"
|
||||||
headerClassName="rb:py-3!"
|
headerClassName="rb:py-3!"
|
||||||
|
className="rb:cursor-pointer"
|
||||||
|
onClick={() => handleToDetail(item)}
|
||||||
extra={
|
extra={
|
||||||
<div onClick={(e) => e.stopPropagation()}>
|
<div onClick={(e) => e.stopPropagation()}>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
@@ -585,7 +587,7 @@ const KnowledgeBaseManagement: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className='' onClick={() => handleToDetail(item)}>
|
<div className=''>
|
||||||
<div className="rb:flex rb:text-[#5B6167] rb:h-5 rb:line-clamp-1 rb:text-sm rb:leading-5 rb:mb-3">
|
<div className="rb:flex rb:text-[#5B6167] rb:h-5 rb:line-clamp-1 rb:text-sm rb:leading-5 rb:mb-3">
|
||||||
{/* <div className="rb:font-medium rb:w-20">{t('knowledgeBase.description')} </div> */}
|
{/* <div className="rb:font-medium rb:w-20">{t('knowledgeBase.description')} </div> */}
|
||||||
<Tooltip title={item.description}>
|
<Tooltip title={item.description}>
|
||||||
|
|||||||
Reference in New Issue
Block a user