1402 lines
32 KiB
Plaintext
1402 lines
32 KiB
Plaintext
<template>
|
|
<scroll-view class="user-profile-page" direction="vertical">
|
|
<!-- 顶部背景和返回 -->
|
|
<view class="header-section">
|
|
<view class="header-bg">
|
|
<image class="bg-image" :src="userInfo.cover" mode="aspectFill"></image>
|
|
<view class="bg-overlay"></view>
|
|
</view>
|
|
|
|
<view class="header-content">
|
|
<view class="header-top">
|
|
<view class="back-btn" @click="goBack">
|
|
<uni-icons type="left" size="24" color="#fff"></uni-icons>
|
|
</view>
|
|
<view class="header-right">
|
|
<view class="header-icon" @click="onShare">
|
|
<uni-icons type="redo" size="20" color="#fff"></uni-icons>
|
|
</view>
|
|
<view class="header-icon" @click="onMore">
|
|
<uni-icons type="more" size="20" color="#fff"></uni-icons>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 用户头像和基本信息 -->
|
|
<view class="user-basic">
|
|
<view class="avatar-section">
|
|
<image class="user-avatar" :src="userInfo.avatar" mode="aspectFill"></image>
|
|
<view v-if="userInfo.online" class="online-badge"></view>
|
|
<view v-if="userInfo.vip" class="vip-badge">VIP{{ userInfo.vipLevel }}</view>
|
|
</view>
|
|
|
|
<view class="user-info">
|
|
<view class="name-section">
|
|
<text class="user-name">{{ userInfo.nickname }}</text>
|
|
<view class="gender-age">
|
|
<view class="gender-badge" :class="userInfo.gender">
|
|
<uni-icons :type="userInfo.gender == 'male' ? 'male' : 'female'" size="16"
|
|
:color="userInfo.gender == 'male' ? '#007AFF' : '#FF2D55'"></uni-icons>
|
|
</view>
|
|
<text class="user-age">{{ userInfo.age }}岁</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="user-tags">
|
|
<view v-for="(tag, index) in userInfo.tags.slice(0, 3)" :key="index" class="tag">
|
|
<text class="tag-text">{{ tag }}</text>
|
|
</view>
|
|
<view v-if="userInfo.tags.length > 3" class="tag more" @click="showAllTags">
|
|
<text class="tag-text">+{{ userInfo.tags.length - 3 }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="user-meta">
|
|
<view class="meta-item">
|
|
<uni-icons type="location" size="16" color="#fff"></uni-icons>
|
|
<text class="meta-text">{{ userInfo.location }}</text>
|
|
</view>
|
|
<view class="meta-item">
|
|
<uni-icons type="time" size="16" color="#fff"></uni-icons>
|
|
<text class="meta-text">{{ formatLastActive(userInfo.lastActive) }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 用户数据统计 -->
|
|
<view class="stats-section">
|
|
<view class="stats-grid">
|
|
<view class="stat-item" @click="navigateTo('followers')">
|
|
<text class="stat-value">{{ formatNumber(userInfo.followers) }}</text>
|
|
<text class="stat-label">粉丝</text>
|
|
</view>
|
|
<view class="stat-item" @click="navigateTo('following')">
|
|
<text class="stat-value">{{ formatNumber(userInfo.following) }}</text>
|
|
<text class="stat-label">关注</text>
|
|
</view>
|
|
<view class="stat-item" @click="navigateTo('moments')">
|
|
<text class="stat-value">{{ formatNumber(userInfo.moments) }}</text>
|
|
<text class="stat-label">动态</text>
|
|
</view>
|
|
<view class="stat-item" @click="navigateTo('gifts')">
|
|
<text class="stat-value">{{ formatNumber(userInfo.gifts) }}</text>
|
|
<text class="stat-label">礼物</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 操作按钮 -->
|
|
<view class="action-section">
|
|
<button class="action-btn follow-btn" :class="{ 'followed': isFollowing }" @click="toggleFollow">
|
|
<uni-icons :type="isFollowing ? 'checkmark' : 'plus'" size="20"
|
|
:color="isFollowing ? '#999' : '#fff'"></uni-icons>
|
|
<text>{{ isFollowing ? '已关注' : '关注' }}</text>
|
|
</button>
|
|
<button class="action-btn chat-btn" @click="startChat">
|
|
<uni-icons type="chat" size="20" color="#fff"></uni-icons>
|
|
<text>发消息</text>
|
|
</button>
|
|
|
|
<button class="action-btn gift-btn" @click="showGiftPanel">
|
|
<uni-icons type="gift" size="20" color="#fff"></uni-icons>
|
|
<text>礼物</text>
|
|
</button>
|
|
</view>
|
|
|
|
<!-- 内容区域 -->
|
|
<scroll-view class="content-section" direction="vertical" :show-scrollbar="false" >
|
|
<!-- 个人简介 -->
|
|
<view class="content-block" v-if="userInfo.introduction">
|
|
<view class="block-header">
|
|
<text class="block-title">个人简介</text>
|
|
</view>
|
|
<view class="block-content">
|
|
<text class="intro-text">{{ userInfo.introduction }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 详细信息 -->
|
|
<view class="content-block">
|
|
<view class="block-header">
|
|
<text class="block-title">详细信息</text>
|
|
</view>
|
|
<view class="detail-grid">
|
|
<view class="detail-item" v-if="userInfo.height">
|
|
<text class="detail-label">身高</text>
|
|
<text class="detail-value">{{ userInfo.height }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.weight">
|
|
<text class="detail-label">体重</text>
|
|
<text class="detail-value">{{ userInfo.weight }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.profession">
|
|
<text class="detail-label">职业</text>
|
|
<text class="detail-value">{{ userInfo.profession }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.income">
|
|
<text class="detail-label">月收入</text>
|
|
<text class="detail-value">{{ userInfo.income }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.education">
|
|
<text class="detail-label">学历</text>
|
|
<text class="detail-value">{{ userInfo.education }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.constellation">
|
|
<text class="detail-label">星座</text>
|
|
<text class="detail-value">{{ userInfo.constellation }}</text>
|
|
</view>
|
|
<view class="detail-item" v-if="userInfo.relationship">
|
|
<text class="detail-label">感情状况</text>
|
|
<text class="detail-value">{{ userInfo.relationship }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 兴趣爱好 -->
|
|
<view class="content-block" v-if="userInfo.hobbies !=null && userInfo.hobbies.length > 0">
|
|
<view class="block-header">
|
|
<text class="block-title">兴趣爱好</text>
|
|
</view>
|
|
<view class="hobbies-grid">
|
|
<view v-for="(hobby, index) in userInfo.hobbies" :key="index" class="hobby-item">
|
|
<text class="hobby-text">{{ hobby }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 照片墙 -->
|
|
<view class="content-block" v-if="userInfo.photos !=null && userInfo.photos.length > 0">
|
|
<view class="block-header">
|
|
<text class="block-title">照片墙</text>
|
|
<text class="block-count">{{ userInfo.photos.length }}张</text>
|
|
</view>
|
|
<view class="photos-grid">
|
|
<view v-for="(photo, index) in userInfo.photos.slice(0, 6)" :key="index" class="photo-item"
|
|
@click="previewPhotos(index)">
|
|
<image class="photo" :src="photo" mode="aspectFill"></image>
|
|
<view v-if="index == 5 && userInfo.photos.length > 6" class="photo-more">
|
|
<text>+{{ userInfo.photos.length - 6 }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 最近动态 -->
|
|
<view class="content-block" v-if="recentMoments.length > 0">
|
|
<view class="block-header">
|
|
<text class="block-title">最近动态</text>
|
|
<view class="view-all" @click="navigateTo('moments')">
|
|
<text class="view-all-text">查看全部</text>
|
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
|
</view>
|
|
</view>
|
|
<view class="moments-list">
|
|
<view v-for="moment in recentMoments" :key="moment.id" class="moment-item"
|
|
@click="viewMoment(moment.id)">
|
|
<view class="moment-content">
|
|
<text class="moment-text">{{ moment.content }}</text>
|
|
<view v-if="moment.images !=null && moment.images.length > 0" class="moment-images">
|
|
<image v-for="(img, idx) in moment.images.slice(0, 3)" :key="idx" class="moment-image"
|
|
:src="img" mode="aspectFill"></image>
|
|
</view>
|
|
</view>
|
|
<view class="moment-footer">
|
|
<text class="moment-time">{{ formatTime(moment.time) }}</text>
|
|
<view class="moment-stats">
|
|
<view class="moment-stat">
|
|
<uni-icons type="heart" size="16" color="#999"></uni-icons>
|
|
<text class="stat-count">{{ moment.likes }}</text>
|
|
</view>
|
|
<view class="moment-stat">
|
|
<uni-icons type="chat" size="16" color="#999"></uni-icons>
|
|
<text class="stat-count">{{ moment.comments }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 相似推荐 -->
|
|
<view class="content-block" v-if="similarUsers.length > 0">
|
|
<view class="block-header">
|
|
<text class="block-title">相似推荐</text>
|
|
</view>
|
|
<scroll-view class="similar-users" direction="horizontal" :show-scrollbar="false">
|
|
<view v-for="user in similarUsers" :key="user.id" class="similar-user" @click="viewUser(user.id)">
|
|
<view class="similar-avatar">
|
|
<image class="avatar" :src="user.avatar" mode="aspectFill"></image>
|
|
<view v-if="user.online" class="online-dot"></view>
|
|
</view>
|
|
<text class="similar-name">{{ user.nickname }}</text>
|
|
<text class="similar-age">{{ user.age }}岁</text>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<!-- 底部空白 -->
|
|
<view class="bottom-space"></view>
|
|
</scroll-view>
|
|
<!-- 礼物面板 -->
|
|
<view v-if="giftPanelVisible" class="gift-panel" @click="hideGiftPanel">
|
|
<view class="panel-content" @click.stop>
|
|
<view class="panel-header">
|
|
<text class="panel-title">选择礼物</text>
|
|
<uni-icons type="close" size="20" color="#999" @click="hideGiftPanel"></uni-icons>
|
|
</view>
|
|
<scroll-view class="gift-list" scroll-y>
|
|
<view v-for="gift in gifts" :key="gift.id" class="gift-item"
|
|
:class="{ selected: selectedGiftId == gift.id }" @click="selectGift(gift)">
|
|
<image class="gift-image" :src="gift.image" mode="aspectFit"></image>
|
|
<text class="gift-name">{{ gift.name }}</text>
|
|
<view class="gift-price">
|
|
<uni-icons type="wallet" size="12" color="#FF9500"></uni-icons>
|
|
<text class="price-text">{{ gift.price }}</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="panel-footer">
|
|
<view class="balance-info">
|
|
<text>余额: </text>
|
|
<text class="balance-amount">{{ userBalance }}</text>
|
|
<uni-icons type="wallet" size="16" color="#FF9500"></uni-icons>
|
|
</view>
|
|
<button class="send-gift-btn" :disabled="selectedGiftId !=null" @click="sendGift">
|
|
赠送
|
|
</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 标签弹窗 -->
|
|
<view v-if="showTagsModal" class="tags-modal" @click="hideTagsModal">
|
|
<view class="modal-content" @click.stop>
|
|
<view class="modal-header">
|
|
<text class="modal-title">所有标签</text>
|
|
<uni-icons type="close" size="20" color="#999" @click="hideTagsModal"></uni-icons>
|
|
</view>
|
|
<view class="tags-list">
|
|
<view v-for="(tag, index) in userInfo.tags" :key="index" class="modal-tag">
|
|
<text class="tag-text">{{ tag }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
|
|
// 用户信息接口
|
|
type UserInfo = {
|
|
id : number
|
|
nickname : string
|
|
avatar : string
|
|
cover : string
|
|
gender : 'male' | 'female'
|
|
age : number
|
|
vip : boolean
|
|
vipLevel : number
|
|
online : boolean
|
|
tags : string[]
|
|
location : string
|
|
lastActive : number
|
|
introduction : string
|
|
followers : number
|
|
following : number
|
|
moments : number
|
|
gifts : number
|
|
height ?: string
|
|
weight ?: string
|
|
profession ?: string
|
|
income ?: string
|
|
education ?: string
|
|
relationship ?: string
|
|
constellation ?: string
|
|
hobbies : string[]
|
|
photos : string[]
|
|
}
|
|
|
|
// 动态接口
|
|
type Moment = {
|
|
id : number
|
|
content : string
|
|
images : string[]
|
|
time : number
|
|
likes : number
|
|
comments : number
|
|
}
|
|
|
|
// 相似用户接口
|
|
type SimilarUser = {
|
|
id : number
|
|
nickname : string
|
|
avatar : string
|
|
age : number
|
|
online : boolean
|
|
}
|
|
|
|
// 礼物接口
|
|
type Gift = {
|
|
id : number
|
|
name : string
|
|
image : string
|
|
price : number
|
|
}
|
|
|
|
// 响应式数据
|
|
const isFollowing = ref(false)
|
|
const giftPanelVisible = ref(false)
|
|
const showTagsModal = ref(false)
|
|
const selectedGiftId = ref<number | null>(null)
|
|
const userBalance = ref(8888)
|
|
|
|
// 用户信息
|
|
const userInfo = reactive<UserInfo>({
|
|
id: 1001,
|
|
nickname: '小雨',
|
|
avatar: 'https://randomuser.me/api/portraits/women/44.jpg',
|
|
cover: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80',
|
|
gender: 'female',
|
|
age: 25,
|
|
vip: true,
|
|
vipLevel: 3,
|
|
online: true,
|
|
tags: ['旅行', '美食', '摄影', '健身', '读书', '电影', '音乐', '舞蹈'],
|
|
location: '上海 · 浦东新区',
|
|
lastActive: Date.now() - 1000 * 60 * 30, // 30分钟前
|
|
introduction: '热爱生活的90后女生,喜欢旅行、摄影和美食。性格开朗,喜欢交朋友,希望在这里遇到有缘的你。',
|
|
followers: 1284,
|
|
following: 234,
|
|
moments: 56,
|
|
gifts: 128,
|
|
height: '165cm',
|
|
weight: '50kg',
|
|
profession: 'UI设计师',
|
|
income: '15-20k',
|
|
education: '本科',
|
|
relationship: '单身',
|
|
constellation: '白羊座',
|
|
hobbies: ['旅行', '摄影', '美食探店', '健身', '看电影', '听音乐', '阅读'],
|
|
photos: [
|
|
'https://images.unsplash.com/photo-1494790108755-2616c113a1c0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1488426862026-3ee34a7d66df?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80',
|
|
'https://images.unsplash.com/photo-1494790108755-2616c113a1c0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
|
|
]
|
|
})
|
|
|
|
// 最近动态
|
|
const recentMoments = reactive<Moment[]>([
|
|
{
|
|
id: 1,
|
|
content: '今天天气真好,和朋友一起去了公园散步,心情美美哒~',
|
|
images: [
|
|
'https://images.unsplash.com/photo-1501854140801-50d01698950b?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80'
|
|
],
|
|
time: Date.now() - 1000 * 60 * 60 * 2, // 2小时前
|
|
likes: 24,
|
|
comments: 5
|
|
},
|
|
{
|
|
id: 2,
|
|
content: '分享一首最近很喜欢的歌,希望大家喜欢~',
|
|
images: [],
|
|
time: Date.now() - 1000 * 60 * 60 * 24, // 1天前
|
|
likes: 36,
|
|
comments: 8
|
|
}
|
|
])
|
|
|
|
// 相似用户
|
|
const similarUsers = reactive<SimilarUser[]>([
|
|
{ id: 1002, nickname: '小美', avatar: 'https://randomuser.me/api/portraits/women/68.jpg', age: 24, online: true },
|
|
{ id: 1003, nickname: '莉莉', avatar: 'https://randomuser.me/api/portraits/women/23.jpg', age: 26, online: false },
|
|
{ id: 1004, nickname: '静静', avatar: 'https://randomuser.me/api/portraits/women/65.jpg', age: 23, online: true },
|
|
{ id: 1005, nickname: '娜娜', avatar: 'https://randomuser.me/api/portraits/women/50.jpg', age: 27, online: true },
|
|
{ id: 1006, nickname: '小雅', avatar: 'https://randomuser.me/api/portraits/women/32.jpg', age: 25, online: false }
|
|
])
|
|
|
|
// 礼物列表
|
|
const gifts = reactive<Gift[]>([
|
|
{ id: 1, name: '玫瑰花', image: 'https://cdn-icons-png.flaticon.com/512/824/824239.png', price: 10 },
|
|
{ id: 2, name: '棒棒糖', image: 'https://cdn-icons-png.flaticon.com/512/3235/3235060.png', price: 20 },
|
|
{ id: 3, name: '爱心', image: 'https://cdn-icons-png.flaticon.com/512/535/535285.png', price: 50 },
|
|
{ id: 4, name: '跑车', image: 'https://cdn-icons-png.flaticon.com/512/744/744465.png', price: 100 },
|
|
{ id: 5, name: '钻戒', image: 'https://cdn-icons-png.flaticon.com/512/3135/3135715.png', price: 520 },
|
|
{ id: 6, name: '皇冠', image: 'https://cdn-icons-png.flaticon.com/512/201/201623.png', price: 1314 }
|
|
])
|
|
|
|
// 页面加载
|
|
onMounted(() => {
|
|
console.log('用户信息页面加载完成')
|
|
//checkFollowStatus()
|
|
})
|
|
|
|
// 返回上一页
|
|
const goBack = () => {
|
|
uni.navigateBack()
|
|
}
|
|
|
|
// 分享用户
|
|
const onShare = () => {
|
|
// uni.showShareMenu({
|
|
// withShareTicket: true,
|
|
// success: () => {
|
|
// console.log('分享用户:', userInfo.nickname)
|
|
// }
|
|
// })
|
|
}
|
|
|
|
// 更多操作
|
|
const onMore = () => {
|
|
uni.showActionSheet({
|
|
itemList: ['举报用户', '拉黑用户', '分享动态'],
|
|
success: (res) => {
|
|
switch (res.tapIndex) {
|
|
case 0:
|
|
// reportUser()
|
|
break
|
|
case 1:
|
|
//blockUser()
|
|
break
|
|
case 2:
|
|
onShare()
|
|
break
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// 格式化最后活跃时间
|
|
const formatLastActive = (timestamp : number) : string => {
|
|
const now = Date.now()
|
|
const diff = now - timestamp
|
|
|
|
if (diff < 60000) { // 1分钟内
|
|
return '刚刚在线'
|
|
} else if (diff < 3600000) { // 1小时内
|
|
return Math.floor(diff / 60000) + '分钟前在线'
|
|
} else if (diff < 86400000) { // 1天内
|
|
return Math.floor(diff / 3600000) + '小时前在线'
|
|
} else if (diff < 7 * 86400000) { // 1周内
|
|
return Math.floor(diff / 86400000) + '天前在线'
|
|
} else {
|
|
return '一周前在线'
|
|
}
|
|
}
|
|
|
|
// 格式化数字
|
|
const formatNumber = (num : number) : string => {
|
|
if (num >= 10000) {
|
|
return (num / 10000).toFixed(1) + 'w'
|
|
} else if (num >= 1000) {
|
|
return (num / 1000).toFixed(1) + 'k'
|
|
}
|
|
return num.toString()
|
|
}
|
|
|
|
// 格式化时间
|
|
const formatTime = (timestamp : number) : string => {
|
|
const now = Date.now()
|
|
const diff = now - timestamp
|
|
|
|
if (diff < 60000) { // 1分钟内
|
|
return '刚刚'
|
|
} else if (diff < 3600000) { // 1小时内
|
|
return Math.floor(diff / 60000) + '分钟前'
|
|
} else if (diff < 86400000) { // 1天内
|
|
return Math.floor(diff / 3600000) + '小时前'
|
|
} else if (diff < 7 * 86400000) { // 1周内
|
|
return Math.floor(diff / 86400000) + '天前'
|
|
} else {
|
|
const date = new Date(timestamp)
|
|
return `${date.getMonth() + 1}月${date.getDate()}日`
|
|
}
|
|
}
|
|
|
|
// 检查关注状态
|
|
const checkFollowStatus = () => {
|
|
const followed = uni.getStorageSync(`follow_${userInfo.id}`)
|
|
isFollowing.value = followed != null
|
|
}
|
|
|
|
// 切换关注状态
|
|
const toggleFollow = () => {
|
|
isFollowing.value = !isFollowing.value
|
|
|
|
if (isFollowing.value) {
|
|
uni.setStorageSync(`follow_${userInfo.id}`, '1')
|
|
userInfo.followers++
|
|
uni.showToast({
|
|
title: '关注成功',
|
|
icon: 'success',
|
|
duration: 1500
|
|
})
|
|
} else {
|
|
uni.removeStorageSync(`follow_${userInfo.id}`)
|
|
userInfo.followers--
|
|
uni.showToast({
|
|
title: '已取消关注',
|
|
icon: 'none',
|
|
duration: 1500
|
|
})
|
|
}
|
|
}
|
|
|
|
// 开始聊天
|
|
const startChat = () => {
|
|
uni.navigateTo({
|
|
url: `/pages/chat/chat?userId=${userInfo.id}&userName=${userInfo.nickname}`
|
|
})
|
|
}
|
|
|
|
// 显示礼物面板
|
|
const showGiftPanel = () => {
|
|
giftPanelVisible.value = !giftPanelVisible.value
|
|
}
|
|
|
|
// 隐藏礼物面板
|
|
const hideGiftPanel = () => {
|
|
giftPanelVisible.value = !giftPanelVisible.value
|
|
selectedGiftId.value = null
|
|
}
|
|
|
|
// 选择礼物
|
|
const selectGift = (gift : Gift) => {
|
|
selectedGiftId.value = gift.id
|
|
}
|
|
|
|
// 发送礼物
|
|
const sendGift = () => {
|
|
if (selectedGiftId.value == null) return
|
|
|
|
const gift = gifts.find(g => g.id == selectedGiftId.value)
|
|
if (gift == null) return
|
|
|
|
if (userBalance.value < gift.price) {
|
|
uni.showModal({
|
|
title: '余额不足',
|
|
content: '您的余额不足,请先充值',
|
|
confirmText: '去充值',
|
|
cancelText: '取消',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.navigateTo({
|
|
url: '/pages/recharge/recharge'
|
|
})
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|
|
|
|
// 扣款
|
|
userBalance.value -= gift.price
|
|
userInfo.gifts++
|
|
|
|
uni.showToast({
|
|
title: `赠送${gift.name}成功`,
|
|
icon: 'success',
|
|
duration: 1500
|
|
})
|
|
|
|
hideGiftPanel()
|
|
}
|
|
|
|
// 显示所有标签
|
|
const showAllTags = () => {
|
|
showTagsModal.value = true
|
|
}
|
|
|
|
// 隐藏标签弹窗
|
|
const hideTagsModal = () => {
|
|
showTagsModal.value = false
|
|
}
|
|
|
|
// 预览照片
|
|
const previewPhotos = (index : number) => {
|
|
uni.previewImage({
|
|
current: index,
|
|
urls: userInfo.photos
|
|
})
|
|
}
|
|
|
|
// 查看动态
|
|
const viewMoment = (momentId : number) => {
|
|
uni.navigateTo({
|
|
url: `/pages/moment-detail/moment-detail?id=${momentId}`
|
|
})
|
|
}
|
|
|
|
// 查看用户
|
|
const viewUser = (userId : number) => {
|
|
uni.navigateTo({
|
|
url: `/pages/user-profile/user-profile?id=${userId}`
|
|
})
|
|
}
|
|
|
|
// 页面跳转
|
|
const navigateTo = (page : string) => {
|
|
let path : string | null = null
|
|
switch (page) {
|
|
case 'followers':
|
|
path = `/pages/followers/followers?userId=${userInfo.id}`
|
|
break;
|
|
case 'following':
|
|
path = `/pages/followers/following?userId=${userInfo.id}`
|
|
break;
|
|
case 'moments':
|
|
path = `/pages/moments/moments?userId=${userInfo.id}`
|
|
break;
|
|
case 'gifts':
|
|
path = `/pages/gifts/gifts?userId=${userInfo.id}`
|
|
break;
|
|
}
|
|
if (path != null) {
|
|
uni.navigateTo({
|
|
url: path
|
|
})
|
|
}
|
|
}
|
|
|
|
// 举报用户
|
|
const reportUser = () => {
|
|
uni.navigateTo({
|
|
url: `/pages/report/report?userId=${userInfo.id}&type=user`
|
|
})
|
|
}
|
|
|
|
// 拉黑用户
|
|
const blockUser = () => {
|
|
uni.showModal({
|
|
title: '拉黑用户',
|
|
content: '拉黑后将不再接收该用户的消息,是否确认?',
|
|
confirmText: '确认拉黑',
|
|
cancelText: '取消',
|
|
confirmColor: '#FF3B30',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showToast({
|
|
title: '已拉黑用户',
|
|
icon: 'success',
|
|
duration: 1500
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.user-profile-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
background-color: #f5f5f5;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* 头部区域 */
|
|
.header-section {
|
|
position: relative;
|
|
height: 400rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.header-bg {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
}
|
|
|
|
.bg-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #e0e0e0;
|
|
}
|
|
|
|
.bg-overlay {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.5));
|
|
}
|
|
|
|
.header-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 40rpx 30rpx 0;
|
|
}
|
|
|
|
.header-top {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.back-btn {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 50%;
|
|
background-color: rgba(0, 0, 0, 0.3);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.header-right {
|
|
display: flex;
|
|
}
|
|
|
|
.header-icon {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 50%;
|
|
background-color: rgba(0, 0, 0, 0.3);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* 用户基本信息 */
|
|
.user-basic {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
margin-top: auto;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.avatar-section {
|
|
position: relative;
|
|
margin-right: 30rpx;
|
|
}
|
|
|
|
.user-avatar {
|
|
width: 140rpx;
|
|
height: 140rpx;
|
|
border-radius: 50%;
|
|
border: 6rpx solid rgba(255, 255, 255, 0.3);
|
|
background-color: #f0f0f0;
|
|
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.online-badge {
|
|
position: absolute;
|
|
top: 10rpx;
|
|
right: 10rpx;
|
|
width: 24rpx;
|
|
height: 24rpx;
|
|
background-color: #4CD964;
|
|
border-radius: 50%;
|
|
border: 4rpx solid #fff;
|
|
}
|
|
|
|
|
|
.vip-badge {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
padding: 6rpx 15rpx;
|
|
background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%);
|
|
color: #fff;
|
|
font-size: 20rpx;
|
|
font-weight: bold;
|
|
border-radius: 20rpx;
|
|
border: 4rpx solid #fff;
|
|
}
|
|
|
|
.user-info {
|
|
flex: 1;
|
|
display: flex;
|
|
}
|
|
|
|
.name-section {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-flow: row nowrap;
|
|
margin-bottom: 15rpx;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.user-name {
|
|
font-size: 40rpx;
|
|
font-weight: bold;
|
|
color: #fff;
|
|
margin-right: 20rpx;
|
|
text-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.gender-age {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-flow: row nowrap;
|
|
}
|
|
|
|
.gender-badge {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.user-age {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
text-shadow: 0 2rpx 5rpx rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.user-tags {
|
|
display: flex;
|
|
flex-flow: row wrap;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.tag {
|
|
padding: 8rpx 20rpx;
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
border-radius: 20rpx;
|
|
}
|
|
|
|
.tag.more {
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.tag-text {
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.user-meta {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
}
|
|
|
|
.meta-item {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.meta-text {
|
|
font-size: 24rpx;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
text-shadow: 0 2rpx 5rpx rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
/* 统计数据 */
|
|
.stats-section {
|
|
background-color: #fff;
|
|
padding: 30rpx 0;
|
|
box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.stats-grid {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
}
|
|
|
|
.stat-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
/* 操作按钮 */
|
|
.action-section {
|
|
position: fixed;
|
|
bottom: 0;
|
|
width:100%;
|
|
display: flex;
|
|
padding: 5rpx;
|
|
flex-flow: row nowrap;
|
|
background-color: #fff;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
}
|
|
|
|
.action-btn {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
flex-flow: row nowrap;
|
|
justify-content: center;
|
|
padding: 3rpx 0;
|
|
border-radius: 40rpx;
|
|
font-size: 24rpx;
|
|
font-weight: 500;
|
|
border: none;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.action-btn:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.follow-btn {
|
|
background-color: #f8f8f8;
|
|
color: #333;
|
|
}
|
|
|
|
.follow-btn.followed {
|
|
background-color: #f0f0f0;
|
|
color: #999;
|
|
}
|
|
|
|
.chat-btn {
|
|
background: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);
|
|
color: #fff;
|
|
}
|
|
|
|
.gift-btn {
|
|
background: linear-gradient(135deg, #FF9500 0%, #FFCC00 100%);
|
|
color: #fff;
|
|
}
|
|
|
|
/* 内容区域 */
|
|
.content-section {
|
|
flex: 1;
|
|
padding: 0 30rpx 30rpx;
|
|
}
|
|
|
|
.content-block {
|
|
background-color: #fff;
|
|
border-radius: 20rpx;
|
|
padding: 30rpx;
|
|
margin-top: 20rpx;
|
|
box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.block-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
flex-flow: row;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.block-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.block-count {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.view-all {
|
|
display: flex;
|
|
flex-flow: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.view-all-text {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.block-content {
|
|
padding: 10rpx 0;
|
|
}
|
|
|
|
.intro-text {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* 详细信息网格 */
|
|
.detail-grid {
|
|
display: flex;
|
|
flex-flow: row wrap;
|
|
}
|
|
|
|
.detail-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20rpx 0;
|
|
border-bottom: 1rpx solid #f5f5f5;
|
|
}
|
|
|
|
/* .detail-item:nth-last-child(-n+2) {
|
|
border-bottom: none;
|
|
} */
|
|
|
|
.detail-label {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.detail-value {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 兴趣爱好 */
|
|
.hobbies-grid {
|
|
display: flex;
|
|
flex-flow:row wrap;
|
|
}
|
|
|
|
.hobby-item {
|
|
padding: 12rpx 25rpx;
|
|
background-color: #f8f8f8;
|
|
border-radius: 30rpx;
|
|
}
|
|
|
|
.hobby-text {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
}
|
|
|
|
/* 照片墙 */
|
|
.photos-grid {
|
|
}
|
|
|
|
.photo-item {
|
|
position: relative;
|
|
border-radius: 10rpx;
|
|
overflow: hidden;
|
|
background-color: #f0f0f0;
|
|
}
|
|
|
|
.photo {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.photo-more {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.photo-more-text {
|
|
font-size: 32rpx;
|
|
color: #fff;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 动态列表 */
|
|
.moments-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.moment-item {
|
|
padding-bottom: 20rpx;
|
|
border-bottom: 1rpx solid #f5f5f5;
|
|
}
|
|
|
|
.moment-item:last-child {
|
|
border-bottom: none;
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.moment-content {
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.moment-text {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 1.5;
|
|
margin-bottom: 15rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.moment-images {
|
|
display: flex;
|
|
}
|
|
|
|
.moment-image {
|
|
width: 200rpx;
|
|
height: 200rpx;
|
|
border-radius: 10rpx;
|
|
background-color: #f0f0f0;
|
|
}
|
|
|
|
.moment-footer {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.moment-time {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.moment-stats {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
}
|
|
|
|
.moment-stat {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.stat-count {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
/* 相似用户 */
|
|
.similar-users {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
padding: 10rpx 0;
|
|
}
|
|
|
|
.similar-user {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
width: 150rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.similar-avatar {
|
|
position: relative;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.similar-avatar .avatar {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
border-radius: 50%;
|
|
background-color: #f0f0f0;
|
|
border: 4rpx solid #fff;
|
|
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.online-dot {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
width: 20rpx;
|
|
height: 20rpx;
|
|
background-color: #4CD964;
|
|
border-radius: 50%;
|
|
border: 3rpx solid #fff;
|
|
}
|
|
|
|
.similar-name {
|
|
font-size: 24rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
margin-bottom: 5rpx;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.similar-age {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
|
|
/* 底部空白 */
|
|
.bottom-space {
|
|
height: 100rpx;
|
|
}
|
|
|
|
/* 礼物面板 */
|
|
.gift-panel,
|
|
.tags-modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: flex-end;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.panel-content {
|
|
width: 100%;
|
|
background-color: #fff;
|
|
border-radius: 30rpx 30rpx 0 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
|
|
|
|
.panel-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 40rpx 30rpx 20rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.gift-list {
|
|
flex: 1;
|
|
padding: 30rpx;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-content: flex-start;
|
|
}
|
|
|
|
.gift-item {
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 20rpx 0;
|
|
border-radius: 20rpx;
|
|
border: 2rpx solid #f0f0f0;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.gift-item.selected {
|
|
border-color: #FF6B6B;
|
|
background-color: #fff5f5;
|
|
}
|
|
|
|
.gift-image {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.gift-name {
|
|
font-size: 24rpx;
|
|
color: #333;
|
|
margin-bottom: 10rpx;
|
|
text-align: center;
|
|
}
|
|
|
|
.gift-price {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.price-text {
|
|
font-size: 20rpx;
|
|
color: #FF9500;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.panel-footer {
|
|
height: 120rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 0 30rpx;
|
|
border-top: 1rpx solid #eee;
|
|
}
|
|
|
|
.balance-info {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.balance-amount {
|
|
font-weight: bold;
|
|
color: #FF9500;
|
|
}
|
|
|
|
.send-gift-btn {
|
|
background: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);
|
|
color: #fff;
|
|
padding: 20rpx 50rpx;
|
|
border-radius: 40rpx;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
border: none;
|
|
}
|
|
|
|
.send-gift-btn:disabled {
|
|
background: #ccc;
|
|
color: #999;
|
|
}
|
|
|
|
/* 标签弹窗 */
|
|
.tags-modal .modal-content {
|
|
width: 100%;
|
|
max-width: 600rpx;
|
|
background-color: #fff;
|
|
border-radius: 30rpx;
|
|
overflow: hidden;
|
|
margin: 0 30rpx 100rpx;
|
|
}
|
|
|
|
.tags-list {
|
|
padding: 30rpx;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
max-height: 400rpx;
|
|
}
|
|
|
|
.modal-tag {
|
|
padding: 12rpx 25rpx;
|
|
background-color: #f8f8f8;
|
|
border-radius: 30rpx;
|
|
}
|
|
|
|
.modal-tag .tag-text {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
}
|
|
</style> |