1
This commit is contained in:
271
src/user_pages/follow/index.tsx
Normal file
271
src/user_pages/follow/index.tsx
Normal file
@@ -0,0 +1,271 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import CustomNavbar from '@/components/CustomNavbar';
|
||||
import FollowUserCard from '@/components/FollowUserCard';
|
||||
import { FollowService, FollowUser } from '@/services/followService';
|
||||
import { withAuth } from '@/components';
|
||||
import './index.scss';
|
||||
|
||||
// 标签页类型
|
||||
type TabType = 'mutual_follow' | 'following' | 'follower' | 'recommend';
|
||||
|
||||
// 标签页配置
|
||||
const TAB_CONFIG = [
|
||||
{ key: 'mutual_follow' as TabType, label: '互相关注' },
|
||||
{ key: 'following' as TabType, label: '关注' },
|
||||
{ key: 'follower' as TabType, label: '粉丝' },
|
||||
{ key: 'recommend' as TabType, label: '推荐' }
|
||||
];
|
||||
|
||||
const FollowPage: React.FC = () => {
|
||||
// 获取页面参数,支持指定默认标签页
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const default_tab = (instance.router?.params?.tab as TabType) || 'mutual_follow';
|
||||
|
||||
// 当前激活的标签页 - 根据设计稿默认显示互相关注
|
||||
const [active_tab, set_active_tab] = useState<TabType>(default_tab);
|
||||
|
||||
// 用户列表数据
|
||||
const [user_lists, set_user_lists] = useState<Record<TabType, FollowUser[]>>({
|
||||
mutual_follow: [],
|
||||
following: [],
|
||||
follower: [],
|
||||
recommend: []
|
||||
});
|
||||
|
||||
// 加载状态 - 根据默认标签页设置初始加载状态
|
||||
const [loading_states, set_loading_states] = useState<Record<TabType, boolean>>(() => ({
|
||||
mutual_follow: default_tab === 'mutual_follow',
|
||||
following: default_tab === 'following',
|
||||
follower: default_tab === 'follower',
|
||||
recommend: default_tab === 'recommend'
|
||||
}));
|
||||
|
||||
// 分页信息
|
||||
const [page_info, set_page_info] = useState<Record<TabType, { page: number; total: number; has_more: boolean }>>(() => ({
|
||||
mutual_follow: { page: 1, total: 0, has_more: true },
|
||||
following: { page: 1, total: 0, has_more: true },
|
||||
follower: { page: 1, total: 0, has_more: true },
|
||||
recommend: { page: 1, total: 0, has_more: true }
|
||||
}));
|
||||
|
||||
// 加载用户列表
|
||||
const load_user_list = async (tab: TabType, is_refresh: boolean = false) => {
|
||||
const current_page = is_refresh ? 1 : page_info[tab].page;
|
||||
const page_size = tab === 'recommend' ? 10 : 20;
|
||||
|
||||
// 设置加载状态
|
||||
set_loading_states(prev => ({ ...prev, [tab]: true }));
|
||||
|
||||
try {
|
||||
const response = await FollowService.get_follow_list(tab, current_page, page_size);
|
||||
|
||||
// 调试日志
|
||||
console.log(`加载${TAB_CONFIG.find(t => t.key === tab)?.label}数据:`, response);
|
||||
|
||||
// 更新用户列表
|
||||
set_user_lists(prev => ({
|
||||
...prev,
|
||||
[tab]: is_refresh ? response.list : [...(prev[tab] || []), ...response.list]
|
||||
}));
|
||||
|
||||
// 更新分页信息
|
||||
set_page_info(prev => ({
|
||||
...prev,
|
||||
[tab]: {
|
||||
page: current_page + 1,
|
||||
total: response.total,
|
||||
has_more: response.list.length === page_size && (current_page * page_size) < response.total
|
||||
}
|
||||
}));
|
||||
|
||||
} catch (error) {
|
||||
console.error(`加载${TAB_CONFIG.find(t => t.key === tab)?.label}列表失败:`, error);
|
||||
Taro.showToast({
|
||||
title: '加载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
set_loading_states(prev => ({ ...prev, [tab]: false }));
|
||||
}
|
||||
};
|
||||
|
||||
// 处理标签页切换
|
||||
const handle_tab_change = (tab: TabType) => {
|
||||
if (tab === active_tab) return;
|
||||
|
||||
set_active_tab(tab);
|
||||
|
||||
// 如果该标签页还没有数据,则加载
|
||||
if (user_lists[tab].length === 0) {
|
||||
load_user_list(tab, true);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理关注状态变化
|
||||
const handle_follow_change = async (user_id: number, is_following: boolean) => {
|
||||
try {
|
||||
if (is_following) {
|
||||
await FollowService.follow_user(user_id);
|
||||
Taro.showToast({
|
||||
title: '关注成功',
|
||||
icon: 'success'
|
||||
});
|
||||
} else {
|
||||
await FollowService.unfollow_user(user_id);
|
||||
Taro.showToast({
|
||||
title: '取消关注成功',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
|
||||
// 更新用户列表中的关注状态
|
||||
set_user_lists(prev => {
|
||||
const new_lists = { ...prev };
|
||||
|
||||
// 更新所有标签页中的用户状态
|
||||
Object.keys(new_lists).forEach(tab_key => {
|
||||
const tab = tab_key as TabType;
|
||||
if (new_lists[tab] && Array.isArray(new_lists[tab])) {
|
||||
new_lists[tab] = new_lists[tab].map(user => {
|
||||
if (user.id === user_id) {
|
||||
// 根据操作结果更新状态
|
||||
let new_status = user.follow_status;
|
||||
if (is_following) {
|
||||
if (user.follow_status === 'follower') {
|
||||
new_status = 'mutual_follow';
|
||||
} else if (user.follow_status === 'recommend') {
|
||||
new_status = 'following';
|
||||
}
|
||||
} else {
|
||||
if (user.follow_status === 'mutual_follow') {
|
||||
new_status = 'follower';
|
||||
} else if (user.follow_status === 'following') {
|
||||
new_status = 'recommend';
|
||||
}
|
||||
}
|
||||
return { ...user, follow_status: new_status };
|
||||
}
|
||||
return user;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return new_lists;
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('关注操作失败:', error);
|
||||
Taro.showToast({
|
||||
title: '操作失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 处理下拉刷新
|
||||
const handle_refresh = () => {
|
||||
load_user_list(active_tab, true);
|
||||
};
|
||||
|
||||
// 处理加载更多
|
||||
const handle_load_more = () => {
|
||||
if (page_info[active_tab]?.has_more && !loading_states[active_tab]) {
|
||||
load_user_list(active_tab, false);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化加载
|
||||
useEffect(() => {
|
||||
try {
|
||||
load_user_list(default_tab, true);
|
||||
} catch (error) {
|
||||
console.error('初始化加载失败:', error);
|
||||
Taro.showToast({
|
||||
title: '初始化失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}, [default_tab]);
|
||||
|
||||
return (
|
||||
<View className="follow_page">
|
||||
{/* 自定义导航栏 */}
|
||||
<CustomNavbar>
|
||||
<View className="navbar_content">
|
||||
<View className="navbar_back" onClick={() => Taro.navigateBack()}>
|
||||
<View className="back_icon" />
|
||||
</View>
|
||||
<Text className="navbar_title">球友</Text>
|
||||
<View className="navbar_action">
|
||||
<View className="action_icon" />
|
||||
</View>
|
||||
</View>
|
||||
</CustomNavbar>
|
||||
|
||||
{/* 标签页导航 */}
|
||||
<View className="tab_navigation">
|
||||
{TAB_CONFIG.map(tab => (
|
||||
<View
|
||||
key={tab.key}
|
||||
className={`tab_item ${active_tab === tab.key ? 'active' : ''}`}
|
||||
onClick={() => handle_tab_change(tab.key)}
|
||||
>
|
||||
<Text className="tab_text">{tab.label}</Text>
|
||||
{tab.key === 'recommend' && (
|
||||
<View className="recommend_icon">
|
||||
{/* 推荐图标 SVG */}
|
||||
<View className="icon_container">
|
||||
<View className="star_icon" />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* 用户列表 */}
|
||||
<ScrollView
|
||||
className="user_list_container"
|
||||
scrollY
|
||||
refresherEnabled
|
||||
refresherTriggered={loading_states[active_tab]}
|
||||
onRefresherRefresh={handle_refresh}
|
||||
onScrollToLower={handle_load_more}
|
||||
lowerThreshold={100}
|
||||
>
|
||||
{user_lists[active_tab]?.map(user => (
|
||||
<FollowUserCard
|
||||
key={user.id}
|
||||
user={user}
|
||||
onFollowChange={handle_follow_change}
|
||||
/>
|
||||
)) || []}
|
||||
|
||||
{/* 加载状态提示 */}
|
||||
{loading_states[active_tab] && (user_lists[active_tab]?.length || 0) === 0 && (
|
||||
<View className="loading_tip">
|
||||
<Text>加载中...</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 空状态提示 */}
|
||||
{!loading_states[active_tab] && (user_lists[active_tab]?.length || 0) === 0 && (
|
||||
<View className="empty_tip">
|
||||
<Text>暂无{TAB_CONFIG.find(t => t.key === active_tab)?.label}用户</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 加载更多提示 */}
|
||||
{(user_lists[active_tab]?.length || 0) > 0 && !page_info[active_tab]?.has_more && (
|
||||
<View className="load_more_tip">
|
||||
<Text>已加载全部</Text>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default withAuth(FollowPage);
|
||||
Reference in New Issue
Block a user