388 lines
12 KiB
Markdown
388 lines
12 KiB
Markdown
# 热门推荐模块前端设计
|
||
|
||
## 一、页面结构
|
||
|
||
### 完整页面布局(4个分类区块纵向堆叠)
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ BannerCarousel │
|
||
├──────────────────────────────────────┤
|
||
│ 热门推荐 │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行1 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行2 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ 🔄 刷新 查看更多 ›│
|
||
├──────────────────────────────────────┤
|
||
│ 热门星卡 │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行1 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行2 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ 🔄 刷新 查看更多 ›│
|
||
├──────────────────────────────────────┤
|
||
│ 热门吧唧 │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行1 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行2 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ 🔄 刷新 查看更多 ›│
|
||
├──────────────────────────────────────┤
|
||
│ 热门海报 │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行1 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ ← 行2 │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ 🔄 刷新 查看更多 ›│
|
||
├──────────────────────────────────────┤
|
||
│ CreationGrid(原有组件,不变) │
|
||
│ [热门作品] [最新作品] [星卡] [吧唧]... │
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
### 单个 HotCategoryBlock 内部结构
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ 热门推荐 │ ← block-title
|
||
├──────────────────────────────────────┤
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ │
|
||
│ └────┘ └────┘ └────┘ └────┘ │ ← block-grid (4×2)
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ 🔄 刷新 查看更多 ›│ ← block-actions
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 二、组件结构
|
||
|
||
### HotCategoryBlock.vue
|
||
|
||
**Props**:
|
||
```javascript
|
||
{
|
||
categoryType: String, // 后端返回的 type: "hot_recommend" / "hot_star_card" / "hot_badge" / "hot_poster"
|
||
title: String // 后端返回的标题: "热门推荐"
|
||
}
|
||
```
|
||
|
||
**状态**:
|
||
- `items: Array` — 作品列表
|
||
- `loading: Boolean` — 首次加载中(显示骨架屏)
|
||
- `refreshing: Boolean` — 刷新中(按钮旋转动画)
|
||
- `hasMore: Boolean` — 是否有更多可加载
|
||
|
||
**事件**:
|
||
- `cardClick(item)` — 点击卡片,跳转详情
|
||
|
||
---
|
||
|
||
## 三、样式规范
|
||
|
||
### 3.1 布局
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| 区块间距 | 上下 `32rpx`,左右 `24rpx` |
|
||
| 网格 | 4列 × 2行,间距 `16rpx` |
|
||
| 卡片宽 | `=(屏宽 - 48rpx - 48rpx) / 4` |
|
||
| 卡片高 | `卡片宽 × 1.3` |
|
||
| 圆角 | `16rpx` |
|
||
|
||
### 3.2 卡片样式
|
||
|
||
```css
|
||
.hot-card {
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
position: relative;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
backdrop-filter: blur(10rpx);
|
||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
.hot-card-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
}
|
||
|
||
/* 底部渐变遮罩 */
|
||
.hot-card-overlay {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 64rpx;
|
||
background: linear-gradient(to top, rgba(0,0,0,0.6), transparent);
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
padding: 0 12rpx 12rpx;
|
||
}
|
||
|
||
.hot-card-user {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
border-radius: 50%;
|
||
margin-right: 6rpx;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 20rpx;
|
||
color: #fff;
|
||
max-width: 120rpx;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.hot-card-likes {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.like-icon {
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
margin-right: 4rpx;
|
||
}
|
||
|
||
.like-count {
|
||
font-size: 20rpx;
|
||
color: #fff;
|
||
}
|
||
```
|
||
|
||
### 3.3 标题栏样式
|
||
|
||
```css
|
||
.block-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
padding: 0 24rpx 16rpx;
|
||
}
|
||
```
|
||
|
||
### 3.4 操作按钮样式
|
||
|
||
```css
|
||
.block-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
padding: 16rpx 24rpx 0;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.refresh-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.refresh-btn .action-icon {
|
||
font-size: 28rpx;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
}
|
||
|
||
.refresh-btn.spinning .action-icon {
|
||
animation: spin 0.8s linear;
|
||
}
|
||
|
||
@keyframes spin {
|
||
from { transform: rotate(0deg); }
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
.more-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.more-text {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
}
|
||
|
||
.more-arrow {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
margin-left: 4rpx;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、状态处理
|
||
|
||
| 状态 | 表现 |
|
||
|------|------|
|
||
| `loading=true` | 显示 8 个骨架屏卡片,操作按钮禁用 |
|
||
| `loading=false && items.length=0` | 空状态提示:「暂无{{title}}作品」 |
|
||
| `loading=false && items.length>0` | 正常显示 8 张卡片 |
|
||
| `refreshing=true` | 刷新按钮旋转动画,卡片 fade-out |
|
||
| `refreshing=false` | 刷新完成,卡片 fade-in |
|
||
|
||
---
|
||
|
||
## 五、骨架屏样式
|
||
|
||
```css
|
||
.skeleton-card {
|
||
border-radius: 16rpx;
|
||
background: #3a3a4a;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
|
||
.skeleton-shimmer {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(
|
||
90deg,
|
||
transparent 0%,
|
||
rgba(255, 255, 255, 0.1) 50%,
|
||
transparent 100%
|
||
);
|
||
animation: shimmer 1.5s infinite;
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
0% { transform: translateX(-100%); }
|
||
100% { transform: translateX(100%); }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、完整组件模板
|
||
|
||
```vue
|
||
<template>
|
||
<view class="hot-category-block">
|
||
<!-- 标题 -->
|
||
<text class="block-title">{{ title }}</text>
|
||
|
||
<!-- 网格区域 -->
|
||
<view v-if="loading" class="block-grid">
|
||
<view v-for="i in 8" :key="i" class="skeleton-card">
|
||
<view class="skeleton-shimmer"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else-if="items.length === 0" class="empty-state">
|
||
<text class="empty-text">暂无{{ title }}作品</text>
|
||
</view>
|
||
|
||
<view v-else class="block-grid">
|
||
<view
|
||
v-for="(item, index) in items"
|
||
:key="item.asset_id || index"
|
||
class="hot-card"
|
||
@click="handleCardClick(item)"
|
||
>
|
||
<image class="hot-card-image" :src="item.cover_url" mode="aspectFill" />
|
||
<view class="hot-card-overlay">
|
||
<view class="hot-card-user">
|
||
<image class="user-avatar" :src="item.owner_avatar" mode="aspectFill" />
|
||
<text class="user-name">{{ item.owner_nickname }}</text>
|
||
</view>
|
||
<view class="hot-card-likes">
|
||
<image class="like-icon" src="/static/icon/heart-icon.png" mode="aspectFit" />
|
||
<text class="like-count">{{ formatCount(item.likes) }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 操作按钮 -->
|
||
<view class="block-actions">
|
||
<view class="refresh-btn" :class="{ spinning: refreshing }" @click="handleRefresh">
|
||
<text class="action-icon">↻</text>
|
||
</view>
|
||
<view class="more-btn" @click="handleViewMore">
|
||
<text class="more-text">查看更多</text>
|
||
<text class="more-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
```
|
||
|
||
---
|
||
|
||
## 七、API 调用
|
||
|
||
```javascript
|
||
// 单个分类刷新
|
||
export function getHotInspirationFlowApi(type) {
|
||
return request({
|
||
url: '/api/v1/inspiration-flow/hot',
|
||
method: 'GET',
|
||
data: { type }
|
||
})
|
||
}
|
||
|
||
// 查看更多分页
|
||
export function getHotInspirationFlowMoreApi(type, cursor = '', limit = 20) {
|
||
return request({
|
||
url: '/api/v1/inspiration-flow/hot/more',
|
||
method: 'GET',
|
||
data: { type, cursor, limit }
|
||
})
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 八、hot-category-more.vue 页面
|
||
|
||
**路由参数**:
|
||
- `type` — 分类类型
|
||
- `title` — 标题(URL 编码)
|
||
|
||
**页面结构**:
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ ← 返回 热门星卡 │
|
||
├──────────────────────────────────────┤
|
||
│ [全部] [光栅卡] [镭射卡] [撕拉卡] [拍立得] │ ← 仅星卡显示
|
||
├──────────────────────────────────────┤
|
||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
|
||
│ │ │ │ │ │ │ │ │ │
|
||
│ └────┘ └────┘ └────┘ └────┘ │
|
||
│ ... │
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
**星卡子标签**(仅 `hot_star_card` 显示):
|
||
|
||
| 子标签 | value | 说明 |
|
||
|-------|-------|------|
|
||
| 全部 | `all` | 全部星卡 |
|
||
| 光栅卡 | `raster` | 光栅卡类型 |
|
||
| 镭射卡 | `holographic` | 镭射卡类型 |
|
||
| 撕拉卡 | `tear_off` | 撕拉卡类型 |
|
||
| 拍立得 | `polaroid` | 拍立得类型 | |