227 lines
6.8 KiB
TypeScript
227 lines
6.8 KiB
TypeScript
import ConversationsSvg from '@/assets/icons/svg/conversations.svg';
|
||
import StoriesSvg from '@/assets/icons/svg/stories.svg';
|
||
import AskNavbar from '@/components/layout/ask';
|
||
import CarouselComponent from '@/components/owner/carousel';
|
||
import CreateCountComponent from '@/components/owner/createCount';
|
||
import Ranking from '@/components/owner/ranking';
|
||
import MemberCard from '@/components/owner/rights/memberCard';
|
||
import SettingModal from '@/components/owner/setting';
|
||
import UserInfo from '@/components/owner/userName';
|
||
import { checkAuthStatus } from '@/lib/auth';
|
||
import { fetchApi } from '@/lib/server-api-util';
|
||
import { CountData, UserInfoDetails } from '@/types/user';
|
||
import { useRouter } from 'expo-router';
|
||
import { useEffect, useState } from 'react';
|
||
import { useTranslation } from 'react-i18next';
|
||
import { FlatList, StyleSheet, View } from 'react-native';
|
||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||
|
||
export default function OwnerPage() {
|
||
const insets = useSafeAreaInsets();
|
||
const { t } = useTranslation();
|
||
const router = useRouter();
|
||
|
||
useEffect(() => {
|
||
const checkAuth = async () => {
|
||
const authStatus = await checkAuthStatus(router);
|
||
if (!authStatus) {
|
||
router.push('/login');
|
||
}
|
||
};
|
||
checkAuth();
|
||
}, [router]);
|
||
|
||
// 设置弹窗
|
||
const [modalVisible, setModalVisible] = useState(false);
|
||
|
||
|
||
// 数据统计
|
||
const [countData, setCountData] = useState<CountData>({} as CountData);
|
||
|
||
// 获取数量统计 --- 需要轮询
|
||
const getCountData = () => {
|
||
fetchApi("/material/statistics").then((res) => {
|
||
setCountData(res as CountData);
|
||
});
|
||
|
||
}
|
||
|
||
// 获取用户信息
|
||
const [userInfoDetails, setUserInfoDetails] = useState<UserInfoDetails>({} as UserInfoDetails);
|
||
const getUserInfo = () => {
|
||
fetchApi("/membership/personal-center-info").then((res) => {
|
||
setUserInfoDetails(res as UserInfoDetails);
|
||
})
|
||
}
|
||
// 设计轮询获取数量统计
|
||
useEffect(() => {
|
||
// 将轮询间隔增加到5秒,减少服务器压力和电池消耗
|
||
const interval = setInterval(() => {
|
||
getCountData();
|
||
}, 5000);
|
||
return () => clearInterval(interval);
|
||
}, []);
|
||
|
||
// 初始化获取用户信息
|
||
useEffect(() => {
|
||
getUserInfo();
|
||
getCountData();
|
||
}, []);
|
||
|
||
return (
|
||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||
<FlatList
|
||
data={[]} // 空数据,因为我们只需要渲染一次
|
||
renderItem={null} // 不需要渲染项目
|
||
contentContainerStyle={styles.contentContainer}
|
||
showsVerticalScrollIndicator={false}
|
||
ListHeaderComponent={
|
||
<View style={{ gap: 16 }}>
|
||
{/* 用户信息 */}
|
||
<UserInfo userInfo={userInfoDetails} />
|
||
|
||
{/* 会员卡 */}
|
||
<MemberCard pro={userInfoDetails?.membership_level} />
|
||
|
||
{/* 分类 */}
|
||
<View style={{ marginHorizontal: -16, marginBottom: -16 }}>
|
||
<CarouselComponent data={userInfoDetails?.material_counter} />
|
||
</View>
|
||
|
||
{/* 作品数据 */}
|
||
<View className='flex flex-row justify-between gap-[1rem]'>
|
||
<CreateCountComponent title={t("generalSetting.storiesCreated", { ns: "personal" })} icon={<StoriesSvg width={30} height={30} />} number={userInfoDetails.stories_count} />
|
||
<CreateCountComponent title={t("generalSetting.conversationsWithMemo", { ns: "personal" })} icon={<ConversationsSvg width={30} height={30} />} number={userInfoDetails.conversations_count} />
|
||
</View>
|
||
|
||
{/* 排行榜 */}
|
||
<Ranking data={userInfoDetails.title_rankings} />
|
||
</View>
|
||
}
|
||
// 优化性能:添加 getItemLayout
|
||
getItemLayout={(data, index) => (
|
||
{ length: 1000, offset: 1000 * index, index }
|
||
)}
|
||
/>
|
||
{/* 设置弹窗 - 使用条件渲染避免层级冲突 */}
|
||
{modalVisible && (
|
||
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
|
||
)}
|
||
|
||
{/* 导航栏 */}
|
||
<AskNavbar />
|
||
</View>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
backgroundColor: 'white',
|
||
paddingBottom: 86,
|
||
},
|
||
contentContainer: {
|
||
paddingHorizontal: 16,
|
||
},
|
||
resourceContainer: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
backgroundColor: "#4C320C",
|
||
paddingVertical: 8,
|
||
paddingHorizontal: 32,
|
||
borderRadius: 18,
|
||
},
|
||
text: {
|
||
fontSize: 12,
|
||
fontWeight: '700',
|
||
color: '#FFB645',
|
||
},
|
||
secondText: {
|
||
fontSize: 16,
|
||
fontWeight: '700',
|
||
color: '#fff',
|
||
},
|
||
userInfo: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
padding: 16,
|
||
},
|
||
medal: {
|
||
marginLeft: 16,
|
||
},
|
||
backButton: {
|
||
padding: 4,
|
||
},
|
||
headerTitle: {
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
color: '#333',
|
||
},
|
||
content: {
|
||
flex: 1,
|
||
},
|
||
profileSection: {
|
||
backgroundColor: '#fff',
|
||
padding: 20,
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
marginBottom: 10,
|
||
},
|
||
avatarContainer: {
|
||
marginRight: 16,
|
||
},
|
||
avatar: {
|
||
width: 70,
|
||
height: 70,
|
||
borderRadius: 35,
|
||
borderWidth: 2,
|
||
borderColor: '#FFD38D',
|
||
},
|
||
profileInfo: {
|
||
flex: 1,
|
||
},
|
||
userName: {
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
color: '#333',
|
||
marginBottom: 4,
|
||
},
|
||
userPhone: {
|
||
fontSize: 14,
|
||
color: '#666',
|
||
},
|
||
editButton: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
padding: 8,
|
||
borderWidth: 1,
|
||
borderColor: '#eee',
|
||
borderRadius: 15,
|
||
},
|
||
editButtonText: {
|
||
marginLeft: 4,
|
||
color: '#666',
|
||
fontSize: 14,
|
||
},
|
||
menuContainer: {
|
||
backgroundColor: '#fff',
|
||
paddingHorizontal: 16,
|
||
},
|
||
menuItem: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
paddingVertical: 16,
|
||
borderBottomWidth: 1,
|
||
borderBottomColor: '#f5f5f5',
|
||
},
|
||
menuItemText: {
|
||
flex: 1,
|
||
marginLeft: 12,
|
||
fontSize: 16,
|
||
color: '#333',
|
||
},
|
||
arrowIcon: {
|
||
marginLeft: 'auto',
|
||
},
|
||
}); |