Update WBBR frontend template collection

This commit is contained in:
Codex
2026-08-27 20:15:24 +08:00
parent bd4d54a110
commit e444605e5d
85 changed files with 6322 additions and 115 deletions

123
app/TemplateHub.tsx Normal file
View File

@@ -0,0 +1,123 @@
"use client";
import Link from "next/link";
import { CSSProperties, useMemo, useState } from "react";
import styles from "./TemplateHub.module.css";
type Category = "全部模板" | "后台业务" | "内容资料" | "可视化工具";
type TemplateItem = {
title: string;
english: string;
href: string;
category: Exclude<Category, "全部模板">;
icon: string;
description: string;
tags: string[];
color: string;
soft: string;
cover?: string;
featured?: boolean;
};
const categories: Category[] = ["全部模板", "后台业务", "内容资料", "可视化工具"];
const templates: TemplateItem[] = [
{ title: "后台组件总览", english: "ADMIN FOUNDATION", href: "/admin", category: "后台业务", icon: "▦", description: "标签、菜单、按钮、图文列表、定时任务等后台基础组件。", tags: ["组件库", "定时任务", "菜单"], color: "#356df3", soft: "#eaf1ff", featured: true },
{ title: "审批流程设计", english: "APPROVAL FLOW", href: "/approval", category: "后台业务", icon: "⌘", description: "类似飞书的前端审批流程图编辑器,支持节点配置。", tags: ["流程图", "节点编辑", "JSON"], color: "#7b61e8", soft: "#f0edff", featured: true },
{ title: "多级工作列表", english: "WORK LIST", href: "/worklist", category: "后台业务", icon: "☷", description: "树形多级表格、展开收起、状态筛选和批量操作。", tags: ["树形表格", "筛选", "批量操作"], color: "#315779", soft: "#eaf1f6" },
{ title: "泳道任务看板", english: "SWIMLANE KANBAN", href: "/kanban", category: "后台业务", icon: "▥", description: "卡片可在不同泳道之间拖动并即时更新状态。", tags: ["拖拽", "泳道", "任务卡片"], color: "#2d8a65", soft: "#e6f6ef" },
{ title: "响应式图床", english: "IMAGE HOST", href: "/image-host", category: "内容资料", icon: "▣", description: "瀑布流图片、三秒大图预览、单图详情与图集浏览。", tags: ["瀑布流", "图集", "悬停预览"], color: "#ef7955", soft: "#fff0e9", cover: "/anime/star-echoes-hero.png", featured: true },
{ title: "视频播放器", english: "VIDEO PLAYER", href: "/media-player", category: "内容资料", icon: "▶", description: "自定义视频控制器,支持进度、倍速、画中画与全屏。", tags: ["视频", "画中画", "本地文件"], color: "#5e63ef", soft: "#eeefff" },
{ title: "音乐播放器", english: "MUSIC PLAYER", href: "/music-player", category: "内容资料", icon: "♫", description: "独立音乐播放页,包含播放列表、波形进度和同步歌词。", tags: ["音乐", "歌词", "播放列表"], color: "#9a59df", soft: "#f5ecff" },
{ title: "时令事件日历", english: "SEASONAL CALENDAR", href: "/calendar", category: "内容资料", icon: "历", description: "按日期查看水果、海鲜应季期与阶段性事项,点击日期同步显示当天详情。", tags: ["日历", "应季时间", "事件详情"], color: "#d96246", soft: "#fff0e9" },
{ title: "全球产物地图", english: "GLOBAL PRODUCE MAP", href: "/produce-map", category: "可视化工具", icon: "地", description: "按中国、日本、中东、欧美等地区切换地图,高亮一级行政区并查看主要作物。", tags: ["地图", "行政区域", "主要产物"], color: "#2f8468", soft: "#e8f5ef" },
{ title: "动漫作品详情", english: "ANIME DETAIL", href: "/anime", category: "内容资料", icon: "星", description: "作品信息、商品展示、剧集列表和评论展示模板。", tags: ["作品", "商品", "评论"], color: "#6f57c9", soft: "#f0edfa", cover: "/anime/star-echoes-hero.png" },
{ title: "角色详情页", english: "CHARACTER PROFILE", href: "/character", category: "内容资料", icon: "人", description: "角色标签、关系、基本档案与剧情轨迹集中展示。", tags: ["角色", "标签", "关系"], color: "#9a5cc5", soft: "#f6edfb" },
{ title: "可重复表单", english: "REPEATABLE FORM", href: "/repeatable-form", category: "内容资料", icon: "F+", description: "可重复添加表单明细,并为每项配置图片和文件列表。", tags: ["动态表单", "图片", "文件"], color: "#3c72d9", soft: "#ebf2ff" },
{ title: "Markdown 编辑器", english: "MARKDOWN EDITOR", href: "/markdown", category: "内容资料", icon: "M↓", description: "Markdown 文档编辑、实时预览和浏览器本地保存。", tags: ["文档", "实时预览", "本地保存"], color: "#51586b", soft: "#eff1f5" },
{ title: "简单列表", english: "SIMPLE LIST", href: "/simple-list", category: "内容资料", icon: "≡", description: "轻量搜索、标签筛选、分页与批量操作列表。", tags: ["列表", "搜索", "标签"], color: "#625cb5", soft: "#eeedfa" },
{ title: "数据大屏", english: "DATA WALL", href: "/bigscreen", category: "可视化工具", icon: "◫", description: "适用于经营数据、实时指标和趋势图表的大屏模板。", tags: ["大屏", "指标", "图表"], color: "#16869a", soft: "#e5f6f8" },
{ title: "星空关系网络", english: "STAR GRAPH", href: "/stargraph", category: "可视化工具", icon: "✦", description: "星空超图节点、直线关联、悬停详情和 JSON 导入导出。", tags: ["关系图", "节点", "Canvas"], color: "#7063db", soft: "#efedff" },
{ title: "网页图标库", english: "WEB ICON LIBRARY", href: "/icons", category: "可视化工具", icon: "◇", description: "分类搜索、预览和复制代码的网页原生图标选择库。", tags: ["图标", "搜索", "代码复制"], color: "#38445b", soft: "#edf0f5" },
];
export default function TemplateHub() {
const [activeCategory, setActiveCategory] = useState<Category>("全部模板");
const [query, setQuery] = useState("");
const filtered = useMemo(() => templates.filter((item) => {
const matchesCategory = activeCategory === "全部模板" || item.category === activeCategory;
const searchable = `${item.title} ${item.english} ${item.description} ${item.tags.join(" ")}`.toLowerCase();
return matchesCategory && searchable.includes(query.trim().toLowerCase());
}), [activeCategory, query]);
const visibleGroups = categories.slice(1).map((category) => ({
category: category as Exclude<Category, "全部模板">,
items: filtered.filter((item) => item.category === category),
})).filter((group) => group.items.length > 0);
return (
<div className={styles.page}>
<header className={styles.header}>
<div className={styles.brand}><span>W</span><div><strong>WBBR</strong><small>AI FRONTEND STYLE SYSTEM</small></div></div>
<nav><a href="#templates"></a><a href="#about">使</a></nav>
<div className={styles.version}><i /> <b>v1.0</b></div>
</header>
<main>
<section className={styles.hero}>
<div className={styles.heroCopy}>
<p>AI FRONTEND STYLE REFERENCE</p>
<h1> AI <br /><em></em></h1>
<span>使 JSON </span>
<div className={styles.heroActions}><a href="#templates"> </a><Link href="/admin"> </Link></div>
</div>
<div className={styles.heroVisual} aria-hidden="true">
<div className={styles.visualWindow}><span><i /><i /><i /><b>wbbr.local/templates</b></span><div className={styles.visualBody}><aside><i /><i /><i /><i /></aside><main><p /><section><b /><b /><b /></section><div><i /><i /><i /><i /><i /><i /></div></main></div></div>
<div className={styles.floatingCard}><span></span><p><strong>{templates.length} </strong><small></small></p></div>
</div>
</section>
<section className={styles.featured} aria-label="精选模板">
{templates.filter((item) => item.featured).map((item, index) => <Link href={item.href} key={item.href} className={styles.featuredCard} style={{ "--accent": item.color, "--soft": item.soft } as CSSProperties}><span>0{index + 1}</span><div><small>{item.english}</small><strong>{item.title}</strong><p>{item.description}</p></div><b></b></Link>)}
</section>
<section className={styles.templates} id="templates">
<div className={styles.sectionHeading}><div><p>ALL TEMPLATES</p><h2></h2><span></span></div><label><span></span><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="搜索模板或功能" />{query && <button onClick={() => setQuery("")}>×</button>}</label></div>
<div className={styles.filters}>{categories.map((category) => <button key={category} className={activeCategory === category ? styles.filterActive : ""} onClick={() => setActiveCategory(category)}>{category}<b>{category === "全部模板" ? templates.length : templates.filter((item) => item.category === category).length}</b></button>)}</div>
{visibleGroups.map((group) => <section className={styles.group} key={group.category}>
<div className={styles.groupTitle}><span>{categoryIcon(group.category)}</span><div><h3>{group.category}</h3><p>{categoryDescription(group.category)}</p></div><b>{group.items.length}</b></div>
<div className={styles.grid}>{group.items.map((item) => <TemplateCard key={item.href} item={item} />)}</div>
</section>)}
{filtered.length === 0 && <div className={styles.empty}><span></span><h3></h3><p></p><button onClick={() => { setQuery(""); setActiveCategory("全部模板"); }}></button></div>}
</section>
<section className={styles.about} id="about"><div><p>LOCAL JSON · NO BACKEND</p><h2>便</h2></div><span> JSON </span><Link href="/admin"> </Link></section>
</main>
<footer><div><span>W</span><strong>WBBR</strong></div><p>AI · React JSON </p><a href="#templates"> </a></footer>
</div>
);
}
function TemplateCard({ item }: { item: TemplateItem }) {
const style = {
"--accent": item.color,
"--soft": item.soft,
...(item.cover ? { backgroundImage: `linear-gradient(135deg, rgba(12,18,32,.16), rgba(12,18,32,.62)), url(${item.cover})` } : {}),
} as CSSProperties;
return <Link href={item.href} className={`${styles.card} ${item.cover ? styles.cardWithCover : ""}`} style={style}>
<div className={styles.cardPreview}><span>{item.icon}</span><small>{item.english}</small><div><i /><i /><i /></div></div>
<div className={styles.cardBody}><div><strong>{item.title}</strong><b> </b></div><p>{item.description}</p><span>{item.tags.map((tag) => <i key={tag}>{tag}</i>)}</span></div>
</Link>;
}
function categoryIcon(category: Exclude<Category, "全部模板">) {
return category === "后台业务" ? "▦" : category === "内容资料" ? "◫" : "✦";
}
function categoryDescription(category: Exclude<Category, "全部模板">) {
return category === "后台业务" ? "流程、任务与管理工作台" : category === "内容资料" ? "列表、文档与内容展示" : "数据、关系与辅助工具";
}