feat: build account dashboard and settings workspace

This commit is contained in:
2026-03-26 23:03:45 +08:00
parent be4bc8a3af
commit 8ee9a696b4
18 changed files with 2468 additions and 54 deletions

View File

@@ -1,69 +1,103 @@
import type { ParentComponent } from "solid-js";
import { A, useLocation } from "@solidjs/router";
import { createSignal } from "solid-js";
const asideList = [
{ label: "账号", url: "/account" },
{ label: "设置", url: "/setting" },
];
const userInfo = {
name: "张三",
id: "123456",
dept: "大数据学院",
class: "3班",
gender: "男",
};
const infoList = [
["名字", userInfo.name],
["学号", userInfo.id],
["学院", userInfo.dept],
["班级", userInfo.class],
["性别", userInfo.gender],
];
const App: ParentComponent = (props) => {
const location = useLocation();
const isActive = (url: string) =>
location.pathname === url ||
(location.pathname === "/" && url === "/account");
return (
<div class="flex h-screen w-full flex-col">
<header class="m-2 flex shrink-0 flex-row items-center justify-between space-x-2 rounded-lg border-2 border-cyan-500/20 bg-zinc-100 px-5 py-2">
<div class="rounded-xl bg-cyan-300/50 px-2 py-1 text-xl">
<A href="/"></A>
</div>
<details class="relative rounded-xl bg-zinc-700/50 px-2 py-1 text-xl">
<summary></summary>
<div class="absolute top-full right-0 w-max gap-y-2 rounded-xl border border-zinc-100 bg-zinc-400/50 p-2">
{infoList.map(([label, value]) => (
<p class="text-lg">
{label}: <span>{value}</span>
</p>
))}
</div>
</details>
</header>
<div class="flex min-h-0 min-w-0 flex-1">
<aside class="m-2 flex shrink-0 flex-col gap-y-1 rounded-lg border-2 border-cyan-500/20 bg-zinc-100 px-2 py-2">
{asideList.map((item) => {
return (
<div class="flex h-screen w-full overflow-hidden bg-[radial-gradient(circle_at_top_left,_rgba(103,232,249,0.24),_transparent_28%),radial-gradient(circle_at_top_right,_rgba(251,191,36,0.16),_transparent_24%),linear-gradient(180deg,_#ecfeff_0%,_#f8fafc_52%,_#eef2ff_100%)] text-zinc-800">
<div class="flex min-h-0 w-full flex-col p-3 sm:p-4">
<header class="flex shrink-0 items-center justify-between gap-4 rounded-[28px] border border-white/70 bg-white/75 px-5 py-4 shadow-[0_18px_50px_-22px_rgba(14,116,144,0.35)] backdrop-blur-xl">
<div class="flex min-w-0 items-center gap-4">
<A
href="/"
class="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-[linear-gradient(135deg,_#06b6d4,_#22c55e)] text-lg font-semibold text-white shadow-lg shadow-cyan-500/20"
>
WK
</A>
<div class="min-w-0">
<A
href={item.url}
class={
location.pathname === item.url ||
(location.pathname === "/" && item.url === "/account"
? true
: false)
? "rounded-xl border border-zinc-100 bg-blue-300/50 p-2"
: "p-2"
}
href="/"
class="block truncate text-2xl font-semibold tracking-wide text-zinc-900"
>
{item.label}
</A>
);
})}
</aside>
<main class="m-2 flex flex-1 flex-col justify-center rounded-lg border-2 border-cyan-500/20 bg-zinc-100 px-2 py-2 text-center">
{props.children}
</main>
<p class="truncate text-sm text-zinc-500">
</p>
</div>
</div>
<div class="rounded-2xl border border-zinc-200/80 bg-zinc-50/90 px-4 py-3 text-right shadow-sm">
<p class="text-sm font-medium text-zinc-800"></p>
<p class="mt-1 text-xs text-zinc-500">
/ /
</p>
</div>
</header>
<div class="mt-4 flex min-h-0 min-w-0 flex-1 gap-4">
<aside class="flex w-64 shrink-0 flex-col rounded-[28px] border border-white/70 bg-white/70 p-3 shadow-[0_18px_50px_-22px_rgba(15,23,42,0.18)] backdrop-blur-xl">
<div class="mb-4 rounded-2xl bg-[linear-gradient(135deg,_rgba(6,182,212,0.12),_rgba(34,197,94,0.14))] px-4 py-4">
<p class="text-xs font-medium tracking-[0.24em] text-cyan-700/75 uppercase">
Navigation
</p>
<p class="mt-2 text-sm leading-6 text-zinc-600">
</p>
</div>
<nav class="flex flex-col gap-2">
{asideList.map((item) => {
const active = isActive(item.url);
return (
<A
href={item.url}
class={
active
? "rounded-2xl border border-cyan-200 bg-[linear-gradient(135deg,_rgba(34,211,238,0.18),_rgba(34,197,94,0.18))] px-4 py-3 text-sm font-medium text-zinc-900 shadow-sm"
: "rounded-2xl border border-transparent px-4 py-3 text-sm font-medium text-zinc-600 transition hover:border-zinc-200 hover:bg-zinc-50/80 hover:text-zinc-900"
}
>
<div class="flex items-center justify-between">
<span>{item.label}</span>
<span
class={
active
? "text-cyan-700"
: "text-zinc-400 transition group-hover:text-zinc-600"
}
>
</span>
</div>
</A>
);
})}
</nav>
<div class="mt-auto rounded-2xl border border-zinc-200/80 bg-zinc-50/90 px-4 py-4">
<p class="text-sm font-medium text-zinc-800"></p>
<p class="mt-1 text-sm text-zinc-500">
{asideList.find((item) => isActive(item.url))?.label ?? "账号"}
</p>
</div>
</aside>
<main class="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden rounded-[32px] border border-white/80 bg-white/80 p-3 shadow-[0_18px_60px_-24px_rgba(15,23,42,0.22)] backdrop-blur-xl sm:p-4">
{props.children}
</main>
</div>
</div>
</div>
);