知识库以及文件重命名、移动、删除
This commit is contained in:
@@ -167,6 +167,14 @@ export async function updateFileLib(data) {
|
||||
return await axios.put(`/api/v1/knowledge/update`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改支持库文件
|
||||
*
|
||||
*/
|
||||
export async function updateFile(data) {
|
||||
return await axios.put(`/api/v1/knowledge/file/update`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除支持库
|
||||
*
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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>
|
||||
))
|
||||
|
||||
@@ -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>
|
||||
@@ -237,6 +307,56 @@ export default function FilesPage() {
|
||||
<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, 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>
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user