|
|
- <template>
- <view class="fans-list-page">
- <navbar title="粉丝列表" leftClick @leftClick="$utils.navigateBack" />
-
- <!-- 标签页切换 -->
- <view class="tabs-container">
- <uv-tabs
- :list="tabsList"
- :current="currentTab"
- :activeStyle="{color: '#333', fontWeight: 600}"
- lineColor="#5baaff"
- lineHeight="6rpx"
- lineWidth="40rpx"
- keyName="name"
- @click="onTabClick"
- />
- </view>
-
- <!-- 用户列表 -->
- <view class="user-list">
- <view
- class="user-item"
- v-for="(user, index) in userList"
- :key="index"
- @click="goToUserProfile(user)"
- >
- <view class="user-avatar">
- <image :src="user.headImage" mode="aspectFill"></image>
- </view>
-
- <view class="user-info">
- <view class="user-name">{{ user.nickName }}</view>
- <view class="user-desc">
- <view class="user-tags">
- <text class="tag" v-if="user.sex">{{ user.sex }}</text>
- <text class="tag" v-if="user.address">{{ user.address }}</text>
- <text class="auth-tag" v-if="user.idCardOpen">{{ getAuthText(user.idCardOpen) }}</text>
- </view>
- </view>
- </view>
-
- <view class="user-action" v-if="!isCurrentUserPage">
- <button
- class="follow-btn"
- :class="{followed: user.isFollowed}"
- @click.stop="toggleFollow(user, index)"
- >
- {{ user.isFollowed ? '已关注' : '关注' }}
- </button>
- </view>
- </view>
- </view>
-
- <!-- 空状态 -->
- <view v-if="!loading && userList.length === 0" class="empty-state">
- <uv-empty
- :text="emptyText"
- icon="account"
- iconSize="120"
- ></uv-empty>
- </view>
-
- <!-- 加载状态 -->
- <view v-if="loading" class="loading-state">
- <uv-loading-icon size="40"></uv-loading-icon>
- <text>加载中...</text>
- </view>
- </view>
- </template>
-
- <script>
- import { mapState } from 'vuex'
-
- export default {
- data() {
- return {
- userId: '', // 用户ID
- type: 'fans', // fans: 粉丝, following: 关注
- currentTab: 0,
- tabsList: [
- { name: '粉丝', type: 'fans' },
- { name: '关注', type: 'following' }
- ],
- userList: [], // 用户列表
- loading: false,
- // 模拟数据
- mockFansData: [
- {
- id: '1',
- nickName: '小美同学',
- headImage: 'https://picsum.photos/100/100?random=1',
- sex: '女',
- address: '北京',
- idCardOpen: 1,
- isFollowed: false
- },
- {
- id: '2',
- nickName: '程序员小王',
- headImage: 'https://picsum.photos/100/100?random=2',
- sex: '男',
- address: '上海',
- idCardOpen: 2,
- isFollowed: true
- },
- {
- id: '3',
- nickName: '设计师小李',
- headImage: 'https://picsum.photos/100/100?random=3',
- sex: '女',
- address: '深圳',
- idCardOpen: 0,
- isFollowed: false
- },
- {
- id: '4',
- nickName: '产品经理老张',
- headImage: 'https://picsum.photos/100/100?random=4',
- sex: '男',
- address: '广州',
- idCardOpen: 1,
- isFollowed: true
- },
- {
- id: '5',
- nickName: '运营小姐姐',
- headImage: 'https://picsum.photos/100/100?random=5',
- sex: '女',
- address: '杭州',
- idCardOpen: 2,
- isFollowed: false
- },
- {
- id: '6',
- nickName: '前端工程师',
- headImage: 'https://picsum.photos/100/100?random=6',
- sex: '男',
- address: '成都',
- idCardOpen: 1,
- isFollowed: true
- },
- {
- id: '7',
- nickName: 'UI设计师',
- headImage: 'https://picsum.photos/100/100?random=7',
- sex: '女',
- address: '武汉',
- idCardOpen: 0,
- isFollowed: false
- },
- {
- id: '8',
- nickName: '后端大神',
- headImage: 'https://picsum.photos/100/100?random=8',
- sex: '男',
- address: '西安',
- idCardOpen: 2,
- isFollowed: true
- }
- ],
- mockFollowingData: [
- {
- id: '9',
- nickName: '技术大牛',
- headImage: 'https://picsum.photos/100/100?random=9',
- sex: '男',
- address: '北京',
- idCardOpen: 2,
- isFollowed: true
- },
- {
- id: '10',
- nickName: '设计总监',
- headImage: 'https://picsum.photos/100/100?random=10',
- sex: '女',
- address: '上海',
- idCardOpen: 2,
- isFollowed: true
- },
- {
- id: '11',
- nickName: '产品总监',
- headImage: 'https://picsum.photos/100/100?random=11',
- sex: '男',
- address: '深圳',
- idCardOpen: 1,
- isFollowed: true
- },
- {
- id: '12',
- nickName: '运营总监',
- headImage: 'https://picsum.photos/100/100?random=12',
- sex: '女',
- address: '广州',
- idCardOpen: 2,
- isFollowed: true
- },
- {
- id: '13',
- nickName: '架构师',
- headImage: 'https://picsum.photos/100/100?random=13',
- sex: '男',
- address: '杭州',
- idCardOpen: 1,
- isFollowed: true
- },
- {
- id: '14',
- nickName: '资深设计师',
- headImage: 'https://picsum.photos/100/100?random=14',
- sex: '女',
- address: '成都',
- idCardOpen: 2,
- isFollowed: true
- }
- ]
- }
- },
- computed: {
- ...mapState(['userInfo']),
-
- // 页面标题
- pageTitle() {
- return this.type === 'fans' ? '粉丝列表' : '关注列表'
- },
-
- // 空状态文本
- emptyText() {
- return this.type === 'fans' ? '暂无粉丝' : '暂无关注'
- },
-
- // 是否是当前用户的页面
- isCurrentUserPage() {
- return this.userId === this.userInfo.id
- }
- },
- onLoad(options) {
- this.userId = options.userId || this.userInfo.id
- this.type = options.type || 'fans'
-
- // 设置初始tab
- this.currentTab = this.type === 'fans' ? 0 : 1
-
- this.loadUserList()
- },
- onPullDownRefresh() {
- this.loadUserList()
- },
- methods: {
- // 返回上一页
- goBack() {
- uni.navigateBack()
- },
-
- // 标签页切换
- onTabClick(item) {
- this.currentTab = item.index
- this.type = item.type
- this.loadUserList()
- },
-
- // 获取认证文本
- getAuthText(status) {
- const authTexts = ['审核中', '个人认证', '店铺认证']
- return authTexts[status] || '未认证'
- },
-
- // 跳转到用户主页
- goToUserProfile(user) {
- uni.navigateTo({
- url: `/pages_order/profile/userProfile?userId=${user.id}`
- })
- },
-
- // 切换关注状态
- toggleFollow(user, index) {
- if (!uni.getStorageSync('token')) {
- uni.showToast({
- title: '请先登录',
- icon: 'none'
- })
- return
- }
-
- const isFollowed = !user.isFollowed
-
- // 模拟API调用
- setTimeout(() => {
- // 更新本地数据
- this.userList[index].isFollowed = isFollowed
-
- // 同时更新模拟数据源
- if (this.type === 'fans') {
- const mockIndex = this.mockFansData.findIndex(item => item.id === user.id)
- if (mockIndex !== -1) {
- this.mockFansData[mockIndex].isFollowed = isFollowed
- }
- } else {
- const mockIndex = this.mockFollowingData.findIndex(item => item.id === user.id)
- if (mockIndex !== -1) {
- this.mockFollowingData[mockIndex].isFollowed = isFollowed
- }
- }
-
- uni.showToast({
- title: isFollowed ? '关注成功' : '取消关注',
- icon: 'success'
- })
- }, 500)
- },
-
- // 加载用户列表
- loadUserList() {
- this.loading = true
-
- // 模拟网络延迟
- setTimeout(() => {
- this.loading = false
- uni.stopPullDownRefresh()
-
- // 使用模拟数据
- if (this.type === 'fans') {
- this.userList = [...this.mockFansData]
- } else {
- this.userList = [...this.mockFollowingData]
- }
-
- // 模拟API调用成功
- console.log(`加载${this.type === 'fans' ? '粉丝' : '关注'}列表成功`)
- }, 1000)
- }
- }
- }
- </script>
-
- <style scoped lang="scss">
- .fans-list-page {
- background-color: #f5f5f5;
- min-height: 100vh;
- }
-
- .navbar {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- z-index: 100;
- height: 88rpx;
- background: #fff;
- border-bottom: 1rpx solid #eee;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 0 30rpx;
- padding-top: var(--status-bar-height, 44rpx);
-
- .nav-title {
- color: #333;
- font-size: 32rpx;
- font-weight: 600;
- }
-
- .nav-left, .nav-right {
- width: 60rpx;
- height: 60rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
-
- .tabs-container {
- margin-top: 88rpx;
- padding-top: var(--status-bar-height, 44rpx);
- background: #fff;
- border-bottom: 1rpx solid #eee;
- padding-left: 20rpx;
- padding-right: 20rpx;
- }
-
- .user-list {
- padding: 20rpx;
-
- .user-item {
- display: flex;
- align-items: center;
- background: #fff;
- padding: 30rpx;
- margin-bottom: 20rpx;
- border-radius: 16rpx;
- box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
-
- .user-avatar {
- width: 100rpx;
- height: 100rpx;
- border-radius: 50rpx;
- overflow: hidden;
- margin-right: 30rpx;
-
- image {
- width: 100%;
- height: 100%;
- }
- }
-
- .user-info {
- flex: 1;
-
- .user-name {
- font-size: 32rpx;
- font-weight: 600;
- color: #333;
- margin-bottom: 12rpx;
- }
-
- .user-desc {
- .user-tags {
- display: flex;
- flex-wrap: wrap;
- gap: 8rpx;
-
- .tag {
- background: #f0f0f0;
- color: #666;
- padding: 4rpx 12rpx;
- border-radius: 12rpx;
- font-size: 20rpx;
- }
-
- .auth-tag {
- background: #52c41a;
- color: #fff;
- padding: 4rpx 12rpx;
- border-radius: 12rpx;
- font-size: 20rpx;
- }
- }
- }
- }
-
- .user-action {
- .follow-btn {
- background: #5baaff;
- color: #fff;
- border: none;
- padding: 16rpx 32rpx;
- border-radius: 30rpx;
- font-size: 24rpx;
-
- &.followed {
- background: #f0f0f0;
- color: #666;
- }
- }
- }
- }
- }
-
- .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;
- }
- }
- </style>
|