|
@@ -18,16 +18,16 @@ import {
|
|
|
Col,
|
|
Col,
|
|
|
Card
|
|
Card
|
|
|
} from 'antd';
|
|
} from 'antd';
|
|
|
-import { EditOutlined, DeleteOutlined, InboxOutlined, PlusOutlined, ArrowLeftOutlined, CloseOutlined, BulbOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
+import { EditOutlined, DeleteOutlined, InboxOutlined, PlusOutlined, ArrowLeftOutlined, CloseOutlined, BulbOutlined, UpOutlined, DownOutlined } from '@ant-design/icons';
|
|
|
import InfoModal from './components/InfoModal';
|
|
import InfoModal from './components/InfoModal';
|
|
|
import InfoModalSetting from './components/InfoModalSetting';
|
|
import InfoModalSetting from './components/InfoModalSetting';
|
|
|
import router from '@/router';
|
|
import router from '@/router';
|
|
|
import { Record } from './types';
|
|
import { Record } from './types';
|
|
|
import dayjs from 'dayjs';
|
|
import dayjs from 'dayjs';
|
|
|
|
|
+import axios from 'axios';
|
|
|
import LocalStorage from '@/LocalStorage';
|
|
import LocalStorage from '@/LocalStorage';
|
|
|
import store from './store';
|
|
import store from './store';
|
|
|
import './style.less';
|
|
import './style.less';
|
|
|
-import { uploadAxiosInstance } from '@/apis/api';
|
|
|
|
|
|
|
|
|
|
const { Dragger } = Upload;
|
|
const { Dragger } = Upload;
|
|
|
|
|
|
|
@@ -75,43 +75,26 @@ const KnowledgeLibInfo : React.FC = () => {
|
|
|
const [userInfoAll, setUserInfoAll] = React.useState<any>({});
|
|
const [userInfoAll, setUserInfoAll] = React.useState<any>({});
|
|
|
// 新手引导(知识库文档)整体可见性(持久化到 localStorage)
|
|
// 新手引导(知识库文档)整体可见性(持久化到 localStorage)
|
|
|
const [showDocGuide, setShowDocGuide] = React.useState<boolean>(() => localStorage.getItem('knowledgeDocGuideHidden') !== 'true');
|
|
const [showDocGuide, setShowDocGuide] = React.useState<boolean>(() => localStorage.getItem('knowledgeDocGuideHidden') !== 'true');
|
|
|
- const hideDocGuide = () => { localStorage.setItem('knowledgeDocGuideHidden', 'true'); setShowDocGuide(false); };
|
|
|
|
|
|
|
+ // 新手引导展开/折叠状态(持久化到 localStorage),默认展开
|
|
|
|
|
+ const [isDocGuideExpanded, setIsDocGuideExpanded] = React.useState<boolean>(() => {
|
|
|
|
|
+ const saved = localStorage.getItem('knowledgeDocGuideExpanded');
|
|
|
|
|
+ // 如果 localStorage 中没有值,默认展开(返回 true)
|
|
|
|
|
+ return saved === null ? true : saved === 'true';
|
|
|
|
|
+ });
|
|
|
|
|
+ const toggleDocGuide = () => {
|
|
|
|
|
+ setIsDocGuideExpanded(prev => {
|
|
|
|
|
+ const newValue = !prev;
|
|
|
|
|
+ // 保存到 localStorage
|
|
|
|
|
+ localStorage.setItem('knowledgeDocGuideExpanded', String(newValue));
|
|
|
|
|
+ return newValue;
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const props : UploadProps = {
|
|
const props : UploadProps = {
|
|
|
name: 'files',
|
|
name: 'files',
|
|
|
multiple: true,
|
|
multiple: true,
|
|
|
- customRequest: async (options) => {
|
|
|
|
|
- const { file, onSuccess, onError, onProgress } = options;
|
|
|
|
|
- const formData = new FormData();
|
|
|
|
|
- formData.append('files', file as File);
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- const response = await uploadAxiosInstance.post(
|
|
|
|
|
- `/deepseek/api/uploadDocument/${params.knowledgeId}`,
|
|
|
|
|
- formData,
|
|
|
|
|
- {
|
|
|
|
|
- headers: {
|
|
|
|
|
- 'Content-Type': 'multipart/form-data',
|
|
|
|
|
- },
|
|
|
|
|
- onUploadProgress: (progressEvent) => {
|
|
|
|
|
- if (progressEvent.total) {
|
|
|
|
|
- const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
|
|
|
|
- onProgress?.({ percent });
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- }
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- // 处理响应
|
|
|
|
|
- if (response.data && response.data.code === 200) {
|
|
|
|
|
- onSuccess?.(response.data, file as any);
|
|
|
|
|
- } else {
|
|
|
|
|
- onError?.(new Error(response.data?.msg || '上传失败'));
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error: any) {
|
|
|
|
|
- onError?.(error);
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ action: '/api/deepseek/api/uploadDocument/' + params.knowledgeId,
|
|
|
|
|
+ headers: getHeaders(),
|
|
|
beforeUpload( file, fileList ) {
|
|
beforeUpload( file, fileList ) {
|
|
|
setUploadLoading( true );
|
|
setUploadLoading( true );
|
|
|
// const allowedExtensions = ['md', 'txt', 'pdf', 'jpg', 'png', 'jpeg', 'docx', 'xlsx', 'pptx', 'eml', 'csv', 'tar', 'gz', 'bz2', 'zip', 'rar', 'jar'];
|
|
// const allowedExtensions = ['md', 'txt', 'pdf', 'jpg', 'png', 'jpeg', 'docx', 'xlsx', 'pptx', 'eml', 'csv', 'tar', 'gz', 'bz2', 'zip', 'rar', 'jar'];
|
|
@@ -230,7 +213,7 @@ const KnowledgeLibInfo : React.FC = () => {
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- const res = await uploadAxiosInstance.post( '/deepseek/api/uploadDocument/' + params.knowledgeId, formData, {
|
|
|
|
|
|
|
+ const res = await axios.post( '/api/deepseek/api/uploadDocument/' + params.knowledgeId, formData, {
|
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
@@ -439,67 +422,71 @@ const KnowledgeLibInfo : React.FC = () => {
|
|
|
<Spin spinning={ uploadLoading || listLoading }>
|
|
<Spin spinning={ uploadLoading || listLoading }>
|
|
|
{showDocGuide && (
|
|
{showDocGuide && (
|
|
|
<div style={{ padding: '12px 20px 12px 20px', background: '#fff' }}>
|
|
<div style={{ padding: '12px 20px 12px 20px', background: '#fff' }}>
|
|
|
- <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
|
|
|
|
|
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: isDocGuideExpanded ? 8 : 0 }}>
|
|
|
<div style={{ fontSize: 13, color: '#333', display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
<div style={{ fontSize: 13, color: '#333', display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
|
<BulbOutlined style={{ color: '#faad14' }} />
|
|
<BulbOutlined style={{ color: '#faad14' }} />
|
|
|
提示:如何上传并管理知识库文档?
|
|
提示:如何上传并管理知识库文档?
|
|
|
</div>
|
|
</div>
|
|
|
- <CloseOutlined onClick={hideDocGuide} style={{ color: '#999', cursor: 'pointer' }} />
|
|
|
|
|
|
|
+ <div onClick={toggleDocGuide} style={{ color: '#999', cursor: 'pointer', display: 'flex', alignItems: 'center' }}>
|
|
|
|
|
+ {isDocGuideExpanded ? <UpOutlined /> : <DownOutlined />}
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- <Row gutter={12}>
|
|
|
|
|
- <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
- <Card
|
|
|
|
|
- size="small"
|
|
|
|
|
- bordered={false}
|
|
|
|
|
- style={{
|
|
|
|
|
- background: 'linear-gradient(90deg, #e6f4ff 0%, #f0f7ff 100%)',
|
|
|
|
|
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
- borderRadius: 8,
|
|
|
|
|
- height: '100%'
|
|
|
|
|
- }}
|
|
|
|
|
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
- title={<span style={{ fontWeight: 600 }}>上传知识文档</span>}
|
|
|
|
|
- >
|
|
|
|
|
- <div style={{ color: '#666', fontSize: 12 }}>支持多种格式(Word、PDF、图片等),单个/总大小有上限,上传后自动处理(约5-10分钟,如遇到超时,可等待几分钟后刷新页面,将自动成功)。</div>
|
|
|
|
|
- {/* <div style={{ color: '#666', fontSize: 12 }}>支持pdf,doc,docx文件格式上传,建议单个文件不要超过10M,页数控制在100页以内。尽量单文件上传。</div> */}
|
|
|
|
|
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 1</div>
|
|
|
|
|
- </Card>
|
|
|
|
|
- </Col>
|
|
|
|
|
- <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
- <Card
|
|
|
|
|
- size="small"
|
|
|
|
|
- bordered={false}
|
|
|
|
|
- style={{
|
|
|
|
|
- background: 'linear-gradient(90deg, #e6fffb 0%, #f0fffe 100%)',
|
|
|
|
|
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
- borderRadius: 8,
|
|
|
|
|
- height: '100%'
|
|
|
|
|
- }}
|
|
|
|
|
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
- title={<span style={{ fontWeight: 600 }}>查看切片与索引</span>}
|
|
|
|
|
- >
|
|
|
|
|
- <div style={{ color: '#666', fontSize: 12 }}>自动解析成功后可查看切片数量与索引状态,必要时可重新生成或调整配置。</div>
|
|
|
|
|
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 2</div>
|
|
|
|
|
- </Card>
|
|
|
|
|
- </Col>
|
|
|
|
|
- <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
- <Card
|
|
|
|
|
- size="small"
|
|
|
|
|
- bordered={false}
|
|
|
|
|
- style={{
|
|
|
|
|
- background: 'linear-gradient(90deg, #fff7e6 0%, #fffaf0 100%)',
|
|
|
|
|
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
- borderRadius: 8,
|
|
|
|
|
- height: '100%'
|
|
|
|
|
- }}
|
|
|
|
|
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
- title={<span style={{ fontWeight: 600 }}>在应用中生效</span>}
|
|
|
|
|
- >
|
|
|
|
|
- <div style={{ color: '#666', fontSize: 12 }}>在RAG应用中切片将会被模型检索并召回,形成大模型对话的依据语料。</div>
|
|
|
|
|
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 3</div>
|
|
|
|
|
- </Card>
|
|
|
|
|
- </Col>
|
|
|
|
|
- </Row>
|
|
|
|
|
|
|
+ {isDocGuideExpanded && (
|
|
|
|
|
+ <Row gutter={12}>
|
|
|
|
|
+ <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
+ <Card
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ bordered={false}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ background: 'linear-gradient(90deg, #e6f4ff 0%, #f0f7ff 100%)',
|
|
|
|
|
+ boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
+ borderRadius: 8,
|
|
|
|
|
+ height: '100%'
|
|
|
|
|
+ }}
|
|
|
|
|
+ bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
+ title={<span style={{ fontWeight: 600 }}>上传知识文档</span>}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div style={{ color: '#666', fontSize: 12 }}>支持多种格式(Word、PDF、图片等),单个/总大小有上限,上传后自动处理(约5-10分钟,如遇到超时,可等待几分钟后刷新页面,将自动成功)。</div>
|
|
|
|
|
+ {/* <div style={{ color: '#666', fontSize: 12 }}>支持pdf,doc,docx文件格式上传,建议单个文件不要超过10M,页数控制在100页以内。尽量单文件上传。</div> */}
|
|
|
|
|
+ <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 1</div>
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
+ <Card
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ bordered={false}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ background: 'linear-gradient(90deg, #e6fffb 0%, #f0fffe 100%)',
|
|
|
|
|
+ boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
+ borderRadius: 8,
|
|
|
|
|
+ height: '100%'
|
|
|
|
|
+ }}
|
|
|
|
|
+ bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
+ title={<span style={{ fontWeight: 600 }}>查看切片与索引</span>}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div style={{ color: '#666', fontSize: 12 }}>自动解析成功后可查看切片数量与索引状态,必要时可重新生成或调整配置。</div>
|
|
|
|
|
+ <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 2</div>
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ <Col xs={24} sm={24} md={12} lg={8}>
|
|
|
|
|
+ <Card
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ bordered={false}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ background: 'linear-gradient(90deg, #fff7e6 0%, #fffaf0 100%)',
|
|
|
|
|
+ boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
|
|
|
|
|
+ borderRadius: 8,
|
|
|
|
|
+ height: '100%'
|
|
|
|
|
+ }}
|
|
|
|
|
+ bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
|
|
|
|
|
+ title={<span style={{ fontWeight: 600 }}>在应用中生效</span>}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div style={{ color: '#666', fontSize: 12 }}>在RAG应用中切片将会被模型检索并召回,形成大模型对话的依据语料。</div>
|
|
|
|
|
+ <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 3</div>
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ </Row>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
|
{
|
|
{
|