浏览代码

知识库以及文件重命名、移动、删除

1025859868@qq.com 1 年之前
父节点
当前提交
8af9a4cb61

+ 8 - 0
src/controllers/API/index.ts

@@ -168,6 +168,14 @@ export async function updateFileLib(data) {
 }
 
 /**
+ * 修改支持库文件
+ *
+ */
+export async function updateFile(data) {
+  return await axios.put(`/api/v1/knowledge/file/update`, data);
+}
+
+/**
  * 删除支持库
  *
  */

+ 3 - 4
src/pages/Knowledge/components/createModel.tsx

@@ -18,7 +18,6 @@ import folderIcon from "../../../assets/knowledge/folder-icon.png";
 export default function CreateModal({ createType, parentId, datalist, open, setOpen, reload }) {
     const { t } = useTranslation()
     const navigate = useNavigate()
-
     const nameRef = useRef(null)
     const descRef = useRef(null)
     const [type, setType] = useState(createType)
@@ -29,12 +28,13 @@ export default function CreateModal({ createType, parentId, datalist, open, setO
 
     // Fetch model data
     useEffect(() => {
+        setType(createType)
         getEmbeddingModel().then(res => {
             const models = res.models || []
             setOptions(models)
             setModal(models[0] || '')
         })
-    }, [])
+    }, [createType])
 
     const { setErrorData } = useContext(alertContext);
 
@@ -63,7 +63,6 @@ export default function CreateModal({ createType, parentId, datalist, open, setO
             parent_id: parentId,
             type: type
         }).then(res => {
-            // @ts-ignore
             reload()
             setOpen(false)
         }))
