index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import { useContext, useEffect, useRef, useState } from "react";
  2. import { useTranslation } from "react-i18next";
  3. import { userContext } from "../../contexts/userContext";
  4. import { deleteFileLib, readFileLibDatabase } from "../../controllers/API";
  5. import { captureAndAlertRequestErrorHoc } from "../../controllers/request";
  6. import { useTable } from "../../util/hook";
  7. import {DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem} from "../../components/ui/dropdown-menu";
  8. import CreateModal from "./components/createModel"
  9. import RenameModal from "./components/renameModel"
  10. import MoveModal from "./components/moveModel";
  11. import addIcon from "../../assets/knowledge/add-icon.png";
  12. import folderIcon from "../../assets/knowledge/folder-icon.png";
  13. import knowledgeIcon from "../../assets/knowledge/knowledge-icon.png";
  14. import duihuaGengduo from "../../assets/chat/duihua-gengduo.png";
  15. import writeIcon from "../../assets/knowledge/write-icon.png";
  16. import moveIcon from "../../assets/knowledge/move-icon.png";
  17. import exportIcon from "../../assets/knowledge/export-icon.png";
  18. import deleteIcon from "../../assets/knowledge/delete-icon.png";
  19. import noFolderIcon from "../../assets/knowledge/no-folder-icon.png";
  20. import { useNavigate } from "react-router-dom";
  21. export default function FileLibPage() {
  22. const [open, setOpen] = useState(false);
  23. const [renameOpen, setRenameOpen] = useState(false);
  24. const [moveOpen, setMoveOpen] = useState(false);
  25. const { user } = useContext(userContext);
  26. const [parentId, setParentId] = useState('0')
  27. const [titleArray, setTitleArray] = useState([]);
  28. const [folderShow, setFolderShow] = useState(false)
  29. const [type, setType] = useState(1)
  30. const [data, setData] = useState({})
  31. const navigate = useNavigate()
  32. const { page, pageSize, data: datalist, total, loading, setPage, search, reload } = useTable({},(param) =>
  33. readFileLibDatabase(param.page, 10000, param.keyword, parentId)
  34. )
  35. useEffect(() => {
  36. reload()
  37. }, [])
  38. // Delete
  39. const { delShow, idRef, close, delConfirm } = useDelete();
  40. const handleDelete = () => {
  41. captureAndAlertRequestErrorHoc(deleteFileLib(idRef.current.id).then(res => {
  42. reload();
  43. close();
  44. }));
  45. }
  46. const handleDetail = (el) => {
  47. if(el.type == 1){
  48. reload();
  49. titleArray.push(el)
  50. setTitleArray(titleArray)
  51. setParentId(el.id)
  52. }else if(el.type == 2){
  53. // @ts-ignore
  54. window.libname = el.name
  55. navigate("/filelib/" + el.id);
  56. }else if(el.type == 3){
  57. }
  58. }
  59. const backFolder = (parentId, index) => {
  60. setParentId(parentId)
  61. reload();
  62. if(index == -1){
  63. setTitleArray([])
  64. }else if(index == (titleArray.length - 1)){
  65. return;
  66. }else{
  67. titleArray.splice(index+1)
  68. }
  69. }
  70. // 进详情页前缓存 page, 临时方案
  71. const handleCachePage = () => {
  72. // @ts-ignore
  73. window.LibPage = page
  74. }
  75. useEffect(() => {
  76. // @ts-ignore
  77. const _page = window.LibPage
  78. if (_page) {
  79. setPage(_page);
  80. // @ts-ignore
  81. delete window.LibPage
  82. } else {
  83. setPage(1);
  84. }
  85. }, [])
  86. const { t } = useTranslation();
  87. return (
  88. <div className="w-full h-screen p-6 overflow-y-auto">
  89. {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">
  90. <span className="loading loading-infinity loading-lg"></span>
  91. </div>}
  92. <div className="w-full">
  93. <div className={'knowledge-header'}>
  94. <div className={'knowledge-title'}>
  95. {titleArray.length > 0?
  96. <div className={"title-list"}>
  97. <div className={"title-item"}>
  98. <label onClick={()=>backFolder('0', -1)}>{t("lib.rootDirectory")}</label>
  99. </div>
  100. {
  101. titleArray.map((title, index) => (
  102. <div className={"title-item"} key={title}>
  103. <span>{index <= (titleArray.length - 1)? ">" : ""}</span>
  104. <label onClick={()=>backFolder(title.id, index)}>{title.name}</label>
  105. </div>
  106. ))
  107. }
  108. </div>
  109. :
  110. t('lib.myKnowledge')
  111. }
  112. </div>
  113. <div className={'knowledge-create-box'}>
  114. <DropdownMenu>
  115. <DropdownMenuTrigger>
  116. <div className={'knowledge-create'} onClick={() => setOpen(true)}>
  117. <img src={addIcon} className={'create-icon'}/>
  118. <label>{t('lib.createNew')}</label>
  119. </div>
  120. </DropdownMenuTrigger>
  121. <DropdownMenuContent>
  122. <DropdownMenuItem onClick={()=>{
  123. setType(1)
  124. setOpen(true)
  125. }}><img src={folderIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>文件夹</DropdownMenuItem>
  126. <DropdownMenuItem onClick={()=>{
  127. setType(2)
  128. setOpen(true)
  129. }}><img src={knowledgeIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>知识库</DropdownMenuItem>
  130. </DropdownMenuContent>
  131. </DropdownMenu>
  132. </div>
  133. </div>
  134. {
  135. datalist.length > 0 ?
  136. <div className={"folder-list"}>
  137. {datalist.map((el) => (
  138. <div className={"folder-item"} key={el.id}>
  139. <div className={"folder-content-item"} onClick={() =>handleDetail(el)}>
  140. <div className={"folder-header"}>
  141. {
  142. el.type == 1?
  143. <span className={"knowledge-img-bg"}>
  144. <img src={el.type == 1? folderIcon :(el.img_url?el.img_url: knowledgeIcon )}/>
  145. </span>
  146. : (
  147. el.img_url?
  148. <img src={knowledgeIcon} className={"knowledge-img"}/>
  149. :
  150. <span className={"knowledge-img-bg"}>
  151. <img src={knowledgeIcon}/>
  152. </span>
  153. )
  154. }
  155. <label>{el.name}</label>
  156. <DropdownMenu>
  157. <DropdownMenuTrigger>
  158. <img src={duihuaGengduo} className={'more-button'}/>
  159. </DropdownMenuTrigger>
  160. <DropdownMenuContent>
  161. <DropdownMenuItem onClick={(event)=>{
  162. event.stopPropagation();
  163. setData(el)
  164. setRenameOpen(true)
  165. }}><img src={writeIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.rename")}</DropdownMenuItem>
  166. <DropdownMenuItem onClick={(event)=>{
  167. event.stopPropagation();
  168. setData(el)
  169. setMoveOpen(true)
  170. }}><img src={moveIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("lib.move")}</DropdownMenuItem>
  171. <DropdownMenuItem><img src={exportIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t("code.export")}</DropdownMenuItem>
  172. {user.role === 'admin' || user.user_id === el.user_id ?
  173. <DropdownMenuItem onClick={(event) => {
  174. event.stopPropagation();
  175. delConfirm(el)
  176. }}>
  177. <img src={deleteIcon} style={{width:'13px',height:'13px',marginRight:'8px'}}/>{t('delete')}
  178. </DropdownMenuItem> :
  179. ''
  180. }
  181. </DropdownMenuContent>
  182. </DropdownMenu>
  183. </div>
  184. <div className={"folder-description"}>
  185. {el.type == 1 ? t("lib.foldDesc") :el.description}
  186. </div>
  187. <div className={"folder-type"}>{el.type == 1?t('lib.folder'):el.type == 2?t('lib.universalKnowledgeBase'):t('lib.webSite')}</div>
  188. </div>
  189. </div>
  190. ))}
  191. </div>
  192. :
  193. <div className={"no-folder"}>
  194. <img src={noFolderIcon}/>
  195. <p>{t('lib.noKnowledgeBase')}</p>
  196. </div>
  197. }
  198. </div>
  199. <CreateModal reload={reload} createType={type} parentId={parentId} datalist={datalist} open={open} setOpen={setOpen}></CreateModal>
  200. <RenameModal reload={reload} data={data} open={renameOpen} setOpen={setRenameOpen}></RenameModal>
  201. <MoveModal reload={reload} data={data} open={moveOpen} setOpen={setMoveOpen} ></MoveModal>
  202. <dialog className={`modal ${delShow && 'modal-open'}`}>
  203. <form method="dialog" className="modal-box w-[360px] bg-[#fff] shadow-lg dialog-box">
  204. <h3 className="tip-title">{t('prompt')}</h3>
  205. <p className="tip-message">{t('lib.confirmDeleteLibrary')}</p>
  206. <div className={"button-box"}>
  207. <button className={"cancel-button tip-button"} onClick={close}>{t("cancel")}</button>
  208. <button className={"confirm-button delete-button tip-button-margin"} onClick={handleDelete}>{t("lib.confirmDelete")}</button>
  209. </div>
  210. </form>
  211. </dialog>
  212. </div>
  213. );
  214. }
  215. const useDelete = () => {
  216. const [delShow, setDelShow] = useState(false)
  217. const idRef = useRef<any>(null)
  218. return {
  219. delShow,
  220. idRef,
  221. close: () => {
  222. setDelShow(false)
  223. },
  224. delConfirm: (id) => {
  225. idRef.current = id
  226. setDelShow(true)
  227. }
  228. }
  229. }