97 lines
2.3 KiB
Markdown
97 lines
2.3 KiB
Markdown
# 设备移出和邀请码优化 - 设计文档
|
||
|
||
## 整体架构
|
||
|
||
本次修复涉及两个独立的 bug,不需要修改架构,只需要修改具体的业务逻辑层代码。
|
||
|
||
### 组件关系图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "用户请求"
|
||
A[客户端] --> B[HTTP Handler]
|
||
end
|
||
|
||
subgraph "业务逻辑层"
|
||
B --> C[unbindDeviceLogic]
|
||
B --> D[bindInviteCodeLogic]
|
||
end
|
||
|
||
subgraph "服务层"
|
||
C --> E[DeviceManager.KickDevice]
|
||
D --> F[UserModel.FindOneByReferCode]
|
||
end
|
||
|
||
subgraph "数据层"
|
||
E --> G[WebSocket连接管理]
|
||
F --> H[GORM/数据库]
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
## 模块详细设计
|
||
|
||
### 模块1: UnbindDeviceLogic 修复
|
||
|
||
#### 当前数据流
|
||
```
|
||
1. 用户请求解绑设备
|
||
2. 验证设备属于当前用户 (device.UserId == u.Id) ✅
|
||
3. 事务中:创建新用户,迁移设备
|
||
4. 调用 KickDevice(u.Id, identifier) ❌ <-- 用户ID错误
|
||
```
|
||
|
||
#### 修复后数据流
|
||
```
|
||
1. 用户请求解绑设备
|
||
2. 验证设备属于当前用户 ✅
|
||
3. 保存原始用户ID: originalUserId := device.UserId ✅
|
||
4. 事务中:创建新用户,迁移设备
|
||
5. 调用 KickDevice(originalUserId, identifier) ✅ <-- 使用正确的用户ID
|
||
```
|
||
|
||
#### 接口契约
|
||
无变化,仅修改内部实现。
|
||
|
||
---
|
||
|
||
### 模块2: BindInviteCodeLogic 修复
|
||
|
||
#### 当前错误处理
|
||
```go
|
||
if err != nil {
|
||
return xerr.DatabaseQueryError // 所有错误统一处理
|
||
}
|
||
```
|
||
|
||
#### 修复后错误处理
|
||
```go
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return xerr.InviteCodeError("无邀请码") // 记录不存在 → 友好提示
|
||
}
|
||
return xerr.DatabaseQueryError // 其他错误保持原样
|
||
}
|
||
```
|
||
|
||
#### 接口契约
|
||
API 返回格式不变,但错误码从 `10001` 变为 `20009`(针对邀请码不存在的情况)。
|
||
|
||
---
|
||
|
||
## 异常处理策略
|
||
|
||
| 场景 | 错误码 | 错误消息 |
|
||
|------|--------|----------|
|
||
| 邀请码不存在 | 20009 | 无邀请码 |
|
||
| 数据库查询错误 | 10001 | Database query error |
|
||
| 绑定自己的邀请码 | 20009 | 不允许绑定自己 |
|
||
|
||
---
|
||
|
||
## 设计原则
|
||
1. **最小改动原则**:只修改必要的代码,不重构现有逻辑
|
||
2. **向后兼容**:不改变 API 接口定义
|
||
3. **代码风格一致**:遵循项目现有的错误处理模式
|