topfans/docs/superpowers/specs/2026-04-13-collection-asset-starbook-refactor.md
2026-04-22 10:30:27 +08:00

703 lines
28 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.

# 典藏/活动藏品体系 + 星册重构设计
> 日期2026-04-13
> 状态:已评审通过
> 负责人zheng020
---
## 零、重构后页面效果
### 星册主页StarbookContent.vue
```
┌─────────────────────────────────────────────┐
│ ✕ 返回 星册 │ ← Header
├─────────────────────────────────────────────┤
│ 背景图starbook.jpg满屏
│ │
│ ┌─────────────────────────────────────┐ │
│ │ │ │
│ │ [ 原创 ] [ 典藏 ] [ 活动 ] │ │ ← 类型Tab横向滚动
│ │ │ │
│ ├─────────────────────────────────────┤ │
│ │ │ │
│ │ 原创 · 等级五 │ │ ← 原创grade 大在上
│ │ ┌────────┐ ┌────────┐ ┌────────┐│ │
│ │ │ 封面 │ │ 封面 │ │ 封面 ││ │
│ │ └────────┘ └────────┘ └────────┘│ │
│ │ 铸爱-A 铸爱-B 铸爱-C ★820 │ │
│ │ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐│ │
│ │ │ 封面 │ │ 封面 │ │ 更多> ││ │
│ │ └────────┘ └────────┘ └────────┘│ │
│ │ 铸爱-D 铸爱-E [点击更多] │ │ ← 超出6个显示"更多>"
│ │ │ │
│ │ ───────────────────────────────── │ │
│ │ │ │
│ │ 原创 · 等级四 │ │
│ │ ┌────────┐ ┌────────┐ │ │
│ │ │ 封面 │ │ 封面 │ │ │
│ │ └────────┘ └────────┘ │ │
│ │ 铸爱-F 铸爱-G │ │
│ │ │ │
│ │ ...(等级三→等级一) │ │
│ │ │ │
│ └─────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────┤
│ [广场] [星册] [铸爱] [星际] [好友] │ ← BottomNav
└─────────────────────────────────────────────┘
```
**切换到"典藏"时:**
```
│ [ 原创 ] [ 典藏 ] [ 活动 ] │ ← 典藏Tab高亮
├─────────────────────────────────────────────┤
│ 典藏 · 限定典藏 │ ← 按category分组无grade
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 封面 │ │ 封面 │ │ 更多> │ │
│ └────────┘ └────────┘ └────────┘ │
│ 典藏-A 典藏-B [点击更多] │
│ │
│ 典藏 · 经典典藏 │
│ ┌────────┐ ┌────────┐ │
│ │ 封面 │ │ 封面 │ │
│ └────────┘ └────────┘ │
│ 典藏-C 典藏-D │
│ │
│ ... │
```
**切换到"活动"时:**
```
│ [ 原创 ] [ 典藏 ] [ 活动 ] │ ← 活动Tab高亮
├─────────────────────────────────────────────┤
│ 活动 · 生日会 │ ← 按activity_type分组
│ ┌────────┐ ┌────────┐ │
│ │ 封面 │ │ 封面 │ │
│ └────────┘ └────────┘ │
│ 活动-A 活动-B │
│ │
│ 活动 · 演唱会 │
│ ┌────────┐ ┌────────┐ │
│ │ ... │ │ ... │ │
│ └────────┘ └────────┘ │
```
**页面说明:**
- **无槽位展示区**:新设计完全移除槽位概念,改为纯分组浏览
- **类型Tab**`[原创] [典藏] [活动]` 三选一,点击切换
- **默认选中"原创"**:进入页面默认展示原创藏品
- **原创**:按 grade 从等级五顶部到等级一底部排列grade 大的在上
- **典藏**:按 category 子分类分组,无 grade
- **活动**:按 activity_type 分组,无 grade
- **每组最多显示6个NftCard**超出6个显示"更多>"卡片("更多>"不计入6个之内
- **"更多>"卡片**:点击跳转 `/pages/starbook/items?type=regular&category=castlove&grade=5`
---
### 查看更多页面(/pages/starbook/items
```
┌─────────────────────────────────────────────┐
│ ← 返回 原创 · 等级五 │ ← Header
├─────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐│
│ │ 封面图 │ │ 封面图 │ │ 封面图 ││
│ └──────────┘ └──────────┘ └──────────┘│
│ 铸爱藏品-A 铸爱藏品-B 铸爱藏品-C │
│ ★820 ★450 ★120 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐│
│ │ 封面图 │ │ 封面图 │ │ 封面图 ││
│ └──────────┘ └──────────┘ └──────────┘│
│ 铸爱藏品-D 铸爱藏品-E 铸爱藏品-F │
│ ★98 ★45 ★30 │
│ │
│ ─────── 第 1/3 页 ─────── │
│ │
├─────────────────────────────────────────────┤
│ [广场] [星册] [铸爱] [星际] [好友] │
└─────────────────────────────────────────────┘
```
**页面说明:**
- **路由参数**`?type=regular&category=castlove&grade=5&page=1`
- **布局**3列网格每行3个 NftCard
- **分页**每次加载20条触底自动加载下一页
---
## 一、背景与目标
### 1.1 现状问题
- `StarbookContent.vue` 混用通用 `getMyAssetsApi`,无法区分藏品类型(原创/典藏/活动)
- `assets` 表只有一套,没有类型区分字段
- 典藏藏品有子分类category需求但目前表结构不支持
- 原创藏品有等级grade需求但目前表结构不支持
- 活动藏品需要独立的生命周期管理
- 前端封面 URL 逐个解析(`Promise.all` + 多次 OSS 请求),性能差
- 前端多重生命周期触发(`onMounted` + `onActivated` + `onWatch` + `onShow`),存在重复请求
### 1.2 重构目标
1. 建立原创藏品、典藏藏品、活动藏品三套并行的数据表结构
2. 原创藏品按 grade1/2/3分组展示典藏按 category 子分类分组,活动按 activity_type 分组
3. 通过 `asset_registry` 统一索引表实现跨类型统一查询
4. 后端直接返回 OSS 公共 URL前端通过该 URL 直接访问 OSS 资源查看封面
5. 星册页面按类型 + 子分类/等级分组展示,每组最多展示 6 条
6. "查看更多" 跳转独立页面,支持分页
7. 原创藏品(铸爱流程)、典藏藏品、活动藏品均可放入星册
---
## 二、数据模型
### 2.1 现有表(不变动)
| 表名 | 说明 |
|------|------|
| `assets` | 原创藏品(铸爱流程),结构不变 |
**说明:** `cover_url`OSS 公共 URL直接存储在数据库中前端可直接访问。
### 2.2 新建表
#### 2.2.1 典藏藏品表 `collection_assets`
```sql
CREATE TABLE collection_assets (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT UNIQUE NOT NULL, -- 关联 assets 表主键
owner_uid BIGINT NOT NULL,
star_id BIGINT NOT NULL,
name VARCHAR(100) NOT NULL,
cover_url VARCHAR(500) NOT NULL,
category VARCHAR(50) NOT NULL, -- 典藏子分类(动态值,示例:'limited', 'classic'
like_count INT NOT NULL DEFAULT 0,
status SMALLINT NOT NULL DEFAULT 0, -- 0=Pending, 1=Active
metadata JSONB, -- 预留扩展字段
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
CONSTRAINT uk_owner_star_name UNIQUE (owner_uid, star_id, name)
);
CREATE INDEX idx_collection_owner_star ON collection_assets (owner_uid, star_id);
CREATE INDEX idx_collection_category ON collection_assets (category);
CREATE INDEX idx_collection_asset_id ON collection_assets (asset_id);
```
#### 2.2.2 活动藏品表 `activity_assets`
```sql
CREATE TABLE activity_assets (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT UNIQUE NOT NULL,
owner_uid BIGINT NOT NULL,
star_id BIGINT NOT NULL,
activity_id BIGINT NOT NULL, -- 所属活动 ID
activity_type VARCHAR(50) NOT NULL, -- 活动类型(动态值,示例:'birthday', 'anniversary', 'concert'
name VARCHAR(100) NOT NULL,
cover_url VARCHAR(500) NOT NULL,
like_count INT NOT NULL DEFAULT 0,
status SMALLINT NOT NULL DEFAULT 0,
metadata JSONB,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
CONSTRAINT uk_owner_activity_name UNIQUE (owner_uid, activity_id, name)
);
CREATE INDEX idx_activity_owner ON activity_assets (owner_uid, activity_id);
CREATE INDEX idx_activity_star ON activity_assets (star_id, activity_id);
CREATE INDEX idx_activity_type ON activity_assets (activity_type);
CREATE INDEX idx_activity_asset_id ON activity_assets (asset_id);
```
#### 2.2.3 统一索引表 `asset_registry`
```sql
CREATE TABLE asset_registry (
id BIGSERIAL PRIMARY KEY,
asset_id BIGINT NOT NULL,
asset_type VARCHAR(20) NOT NULL, -- 'regular' | 'collection' | 'activity'
owner_uid BIGINT NOT NULL,
star_id BIGINT NOT NULL,
-- 原创藏品专属字段(其他类型时为 NULL
grade SMALLINT, -- 原创藏品等级1 / 2 / 3仅 regular 时有效)
-- 典藏专属字段(其他类型时为 NULL
collection_category VARCHAR(50), -- 典藏子分类(仅 collection 时有效)
-- 活动专属字段(其他类型时为 NULL
activity_id BIGINT,
activity_type VARCHAR(50),
-- 公共字段
status SMALLINT NOT NULL DEFAULT 0,
like_count INT NOT NULL DEFAULT 0,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
CONSTRAINT uk_asset_type_id UNIQUE (asset_type, asset_id),
CONSTRAINT uk_owner_star_type_asset UNIQUE (owner_uid, star_id, asset_type, asset_id)
);
CREATE INDEX idx_registry_owner_star ON asset_registry (owner_uid, star_id);
CREATE INDEX idx_registry_type_star ON asset_registry (asset_type, star_id);
CREATE INDEX idx_registry_star_grade ON asset_registry (star_id, grade)
WHERE asset_type = 'regular';
CREATE INDEX idx_registry_star_activity ON asset_registry (star_id, activity_id)
WHERE asset_type = 'activity';
```
**说明:**
- `asset_type='regular'`(原创藏品):`grade` 有效1/2/3`collection_category` 为 NULL
- `asset_type='collection'`(典藏):`collection_category` 有效,`grade` 为 NULL
- `asset_type='activity'`(活动藏品):`activity_id` / `activity_type` 有效,`grade` 为 NULL
- **同一 `asset_id` 只能属于一种 type**,不能同时注册为 regular 和 collection
### 2.3 设计说明
1. **三种类型的区分方式:**
- `regular`(原创藏品):`grade` 有效1/2/3由点赞数计算得出预留升级接口
- `collection`(典藏):`collection_category` 有效(动态字符串),无 grade
- `activity`(活动藏品):`activity_id` / `activity_type` 有效,无 grade
2. **category / activity_type 为动态字符串**,不预设枚举值,应用层负责校验和展示名称映射
3. **registry 表不自增 asset_id**,由各类型表创建时写入,保证主从表一致性
4. **UNIQUE 约束**`owner_uid + star_id + asset_type + asset_id` 保证用户每种类型下无重复藏品
5. **同一 `asset_id` 只能属于一种 type**,原创藏品、典藏、活动藏品互斥,不能重复注册
6. **`grade` 字段在数据库中为 NULL 表示非原创藏品**,在 API 响应中统一转换为 `0`(由 Gateway 转换层处理)
---
## 三、藏品创建流程
### 3.1 原创藏品(铸爱流程)
```
用户上传素材 → 铸造订单创建 → assets 表写入
→ 同时写入 asset_registry (type='regular', grade=1) -- grade 初始为1升级规则预留
```
说明:原创藏品(铸爱流程)纳入星册体系,创建时同步写入 registry`grade` 初始为 1后续按点赞数升级规则待确认
### 3.2 典藏藏品
```
用户选择"典藏"类型 → 创建 assets 通用记录
→ 创建 collection_assets 专属记录category
→ 同时写入 asset_registry (type='collection')
```
### 3.3 活动藏品
```
用户参与活动并获得奖励 → 创建 assets 通用记录
→ 创建 activity_assets 专属记录activity_id, activity_type
→ 同时写入 asset_registry (type='activity')
```
### 3.4 写入一致性保障
建议在同一个事务内完成 assets 写入和 registry 写入,确保一致性。
---
## 四、原创藏品等级升级机制(预留接口)
`grade` 初始值为 1升级规则待定由团队讨论确认后实现。设计上预留扩展接口
```go
// AssetService 或独立的 GradeService 预留方法
UpgradeGrade(assetID int64, fromGrade, toGrade int) error
// 升级条件判断后期实现,支持:
// - 点赞数阈值触发(如 grade1: ≥0, grade2: ≥100, grade3: ≥500
// - 全网排名触发
// - 手动升级(运营操作)
// 升级后同步更新 asset_registry.grade
```
典藏藏品collection无 grade 字段,按 `category` 子分类区分。
---
## 五、API 设计
### 5.1 核心原则
- **后端直接返回 OSS 公共 URL**,前端直接使用该 URL 访问 OSS 资源(无需调用 OSS 预签名接口)
- **单次请求返回首页全量数据**,避免前端多次请求
### 5.2 接口列表
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/v1/starbook/home` | GET | 星册首页,按 type → category/grade 分组,含原创/典藏/活动三种类型 |
| `/api/v1/starbook/items` | GET | 某分组的藏品列表(分页) |
### 5.3 详细接口定义
#### GET /api/v1/starbook/home
**说明:** 获取当前用户在当前 star 下的星册首页数据
**响应示例:**
```json
{
"code": 200,
"data": {
"groups": [
{
"type": "regular",
"category": "castlove",
"category_name": "原创",
"grades": [
{
"grade": 5,
"items": [
{ "asset_id": 201, "name": "铸爱藏品-A", "cover_url": "https://bucket.oss-cn-shanghai.aliyuncs.com/xxx.jpg", "like_count": 820, "category": "castlove", "grade": 5 }
],
"total_count": 3,
"has_more": false
},
{
"grade": 4,
"items": [...],
"total_count": 8,
"has_more": true
}
]
},
{
"type": "collection",
"category": "limited",
"category_name": "限定典藏",
"items": [
{ "asset_id": 101, "name": "限定典藏-1", "cover_url": "https://bucket.oss-cn-shanghai.aliyuncs.com/xxx.jpg", "like_count": 820, "category": "limited" }
],
"total_count": 5,
"has_more": true
},
{
"type": "activity",
"category": "birthday",
"category_name": "生日会",
"items": [...],
"total_count": 2,
"has_more": false
}
]
}
}
```
**说明:**
- `star_id` 从认证上下文JWT Token获取不在请求参数中显式传递
- `groups`:三种类型的分组逻辑不同
- `type='regular'`(原创藏品):按 `grade` 分组grade=1/2/3...`category='castlove'` 固定
- `type='collection'`(典藏):按 `category` 子分类分组,无 grade
- `type='activity'`(活动藏品):按 `activity_type` 分组,无 grade
- 每组最多返回 6 条,`has_more=true` 表示还有更多(点击"查看更多"跳转分页页)
- **Gateway 转换层**:数据库中 `grade` 为 NULL 时,转换为 `0` 返回(非 regular 类型)
#### GET /api/v1/starbook/items
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| type | string | 是 | `regular` / `collection` / `activity` |
| category | string | 否 | 子分类不传则返回该类型全部regular 时传 `castlove` |
| grade | int | 否 | 等级(仅 regular 时有效1/2/3... |
| page | int | 否 | 默认 1 |
| page_size | int | 否 | 默认 20 |
**响应示例:**
```json
{
"code": 200,
"data": {
"items": [
{
"asset_id": 201,
"asset_type": "regular",
"name": "铸爱藏品-A",
"cover_url": "https://bucket.oss-cn-shanghai.aliyuncs.com/xxx.jpg",
"like_count": 120,
"category": "castlove",
"grade": 5,
"created_at": 1743004800000
}
],
"total": 15,
"page": 1,
"page_size": 20,
"has_more": false
}
}
```
**说明:**
- `type='regular'``grade` 取值 1/2/3...`category='castlove'` 固定
- `type='collection'` 时无 grade 字段,按 `category` 筛选
- `type='activity'` 时无 grade 字段,按 `activity_type`(即 category 参数)筛选
---
## 六、后端模块划分
### 6.1 Service 层
| Service | 职责 |
|---------|------|
| `AssetService` | 现有流程改造:创建原创藏品时同步写 asset_registry (type='regular', grade=1);预留 grade 升级接口 |
| `CollectionService`(新建) | 管理 `collection_assets`,典藏专属逻辑(含 category 子分类) |
| `ActivityAssetService`(新建) | 管理 `activity_assets`,活动藏品专属逻辑 |
| `StarbookService`(新建) | 星册业务编排,调用各 Service整合数据返回 OSS URL |
### 6.2 StarbookService 核心逻辑
1.`asset_registry` 查询当前用户 + 当前 star 下的所有藏品regular + collection + activity
2. 按 type → 各自维度分组regular 按 gradecollection 按 categoryactivity 按 activity_type
3. 直接返回 OSS URL无需调用 OSS 预签名服务)
4. 返回结构化数据
### 6.3 Repository 层
| Repository | 表 |
|------------|-----|
| `CollectionRepository` | `collection_assets` |
| `ActivityAssetRepository` | `activity_assets` |
| `AssetRegistryRepository` | `asset_registry` |
---
## 七、Proto 文件变更
### 7.1 新建 starbook.proto
```protobuf
syntax = "proto3";
package topfans.starbook;
option go_package = "github.com/topfans/backend/pkg/proto/starbook;starbook";
import "proto/common.proto";
import "google/api/annotations.proto";
service StarbookService {
// 星册首页
rpc GetStarbookHome(GetStarbookHomeRequest) returns (GetStarbookHomeResponse) {
option (google.api.http) = {
get: "/api/v1/starbook/home"
};
}
// 藏品列表(分页)
rpc GetStarbookItems(GetStarbookItemsRequest) returns (GetStarbookItemsResponse) {
option (google.api.http) = {
get: "/api/v1/starbook/items"
};
}
}
message GetStarbookHomeRequest {}
message GetStarbookHomeResponse {
topfans.common.BaseResponse base = 1;
StarbookHomeData data = 2;
}
message StarbookHomeData {
repeated AssetGroup groups = 1;
}
message AssetGroup {
string type = 1; // 'regular' / 'collection' / 'activity'
string category = 2; // 'castlove'(regular) / collection_category / activity_type
string category_name = 3;
// regular 使用 grades 分组collection/activity 使用 flat items 列表
repeated GradeSection grades = 4; // 仅 regular 时有效
repeated AssetItem items = 5; // collection / activity 时有效
int32 total_count = 6;
bool has_more = 7;
}
message GradeSection {
int32 grade = 1; // 仅 regular 时使用
repeated AssetItem items = 2;
int32 total_count = 3;
bool has_more = 4;
}
message AssetItem {
int64 asset_id = 1;
string name = 2;
string cover_url = 3;
int32 like_count = 4;
int64 created_at = 5;
string category = 6; // regular: 'castlove' / collection: category / activity: activity_type
int32 grade = 7; // 仅 regular 时有效1/2/3...),其他类型为 0
}
message GetStarbookItemsRequest {
string type = 1; // 'regular' / 'collection' / 'activity'
string category = 2; // regular 时固定传 'castlove'
int32 grade = 3; // 仅 regular 时有效1/2/3...
int32 page = 4;
int32 page_size = 5;
}
message GetStarbookItemsResponse {
topfans.common.BaseResponse base = 1;
AssetListData data = 2;
}
message AssetListData {
repeated AssetItem items = 1;
int64 total = 2;
int32 page = 3;
int32 page_size = 4;
bool has_more = 5;
}
```
---
## 八、前端重构
### 8.1 生命周期优化
**问题:** 当前 `onMounted` + `onActivated` + `onShow` + `watch(isActive)` 四处触发 `loadAssetsList()`
**解决:**
```js
// 只保留 onShow + watch isActive合并为单一加载逻辑
let lastLoadedAt = 0;
onShow(() => {
if (props.isActive) {
loadStarbookData();
}
});
watch(() => props.isActive, (newVal) => {
if (newVal) loadStarbookData();
});
// 限制频繁刷新:距离上次加载不足 1 秒则跳过
function loadStarbookData() {
const now = Date.now();
if (now - lastLoadedAt < 1000) return;
lastLoadedAt = now;
// ... 实际加载逻辑
}
```
### 8.2 数据流变更
| 变更前 | 变更后 |
|--------|--------|
| 调用 `getMyAssetsApi`(原创藏品) | 调用 `getStarbookHomeApi`(统一,含 regular/collection/activity |
| 手动解析封面 URL`Promise.all` 逐个调 OSS | 后端直接返回 `cover_url` |
| 前端按 index 硬分组 | 后端按 type → category → grade 分组返回 |
| 原创藏品不展示在星册 | 原创藏品type='regular')纳入星册体系 |
### 8.3 页面路由
| 页面 | 路由 | 说明 |
|------|------|------|
| 星册主页 | `/pages/starbook/index` | 不变 |
| 查看更多 | `/pages/starbook/items?type=regular&category=castlove&grade=5` | 新页面,接分页数据 |
### 8.4 数据结构(前端 JavaScript
```ts
interface StarbookHomeData {
groups: AssetGroup[]
}
interface AssetGroup {
type: 'regular' | 'collection' | 'activity'
category: string // regular: 'castlove' / collection: 子分类 / activity: activity_type
category_name: string
// regular 按 grade 分组collection/activity 直接用 items 列表
grades?: GradeSection[] // 仅 regular 时有效
items?: AssetItem[] // collection / activity 时有效
total_count: number
has_more: boolean
}
interface GradeSection {
grade: number // regular: 1/2/3...
items: AssetItem[]
total_count: number
has_more: boolean
}
interface AssetItem {
asset_id: number
name: string
cover_url: string
like_count: number
created_at: number
category: string // regular: 'castlove' / collection: 子分类 / activity: activity_type
grade: number // regular: 1/2/3...,其他类型为 0
}
// grade 中文转换函数(前端使用)
function toChineseGrade(grade) {
const map = { 1: '一', 2: '二', 3: '三', 4: '四', 5: '五' };
return `等级${map[grade] || grade}`;
}
```
**说明:**
- `type='regular'``grades[]` 分组(按 grade`grade` 取值 1/2/3...`category='castlove'` 固定
- `type='collection'``items[]` 列表(按 category 分组),`grade=0`(数据库存 NULLAPI 转换层统一返回 0`category` 为典藏子分类
- `type='activity'``items[]` 列表(按 activity_type 分组),`grade=0`(数据库存 NULLAPI 转换层统一返回 0`category` 为活动类型
---
## 九、性能保障
1. **后端直接返回 OSS URL**:无需调用 OSS 预签名服务,前端直接用该 URL 访问 OSS 资源
2. **Registry 单表索引**三条索引覆盖所有查询路径owner+star, type+star, star+grade[regular]
3. **首页按组截断**:每 grade 组最多返回 6 条,`has_more` 标识是否还有更多
4. **前端防抖**1 秒内重复触发只执行一次加载
5. **分类动态扩展**category / activity_type 不写死枚举,应用层通过配置或枚举接口获取展示名
---
## 十、待确认事项
| 事项 | 状态 | 说明 |
|------|------|------|
| 典藏子分类category枚举值 | 待确认 | 动态字符串,设计已支持 |
| 活动类型activity_type枚举值 | 待确认 | 动态字符串,设计已支持 |
| 原创藏品 grade 升级规则 | 待确认 | 设计已预留 `UpgradeGrade` 接口 |
| 原创藏品 category 固定值 | 待确认 | 建议 `category='castlove'` |
---
## 十一、影响范围
| 范围 | 变更内容 |
|------|----------|
| 数据库 | 新建 3 张表collection_assets, activity_assets, asset_registry |
| Proto | 新建 starbook.proto |
| Gateway | 新建 StarbookController新增 2 个路由 |
| Service 层 | 新建 CollectionService, ActivityAssetService, StarbookService |
| Repository 层 | 新建 CollectionRepository, ActivityAssetRepository, AssetRegistryRepository |
| 前端 | StarbookContent.vue 重构,新增 /pages/starbook/items.vue |
| 铸爱流程 | **受影响**,原创藏品创建时需同步写入 asset_registrytype='regular', grade=1|