|
|
- <template>
- <view class="profile-page">
- <!-- 顶部导航 -->
- <!-- <navbar
- :title="userProfile.nickName || '用户主页'"
- :leftClick="true"
- :moreClick="showMoreOptions"
- bgColor="transparent"
- color="#fff"
- @leftClick="$utils.navigateBack"
- /> -->
-
- <!-- 用户信息头部 -->
- <view class="profile-header">
- <!-- 背景装饰 -->
- <view class="header-bg"></view>
-
- <!-- 返回按钮 -->
- <view class="back-btn" @click="$utils.navigateBack">
- <uv-icon name="arrow-left" size="30rpx" color="#fff"></uv-icon>
- </view>
-
- <!-- 用户基本信息 -->
- <view class="user-info">
- <view class="user-avatar">
- <image :src="userProfile.headImage" mode="aspectFill" @click="previewAvatar"></image>
- <!-- VIP标识 -->
- <view class="vip-badge" v-if="userProfile.isPay">
- <text>{{ getVipLevel(userProfile.isPay) }}</text>
- </view>
- </view>
-
- <view class="user-details">
- <view class="username">{{ userProfile.nickName }}</view>
- <view class="user-tags">
- <!-- 性别年龄 -->
- <view class="tag gender-tag" v-if="userProfile.sex">
- <uv-icon :name="sexIcons[userProfile.sex]" size="24rpx" :color="sexColors[userProfile.sex]"></uv-icon>
- <text>{{ userProfile.sex }}</text>
- <text v-if="userProfile.yearDate">{{ getAge() }}岁</text>
- </view>
- <!-- 地址 -->
- <view class="tag location-tag" v-if="userProfile.address">
- <uv-icon name="map-pin" size="20rpx" color="#666"></uv-icon>
- <text>{{ userProfile.address }}</text>
- </view>
- <!-- 认证状态 -->
- <view class="tag auth-tag" v-if="userProfile.idCardOpen">
- <uv-icon name="checkmark-circle-fill" size="20rpx" color="#52c41a"></uv-icon>
- <text>{{ getAuthText(userProfile.idCardOpen) }}</text>
- </view>
- </view>
-
- <!-- 学校信息 -->
- <view class="school-info" v-if="userProfile.czSchool || userProfile.gzSchool">
- <text v-if="userProfile.czSchool">🎓 {{ userProfile.czSchool }}</text>
- <text v-if="userProfile.gzSchool">🏫 {{ userProfile.gzSchool }}</text>
- </view>
- </view>
- </view>
-
- <!-- 数据统计 -->
- <view class="stats-row">
- <view class="stat-item" @click="showFans">
- <view class="stat-number">{{ userProfile.intentionNum || 0 }}</view>
- <view class="stat-label">粉丝</view>
- </view>
- <view class="stat-item" @click="showFollowing">
- <view class="stat-number">{{ userProfile.followNum || 0 }}</view>
- <view class="stat-label">关注</view>
- </view>
- <view class="stat-item" @click="showLikes">
- <view class="stat-number">{{ userProfile.likeNum || 0 }}</view>
- <view class="stat-label">获赞</view>
- </view>
- </view>
-
- <!-- 操作按钮 -->
- <view class="action-buttons" v-if="!isCurrentUser">
- <button class="follow-btn" :class="{followed: isFollowed}" @click="toggleFollow">
- <uv-icon :name="isFollowed ? 'checkmark' : 'plus'" size="24rpx"></uv-icon>
- <text>{{ isFollowed ? '已关注' : '关注' }}</text>
- </button>
- <button class="message-btn" @click="sendMessage">
- <uv-icon name="chat" size="24rpx"></uv-icon>
- <text>私信</text>
- </button>
- </view>
- </view>
-
- <!-- 内容标签页 -->
- <view class="content-tabs">
- <uv-tabs
- :list="contentTabs"
- :current="currentTabIndex"
- :activeStyle="{color: '#333', fontWeight: 600}"
- lineColor="#5baaff"
- lineHeight="6rpx"
- lineWidth="40rpx"
- keyName="name"
- @click="onTabClick"
- />
- </view>
-
- <!-- 内容区域 -->
- <view class="content-container">
- <!-- 帖子 - 瀑布流展示 -->
- <view v-if="currentTabIndex === 0" class="posts-content">
- <waterfallContainer
- v-if="postsList.length > 0"
- :list="postsList"
- @item-click="onPostClick"
- @item-like="onPostLike"
- />
- </view>
-
- <!-- 租房信息 -->
- <view v-else-if="currentTabIndex === 1" class="renting-content">
- <rentingItem
- v-for="(item, index) in rentingList"
- :key="index"
- :item="item"
- @click="onRentingClick(item)"
- />
- </view>
-
- <!-- 招聘信息 -->
- <view v-else-if="currentTabIndex === 2" class="work-content">
- <workItem
- v-for="(item, index) in workList"
- :key="index"
- :item="item"
- @click="onWorkClick(item)"
- />
- </view>
-
- <!-- 店铺信息 -->
- <view v-else-if="currentTabIndex === 3" class="shop-content">
- <gourmetItem
- v-for="(item, index) in shopList"
- :key="index"
- :item="item"
- @click="onShopClick(item)"
- />
- </view>
-
- <!-- 加载更多提示 -->
- <view v-if="showLoadMore" class="load-more-state">
- <uv-loading-icon size="32"></uv-loading-icon>
- <text>加载更多...</text>
- </view>
-
- <!-- 没有更多数据提示 -->
- <view v-if="showNoMore" class="no-more-state">
- <text>— 没有更多了 —</text>
- </view>
- </view>
-
- <!-- 空状态 -->
- <view v-if="showEmptyState" class="empty-state">
- <uv-empty
- :text="getEmptyText()"
- :icon="getEmptyIcon()"
- iconSize="120"
- ></uv-empty>
- </view>
-
- <!-- 初始加载状态 -->
- <view v-if="loading && currentList.length === 0" class="loading-state">
- <uv-loading-icon size="40"></uv-loading-icon>
- <text>加载中...</text>
- </view>
- </view>
- </template>
-
- <script>
- import navbar from '@/components/base/navbar.vue'
- import waterfallContainer from '@/components/list/square/waterfallContainer.vue'
- import rentingItem from '@/components/list/renting/rentingItem.vue'
- import workItem from '@/components/list/work/workItem.vue'
- import gourmetItem from '@/components/list/gourmet/gourmetItem.vue'
- import { mapState } from 'vuex'
-
- export default {
- components: {
- navbar,
- waterfallContainer,
- rentingItem,
- workItem,
- gourmetItem
- },
- data() {
- return {
- userId: '', // 要查看的用户ID
- userProfile: {}, // 用户资料
- currentTabIndex: 0, // 当前标签页索引
- contentTabs: [
- { name: '帖子', icon: 'grid' },
- { name: '租房', icon: 'home' },
- { name: '招聘', icon: 'search' },
- { name: '店铺', icon: 'shop' }
- ],
- postsList: [], // 帖子列表
- rentingList: [], // 租房列表
- workList: [], // 招聘列表
- shopList: [], // 店铺列表
- loading: false, // 初始加载状态
- loadingMore: false, // 加载更多状态
- isFollowed: false, // 是否已关注
- // 分页参数
- pageParams: {
- postsList: { pageNum: 1, hasMore: true },
- rentingList: { pageNum: 1, hasMore: true },
- workList: { pageNum: 1, hasMore: true },
- shopList: { pageNum: 1, hasMore: true }
- },
- sexIcons: {
- '男': 'mars',
- '女': 'venus',
- '其他': 'transgender'
- },
- sexColors: {
- '男': '#4A90E2',
- '女': '#FF69B4',
- '其他': '#999'
- }
- }
- },
- computed: {
- ...mapState(['userInfo']),
-
- // 是否是当前登录用户
- isCurrentUser() {
- return this.userInfo.id === this.userId
- },
-
- // 当前显示的列表
- currentList() {
- const listMap = ['postsList', 'rentingList', 'workList', 'shopList']
- return this[listMap[this.currentTabIndex]] || []
- },
-
- // 当前列表的分页参数
- currentPageParams() {
- const listMap = ['postsList', 'rentingList', 'workList', 'shopList']
- return this.pageParams[listMap[this.currentTabIndex]]
- },
-
- // 是否显示空状态
- showEmptyState() {
- return !this.loading && this.currentList.length === 0
- },
-
- // 是否显示加载更多
- showLoadMore() {
- return this.currentList.length > 0 && this.currentPageParams.hasMore && this.loadingMore
- },
-
- // 是否显示没有更多
- showNoMore() {
- return this.currentList.length > 0 && !this.currentPageParams.hasMore
- }
- },
- onLoad(options) {
- this.userId = options.userId || this.userInfo.id
- this.loadUserProfile()
- this.loadUserContent(false)
- },
- onPullDownRefresh() {
- this.loadUserProfile()
- this.refreshUserContent()
- },
- onReachBottom() {
- this.loadMoreContent()
- },
- methods: {
-
- // 显示更多选项
- showMoreOptions() {
- uni.showActionSheet({
- itemList: ['举报用户', '拉黑用户'],
- success: (res) => {
- if (res.tapIndex === 0) {
- this.reportUser()
- } else if (res.tapIndex === 1) {
- this.blockUser()
- }
- }
- })
- },
-
- // 预览头像
- previewAvatar() {
- if (this.userProfile.headImage) {
- uni.previewImage({
- urls: [this.userProfile.headImage]
- })
- }
- },
-
- // 获取VIP等级
- getVipLevel(level) {
- const levels = ['', 'VIP', 'SVIP']
- return levels[level] || ''
- },
-
- // 获取年龄
- getAge() {
- if (!this.userProfile.yearDate) return ''
- const birthYear = parseInt(this.userProfile.yearDate)
- const currentYear = new Date().getFullYear()
- return currentYear - birthYear
- },
-
- // 获取认证文本
- getAuthText(status) {
- const authTexts = ['审核中', '个人认证', '店铺认证']
- return authTexts[status] || '未认证'
- },
-
- // 标签页切换
- onTabClick(item) {
- this.currentTabIndex = item.index
- this.refreshUserContent()
- },
-
- // 切换关注状态
- toggleFollow() {
- if (!uni.getStorageSync('token')) {
- uni.showToast({
- title: '请先登录',
- icon: 'none'
- })
- return
- }
-
- this.isFollowed = !this.isFollowed
- // 这里调用关注/取消关注API
- this.$api(this.isFollowed ? 'followUser' : 'unfollowUser', {
- userId: this.userId
- }, res => {
- if (res.code === 200) {
- uni.showToast({
- title: this.isFollowed ? '关注成功' : '取消关注',
- icon: 'success'
- })
- }
- })
- },
-
- // 发送私信
- sendMessage() {
- if (!uni.getStorageSync('token')) {
- uni.showToast({
- title: '请先登录',
- icon: 'none'
- })
- return
- }
-
- uni.navigateTo({
- url: `/pages_order/chat/chatDetail?userId=${this.userId}`
- })
- },
-
- // 显示粉丝列表
- showFans() {
- uni.navigateTo({
- url: `/pages_order/profile/fansList?userId=${this.userId}&type=fans`
- })
- },
-
- // 显示关注列表
- showFollowing() {
- uni.navigateTo({
- url: `/pages_order/profile/fansList?userId=${this.userId}&type=following`
- })
- },
-
- // 显示点赞列表
- showLikes() {
- uni.showToast({
- title: '功能开发中',
- icon: 'none'
- })
- },
-
- // 加载用户资料
- loadUserProfile() {
- this.loading = true
- this.$api('getUserProfile', { userId: this.userId }, res => {
- this.loading = false
- uni.stopPullDownRefresh()
-
- if (res.code === 200) {
- this.userProfile = res.result
- // 检查是否已关注(如果不是当前用户)
- if (!this.isCurrentUser) {
- this.checkFollowStatus()
- }
- }
- })
- },
-
- // 检查关注状态
- checkFollowStatus() {
- this.$api('checkFollowStatus', { userId: this.userId }, res => {
- if (res.code === 200) {
- this.isFollowed = res.result.isFollowed
- }
- })
- },
-
- // 刷新用户内容(重置分页)
- refreshUserContent() {
- const listMap = ['postsList', 'rentingList', 'workList', 'shopList']
- const currentListKey = listMap[this.currentTabIndex]
-
- // 重置分页参数
- this.pageParams[currentListKey].pageNum = 1
- this.pageParams[currentListKey].hasMore = true
-
- // 清空当前列表
- this[currentListKey] = []
-
- // 加载第一页数据
- this.loadUserContent(false)
- },
-
- // 加载用户内容
- loadUserContent(isLoadMore = false) {
- const apiMap = [
- 'getUserPosts', // 帖子
- 'getUserRenting', // 租房
- 'getUserWork', // 招聘
- 'getUserShop' // 店铺
- ]
-
- const listMap = ['postsList', 'rentingList', 'workList', 'shopList']
- const currentListKey = listMap[this.currentTabIndex]
- const currentPageParams = this.pageParams[currentListKey]
-
- // 设置加载状态
- if (isLoadMore) {
- this.loadingMore = true
- } else {
- this.loading = true
- }
-
- this.$api(apiMap[this.currentTabIndex], {
- userId: this.userId,
- pageNum: currentPageParams.pageNum,
- pageSize: 20
- }, res => {
- // 清除加载状态
- this.loading = false
- this.loadingMore = false
- uni.stopPullDownRefresh()
-
- if (res.code === 200) {
- const newData = res.result.records || res.result || []
-
- if (isLoadMore) {
- // 加载更多:追加数据
- this[currentListKey] = [...this[currentListKey], ...newData]
- } else {
- // 首次加载:替换数据
- this[currentListKey] = newData
- }
-
- // 更新分页状态
- if (newData.length < 20) {
- // 数据不足一页,说明没有更多了
- this.pageParams[currentListKey].hasMore = false
- } else {
- // 还有更多数据,页码+1
- this.pageParams[currentListKey].pageNum += 1
- }
- } else {
- // 请求失败,恢复分页参数
- if (isLoadMore && currentPageParams.pageNum > 1) {
- this.pageParams[currentListKey].pageNum -= 1
- }
- }
- })
- },
-
- // 加载更多内容
- loadMoreContent() {
- // 检查是否有更多数据和是否正在加载
- if (!this.currentPageParams.hasMore || this.loadingMore || this.loading) {
- return
- }
-
- // 检查当前列表是否有数据
- if (this.currentList.length === 0) {
- return
- }
-
- this.loadUserContent(true)
- },
-
- // 点击帖子
- onPostClick(item) {
- this.$utils.navigateTo(`/pages_order/post/postDetail?id=${item.id}`)
- },
-
- // 点赞帖子
- onPostLike(item) {
- console.log('点赞帖子:', item.id)
- },
-
- // 点击租房
- onRentingClick(item) {
- this.$utils.navigateTo(`/pages_order/renting/rentingDetail?id=${item.id}`)
- },
-
- // 点击招聘
- onWorkClick(item) {
- this.$utils.navigateTo(`/pages_order/work/workDetail?id=${item.id}`)
- },
-
- // 点击店铺
- onShopClick(item) {
- this.$utils.navigateTo(`/pages_order/gourmet/gourmetDetail?id=${item.id}`)
- },
-
- // 举报用户
- reportUser() {
- uni.showToast({
- title: '举报功能开发中',
- icon: 'none'
- })
- },
-
- // 拉黑用户
- blockUser() {
- uni.showModal({
- title: '确认拉黑该用户?',
- success: (res) => {
- if (res.confirm) {
- // 调用拉黑API
- uni.showToast({
- title: '拉黑功能开发中',
- icon: 'none'
- })
- }
- }
- })
- },
-
- // 获取空状态文本
- getEmptyText() {
- const emptyTexts = ['暂无帖子', '暂无租房信息', '暂无招聘信息', '暂无店铺信息']
- return emptyTexts[this.currentTabIndex] || '暂无数据'
- },
-
- // 获取空状态图标
- getEmptyIcon() {
- const emptyIcons = ['list', 'home', 'search', 'shop']
- return emptyIcons[this.currentTabIndex] || 'list'
- }
- }
- }
- </script>
-
- <style scoped lang="scss">
- .profile-page {
- background-color: #f5f5f5;
- min-height: 100vh;
- }
-
-
-
- .profile-header {
- position: relative;
- padding: 40rpx 30rpx 40rpx;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- padding-top: 180rpx;
-
- .header-bg {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: linear-gradient(135deg, rgba(102, 126, 234, 0.9) 0%, rgba(118, 75, 162, 0.9) 100%);
- }
-
- .back-btn {
- position: absolute;
- top: 80rpx;
- left: 30rpx;
- z-index: 3;
- width: 70rpx;
- height: 70rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 50%;
- backdrop-filter: blur(10rpx);
- }
-
- .user-info {
- position: relative;
- z-index: 2;
- display: flex;
- margin-bottom: 40rpx;
-
- .user-avatar {
- position: relative;
- margin-right: 30rpx;
-
- image {
- width: 160rpx;
- height: 160rpx;
- border-radius: 80rpx;
- border: 6rpx solid rgba(255, 255, 255, 0.3);
- }
-
- .vip-badge {
- position: absolute;
- bottom: -10rpx;
- left: 50%;
- transform: translateX(-50%);
- background: linear-gradient(45deg, #FFD700, #FFA500);
- color: #333;
- padding: 6rpx 16rpx;
- border-radius: 20rpx;
- font-size: 20rpx;
- font-weight: 600;
- }
- }
-
- .user-details {
- flex: 1;
- color: #fff;
-
- .username {
- font-size: 36rpx;
- font-weight: 600;
- margin-bottom: 16rpx;
- }
-
- .user-tags {
- display: flex;
- flex-wrap: wrap;
- gap: 12rpx;
- margin-bottom: 16rpx;
-
- .tag {
- display: flex;
- align-items: center;
- background: rgba(255, 255, 255, 0.2);
- padding: 8rpx 16rpx;
- border-radius: 20rpx;
- font-size: 22rpx;
-
- text {
- margin-left: 6rpx;
- }
- }
- }
-
- .school-info {
- font-size: 24rpx;
- opacity: 0.9;
-
- text {
- display: block;
- margin-bottom: 6rpx;
- }
- }
- }
- }
-
- .stats-row {
- position: relative;
- z-index: 2;
- display: flex;
- justify-content: space-around;
- margin-bottom: 40rpx;
-
- .stat-item {
- text-align: center;
- color: #fff;
-
- .stat-number {
- font-size: 40rpx;
- font-weight: 600;
- margin-bottom: 8rpx;
- }
-
- .stat-label {
- font-size: 24rpx;
- opacity: 0.8;
- }
- }
- }
-
- .action-buttons {
- position: relative;
- z-index: 2;
- display: flex;
- gap: 20rpx;
-
- button {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 20rpx 0;
- border-radius: 50rpx;
- font-size: 28rpx;
- border: none;
-
- text {
- margin-left: 8rpx;
- }
- }
-
- .follow-btn {
- background: #fff;
- color: #333;
-
- &.followed {
- background: rgba(255, 255, 255, 0.3);
- color: #fff;
- }
- }
-
- .message-btn {
- background: rgba(255, 255, 255, 0.3);
- color: #fff;
- }
- }
- }
-
- .content-tabs {
- background: #fff;
- border-bottom: 1rpx solid #eee;
- padding: 0 20rpx;
- }
-
- .content-container {
- min-height: 400rpx;
-
- .posts-content,
- .renting-content,
- .work-content,
- .shop-content {
- padding: 20rpx 0;
- }
- }
-
- .empty-state {
- padding: 100rpx 0;
- text-align: center;
- }
-
- .loading-state {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 60rpx 0;
-
- text {
- margin-top: 20rpx;
- font-size: 28rpx;
- color: #999;
- }
- }
-
- .load-more-state {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 40rpx 0;
-
- text {
- margin-top: 15rpx;
- font-size: 24rpx;
- color: #666;
- }
- }
-
- .no-more-state {
- padding: 30rpx 0;
- text-align: center;
-
- text {
- font-size: 24rpx;
- color: #ccc;
- }
- }
- </style>
|