import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { ArrowLeft, FolderGit2, Search } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Spinner } from '@/components/ui/spinner'; import { notify } from '@/lib/notify'; import { api } from '../api/client'; import type { GiteaProject } from '../api/types'; import ProjectListItem from '../components/ProjectListItem'; import { InFlowSiteFooter } from '../components/SiteFooter'; import { joinSEOKeywords, usePageSEO } from '../hooks/usePageSEO'; import { getCachedSiteBranding } from '../hooks/useSiteBranding'; export default function ProjectsPage() { const nav = useNavigate(); const [list, setList] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(0); const [loading, setLoading] = useState(true); const [queryInput, setQueryInput] = useState(''); const [query, setQuery] = useState(''); usePageSEO({ title: '开源码桶', description: '论坛会员在 Gitea 上的公开仓库', keywords: joinSEOKeywords('开源码桶', '项目', getCachedSiteBranding().keywords), canonicalPath: '/projects', }); useEffect(() => { const t = window.setTimeout(() => { const next = queryInput.trim(); setQuery(prev => { if (prev === next) return prev; setPage(1); return next; }); }, 300); return () => window.clearTimeout(t); }, [queryInput]); useEffect(() => { let cancelled = false; setLoading(true); api.projects({ page, limit: 30, q: query || undefined }) .then(d => { if (cancelled) return; setList(Array.isArray(d.projects) ? d.projects : []); setTotal(d.total ?? 0); setTotalPages(d.total_pages ?? 0); }) .catch(e => { if (!cancelled) notify.error(e instanceof Error ? e.message : '加载失败'); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [page, query]); return (

开源码桶

论坛会员在 Gitea 上的公开仓库 {total > 0 ? ` · 共 ${total} 个` : ''}

{loading ? (
) : list.length === 0 ? (

{query ? '没有匹配的仓库' : '暂无同步到的公开项目'}

{query ? '试试其他关键词,或清空搜索' : '需管理员在「系统设置 → Gitea 同步」开启并执行同步后才会出现仓库'}

) : ( <>
{list.map(p => ( ))}
{totalPages > 1 && (
{page} / {totalPages}
)} )}
); }