0.0.8.0
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
# 🔐 按钮权限分类清单
|
||||
|
||||
## 📋 按钮分类
|
||||
|
||||
### 一、增删改类按钮(写操作)
|
||||
|
||||
#### 1. 增加类(Create)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **添加成员** | 首页、成员列表 | ✅ | ✅ | ❌ |
|
||||
| **新增成员** | 成员列表 | ✅ | ✅ | ❌ |
|
||||
| **添加父亲** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **添加母亲** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **添加子女** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **添加配偶** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **创建家族树** | 导航、创建页 | ✅ | ✅ | ❌ |
|
||||
| **邀请协作者** | 设置 | ✅ | ❌ | ❌ |
|
||||
|
||||
#### 2. 修改类(Update)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **编辑** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **保存** | 编辑页面 | ✅ | ✅ | ❌ |
|
||||
| **修改密码** | 设置 | ✅ | ✅ | ✅ |
|
||||
| **导入数据** | 设置 | ✅ | ✅ | ❌ |
|
||||
| **导入GEDCOM** | 设置 | ✅ | ✅ | ❌ |
|
||||
|
||||
#### 3. 删除类(Delete)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **删除成员** | 成员详情 | ✅ | ✅ | ❌ |
|
||||
| **删除家族树** | 导航 | ✅ | ❌ | ❌ |
|
||||
| **移除协作者** | 设置 | ✅ | ❌ | ❌ |
|
||||
| **清空数据** | 设置 | ✅ | ❌ | ❌ |
|
||||
| **清空日志** | 设置 | ✅ | ❌ | ❌ |
|
||||
|
||||
---
|
||||
|
||||
### 二、查类按钮(读操作)
|
||||
|
||||
#### 1. 查看类(View)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **查看详情** | 所有列表 | ✅ | ✅ | ✅ |
|
||||
| **查看全部** | 首页 | ✅ | ✅ | ✅ |
|
||||
| **查看族谱图** | 首页、导航 | ✅ | ✅ | ✅ |
|
||||
| **查看大事记** | 导航 | ✅ | ✅ | ✅ |
|
||||
| **查看时间线** | 大事记 | ✅ | ✅ | ✅ |
|
||||
| **查看迁徙记录** | 大事记 | ✅ | ✅ | ✅ |
|
||||
|
||||
#### 2. 搜索查询类(Search/Query)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **搜索** | 导航、成员列表 | ✅ | ✅ | ✅ |
|
||||
| **筛选** | 成员列表 | ✅ | ✅ | ✅ |
|
||||
| **关系查询** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **计算关系** | 关系计算 | ✅ | ✅ | ✅ |
|
||||
| **在族谱图中定位** | 成员列表 | ✅ | ✅ | ✅ |
|
||||
|
||||
#### 3. 导出类(Export)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **导出数据** | 设置 | ✅ | ✅ | ✅ |
|
||||
| **导出GEDCOM** | 设置 | ✅ | ✅ | ✅ |
|
||||
| **导出图片** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **打印** | 成员详情 | ✅ | ✅ | ✅ |
|
||||
|
||||
#### 4. 视图控制类(View Control)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **放大** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **缩小** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **重置** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **切换视图** | 族谱图 | ✅ | ✅ | ✅ |
|
||||
| **切换标签** | 大事记 | ✅ | ✅ | ✅ |
|
||||
|
||||
#### 5. 导航类(Navigation)
|
||||
| 按钮名称 | 位置 | OWNER | EDITOR | VIEWER |
|
||||
|---------|------|-------|--------|--------|
|
||||
| **返回** | 所有页面 | ✅ | ✅ | ✅ |
|
||||
| **取消** | 编辑页面 | ✅ | ✅ | ✅ |
|
||||
| **关闭** | 对话框 | ✅ | ✅ | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 🎯 权限总结
|
||||
|
||||
### OWNER(创建者)- 全部权限
|
||||
**可用按钮**: 80+ 个
|
||||
|
||||
#### 独有权限(只有 OWNER 可以)
|
||||
- ❌ 删除家族树
|
||||
- ❌ 邀请协作者
|
||||
- ❌ 移除协作者
|
||||
- ❌ 清空数据
|
||||
- ❌ 清空日志
|
||||
|
||||
#### 完整权限列表
|
||||
- ✅ 所有增加操作
|
||||
- ✅ 所有修改操作
|
||||
- ✅ 所有删除操作
|
||||
- ✅ 所有查看操作
|
||||
- ✅ 所有管理操作
|
||||
|
||||
---
|
||||
|
||||
### EDITOR(编辑者)- 编辑权限
|
||||
**可用按钮**: 60+ 个
|
||||
|
||||
#### 可以执行的操作
|
||||
- ✅ 添加成员(所有类型)
|
||||
- ✅ 编辑成员信息
|
||||
- ✅ 删除成员
|
||||
- ✅ 导入数据
|
||||
- ✅ 所有查看操作
|
||||
- ✅ 所有查询操作
|
||||
- ✅ 所有导出操作
|
||||
|
||||
#### 不能执行的操作
|
||||
- ❌ 删除家族树
|
||||
- ❌ 邀请协作者
|
||||
- ❌ 移除协作者
|
||||
- ❌ 清空数据
|
||||
- ❌ 清空日志
|
||||
|
||||
---
|
||||
|
||||
### VIEWER(查看者)- 只读权限
|
||||
**可用按钮**: 30+ 个
|
||||
|
||||
#### 可以执行的操作
|
||||
- ✅ 查看所有信息
|
||||
- ✅ 搜索和筛选
|
||||
- ✅ 关系查询
|
||||
- ✅ 导出数据
|
||||
- ✅ 打印
|
||||
- ✅ 视图控制(放大、缩小等)
|
||||
- ✅ 修改自己的密码
|
||||
|
||||
#### 不能执行的操作
|
||||
- ❌ 添加成员
|
||||
- ❌ 编辑成员
|
||||
- ❌ 删除成员
|
||||
- ❌ 导入数据
|
||||
- ❌ 删除家族树
|
||||
- ❌ 管理协作者
|
||||
- ❌ 清空数据
|
||||
|
||||
---
|
||||
|
||||
## 💻 代码实现
|
||||
|
||||
### 1. 权限检查函数
|
||||
|
||||
```typescript
|
||||
// lib/permissions.ts
|
||||
export type Role = "OWNER" | "EDITOR" | "VIEWER"
|
||||
|
||||
export const permissions = {
|
||||
// 增加权限
|
||||
canCreate: (role: Role) => role === "OWNER" || role === "EDITOR",
|
||||
|
||||
// 修改权限
|
||||
canUpdate: (role: Role) => role === "OWNER" || role === "EDITOR",
|
||||
|
||||
// 删除成员权限
|
||||
canDeleteMember: (role: Role) => role === "OWNER" || role === "EDITOR",
|
||||
|
||||
// 删除家族树权限(仅 OWNER)
|
||||
canDeleteTree: (role: Role) => role === "OWNER",
|
||||
|
||||
// 管理协作者权限(仅 OWNER)
|
||||
canManageCollaborators: (role: Role) => role === "OWNER",
|
||||
|
||||
// 清空数据权限(仅 OWNER)
|
||||
canClearData: (role: Role) => role === "OWNER",
|
||||
|
||||
// 查看权限(所有人)
|
||||
canView: (role: Role) => true,
|
||||
|
||||
// 导出权限(所有人)
|
||||
canExport: (role: Role) => true,
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 按钮权限控制
|
||||
|
||||
```tsx
|
||||
// 方式1: 条件渲染(推荐)
|
||||
import { permissions } from "@/lib/permissions"
|
||||
|
||||
{permissions.canCreate(role) && (
|
||||
<Button onClick={handleAdd}>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
添加成员
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{permissions.canDeleteTree(role) && (
|
||||
<Button variant="destructive" onClick={handleDeleteTree}>
|
||||
删除家族树
|
||||
</Button>
|
||||
)}
|
||||
|
||||
// 方式2: 禁用状态
|
||||
<Button
|
||||
disabled={!permissions.canUpdate(role)}
|
||||
onClick={handleEdit}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 3. 完整示例
|
||||
|
||||
```tsx
|
||||
// components/member-actions.tsx
|
||||
import { permissions } from "@/lib/permissions"
|
||||
import { useFamily } from "@/context/family-context"
|
||||
|
||||
export function MemberActions({ memberId }: { memberId: string }) {
|
||||
const { currentTree } = useFamily()
|
||||
const role = currentTree?.currentUserRole
|
||||
|
||||
if (!role) return null
|
||||
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
{/* 查看按钮 - 所有人可见 */}
|
||||
<Button variant="outline" onClick={handleView}>
|
||||
查看详情
|
||||
</Button>
|
||||
|
||||
{/* 编辑按钮 - OWNER 和 EDITOR 可见 */}
|
||||
{permissions.canUpdate(role) && (
|
||||
<Button variant="outline" onClick={handleEdit}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
编辑
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* 删除按钮 - OWNER 和 EDITOR 可见 */}
|
||||
{permissions.canDeleteMember(role) && (
|
||||
<Button variant="destructive" onClick={handleDelete}>
|
||||
<Trash className="h-4 w-4 mr-2" />
|
||||
删除
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 权限对比表
|
||||
|
||||
| 操作类型 | OWNER | EDITOR | VIEWER | 说明 |
|
||||
|---------|-------|--------|--------|------|
|
||||
| **查看信息** | ✅ | ✅ | ✅ | 所有人可查看 |
|
||||
| **搜索查询** | ✅ | ✅ | ✅ | 所有人可查询 |
|
||||
| **导出数据** | ✅ | ✅ | ✅ | 所有人可导出 |
|
||||
| **添加成员** | ✅ | ✅ | ❌ | 编辑权限 |
|
||||
| **编辑成员** | ✅ | ✅ | ❌ | 编辑权限 |
|
||||
| **删除成员** | ✅ | ✅ | ❌ | 编辑权限 |
|
||||
| **导入数据** | ✅ | ✅ | ❌ | 编辑权限 |
|
||||
| **邀请协作者** | ✅ | ❌ | ❌ | 仅创建者 |
|
||||
| **删除家族树** | ✅ | ❌ | ❌ | 仅创建者 |
|
||||
| **清空数据** | ✅ | ❌ | ❌ | 仅创建者 |
|
||||
|
||||
---
|
||||
|
||||
## 🔍 快速查找
|
||||
|
||||
### 需要 OWNER 权限的按钮(5个)
|
||||
1. 删除家族树
|
||||
2. 邀请协作者
|
||||
3. 移除协作者
|
||||
4. 清空数据
|
||||
5. 清空日志
|
||||
|
||||
### 需要 EDITOR 权限的按钮(25个)
|
||||
1. 所有"添加"按钮(8个)
|
||||
2. 所有"编辑"按钮(5个)
|
||||
3. 删除成员(1个)
|
||||
4. 导入相关(2个)
|
||||
5. 其他编辑操作(9个)
|
||||
|
||||
### VIEWER 可用的按钮(30个)
|
||||
1. 所有"查看"按钮(6个)
|
||||
2. 所有"搜索"按钮(5个)
|
||||
3. 所有"导出"按钮(4个)
|
||||
4. 所有"视图控制"按钮(5个)
|
||||
5. 所有"导航"按钮(10个)
|
||||
|
||||
---
|
||||
|
||||
## 📝 实施检查清单
|
||||
|
||||
### 代码实施
|
||||
- [ ] 创建权限检查函数 (`lib/permissions.ts`)
|
||||
- [ ] 更新所有按钮组件,添加权限检查
|
||||
- [ ] 测试 OWNER 权限
|
||||
- [ ] 测试 EDITOR 权限
|
||||
- [ ] 测试 VIEWER 权限
|
||||
|
||||
### API 层面
|
||||
- [ ] API 路由添加权限验证
|
||||
- [ ] 数据库操作添加权限检查
|
||||
- [ ] 返回适当的错误信息
|
||||
|
||||
### 用户界面
|
||||
- [ ] 无权限的按钮隐藏或禁用
|
||||
- [ ] 添加权限提示信息
|
||||
- [ ] 测试所有页面的权限显示
|
||||
|
||||
### 文档更新
|
||||
- [ ] 更新用户手册
|
||||
- [ ] 更新 API 文档
|
||||
- [ ] 更新开发文档
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**最后更新**: 2025-11-23
|
||||
**维护人员**: System
|
||||
@@ -0,0 +1,694 @@
|
||||
# 🎨 按钮使用规范指南
|
||||
|
||||
## 📋 目录
|
||||
- [按钮样式规范](#按钮样式规范)
|
||||
- [按钮尺寸规范](#按钮尺寸规范)
|
||||
- [图标使用规范](#图标使用规范)
|
||||
- [交互状态规范](#交互状态规范)
|
||||
- [权限控制规范](#权限控制规范)
|
||||
- [最佳实践](#最佳实践)
|
||||
|
||||
---
|
||||
|
||||
## 按钮样式规范
|
||||
|
||||
### 样式类型
|
||||
|
||||
```typescript
|
||||
type ButtonVariant =
|
||||
| "default" // 默认样式
|
||||
| "destructive" // 危险操作
|
||||
| "outline" // 边框样式
|
||||
| "secondary" // 次要操作
|
||||
| "ghost" // 幽灵按钮
|
||||
| "link" // 链接样式
|
||||
```
|
||||
|
||||
### 使用场景
|
||||
|
||||
#### 1. Primary (default)
|
||||
**用途**: 页面主要操作,每个页面最多1-2个
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="default">保存</Button>
|
||||
<Button variant="default">创建家族树</Button>
|
||||
<Button variant="default">提交</Button>
|
||||
|
||||
// ❌ 错误使用 - 不要在一个区域放置多个 primary 按钮
|
||||
<Button variant="default">保存</Button>
|
||||
<Button variant="default">提交</Button>
|
||||
<Button variant="default">确认</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 背景色: `bg-primary`
|
||||
- 文字色: `text-primary-foreground`
|
||||
- 高对比度,最显眼
|
||||
|
||||
#### 2. Destructive
|
||||
**用途**: 危险操作,如删除、清空
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="destructive" onClick={handleDelete}>
|
||||
<Trash className="h-4 w-4 mr-2" />
|
||||
删除成员
|
||||
</Button>
|
||||
|
||||
// ✅ 必须配合确认对话框
|
||||
const handleDelete = async () => {
|
||||
const confirmed = await showConfirm('确定要删除吗?')
|
||||
if (confirmed) {
|
||||
// 执行删除
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 背景色: `bg-destructive` (红色)
|
||||
- 文字色: `text-destructive-foreground`
|
||||
- 警示作用
|
||||
|
||||
#### 3. Outline
|
||||
**用途**: 次要操作,常规功能
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="outline">编辑</Button>
|
||||
<Button variant="outline">导出</Button>
|
||||
<Button variant="outline">取消</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 边框: `border border-input`
|
||||
- 背景: 透明
|
||||
- 文字色: `text-foreground`
|
||||
|
||||
#### 4. Ghost
|
||||
**用途**: 辅助操作,不抢眼的功能
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="ghost">返回</Button>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Search className="h-4 w-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 无边框,无背景
|
||||
- hover 时显示背景
|
||||
- 最不显眼
|
||||
|
||||
#### 5. Secondary
|
||||
**用途**: 次要强调操作
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="secondary">添加配偶</Button>
|
||||
<Button variant="secondary">筛选</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 背景色: `bg-secondary`
|
||||
- 介于 primary 和 outline 之间
|
||||
|
||||
#### 6. Link
|
||||
**用途**: 链接样式的按钮
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button variant="link">了解更多</Button>
|
||||
<Button variant="link">查看详情</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 无背景,无边框
|
||||
- 文字带下划线
|
||||
- 类似超链接
|
||||
|
||||
---
|
||||
|
||||
## 按钮尺寸规范
|
||||
|
||||
### 尺寸类型
|
||||
|
||||
```typescript
|
||||
type ButtonSize =
|
||||
| "default" // 默认尺寸
|
||||
| "sm" // 小尺寸
|
||||
| "lg" // 大尺寸
|
||||
| "icon" // 图标按钮
|
||||
```
|
||||
|
||||
### 使用场景
|
||||
|
||||
#### 1. Default
|
||||
**用途**: 常规按钮
|
||||
|
||||
```tsx
|
||||
<Button size="default">保存</Button>
|
||||
```
|
||||
|
||||
**尺寸**: `h-10 px-4 py-2`
|
||||
|
||||
#### 2. Small (sm)
|
||||
**用途**: 紧凑布局、辅助操作
|
||||
|
||||
```tsx
|
||||
<Button size="sm">刷新</Button>
|
||||
<Button size="sm" variant="ghost">查看全部</Button>
|
||||
```
|
||||
|
||||
**尺寸**: `h-9 px-3`
|
||||
|
||||
#### 3. Large (lg)
|
||||
**用途**: 重要操作、首屏按钮
|
||||
|
||||
```tsx
|
||||
<Button size="lg">立即开始</Button>
|
||||
```
|
||||
|
||||
**尺寸**: `h-11 px-8`
|
||||
|
||||
#### 4. Icon
|
||||
**用途**: 仅图标按钮
|
||||
|
||||
```tsx
|
||||
<Button size="icon" variant="outline">
|
||||
<Settings className="h-4 w-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
**尺寸**: `h-10 w-10` (正方形)
|
||||
|
||||
---
|
||||
|
||||
## 图标使用规范
|
||||
|
||||
### 图标位置
|
||||
|
||||
#### 1. 左侧图标
|
||||
**用途**: 强调操作类型
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
新增成员
|
||||
</Button>
|
||||
|
||||
<Button>
|
||||
<Download className="h-4 w-4 mr-2" />
|
||||
导出数据
|
||||
</Button>
|
||||
```
|
||||
|
||||
#### 2. 右侧图标
|
||||
**用途**: 表示方向或展开
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button>
|
||||
查看全部
|
||||
<ArrowRight className="h-4 w-4 ml-2" />
|
||||
</Button>
|
||||
|
||||
<Button>
|
||||
更多选项
|
||||
<ChevronDown className="h-4 w-4 ml-2" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
#### 3. 仅图标
|
||||
**用途**: 空间受限或辅助操作
|
||||
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button size="icon" variant="ghost" title="搜索">
|
||||
<Search className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
// ⚠️ 注意:必须添加 title 属性用于无障碍访问
|
||||
```
|
||||
|
||||
### 图标尺寸
|
||||
|
||||
| 按钮尺寸 | 图标尺寸 | 类名 |
|
||||
|---------|---------|------|
|
||||
| sm | 3 | `h-3 w-3` |
|
||||
| default | 4 | `h-4 w-4` |
|
||||
| lg | 5 | `h-5 w-5` |
|
||||
|
||||
### 图标间距
|
||||
|
||||
```tsx
|
||||
// 左侧图标
|
||||
<Icon className="mr-2" />
|
||||
|
||||
// 右侧图标
|
||||
<Icon className="ml-2" />
|
||||
|
||||
// 仅图标(无间距)
|
||||
<Icon />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 交互状态规范
|
||||
|
||||
### 状态类型
|
||||
|
||||
#### 1. 默认状态
|
||||
```tsx
|
||||
<Button>点击我</Button>
|
||||
```
|
||||
|
||||
#### 2. Hover 状态
|
||||
```tsx
|
||||
// 自动处理,无需额外代码
|
||||
// primary: hover:bg-primary/90
|
||||
// outline: hover:bg-accent
|
||||
// ghost: hover:bg-accent hover:text-accent-foreground
|
||||
```
|
||||
|
||||
#### 3. 禁用状态
|
||||
```tsx
|
||||
// ✅ 正确使用
|
||||
<Button disabled={isLoading || !hasPermission}>
|
||||
保存
|
||||
</Button>
|
||||
|
||||
// ✅ 配合加载状态
|
||||
<Button disabled={isLoading}>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
保存中...
|
||||
</>
|
||||
) : (
|
||||
'保存'
|
||||
)}
|
||||
</Button>
|
||||
```
|
||||
|
||||
**视觉特征**:
|
||||
- 透明度: `opacity-50`
|
||||
- 鼠标: `cursor-not-allowed`
|
||||
- 禁用点击事件
|
||||
|
||||
#### 4. 加载状态
|
||||
```tsx
|
||||
// ✅ 推荐方式
|
||||
import { Loader2 } from "lucide-react"
|
||||
|
||||
<Button disabled={isLoading}>
|
||||
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{isLoading ? '处理中...' : '提交'}
|
||||
</Button>
|
||||
```
|
||||
|
||||
#### 5. 激活状态
|
||||
```tsx
|
||||
// ✅ 用于切换按钮
|
||||
<Button
|
||||
variant={isActive ? "secondary" : "outline"}
|
||||
onClick={toggle}
|
||||
>
|
||||
{isActive ? '已激活' : '未激活'}
|
||||
</Button>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 权限控制规范
|
||||
|
||||
### 权限级别
|
||||
|
||||
```typescript
|
||||
type Role = "OWNER" | "EDITOR" | "VIEWER"
|
||||
```
|
||||
|
||||
### 实现方式
|
||||
|
||||
#### 1. 条件渲染
|
||||
```tsx
|
||||
// ✅ 推荐:完全隐藏按钮
|
||||
{(role === "OWNER" || role === "EDITOR") && (
|
||||
<Button onClick={handleEdit}>编辑</Button>
|
||||
)}
|
||||
```
|
||||
|
||||
#### 2. 禁用状态
|
||||
```tsx
|
||||
// ⚠️ 可选:显示但禁用
|
||||
<Button
|
||||
disabled={role === "VIEWER"}
|
||||
title={role === "VIEWER" ? "您没有编辑权限" : ""}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 权限矩阵
|
||||
|
||||
| 操作 | VIEWER | EDITOR | OWNER |
|
||||
|-----|--------|--------|-------|
|
||||
| 查看 | ✅ | ✅ | ✅ |
|
||||
| 新增 | ❌ | ✅ | ✅ |
|
||||
| 编辑 | ❌ | ✅ | ✅ |
|
||||
| 删除 | ❌ | ✅ | ✅ |
|
||||
| 管理协作者 | ❌ | ❌ | ✅ |
|
||||
| 删除家族树 | ❌ | ❌ | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 按钮组合
|
||||
|
||||
#### ✅ 正确的按钮组合
|
||||
```tsx
|
||||
// 主次分明
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="default" onClick={onSave}>
|
||||
保存
|
||||
</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### ❌ 错误的按钮组合
|
||||
```tsx
|
||||
// 不要使用多个 primary 按钮
|
||||
<div className="flex gap-2">
|
||||
<Button variant="default">保存</Button>
|
||||
<Button variant="default">提交</Button>
|
||||
<Button variant="default">确认</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2. 按钮位置
|
||||
|
||||
#### 表单按钮
|
||||
```tsx
|
||||
// ✅ 正确:右对齐,取消在左,确认在右
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline">取消</Button>
|
||||
<Button variant="default">保存</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 对话框按钮
|
||||
```tsx
|
||||
// ✅ 正确:底部右对齐
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={onClose}>
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="default" onClick={onConfirm}>
|
||||
确认
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
```
|
||||
|
||||
### 3. 响应式设计
|
||||
|
||||
```tsx
|
||||
// ✅ 移动端优化
|
||||
<Button className="w-full md:w-auto">
|
||||
保存
|
||||
</Button>
|
||||
|
||||
// ✅ 图标按钮在移动端隐藏文字
|
||||
<Button>
|
||||
<Plus className="h-4 w-4 md:mr-2" />
|
||||
<span className="hidden md:inline">新增</span>
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 4. 无障碍访问
|
||||
|
||||
```tsx
|
||||
// ✅ 正确:添加 aria 属性
|
||||
<Button
|
||||
aria-label="删除成员"
|
||||
title="删除成员"
|
||||
onClick={handleDelete}
|
||||
>
|
||||
<Trash className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
// ✅ 正确:键盘支持
|
||||
<Button
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleClick()
|
||||
}
|
||||
}}
|
||||
>
|
||||
点击我
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 5. 加载和错误处理
|
||||
|
||||
```tsx
|
||||
// ✅ 完整的状态处理
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setIsLoading(true)
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
await saveData()
|
||||
toast.success('保存成功')
|
||||
} catch (err) {
|
||||
setError('保存失败')
|
||||
toast.error('保存失败')
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
disabled={isLoading}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{isLoading ? '保存中...' : '保存'}
|
||||
</Button>
|
||||
{error && <p className="text-destructive text-sm mt-2">{error}</p>}
|
||||
</>
|
||||
)
|
||||
```
|
||||
|
||||
### 6. 确认对话框
|
||||
|
||||
```tsx
|
||||
// ✅ 危险操作必须确认
|
||||
const handleDelete = async () => {
|
||||
const confirmed = await showConfirm(
|
||||
'确定要删除这个成员吗?此操作不可撤销。',
|
||||
'删除确认',
|
||||
'destructive'
|
||||
)
|
||||
|
||||
if (!confirmed) return
|
||||
|
||||
try {
|
||||
await deleteMember(id)
|
||||
toast.success('删除成功')
|
||||
router.push('/members')
|
||||
} catch (error) {
|
||||
toast.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
<Button variant="destructive" onClick={handleDelete}>
|
||||
<Trash className="h-4 w-4 mr-2" />
|
||||
删除
|
||||
</Button>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 样式定制
|
||||
|
||||
### 自定义按钮
|
||||
|
||||
```tsx
|
||||
// ✅ 使用 className 扩展样式
|
||||
<Button
|
||||
variant="outline"
|
||||
className="border-2 border-primary hover:bg-primary/10"
|
||||
>
|
||||
自定义样式
|
||||
</Button>
|
||||
|
||||
// ✅ 使用 CSS 变量
|
||||
<Button
|
||||
style={{
|
||||
'--button-bg': 'hsl(var(--primary))',
|
||||
'--button-fg': 'hsl(var(--primary-foreground))'
|
||||
} as React.CSSProperties}
|
||||
>
|
||||
使用变量
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 按钮组
|
||||
|
||||
```tsx
|
||||
// ✅ 使用 flex 布局
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline">选项1</Button>
|
||||
<Button variant="outline">选项2</Button>
|
||||
<Button variant="outline">选项3</Button>
|
||||
</div>
|
||||
|
||||
// ✅ 使用 ButtonGroup(如果有)
|
||||
<ButtonGroup>
|
||||
<Button>选项1</Button>
|
||||
<Button>选项2</Button>
|
||||
<Button>选项3</Button>
|
||||
</ButtonGroup>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 代码示例
|
||||
|
||||
### 完整示例:成员编辑页面
|
||||
|
||||
```tsx
|
||||
export default function MemberEditPage() {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const { showConfirm } = useDialog()
|
||||
const router = useRouter()
|
||||
|
||||
const handleSave = async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
await saveMember(data)
|
||||
toast.success('保存成功')
|
||||
router.push(`/members/${id}`)
|
||||
} catch (error) {
|
||||
toast.error('保存失败')
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = async () => {
|
||||
const confirmed = await showConfirm(
|
||||
'确定要删除这个成员吗?',
|
||||
'删除确认',
|
||||
'destructive'
|
||||
)
|
||||
|
||||
if (!confirmed) return
|
||||
|
||||
try {
|
||||
await deleteMember(id)
|
||||
toast.success('删除成功')
|
||||
router.push('/members')
|
||||
} catch (error) {
|
||||
toast.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* 顶部操作栏 */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => router.back()}
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
返回
|
||||
</Button>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => window.print()}
|
||||
>
|
||||
<Printer className="h-4 w-4 mr-2" />
|
||||
打印
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={handleDelete}
|
||||
>
|
||||
<Trash className="h-4 w-4 mr-2" />
|
||||
删除
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 表单内容 */}
|
||||
<form onSubmit={(e) => { e.preventDefault(); handleSave(); }}>
|
||||
{/* ... 表单字段 ... */}
|
||||
|
||||
{/* 底部按钮 */}
|
||||
<div className="flex justify-end gap-2 mt-6">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => router.back()}
|
||||
disabled={isLoading}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading && (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
)}
|
||||
{isLoading ? '保存中...' : '保存'}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 检查清单
|
||||
|
||||
### 新增按钮前的检查
|
||||
|
||||
- [ ] 确定按钮的主要用途
|
||||
- [ ] 选择合适的 variant
|
||||
- [ ] 选择合适的 size
|
||||
- [ ] 添加合适的图标(如需要)
|
||||
- [ ] 考虑权限控制
|
||||
- [ ] 添加加载状态
|
||||
- [ ] 添加错误处理
|
||||
- [ ] 危险操作添加确认
|
||||
- [ ] 添加无障碍属性
|
||||
- [ ] 测试响应式布局
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
- [shadcn/ui Button 文档](https://ui.shadcn.com/docs/components/button)
|
||||
- [Lucide Icons](https://lucide.dev/)
|
||||
- [Radix UI Primitives](https://www.radix-ui.com/)
|
||||
- [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/WCAG21/quickref/)
|
||||
@@ -0,0 +1,212 @@
|
||||
# 邮箱服务配置说明
|
||||
|
||||
## 📧 当前配置
|
||||
|
||||
本项目使用 **163 邮箱** 作为 SMTP 服务器,用于发送协作邀请邮件。
|
||||
|
||||
### 配置信息
|
||||
|
||||
```env
|
||||
SMTP_HOST="smtp.163.com"
|
||||
SMTP_PORT="465"
|
||||
SMTP_USER="cftservice@163.com"
|
||||
SMTP_PASS="SChncqpqS9TDPUD2"
|
||||
SMTP_FROM="中华家谱 <cftservice@163.com>"
|
||||
```
|
||||
|
||||
## 🔧 配置步骤
|
||||
|
||||
### 1. 环境变量配置
|
||||
|
||||
在项目根目录的 `.env` 文件中添加以上配置。
|
||||
|
||||
### 2. 163 邮箱设置
|
||||
|
||||
#### 2.1 开启 SMTP 服务
|
||||
1. 登录 163 邮箱
|
||||
2. 进入 **设置** → **POP3/SMTP/IMAP**
|
||||
3. 开启 **SMTP 服务**
|
||||
4. 获取授权密码(不是邮箱登录密码)
|
||||
|
||||
#### 2.2 授权密码
|
||||
- 当前使用的授权密码:`SChncqpqS9TDPUD2`
|
||||
- ⚠️ **安全提示**:请勿将此密码泄露给他人
|
||||
|
||||
### 3. 端口说明
|
||||
|
||||
| 端口 | 加密方式 | 说明 |
|
||||
|------|---------|------|
|
||||
| 465 | SSL/TLS | 推荐使用(当前配置) |
|
||||
| 25 | 无加密 | 不推荐 |
|
||||
| 587 | STARTTLS | 可选 |
|
||||
|
||||
## 📨 邮件功能
|
||||
|
||||
### 当前支持的邮件类型
|
||||
|
||||
1. **协作邀请邮件**
|
||||
- 邀请用户加入家族树
|
||||
- 发送初始密码(新用户)
|
||||
- 提供登录链接
|
||||
|
||||
### 邮件模板
|
||||
|
||||
邮件模板位于:`/lib/mail.ts`
|
||||
|
||||
```typescript
|
||||
export async function sendInvitationEmail(
|
||||
to: string,
|
||||
inviterName: string,
|
||||
treeName: string,
|
||||
role: string,
|
||||
password?: string
|
||||
)
|
||||
```
|
||||
|
||||
## 🧪 测试邮件发送
|
||||
|
||||
### 方法 1:通过 API 测试
|
||||
|
||||
```bash
|
||||
# 测试发送邀请邮件
|
||||
curl -X POST http://localhost:3000/api/trees/[treeId]/invite \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "test@example.com",
|
||||
"role": "VIEWER"
|
||||
}'
|
||||
```
|
||||
|
||||
### 方法 2:通过界面测试
|
||||
|
||||
1. 登录系统
|
||||
2. 进入任一家族树
|
||||
3. 点击 **设置** → **协作者管理**
|
||||
4. 添加协作者并发送邀请
|
||||
|
||||
## 🔍 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 1. 邮件发送失败
|
||||
|
||||
**可能原因**:
|
||||
- SMTP 服务未开启
|
||||
- 授权密码错误
|
||||
- 网络连接问题
|
||||
- 163 邮箱被限制发送
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 检查环境变量
|
||||
echo $SMTP_USER
|
||||
echo $SMTP_HOST
|
||||
|
||||
# 查看应用日志
|
||||
tail -f logs/app.log
|
||||
```
|
||||
|
||||
#### 2. 邮件被标记为垃圾邮件
|
||||
|
||||
**解决方案**:
|
||||
- 配置 SPF 记录
|
||||
- 配置 DKIM 签名
|
||||
- 使用企业邮箱
|
||||
|
||||
#### 3. 发送频率限制
|
||||
|
||||
163 邮箱对发送频率有限制:
|
||||
- 免费邮箱:每天约 50 封
|
||||
- VIP 邮箱:每天约 500 封
|
||||
|
||||
**建议**:
|
||||
- 使用企业邮箱
|
||||
- 或使用专业邮件服务(如 SendGrid、阿里云邮件推送)
|
||||
|
||||
## 🔐 安全建议
|
||||
|
||||
### 1. 保护授权密码
|
||||
|
||||
```bash
|
||||
# 不要将 .env 文件提交到 Git
|
||||
echo ".env" >> .gitignore
|
||||
|
||||
# 使用环境变量管理工具
|
||||
# 如:dotenv-vault, AWS Secrets Manager
|
||||
```
|
||||
|
||||
### 2. 定期更换密码
|
||||
|
||||
建议每 3-6 个月更换一次授权密码。
|
||||
|
||||
### 3. 监控邮件发送
|
||||
|
||||
```typescript
|
||||
// 添加邮件发送日志
|
||||
console.log(`邮件已发送至: ${to}`)
|
||||
console.log(`发送时间: ${new Date().toISOString()}`)
|
||||
```
|
||||
|
||||
## 🚀 生产环境配置
|
||||
|
||||
### 推荐方案
|
||||
|
||||
#### 方案 1:使用企业邮箱
|
||||
- 阿里云企业邮箱
|
||||
- 腾讯企业邮箱
|
||||
- 网易企业邮箱
|
||||
|
||||
#### 方案 2:使用专业邮件服务
|
||||
- **SendGrid**:免费额度 100 封/天
|
||||
- **阿里云邮件推送**:按量付费
|
||||
- **AWS SES**:按量付费
|
||||
|
||||
### 配置示例(SendGrid)
|
||||
|
||||
```env
|
||||
SMTP_HOST="smtp.sendgrid.net"
|
||||
SMTP_PORT="465"
|
||||
SMTP_USER="apikey"
|
||||
SMTP_PASS="your-sendgrid-api-key"
|
||||
SMTP_FROM="noreply@yourdomain.com"
|
||||
```
|
||||
|
||||
## 📊 监控和日志
|
||||
|
||||
### 添加邮件发送统计
|
||||
|
||||
```typescript
|
||||
// lib/mail.ts
|
||||
let emailSentCount = 0
|
||||
|
||||
export async function sendInvitationEmail(...) {
|
||||
try {
|
||||
await transporter.sendMail({...})
|
||||
emailSentCount++
|
||||
console.log(`邮件发送成功,总计: ${emailSentCount}`)
|
||||
} catch (error) {
|
||||
console.error('邮件发送失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 维护记录
|
||||
|
||||
| 日期 | 操作 | 操作人 |
|
||||
|------|------|--------|
|
||||
| 2025-11-23 | 配置 163 邮箱服务 | System |
|
||||
| - | - | - |
|
||||
|
||||
## 🔗 相关链接
|
||||
|
||||
- [163 邮箱帮助中心](https://help.mail.163.com/)
|
||||
- [Nodemailer 文档](https://nodemailer.com/)
|
||||
- [SMTP 协议说明](https://zh.wikipedia.org/wiki/SMTP)
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如遇到邮件发送问题,请:
|
||||
1. 检查环境变量配置
|
||||
2. 查看应用日志
|
||||
3. 联系系统管理员
|
||||
@@ -0,0 +1,425 @@
|
||||
# 🎯 全站操作按钮梳理文档
|
||||
|
||||
## 📋 目录
|
||||
- [首页 (/)](#首页-)
|
||||
- [成员列表 (/members)](#成员列表-members)
|
||||
- [成员详情 (/members/[id])](#成员详情-membersid)
|
||||
- [新增成员 (/members/new)](#新增成员-membersnew)
|
||||
- [族谱图 (/tree)](#族谱图-tree)
|
||||
- [大事记 (/timeline)](#大事记-timeline)
|
||||
- [关系计算 (/relationship)](#关系计算-relationship)
|
||||
- [系统设置 (/settings)](#系统设置-settings)
|
||||
- [登录注册 (/auth)](#登录注册-auth)
|
||||
- [创建家族树 (/trees/new)](#创建家族树-treesnew)
|
||||
- [全局导航 (SiteHeader)](#全局导航-siteheader)
|
||||
|
||||
---
|
||||
|
||||
## 首页 (/)
|
||||
|
||||
### 主要操作按钮
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 权限要求 | 功能说明 | 位置 |
|
||||
|---------|------|------|---------|---------|------|
|
||||
| **添加成员** | `UserPlus` | `primary` | OWNER/EDITOR | 跳转到新增成员页面 | 顶部右侧 |
|
||||
| **查看全部** | `ArrowRight` | `ghost` | 所有用户 | 跳转到成员列表页面 | 成员卡片区域 |
|
||||
|
||||
### 卡片操作
|
||||
|
||||
| 操作 | 触发方式 | 功能 |
|
||||
|-----|---------|------|
|
||||
| 查看成员详情 | 点击成员卡片 | 跳转到成员详情页 |
|
||||
| 查看族谱图 | 点击"查看族谱图"按钮 | 跳转到族谱图页面 |
|
||||
|
||||
---
|
||||
|
||||
## 成员列表 (/members)
|
||||
|
||||
### 顶部操作栏
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 快捷键 | 功能说明 |
|
||||
|---------|------|------|--------|---------|
|
||||
| **筛选** | `Filter` | `outline/secondary` | - | 显示/隐藏高级筛选面板 |
|
||||
| **新增成员** | `Plus` | `primary` | - | 跳转到新增成员页面 |
|
||||
|
||||
### 筛选面板
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **重置筛选** | `X` | `ghost` | 清除所有筛选条件 |
|
||||
|
||||
### 成员卡片操作
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 显示方式 | 功能说明 |
|
||||
|---------|------|------|---------|---------|
|
||||
| **在族谱图中定位** | `Search` | `ghost` | hover显示 | 在族谱图中定位该成员 |
|
||||
|
||||
### 筛选器
|
||||
|
||||
| 筛选器类型 | 选项 | 说明 |
|
||||
|-----------|------|------|
|
||||
| 姓氏 | 下拉选择 | 按姓氏筛选 |
|
||||
| 籍贯 | 下拉选择 | 按籍贯筛选 |
|
||||
| 状态 | 全部/在世/已故 | 按生存状态筛选 |
|
||||
| 世系范围 | 滑块 | 按世代范围筛选 |
|
||||
|
||||
---
|
||||
|
||||
## 成员详情 (/members/[id])
|
||||
|
||||
### 顶部操作栏
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 权限要求 | 功能说明 |
|
||||
|---------|------|------|---------|---------|
|
||||
| **返回** | `ArrowLeft` | `ghost` | 所有用户 | 返回上一页 |
|
||||
|
||||
### 主要操作按钮
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 权限要求 | 功能说明 |
|
||||
|---------|------|------|---------|---------|
|
||||
| **添加父亲** | `UserPlus` | `outline` | OWNER/EDITOR | 快速添加父亲(条件显示) |
|
||||
| **添加母亲** | `UserPlus` | `outline` | OWNER/EDITOR | 快速添加母亲(条件显示) |
|
||||
| **添加子女** | `UserPlus` | `default` | OWNER/EDITOR | 快速添加子女 |
|
||||
| **添加配偶** | `UserPlus` | `secondary` | OWNER/EDITOR | 快速添加配偶 |
|
||||
| **打印** | `Printer` | `outline` | 所有用户 | 打印成员信息 |
|
||||
| **分享** | `Share2` | `outline` | 所有用户 | 分享成员信息 |
|
||||
| **编辑** | `Edit` | `outline` | OWNER/EDITOR | 进入编辑模式 |
|
||||
| **删除** | `Trash` | `destructive` | OWNER/EDITOR | 删除成员(需确认) |
|
||||
|
||||
### 编辑模式
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **返回** | `ArrowLeft` | `ghost` | 退出编辑模式 |
|
||||
| **取消** | - | `outline` | 取消编辑,返回详情页 |
|
||||
| **保存** | - | `primary` | 保存修改 |
|
||||
|
||||
### 条件显示逻辑
|
||||
|
||||
- **添加父亲**: 仅当成员没有父亲时显示
|
||||
- **添加母亲**: 仅当成员没有母亲时显示
|
||||
- **添加子女**: 始终显示
|
||||
- **添加配偶**: 始终显示
|
||||
|
||||
---
|
||||
|
||||
## 新增成员 (/members/new)
|
||||
|
||||
### 顶部操作栏
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **返回** | `ArrowLeft` | `ghost` | 返回上一页 |
|
||||
|
||||
### 表单操作
|
||||
|
||||
| 按钮名称 | 样式 | 位置 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **取消** | `outline` | 底部左侧 | 取消新增,返回上一页 |
|
||||
| **保存** | `primary` | 底部右侧 | 保存新成员 |
|
||||
|
||||
---
|
||||
|
||||
## 族谱图 (/tree)
|
||||
|
||||
### 顶部工具栏
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **关系查询** | `Users` | `default/secondary` | 切换关系查询模式 |
|
||||
| **视图模式** | `LayoutGrid` | `outline` | 切换视图模式(下拉菜单) |
|
||||
| **放大** | `ZoomIn` | `outline` | 放大族谱图 |
|
||||
| **缩小** | `ZoomOut` | `outline` | 缩小族谱图 |
|
||||
| **重置** | `Move` | `outline` | 重置视图位置和缩放 |
|
||||
| **导出图片** | `Download` | `outline` | 导出族谱图为图片 |
|
||||
|
||||
### 视图模式选项
|
||||
|
||||
| 模式名称 | 说明 |
|
||||
|---------|------|
|
||||
| 传统视图 | 传统的树状布局 |
|
||||
| D3组织图 | 使用D3.js的组织图布局 |
|
||||
|
||||
### 关系查询模式
|
||||
|
||||
| 状态 | 说明 | 操作 |
|
||||
|-----|------|------|
|
||||
| 未激活 | 正常浏览模式 | 点击"关系查询"按钮激活 |
|
||||
| 激活 | 选择两个成员计算关系 | 依次点击两个成员 |
|
||||
| 结果显示 | 弹出对话框显示关系 | 点击"关闭"或"继续查询" |
|
||||
|
||||
### 对话框按钮
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **关闭** | `outline` | 关闭对话框 |
|
||||
| **继续查询** | `default` | 关闭对话框并保持查询模式 |
|
||||
|
||||
---
|
||||
|
||||
## 大事记 (/timeline)
|
||||
|
||||
### 标签切换
|
||||
|
||||
| 标签名称 | 内容 |
|
||||
|---------|------|
|
||||
| 时间线 | 按时间顺序显示事件 |
|
||||
| 迁徙记录 | 显示家族迁徙地图 |
|
||||
|
||||
### 操作
|
||||
|
||||
| 操作 | 触发方式 | 功能 |
|
||||
|-----|---------|------|
|
||||
| 查看成员详情 | 点击事件中的成员名称 | 跳转到成员详情页 |
|
||||
| 查看地图 | 切换到"迁徙记录"标签 | 显示迁徙地图 |
|
||||
|
||||
---
|
||||
|
||||
## 关系计算 (/relationship)
|
||||
|
||||
### 主要操作
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **计算关系** | `default` | 计算两个成员之间的关系 |
|
||||
| **清除** | `outline` | 清除选择 |
|
||||
| **交换** | `ghost` | 交换两个成员的位置 |
|
||||
|
||||
### 成员选择
|
||||
|
||||
| 选择器 | 说明 |
|
||||
|-------|------|
|
||||
| 成员A | 下拉选择第一个成员 |
|
||||
| 成员B | 下拉选择第二个成员 |
|
||||
|
||||
---
|
||||
|
||||
## 系统设置 (/settings)
|
||||
|
||||
### 用户信息卡片
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **修改密码** | `outline` | 打开修改密码对话框 |
|
||||
|
||||
### 数据管理
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **导出数据** | `Download` | `outline` | 导出家族树数据为JSON |
|
||||
| **导入数据** | `Upload` | `outline` | 导入JSON数据 |
|
||||
| **导出GEDCOM** | `FileText` | `outline` | 导出为GEDCOM格式 |
|
||||
| **导入GEDCOM** | `Upload` | `outline` | 导入GEDCOM文件 |
|
||||
| **清空数据** | `AlertTriangle` | `destructive` | 清空所有数据(需确认) |
|
||||
|
||||
### 操作日志
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **刷新** | `RefreshCw` | `outline` | 刷新日志列表 |
|
||||
| **清空日志** | `Trash` | `destructive` | 清空所有日志(需确认) |
|
||||
|
||||
### 修改密码对话框
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **取消** | `outline` | 关闭对话框 |
|
||||
| **确认修改** | `default` | 提交密码修改 |
|
||||
|
||||
---
|
||||
|
||||
## 登录注册 (/auth)
|
||||
|
||||
### 登录页面 (/auth/signin)
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **登录** | `default` | 提交登录表单 |
|
||||
| **注册账号** | `link` | 跳转到注册页面 |
|
||||
|
||||
### 注册页面 (/auth/register)
|
||||
|
||||
| 按钮名称 | 样式 | 功能说明 |
|
||||
|---------|------|---------|
|
||||
| **注册** | `default` | 提交注册表单 |
|
||||
| **已有账号?登录** | `link` | 跳转到登录页面 |
|
||||
|
||||
---
|
||||
|
||||
## 创建家族树 (/trees/new)
|
||||
|
||||
### 表单操作
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **返回** | `ArrowLeft` | `ghost` | 返回首页 |
|
||||
| **取消** | - | `outline` | 取消创建 |
|
||||
| **创建** | - | `primary` | 创建新家族树 |
|
||||
|
||||
---
|
||||
|
||||
## 全局导航 (SiteHeader)
|
||||
|
||||
### 主导航
|
||||
|
||||
| 导航项 | 路径 | 说明 |
|
||||
|-------|------|------|
|
||||
| 总览 | `/` | 首页 |
|
||||
| 族谱 | `/tree` | 族谱图 |
|
||||
| 成员 | `/members` | 成员列表 |
|
||||
| 大事记 | `/timeline` | 时间线 |
|
||||
|
||||
### 顶部操作栏
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **搜索** | `Search` | 输入框 | 全局搜索成员 |
|
||||
| **通知** | `Bell` | `ghost` | 查看通知(未实现) |
|
||||
| **关系计算器** | `Calculator` | `ghost` | 跳转到关系计算页面 |
|
||||
| **设置** | `Settings` | `ghost` | 跳转到系统设置 |
|
||||
| **用户菜单** | `Avatar` | 下拉菜单 | 用户信息和退出登录 |
|
||||
|
||||
### 家族树选择器
|
||||
|
||||
| 按钮名称 | 图标 | 样式 | 功能说明 |
|
||||
|---------|------|------|---------|
|
||||
| **当前家族树** | `ChevronDown` | `outline` | 显示家族树列表 |
|
||||
| **创建新家族树** | `Plus` | 菜单项 | 跳转到创建页面 |
|
||||
| **删除家族树** | `Trash2` | `ghost` | 删除家族树(仅所有者) |
|
||||
|
||||
### 用户下拉菜单
|
||||
|
||||
| 菜单项 | 图标 | 功能说明 |
|
||||
|-------|------|---------|
|
||||
| **系统设置** | `Settings` | 跳转到设置页面 |
|
||||
| **退出登录** | `LogOut` | 退出当前账号 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 按钮统计
|
||||
|
||||
### 按样式分类
|
||||
|
||||
| 样式 | 数量 | 用途 |
|
||||
|-----|------|------|
|
||||
| `primary` | 8 | 主要操作(保存、创建、新增等) |
|
||||
| `outline` | 25+ | 次要操作(编辑、导出、返回等) |
|
||||
| `ghost` | 15+ | 辅助操作(返回、搜索、刷新等) |
|
||||
| `destructive` | 5 | 危险操作(删除、清空等) |
|
||||
| `secondary` | 3 | 次要强调操作 |
|
||||
| `link` | 2 | 链接样式按钮 |
|
||||
|
||||
### 按功能分类
|
||||
|
||||
| 功能类别 | 按钮数量 | 主要按钮 |
|
||||
|---------|---------|---------|
|
||||
| **导航** | 10+ | 返回、跳转、查看全部 |
|
||||
| **CRUD操作** | 15+ | 新增、编辑、删除、保存 |
|
||||
| **数据管理** | 8 | 导入、导出、清空 |
|
||||
| **视图控制** | 6 | 放大、缩小、重置、切换视图 |
|
||||
| **关系查询** | 4 | 关系查询、计算关系、清除 |
|
||||
| **用户操作** | 5 | 登录、注册、修改密码、退出 |
|
||||
|
||||
### 按权限分类
|
||||
|
||||
| 权限级别 | 可用按钮 |
|
||||
|---------|---------|
|
||||
| **所有用户** | 查看、搜索、打印、分享、导出 |
|
||||
| **EDITOR** | 新增、编辑、删除成员 |
|
||||
| **OWNER** | 所有操作 + 删除家族树、管理协作者 |
|
||||
|
||||
---
|
||||
|
||||
## 🎨 设计规范
|
||||
|
||||
### 按钮尺寸
|
||||
|
||||
| 尺寸 | 使用场景 |
|
||||
|-----|---------|
|
||||
| `sm` | 辅助操作、图标按钮 |
|
||||
| `default` | 常规操作 |
|
||||
| `lg` | 主要操作(未使用) |
|
||||
|
||||
### 图标使用
|
||||
|
||||
| 图标库 | 使用率 |
|
||||
|-------|--------|
|
||||
| Lucide React | 100% |
|
||||
|
||||
### 常用图标
|
||||
|
||||
| 图标 | 用途 | 使用次数 |
|
||||
|-----|------|---------|
|
||||
| `Plus` / `UserPlus` | 新增操作 | 10+ |
|
||||
| `ArrowLeft` | 返回 | 8 |
|
||||
| `Edit` | 编辑 | 5 |
|
||||
| `Trash` / `Trash2` | 删除 | 5 |
|
||||
| `Download` | 导出/下载 | 4 |
|
||||
| `Upload` | 导入/上传 | 3 |
|
||||
| `Search` | 搜索 | 3 |
|
||||
|
||||
---
|
||||
|
||||
## 🔍 优化建议
|
||||
|
||||
### 高优先级
|
||||
|
||||
1. **统一确认对话框**
|
||||
- 所有删除操作应使用统一的确认对话框
|
||||
- 建议使用 `AlertDialog` 组件
|
||||
|
||||
2. **加载状态**
|
||||
- 为异步操作添加加载状态
|
||||
- 使用 `loading` 属性或 `Spinner` 组件
|
||||
|
||||
3. **禁用状态**
|
||||
- 根据权限自动禁用按钮
|
||||
- 添加 `disabled` 状态和提示
|
||||
|
||||
4. **快捷键支持**
|
||||
- 为常用操作添加快捷键
|
||||
- 如:Ctrl+S 保存,Esc 取消
|
||||
|
||||
### 中优先级
|
||||
|
||||
5. **批量操作**
|
||||
- 成员列表添加批量选择
|
||||
- 支持批量删除、导出
|
||||
|
||||
6. **撤销/重做**
|
||||
- 为编辑操作添加撤销功能
|
||||
- 特别是删除操作
|
||||
|
||||
7. **操作反馈**
|
||||
- 添加 Toast 提示
|
||||
- 操作成功/失败的明确反馈
|
||||
|
||||
### 低优先级
|
||||
|
||||
8. **按钮分组**
|
||||
- 相关按钮使用 `ButtonGroup` 组件
|
||||
- 提高视觉层次
|
||||
|
||||
9. **响应式优化**
|
||||
- 移动端按钮大小调整
|
||||
- 使用下拉菜单收纳次要操作
|
||||
|
||||
10. **国际化**
|
||||
- 按钮文本支持多语言
|
||||
- 图标 + 文本的组合
|
||||
|
||||
---
|
||||
|
||||
## 📝 维护记录
|
||||
|
||||
| 日期 | 更新内容 | 更新人 |
|
||||
|------|---------|--------|
|
||||
| 2025-11-23 | 初始版本,梳理全站按钮 | System |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 相关文档
|
||||
|
||||
- [组件库文档](../components/ui/README.md)
|
||||
- [权限系统文档](./PERMISSIONS.md)
|
||||
- [用户体验指南](./UX_GUIDELINES.md)
|
||||
Reference in New Issue
Block a user