# 个人中心 UI 改版设计

## Context

当前 `/profile` 页面（commit `7c49868`）的视觉太单调——内容用 `max-w-xl` 限宽，单张白卡片孤立漂浮在空白页上，没有头部装饰，整体像一个被推平的弹窗。改为 GitHub/Notion 风格的"个人页"：渐变 Banner + 大头像 + Tab 切换的卡片。

## 决策摘要

| 项 | 决策 |
|---|---|
| 整体风格 | 顶部渐变 Banner + 头像 + 下方 Tab 卡片（方案 A） |
| Banner 高度 | h-40（160px） |
| Banner 背景 | `bg-gradient-to-br from-[var(--accent)] to-[var(--accent-hover)]` |
| 头像 | 80px 圆形，主色背景 + 白字首字母，`ring-4 ring-white/20` |
| 退出按钮位置 | Banner 右上角 absolute（白底红描边红字） |
| Tab 风格 | 沿用版本详情页风格（active 主色下划线） |
| 字段布局 | 单栏堆叠（用户决定，避免两栏挤迫） |
| 卡片宽度 | `max-w-3xl mx-auto` 居中 |
| 保存反馈 | 提交中 spinner + 已保存绿色文字 3 秒淡出 |
| 移动端 | 不考虑（项目仅面向桌面端） |

## 1. Banner 视觉规格

**结构**：

```
┌─────────────────────────────────────────────────────┐
│ [渐变背景 h-40]                                       │
│                                          [退出登录]   │
│                                                      │
│   [80px 圆头像]   张三                               │
│      "张"         产品经理 · 产品部 / 前端组          │
│                   📞 138... · ✉ zhang@...            │
└─────────────────────────────────────────────────────┘
```

**实现要点**：
- 容器 `relative h-40 px-8 py-6 rounded-b-3xl bg-gradient-to-br from-[var(--accent)] to-[var(--accent-hover)] text-white`
- 内部 flex 布局：左侧头像 + 文字组，右上 absolute 退出按钮
- 头像：`h-20 w-20 rounded-full bg-white/15 ring-4 ring-white/20 flex items-center justify-center text-3xl font-semibold`，内容是 `user.name?.[0]`
- 主名 `text-2xl font-semibold`
- 副名 `text-sm text-white/80`，格式："角色名 · 部门层级"
- 联系方式 `text-xs text-white/60`，Phone/Mail icon + 文本
- 退出按钮：`absolute top-5 right-5 h-8 px-3 rounded-lg bg-white/10 border border-white/20 hover:bg-white/20 text-white`（白色透明）

## 2. Tab 内容布局

**结构**：

```
[Banner]

  ┌─ 个人信息 ─┐  ┌─ 修改密码 ─┐                       
  ════════════                                          

  ┌──────────────────────────────────────────┐
  │ 基本信息                                   │
  │ 修改后立即生效                              │
  │ ─────────────────────────────────────     │
  │                                            │
  │ 姓名 *                                      │
  │ [_____________________________________]    │
  │                                            │
  │ 手机号 *                                    │
  │ [_____________________________________]    │
  │                                            │
  │ 邮箱 *                                      │
  │ [_____________________________________]    │
  │                                            │
  │ 部门                                        │
  │ [产品部 / 前端组]                           │
  │                                            │
  │ 角色                                        │
  │ [产品经理]                                   │
  │                                            │
  │                          [取消]  [保存]     │
  └──────────────────────────────────────────┘
```

**实现要点**：
- Banner 与 Tab 之间留 `mt-6` 间距
- Tab 容器 `max-w-3xl mx-auto px-5`，无外边框，仅 Tab 按钮带下划线
- 卡片 `max-w-3xl mx-auto rounded-2xl border border-[var(--line)] bg-[var(--bg-card)] p-6`
- 卡片头：标题 `text-base font-semibold` + 副标题 `text-xs text-[var(--ink-muted)] mt-1`
- 标题区下细分割线 `border-t border-[var(--line)] pt-5 mt-4`
- 字段单栏堆叠 `space-y-4`
- 必填星号 `text-red-500`
- 部门、角色字段 `disabled bg-zinc-50`

**密码 Tab**：
- 卡片标题"修改密码"+ 副标题"密码修改后下次登录生效"
- 三个字段单栏堆叠（与第 1 节澄清一致）
- 眼睛 icon 切换可见性保留

## 3. 保存反馈微调

**保存按钮三态**：

```
普通：       [取消]  [保存]
提交中：     [取消]  [● 保存中...]   ← spinner 禁用
成功：       已保存 ✓      [取消]  [保存]   ← 绿色文字 3 秒淡出
```

- 提交瞬间设 `submitting=true`，按钮 disabled + 左侧 Loader2 icon spinning
- 成功后 `submitting=false` + `savedAt=Date.now()`，3 秒后 `setTimeout` 清掉 savedAt
- 已保存提示：`text-emerald-600` + Check icon

**取消按钮**：
- 个人信息 Tab：`handleReset` 重读 `useMemberStore.members.find(m => m.id === user.id)` 的字段
- 密码 Tab：清空三个输入 + 清空 errors

**Banner 与表单同步**：
- 字段改了未保存：Banner 仍显老值（不联动）
- 保存成功 → `refreshUser()` → Banner 立即更新

## 数据流

```
useAuthStore.user
   │
   └─ 触发渲染
         │
         ├─ Banner（user.name / role.name / dept name 链 / phone / email）
         └─ 表单字段（从 useMemberStore.members.find 取最新值）

提交流程：
   form submit → updateMember() → refreshUser() → Banner 自动重渲
```

## 实施清单

修改：
- `apps/web/app/profile/page.tsx` — 整页重写：Banner + Tab + 卡片布局 + 保存 spinner + 已保存淡出

不变：
- `apps/web/components/layout/Sidebar.tsx`（已正确）
- `apps/web/stores/useAuthStore.ts`（已加 refreshUser）
- `apps/web/components/FieldError.tsx`（复用）

## 验证

1. `pnpm type-check` 0 错误
2. `pnpm build` 14+1 个页面成功
3. 进入 `/profile`：
   - 顶部渐变 Banner，左下圆头像 + 姓名/角色/部门/联系方式
   - 右上角白底红字退出按钮
   - Banner 下 Tab 切换条 + 卡片
4. 改姓名后保存：
   - 按钮 spinner 一闪
   - 显示绿色"已保存 ✓"3 秒后淡出
   - Banner 上的姓名立即更新（refreshUser 生效）
5. 修改密码：spinner + "密码已修改，下次登录生效" 3 秒淡出
6. 取消按钮：恢复初始值
