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
+18
View File
@@ -0,0 +1,18 @@
import { useState } from "react";
import { LogOut, Upload } from "lucide-react";
import type { Team, User } from "../types";
import { ConfirmModal, SettingRow, TeamModal } from "../components/overlays";
export function SettingsPage({ user, team, initialSection = "profile" }: { user: User; team: Team; initialSection?: string }) {
const [section, setSection] = useState(initialSection);
const [modal, setModal] = useState<"" | "avatar" | "logout">("");
const sections = [["profile", "个人资料"], ["security", "安全"], ["notify", "通知"], ["pref", "创作偏好"], ["display", "显示"]];
return (
<>
<div className="page-head"><div><h1>设置</h1><div className="sub"><span className="mono">// profile · security · notify · preference · display</span></div></div><div className="actions"><button className="btn" type="button">取消</button><button className="btn btn-primary" type="button">保存设置</button></div></div>
<div className="settings-layout"><aside className="settings-side">{sections.map(([key, label]) => <button className={section === key ? "active" : ""} type="button" key={key} onClick={() => setSection(key)}>{label}</button>)}<button className="logout-pill" type="button" onClick={() => setModal("logout")}><LogOut size={13} />退出当前设备</button></aside><section className="settings-main">{section === "profile" && <div className="pane"><h3>个人资料</h3><div className="profile-row"><div className="av-big">{user.username.slice(0, 1).toUpperCase()}</div><button className="btn btn-sm" type="button" onClick={() => setModal("avatar")}>上传新头像</button></div><div className="field"><label className="field-label">用户名</label><input className="input" value={user.username} readOnly /></div><div className="field"><label className="field-label">邮箱</label><input className="input" value={user.email || ""} readOnly /></div><div className="field"><label className="field-label">团队</label><input className="input" value={team.name} readOnly /></div></div>}{section === "security" && <div className="pane"><h3>安全</h3><SettingRow title="登录密码" desc="上次更新: 2026-05-28" action="修改" /><SettingRow title="双因素认证" desc="建议超管开启" toggle /></div>}{section === "notify" && <div className="pane"><h3>通知策略</h3><SettingRow title="导出完成" desc="成片 / 套图完成后提醒" toggle checked /><SettingRow title="任务失败" desc="失败和扣费异常必须提醒" toggle checked /><SettingRow title="额度预警" desc="余额低于阈值时提醒" toggle checked /></div>}{section === "pref" && <div className="pane"><h3>创作偏好</h3><SettingRow title="自动水印" desc="VIP 可关闭" toggle checked /></div>}{section === "display" && <div className="pane"><h3>显示偏好</h3><div className="field"><label className="field-label">主题</label><select className="select"><option>跟随系统</option><option>浅色</option></select></div></div>}</section></div>
<TeamModal open={modal === "avatar"} title="上传头像" subtitle="// JPG / PNG / WebP" icon={<Upload size={16} />} close={() => setModal("")}><div className="upload-zone">点击或拖入图片上传<br /><span className="mono">// 头像上传接口待后端补充</span></div></TeamModal>
<ConfirmModal open={modal === "logout"} title="退出当前账号" detail="当前有未保存的设置变更时,退出后这些变更不会保存。" confirmText="退出" onCancel={() => setModal("")} onConfirm={() => setModal("")} />
</>
);
}