feat(web): 重做设计系统与全部页面,前端观感对齐当下审美
用户反馈"UI 太丑、太简陋"。不是换配色,而是先立 token 再让页面去用: - tailwind.config.js:纸白 paper / 墨绿 primary / 陶土橙 clay + 语义色 sage/wheat/rust/sky,字号阶、圆角阶、投影、动效 - index.css:卡片、按钮五种变体、输入、pill/chip、导航、骨架屏 - 新增 icons.tsx(线性图标集)与 ui.tsx(Button/Sheet/Toast/空态/骨架/PageHeader) - 新增 AppShell 取代 Layout + WorkspaceNav:桌面侧栏 + 移动顶部横条,工单未读角标 - 六个页面全部重写:登录、首页、任务、看板、工单、知识、成员、邀请落地 - 详情抽屉改用 Sheet,工单态补齐需求人/办理人/退回次数/动作按钮 e2e 因 DOM 升级同步调整(抽屉按 role=dialog 定位、下拉改用 aria-label), 三套用例(7 + 8 + 7 项)全部重跑通过;tsc 0 错,构建 45 modules / gzip 76.70 kB。
This commit is contained in:
+33
-10
@@ -1,7 +1,8 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useAuth } from "../App";
|
||||
import { Layout } from "../components/Layout";
|
||||
import { Check, Logo, Spinner } from "../components/icons";
|
||||
import { Button, InlineAlert } from "../components/ui";
|
||||
import { ApiError, api, session } from "../lib/client";
|
||||
import type { Workspace } from "../lib/types";
|
||||
|
||||
@@ -11,6 +12,7 @@ export function JoinPage() {
|
||||
const { user, loading, reload } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [message, setMessage] = useState("正在加入工作区…");
|
||||
const [done, setDone] = useState(false);
|
||||
const [failed, setFailed] = useState(false);
|
||||
const started = useRef(false);
|
||||
|
||||
@@ -27,8 +29,9 @@ export function JoinPage() {
|
||||
try {
|
||||
const ws = await api.post<Workspace>(`/workspaces/${wsId}/join`, { code });
|
||||
await reload();
|
||||
setDone(true);
|
||||
setMessage(`已加入「${ws.name}」,正在跳转…`);
|
||||
setTimeout(() => navigate(`/w/${wsId}`, { replace: true }), 600);
|
||||
window.setTimeout(() => navigate(`/w/${wsId}`, { replace: true }), 700);
|
||||
} catch (err) {
|
||||
setFailed(true);
|
||||
setMessage(err instanceof ApiError ? err.message : "加入失败");
|
||||
@@ -37,17 +40,37 @@ export function JoinPage() {
|
||||
}, [loading, user, wsId, code, navigate, reload]);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="mx-auto mt-10 max-w-md">
|
||||
<div className="card text-center">
|
||||
<p className={failed ? "text-sm text-red-600" : "text-sm text-ink-700"}>{message}</p>
|
||||
<main className="grid min-h-full place-items-center bg-paper-100 px-6">
|
||||
<div className="w-full max-w-sm animate-slide-up">
|
||||
<div className="mb-6 flex justify-center">
|
||||
<Logo size={40} />
|
||||
</div>
|
||||
<div className="card p-7 text-center">
|
||||
<div className="mx-auto mb-4 grid h-12 w-12 place-items-center rounded-2xl bg-primary-50 text-primary-700">
|
||||
{failed ? (
|
||||
<span className="text-xl">!</span>
|
||||
) : done ? (
|
||||
<Check size={22} />
|
||||
) : (
|
||||
<Spinner size={20} />
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm leading-relaxed text-ink-700">{message}</p>
|
||||
<p className="mt-1 text-2xs text-ink-400">
|
||||
{failed ? "链接可能已失效,或你已经加入过了。" : "邀请码一次有效"}
|
||||
</p>
|
||||
{failed && (
|
||||
<button className="btn-ghost mt-4" onClick={() => navigate("/")}>
|
||||
返回工作区列表
|
||||
</button>
|
||||
<>
|
||||
<div className="mt-4">
|
||||
<InlineAlert>可以把邀请码发给同事,让他重新生成一条链接。</InlineAlert>
|
||||
</div>
|
||||
<Button variant="ghost" className="mt-4 w-full" onClick={() => navigate("/")}>
|
||||
返回工作区列表
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user