2025-07-31 19:40:28 +08:00

227 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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',
},
});