import { useEffect, useRef, useState, useMemo, useCallback } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { Space, Modal, Tooltip, message, Alert, Empty, Upload, Input, InputRef } from 'antd'; import { NotSaveGroupId, isCtrlKey, ctrlKeyStr, FeatZipSubfix, ProjectGroupInfo, GetProjecPageListQuery, } from '@easytwin/core'; import { SearchOutlined, DragOutlined, DownloadOutlined, DeleteSquareOutlined, CodepenOutlined, CopySquareOutlined, RecycleOutlined, PlusOutlined, ExclamationCircleOutlined, } from '@easyv/react-icons'; import { useRecoilState } from 'recoil'; import classnames from 'classnames'; import { useKey } from 'react-use'; import { initData } from '@/server'; import { GroupMenu, ProButton } from '@/components'; import { _globalLoadingInfo } from '@/pages/module'; import { useProjectGroup, useProjectList, useProject } from './module'; import { NameEdit, ProjectCard } from './components'; export default function ProjectManage() { const location = useLocation(); const navigate = useNavigate(); useEffect(() => { initData(); if ((location.state as any)?.isClear) { navigate('/'); window.location.reload(); } }, [location, navigate]); const [, setLoadingInfo] = useRecoilState(_globalLoadingInfo); const [searchParams, setSearchParams] = useState<{ name: string; }>({ name: '', }); const searchInputRef = useRef(null); const [searchAutoFocus, setSearchAutoFocus] = useState(false); const [handleId, setHhandleId] = useState(); const { pageQuery, projectPageList, getProjectPageList } = useProjectList(); const { selectGroupKey, setSelectGroupKey, getProjectGroupListReq, createProjectGroupReq, updateProjectGroupReq, removeProjectGroupReq, } = useProjectGroup(); const beforeDataSource = useMemo(() => { let all = {}; let unnamed = {}; if (!getProjectGroupListReq.data?.length) return []; getProjectGroupListReq.data?.forEach((item) => { if (item.id === NotSaveGroupId.NOT_GROUP_FOR_PROJECT) unnamed = item; if (item.id === NotSaveGroupId.ALL_GROUP_FOR_PROJECT) all = item; }); return [all, unnamed] as ProjectGroupInfo[]; }, [getProjectGroupListReq.data]); const [, unnamed] = beforeDataSource; const id = selectGroupKey === NotSaveGroupId.ALL_GROUP_FOR_PROJECT || selectGroupKey === NotSaveGroupId.NOT_GROUP_FOR_PROJECT ? unnamed?.dataId : selectGroupKey; const handleRemoveGroup = (id: string) => { Modal.confirm({ title: '确认删除', icon: , content: '确认删除该分组?', async onOk() { removeProjectGroupReq.mutate({ ids: [id] }); }, }); }; const changeGroupData = useMemo( () => getProjectGroupListReq.data?.filter((i) => i.id !== NotSaveGroupId.ALL_GROUP_FOR_PROJECT) || [], [getProjectGroupListReq.data], ); const { updateProjectReq, removeProjectReq, isRecycle, setIsRecycle, getProjectRecycleListReq, recycleProjectReq, copyProject, exportProject, importProject, } = useProject(); const handleGetPageList = useCallback(() => { if (id) { let query: GetProjecPageListQuery = { ...searchParams, ...pageQuery, deleted: isRecycle, }; if (!(selectGroupKey === NotSaveGroupId.ALL_GROUP_FOR_PROJECT || isRecycle)) { query = { ...query, groupId: id }; } getProjectPageList(query); } }, [id, pageQuery, searchParams, getProjectPageList, isRecycle]); useEffect(() => { handleGetPageList(); }, [handleGetPageList]); const handleExportProject = async (id: string) => { try { setLoadingInfo({ loading: true, tip: '正在导出文件...', }); await exportProject({ id, }); message.success('导出成功'); } catch { message.error('导出失败'); } finally { setLoadingInfo({ loading: false, tip: null, }); } }; const handleRemoveProject = (id: string) => { Modal.confirm({ title: '确认删除', icon: , content: '项目删除后可在回收站中查看,确认删除该项目?', async onOk() { await removeProjectReq.mutate( { ids: [id], }, { onSuccess: () => { message.success('删除成功'); handleGetPageList(); getProjectGroupListReq.mutate(); }, }, ); }, }); }; const handelSearchFocusChange = useCallback(() => { if (searchAutoFocus) { searchInputRef.current?.blur(); setSearchParams((state) => ({ ...state, name: '' })); } else { searchInputRef.current?.focus(); } setSearchAutoFocus(!searchAutoFocus); }, [searchAutoFocus]); const onDropProject = async (groupId: string) => { if (!handleId) return; await updateProjectReq.mutate( { id: handleId, groupId, }, { onSuccess: () => { handleGetPageList(); getProjectGroupListReq.mutate(); message.success('修改成功'); }, }, ); }; useKey((e) => isCtrlKey(e) && e.code === 'KeyF', handelSearchFocusChange, undefined, [ handelSearchFocusChange, ]); return (
{/* left menu */}
{/* menu list */}
} beforeDataSource={beforeDataSource} afterDataSource={ getProjectGroupListReq.data?.filter( (i) => i.id !== NotSaveGroupId.ALL_GROUP_FOR_PROJECT && i.id !== NotSaveGroupId.NOT_GROUP_FOR_PROJECT, ) || [] } selectKey={selectGroupKey} onSelect={(key) => { setIsRecycle(false); setSelectGroupKey(key); }} onCreate={(name) => createProjectGroupReq.mutate( { name }, { onSuccess: (data) => { setIsRecycle(false); setSelectGroupKey(data?.id); }, }, ) } onEditName={(id, name) => updateProjectGroupReq.mutate({ id, name })} onRomove={handleRemoveGroup} onDropProject={onDropProject} />
{/* 回收站 */}
{ setIsRecycle(true); setSelectGroupKey(null); getProjectRecycleListReq.mutate({ ...pageQuery, deleted: true, }); }}> 回收站
{/* right content */}
{/* top tool */} {!isRecycle ? (
{/* */}
} onClick={() => navigate(`/project-template/${id}`)}> 新建 { if (id) { await importProject({ file, groupId: id }); await getProjectGroupListReq.mutate(); await handleGetPageList(); } return false; }}> 导入
{/* */}
} onChange={(e) => setSearchParams({ ...searchParams, name: e.target.value })} />
) : ( )} {/* main */}
{!isRecycle ? ( projectPageList?.length ? (
{projectPageList.map((item) => ( updateProjectReq.mutate( { id: item.id, name: value, }, { onSuccess: () => { message.success('修改成功'); }, }, ) } /> } extendRender={
{ setHhandleId(item.id); }}> { setLoadingInfo({ loading: true, tip: '复制项目中...', }); await copyProject({ id: item.id, name: item.name, }); setLoadingInfo({ loading: false, tip: null, }); message.success('复制成功'); await getProjectGroupListReq.mutate(); await handleGetPageList(); }} /> handleExportProject(item.id)} /> handleRemoveProject(item.id)} /> navigate( `/project-preview/${item.id}?from=${window.location.hash .split('#') .join('')}`, ) }> 预览 navigate(`/project-editor/${item.id}`)}> 编辑
} /> ))}
) : ( ) ) : getProjectRecycleListReq.data?.length ? (
{getProjectRecycleListReq.data.map((item) => ( } extendRender={
{ recycleProjectReq.mutate( { ids: [item.id], }, { onSuccess: () => { message.success('恢复成功'); getProjectGroupListReq.mutate(); getProjectRecycleListReq.mutate({ ...pageQuery, deleted: true, }); }, }, ); }}> 恢复
} /> ))}
) : ( )}
); }