Initial commit
This commit is contained in:
6
miniprogram/pages/profile/profile.json
Normal file
6
miniprogram/pages/profile/profile.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"navigationStyle": "custom",
|
||||
"usingComponents": {
|
||||
"post-card": "/components/post-card/post-card"
|
||||
}
|
||||
}
|
||||
167
miniprogram/pages/profile/profile.ts
Normal file
167
miniprogram/pages/profile/profile.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { Post } from '../../types/index'
|
||||
import { api } from '../../utils/api'
|
||||
import { getAvatarGradient, getPetEmoji, formatCount } from '../../utils/format'
|
||||
|
||||
const app = getApp<{ userInfo: any; isLoggedIn: boolean }>()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 0,
|
||||
tabBarHeight: 56,
|
||||
userInfo: {
|
||||
nickName: '',
|
||||
handle: '',
|
||||
bio: '',
|
||||
location: '',
|
||||
stats: { posts: 0, friends: 0, likes: 0 },
|
||||
pets: [],
|
||||
} as any,
|
||||
formattedLikes: '0',
|
||||
avatarGradient: 'linear-gradient(135deg, #ffd6e8, #fff1a6)',
|
||||
posts: [] as Post[],
|
||||
postView: 'grid' as 'grid' | 'list',
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
const info = wx.getSystemInfoSync()
|
||||
this.setData({ statusBarHeight: info.statusBarHeight })
|
||||
this.loadProfile()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
const tabBar = this.getTabBar() as any
|
||||
tabBar?.setSelected?.(3)
|
||||
this.syncFromGlobal()
|
||||
},
|
||||
|
||||
syncFromGlobal() {
|
||||
const user = app.globalData?.userInfo
|
||||
if (!user) {
|
||||
wx.redirectTo({ url: '/pages/login/login' })
|
||||
return
|
||||
}
|
||||
const pets = (user.pets || []).map((p: any) => ({
|
||||
...p,
|
||||
emoji: getPetEmoji(p.species, p.breed),
|
||||
gradient: getAvatarGradient(p._id),
|
||||
}))
|
||||
this.setData({
|
||||
userInfo: { ...user, pets },
|
||||
formattedLikes: formatCount(user.stats?.likes || 0),
|
||||
avatarGradient: getAvatarGradient(user.openid || user._id || ''),
|
||||
})
|
||||
},
|
||||
|
||||
async loadProfile() {
|
||||
this.setData({ loading: true })
|
||||
try {
|
||||
const [_user, postsRes] = await Promise.all([
|
||||
api.getUserProfile(app.globalData?.userInfo?._id || '').catch(() => null),
|
||||
api.getUserPosts(app.globalData?.userInfo?._id || '').catch(() => ({ list: [], total: 0 })),
|
||||
])
|
||||
if (_user) {
|
||||
app.globalData.userInfo = _user
|
||||
this.syncFromGlobal()
|
||||
}
|
||||
this.setData({ posts: postsRes.list })
|
||||
} catch {
|
||||
} finally {
|
||||
this.setData({ loading: false, refreshing: false })
|
||||
}
|
||||
},
|
||||
|
||||
setPostView(e: WechatMiniprogram.CustomEvent) {
|
||||
this.setData({ postView: e.currentTarget.dataset.v as 'grid' | 'list' })
|
||||
},
|
||||
|
||||
onStatTap(e: WechatMiniprogram.CustomEvent) {
|
||||
const type = e.currentTarget.dataset.type
|
||||
if (type === 'following') {
|
||||
wx.switchTab({ url: '/pages/friends/friends' })
|
||||
}
|
||||
},
|
||||
|
||||
onGridItemTap(e: WechatMiniprogram.CustomEvent) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
wx.navigateTo({ url: `/pages/post-detail/post-detail?id=${id}` })
|
||||
},
|
||||
|
||||
onPetTap(e: WechatMiniprogram.CustomEvent) {
|
||||
const pid = e.currentTarget.dataset.pid
|
||||
wx.navigateTo({ url: `/pages/pet-edit/pet-edit?id=${pid}` })
|
||||
},
|
||||
|
||||
onAddPet() {
|
||||
wx.navigateTo({ url: '/pages/pet-edit/pet-edit' })
|
||||
},
|
||||
|
||||
onEditProfile() {
|
||||
wx.navigateTo({ url: '/pages/edit-profile/edit-profile' })
|
||||
},
|
||||
|
||||
onEditAvatar() {
|
||||
wx.showActionSheet({
|
||||
itemList: ['从相册选取', '拍照'],
|
||||
success: res => {
|
||||
wx.chooseMedia({
|
||||
count: 1,
|
||||
mediaType: ['image'],
|
||||
sourceType: [res.tapIndex === 0 ? 'album' : 'camera'],
|
||||
success: async mediaRes => {
|
||||
const path = mediaRes.tempFiles[0].tempFilePath
|
||||
const cloudPath = `avatars/${app.globalData.userInfo?._id || Date.now()}.jpg`
|
||||
wx.showLoading({ title: '上传中...' })
|
||||
try {
|
||||
const r = await wx.cloud.uploadFile({ cloudPath, filePath: path })
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '头像已更新', icon: 'success' })
|
||||
} catch {
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '上传失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
onSettings() {
|
||||
wx.showActionSheet({
|
||||
itemList: ['账号设置', '隐私设置', '退出登录'],
|
||||
success: res => {
|
||||
if (res.tapIndex === 2) {
|
||||
wx.showModal({
|
||||
title: '退出登录',
|
||||
content: '确定要退出汪圈吗?',
|
||||
success: modal => {
|
||||
if (modal.confirm) {
|
||||
wx.clearStorageSync()
|
||||
app.globalData.userInfo = null
|
||||
app.globalData.isLoggedIn = false
|
||||
wx.redirectTo({ url: '/pages/login/login' })
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
onGoPost() {
|
||||
wx.navigateTo({ url: '/pages/post/post' })
|
||||
},
|
||||
|
||||
async onRefresh() {
|
||||
this.setData({ refreshing: true })
|
||||
await this.loadProfile()
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: `${this.data.userInfo.nickName}的汪圈主页`,
|
||||
path: `/pages/pet-detail/pet-detail?userId=${app.globalData?.userInfo?._id}`,
|
||||
}
|
||||
},
|
||||
})
|
||||
148
miniprogram/pages/profile/profile.wxml
Normal file
148
miniprogram/pages/profile/profile.wxml
Normal file
@@ -0,0 +1,148 @@
|
||||
<view class="profile-page">
|
||||
<view class="safe-top" style="height: {{statusBarHeight}}px"></view>
|
||||
|
||||
<scroll-view
|
||||
scroll-y="true"
|
||||
class="profile-scroll"
|
||||
enhanced="true"
|
||||
show-scrollbar="false"
|
||||
refresher-enabled="true"
|
||||
bindrefresherrefresh="onRefresh"
|
||||
refresher-triggered="{{refreshing}}"
|
||||
>
|
||||
<!-- 用户信息区 -->
|
||||
<view class="profile-header">
|
||||
<!-- 头部操作栏 -->
|
||||
<view class="header-topbar">
|
||||
<view class="settings-btn" bindtap="onSettings">⚙️</view>
|
||||
</view>
|
||||
|
||||
<!-- 头像 + 基本信息 -->
|
||||
<view class="user-top">
|
||||
<view class="user-avatar-wrap">
|
||||
<view class="user-avatar" style="background: {{avatarGradient}}">
|
||||
<text class="avatar-text">{{userInfo.nickName[0] || '?'}}</text>
|
||||
</view>
|
||||
<view class="avatar-edit" bindtap="onEditAvatar">✏️</view>
|
||||
</view>
|
||||
<view class="user-meta">
|
||||
<view class="user-name-row">
|
||||
<text class="user-name">{{userInfo.nickName}}</text>
|
||||
</view>
|
||||
<text class="user-handle">{{userInfo.handle || '@' + userInfo.openid.slice(0,8)}} · {{userInfo.location || '上海'}}</text>
|
||||
<text class="user-bio">{{userInfo.bio || '还没有介绍~'}}</text>
|
||||
</view>
|
||||
<view class="edit-profile-btn" bindtap="onEditProfile">编辑</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<view class="stats-row">
|
||||
<view class="stat-item" bindtap="onStatTap" data-type="posts">
|
||||
<text class="stat-num">{{userInfo.stats.posts || 0}}</text>
|
||||
<text class="stat-label">动态</text>
|
||||
</view>
|
||||
<view class="stat-divider"></view>
|
||||
<view class="stat-item" bindtap="onStatTap" data-type="following">
|
||||
<text class="stat-num">{{userInfo.stats.friends || 0}}</text>
|
||||
<text class="stat-label">汪友</text>
|
||||
</view>
|
||||
<view class="stat-divider"></view>
|
||||
<view class="stat-item" bindtap="onStatTap" data-type="likes">
|
||||
<text class="stat-num">{{formattedLikes}}</text>
|
||||
<text class="stat-label">获赞</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 宠物档案卡 -->
|
||||
<view class="section-wrap">
|
||||
<view class="section-header">
|
||||
<text class="section-title">我的宝贝</text>
|
||||
<view class="add-pet-btn" bindtap="onAddPet">+ 添加</view>
|
||||
</view>
|
||||
|
||||
<!-- 宠物卡片横滑 -->
|
||||
<scroll-view scroll-x="true" enhanced="true" show-scrollbar="false" class="pets-scroll">
|
||||
<view
|
||||
wx:for="{{userInfo.pets}}"
|
||||
wx:key="_id"
|
||||
class="pet-card"
|
||||
bindtap="onPetTap"
|
||||
data-pid="{{item._id}}"
|
||||
>
|
||||
<view class="pet-avatar" style="background: {{item.gradient || 'linear-gradient(135deg, #c9f7df, #d9d2ff)'}}">
|
||||
<text class="pet-emoji">{{item.emoji || '🐾'}}</text>
|
||||
</view>
|
||||
<view class="pet-info">
|
||||
<text class="pet-name">{{item.name}}</text>
|
||||
<text class="pet-breed">{{item.breed}} · {{item.gender === 'female' ? '女生' : '男生'}} · {{item.age}}</text>
|
||||
</view>
|
||||
<view class="pet-badge">我的宝贝</view>
|
||||
</view>
|
||||
|
||||
<!-- 空态时添加宠物 -->
|
||||
<view wx:if="{{userInfo.pets.length === 0}}" class="pet-card pet-card-empty" bindtap="onAddPet">
|
||||
<view class="pet-avatar pet-avatar-add">
|
||||
<text style="font-size: 48rpx;">+</text>
|
||||
</view>
|
||||
<view class="pet-info">
|
||||
<text class="pet-name">添加宠物</text>
|
||||
<text class="pet-breed">建立您的宠物档案</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 动态网格 / 列表切换 -->
|
||||
<view class="section-wrap">
|
||||
<view class="section-header">
|
||||
<text class="section-title">全部动态</text>
|
||||
<view class="view-toggle">
|
||||
<view class="toggle-item {{postView === 'grid' ? 'active' : ''}}" bindtap="setPostView" data-v="grid">▦</view>
|
||||
<view class="toggle-item {{postView === 'list' ? 'active' : ''}}" bindtap="setPostView" data-v="list">☰</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 网格视图 -->
|
||||
<view wx:if="{{postView === 'grid'}}" class="post-grid">
|
||||
<view
|
||||
wx:for="{{posts}}"
|
||||
wx:key="_id"
|
||||
class="grid-item"
|
||||
bindtap="onGridItemTap"
|
||||
data-id="{{item._id}}"
|
||||
>
|
||||
<image
|
||||
wx:if="{{item.images && item.images.length > 0}}"
|
||||
class="grid-img"
|
||||
src="{{item.images[0]}}"
|
||||
mode="aspectFill"
|
||||
lazy-load="true"
|
||||
/>
|
||||
<view wx:else class="grid-no-img">
|
||||
<text>{{item.content.slice(0, 20)}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空态 -->
|
||||
<view wx:if="{{posts.length === 0}}" class="grid-empty">
|
||||
<text class="empty-emoji">📸</text>
|
||||
<text class="empty-tip">还没有动态,去发一条吧</text>
|
||||
<view class="btn-primary post-btn" bindtap="onGoPost">发动态</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表视图 -->
|
||||
<view wx:else>
|
||||
<post-card
|
||||
wx:for="{{posts}}"
|
||||
wx:key="_id"
|
||||
post="{{item}}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="height: {{tabBarHeight}}px"></view>
|
||||
<view class="safe-bottom"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
310
miniprogram/pages/profile/profile.wxss
Normal file
310
miniprogram/pages/profile/profile.wxss
Normal file
@@ -0,0 +1,310 @@
|
||||
.profile-page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #fff8f2 0%, #fff4fb 50%, #f5f0ff 100%);
|
||||
}
|
||||
|
||||
.profile-scroll { min-height: 100vh; }
|
||||
|
||||
/* 用户信息区 */
|
||||
.profile-header {
|
||||
padding: 0 28rpx 28rpx;
|
||||
background: linear-gradient(180deg, rgba(255, 225, 90, 0.18), transparent);
|
||||
}
|
||||
|
||||
.header-topbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 16rpx 0 12rpx;
|
||||
}
|
||||
|
||||
.settings-btn {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
box-shadow: 0 8rpx 18rpx rgba(78, 56, 96, 0.10);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.user-top {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 24rpx;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.user-avatar-wrap {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
border-radius: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 12rpx 24rpx rgba(98, 60, 118, 0.18);
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
font-size: 56rpx;
|
||||
font-weight: 800;
|
||||
color: rgba(39, 34, 53, 0.72);
|
||||
}
|
||||
|
||||
.avatar-edit {
|
||||
position: absolute;
|
||||
bottom: -6rpx;
|
||||
right: -6rpx;
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 4rpx 10rpx rgba(78, 56, 96, 0.16);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.user-meta {
|
||||
flex: 1;
|
||||
padding-top: 6rpx;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.user-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: 900;
|
||||
color: #272235;
|
||||
}
|
||||
|
||||
.user-handle {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #9b8fa8;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.user-bio {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #6a6178;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.edit-profile-btn {
|
||||
background: rgba(255, 255, 255, 0.80);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.72);
|
||||
border-radius: 999rpx;
|
||||
padding: 14rpx 28rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
color: #272235;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 8rpx 18rpx rgba(78, 56, 96, 0.08);
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
/* 数据统计 */
|
||||
.stats-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
padding: 24rpx 0;
|
||||
text-align: center;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.72);
|
||||
border-radius: 30rpx;
|
||||
box-shadow: 0 10rpx 22rpx rgba(78, 56, 96, 0.07);
|
||||
}
|
||||
|
||||
.stat-num {
|
||||
display: block;
|
||||
font-size: 40rpx;
|
||||
font-weight: 900;
|
||||
color: #ff4f91;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #9b8fa8;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
/* 区块 */
|
||||
.section-wrap {
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 28rpx 14rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 900;
|
||||
color: #9b8fa8;
|
||||
letter-spacing: 0.5rpx;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.add-pet-btn {
|
||||
font-size: 24rpx;
|
||||
font-weight: 800;
|
||||
color: #ff4f91;
|
||||
background: #ffe5f0;
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
/* 宠物卡片 */
|
||||
.pets-scroll {
|
||||
white-space: nowrap;
|
||||
padding: 0 28rpx 16rpx;
|
||||
}
|
||||
|
||||
.pet-card {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 18rpx;
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.82), rgba(201, 247, 223, 0.72));
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.72);
|
||||
border-radius: 36rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
margin-right: 20rpx;
|
||||
box-shadow: 0 12rpx 26rpx rgba(78, 56, 96, 0.09);
|
||||
white-space: normal;
|
||||
vertical-align: top;
|
||||
max-width: 560rpx;
|
||||
}
|
||||
|
||||
.pet-card-empty {
|
||||
background: rgba(255, 255, 255, 0.60);
|
||||
border: 3rpx dashed rgba(43, 37, 61, 0.16);
|
||||
}
|
||||
|
||||
.pet-avatar {
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pet-avatar-add { background: rgba(255, 255, 255, 0.60); color: #9b8fa8; }
|
||||
|
||||
.pet-emoji { font-size: 44rpx; line-height: 1; }
|
||||
|
||||
.pet-info { min-width: 0; }
|
||||
|
||||
.pet-name {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 900;
|
||||
color: #272235;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.pet-breed {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #9b8fa8;
|
||||
}
|
||||
|
||||
.pet-badge {
|
||||
background: #ffe5f0;
|
||||
border-radius: 999rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
font-size: 20rpx;
|
||||
color: #a91d5b;
|
||||
font-weight: 900;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 视图切换 */
|
||||
.view-toggle {
|
||||
display: flex;
|
||||
background: rgba(255, 255, 255, 0.60);
|
||||
border: 1rpx solid rgba(43, 37, 61, 0.10);
|
||||
border-radius: 14rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toggle-item {
|
||||
padding: 10rpx 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #9b8fa8;
|
||||
}
|
||||
|
||||
.toggle-item.active {
|
||||
background: rgba(255, 79, 145, 0.12);
|
||||
color: #ff4f91;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
/* 动态网格 */
|
||||
.post-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 6rpx;
|
||||
padding: 0 28rpx 20rpx;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
aspect-ratio: 1;
|
||||
border-radius: 28rpx;
|
||||
overflow: hidden;
|
||||
background: #f0eef5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.grid-img { width: 100%; height: 100%; }
|
||||
|
||||
.grid-no-img {
|
||||
padding: 12rpx;
|
||||
font-size: 20rpx;
|
||||
color: #9b8fa8;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.grid-empty {
|
||||
grid-column: span 3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 60rpx 0;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.empty-emoji { font-size: 72rpx; }
|
||||
|
||||
.empty-tip { font-size: 26rpx; color: #9b8fa8; }
|
||||
|
||||
.post-btn { padding: 18rpx 48rpx; font-size: 26rpx; font-weight: 800; margin-top: 8rpx; }
|
||||
Reference in New Issue
Block a user