import { useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { Card, Empty, Modal, Form, Input, Row, Col, Space, Button, Switch, message } from 'antd' import { PlusOutlined, FolderOutlined, TeamOutlined, EyeOutlined, ShareAltOutlined, CopyOutlined } from '@ant-design/icons' import { getMyProjects, createProject, deleteProject } from '@/api/project' import { getProjectShareInfo, updateShareSettings } from '@/api/share' import MainLayout from '@/components/MainLayout/MainLayout' import ListActionBar from '@/components/ListActionBar/ListActionBar' import Toast from '@/components/Toast/Toast' import './ProjectList.css' function ProjectList() { const [projects, setProjects] = useState([]) const [loading, setLoading] = useState(false) const [modalVisible, setModalVisible] = useState(false) const [shareModalVisible, setShareModalVisible] = useState(false) const [currentProject, setCurrentProject] = useState(null) const [shareInfo, setShareInfo] = useState(null) const [hasPassword, setHasPassword] = useState(false) const [password, setPassword] = useState('') const [searchKeyword, setSearchKeyword] = useState('') const [form] = Form.useForm() const navigate = useNavigate() useEffect(() => { fetchProjects() }, []) const fetchProjects = async () => { setLoading(true) try { const res = await getMyProjects() setProjects(res.data || []) } catch (error) { console.error('Fetch projects error:', error) } finally { setLoading(false) } } const handleCreateProject = async (values) => { try { await createProject(values) Toast.success('创建成功', '项目已创建') setModalVisible(false) form.resetFields() fetchProjects() } catch (error) { console.error('Create project error:', error) } } const handleDeleteProject = async (projectId) => { Modal.confirm({ title: '确认删除', content: '确定要删除这个项目吗?删除后可以在归档中找到', onOk: async () => { try { await deleteProject(projectId) Toast.success('归档成功', '项目已归档') fetchProjects() } catch (error) { console.error('Delete project error:', error) } }, }) } const handleOpenProject = (projectId) => { navigate(`/projects/${projectId}/docs`) } // 打开分享设置 const handleShare = async (e, project) => { e.stopPropagation() setCurrentProject(project) try { const res = await getProjectShareInfo(project.id) setShareInfo(res.data) setHasPassword(res.data.has_password) setPassword('') setShareModalVisible(true) } catch (error) { console.error('Get share info error:', error) message.error('获取分享信息失败') } } // 复制分享链接 const handleCopyLink = () => { if (!shareInfo) return const fullUrl = `${window.location.origin}${shareInfo.share_url}` navigator.clipboard.writeText(fullUrl) message.success('分享链接已复制') } // 切换密码保护 const handlePasswordToggle = async (checked) => { if (!checked) { // 取消密码 try { await updateShareSettings(currentProject.id, { access_pass: null }) setHasPassword(false) setPassword('') message.success('已取消访问密码') // 刷新分享信息 const res = await getProjectShareInfo(currentProject.id) setShareInfo(res.data) } catch (error) { console.error('Update settings error:', error) message.error('操作失败') } } else { setHasPassword(true) } } // 保存密码 const handleSavePassword = async () => { if (!password.trim()) { message.warning('请输入访问密码') return } try { await updateShareSettings(currentProject.id, { access_pass: password }) message.success('访问密码已设置') // 刷新分享信息 const res = await getProjectShareInfo(currentProject.id) setShareInfo(res.data) setHasPassword(true) } catch (error) { console.error('Save password error:', error) message.error('设置密码失败') } } // 过滤项目 const filteredProjects = projects.filter((project) => project.name.toLowerCase().includes(searchKeyword.toLowerCase()) ) return (
, onClick: () => setModalVisible(true), }, ]} search={{ placeholder: '搜索项目...', value: searchKeyword, onChange: setSearchKeyword, onSearch: (value) => setSearchKeyword(value), }} showRefresh onRefresh={fetchProjects} /> {filteredProjects.map((project) => ( handleOpenProject(project.id)} actions={[ handleShare(e, project)} />, , , ]} >

{project.name}

{project.description || '暂无描述'}

访问: {project.visit_count}
))} {projects.length === 0 && !loading && ( )}
{ setModalVisible(false) form.resetFields() }} footer={null} >
setShareModalVisible(false)} footer={null} width={500} > {shareInfo && (
} />
访问密码保护
{hasPassword && (
setPassword(e.target.value)} />
)}
)}
) } export default ProjectList