|
@@ -1,304 +1,451 @@
|
|
|
-import * as React from 'react';
|
|
|
|
|
-import { observer } from 'mobx-react';
|
|
|
|
|
-import { generatePath, useLocation, useParams } from 'react-router-dom';
|
|
|
|
|
-import { Form, Input, Button, message, Upload, UploadProps } from 'antd';
|
|
|
|
|
-import { apis } from '@/apis';
|
|
|
|
|
-import router from '@/router';
|
|
|
|
|
-import { ArrowLeftOutlined } from '@ant-design/icons';
|
|
|
|
|
-import config, { getHeaders } from '@/apis/config';
|
|
|
|
|
|
|
+import * as React from "react";
|
|
|
|
|
+import { observer } from "mobx-react";
|
|
|
|
|
+import { generatePath, useLocation, useParams } from "react-router-dom";
|
|
|
|
|
+import { Form, Input, Button, message, Upload, UploadProps, Spin } from "antd";
|
|
|
|
|
+import { apis } from "@/apis";
|
|
|
|
|
+import router from "@/router";
|
|
|
|
|
+import { ArrowLeftOutlined } from "@ant-design/icons";
|
|
|
|
|
+import config, { getHeaders } from "@/apis/config";
|
|
|
const { TextArea } = Input;
|
|
const { TextArea } = Input;
|
|
|
-import { useState, useRef, useEffect } from 'react';
|
|
|
|
|
-import { EyeOutlined, CloseOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
+import { useState, useRef, useEffect } from "react";
|
|
|
|
|
+import { EyeOutlined, CloseOutlined } from "@ant-design/icons";
|
|
|
const FormItem = Form.Item;
|
|
const FormItem = Form.Item;
|
|
|
// 引入富文本
|
|
// 引入富文本
|
|
|
import MarkdownIt from "markdown-it";
|
|
import MarkdownIt from "markdown-it";
|
|
|
import MdEditor from "react-markdown-editor-lite";
|
|
import MdEditor from "react-markdown-editor-lite";
|
|
|
import "react-markdown-editor-lite/lib/index.css";
|
|
import "react-markdown-editor-lite/lib/index.css";
|
|
|
-import './style.less';
|
|
|
|
|
|
|
+import "./style.less";
|
|
|
|
|
|
|
|
// 初始化 markdown-it
|
|
// 初始化 markdown-it
|
|
|
const mdParser = new MarkdownIt({
|
|
const mdParser = new MarkdownIt({
|
|
|
html: true,
|
|
html: true,
|
|
|
- typographer: true
|
|
|
|
|
|
|
+ typographer: true,
|
|
|
});
|
|
});
|
|
|
const ar2 = [
|
|
const ar2 = [
|
|
|
{
|
|
{
|
|
|
- name:'我是图片1',
|
|
|
|
|
- url:'https://jkeckms.ryuiso.com/chat-bg.jpg'
|
|
|
|
|
|
|
+ name: "我是图片1",
|
|
|
|
|
+ url: "https://jkeckms.ryuiso.com/chat-bg.jpg",
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- name:'我是图片2',
|
|
|
|
|
- url:'https://jkeckms.ryuiso.com/chat-bg.jpg'
|
|
|
|
|
|
|
+ name: "我是图片2",
|
|
|
|
|
+ url: "https://jkeckms.ryuiso.com/chat-bg.jpg",
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- name:'我是图片3',
|
|
|
|
|
- url:'https://jkeckms.ryuiso.com/chat-bg.jpg'
|
|
|
|
|
- }
|
|
|
|
|
-]
|
|
|
|
|
|
|
+ name: "我是图片3",
|
|
|
|
|
+ url: "https://jkeckms.ryuiso.com/chat-bg.jpg",
|
|
|
|
|
+ },
|
|
|
|
|
+];
|
|
|
interface MdImg {
|
|
interface MdImg {
|
|
|
name: string;
|
|
name: string;
|
|
|
url: string;
|
|
url: string;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const SliceDetail: React.FC = () => {
|
|
const SliceDetail: React.FC = () => {
|
|
|
- const [form] = Form.useForm();
|
|
|
|
|
- const params = useParams();
|
|
|
|
|
- const location = useLocation();
|
|
|
|
|
- // console.log('location------',location);
|
|
|
|
|
- const { text = '', page } = location.state??{};
|
|
|
|
|
- const [listLoading, setListLoading] = React.useState(false);
|
|
|
|
|
- const [mdImgUrlList, setMdImgUrlList] = useState<MdImg[]>();
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const [form] = Form.useForm();
|
|
|
|
|
+ const params = useParams();
|
|
|
|
|
+ const location = useLocation();
|
|
|
|
|
+ // console.log('location------',location);
|
|
|
|
|
+ const { text = "", page } = location.state ?? {};
|
|
|
|
|
+ const [listLoading, setListLoading] = React.useState(false);
|
|
|
|
|
+ const [mdImgUrlList, setMdImgUrlList] = useState<MdImg[]>();
|
|
|
|
|
+ const [sliceList, setSliceList] = useState<string[]>([]); // 存储切片ID列表
|
|
|
|
|
+ const [currentIndex, setCurrentIndex] = useState<number>(-1); // 当前切片在列表中的索引
|
|
|
|
|
+ const [switchLoading, setSwitchLoading] = useState(false); // 切换切片时的loading状态
|
|
|
|
|
|
|
|
- const appApi = {
|
|
|
|
|
- fetchList: async () => {
|
|
|
|
|
- setListLoading(true);
|
|
|
|
|
- try {
|
|
|
|
|
- if (!params.sliceId || !params.knowledgeId) {
|
|
|
|
|
- throw new Error('参数错误');
|
|
|
|
|
- }
|
|
|
|
|
- const res = await apis.fetchTakaiSliceDetail(params.sliceId, params.knowledgeId);
|
|
|
|
|
- const info = res.data.data;
|
|
|
|
|
- form.setFieldsValue({
|
|
|
|
|
- slice_id: info.slice_id,
|
|
|
|
|
- slice_text: info.slice_text,
|
|
|
|
|
- document_id: info.document_id,
|
|
|
|
|
- })
|
|
|
|
|
- setContentMd(info.slice_text || '');
|
|
|
|
|
- setMdImgUrlList(info.imageList || []);
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error(error);
|
|
|
|
|
- } finally {
|
|
|
|
|
- setListLoading(false);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const appApi = {
|
|
|
|
|
+ fetchList: async () => {
|
|
|
|
|
+ setListLoading(true);
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (!params.sliceId || !params.knowledgeId) {
|
|
|
|
|
+ throw new Error("参数错误");
|
|
|
}
|
|
}
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const init = async () => {
|
|
|
|
|
- if (params.sliceId && params.sliceId !== 'new') {
|
|
|
|
|
- await appApi.fetchList();
|
|
|
|
|
|
|
+ const res = await apis.fetchTakaiSliceDetail(
|
|
|
|
|
+ params.sliceId,
|
|
|
|
|
+ params.knowledgeId
|
|
|
|
|
+ );
|
|
|
|
|
+ const info = res.data.data;
|
|
|
|
|
+ form.setFieldsValue({
|
|
|
|
|
+ slice_id: info.slice_id,
|
|
|
|
|
+ slice_text: info.slice_text,
|
|
|
|
|
+ document_id: info.document_id,
|
|
|
|
|
+ });
|
|
|
|
|
+ setContentMd(info.slice_text || "");
|
|
|
|
|
+ setMdImgUrlList(info.imageList || []);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setListLoading(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取切片列表用于导航
|
|
|
|
|
+ fetchSliceList: async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (!params.knowledgeId || !params.documentId) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- React.useEffect(() => {
|
|
|
|
|
- init();
|
|
|
|
|
- }, [])
|
|
|
|
|
|
|
+ const res = await apis.fetchTakaiSliceList({
|
|
|
|
|
+ knowledge_id: params.knowledgeId,
|
|
|
|
|
+ document_id: params.documentId,
|
|
|
|
|
+ text: text || "",
|
|
|
|
|
+ pageSize: 10000, // 获取所有切片
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ });
|
|
|
|
|
+ const ids = res.rows.map((item: any) => item.sliceId);
|
|
|
|
|
+ setSliceList(ids);
|
|
|
|
|
|
|
|
- const [cursorEndPosition, setCursorEndPosition] = React.useState<number>(0);
|
|
|
|
|
|
|
+ // 找到当前切片的索引
|
|
|
|
|
+ if (params.sliceId && params.sliceId !== "new") {
|
|
|
|
|
+ const index = ids.findIndex((id: string) => id === params.sliceId);
|
|
|
|
|
+ setCurrentIndex(index);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error("获取切片列表失败:", error);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- // 上传图片配置
|
|
|
|
|
- const uploadImageConfig: UploadProps = {
|
|
|
|
|
- name: 'files',
|
|
|
|
|
- action: config.baseURL + `/deepseek/api/uploadSliceImage/${params.knowledgeId}/${params.documentId}`,
|
|
|
|
|
- method: 'POST',
|
|
|
|
|
- headers: getHeaders(),
|
|
|
|
|
- accept: ['.png', '.jpg', '.jpeg'].join(','),
|
|
|
|
|
- multiple: true,
|
|
|
|
|
- maxCount: 5,
|
|
|
|
|
- showUploadList: false,
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ const init = async () => {
|
|
|
|
|
+ if (params.sliceId && params.sliceId !== "new") {
|
|
|
|
|
+ await appApi.fetchList();
|
|
|
|
|
+ }
|
|
|
|
|
+ await appApi.fetchSliceList();
|
|
|
|
|
+ setSwitchLoading(false); // 加载完成后关闭loading
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- // 处理markdown编辑器
|
|
|
|
|
- const [contentMd, setContentMd] = React.useState('');
|
|
|
|
|
- // 在这里做关键字替换
|
|
|
|
|
- const customRender = (text: string)=> {
|
|
|
|
|
- let html = mdParser.render(text);
|
|
|
|
|
|
|
+ React.useEffect(() => {
|
|
|
|
|
+ init();
|
|
|
|
|
+ }, [params.sliceId]);
|
|
|
|
|
|
|
|
- // 比如:把 "我是图片" 替换成一张图片
|
|
|
|
|
- mdImgUrlList?.forEach(item=>{
|
|
|
|
|
- html = html.replace(new RegExp(item.name, 'g'), `<img src="${item.url}" alt="${item.name}" />`);
|
|
|
|
|
- })
|
|
|
|
|
- // html = html.replace(/我是图片/g, `<img src="https://jkeckms.ryuiso.com/chat-bg.jpg" alt="我是图片" />`);
|
|
|
|
|
- // 你还可以做更多规则,比如匹配 [img:xxx] 这种自定义语法
|
|
|
|
|
- // html = html.replace(/\[img:(.+?)\]/g, (_, name) => `<img src="/images/${name}.png" />`);
|
|
|
|
|
- form.setFieldsValue({ slice_text: text });
|
|
|
|
|
- return html;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const [cursorEndPosition, setCursorEndPosition] = React.useState<number>(0);
|
|
|
|
|
|
|
|
|
|
+ // 上传图片配置
|
|
|
|
|
+ const uploadImageConfig: UploadProps = {
|
|
|
|
|
+ name: "files",
|
|
|
|
|
+ action:
|
|
|
|
|
+ config.baseURL +
|
|
|
|
|
+ `/deepseek/api/uploadSliceImage/${params.knowledgeId}/${params.documentId}`,
|
|
|
|
|
+ method: "POST",
|
|
|
|
|
+ headers: getHeaders(),
|
|
|
|
|
+ accept: [".png", ".jpg", ".jpeg"].join(","),
|
|
|
|
|
+ multiple: true,
|
|
|
|
|
+ maxCount: 5,
|
|
|
|
|
+ showUploadList: false,
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // 处理markdown编辑器
|
|
|
|
|
+ const [contentMd, setContentMd] = React.useState("");
|
|
|
|
|
+ // 在这里做关键字替换
|
|
|
|
|
+ const customRender = (text: string) => {
|
|
|
|
|
+ let html = mdParser.render(text);
|
|
|
|
|
|
|
|
|
|
+ // 比如:把 "我是图片" 替换成一张图片
|
|
|
|
|
+ mdImgUrlList?.forEach((item) => {
|
|
|
|
|
+ html = html.replace(
|
|
|
|
|
+ new RegExp(item.name, "g"),
|
|
|
|
|
+ `<img src="${item.url}" alt="${item.name}" />`
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+ // html = html.replace(/我是图片/g, `<img src="https://jkeckms.ryuiso.com/chat-bg.jpg" alt="我是图片" />`);
|
|
|
|
|
+ // 你还可以做更多规则,比如匹配 [img:xxx] 这种自定义语法
|
|
|
|
|
+ // html = html.replace(/\[img:(.+?)\]/g, (_, name) => `<img src="/images/${name}.png" />`);
|
|
|
|
|
+ form.setFieldsValue({ slice_text: text });
|
|
|
|
|
+ return html;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // 导航到指定切片
|
|
|
|
|
+ const navigateToSlice = (sliceId: string) => {
|
|
|
|
|
+ const path = generatePath(
|
|
|
|
|
+ "/deepseek/knowledgeLib/:knowledgeId/:createBy/slice/:documentId/:embeddingId/:sliceId",
|
|
|
|
|
+ {
|
|
|
|
|
+ knowledgeId: params.knowledgeId as string,
|
|
|
|
|
+ createBy: params.createBy as string,
|
|
|
|
|
+ documentId: params.documentId as string,
|
|
|
|
|
+ embeddingId: params.embeddingId as string,
|
|
|
|
|
+ sliceId: sliceId,
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ router.navigate({ pathname: path }, { state: { text: text, page } });
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ // 上一步
|
|
|
|
|
+ const handlePrevious = () => {
|
|
|
|
|
+ if (currentIndex > 0) {
|
|
|
|
|
+ setSwitchLoading(true);
|
|
|
|
|
+ const prevSliceId = sliceList[currentIndex - 1];
|
|
|
|
|
+ navigateToSlice(prevSliceId);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- return (
|
|
|
|
|
- <div>
|
|
|
|
|
- <div className='questionAnswerList'>
|
|
|
|
|
- <div style={{ height: '100%', marginLeft: '10px' }}>
|
|
|
|
|
- <Form
|
|
|
|
|
- style={{ paddingTop: '20px', height: '100%' }}
|
|
|
|
|
- form={form}
|
|
|
|
|
- layout='vertical'
|
|
|
|
|
- >
|
|
|
|
|
- <Form.Item
|
|
|
|
|
- // name="slice_text"
|
|
|
|
|
- rules={[{ required: true, message: '内容不能为空' }]}
|
|
|
|
|
- >
|
|
|
|
|
- <MdEditor
|
|
|
|
|
- config={{
|
|
|
|
|
- view:{
|
|
|
|
|
- menu:false
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- value={contentMd}
|
|
|
|
|
- style={{ height: "450px",width:'98%' }}
|
|
|
|
|
- renderHTML={customRender}
|
|
|
|
|
- onChange={({ text }) => setContentMd(text)}
|
|
|
|
|
- onBlur={(e: React.FocusEvent<HTMLTextAreaElement>) => {
|
|
|
|
|
- const ta = e.target as HTMLTextAreaElement;
|
|
|
|
|
- const start = ta.selectionStart;
|
|
|
|
|
- const end = ta.selectionEnd;
|
|
|
|
|
- setCursorEndPosition(end);
|
|
|
|
|
- // setCursor({ start, end });
|
|
|
|
|
- // console.log('blur cursor', start, end, ta.value);
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </Form.Item>
|
|
|
|
|
- {false && <FormItem
|
|
|
|
|
- name="slice_text"
|
|
|
|
|
- rules={[{ required: true, message: '切片内容不能为空' }]}>
|
|
|
|
|
- <TextArea
|
|
|
|
|
- style={{
|
|
|
|
|
- width: '50%',
|
|
|
|
|
- height: '200px',
|
|
|
|
|
- overflow: 'auto',
|
|
|
|
|
- resize: 'both',
|
|
|
|
|
- boxSizing: 'border-box',
|
|
|
|
|
|
|
+ // 下一步
|
|
|
|
|
+ const handleNext = () => {
|
|
|
|
|
+ if (currentIndex < sliceList.length - 1) {
|
|
|
|
|
+ setSwitchLoading(true);
|
|
|
|
|
+ const nextSliceId = sliceList[currentIndex + 1];
|
|
|
|
|
+ navigateToSlice(nextSliceId);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- }}
|
|
|
|
|
- placeholder=""
|
|
|
|
|
- autoSize={{ minRows: 20, maxRows: 5000 }}
|
|
|
|
|
- onBlur={(e) => {
|
|
|
|
|
- const target = e.target as HTMLTextAreaElement;
|
|
|
|
|
- // 更新光标终点位置
|
|
|
|
|
- setCursorEndPosition(target.selectionEnd);
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
- </FormItem>}
|
|
|
|
|
- <Upload
|
|
|
|
|
- {...uploadImageConfig}
|
|
|
|
|
- onChange={(info) => {
|
|
|
|
|
- const insertToSliceText = (text: string) => {
|
|
|
|
|
- const slice_text = contentMd
|
|
|
|
|
- // 获取当前光标位置
|
|
|
|
|
- const position = cursorEndPosition;
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div style={{ position: "relative" }}>
|
|
|
|
|
+ <Spin
|
|
|
|
|
+ spinning={switchLoading}
|
|
|
|
|
+ size="large"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ position: "fixed",
|
|
|
|
|
+ top: "50%",
|
|
|
|
|
+ left: "50%",
|
|
|
|
|
+ transform: "translate(-50%, -50%)",
|
|
|
|
|
+ zIndex: 9999,
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div style={{ width: 0, height: 0 }} />
|
|
|
|
|
+ </Spin>
|
|
|
|
|
+ <div className="questionAnswerList">
|
|
|
|
|
+ <div style={{ height: "100%", marginLeft: "10px" }}>
|
|
|
|
|
+ <Form
|
|
|
|
|
+ style={{ paddingTop: "20px", height: "100%" }}
|
|
|
|
|
+ form={form}
|
|
|
|
|
+ layout="vertical"
|
|
|
|
|
+ >
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ // name="slice_text"
|
|
|
|
|
+ rules={[{ required: true, message: "内容不能为空" }]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <MdEditor
|
|
|
|
|
+ config={{
|
|
|
|
|
+ view: {
|
|
|
|
|
+ menu: false,
|
|
|
|
|
+ },
|
|
|
|
|
+ }}
|
|
|
|
|
+ value={contentMd}
|
|
|
|
|
+ style={{ height: "450px", width: "98%" }}
|
|
|
|
|
+ renderHTML={customRender}
|
|
|
|
|
+ onChange={({ text }) => setContentMd(text)}
|
|
|
|
|
+ onBlur={(e: React.FocusEvent<HTMLTextAreaElement>) => {
|
|
|
|
|
+ const ta = e.target as HTMLTextAreaElement;
|
|
|
|
|
+ const start = ta.selectionStart;
|
|
|
|
|
+ const end = ta.selectionEnd;
|
|
|
|
|
+ setCursorEndPosition(end);
|
|
|
|
|
+ // setCursor({ start, end });
|
|
|
|
|
+ // console.log('blur cursor', start, end, ta.value);
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ {false && (
|
|
|
|
|
+ <FormItem
|
|
|
|
|
+ name="slice_text"
|
|
|
|
|
+ rules={[{ required: true, message: "切片内容不能为空" }]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <TextArea
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: "50%",
|
|
|
|
|
+ height: "200px",
|
|
|
|
|
+ overflow: "auto",
|
|
|
|
|
+ resize: "both",
|
|
|
|
|
+ boxSizing: "border-box",
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder=""
|
|
|
|
|
+ autoSize={{ minRows: 20, maxRows: 5000 }}
|
|
|
|
|
+ onBlur={(e) => {
|
|
|
|
|
+ const target = e.target as HTMLTextAreaElement;
|
|
|
|
|
+ // 更新光标终点位置
|
|
|
|
|
+ setCursorEndPosition(target.selectionEnd);
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </FormItem>
|
|
|
|
|
+ )}
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ display: "flex",
|
|
|
|
|
+ justifyContent: "space-between",
|
|
|
|
|
+ alignItems: "center",
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Upload
|
|
|
|
|
+ {...uploadImageConfig}
|
|
|
|
|
+ onChange={(info) => {
|
|
|
|
|
+ const insertToSliceText = (text: string) => {
|
|
|
|
|
+ const slice_text = contentMd;
|
|
|
|
|
+ // 获取当前光标位置
|
|
|
|
|
+ const position = cursorEndPosition;
|
|
|
|
|
|
|
|
- let newValue = '';
|
|
|
|
|
|
|
+ let newValue = "";
|
|
|
|
|
|
|
|
- if (!slice_text) {
|
|
|
|
|
- newValue = text;
|
|
|
|
|
- } else {
|
|
|
|
|
- newValue = slice_text.slice(0, position) + text + slice_text.slice(position);
|
|
|
|
|
- }
|
|
|
|
|
- setContentMd(newValue);
|
|
|
|
|
- form.setFieldsValue({ slice_text: newValue });
|
|
|
|
|
- }
|
|
|
|
|
- const file = info.file;
|
|
|
|
|
- if (file.status === 'done') {// 上传成功
|
|
|
|
|
- const { code, msg, data } = file.response;
|
|
|
|
|
- if (code === 200) {
|
|
|
|
|
- const text = data&&data[0]?.name||'';
|
|
|
|
|
- insertToSliceText(text);
|
|
|
|
|
- const flagList = mdImgUrlList || [];
|
|
|
|
|
- const flagList1 = [...flagList,...data];
|
|
|
|
|
- setMdImgUrlList(flagList1)
|
|
|
|
|
- message.success('上传成功');
|
|
|
|
|
- } else {
|
|
|
|
|
- message.error(msg);
|
|
|
|
|
- }
|
|
|
|
|
- } else if (file.status === 'error') {// 上传失败
|
|
|
|
|
- // 检查是否是504超时错误
|
|
|
|
|
- const response = file.response;
|
|
|
|
|
- if (response?.status === 504 || file.error?.includes('timeout')) {
|
|
|
|
|
- message.error('上传图片超时,请修改图片后再上传');
|
|
|
|
|
- } else {
|
|
|
|
|
- message.error('上传失败');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- <Button type='primary'>
|
|
|
|
|
- 解析图片
|
|
|
|
|
- </Button>
|
|
|
|
|
- </Upload>
|
|
|
|
|
- <Button
|
|
|
|
|
- style={{ margin: '0 16px' }}
|
|
|
|
|
- type='primary'
|
|
|
|
|
- icon={<ArrowLeftOutlined />}
|
|
|
|
|
- onClick={() => {
|
|
|
|
|
- const path = generatePath('/deepseek/knowledgeLib/:knowledgeId/:createBy/slice/:documentId/:embeddingId', {
|
|
|
|
|
- knowledgeId: params.knowledgeId as string,
|
|
|
|
|
- documentId: params.documentId as string,
|
|
|
|
|
- createBy: params.createBy as string,
|
|
|
|
|
- embeddingId: params.embeddingId as string,
|
|
|
|
|
- });
|
|
|
|
|
- router.navigate({ pathname: path },
|
|
|
|
|
- { state: { text: text, page } }
|
|
|
|
|
- );
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- 返回
|
|
|
|
|
- </Button>
|
|
|
|
|
- <Button
|
|
|
|
|
- type='primary'
|
|
|
|
|
- onClick={() => {
|
|
|
|
|
- form.validateFields().then(async (values) => {
|
|
|
|
|
- values = {
|
|
|
|
|
- slice_text:contentMd
|
|
|
|
|
- }
|
|
|
|
|
- // 验证参数是否存在
|
|
|
|
|
- if (!params.knowledgeId || !params.sliceId) {
|
|
|
|
|
- message.error('知识库ID或切片ID无效');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const data = values;
|
|
|
|
|
- const info = {
|
|
|
|
|
- knowledgeId: params.knowledgeId,
|
|
|
|
|
- sliceId: params.sliceId === null ? '' : params.sliceId,
|
|
|
|
|
- sliceText: btoa(unescape(encodeURIComponent(values.slice_text))),
|
|
|
|
|
- documentId: params.documentId,
|
|
|
|
|
- };
|
|
|
|
|
- let res = null;
|
|
|
|
|
- if (params.sliceId && params.sliceId !== 'null' && params.sliceId !== 'new') {
|
|
|
|
|
- // 编辑应用
|
|
|
|
|
- res = await apis.modifyTakaiSliceInfo(info as any);
|
|
|
|
|
- } else {
|
|
|
|
|
- res = await apis.addTakaiSlice(info as any);
|
|
|
|
|
- }
|
|
|
|
|
- if (res.code === 200 && res.data === 1) {
|
|
|
|
|
- if (params.sliceId && params.sliceId !== 'null' && params.sliceId !== 'new') {
|
|
|
|
|
- message.success('修改成功');
|
|
|
|
|
- } else {
|
|
|
|
|
- message.success('新增成功');
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- if (params.sliceId && params.sliceId !== 'null' && params.sliceId !== 'new') {
|
|
|
|
|
- message.error('修改失败');
|
|
|
|
|
- } else {
|
|
|
|
|
- message.error('新增失败');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- const path = generatePath('/deepseek/knowledgeLib/:knowledgeId/:createBy/slice/:documentId/:embeddingId', {
|
|
|
|
|
- knowledgeId: params.knowledgeId as string,
|
|
|
|
|
- createBy: params.createBy as string,
|
|
|
|
|
- documentId: params.documentId as string,
|
|
|
|
|
- embeddingId: params.embeddingId as string,
|
|
|
|
|
- });
|
|
|
|
|
- router.navigate({ pathname: path }, {
|
|
|
|
|
- state: { text: text, page }
|
|
|
|
|
- });
|
|
|
|
|
- }).catch((error) => {
|
|
|
|
|
- console.error(error);
|
|
|
|
|
- });
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- 保存
|
|
|
|
|
- </Button>
|
|
|
|
|
- </Form>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ if (!slice_text) {
|
|
|
|
|
+ newValue = text;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ newValue =
|
|
|
|
|
+ slice_text.slice(0, position) +
|
|
|
|
|
+ text +
|
|
|
|
|
+ slice_text.slice(position);
|
|
|
|
|
+ }
|
|
|
|
|
+ setContentMd(newValue);
|
|
|
|
|
+ form.setFieldsValue({ slice_text: newValue });
|
|
|
|
|
+ };
|
|
|
|
|
+ const file = info.file;
|
|
|
|
|
+ if (file.status === "done") {
|
|
|
|
|
+ // 上传成功
|
|
|
|
|
+ const { code, msg, data } = file.response;
|
|
|
|
|
+ if (code === 200) {
|
|
|
|
|
+ const text = (data && data[0]?.name) || "";
|
|
|
|
|
+ insertToSliceText(text);
|
|
|
|
|
+ const flagList = mdImgUrlList || [];
|
|
|
|
|
+ const flagList1 = [...flagList, ...data];
|
|
|
|
|
+ setMdImgUrlList(flagList1);
|
|
|
|
|
+ message.success("上传成功");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ message.error(msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (file.status === "error") {
|
|
|
|
|
+ // 上传失败
|
|
|
|
|
+ // 检查是否是504超时错误
|
|
|
|
|
+ const response = file.response;
|
|
|
|
|
+ if (
|
|
|
|
|
+ response?.status === 504 ||
|
|
|
|
|
+ file.error?.includes("timeout")
|
|
|
|
|
+ ) {
|
|
|
|
|
+ message.error("上传图片超时,请修改图片后再上传");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ message.error("上传失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Button type="primary">解析图片</Button>
|
|
|
|
|
+ </Upload>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ style={{ margin: "0 16px" }}
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ icon={<ArrowLeftOutlined />}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ const path = generatePath(
|
|
|
|
|
+ "/deepseek/knowledgeLib/:knowledgeId/:createBy/slice/:documentId/:embeddingId",
|
|
|
|
|
+ {
|
|
|
|
|
+ knowledgeId: params.knowledgeId as string,
|
|
|
|
|
+ documentId: params.documentId as string,
|
|
|
|
|
+ createBy: params.createBy as string,
|
|
|
|
|
+ embeddingId: params.embeddingId as string,
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ router.navigate(
|
|
|
|
|
+ { pathname: path },
|
|
|
|
|
+ { state: { text: text, page } }
|
|
|
|
|
+ );
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 返回
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ form
|
|
|
|
|
+ .validateFields()
|
|
|
|
|
+ .then(async (values) => {
|
|
|
|
|
+ values = {
|
|
|
|
|
+ slice_text: contentMd,
|
|
|
|
|
+ };
|
|
|
|
|
+ // 验证参数是否存在
|
|
|
|
|
+ if (!params.knowledgeId || !params.sliceId) {
|
|
|
|
|
+ message.error("知识库ID或切片ID无效");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const data = values;
|
|
|
|
|
+ const info = {
|
|
|
|
|
+ knowledgeId: params.knowledgeId,
|
|
|
|
|
+ sliceId:
|
|
|
|
|
+ params.sliceId === null ? "" : params.sliceId,
|
|
|
|
|
+ sliceText: btoa(
|
|
|
|
|
+ unescape(encodeURIComponent(values.slice_text))
|
|
|
|
|
+ ),
|
|
|
|
|
+ documentId: params.documentId,
|
|
|
|
|
+ };
|
|
|
|
|
+ let res = null;
|
|
|
|
|
+ if (
|
|
|
|
|
+ params.sliceId &&
|
|
|
|
|
+ params.sliceId !== "null" &&
|
|
|
|
|
+ params.sliceId !== "new"
|
|
|
|
|
+ ) {
|
|
|
|
|
+ // 编辑应用
|
|
|
|
|
+ res = await apis.modifyTakaiSliceInfo(info as any);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ res = await apis.addTakaiSlice(info as any);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (res.code === 200 && res.data === 1) {
|
|
|
|
|
+ if (
|
|
|
|
|
+ params.sliceId &&
|
|
|
|
|
+ params.sliceId !== "null" &&
|
|
|
|
|
+ params.sliceId !== "new"
|
|
|
|
|
+ ) {
|
|
|
|
|
+ message.success("修改成功");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ message.success("新增成功");
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (
|
|
|
|
|
+ params.sliceId &&
|
|
|
|
|
+ params.sliceId !== "null" &&
|
|
|
|
|
+ params.sliceId !== "new"
|
|
|
|
|
+ ) {
|
|
|
|
|
+ message.error("修改失败");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ message.error("新增失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const path = generatePath(
|
|
|
|
|
+ "/deepseek/knowledgeLib/:knowledgeId/:createBy/slice/:documentId/:embeddingId",
|
|
|
|
|
+ {
|
|
|
|
|
+ knowledgeId: params.knowledgeId as string,
|
|
|
|
|
+ createBy: params.createBy as string,
|
|
|
|
|
+ documentId: params.documentId as string,
|
|
|
|
|
+ embeddingId: params.embeddingId as string,
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ router.navigate(
|
|
|
|
|
+ { pathname: path },
|
|
|
|
|
+ {
|
|
|
|
|
+ state: { text: text, page },
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((error) => {
|
|
|
|
|
+ console.error(error);
|
|
|
|
|
+ });
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 保存
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ style={{ marginLeft: 16 }}
|
|
|
|
|
+ type="default"
|
|
|
|
|
+ disabled={
|
|
|
|
|
+ currentIndex <= 0 ||
|
|
|
|
|
+ params.sliceId === "new" ||
|
|
|
|
|
+ switchLoading
|
|
|
|
|
+ }
|
|
|
|
|
+ onClick={handlePrevious}
|
|
|
|
|
+ >
|
|
|
|
|
+ 上一步
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ style={{ marginLeft: 8 }}
|
|
|
|
|
+ type="default"
|
|
|
|
|
+ disabled={
|
|
|
|
|
+ currentIndex >= sliceList.length - 1 ||
|
|
|
|
|
+ params.sliceId === "new" ||
|
|
|
|
|
+ switchLoading
|
|
|
|
|
+ }
|
|
|
|
|
+ onClick={handleNext}
|
|
|
|
|
+ >
|
|
|
|
|
+ 下一步
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </Form>
|
|
|
</div>
|
|
</div>
|
|
|
- )
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-export default observer(SliceDetail);
|
|
|
|
|
|
|
+export default observer(SliceDetail);
|