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 ( nav('/')}> 返回 开源部署展柜 {!loading && items.length > 0 && ( 精选 {items.length} 站 )} 以下站点自愿开启社区上报,并由官方演示站精选推荐(非全量目录) {loading ? ( ) : items.length === 0 ? ( 暂无精选实例 有站点被官方推荐后会出现在这里 ) : ( {items.map((item) => { const name = item.site_name || '未命名站点'; return ( {name} {hostLabel(item.site_url)} {item.featured_note ? ( {item.featured_note} ) : null} {item.version ? ( v{item.version} ) : null} ); })} )} ); }
以下站点自愿开启社区上报,并由官方演示站精选推荐(非全量目录)
暂无精选实例