topfans/backend/docs/资产服务设计文档.md
2026-04-07 22:29:48 +08:00

1446 lines
51 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 资产服务Asset Service设计文档
## 📊 文档状态总结
### ✅ 已完成
- ✅ 数据库模型设计(`pkg/models/asset.go` 已实现)
- ✅ 核心功能设计确认Q1-Q17, Q23-Q25 已确认)
- ✅ 数据库表结构设计assets、mint_orders、asset_likes 表结构已确定)
- ✅ 服务职责边界定义
- ✅ 配置设计(参考 socialService 的配置模式)
### ⚠️ 需要补充和确认
#### 🔴 高优先级(阻塞开发)
1. **User Service 接口补充**
-`UpdateCrystalBalance` RPC 接口(需要在 `proto/user.proto` 中添加)
- ⚠️ `UpdateAssetsCount` RPC 接口Repository 层已实现,需要添加 RPC 接口)
2. **Asset Service Proto 定义**
- ❌ 需要创建 `proto/asset.proto` 文件
- ❌ 定义资产服务的所有 RPC 接口
3. **Social Service 接口补充**
- ❌ 资产点赞相关的 RPC 接口(需要在 `proto/social.proto` 中添加)
#### 🟡 中优先级(建议确认)
4. **事件驱动机制****已确认:不使用消息队列**
- ✅ 不使用消息队列RocketMQ/Kafka/RabbitMQ直接通过 RPC 调用或数据库记录
- ⚠️ 事件格式规范(如需事件记录,可在数据库中记录)
- ⚠️ 事件重试机制(如需重试,可在应用层实现)
5. **缓存策略****已确认:不使用 Redis 缓存**
- ✅ 不使用 Redis 缓存,直接查询数据库
- ✅ 所有数据查询都直接访问数据库
#### 🟢 低优先级(可后续优化)
6. **错误处理国际化**
- ⚠️ 是否需要多语言支持
### 📝 待实现内容
#### 1. 服务实现(未开始)
- [ ] 创建 `services/assetService/` 目录结构
- [ ] 实现 Repository 层asset_repository.go、mint_order_repository.go、asset_like_repository.go
- [ ] 实现 Service 层asset_service.go、mint_service.go
- [ ] 实现 Provider 层asset_provider.go
- [ ] 实现 RPC Clientuser_rpc_client.go
#### 2. Gateway 集成(未开始)
- [ ] 创建 `gateway/controller/asset_controller.go`
- [ ] 创建 `gateway/dto/asset_converter.go`
- [ ]`gateway/router/router.go` 中添加路由
#### 3. 数据库迁移(未开始)
- [ ] 创建表结构迁移脚本
- [ ] 创建索引
#### 4. 测试(未开始)
- [ ] 单元测试
- [ ] 集成测试
- [ ] HTTP 完整测试流程
---
## 📋 快速参考
### 数据库表设计(基于提供设计 + 服务交互字段)
#### assets 表
- **基础字段**(来自提供设计):`id`, `owner_uid`, `star_id`, `name`, `cover_url`, `status`, `tx_hash`, `block_number`, `like_count`
- **新增字段**(需求确认):`material_url`(用户上传素材),`description`, `rarity`, `tags`, `visibility`(预留)
- **新增字段**(服务交互):`created_at`, `updated_at`, `minted_at`, `deleted_at`, `is_active`
#### mint_orders 表
- **基础字段**(来自提供设计):`order_id`UUID, `user_id`, `asset_id`, `star_id`, `status`, `created_at`
- **新增字段**(服务交互):`updated_at`, `minted_at`, `cost_crystal`, `error_message`, `retry_count`
### 服务间交互字段映射
| 交互服务 | 使用的字段 | 用途 |
|---------|----------|------|
| **User Service** | `mint_orders.cost_crystal` | 扣除/退款水晶 |
| **User Service** | `assets.owner_uid`, `assets.star_id` | 更新资产数量 |
| **Social Service** | `assets.like_count` | 更新点赞数 |
| **Gallery Service** | - | 暂不考虑,后续再实现 |
| **Task Service** | `assets.created_at`, `assets.minted_at` | 事件发布 |
### 需要确认的关键问题
**🔴 高优先级(必须确认):**
1. 铸造费用和支付方式Q1
2. 区块链集成方式Q11, Q23
3. User Service 接口可用性Q18
**🟡 中优先级(建议确认):**
4. 资产属性字段Q13
5. 订单表设计细节Q14
**🟢 低优先级(可后续优化):**
6. 其他功能细节Q5-Q10, Q15-Q17, Q19-Q30
---
## 一、服务概述
### 1.1 服务定位
**Asset Service资产服务** 是负责数字藏品NFT全生命周期管理的核心微服务包括
- 数字藏品的铸造(链下记录 + 链上确权)
- 资产查询与列表管理
- 资产详情展示
- 素材管理(平台素材库)
- 图片上传与审核
### 1.2 服务职责边界
**Asset Service 负责:**
- ✅ 资产的创建、查询、更新
- ✅ 铸造订单的管理
- ✅ 素材库管理
- ✅ 图片上传处理
- ✅ 资产上链状态跟踪
**Asset Service 不负责:**
- ❌ 用户余额管理CoinBalance, CrystalBalance- 由 User Service 管理
- ❌ 资产数量统计AssetsCount- 由 User Service 管理(通过 RPC 调用更新)
- ❌ 资产展示(展馆)- 由 Gallery Service 管理
- ❌ 资产点赞 - 由 Social Service 管理
---
## 二、核心功能设计
### 2.1 资产铸造流程
#### 2.1.1 铸造流程概述
```
用户发起铸造请求
1. 验证用户权限和余额
2. 创建资产记录(链下)
3. 创建铸造订单(异步)
4. 调用区块链服务上链
5. 更新资产状态和链上信息
6. 更新用户资产数量(调用 User Service
7. 发布事件asset.mint_complete
```
#### 2.1.2 ✅ 已确认
**Q1: 铸造费用和支付方式**
- ✅ 铸造需要消耗水晶CrystalBalance
- ✅ 费用后续同样会引入规则表进行定义,现在直接和 socialService 一致,统一定义在 `config/asset_config.go` 文件中(`CostCrystal`
- ✅ 支付是在创建订单的时候扣除
- ✅ 上链失败会进行退款
**Q2: 铸造材料来源**
- ✅ 目前可以暂不考虑,随机生成一个图片的 URL 即可
- ✅ 后续再进行拓展
**Q3: 铸造限制**
- ✅ 次数限制同样和 Q1 一致,后续同样会引入规则表进行定义
- ✅ 现在直接和 socialService 一致,统一定义在 `config/asset_config.go` 文件中(`MaxMintCountPerDay`, `MaxMintCountPerUser`
**Q4: 异步处理机制**
- ✅ 上链为异步机制
- ✅ 但是目前不引入上链功能,所以只需要做简单的模拟
- ✅ 后续引入后再进行优化
---
### 2.2 资产查询功能
#### 2.2.1 我的藏品列表
**接口设计:**
```
GET /api/v1/assets/me
Query Parameters:
- page: 页码默认1
- page_size: 每页数量默认20最大100
- status: 状态筛选all, pending, minted, failed
- keyword: 关键词搜索(资产名称)
- sort: 排序方式created_at_desc, created_at_asc, name_asc
```
**响应结构:**
```json
{
"code": 200,
"message": "ok",
"data": {
"items": [
{
"asset_id": 123,
"name": "藏品名称",
"cover_url": "https://...",
"status": "minted", // pending, minting, minted, failed
"token_id": "0x123...",
"tx_hash": "0xabc...",
"created_at": 1704067200000,
"minted_at": 1704067300000
}
],
"total": 100,
"page": 1,
"page_size": 20,
"has_more": true
}
}
```
#### 2.2.2 资产详情
**接口设计:**
```
GET /api/v1/assets/{asset_id}
```
**响应结构:**
```json
{
"code": 200,
"message": "ok",
"data": {
"asset_id": 123,
"name": "藏品名称",
"description": "藏品描述",
"cover_url": "https://...",
"owner": {
"user_id": 1,
"nickname": "张三"
},
"star_id": 1,
"status": "minted",
"token_id": "0x123...",
"tx_hash": "0xabc...",
"materials": [
{
"material_id": 1,
"type": "platform",
"url": "https://..."
}
],
"created_at": 1704067200000,
"minted_at": 1704067300000,
"like_count": 10,
"is_liked": false // 当前用户是否点赞
}
}
```
#### 2.2.3 ✅ 已确认
**Q5: 资产可见性**
- ✅ 用户不能看到别人的资产
- ✅ 目前不需要考虑分享等功能
- ✅ 但是在表格设计的时候可以留一个权限控制的字段接口出来(`visibility` 字段)
**Q6: 资产属性**
- ✅ 名称name和封面图cover_url是目前设计的必须字段
- ✅ 同样可以预留描述description、稀有度rarity、标签tags的字段接口以便后续功能添加
---
### 2.3 素材管理功能
#### 2.3.1 平台素材列表
**接口设计:**
```
GET /api/v1/materials/platform
Query Parameters:
- page: 页码
- page_size: 每页数量
- category: 分类筛选(可选)
```
**响应结构:**
```json
{
"code": 200,
"message": "ok",
"data": {
"items": [
{
"material_id": 1,
"name": "素材名称",
"url": "https://...",
"category": "背景",
"star_id": 1
}
],
"total": 50,
"page": 1,
"page_size": 20
}
}
```
#### 2.3.2 ✅ 已确认
**Q7: 素材分类和管理**
- ✅ 素材需要根据 `star_id` 进行隔离
**Q8: 用户上传素材**
- ✅ 用户可以上传自己的素材
- ✅ 目前暂不需要审核功能
- ✅ 不需要 `materials` 表,直接在 `assets` 表里面加入一个 `material_url` 字段代表素材的 URL 即可
- ✅ 后续会定期清理这个字段
---
### 2.4 图片上传功能
#### 2.4.1 上传接口设计
**接口设计:**
```
POST /api/v1/assets/upload
Content-Type: multipart/form-data
Form Data:
- file: 图片文件
- type: 上传类型cover, material
```
**响应结构:**
```json
{
"code": 200,
"message": "ok",
"data": {
"url": "https://minio.example.com/bucket/path/to/image.jpg",
"upload_id": "upload_123"
}
}
```
#### 2.4.2 ✅ 已确认
**Q9: 图片存储和审核**
- ✅ 暂不考虑图片存储的细节问题,存一个 URL 即可
**Q10: 上传任务管理**
- ✅ 不需要上传任务表
- ✅ 直接阻塞上传,上传成功返回后才会允许前端用户进行下一步操作
---
### 2.5 上链状态查询
#### 2.5.1 状态查询接口
**接口设计:**
```
GET /api/v1/assets/{asset_id}/status
```
**响应结构:**
```json
{
"code": 200,
"message": "ok",
"data": {
"asset_id": 123,
"status": "minting", // pending, minting, minted, failed
"tx_hash": "0xabc...",
"token_id": "0x123...",
"block_number": 12345,
"minted_at": 1704067300000,
"error_message": "" // 如果失败,错误信息
}
}
```
#### 2.5.2 ✅ 已确认
**Q11: 区块链集成**
- ✅ 区块链暂不考虑,后续才会引入相应的函数功能
- ✅ 目前只需要模拟已经上链成功结束即可
**Q12: 上链信息存储**
- ✅ 只需要存储 `tx_hash``block_number` 即可
- ✅ 不需要 `token_id`
---
## 三、数据库设计
### 3.1 核心表结构
#### 3.1.1 assets 表(资产表)
**基于提供的数据库设计,完善后的表结构:**
```sql
CREATE TABLE assets (
-- 主键和基础字段
id BIGSERIAL PRIMARY KEY, -- asset_id (Asset ID)
owner_uid BIGINT NOT NULL, -- 当前持有者 (Current Owner)
star_id BIGINT NOT NULL, -- 所属星球 (Belonging Planet)
name VARCHAR(100) NOT NULL, -- 藏品名称 (Collection Name)
cover_url VARCHAR(500) NOT NULL, -- 封面图URL (Cover Image URL)
-- 用户上传的素材URL后续会定期清理
material_url VARCHAR(500), -- 用户上传的素材URL可选
-- 预留字段(后续功能扩展)
description TEXT, -- 藏品描述(预留)
rarity INT, -- 稀有度(预留)
tags JSONB, -- 标签预留JSON数组
-- 权限控制字段(预留)
visibility VARCHAR(20) DEFAULT 'private', -- 可见性private, friends, public预留
-- 状态字段
status INT NOT NULL DEFAULT 0, -- 0:Pending, 1:Active (状态枚举)
-- 链上信息(目前模拟,后续引入区块链功能)
tx_hash VARCHAR(100), -- Web3:交易哈希
block_number BIGINT, -- 区块号
-- 社交相关(与 Social Service 交互)
like_count INT NOT NULL DEFAULT 0, -- 点赞数 (Like Count)
-- 时间戳字段(用于排序、查询、事件追踪)
created_at BIGINT NOT NULL, -- 创建时间(毫秒时间戳)
updated_at BIGINT NOT NULL, -- 更新时间(毫秒时间戳)
minted_at BIGINT, -- 上链成功时间(毫秒时间戳,用于 Task Service 事件)
-- 软删除(与现有服务保持一致)
deleted_at BIGINT, -- 软删除时间戳NULL 表示未删除)
is_active BOOLEAN NOT NULL DEFAULT true, -- 是否激活(用于快速查询过滤)
-- 索引
INDEX idx_assets_owner_star (owner_uid, star_id),
INDEX idx_assets_status (status),
INDEX idx_assets_created_at (created_at DESC),
INDEX idx_assets_tx_hash (tx_hash),
INDEX idx_assets_star_active (star_id, is_active),
INDEX idx_assets_deleted_at (deleted_at)
);
```
**完整字段列表(基于提供的设计 + 服务交互所需字段):**
| 字段名 | 类型 | 约束 | 默认值 | 说明 | 来源 |
|--------|------|------|--------|------|------|
| `id` | BIGINT | PK, AUTO_INCREMENT | - | 资产ID | 提供设计 |
| `owner_uid` | BIGINT | NOT NULL, FK | - | 当前持有者 | 提供设计 |
| `star_id` | BIGINT | NOT NULL, FK | - | 所属星球 | 提供设计 |
| `name` | VARCHAR(100) | NOT NULL | - | 藏品名称 | 提供设计 |
| `cover_url` | VARCHAR(500) | NOT NULL | - | MinIO地址 | 提供设计 |
| `status` | INT | NOT NULL | 0 | 状态0:Pending, 1:Active | 提供设计 |
| `tx_hash` | VARCHAR(100) | NULL | NULL | Web3交易哈希 | 提供设计 |
| `token_id` | VARCHAR(100) | NULL | NULL | Web3链上ID | 提供设计 |
| `like_count` | INT | NOT NULL | 0 | 点赞数 | 提供设计 |
| `created_at` | BIGINT | NOT NULL | - | 创建时间(毫秒时间戳) | **新增** |
| `updated_at` | BIGINT | NOT NULL | - | 更新时间(毫秒时间戳) | **新增** |
| `minted_at` | BIGINT | NULL | NULL | 上链成功时间(毫秒时间戳) | **新增** |
| `deleted_at` | BIGINT | NULL | NULL | 软删除时间戳 | **新增** |
| `is_active` | BOOLEAN | NOT NULL | true | 是否激活 | **新增** |
**字段说明:**
| 字段 | 类型 | 说明 | 用途 |
|------|------|------|------|
| `id` | bigint | 资产ID主键 | 唯一标识 |
| `owner_uid` | bigint | 当前持有者 | 资产归属,与 User Service 交互 |
| `star_id` | bigint | 所属星球 | 数据隔离,与现有服务保持一致 |
| `name` | varchar | 藏品名称 | 显示和搜索 |
| `cover_url` | varchar | 封面图URL | 图片展示 |
| `material_url` | varchar | 用户上传的素材URL | 用户自定义素材(后续会清理) |
| `status` | int | 状态0:Pending, 1:Active | 状态管理 |
| `tx_hash` | varchar | 交易哈希 | 链上查询(目前模拟) |
| `block_number` | bigint | 区块号 | 链上查询(目前模拟) |
| `like_count` | int | 点赞数 | 与 Social Service 交互 |
| `created_at` | bigint | 创建时间 | 排序、查询、Task Service 事件 |
| `updated_at` | bigint | 更新时间 | 追踪变更 |
| `minted_at` | bigint | 上链成功时间 | 事件发布、统计 |
| `deleted_at` | bigint | 软删除时间 | 数据恢复、审计 |
| `is_active` | boolean | 是否激活 | 快速查询过滤 |
| `description` | text | 藏品描述 | 🔵 预留字段 |
| `rarity` | int | 稀有度 | 🔵 预留字段 |
| `tags` | jsonb | 标签JSON数组 | 🔵 预留字段 |
| `visibility` | varchar | 可见性private/friends/public | 🔵 预留字段 |
**状态枚举值:**
```go
const (
AssetStatusPending = 0 // 待处理(创建中)
AssetStatusActive = 1 // 已激活(上链成功)
// 预留AssetStatusMinting = 2 // 上链中
// 预留AssetStatusFailed = 3 // 上链失败
)
```
**索引设计说明:**
| 索引名 | 字段 | 用途 |
|--------|------|------|
| `idx_assets_owner_star` | `(owner_uid, star_id)` | 查询用户的资产列表 |
| `idx_assets_status` | `(status)` | 按状态筛选资产 |
| `idx_assets_created_at` | `(created_at DESC)` | 按创建时间排序 |
| `idx_assets_tx_hash` | `(tx_hash)` | 通过交易哈希查询 |
| `idx_assets_star_active` | `(star_id, is_active)` | 按明星和激活状态查询 |
| `idx_assets_deleted_at` | `(deleted_at)` | 软删除查询过滤 |
**Q13: 资产表字段补充**
-`description`(描述)字段:已添加为预留字段
-`block_number`(区块号)字段:已添加
-`token_id`链上ID字段不需要已移除
-`contract_address`(合约地址)字段:不需要
-`chain_id`链ID字段不需要
-`material_url`用户上传素材URL字段已添加后续会定期清理
- ✅ 不需要合约地址和链ID其他都需要description, block_number等
#### 3.1.2 mint_orders 表(铸造订单表)
**基于提供的数据库设计,完善后的表结构:**
```sql
CREATE TABLE mint_orders (
-- 主键
order_id VARCHAR(100) PRIMARY KEY, -- 铸造订单号 (Mint Order Number)
-- 关联字段
user_id BIGINT NOT NULL, -- 用户ID
asset_id BIGINT, -- 关联资产(生成后回填) (Associated Asset)
star_id BIGINT NOT NULL, -- 明星ID用于数据隔离
-- 状态字段
status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING/PROCESSING/SUCCESS/FAILED
-- 费用相关(与 User Service 交互)
cost_crystal BIGINT DEFAULT 0, -- 消耗的水晶数量(用于记录和审计)
-- 错误处理
error_message TEXT, -- 错误信息(如果失败)
retry_count INT DEFAULT 0, -- 重试次数(用于上链失败重试)
-- 时间戳字段
created_at BIGINT NOT NULL, -- 创建时间(毫秒时间戳)
updated_at BIGINT NOT NULL, -- 更新时间(毫秒时间戳)
minted_at BIGINT, -- 上链成功时间(用于 Task Service 事件)
-- 外键约束
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE SET NULL,
-- 索引
INDEX idx_mint_orders_user_star (user_id, star_id),
INDEX idx_mint_orders_asset (asset_id),
INDEX idx_mint_orders_status (status),
INDEX idx_mint_orders_created_at (created_at DESC)
);
```
**字段说明:**
| 字段 | 类型 | 说明 | 用途 |
|------|------|------|------|
| `order_id` | varchar | 铸造订单号(主键) | 唯一标识,使用 UUID 生成 |
| `user_id` | bigint | 用户ID | 与 User Service 交互 |
| `asset_id` | bigint | 关联资产ID | 关联 assets 表(创建资产后回填) |
| `star_id` | bigint | 明星ID | 数据隔离 |
| `status` | varchar | 订单状态 | PENDING/PROCESSING/SUCCESS/FAILED |
| `cost_crystal` | bigint | 消耗的水晶数量 | 记录费用,用于审计和退款 |
| `error_message` | text | 错误信息 | 失败原因记录 |
| `retry_count` | int | 重试次数 | 上链失败重试机制 |
| `created_at` | bigint | 创建时间 | 排序、查询 |
| `updated_at` | bigint | 更新时间 | 追踪变更 |
| `minted_at` | bigint | 上链成功时间 | Task Service 事件发布 |
**状态枚举值:**
```go
const (
MintOrderStatusPending = "PENDING" // 待处理
MintOrderStatusProcessing = "PROCESSING" // 处理中(上链中,目前模拟)
MintOrderStatusSuccess = "SUCCESS" // 成功
MintOrderStatusFailed = "FAILED" // 失败
// 注意:不需要 CANCELLED 状态,不支持订单取消功能
)
```
**字段说明:**
| 字段 | 类型 | 说明 | 状态 |
|------|------|------|------|
| `order_id` | varchar | 铸造订单号UUID | ✅ 必需 |
| `user_id` | bigint | 用户ID | ✅ 必需 |
| `asset_id` | bigint | 关联资产ID | ✅ 必需 |
| `star_id` | bigint | 明星ID | ✅ 必需 |
| `status` | varchar | 订单状态 | ✅ 必需 |
| `cost_crystal` | bigint | 消耗的水晶数量 | ✅ 必需 |
| `error_message` | text | 错误信息 | ✅ 必需 |
| `retry_count` | int | 重试次数 | ✅ 必需 |
| `created_at` | bigint | 创建时间 | ✅ 必需 |
| `updated_at` | bigint | 更新时间 | ✅ 必需 |
| `minted_at` | bigint | 上链成功时间 | ✅ 必需 |
### 3.2 与现有服务交互所需的额外字段
#### 3.2.1 与 User Service 交互
**需要添加的字段:**
1. **`assets.created_at` / `mint_orders.created_at`**
- **用途**:记录创建时间,用于:
- 资产列表排序(按创建时间)
- Task Service 事件发布(`asset.mint` 事件需要时间戳)
- 统计和报表(每日/每月新增资产数)
2. **`assets.minted_at` / `mint_orders.minted_at`**
- **用途**:记录上链成功时间,用于:
- Task Service 事件发布(`asset.mint_complete` 事件)
- 统计上链成功率
- 计算上链耗时
3. **`mint_orders.cost_crystal`**
- **用途**:记录消耗的水晶数量,用于:
- 调用 User Service 扣除余额时的参数
- 上链失败时的退款计算
- 费用审计和统计
4. **`assets.updated_at` / `mint_orders.updated_at`**
- **用途**:追踪数据变更,用于:
- 数据同步和缓存更新
- 审计日志
#### 3.2.2 与 Social Service 交互
**已包含的字段:**
1. **`assets.like_count`**
- **用途**:存储点赞数,避免每次查询都 JOIN `asset_likes`
- **更新方式**Social Service 点赞/取消点赞时,通过 RPC 调用更新
**✅ 已确认:**
- ✅ 暂不考虑 Gallery Service不需要 `is_exhibited` 字段
#### 3.2.3 与 Gallery Service 交互(暂不考虑)
**✅ 已确认:**
- ✅ 目前不考虑 Gallery Service 的实现
- ✅ 后续引入 Gallery Service 时,再添加相应的字段和接口
- ✅ 可能的字段:`assets.is_exhibited` 或通过关联表实现
#### 3.2.4 与 Task Service 交互
**需要添加的字段:**
1. **`assets.created_at`**
- **用途**:发布 `asset.mint` 事件时的时间戳
2. **`assets.minted_at`**
- **用途**:发布 `asset.mint_complete` 事件时的时间戳
**事件发布格式:**
```json
{
"event_type": "asset.mint_complete",
"user_id": 1,
"star_id": 1,
"asset_id": 123,
"minted_at": 1704067300000,
"timestamp": 1704067300000
}
```
#### 3.2.5 数据隔离和软删除
**需要添加的字段:**
1. **`assets.deleted_at` / `mint_orders.deleted_at`**
- **类型**BIGINT NULL
- **用途**软删除与现有服务User Service保持一致
- **查询过滤**`WHERE deleted_at IS NULL`
2. **`assets.is_active`**
- **类型**BOOLEAN DEFAULT true
- **用途**:快速查询过滤,避免每次都检查 `deleted_at`
- **索引**`(star_id, is_active)` 复合索引
#### 3.2.6 字段添加总结
**assets 表需要添加的字段:**
| 字段名 | 类型 | 默认值 | 说明 | 交互服务 |
|--------|------|--------|------|----------|
| `created_at` | BIGINT | NOT NULL | 创建时间(毫秒时间戳) | Task Service |
| `updated_at` | BIGINT | NOT NULL | 更新时间(毫秒时间戳) | 通用 |
| `minted_at` | BIGINT | NULL | 上链成功时间(毫秒时间戳) | Task Service |
| `deleted_at` | BIGINT | NULL | 软删除时间戳 | 通用 |
| `is_active` | BOOLEAN | true | 是否激活 | 通用 |
**mint_orders 表需要添加的字段:**
| 字段名 | 类型 | 默认值 | 说明 | 交互服务 |
|--------|------|--------|------|----------|
| `updated_at` | BIGINT | NOT NULL | 更新时间(毫秒时间戳) | 通用 |
| `minted_at` | BIGINT | NULL | 上链成功时间(毫秒时间戳) | Task Service |
| `cost_crystal` | BIGINT | 0 | 消耗的水晶数量 | User Service |
| `error_message` | TEXT | NULL | 错误信息 | 错误处理 |
| `retry_count` | INT | 0 | 重试次数 | 错误处理 |
---
**✅ 已确认:**
- ✅ 不需要 `materials` 表:用户上传的素材直接存储在 `assets.material_url` 字段中
- ✅ 不需要 `asset_materials` 表:资产和素材的关联关系不需要单独维护
- ✅ 不需要 `upload_tasks` 表:上传采用阻塞式,上传成功返回后才会允许前端用户进行下一步操作
- ✅ 素材隔离:根据 `star_id` 进行隔离(在 `assets` 表中已有 `star_id` 字段)
#### 3.1.3 asset_likes 表(点赞记录表)
**用于存储用户对资产的点赞记录,支持高并发场景:**
```sql
CREATE TABLE asset_likes (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL, -- 用于数据隔离和查询优化
created_at BIGINT NOT NULL,
-- 唯一索引:防止重复点赞(数据库层面保护)
UNIQUE KEY uk_asset_likes_user_asset (asset_id, user_id),
-- 索引:用于查询用户点赞列表
INDEX idx_asset_likes_user_star (user_id, star_id, created_at DESC),
-- 索引:用于查询资产点赞用户列表(可选功能)
INDEX idx_asset_likes_asset (asset_id, created_at DESC),
-- 外键约束
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE CASCADE
);
```
**字段说明:**
| 字段 | 类型 | 说明 | 用途 |
|------|------|------|------|
| `id` | bigint | 主键 | 唯一标识 |
| `asset_id` | bigint | 资产ID | 关联 assets 表 |
| `user_id` | bigint | 用户ID | 点赞用户 |
| `star_id` | bigint | 明星ID | 数据隔离,查询优化 |
| `created_at` | bigint | 创建时间 | 排序、统计 |
**设计要点:**
-**唯一索引**`uk_asset_likes_user_asset` 防止重复点赞
-**复合索引**`idx_asset_likes_user_star` 支持查询用户点赞列表
-**外键约束**:资产删除时自动删除点赞记录
-**第一阶段设计**:直接数据库查询,不使用 Redis 缓存(后续可根据性能需求再引入)
**详细设计文档:** [资产点赞功能高性能设计.md](./资产点赞功能高性能设计.md)
---
## 四、服务间交互设计
### 4.1 与 User Service 的交互
#### 4.1.1 需要调用的接口
**验证用户和粉丝档案:**
```
RPC: ValidateUser(user_id) -> bool
RPC: ValidateFanProfile(user_id, star_id) -> bool
```
- **使用场景**:创建铸造订单前验证用户有效性
- **使用字段**`mint_orders.user_id`, `mint_orders.star_id`
**扣除/增加余额:**
```
RPC: UpdateCrystalBalance(user_id, star_id, delta) -> new_balance
RPC: UpdateCoinBalance(user_id, star_id, delta) -> new_balance
```
- **使用场景**
- 创建铸造订单时扣除水晶(`mint_orders.cost_crystal`
- 上链失败时退款
- **使用字段**`mint_orders.cost_crystal`, `mint_orders.user_id`, `mint_orders.star_id`
**更新资产数量:**
```
RPC: UpdateAssetsCount(user_id, star_id, delta) -> new_count
```
- **使用场景**:资产上链成功后,更新用户的资产数量
- **使用字段**`assets.owner_uid`, `assets.star_id`
- **触发时机**`assets.status` 从 `0` (Pending) 变为 `1` (Active) 时
#### 4.1.2 需要提供的接口
**查询用户信息(用于资产详情展示):**
```
RPC: GetUserInfo(user_id) -> UserInfo
```
- **使用场景**:资产详情中显示持有者信息
- **使用字段**`assets.owner_uid`
**需要确认的问题 ⚠️**
**Q18: User Service 接口**
-`ValidateUser(user_id) -> bool` - **已实现**(通过 `GetUser` RPC 接口实现Social Service 中已有使用)
-`ValidateFanProfile(user_id, star_id) -> bool` - **已实现**(通过 `GetFanProfile` RPC 接口实现Social Service 中已有使用)
-`UpdateCrystalBalance(user_id, star_id, delta) -> new_balance` - **未实现**,需要在 User Service 中添加 RPC 接口
- ⚠️ `UpdateAssetsCount(user_id, star_id, delta) -> new_count` - **Repository 层已实现**`IncrementAssetsCount`/`DecrementAssetsCount`),但**缺少 RPC 接口**,需要在 User Service 中添加
**补充说明:**
- `ValidateUser``ValidateFanProfile` 可以通过现有的 `GetUser``GetFanProfile` 接口实现,返回错误即表示不存在
- `UpdateCrystalBalance` 需要新增 RPC 接口,用于扣除/增加水晶余额
- `UpdateAssetsCount` 需要在 User Service 的 Proto 中新增 RPC 接口,调用现有的 Repository 方法
**Q19: 接口提供**
- ✅ Asset Service 需要提供 RPC 接口给其他服务
- ✅ 需要调用的服务:
- **Social Service**:需要 `GetAsset(asset_id)` 接口用于验证资产是否存在(点赞功能)
- **Gallery Service**(后续):需要 `ValidateAsset``GetAsset` 接口
- **Task Service**(后续):可能需要查询资产信息用于事件处理
---
### 4.2 与 Social Service 的交互
#### 4.2.1 点赞功能交互
**Social Service 需要提供的接口:**
**更新点赞数:**
```
RPC: UpdateAssetLikeCount(asset_id, delta) -> new_count
```
- **使用场景**:用户点赞/取消点赞时,更新 `assets.like_count`
- **使用字段**`assets.like_count`
- **delta 值**+1点赞或 -1取消点赞
**查询用户是否点赞:**
```
RPC: CheckAssetLike(user_id, star_id, asset_id) -> bool
```
- **使用场景**:资产详情中显示 `is_liked` 状态
- **使用字段**`assets.id`
**Asset Service 需要提供的接口:**
**获取资产信息:**
```
RPC: GetAsset(asset_id) -> AssetInfo
```
- **使用场景**Social Service 点赞时验证资产是否存在
- **使用字段**`assets.id`, `assets.status`, `assets.is_active`
**✅ 简化设计方案(第一阶段,直接数据库交互):**
**核心设计要点:**
1. **数据库直接交互**
- 点赞操作直接写入数据库
- 使用数据库原子更新保证一致性
- 使用唯一索引防止重复点赞
2. **原子操作**
- 使用 `UPDATE assets SET like_count = like_count + 1` 原子更新
- 使用数据库唯一索引 `uk_asset_likes_user_asset` 防止重复
3. **防重复点赞**
- 数据库唯一索引 `uk_asset_likes_user_asset` 保护
- 应用层先查询再插入(双重保护)
4. **性能优化**
- 数据库索引优化(`uk_asset_likes_user_asset`, `idx_asset_likes_user_star`
- 原子更新减少锁竞争
- 不使用 Redis 缓存,直接查询数据库(后续可根据性能需求再引入)
**实现方式:**
```go
// 点赞操作(直接数据库)
1. 检查是否已点赞SELECT COUNT(*) FROM asset_likes WHERE asset_id = ? AND user_id = ?
2. 如果未点赞
- INSERT INTO asset_likes (asset_id, user_id, star_id, created_at)
- UPDATE assets SET like_count = like_count + 1 WHERE id = ?
3. 返回成功
```
**后续优化(第二阶段,暂不实现):**
- 如需提升性能,可后续引入 Redis 缓存
- 可考虑异步写入数据库
- 详细设计参考:[资产点赞功能高性能设计.md](./资产点赞功能高性能设计.md)
**需要确认的问题 ⚠️**
**Q20: 点赞功能实现**
- ✅ 资产点赞功能在 Social Service 中实现(参考:[资产点赞功能高性能设计.md](./资产点赞功能高性能设计.md)
- ✅ Asset Service 不需要提供资产列表Social Service 直接查询 assets 表
- ✅ 资产详情中的 like_count 和 is_liked 获取方式:
- **当前实现**:直接查询数据库(`assets.like_count` 和 `asset_likes` 表)
- **后续优化**:如需提升性能,可后续引入 Redis 缓存(暂不实现)
- ⚠️ **需要补充**Social Service 的 Proto 中需要添加资产点赞相关的 RPC 接口定义(`LikeAsset`, `UnlikeAsset`, `CheckAssetLike` 等)
---
### 4.3 与 Gallery Service 的交互
#### 4.3.1 资产验证
**Asset Service 需要提供的接口:**
**验证资产是否存在:**
```
RPC: ValidateAsset(asset_id, user_id, star_id) -> bool
```
- **使用场景**Gallery Service 放置资产前验证资产是否存在且属于当前用户
- **使用字段**`assets.id`, `assets.owner_uid`, `assets.star_id`, `assets.status`, `assets.is_active`
**获取资产信息:**
```
RPC: GetAsset(asset_id) -> AssetInfo
```
- **使用场景**Gallery Service 获取资产信息用于展示
- **使用字段**`assets.*`
#### 4.3.2 展馆状态同步
**Gallery Service 需要提供的接口:**
**更新资产展馆状态:**
```
RPC: UpdateAssetExhibitionStatus(asset_id, is_exhibited) -> void
```
- **使用场景**:资产放置/下架时,更新 `assets.is_exhibited`
- **使用字段**`assets.is_exhibited`
- **触发时机**
- 放置资产:`is_exhibited = true`
- 下架资产:`is_exhibited = false`
**需要确认的问题 ⚠️**
**Q21: 展馆集成**
- [ ] Gallery Service 是否需要验证资产是否存在?
- [ ] Asset Service 是否需要提供资产列表接口给 Gallery Service
- [ ] 资产下架时,是否需要通知 Gallery Service
- [ ] 是否需要 `assets.is_exhibited` 字段,还是通过关联表查询?
---
### 4.4 与 Task Service 的交互
#### 4.4.1 事件发布 ✅ **已确认:不使用消息队列**
**实现方式:**
- ✅ 不使用消息队列RocketMQ/Kafka/RabbitMQ
- ✅ 如需事件通知,直接通过 RPC 调用 Task Service
- ✅ 如需事件记录,可在数据库中创建事件表进行记录
**事件类型(如需实现):**
1. **`asset.mint`** - 资产创建事件
- **触发时机**:创建资产记录时(`assets.status = 0`
- **使用字段**`assets.created_at`, `assets.owner_uid`, `assets.star_id`, `assets.id`
- **实现方式**:直接 RPC 调用 Task Service 或数据库记录
2. **`asset.mint_complete`** - 资产上链成功事件
- **触发时机**:资产上链成功,`assets.status` 从 `0` 变为 `1`
- **使用字段**`assets.minted_at`, `assets.owner_uid`, `assets.star_id`, `assets.id`
- **实现方式**:直接 RPC 调用 Task Service 或数据库记录
3. **`asset.mint_failed`** - 资产上链失败事件(可选)
- **触发时机**:资产上链失败时
- **实现方式**:直接 RPC 调用 Task Service 或数据库记录
**✅ 已确认:**
- ✅ 不使用消息队列,直接通过 RPC 调用或数据库记录
- ⚠️ 事件格式是否需要统一规范?**待确认**(如需事件记录,可在数据库中创建事件表)
- ⚠️ 是否需要事件重试机制?**待确认**(如需重试,可在应用层实现)
- ⚠️ 是否需要 `asset.mint_failed` 事件(上链失败时)?**待确认**(如需记录,可在数据库中记录)
---
## 五、配置设计
### 5.1 配置结构
参考 `socialService` 的配置设计,在 `assetService/config/asset_config.go` 中定义配置:
```go
package config
// AssetConfig 资产服务配置
type AssetConfig struct {
// MintConfig 铸造相关配置
MintConfig MintConfig
// RetryConfig 重试相关配置
RetryConfig RetryConfig
}
// MintConfig 铸造配置
type MintConfig struct {
// CostCrystal 铸造费用(水晶数量)
// 后续会引入规则表进行定义现在统一定义在config文件中
CostCrystal int64
// MaxMintCountPerDay 每日最大铸造次数
// 后续会引入规则表进行定义现在统一定义在config文件中
MaxMintCountPerDay int
// MaxMintCountPerUser 用户最大铸造次数(总次数)
// 后续会引入规则表进行定义现在统一定义在config文件中
MaxMintCountPerUser int
}
// RetryConfig 重试配置
type RetryConfig struct {
// MaxRetryCount 上链失败最大重试次数
MaxRetryCount int
// RetryIntervalSeconds 重试间隔(秒)
RetryIntervalSeconds int
}
// GlobalAssetConfig 全局资产配置实例
var GlobalAssetConfig = &AssetConfig{
MintConfig: MintConfig{
CostCrystal: 100, // 默认100水晶
MaxMintCountPerDay: 10, // 默认每日10次
MaxMintCountPerUser: 100, // 默认总次数100次
},
RetryConfig: RetryConfig{
MaxRetryCount: 3, // 默认重试3次
RetryIntervalSeconds: 5, // 默认间隔5秒
},
}
```
### 5.2 配置使用场景
#### 5.2.1 铸造费用CostCrystal
**使用场景:**
- 创建铸造订单时,从用户账户扣除 `CostCrystal` 数量的水晶
- 上链失败时,退还 `CostCrystal` 数量的水晶
**实现位置:**
- `service/mint_service.go` - `CreateMintOrder` 方法
#### 5.2.2 次数限制MaxMintCountPerDay / MaxMintCountPerUser
**使用场景:**
- 创建铸造订单前,检查用户是否超过每日/总次数限制
**实现位置:**
- `service/mint_service.go` - `CreateMintOrder` 方法
- 需要查询 `mint_orders` 表统计用户今日/总铸造次数
#### 5.2.3 重试配置MaxRetryCount / RetryIntervalSeconds
**使用场景:**
- 上链失败时,根据 `MaxRetryCount` 决定是否重试
- 重试间隔由 `RetryIntervalSeconds` 控制
**实现位置:**
- `service/mint_service.go` - 上链失败处理逻辑(目前模拟)
### 5.3 配置更新方法(预留)
```go
// UpdateMintConfig 更新铸造配置
// 注意:后续可以从规则表或配置中心读取配置并调用此方法更新
func (c *AssetConfig) UpdateMintConfig(costCrystal int64, maxPerDay, maxPerUser int) {
c.MintConfig.CostCrystal = costCrystal
c.MintConfig.MaxMintCountPerDay = maxPerDay
c.MintConfig.MaxMintCountPerUser = maxPerUser
}
// UpdateRetryConfig 更新重试配置
func (c *AssetConfig) UpdateRetryConfig(maxRetryCount, retryIntervalSeconds int) {
c.RetryConfig.MaxRetryCount = maxRetryCount
c.RetryConfig.RetryIntervalSeconds = retryIntervalSeconds
}
```
**✅ 已确认:**
- ✅ 铸造费用:配置在 `config/asset_config.go` 中,创建订单时扣除,上链失败退款
- ✅ 次数限制:配置在 `config/asset_config.go` 中,后续会引入规则表
- ✅ 重试次数:配置在 `config/asset_config.go`默认3次
---
## 六、技术架构设计
### 5.1 服务结构
```
assetService/
├── main.go # 服务入口
├── config/ # 配置管理
│ └── asset_config.go
├── repository/ # 数据访问层
│ ├── asset_repository.go
│ ├── mint_order_repository.go
│ └── asset_like_repository.go # 点赞记录(第一阶段:直接数据库)
├── service/ # 业务逻辑层
│ ├── asset_service.go
│ └── mint_service.go
├── provider/ # RPC 提供者
│ └── asset_provider.go
├── client/ # RPC 客户端(调用其他服务)
│ └── user_rpc_client.go
├── proto/ # Proto 定义(可选,如果单独定义)
└── start.sh # 启动脚本
```
### 5.2 外部依赖
#### 6.2.1 区块链服务
**✅ 已确认:**
- ✅ 区块链暂不考虑,后续才会引入相应的功能
- ✅ 目前只需要模拟已经上链成功结束即可
- ✅ 上链为异步机制,但目前不引入上链功能,只做简单模拟
**实现方式:**
- 创建资产时,随机生成 `tx_hash``block_number`
- 模拟异步上链:延迟几秒后更新 `assets.status = 1`Active
- 后续引入区块链功能后再进行优化
#### 6.2.2 对象存储服务
**✅ 已确认:**
- ✅ 暂不考虑图片存储的细节问题存一个URL即可
- ✅ 封面图URL直接存储在 `assets.cover_url` 字段中
- ✅ 用户上传的素材URL存储在 `assets.material_url` 字段中(后续会定期清理)
**实现方式:**
- 前端上传图片后返回图片URL
- 后端直接存储URL不进行图片处理
---
## 七、API 接口设计
### 7.1 接口列表
| 功能 | 方法 | 路径 | 说明 |
|------|------|------|------|
| 创建铸造订单 | POST | `/api/v1/assets/mints` | 创建资产并发起铸造(包含上传封面图) |
| 获取我的藏品列表 | GET | `/api/v1/assets/me` | 获取当前用户的藏品列表 |
| 获取资产详情 | GET | `/api/v1/assets/{asset_id}` | 获取资产详细信息(仅限自己的资产) |
| 查询上链状态 | GET | `/api/v1/assets/{asset_id}/status` | 查询资产上链状态(仅限自己的资产) |
**✅ 已确认:**
- ✅ 不需要单独的上传接口:上传采用阻塞式,在创建铸造订单时一起处理
- ✅ 不需要素材管理接口:用户上传的素材直接存储在 `assets.material_url` 字段中
- ✅ 不需要订单取消接口:不支持订单取消功能
- ✅ 用户不能看到别人的资产:所有查询接口都只返回当前用户的资产
### 6.2 需要确认的问题 ⚠️
**Q26: API 路径规范**
- ✅ API 路径前缀使用 `/api/v1/assets`(与其他服务保持一致)
- ✅ 需要版本控制v1
**Q27: 权限控制**
- ✅ 所有接口都需要登录(通过 Gateway 的 auth middleware
- ✅ 资产查询接口需要验证资产所有权(只能查询自己的资产)
- ✅ 创建铸造订单接口需要验证用户权限和余额
---
## 七、数据隔离设计
### 7.1 隔离方案
**所有表都包含 `star_id` 字段,实现数据隔离:**
```sql
-- 所有查询都基于 user_id + star_id
SELECT * FROM assets
WHERE user_id = ? AND star_id = ?;
```
### 7.2 需要确认的问题 ⚠️
**Q28: 跨明星资产**
- ✅ 资产不能跨明星使用(通过 `star_id` 字段隔离)
- ✅ 用户切换明星身份后,只能看到当前明星下的资产(通过 `star_id` 过滤)
---
## 八、性能优化设计
### 8.1 缓存策略
**需要确认的问题 ⚠️**
**Q29: 缓存需求****已确认:不使用 Redis 缓存**
- ✅ 不使用 Redis 缓存,所有数据查询都直接访问数据库
- ✅ 所有接口都直接查询数据库,保证数据实时性
- ⚠️ **后续优化**:如需提升性能,可后续引入 Redis 缓存(暂不实现)
### 8.2 分页和索引
- ✅ 所有列表接口都支持分页(默认 page=1, page_size=20最大 page_size=100
- ✅ 关键字段建立索引user_id, star_id, status, created_at
---
## 九、错误处理设计
### 9.1 错误码定义
**需要确认的问题 ⚠️**
**Q30: 错误处理**
- ✅ 使用统一的错误码体系(参考 `pkg/errors/errors.go`
- ⚠️ **待确认**:错误信息是否需要国际化?(建议第一阶段仅支持中文,后续再扩展)
---
## 十、数据库设计总结
### 10.1 完整表结构(基于提供设计 + 服务交互字段)
#### assets 表(最终设计)
```sql
CREATE TABLE assets (
-- 主键和基础字段(来自提供设计)
id BIGSERIAL PRIMARY KEY,
owner_uid BIGINT NOT NULL,
star_id BIGINT NOT NULL,
name VARCHAR(100) NOT NULL,
cover_url VARCHAR(500) NOT NULL,
material_url VARCHAR(500), -- 用户上传的素材URL后续会定期清理
description TEXT, -- 藏品描述(预留)
rarity INT, -- 稀有度(预留)
tags JSONB, -- 标签预留JSON数组
visibility VARCHAR(20) DEFAULT 'private', -- 可见性(预留)
status INT NOT NULL DEFAULT 0, -- 0:Pending, 1:Active
tx_hash VARCHAR(100), -- 交易哈希(目前模拟)
block_number BIGINT, -- 区块号(目前模拟)
like_count INT NOT NULL DEFAULT 0,
-- 服务交互所需字段(新增)
created_at BIGINT NOT NULL, -- Task Service 事件
updated_at BIGINT NOT NULL, -- 通用
minted_at BIGINT, -- Task Service 事件
deleted_at BIGINT, -- 软删除
is_active BOOLEAN NOT NULL DEFAULT true, -- 快速查询
-- 索引
INDEX idx_assets_owner_star (owner_uid, star_id),
INDEX idx_assets_status (status),
INDEX idx_assets_created_at (created_at DESC),
INDEX idx_assets_tx_hash (tx_hash),
INDEX idx_assets_star_active (star_id, is_active),
INDEX idx_assets_deleted_at (deleted_at)
);
```
#### mint_orders 表(最终设计)
```sql
CREATE TABLE mint_orders (
-- 主键和基础字段(来自提供设计)
order_id VARCHAR(100) PRIMARY KEY,
user_id BIGINT NOT NULL,
asset_id BIGINT,
star_id BIGINT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
created_at BIGINT NOT NULL,
-- 服务交互所需字段(新增)
updated_at BIGINT NOT NULL, -- 通用
minted_at BIGINT, -- Task Service 事件
cost_crystal BIGINT DEFAULT 0, -- User Service 交互
error_message TEXT, -- 错误处理
retry_count INT DEFAULT 0, -- 重试机制
-- 外键和索引
FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE SET NULL,
INDEX idx_mint_orders_user_star (user_id, star_id),
INDEX idx_mint_orders_asset (asset_id),
INDEX idx_mint_orders_status (status),
INDEX idx_mint_orders_created_at (created_at DESC)
);
```
### 10.2 字段分类总结
**来自提供设计的字段:**
-`assets.id`, `assets.owner_uid`, `assets.star_id`, `assets.name`, `assets.cover_url`
-`assets.status`, `assets.tx_hash`, `assets.like_count`
-`mint_orders.order_id`, `mint_orders.user_id`, `mint_orders.asset_id`, `mint_orders.status`, `mint_orders.created_at`
**根据需求新增的字段:**
-`assets.material_url` - 用户上传的素材URL后续会定期清理
-`assets.description`, `assets.rarity`, `assets.tags`, `assets.visibility` - 预留字段
-`assets.block_number` - 区块号(目前模拟)
-`assets.created_at`, `assets.updated_at`, `assets.minted_at` - 时间戳Task Service 事件)
-`assets.deleted_at`, `assets.is_active` - 软删除(与现有服务一致)
-`mint_orders.updated_at`, `mint_orders.minted_at` - 时间戳
-`mint_orders.cost_crystal` - 费用记录User Service 交互)
-`mint_orders.error_message`, `mint_orders.retry_count` - 错误处理
**已移除的字段:**
-`assets.token_id` - 不需要根据Q12确认
-`assets.is_exhibited` - 暂不需要Gallery Service集成后续再考虑
---
## 十一、待确认问题汇总
### ✅ 已确认的问题
**Q1-Q4: 铸造流程相关**
- ✅ Q1: 铸造费用在config文件中定义创建订单时扣除上链失败退款
- ✅ Q2: 暂不考虑随机生成图片URL即可
- ✅ Q3: 次数限制在config文件中定义
- ✅ Q4: 上链为异步机制,但目前只做简单模拟
**Q5-Q6: 资产可见性和属性**
- ✅ Q5: 用户不能看到别人的资产,预留权限控制字段
- ✅ Q6: 名称和封面图必须,预留描述、稀有度、标签字段
**Q7-Q10: 素材和上传**
- ✅ Q7: 素材需要根据star_id隔离
- ✅ Q8: 用户可以上传素材不需要审核不需要materials表在assets表加material_url字段
- ✅ Q9: 暂不考虑图片存储细节存URL即可
- ✅ Q10: 不需要上传任务表,直接阻塞上传
**Q11-Q12: 区块链集成**
- ✅ Q11: 区块链暂不考虑,模拟上链成功
- ✅ Q12: 只需要tx_hash和block_number不需要token_id
**Q13-Q14: 数据库表字段**
- ✅ Q13: 不需要合约地址和链ID其他都需要description, block_number等
- ✅ Q14: UUID生成不需要支付状态不需要取消功能重试次数在config中
**Q15-Q17: 其他表设计**
- ✅ Q15-Q17: 不需要materials表、asset_materials表、upload_tasks表
**Q23-Q25: 技术选型**
- ✅ Q23: 区块链暂不考虑,后续引入
- ✅ Q24: 暂不考虑图片存储细节
- ✅ Q25: 暂不考虑AI生成功能
### ⚠️ 仍需确认的问题
**Q18: User Service 接口可用性** ⚠️ **部分已实现,部分待补充**
-`ValidateUser` - 已实现(通过 `GetUser` 接口)
-`ValidateFanProfile` - 已实现(通过 `GetFanProfile` 接口)
-`UpdateCrystalBalance` - **需要在 User Service 中新增 RPC 接口**
- ⚠️ `UpdateAssetsCount` - Repository 层已实现,**需要在 User Service 中新增 RPC 接口**
**Q19-Q22: 服务间交互细节**
- ✅ Q19: Asset Service 需要提供 RPC 接口给 Social Service 和 Gallery Service
- ✅ Q20: 资产点赞功能在 Social Service 中实现,直接查询数据库(不使用 Redis
- ✅ Q21: Gallery Service 集成暂不考虑,后续再实现
- ✅ Q22: 事件驱动已确认不使用消息队列,直接通过 RPC 调用或数据库记录
**Q26-Q30: 其他技术细节**
- ✅ Q26-Q27: API 路径规范和权限控制已确认
- ✅ Q28: 跨明星资产隔离已确认
- ✅ Q29: 缓存需求已确认(不使用 Redis 缓存,直接查询数据库)
- ⚠️ Q30: 错误处理国际化待确认
### 📝 需要补充的内容
#### 1. Proto 接口定义
- [ ] **Asset Service Proto**:需要创建 `proto/asset.proto` 文件,定义资产服务的 RPC 接口
- [ ] **User Service Proto 补充**:需要在 `proto/user.proto` 中添加:
- `UpdateCrystalBalance` RPC 接口
- `UpdateAssetsCount` RPC 接口
- [ ] **Social Service Proto 补充**:需要在 `proto/social.proto` 中添加资产点赞相关的 RPC 接口
#### 2. 服务实现状态
- [ ] **Asset Service 服务目录**:需要创建 `services/assetService/` 目录结构
- [ ] **配置管理**:需要创建 `services/assetService/config/asset_config.go`(参考 `socialService/config/social_config.go`
- [ ] **Repository 层**:需要实现 `asset_repository.go`、`mint_order_repository.go`、`asset_like_repository.go`
- [ ] **Service 层**:需要实现 `asset_service.go`、`mint_service.go`
- [ ] **Provider 层**:需要实现 `asset_provider.go`
- [ ] **RPC Client**:需要实现 `user_rpc_client.go`(调用 User Service
#### 3. Gateway 集成
- [ ] **路由配置**:需要在 `gateway/router/router.go` 中添加资产服务的路由
- [ ] **Controller**:需要创建 `gateway/controller/asset_controller.go`
- [ ] **DTO 转换**:需要创建 `gateway/dto/asset_converter.go`
#### 4. 数据库迁移
- [ ] **表结构创建**:需要创建 `assets`、`mint_orders`、`asset_likes` 表的迁移脚本
- [ ] **索引创建**:确保所有索引都已创建
#### 5. 测试
- [ ] **单元测试**Repository 层、Service 层的单元测试
- [ ] **集成测试**:服务间交互的集成测试
- [ ] **HTTP 测试**Gateway 接口的完整测试流程(参考 `用户服务HTTP完整测试流程.md`
---
## 十一、下一步行动
### 阶段 1: 需求确认(当前阶段)✅ **进行中**
- [x] 与产品/业务确认上述 30 个问题(大部分已确认)
- [x] 确定核心功能范围(已确定)
- [x] 确定技术选型(已确定)
- [ ] **待补充**:确认 User Service 接口补充需求
- [ ] **待补充**:确认 Social Service 资产点赞接口定义
### 阶段 2: 详细设计 ⚠️ **部分完成**
- [x] 完善数据库表结构(已完成,见 `pkg/models/asset.go`
- [ ] **待补充**:设计 Asset Service Proto 接口定义
- [ ] **待补充**:设计 User Service Proto 接口补充(`UpdateCrystalBalance`、`UpdateAssetsCount`
- [ ] **待补充**:设计 Social Service Proto 接口补充(资产点赞相关)
- [x] 设计服务间交互协议(已设计)
- [x] 设计错误处理机制(参考现有服务)
### 阶段 3: 开发实现 ❌ **未开始**
- [ ] Repository 层实现
- [ ] Service 层实现
- [ ] Provider 层实现
- [ ] Gateway 集成
- [ ] 单元测试
### 阶段 4: 测试和上线 ❌ **未开始**
- [ ] 集成测试
- [ ] 性能测试
- [ ] 上线部署
---
## 附录:参考文档
- [微服务架构设计文档](./微服务架构设计.md)
- [用户服务实现文档](../services/userService/README.md)
- [社交服务实现文档](../services/socialService/IMPLEMENTATION_COMPLETE.md)