0.0.0.5
This commit is contained in:
+431
@@ -0,0 +1,431 @@
|
||||
# 后端功能实施方案
|
||||
|
||||
## 概述
|
||||
|
||||
以下功能需要后端服务支持,目前应用是纯前端应用(使用 IndexedDB 本地存储)。要实现这些功能,需要搭建后端服务。
|
||||
|
||||
---
|
||||
|
||||
## 1. 多用户系统
|
||||
|
||||
### 需求分析
|
||||
- 支持多个用户注册和登录
|
||||
- 每个用户可以创建和管理自己的家族树
|
||||
- 用户可以邀请其他用户协作编辑同一个家族树
|
||||
|
||||
### 技术方案
|
||||
|
||||
#### 后端技术栈选择
|
||||
- **Node.js + Express** 或 **Next.js API Routes**
|
||||
- **数据库**: PostgreSQL / MongoDB
|
||||
- **认证**: NextAuth.js / Auth0 / Supabase Auth
|
||||
|
||||
#### 数据模型
|
||||
|
||||
```typescript
|
||||
// 用户表
|
||||
interface User {
|
||||
id: string
|
||||
email: string
|
||||
name: string
|
||||
avatar?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
// 家族树表
|
||||
interface FamilyTree {
|
||||
id: string
|
||||
name: string // 家族名称,如"李氏家族"
|
||||
ownerId: string // 创建者
|
||||
rootMemberId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
// 家族成员表(扩展现有 FamilyMember)
|
||||
interface FamilyMember {
|
||||
// ... 现有字段
|
||||
treeId: string // 所属家族树
|
||||
}
|
||||
|
||||
// 用户-家族树关系表(协作者)
|
||||
interface TreeCollaborator {
|
||||
id: string
|
||||
treeId: string
|
||||
userId: string
|
||||
role: 'owner' | 'editor' | 'viewer'
|
||||
invitedBy: string
|
||||
invitedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
#### API 端点
|
||||
|
||||
```typescript
|
||||
// 用户认证
|
||||
POST /api/auth/register
|
||||
POST /api/auth/login
|
||||
POST /api/auth/logout
|
||||
GET /api/auth/me
|
||||
|
||||
// 家族树管理
|
||||
GET /api/trees // 获取用户的所有家族树
|
||||
POST /api/trees // 创建新家族树
|
||||
GET /api/trees/:id // 获取家族树详情
|
||||
PUT /api/trees/:id // 更新家族树
|
||||
DELETE /api/trees/:id // 删除家族树
|
||||
|
||||
// 协作者管理
|
||||
GET /api/trees/:id/collaborators
|
||||
POST /api/trees/:id/invite // 邀请协作者
|
||||
DELETE /api/trees/:id/collaborators/:userId
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 云端同步
|
||||
|
||||
### 需求分析
|
||||
- 数据自动同步到云端
|
||||
- 多设备数据同步
|
||||
- 离线编辑,在线时自动同步
|
||||
- 冲突检测和解决
|
||||
|
||||
### 技术方案
|
||||
|
||||
#### 同步策略
|
||||
|
||||
**1. 实时同步(推荐)**
|
||||
- 使用 WebSocket 或 Server-Sent Events
|
||||
- 每次操作立即同步到服务器
|
||||
- 其他客户端实时接收更新
|
||||
|
||||
**2. 定时同步**
|
||||
- 每隔一定时间(如 30 秒)同步一次
|
||||
- 适合网络不稳定的场景
|
||||
|
||||
**3. 混合模式**
|
||||
- 在线时实时同步
|
||||
- 离线时本地存储
|
||||
- 重新联网时批量同步
|
||||
|
||||
#### 数据同步流程
|
||||
|
||||
```typescript
|
||||
// 同步记录表
|
||||
interface SyncRecord {
|
||||
id: string
|
||||
treeId: string
|
||||
userId: string
|
||||
action: 'create' | 'update' | 'delete'
|
||||
entityType: 'member' | 'photo' | 'story'
|
||||
entityId: string
|
||||
data: any
|
||||
timestamp: string
|
||||
synced: boolean
|
||||
}
|
||||
|
||||
// 同步 API
|
||||
POST /api/sync/push // 推送本地更改
|
||||
GET /api/sync/pull // 拉取远程更改
|
||||
GET /api/sync/status // 获取同步状态
|
||||
```
|
||||
|
||||
#### 冲突解决策略
|
||||
|
||||
1. **最后写入优先(Last Write Wins)**
|
||||
- 简单但可能丢失数据
|
||||
|
||||
2. **版本控制**
|
||||
- 每条记录有版本号
|
||||
- 冲突时提示用户选择
|
||||
|
||||
3. **操作转换(Operational Transformation)**
|
||||
- 复杂但最准确
|
||||
- 类似 Google Docs 的协作编辑
|
||||
|
||||
#### 实现示例(使用 Supabase)
|
||||
|
||||
```typescript
|
||||
// lib/sync.ts
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
)
|
||||
|
||||
// 推送本地更改到云端
|
||||
export async function pushChanges(changes: SyncRecord[]) {
|
||||
const { data, error } = await supabase
|
||||
.from('sync_records')
|
||||
.insert(changes)
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
|
||||
// 从云端拉取更改
|
||||
export async function pullChanges(treeId: string, lastSyncTime: string) {
|
||||
const { data, error } = await supabase
|
||||
.from('sync_records')
|
||||
.select('*')
|
||||
.eq('treeId', treeId)
|
||||
.gt('timestamp', lastSyncTime)
|
||||
.order('timestamp', { ascending: true })
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
|
||||
// 实时订阅更改
|
||||
export function subscribeToChanges(treeId: string, callback: (change: any) => void) {
|
||||
return supabase
|
||||
.channel(`tree:${treeId}`)
|
||||
.on('postgres_changes', {
|
||||
event: '*',
|
||||
schema: 'public',
|
||||
table: 'family_members',
|
||||
filter: `treeId=eq.${treeId}`
|
||||
}, callback)
|
||||
.subscribe()
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 权限管理
|
||||
|
||||
### 需求分析
|
||||
- 不同用户有不同的操作权限
|
||||
- 支持角色:所有者、编辑者、查看者
|
||||
- 细粒度权限控制
|
||||
|
||||
### 权限模型
|
||||
|
||||
```typescript
|
||||
// 角色定义
|
||||
enum Role {
|
||||
OWNER = 'owner', // 所有者:完全控制
|
||||
EDITOR = 'editor', // 编辑者:可以增删改
|
||||
VIEWER = 'viewer' // 查看者:只读
|
||||
}
|
||||
|
||||
// 权限定义
|
||||
interface Permission {
|
||||
canView: boolean
|
||||
canCreate: boolean
|
||||
canUpdate: boolean
|
||||
canDelete: boolean
|
||||
canInvite: boolean
|
||||
canExport: boolean
|
||||
canManageSettings: boolean
|
||||
}
|
||||
|
||||
// 角色权限映射
|
||||
const rolePermissions: Record<Role, Permission> = {
|
||||
owner: {
|
||||
canView: true,
|
||||
canCreate: true,
|
||||
canUpdate: true,
|
||||
canDelete: true,
|
||||
canInvite: true,
|
||||
canExport: true,
|
||||
canManageSettings: true,
|
||||
},
|
||||
editor: {
|
||||
canView: true,
|
||||
canCreate: true,
|
||||
canUpdate: true,
|
||||
canDelete: false,
|
||||
canInvite: false,
|
||||
canExport: true,
|
||||
canManageSettings: false,
|
||||
},
|
||||
viewer: {
|
||||
canView: true,
|
||||
canCreate: false,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canInvite: false,
|
||||
canExport: true,
|
||||
canManageSettings: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 权限检查中间件
|
||||
|
||||
```typescript
|
||||
// middleware/auth.ts
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export async function requireAuth(req: NextRequest) {
|
||||
const token = req.headers.get('authorization')
|
||||
if (!token) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
// 验证 token
|
||||
const user = await verifyToken(token)
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Invalid token' }, { status: 401 })
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
export async function requirePermission(
|
||||
userId: string,
|
||||
treeId: string,
|
||||
permission: keyof Permission
|
||||
) {
|
||||
// 获取用户在该家族树的角色
|
||||
const collaborator = await db.treeCollaborators.findFirst({
|
||||
where: { userId, treeId }
|
||||
})
|
||||
|
||||
if (!collaborator) {
|
||||
throw new Error('No access to this tree')
|
||||
}
|
||||
|
||||
const permissions = rolePermissions[collaborator.role]
|
||||
if (!permissions[permission]) {
|
||||
throw new Error(`Permission denied: ${permission}`)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
### 前端权限控制
|
||||
|
||||
```typescript
|
||||
// hooks/usePermissions.ts
|
||||
import { useAuth } from './useAuth'
|
||||
import { useFamilyTree } from './useFamilyTree'
|
||||
|
||||
export function usePermissions() {
|
||||
const { user } = useAuth()
|
||||
const { currentTree } = useFamilyTree()
|
||||
|
||||
const [permissions, setPermissions] = useState<Permission>()
|
||||
|
||||
useEffect(() => {
|
||||
if (user && currentTree) {
|
||||
fetchPermissions(user.id, currentTree.id).then(setPermissions)
|
||||
}
|
||||
}, [user, currentTree])
|
||||
|
||||
return permissions
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
function MemberForm() {
|
||||
const permissions = usePermissions()
|
||||
|
||||
if (!permissions?.canCreate) {
|
||||
return <div>您没有权限添加成员</div>
|
||||
}
|
||||
|
||||
return <form>...</form>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 推荐的实施方案
|
||||
|
||||
### 方案 A:使用 Supabase(最简单)
|
||||
|
||||
**优点**:
|
||||
- 开箱即用的认证、数据库、实时订阅
|
||||
- 无需自己搭建后端
|
||||
- 免费额度足够个人使用
|
||||
- 自动处理权限和 RLS(Row Level Security)
|
||||
|
||||
**步骤**:
|
||||
1. 创建 Supabase 项目
|
||||
2. 设计数据库表结构
|
||||
3. 配置 RLS 规则
|
||||
4. 集成 Supabase 客户端
|
||||
5. 迁移现有 IndexedDB 数据
|
||||
|
||||
### 方案 B:使用 Next.js API Routes + PostgreSQL
|
||||
|
||||
**优点**:
|
||||
- 完全控制后端逻辑
|
||||
- 可以部署在 Vercel
|
||||
- 适合需要复杂业务逻辑的场景
|
||||
|
||||
**步骤**:
|
||||
1. 添加 API Routes
|
||||
2. 配置数据库(Vercel Postgres / Neon)
|
||||
3. 实现认证逻辑(NextAuth.js)
|
||||
4. 实现同步 API
|
||||
5. 添加权限中间件
|
||||
|
||||
### 方案 C:使用 Firebase
|
||||
|
||||
**优点**:
|
||||
- Google 生态系统
|
||||
- 实时数据库
|
||||
- 免费额度较大
|
||||
|
||||
**步骤**:
|
||||
1. 创建 Firebase 项目
|
||||
2. 配置 Firestore
|
||||
3. 设置 Firebase Auth
|
||||
4. 配置安全规则
|
||||
5. 集成 Firebase SDK
|
||||
|
||||
---
|
||||
|
||||
## 估算工作量
|
||||
|
||||
| 功能 | 使用 Supabase | 自建后端 |
|
||||
|------|--------------|----------|
|
||||
| 多用户系统 | 2-3 天 | 5-7 天 |
|
||||
| 云端同步 | 3-5 天 | 7-10 天 |
|
||||
| 权限管理 | 2-3 天 | 5-7 天 |
|
||||
| **总计** | **1-2 周** | **3-4 周** |
|
||||
|
||||
---
|
||||
|
||||
## 下一步行动
|
||||
|
||||
1. **选择技术方案**:推荐 Supabase(快速、简单)
|
||||
2. **数据迁移计划**:设计从 IndexedDB 到云端的迁移方案
|
||||
3. **逐步实施**:
|
||||
- 第一阶段:多用户系统
|
||||
- 第二阶段:云端同步
|
||||
- 第三阶段:权限管理
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据安全**:
|
||||
- 使用 HTTPS
|
||||
- 加密敏感数据
|
||||
- 定期备份
|
||||
|
||||
2. **性能优化**:
|
||||
- 使用缓存
|
||||
- 分页加载
|
||||
- 图片 CDN
|
||||
|
||||
3. **用户体验**:
|
||||
- 离线优先
|
||||
- 乐观更新
|
||||
- 友好的错误提示
|
||||
|
||||
---
|
||||
|
||||
**建议**:如果您想快速实现这些功能,我推荐使用 Supabase。我可以帮您:
|
||||
1. 设计 Supabase 数据库结构
|
||||
2. 实现认证和权限
|
||||
3. 添加实时同步功能
|
||||
|
||||
是否需要我开始实施?
|
||||
Reference in New Issue
Block a user