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

File diff suppressed because one or more lines are too long

105
app/simple-list/page.tsx Normal file
View File

@@ -0,0 +1,105 @@
"use client";
import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import data from "../data/content-templates.json";
import styles from "./SimpleList.module.css";
const categories = ["全部", "世界观", "制作资料", "角色", "音乐", "品牌", "运营"];
const statusStyles: Record<string, string> = {
"已发布": "statusPublished",
"评审中": "statusReview",
"草稿": "statusDraft",
"已归档": "statusArchived",
};
export default function SimpleListPage() {
const [query, setQuery] = useState("");
const [category, setCategory] = useState("全部");
const [status, setStatus] = useState("全部状态");
const [selected, setSelected] = useState<string[]>([]);
const [favorites, setFavorites] = useState<string[]>(data.listItems.filter((item) => item.favorite).map((item) => item.id));
const [toast, setToast] = useState("");
const [compact, setCompact] = useState(false);
useEffect(() => {
const saved = window.localStorage.getItem("orbit-simple-list-favorites");
if (saved) {
try { setFavorites(JSON.parse(saved)); } catch { /* use JSON defaults */ }
}
}, []);
useEffect(() => {
window.localStorage.setItem("orbit-simple-list-favorites", JSON.stringify(favorites));
}, [favorites]);
const items = useMemo(() => data.listItems.filter((item) => {
const matchQuery = `${item.title}${item.description}${item.id}${item.tags.join("")}`.toLowerCase().includes(query.toLowerCase());
return matchQuery && (category === "全部" || item.category === category) && (status === "全部状态" || item.status === status);
}), [query, category, status]);
const notify = (message: string) => {
setToast(message);
window.setTimeout(() => setToast(""), 2000);
};
const toggleAll = () => setSelected(selected.length === items.length ? [] : items.map((item) => item.id));
return (
<div className={styles.page}>
<header className={styles.topbar}>
<Link className={styles.brand} href="/"><span>O</span><strong>Orbit Docs</strong></Link>
<nav><Link className={styles.active} href="/simple-list"></Link><Link href="/character"></Link><Link href="/markdown">Markdown </Link></nav>
<div className={styles.topActions}><button onClick={() => notify("帮助中心为模板占位")}>?</button><span></span></div>
</header>
<main className={styles.content}>
<div className={styles.heading}>
<div><p>CONTENT LIBRARY</p><h1></h1><span></span></div>
<button className={styles.createButton} onClick={() => notify("新建资料表单为模板占位")}> </button>
</div>
<section className={styles.summary}>
<div><span className={styles.iconPurple}></span><p><small></small><strong>{data.listItems.length}</strong></p></div>
<div><span className={styles.iconGreen}></span><p><small></small><strong>{data.listItems.filter((item) => item.status === "已发布").length}</strong></p></div>
<div><span className={styles.iconOrange}></span><p><small></small><strong>{data.listItems.filter((item) => item.status === "评审中").length}</strong></p></div>
<div><span className={styles.iconBlue}></span><p><small></small><strong>{favorites.length}</strong></p></div>
</section>
<section className={styles.listPanel}>
<div className={styles.categoryTabs}>
{categories.map((item) => <button key={item} className={category === item ? styles.tabActive : ""} onClick={() => setCategory(item)}>{item}</button>)}
</div>
<div className={styles.toolbar}>
<label className={styles.search}><span></span><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="搜索标题、编号或标签" />{query && <button onClick={() => setQuery("")}>×</button>}</label>
<select value={status} onChange={(event) => setStatus(event.target.value)}><option></option><option></option><option></option><option>稿</option><option></option></select>
<button className={styles.filterButton} onClick={() => { setQuery(""); setCategory("全部"); setStatus("全部状态"); }}></button>
<div className={styles.viewToggle}><button className={!compact ? styles.viewActive : ""} onClick={() => setCompact(false)}></button><button className={compact ? styles.viewActive : ""} onClick={() => setCompact(true)}></button></div>
</div>
{selected.length > 0 && <div className={styles.bulkBar}><strong> {selected.length} </strong><button onClick={() => notify("已添加到收藏")}></button><button onClick={() => notify("已移动到归档")}></button><button onClick={() => setSelected([])}></button></div>}
<div className={`${styles.list} ${compact ? styles.compact : ""}`}>
<div className={styles.listHeader}><input type="checkbox" checked={items.length > 0 && selected.length === items.length} onChange={toggleAll} aria-label="全选" /><span></span><span></span><span></span><span></span><span></span><span /></div>
{items.map((item) => {
const checked = selected.includes(item.id);
const favorite = favorites.includes(item.id);
return <article key={item.id} className={checked ? styles.rowSelected : ""}>
<input type="checkbox" checked={checked} onChange={() => setSelected((current) => checked ? current.filter((id) => id !== item.id) : [...current, item.id])} aria-label={`选择 ${item.title}`} />
<button className={styles.titleCell} onClick={() => notify(`打开:${item.title}`)}><span>{item.category.slice(0, 1)}</span><div><strong>{item.title}</strong><p>{item.description}</p><small>{item.id} {item.tags.map((tag) => <i key={tag}>#{tag}</i>)}</small></div></button>
<span className={styles.category}>{item.category}</span>
<span className={`${styles.status} ${styles[statusStyles[item.status]]}`}><i />{item.status}</span>
<span className={styles.owner}><i>{item.initial}</i>{item.owner}</span>
<time>{item.updated}</time>
<div className={styles.rowActions}><button className={favorite ? styles.favorite : ""} onClick={() => setFavorites((current) => favorite ? current.filter((id) => id !== item.id) : [...current, item.id])}></button><button onClick={() => notify("更多操作:复制、移动、归档")}></button></div>
</article>;
})}
{items.length === 0 && <div className={styles.empty}><span></span><strong></strong><p></p><button onClick={() => { setQuery(""); setCategory("全部"); setStatus("全部状态"); }}></button></div>}
</div>
<footer className={styles.pagination}><span> {items.length} {data.listItems.length} </span><div><button disabled></button><button className={styles.pageActive}>1</button><button>2</button><button></button></div></footer>
</section>
</main>
{toast && <div className={styles.toast}> {toast}</div>}
</div>
);
}