feat: ui update
This commit is contained in:
@@ -1,26 +1,49 @@
|
||||
import { request, redirectToLogin } from '../../utils/request'
|
||||
import * as auth from '../../utils/auth'
|
||||
import { PagedResult, OutfitItem } from '../../types/models'
|
||||
import { PagedResult, OutfitItem, CommunityOutfitItem } from '../../types/models'
|
||||
import { OutfitSource, IsPublic, STORAGE_KEYS } from '../../utils/config'
|
||||
import { normalizePaged, mergePaged, hasMorePaged } from '../../utils/paged'
|
||||
import { setTabBarSelected } from '../../utils/tabbar'
|
||||
import { formatRelativeTime } from '../../utils/format'
|
||||
import { navScroll } from '../../utils/nav'
|
||||
import { logger } from '../../utils/logger'
|
||||
|
||||
// 日志模块名
|
||||
const LOG = 'outfit'
|
||||
|
||||
// 拼图封面单元:无图时前端渲染线稿占位
|
||||
type CoverCell = { k: string; img: string }
|
||||
|
||||
// 列表行:我的穿搭/已收藏来自 OutfitItem;社区来自 CommunityOutfitItem(额外带作者与互动计数)。
|
||||
// 统一为交叉类型,模板按 activeTab 条件渲染差异字段。
|
||||
type OutfitRow = OutfitItem & Partial<CommunityOutfitItem> & {
|
||||
_likeCount?: number
|
||||
_collectCount?: number
|
||||
// cls 为胶囊类名(零彩色:pill--ink / pill--line / 空)
|
||||
_status?: { text: string; cls: string }
|
||||
_time?: string
|
||||
_covers?: CoverCell[]
|
||||
_collageCls?: string
|
||||
_moreCount?: number
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
activeTab: 0,
|
||||
list: [] as OutfitItem[],
|
||||
list: [] as OutfitRow[],
|
||||
loading: true,
|
||||
refreshing: false,
|
||||
loadingMore: false,
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
hasMore: true,
|
||||
// 滚动收缩:由 utils/nav.ts 的共享 handler 驱动
|
||||
navScrolled: false,
|
||||
},
|
||||
|
||||
// scroll-view 滚动 → 导航收缩为玻璃小标题
|
||||
onNavScroll: navScroll,
|
||||
|
||||
onShow() {
|
||||
this.syncTabBar()
|
||||
// 未登录直接回登录页(幂等跳转),不再发出必然 401 的请求
|
||||
@@ -73,16 +96,16 @@ Page({
|
||||
},
|
||||
|
||||
fetchList(page: number): Promise<void> {
|
||||
const isCollect = this.data.activeTab === 1
|
||||
const url = isCollect ? '/collect' : '/outfit'
|
||||
const tab = this.data.activeTab
|
||||
const url = tab === 1 ? '/collect' : tab === 2 ? '/outfit/community' : '/outfit'
|
||||
|
||||
const seq = ((this as any).reqSeq || 0) + 1
|
||||
;(this as any).reqSeq = seq
|
||||
if (page > 1) this.setData({ loadingMore: true })
|
||||
|
||||
return request<PagedResult<OutfitItem>>({ url, data: { page, page_size: this.data.pageSize } })
|
||||
return request<PagedResult<OutfitRow>>({ url, data: { page, page_size: this.data.pageSize } })
|
||||
.then(async (res) => {
|
||||
const { list: raw, total } = normalizePaged<OutfitItem>(res)
|
||||
const { list: raw, total } = normalizePaged<OutfitRow>(res)
|
||||
logger.debug(LOG, '列表加载成功, url=', url, 'page=', page, '条数=', raw && raw.length)
|
||||
const items = await this.decorateList(raw)
|
||||
// decorateList 是异步的,期间可能已切换 tab:序号不匹配则丢弃
|
||||
@@ -103,7 +126,18 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
decorateList(list: OutfitItem[]): Promise<OutfitItem[]> {
|
||||
decorateList(list: OutfitRow[]): Promise<OutfitRow[]> {
|
||||
// 社区分段:作者与互动计数由后端一次性下发,本地仅补相对时间,避免逐条请求点赞接口
|
||||
if (this.data.activeTab === 2) {
|
||||
return Promise.resolve(
|
||||
list.map((it) => ({
|
||||
...it,
|
||||
_likeCount: it.like_count || 0,
|
||||
_collectCount: it.collect_count || 0,
|
||||
_time: formatRelativeTime(it.created_at),
|
||||
})),
|
||||
)
|
||||
}
|
||||
return Promise.all(
|
||||
list.map(async (it) => {
|
||||
let likeCount = 0
|
||||
@@ -116,15 +150,31 @@ Page({
|
||||
} catch (e: any) {
|
||||
logger.warn(LOG, '点赞数拉取失败, uuid=', it.outfit_uuid, 'code=', e && e.code)
|
||||
}
|
||||
return { ...it, _likeCount: likeCount, _status: this.getStatusText(it) }
|
||||
return { ...it, ...this.decorateCover(it), _likeCount: likeCount, _status: this.getStatusText(it) }
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
getStatusText(it: OutfitItem): { text: string; type: string } {
|
||||
if (it.source === OutfitSource.AI) return { text: 'AI 推荐', type: 'indigo' }
|
||||
if (it.is_public === IsPublic.PUBLIC) return { text: '已公开', type: 'blue' }
|
||||
return { text: '仅自己可见', type: 'gray' }
|
||||
// 无缝拼图封面:取前 4 件,超出用 +N 角标;不足 1 件时补一个线稿占位格
|
||||
decorateCover(it: OutfitItem): { _covers: CoverCell[]; _collageCls: string; _moreCount: number } {
|
||||
const items = it.items || []
|
||||
const covers: CoverCell[] = items.slice(0, 4).map((c) => ({
|
||||
k: c.clothes_uuid,
|
||||
img: c.processed_image || '',
|
||||
}))
|
||||
if (!covers.length) covers.push({ k: 'empty', img: '' })
|
||||
return {
|
||||
_covers: covers,
|
||||
_collageCls: `collage--${covers.length}`,
|
||||
_moreCount: Math.max(items.length - 4, 0),
|
||||
}
|
||||
},
|
||||
|
||||
// 零彩色状态语义:AI 来源 = 黑底白字,已公开 = 描边,仅自己可见 = 浅灰
|
||||
getStatusText(it: OutfitItem): { text: string; cls: string } {
|
||||
if (it.source === OutfitSource.AI) return { text: 'AI 推荐', cls: 'pill--ink' }
|
||||
if (it.is_public === IsPublic.PUBLIC) return { text: '已公开', cls: 'pill--line' }
|
||||
return { text: '仅自己可见', cls: '' }
|
||||
},
|
||||
|
||||
onCreate() {
|
||||
|
||||
@@ -1,84 +1,106 @@
|
||||
<view class="page page-flex">
|
||||
<navigation-bar title="穿搭" back="{{false}}" />
|
||||
<navigation-bar title="穿搭" back="{{false}}" scrolled="{{navScrolled}}" />
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="scroll-body"
|
||||
class="scroll-body pb-float"
|
||||
refresher-enabled
|
||||
refresher-triggered="{{refreshing}}"
|
||||
bindrefresherrefresh="onRefresh"
|
||||
bindscrolltolower="onReachBottom"
|
||||
bindscroll="onNavScroll"
|
||||
>
|
||||
<!-- 分段控件 -->
|
||||
<view class="topbar">
|
||||
<view class="segment">
|
||||
<view class="segment-item {{activeTab === 0 ? 'active' : ''}}" data-index="0" bindtap="onTabChange">我的穿搭</view>
|
||||
<view class="segment-item {{activeTab === 1 ? 'active' : ''}}" data-index="1" bindtap="onTabChange">已收藏</view>
|
||||
<!-- 大标题页头 -->
|
||||
<view class="head">
|
||||
<view class="eyebrow">Styling</view>
|
||||
<view class="display">穿搭</view>
|
||||
</view>
|
||||
|
||||
<!-- 下划线式文字分段 -->
|
||||
<view class="segbar">
|
||||
<view class="seg">
|
||||
<view class="seg-item {{activeTab === 0 ? 'is-on' : ''}}" data-index="0" bindtap="onTabChange">我的穿搭</view>
|
||||
<view class="seg-item {{activeTab === 1 ? 'is-on' : ''}}" data-index="1" bindtap="onTabChange">已收藏</view>
|
||||
<view class="seg-item {{activeTab === 2 ? 'is-on' : ''}}" data-index="2" bindtap="onTabChange">社区</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 入口按钮 -->
|
||||
<view class="entry-row">
|
||||
<view class="entry-btn entry-outline" bindtap="onCreate">+ 创建穿搭</view>
|
||||
<view class="entry-btn entry-primary" bindtap="onAiRecommend">AI 推荐</view>
|
||||
</view>
|
||||
|
||||
<!-- 骨架屏 -->
|
||||
<view wx:if="{{loading}}" class="list">
|
||||
<view class="skeleton sk-card" wx:for="{{[1, 2, 3]}}" wx:key="*this"></view>
|
||||
<view wx:if="{{loading}}" class="of-skel">
|
||||
<view class="of-skel-item" wx:for="{{[1, 2]}}" wx:key="*this">
|
||||
<view class="sk sk-img sk-cover"></view>
|
||||
<view class="sk sk-ln" style="width: 44%;"></view>
|
||||
<view class="sk sk-ln" style="width: 72%;"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空态 -->
|
||||
<empty-state
|
||||
wx:elif="{{!list.length}}"
|
||||
icon="icon-shirt"
|
||||
title="{{activeTab === 0 ? '还没有穿搭' : '还没有收藏的穿搭'}}"
|
||||
desc="{{activeTab === 0 ? '从衣橱挑几件,搭一套吧' : ''}}"
|
||||
title="{{activeTab === 0 ? '还没有穿搭' : activeTab === 1 ? '还没有收藏的穿搭' : '还没有公开的穿搭'}}"
|
||||
desc="{{activeTab === 0 ? '从衣橱挑几件,搭一套吧' : activeTab === 1 ? '在社区或 AI 推荐中点亮小星星,喜欢的穿搭会出现在这里' : '把喜欢的穿搭公开到社区,让大家看到你的搭配'}}"
|
||||
buttonText="{{activeTab === 0 ? '创建穿搭' : ''}}"
|
||||
bind:action="onCreate"
|
||||
/>
|
||||
|
||||
<!-- 卡片流 -->
|
||||
<view wx:else class="list">
|
||||
<view wx:else class="of-list">
|
||||
<view
|
||||
class="outfit-card card"
|
||||
class="of-card"
|
||||
wx:for="{{list}}"
|
||||
wx:key="outfit_uuid"
|
||||
data-uuid="{{item.outfit_uuid}}"
|
||||
bindtap="onOutfitTap"
|
||||
>
|
||||
<view class="cover">
|
||||
<view
|
||||
class="cover-item cover-{{index}}"
|
||||
wx:for="{{item.items}}"
|
||||
wx:key="clothes_uuid"
|
||||
wx:if="{{index < 5}}"
|
||||
>
|
||||
<image wx:if="{{item.processed_image}}" class="cover-img" src="{{item.processed_image}}" mode="aspectFit" />
|
||||
<view wx:else class="icon icon-hanger cover-ph"></view>
|
||||
<!-- 作者行:仅社区分段 -->
|
||||
<view class="of-author" wx:if="{{activeTab === 2}}">
|
||||
<image wx:if="{{item.owner_avatar}}" class="of-av" src="{{item.owner_avatar}}" mode="aspectFill" />
|
||||
<view wx:else class="of-av">
|
||||
<view class="icon icon-user"></view>
|
||||
</view>
|
||||
<view wx:if="{{!item.items.length}}" class="icon icon-hanger"></view>
|
||||
<text class="cover-count">{{item.items.length}} 件</text>
|
||||
<text class="of-aname">{{item.owner_name || '穿搭达人'}}</text>
|
||||
<text class="of-atime">{{item._time}}</text>
|
||||
</view>
|
||||
<view class="card-body">
|
||||
<view class="title-row">
|
||||
<text class="title">{{item.outfit_name}}</text>
|
||||
<text class="tag tag-{{item._status.type}}">{{item._status.text}}</text>
|
||||
|
||||
<!-- 无缝拼图封面 -->
|
||||
<view class="collage {{item._collageCls}}">
|
||||
<view class="cg" wx:for="{{item._covers}}" wx:for-item="c" wx:key="k">
|
||||
<image wx:if="{{c.img}}" class="pic" src="{{c.img}}" mode="aspectFill" lazy-load />
|
||||
<view wx:else class="ph icon icon-hanger"></view>
|
||||
</view>
|
||||
<view class="desc" wx:if="{{item.outfit_desc}}">{{item.outfit_desc}}</view>
|
||||
<view class="meta-row">
|
||||
<text class="tag tag-gray" wx:if="{{item.scene}}">{{item.scene}}</text>
|
||||
<text class="meta">{{item.items.length}} 件衣物</text>
|
||||
<view class="spacer"></view>
|
||||
<view class="meta-icon">
|
||||
<view class="icon icon-heart heart"></view>
|
||||
<text>{{item._likeCount || 0}}</text>
|
||||
</view>
|
||||
<view wx:if="{{item._moreCount > 0}}" class="cg-more">+{{item._moreCount}}</view>
|
||||
<text class="cg-badge num">{{item.items.length}} 件</text>
|
||||
</view>
|
||||
|
||||
<view class="of-trow">
|
||||
<text class="of-title">{{item.outfit_name}}</text>
|
||||
<text wx:if="{{activeTab !== 2}}" class="pill {{item._status.cls}}">{{item._status.text}}</text>
|
||||
</view>
|
||||
<view class="of-desc" wx:if="{{item.outfit_desc}}">{{item.outfit_desc}}</view>
|
||||
<view class="of-meta">
|
||||
<text class="pill pill--line" wx:if="{{item.scene}}">{{item.scene}}</text>
|
||||
<text class="of-m">{{item.items.length}} 件衣物</text>
|
||||
<view class="spacer"></view>
|
||||
<view class="of-m">
|
||||
<view class="icon icon-heart"></view>
|
||||
<text class="num">{{item._likeCount || 0}}</text>
|
||||
</view>
|
||||
<view class="of-m" wx:if="{{activeTab === 2}}">
|
||||
<view class="icon icon-star"></view>
|
||||
<text class="num">{{item._collectCount || 0}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{list.length && !hasMore}}" class="no-more">没有更多了</view>
|
||||
<view wx:if="{{list.length && !hasMore}}" class="foot-note">没有更多了</view>
|
||||
<view class="gap-64"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 悬浮玻璃双按钮条(社区为浏览场景,不展示管理入口) -->
|
||||
<view class="float-duo" wx:if="{{activeTab !== 2}}">
|
||||
<view class="btn btn--glass" bindtap="onCreate">创建穿搭</view>
|
||||
<view class="btn btn--ink" bindtap="onAiRecommend">AI 推荐</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** 穿搭:下划线分段 + 无缝拼图卡 + 悬浮双按钮条 **/
|
||||
.page-flex {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
@@ -10,199 +11,137 @@
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
background: #fff;
|
||||
padding: 20rpx 32rpx;
|
||||
/* 分段条:吸顶玻璃 */
|
||||
.segbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
margin-top: 36rpx;
|
||||
background: var(--glass);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
border-bottom: 1rpx solid var(--hairline);
|
||||
}
|
||||
|
||||
.segment {
|
||||
.of-list {
|
||||
padding: 40rpx var(--pad) 0;
|
||||
display: flex;
|
||||
background: #F2F2F7;
|
||||
border-radius: 20rpx;
|
||||
padding: 6rpx;
|
||||
flex-direction: column;
|
||||
gap: 56rpx;
|
||||
}
|
||||
|
||||
.segment-item {
|
||||
flex: 1;
|
||||
height: 64rpx;
|
||||
line-height: 64rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #3C3C43;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.segment-item.active {
|
||||
background: #fff;
|
||||
color: #007AFF;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.entry-row {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
padding: 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.entry-btn {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
border-radius: 36rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.entry-outline {
|
||||
border: 1rpx solid #007AFF;
|
||||
color: #007AFF;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.entry-primary {
|
||||
background: #007AFF;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.sk-card {
|
||||
height: 360rpx;
|
||||
border-radius: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.outfit-card {
|
||||
margin-bottom: 24rpx;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.cover {
|
||||
height: 280rpx;
|
||||
background: #F8F8FA;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #C7C7CC;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cover .icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
}
|
||||
|
||||
.cover-item {
|
||||
position: absolute;
|
||||
width: 150rpx;
|
||||
height: 190rpx;
|
||||
background: #fff;
|
||||
border: 1rpx solid #E5E5EA;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cover-0 { left: 16rpx; top: 40rpx; transform: rotate(-6deg); }
|
||||
.cover-1 { left: 140rpx; top: 82rpx; transform: rotate(3deg); }
|
||||
.cover-2 { left: 268rpx; top: 32rpx; transform: rotate(5deg); }
|
||||
.cover-3 { left: 392rpx; top: 84rpx; transform: rotate(-3deg); }
|
||||
.cover-4 { left: 480rpx; top: 40rpx; transform: rotate(6deg); }
|
||||
|
||||
.cover-img {
|
||||
.of-card {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.cover-ph {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
color: #C7C7CC;
|
||||
.of-card:active {
|
||||
transform: scale(.985);
|
||||
}
|
||||
|
||||
.cover-count {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
font-size: 22rpx;
|
||||
color: #007AFF;
|
||||
background: rgba(0, 122, 255, 0.1);
|
||||
padding: 4rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
.of-skel {
|
||||
padding: 40rpx var(--pad) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 56rpx;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
margin-top: 20rpx;
|
||||
.of-skel-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.title-row {
|
||||
.sk-cover {
|
||||
aspect-ratio: 4 / 3;
|
||||
}
|
||||
|
||||
/* 作者行(仅社区分段) */
|
||||
.of-author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
.of-av {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
background: var(--paper-3);
|
||||
color: var(--ink-3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.of-av .icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
}
|
||||
|
||||
.of-aname {
|
||||
font-size: 25rpx;
|
||||
letter-spacing: .01em;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.of-atime {
|
||||
margin-left: auto;
|
||||
font-size: 22rpx;
|
||||
color: var(--ink-3);
|
||||
}
|
||||
|
||||
.of-trow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.of-title {
|
||||
font-family: var(--serif);
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.35;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 26rpx;
|
||||
color: #8E8E93;
|
||||
margin-top: 12rpx;
|
||||
.of-desc {
|
||||
margin-top: 14rpx;
|
||||
font-size: 25rpx;
|
||||
line-height: 1.62;
|
||||
color: var(--ink-2);
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.meta-row {
|
||||
.of-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 16rpx;
|
||||
gap: 22rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.meta {
|
||||
font-size: 22rpx;
|
||||
color: #8E8E93;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.meta-icon {
|
||||
display: flex;
|
||||
.of-m {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
font-size: 22rpx;
|
||||
color: #8E8E93;
|
||||
color: var(--ink-3);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.heart {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
color: #C7C7CC;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.no-more {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #C7C7CC;
|
||||
padding: 24rpx 0 40rpx;
|
||||
.of-m .icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user