@@ -177,7 +176,7 @@ export default function CreateModal({ createType, parentId, datalist, open, setO
     return (
         <div>
             {
-                type == 1? <CreateFolder /> : <CreateKnowLedge />
+                createType == 1? <CreateFolder /> : <CreateKnowLedge />
             }
         </div>
     );

+ 42 - 18
src/pages/Knowledge/components/moveModel.tsx

@@ -1,7 +1,7 @@
 import { useTranslation } from "react-i18next";
 import {useContext, useEffect, useRef, useState} from "react";
 import {useNavigate} from "react-router-dom";
-import {readFileLibDatabase, updateFileLib} from "../../../controllers/API";
+import {readFileLibDatabase, updateFile, updateFileLib} from "../../../controllers/API";
 import {alertContext} from "../../../contexts/alertContext";
 import {captureAndAlertRequestErrorHoc} from "../../../controllers/request";
 import {
@@ -14,32 +14,58 @@ import {useTable} from "../../../util/hook";
 import moveIcon from "../../../assets/knowledge/move-icon.png";
 import folderIcon from "../../../assets/knowledge/folder-icon.png";
 import noFolderIcon from "../../../assets/knowledge/no-folder-icon.png";
+import knowledgeIcon from "@/assets/knowledge/knowledge-icon.png";
 
 export default function MoveModal({ data, open, setOpen, reload }) {
+    if(!open) return null
+
     const { t } = useTranslation()
     const navigate = useNavigate()
     const [parentId, setParentId] = useState("")
     const { setErrorData } = useContext(alertContext);
     const [error, setError] = useState({ name: false })
+    const [datalist, setDatalist] = useState([])
+
+    useEffect(() => {
+        readFileLibDatabase(1, 10000, "", data.nameType == "file" ? data.knowledge_id : data.parent_id, '1').then(res => {
+            const list = res.data || []
+            const array = []
+            list.forEach((item) => {
+                if(item.id != data.id){
+                    array.push(item)
+                }
+            })
+            setDatalist(array)
+        })
+    }, [])
+
     const handleMove = () => {
         const errorlist = []
         if (!parentId) errorlist.push(t('lib.selectFold'))
 
         if (errorlist.length) return handleError(errorlist)
 
-        captureAndAlertRequestErrorHoc(updateFileLib({
-            id: data.id,
-            name: data.name,
-            parent_id: parentId
-        }).then(res => {
-            reload()
-            setOpen(false)
-        }))
+        if(data.nameType == "file"){
+            captureAndAlertRequestErrorHoc(updateFile({
+                id: data.id,
+                file_name: data.file_name,
+                knowledge_id: parentId
+            }).then(res => {
+                reload()
+                setOpen(false)
+            }))
+        }else{
+            captureAndAlertRequestErrorHoc(updateFileLib({
+                id: data.id,
+                name: data.name,
+                parent_id: parentId
+            }).then(res => {
+                reload()
+                setOpen(false)
+            }))
+        }
     }
 
-    const { page, pageSize, data: datalist, total, loading, setPage, search} = useTable({},(param) =>
-        readFileLibDatabase(param.page, 10000, param.keyword, '', '1')
-    )
 
     const handleError = (list) => {
         setErrorData({
@@ -57,13 +83,12 @@ export default function MoveModal({ data, open, setOpen, reload }) {
                     datalist.length > 0 ?
                         <div className={"folder-list third-list"}>
                             {datalist.map((el) => (
-                                el.id != data.id ?
                                 <div className={parentId == el.id ? "folder-item third-item folder-item-active" : "folder-item third-item"} key={el.id}>
                                     <div className={"folder-content-item"} onClick={() =>setParentId(el.id)}>
                                         <div className={"folder-header"}>
                                             <span className={"knowledge-img-bg"}>
-                                                <img src={folderIcon}/>
-                                            </span>
+                                                        <img src={folderIcon}/>
+                                                    </span>
                                             <label>{el.name}</label>
                                         </div>
                                         <div className={"folder-description"}>
@@ -72,12 +97,11 @@ export default function MoveModal({ data, open, setOpen, reload }) {
                                         <div className={"folder-type"}>{el.type == 1?t('lib.folder'):el.type == 2?t('lib.universalKnowledgeBase'):t('lib.webSite')}</div>
                                     </div>
                                 </div>
-                                    : ""
                             ))}
                         </div>
                         :
-                        <div  className={"no-folder"}>
-                            <img src={noFolderIcon}/>
+                        <div  className={"no-folder"} style={{marginBottom: '50px'}}>
+                            <img src={noFolderIcon} style={{marginTop: '100px'}}/>
                             <p>{t('lib.noFold')}</p>
                         </div>
                 }

+ 24 - 12
src/pages/Knowledge/components/renameModel.tsx

@@ -1,7 +1,7 @@
 import { useTranslation } from "react-i18next";
 import {useContext, useEffect, useRef, useState} from "react";
 import {useNavigate} from "react-router-dom";
-import {updateFileLib} from "../../../controllers/API";
+import {updateFileLib, updateFile} from "../../../controllers/API";
 import {alertContext} from "../../../contexts/alertContext";
 import {captureAndAlertRequestErrorHoc} from "../../../controllers/request";
 import writeIcon from "../../../assets/knowledge/write-icon.png";
@@ -9,11 +9,12 @@ import writeIcon from "../../../assets/knowledge/write-icon.png";
 export default function CreateModal({ data, open, setOpen, reload }) {
     const { t } = useTranslation()
     const navigate = useNavigate()
-    const [nameValue, setNameValue] = useState(data.name)
+    const name = data.nameType == "file"? data.file_name :data.name
+    const [nameValue, setNameValue] = useState(name)
 
     useEffect(() => {
-        setNameValue(data.name);
-    }, [data.name]);
+        setNameValue(name)
+    }, [name]);
 
     const nameRef = useRef(data.name)
     const { setErrorData } = useContext(alertContext);
@@ -28,14 +29,25 @@ export default function CreateModal({ data, open, setOpen, reload }) {
         setError({ name: !!nameErrors})
         if (errorlist.length) return handleError(errorlist)
 
-        captureAndAlertRequestErrorHoc(updateFileLib({
-            id: data.id,
-            name: name,
-            parent_id: data.parent_id
-        }).then(res => {
-            reload()
-            setOpen(false)
-        }))
+        if(data.nameType == "file"){
+            captureAndAlertRequestErrorHoc(updateFile({
+                id: data.id,
+                file_name: name,
+                knowledge_id: data.knowledge_id
+            }).then(res => {
+                reload()
+                setOpen(false)
+            }))
+        }else{
+            captureAndAlertRequestErrorHoc(updateFileLib({
+                id: data.id,
+                name: name,
+                parent_id: data.parent_id
+            }).then(res => {
+                reload()
+                setOpen(false)
+            }))
+        }
     }
 
     const handleError = (list) => {

+ 8 - 4
src/pages/Knowledge/index.tsx

@@ -34,6 +34,10 @@ export default function FileLibPage() {
         readFileLibDatabase(param.page, 10000, param.keyword, parentId)
     )
 
+    useEffect(() => {
+        reload()
+    }, [])
+
     // Delete
     const { delShow, idRef, close, delConfirm } = useDelete();
 
@@ -62,12 +66,12 @@ export default function FileLibPage() {
     const backFolder = (parentId, index) => {
         setParentId(parentId)
         reload();
-        if(index != -1){
-            titleArray.splice(index)
+        if(index == -1){
+            setTitleArray([])
         }else if(index == (titleArray.length - 1)){
             return;
         }else{
-            setTitleArray([])
+            titleArray.splice(index+1)
         }
     }
 
@@ -108,7 +112,7 @@ export default function FileLibPage() {
                                 {
                                     titleArray.map((title, index) => (
                                         <div className={"title-item"} key={title}>
-                                            <span>{index == (titleArray.length - 1)? ">" : ""}</span>
+                                            <span>{index <= (titleArray.length - 1)? ">" : ""}</span>
                                             <label onClick={()=>backFolder(title.id, index)}>{title.name}</label>
                                         </div>
                                     ))

+ 143 - 19
src/pages/Knowledge/knowledge.tsx

@@ -25,7 +25,13 @@ import ShadTooltip from "../../components/ShadTooltipComponent";
 import { Input } from "../../components/ui/input";
 import { Select, SelectContent, SelectGroup, SelectIconTrigger, SelectItem } from "../../components/ui/select1";
 import { locationContext } from "../../contexts/locationContext";
-import { deleteFile, readFileByLibDatabase, retryKnowledgeFileApi } from "../../controllers/API";
+import {
+    deleteFile,
+    deleteFileLib,
+    readFileByLibDatabase,
+    readFileLibDatabase,
+    retryKnowledgeFileApi
+} from "../../controllers/API";
 import { captureAndAlertRequestErrorHoc } from "../../controllers/request";
 import UploadModal from "../../modals/UploadModal";
 import { useTable } from "../../util/hook";
@@ -50,16 +56,15 @@ export default function FilesPage() {
     const nameRef = useRef(null)
     const [renameOpen, setRenameOpen] = useState(false);
     const [moveOpen, setMoveOpen] = useState(false);
-    const [parentId, setParentId] = useState('0')
+    const [parentId, setParentId] = useState(id)
+
+    useEffect(() => {
+        setParentId(id)
+    }, [id])
+
     const [type, setType] = useState(1)
     const [data, setData] = useState({})
-
-    const { page, pageSize, data: datalist, total, loading, setPage, search, reload, filterData, refreshData } = useTable({}, (param) =>
-        readFileByLibDatabase({ ...param, id, name: param.keyword }).then(res => {
-            setHasPermission(res.writeable)
-            return res
-        })
-    )
+    const [titleArray, setTitleArray] = useState([]);
 
     const detailData = {
         img_url: ""
@@ -70,10 +75,28 @@ export default function FilesPage() {
 
     // filter
     const [filter, setFilter] = useState(999)
+
+    const { data: libList, total: libTotal, loading: libLoading, search: libSearch, reload:libReload } = useTable({},(param) =>
+        readFileLibDatabase(param.page, 10000, param.keyword, parentId)
+    )
+
+    const { page, pageSize, data: datalist, total, loading, setPage, search, reload:fileReload, filterData, refreshData } = useTable({}, (param) =>
+        readFileByLibDatabase({ ...param, id: parentId, pageSize: 10000, name: param.keyword }).then(res => {
+            setHasPermission(res.writeable)
+            return res
+        })
+    )
+
     useEffect(() => {
         filterData({ status: filter })
     }, [filter])
 
+
+    const reload = () => {
+        fileReload()
+        libReload()
+    }
+
     useEffect(() => {
         // @ts-ignore
         const libname = window.libname // 临时记忆
@@ -91,13 +114,22 @@ export default function FilesPage() {
     }
 
     // 删除
-    const { delShow, idRef, close, delConfim } = useDelete()
+    const { delShow, idRef, delType, close, delConfim } = useDelete()
 
     const handleDelete = () => {
-        captureAndAlertRequestErrorHoc(deleteFile(idRef.current).then(res => {
-            reload()
-            close()
-        }))
+        //知识库里面有文件和文件夹,它对应两个表
+        if(delType == "file"){
+            captureAndAlertRequestErrorHoc(deleteFile(idRef.current).then(res => {
+                reload()
+                close()
+            }))
+        }else if(delType == "folder"){
+            captureAndAlertRequestErrorHoc(deleteFileLib(idRef.current).then(res => {
+                reload();
+                close();
+            }));
+        }
+
     }
 
     const [repeatFiles, setRepeatFiles] = useState([])
@@ -141,6 +173,25 @@ export default function FilesPage() {
         setFilter(Number(id))
     }
 
+    const handleLibDetail = (el) => {
+        setParentId(el.id)
+        titleArray.push(el)
+        setTitleArray(titleArray)
+        reload();
+    }
+
+    const backFolder = (parentId, index) => {
+        setParentId(parentId)
+        reload();
+        if(index == -1){
+            setTitleArray([])
+        }else if(index == (titleArray.length - 1)){
+            return;
+        }else{
+            titleArray.splice(index+1)
+        }
+    }
+
     return (
         <div className="w-full h-screen relative">
             {loading && <div className="absolute w-full h-full top-0 left-0 flex justify-center items-center z-10 bg-[rgba(255,255,255,0.6)] dark:bg-blur-shared">
@@ -158,7 +209,7 @@ export default function FilesPage() {
                                         <img src={"/src/assets/knowledge/knowledge-icon.png"}/>
                                     </span>
                             }
-                            <label>知识库</label>
+                            <label>{ title }</label>
                         </div>
                         <div className={"folder-type"}>{t('lib.universalKnowledgeBase')}</div>
                         <div className={"file-menu-active"}>
@@ -178,7 +229,23 @@ export default function FilesPage() {
                     <div className={"file-list  p-6 overflow-y-auto"}>
                         <div className={'knowledge-header'}>
                             <div className={'knowledge-title'}>
-                                {t("lib.file")}(6)
+                                {titleArray.length > 0?
+                                    <div className={"title-list"}>
+                                        <div className={"title-item"}>
+                                            <label onClick={()=>backFolder(id, -1)}>{t("lib.rootDirectory")}</label>
+                                        </div>
+                                        {
+                                            titleArray.map((title, index) => (
+                                                <div className={"title-item"} key={title}>
+                                                    <span>{index <= (titleArray.length - 1)? ">" : ""}</span>
+                                                    <label onClick={()=>backFolder(title.id, index)}>{title.name}</label>
+                                                </div>
+                                            ))
+                                        }
+                                    </div>
+                                    :
+                                    <div>{t("lib.file")}({libTotal + total})</div>
+                                }
                             </div>
                             {hasPermission &&
                                 <div className={'knowledge-create-box'}>
@@ -190,7 +257,10 @@ export default function FilesPage() {
                                             </div>
                                         </DropdownMenuTrigger>
                                         <DropdownMenuContent>
-                                            <DropdownMenuItem ><img src={"/src/assets/knowledge/folder-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.folder")}</DropdownMenuItem>
+                                            <DropdownMenuItem onClick={()=>{
+                                                setType(1)
+                                                setOpen(true)
+                                            }}><img src={"/src/assets/knowledge/folder-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.folder")}</DropdownMenuItem>
                                             <DropdownMenuItem ><img src={"/src/assets/knowledge/write-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.manualDataset")}</DropdownMenuItem>
                                             <DropdownMenuItem ><img src={"/src/assets/knowledge/knowledge-no-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.textDataset")}</DropdownMenuItem>
                                             <DropdownMenuItem ><img src={"/src/assets/knowledge/table-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.tableDataset")}</DropdownMenuItem>
@@ -245,6 +315,56 @@ export default function FilesPage() {
                                                 <DropdownMenuContent>
                                                     <DropdownMenuItem onClick={(event)=>{
                                                         event.stopPropagation();
+                                                        // 数据集重命名
+                                                        setData({ ...el, nameType: "file" })
+                                                        setRenameOpen(true)
+                                                    }}><img src={"/src/assets/knowledge/write-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.rename")}</DropdownMenuItem>
+                                                    <DropdownMenuItem onClick={(event)=>{
+                                                        event.stopPropagation();
+                                                        setData({ ...el, nameType: "file" })
+                                                        setMoveOpen(true)
+                                                    }}><img src={"/src/assets/knowledge/move-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.move")}</DropdownMenuItem>
+                                                    {hasPermission &&
+                                                        <DropdownMenuItem  onClick={(event) => {
+                                                            event.stopPropagation();
+                                                            delConfim(el.id, "file")
+                                                        }}>
+                                                            <img src={"/src/assets/knowledge/delete-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t('delete')}
+                                                        </DropdownMenuItem>
+                                                    }
+
+                                                </DropdownMenuContent>
+                                            </DropdownMenu>
+                                        </TableCell>
+                                    </TableRow>
+                                ))}
+                                {libList.map((el,index) => (
+                                    <TableRow key={el.id} className={"file-row"}>
+                                        <TableCell>{index + 1}</TableCell>
+                                        <TableCell onClick={ () => handleLibDetail(el) }>
+                                            <img className={"img-icon"} src={"/src/assets/knowledge/folder-icon.png"}/>
+                                            {el.name}
+                                        </TableCell>
+                                        <TableCell></TableCell>
+                                        <TableCell>{el.update_time.replace('T', ' ')}</TableCell>
+                                        <TableCell>
+                                            {el.status === 3 ? <div className="flex items-center">
+                                                    <div className="tooltip" data-tip={el.remark}>
+                                                        <span className='text-red-500'>{t('lib.parseFailed')}</span>
+                                                    </div>
+                                                    <Button variant="link"><RotateCw size={16} onClick={() => handleRetry([el])} /></Button>
+                                                </div> :
+                                                <span className={el.status === 3 && 'text-red-500'}>{[t('lib.parseFailed'), t('lib.parsing'), t('lib.completed'), t('lib.parseFailed')][el.status]}</span>
+                                            }
+                                        </TableCell>
+                                        <TableCell>
+                                            <DropdownMenu>
+                                                <DropdownMenuTrigger>
+                                                    <img src={"/src/assets/chat/duihua-gengduo.png"} className={'more-button'}/>
+                                                </DropdownMenuTrigger>
+                                                <DropdownMenuContent>
+                                                    <DropdownMenuItem onClick={(event)=>{
+                                                        event.stopPropagation();
                                                         setData(el)
                                                         setRenameOpen(true)
                                                     }}><img src={"/src/assets/knowledge/write-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.rename")}</DropdownMenuItem>
@@ -256,7 +376,7 @@ export default function FilesPage() {
                                                     {hasPermission &&
                                                         <DropdownMenuItem  onClick={(event) => {
                                                             event.stopPropagation();
-                                                            delConfim(el.id)
+                                                            delConfim(el.id, "folder")
                                                         }}>
                                                             <img src={"/src/assets/knowledge/delete-icon.png"} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t('delete')}
                                                         </DropdownMenuItem>
@@ -293,16 +413,20 @@ export default function FilesPage() {
 
 const useDelete = () => {
     const [delShow, setDelShow] = useState(false)
+    const [delType, setDelType] = useState("")
     const idRef = useRef<any>(null)
 
     return {
         delShow,
         idRef,
+        delType,
         close: () => {
             setDelShow(false)
         },
-        delConfim: (id) => {
+        delConfim: (id, delType) => {
             idRef.current = id
+            setDelType(delType)
+            console.log(delType)
             setDelShow(true)
         }
     }