import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { ArrowLeft, ExternalLink, Globe2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Spinner } from '@/components/ui/spinner'; import { api } from '../api/client'; import type { CommunityShowcaseItem } from '../api/types'; import { joinSEOKeywords, usePageSEO } from '../hooks/usePageSEO'; import { getCachedSiteBranding, useSiteBranding } from '../hooks/useSiteBranding'; import { InFlowSiteFooter } from '../components/SiteFooter'; import { useSessionResource } from '../hooks/useSessionResource'; function siteMark(name: string, url: string): string { const raw = (name || '').trim() || url.replace(/^https?:\/\//i, ''); const ch = Array.from(raw)[0]; return ch ? ch.toUpperCase() : '?'; } function hostLabel(url: string): string { try { return new URL(url).host; } catch { return url.replace(/^https?:\/\//i, ''); } } /** 目标站约定路径 /favicon.ico */ function faviconURL(siteURL: string): string | null { try { return new URL('/favicon.ico', siteURL).href; } catch { return null; } } function ShowcaseFavicon({ name, url }: { name: string; url: string }) { const src = faviconURL(url); const [failed, setFailed] = useState(!src); const mark = siteMark(name, url); if (failed || !src) { return ( {mark} ); } return ( setFailed(true)} /> ); } /** 官方精选的公网部署展柜(只读;仅人工精选条目) */ export default function ShowcasePage() { const nav = useNavigate(); const { branding } = useSiteBranding(); const { data: items = [], loading } = useSessionResource( 'showcase', () => api.communityShowcase().then((r) => (Array.isArray(r.items) ? r.items : [])), { revalidateEmpty: true }, ); usePageSEO({ title: '开源部署展柜', description: `${branding.name} 精选的姜十三论坛公网部署`, keywords: joinSEOKeywords('开源', '部署', '展柜', getCachedSiteBranding().keywords), canonicalPath: '/showcase', }); return (

开源部署展柜

{!loading && items.length > 0 && ( 精选 {items.length} 站 )}

以下站点自愿开启社区上报,并由官方演示站精选推荐(非全量目录)

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

暂无精选实例

有站点被官方推荐后会出现在这里
) : ( )}
); }