feat: add AirShelf core implementation

This commit is contained in:
zyc
2026-06-05 10:21:40 +08:00
parent 2ba1058329
commit cfdcd84a30
252 changed files with 70828 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
import { useState } from "react";
import { Bell, Search } from "lucide-react";
import type { Page } from "./route-config";
import { routeLabels } from "./route-config";
export function MessagesPage({ navigate }: { navigate: (page: Page) => void }) {
const messages = [
{ id: "m1", type: "task", priority: "ok", title: "补水面膜 · 痛点种草 v3 成片已完成", brief: "7 镜 · 40 秒 · ¥18.40 已结算。", body: "视频生成全部完成。", target: "pipeline" as Page },
{ id: "m2", type: "billing", priority: "warn", title: "团队余额低于预警线", brief: "当前余额低于 ¥100。", body: "建议先充值或降低任务量。", target: "account" as Page }
];
const [query, setQuery] = useState("");
const [selectedId, setSelectedId] = useState(messages[0].id);
const visible = messages.filter((item) => !query || `${item.title} ${item.brief}`.toLowerCase().includes(query.toLowerCase()));
const selected = messages.find((item) => item.id === selectedId) || visible[0] || messages[0];
return (
<>
<div className="page-head"><div><h1>消息中心</h1><div className="sub"><span className="mono">// {messages.length} 条总计</span> 任务提醒 · 团队协作 · 计费与系统公告</div></div><div className="actions"><button className="btn" type="button" onClick={() => navigate("settingsNotify")}>通知设置</button></div></div>
<div className="msg-workbench"><section className="msg-panel msg-inbox"><div className="msg-panel-h"><span className="ti">收件箱</span><span className="mono">// 显示 {visible.length} 条</span></div><div className="msg-search"><Search size={14} /><input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="搜索项目、来源、内容" /></div><div className="msg-list">{visible.map((item) => <button className={`msg-item ${selected.id === item.id ? "active" : ""}`} type="button" key={item.id} onClick={() => setSelectedId(item.id)}><span className={`msg-type-ic ${item.type}`}><Bell size={13} /></span><span className="msg-item-main"><span className="msg-item-title">{item.title}</span><span className="msg-brief">{item.brief}</span></span></button>)}</div></section><section className="msg-panel msg-detail"><div className="msg-detail-body"><div className="msg-detail-top"><span className={`msg-type-ic ${selected.type}`}><Bell size={15} /></span><div className="msg-detail-title"><h2>{selected.title}</h2><div className="meta"><span>{selected.type}</span></div></div></div><p className="msg-body-text">{selected.body}</p><div className="msg-props"><span className="k">关联资源</span><span className="v">{routeLabels[selected.target]}</span></div></div><div className="msg-detail-f"><span className="spacer" /><button className="btn btn-primary" type="button" onClick={() => navigate(selected.target)}>进入{routeLabels[selected.target]}</button></div></section></div>
</>
);
}