334 lines
8.4 KiB
Markdown
334 lines
8.4 KiB
Markdown
# 资产点赞功能实现总结
|
||
|
||
## 📝 实现概述
|
||
|
||
本次实现完成了:
|
||
- **阶段4**:Asset Service - Repository 层的资产点赞记录Repository
|
||
- **阶段6**:Social Service 资产点赞功能(Service 层和 Provider 层)
|
||
|
||
## ✅ 已完成的功能
|
||
|
||
### 1. Asset Service - AssetLike Repository(资产点赞记录)
|
||
|
||
**文件**: `services/assetService/repository/asset_like_repository.go`
|
||
|
||
#### 接口定义
|
||
```go
|
||
type AssetLikeRepository interface {
|
||
Create(like *models.AssetLike) error
|
||
Delete(assetID, userID, starID int64) error
|
||
Exists(assetID, userID, starID int64) (bool, error)
|
||
GetByAsset(assetID int64, limit, offset int) ([]*models.AssetLike, error)
|
||
GetByUser(userID, starID int64, limit, offset int) ([]*models.AssetLike, error)
|
||
CountByAsset(assetID int64) (int64, error)
|
||
CountByUser(userID, starID int64) (int64, error)
|
||
}
|
||
```
|
||
|
||
#### 功能说明
|
||
- ✅ **Create**: 创建点赞记录,自动检查重复点赞
|
||
- ✅ **Delete**: 删除点赞记录
|
||
- ✅ **Exists**: 检查点赞记录是否存在
|
||
- ✅ **GetByAsset**: 分页获取资产的点赞列表
|
||
- ✅ **GetByUser**: 分页获取用户的点赞列表
|
||
- ✅ **CountByAsset**: 统计资产的点赞数
|
||
- ✅ **CountByUser**: 统计用户的点赞数
|
||
|
||
#### 测试文件
|
||
**文件**: `services/assetService/repository/asset_like_repository_test.go`
|
||
|
||
**测试用例** (8个):
|
||
1. TestAssetLikeRepository_Create - 创建点赞
|
||
2. TestAssetLikeRepository_Delete - 删除点赞
|
||
3. TestAssetLikeRepository_Exists - 检查存在性
|
||
4. TestAssetLikeRepository_GetByAsset - 按资产查询
|
||
5. TestAssetLikeRepository_GetByUser - 按用户查询
|
||
6. TestAssetLikeRepository_CountByAsset - 统计资产点赞数
|
||
7. TestAssetLikeRepository_CountByUser - 统计用户点赞数
|
||
8. TestAssetLikeRepository_LikeUnlikeFlow - 完整的点赞-取消点赞流程
|
||
|
||
---
|
||
|
||
### 2. Social Service - Asset RPC 客户端
|
||
|
||
**文件**: `services/socialService/client/asset_client.go`
|
||
|
||
#### 功能说明
|
||
封装了对 Asset Service 的 RPC 调用:
|
||
|
||
- ✅ **GetAsset**: 获取资产信息
|
||
- ✅ **LikeAsset**: 点赞资产
|
||
- ✅ **UnlikeAsset**: 取消点赞资产
|
||
- ✅ **CheckAssetLike**: 检查是否已点赞
|
||
- ✅ **GetAssetLikes**: 获取资产点赞列表
|
||
|
||
#### 连接配置
|
||
```go
|
||
client.WithClientURL(fmt.Sprintf("tri://localhost:20002/%s", assetPb.AssetServiceClientImpl))
|
||
```
|
||
- 协议: Triple (Dubbo-go v3)
|
||
- 地址: localhost:20002 (Asset Service 端口)
|
||
|
||
---
|
||
|
||
### 3. Social Service - AssetLike Service 层
|
||
|
||
**文件**: `services/socialService/service/asset_like_service.go`
|
||
|
||
#### 功能说明
|
||
实现了资产点赞的业务逻辑:
|
||
|
||
- ✅ **LikeAsset**:
|
||
1. 验证资产是否存在
|
||
2. 检查是否已点赞
|
||
3. 调用 Asset Service 点赞接口
|
||
|
||
- ✅ **UnlikeAsset**:
|
||
1. 检查是否已点赞
|
||
2. 调用 Asset Service 取消点赞接口
|
||
|
||
- ✅ **CheckAssetLike**:
|
||
- 调用 Asset Service 检查点赞状态
|
||
|
||
- ✅ **GetAssetLikes**:
|
||
- 调用 Asset Service 获取点赞列表
|
||
|
||
---
|
||
|
||
### 4. Social Service - Provider 层更新
|
||
|
||
**文件**: `services/socialService/provider/social_provider.go`
|
||
|
||
#### 更新内容
|
||
|
||
1. **结构体更新**:
|
||
```go
|
||
type SocialProvider struct {
|
||
friendService service.FriendService
|
||
assetLikeService *service.AssetLikeService // 新增
|
||
}
|
||
```
|
||
|
||
2. **方法实现**:
|
||
|
||
- ✅ **LikeAsset**:
|
||
- 从上下文提取用户信息 (user_id, star_id)
|
||
- 调用 AssetLikeService.LikeAsset
|
||
- 返回标准响应
|
||
|
||
- ✅ **UnlikeAsset**:
|
||
- 从上下文提取用户信息
|
||
- 调用 AssetLikeService.UnlikeAsset
|
||
- 返回标准响应
|
||
|
||
- ✅ **CheckAssetLike**:
|
||
- 从上下文提取用户信息
|
||
- 调用 AssetLikeService.CheckAssetLike
|
||
- 返回点赞状态
|
||
|
||
---
|
||
|
||
### 5. Social Service - Main.go 更新
|
||
|
||
**文件**: `services/socialService/main.go`
|
||
|
||
#### 更新内容
|
||
|
||
1. **导入 client 包**:
|
||
```go
|
||
socialClient "github.com/topfans/backend/services/socialService/client"
|
||
```
|
||
|
||
2. **创建 AssetClient**:
|
||
```go
|
||
func createAssetServiceClient() (*socialClient.AssetClient, error) {
|
||
assetClient, err := socialClient.NewAssetClient(logger.Logger)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to create asset client: %w", err)
|
||
}
|
||
return assetClient, nil
|
||
}
|
||
```
|
||
|
||
3. **初始化 AssetLikeService**:
|
||
```go
|
||
assetClient, err := createAssetServiceClient()
|
||
// ...
|
||
assetLikeService := service.NewAssetLikeService(assetClient)
|
||
```
|
||
|
||
4. **更新 Provider 创建**:
|
||
```go
|
||
socialProvider := provider.NewSocialProvider(friendService, assetLikeService)
|
||
```
|
||
|
||
---
|
||
|
||
## 🔄 完整的数据流
|
||
|
||
### 点赞流程
|
||
|
||
```
|
||
1. Gateway 接收 HTTP 请求
|
||
↓
|
||
2. Gateway 验证用户身份,提取 user_id, star_id
|
||
↓
|
||
3. Gateway 通过 RPC 调用 Social Service
|
||
(将 user_id, star_id 通过 Dubbo attachments 传递)
|
||
↓
|
||
4. Social Service Provider 提取用户信息
|
||
↓
|
||
5. Social Service 调用 AssetLikeService
|
||
↓
|
||
6. AssetLikeService 通过 RPC 调用 Asset Service
|
||
↓
|
||
7. Asset Service 验证资产、创建点赞记录、增加点赞数
|
||
↓
|
||
8. 返回响应
|
||
```
|
||
|
||
### 取消点赞流程
|
||
|
||
```
|
||
1. Gateway 接收 HTTP 请求
|
||
↓
|
||
2. Gateway 验证用户身份,提取 user_id, star_id
|
||
↓
|
||
3. Gateway 通过 RPC 调用 Social Service
|
||
↓
|
||
4. Social Service Provider 提取用户信息
|
||
↓
|
||
5. Social Service 调用 AssetLikeService
|
||
↓
|
||
6. AssetLikeService 通过 RPC 调用 Asset Service
|
||
↓
|
||
7. Asset Service 删除点赞记录、减少点赞数
|
||
↓
|
||
8. 返回响应
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 数据模型
|
||
|
||
### AssetLike 表结构
|
||
```go
|
||
type AssetLike struct {
|
||
ID int64 // 主键
|
||
AssetID int64 // 资产ID
|
||
UserID int64 // 用户ID
|
||
StarID int64 // 明星ID(数据隔离)
|
||
CreatedAt int64 // 创建时间戳
|
||
}
|
||
```
|
||
|
||
### 索引
|
||
- **唯一索引**: `uk_asset_likes_user_asset` (asset_id, user_id)
|
||
- 确保一个用户对一个资产只能点赞一次
|
||
- **普通索引**:
|
||
- `idx_asset_likes_asset` (asset_id, created_at DESC)
|
||
- `idx_asset_likes_user_star` (user_id, star_id, created_at DESC)
|
||
|
||
---
|
||
|
||
## 🧪 测试覆盖
|
||
|
||
### AssetLike Repository 测试
|
||
- ✅ 创建点赞记录
|
||
- ✅ 重复点赞检测
|
||
- ✅ 删除点赞记录
|
||
- ✅ 检查点赞存在性
|
||
- ✅ 按资产分页查询
|
||
- ✅ 按用户分页查询
|
||
- ✅ 统计功能
|
||
- ✅ 完整流程测试
|
||
|
||
### 测试数据
|
||
- 测试用户手机号前缀: `199002`
|
||
- 测试明星 IdentityID 前缀: `test_like_`
|
||
- 自动清理测试数据
|
||
|
||
---
|
||
|
||
## 🎯 待完成的任务
|
||
|
||
### Asset Service 部分
|
||
1. **Provider 层实现**: 实现 Asset Service 的 LikeAsset、UnlikeAsset、CheckAssetLike 接口
|
||
2. **Service 层实现**: 实现资产点赞的业务逻辑(调用 Repository)
|
||
3. **网关路由**: 添加资产点赞相关的 HTTP 路由
|
||
|
||
### 集成测试
|
||
1. **端到端测试**: 测试从 Gateway 到 Asset Service 的完整流程
|
||
2. **并发测试**: 测试高并发点赞场景
|
||
3. **边界测试**: 测试各种异常情况
|
||
|
||
---
|
||
|
||
## 📝 代码文件清单
|
||
|
||
### Asset Service
|
||
- ✅ `services/assetService/repository/asset_like_repository.go` (225 行)
|
||
- ✅ `services/assetService/repository/asset_like_repository_test.go` (302 行)
|
||
|
||
### Social Service
|
||
- ✅ `services/socialService/client/asset_client.go` (104 行)
|
||
- ✅ `services/socialService/service/asset_like_service.go` (183 行)
|
||
- ✅ `services/socialService/provider/social_provider.go` (更新)
|
||
- ✅ `services/socialService/main.go` (更新)
|
||
|
||
---
|
||
|
||
## 🚀 运行测试
|
||
|
||
### AssetLike Repository 测试
|
||
```bash
|
||
cd services/assetService
|
||
go test ./repository/... -run TestAssetLike -v
|
||
```
|
||
|
||
### 检查编译
|
||
```bash
|
||
# Social Service
|
||
cd services/socialService
|
||
go build
|
||
|
||
# Asset Service
|
||
cd services/assetService
|
||
go build
|
||
```
|
||
|
||
---
|
||
|
||
## 📌 注意事项
|
||
|
||
1. **数据一致性**: 点赞记录和点赞数需要保持一致
|
||
2. **幂等性**: 重复点赞/取消点赞应该被正确处理
|
||
3. **权限验证**: 确保用户信息从上下文正确提取
|
||
4. **错误处理**: 所有 RPC 调用都应该有完善的错误处理
|
||
5. **日志记录**: 关键操作都有详细的日志记录
|
||
|
||
---
|
||
|
||
## 🎉 总结
|
||
|
||
**已完成**:
|
||
- ✅ AssetLike Repository(完整实现 + 测试)
|
||
- ✅ Asset RPC 客户端(Social Service)
|
||
- ✅ AssetLikeService(业务逻辑层)
|
||
- ✅ SocialProvider(更新 Provider 层)
|
||
- ✅ Main.go(更新服务初始化)
|
||
|
||
**待实现**:
|
||
- ⏳ Asset Service Provider 层(RPC 接口实现)
|
||
- ⏳ Asset Service Service 层(业务逻辑)
|
||
- ⏳ Gateway 路由(HTTP 接口)
|
||
- ⏳ 集成测试
|
||
|
||
**文件数量**: 6 个文件(新建 4 个 + 更新 2 个)
|
||
**代码行数**: 约 800+ 行
|
||
|
||
---
|
||
|
||
**实现时间**: 2026-01-12
|
||
**实现者**: AI Assistant
|