jinyaqiu 828e84710f
All checks were successful
Dev Deploy / Explore-Gitea-Actions (push) Successful in 24s
feat: 个人中心
2025-07-14 10:42:59 +08:00

211 lines
7.6 KiB
TypeScript

import ConversationsSvg from '@/assets/icons/svg/conversations.svg';
import PointsSvg from '@/assets/icons/svg/points.svg';
import StoriesSvg from '@/assets/icons/svg/stories.svg';
import UsedStorageSvg from '@/assets/icons/svg/usedStorage.svg';
import AskNavbar from '@/components/layout/ask';
import AlbumComponent from '@/components/owner/album';
import CategoryComponent from '@/components/owner/category';
import CountComponent from '@/components/owner/count';
import CreateCountComponent from '@/components/owner/createCount';
import Ranking from '@/components/owner/ranking';
import ResourceComponent from '@/components/owner/resource';
import SettingModal from '@/components/owner/setting';
import UserInfo from '@/components/owner/userName';
import { formatDuration } from '@/components/utils/time';
import { fetchApi } from '@/lib/server-api-util';
import { CountData, UserInfoDetails } from '@/types/user';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ScrollView, StyleSheet, View } from 'react-native';
import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function OwnerPage() {
const insets = useSafeAreaInsets();
const { t } = useTranslation();
// 设置弹窗
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(() => {
// const interval = setInterval(() => {
// getCountData();
// }, 1000);
// return () => clearInterval(interval);
// }, []);
// 初始化获取用户信息
useEffect(() => {
getUserInfo();
getCountData();
}, []);
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={{ flexGrow: 1, gap: 16, marginHorizontal: 16 }}
>
{/* 用户信息 */}
<UserInfo userInfo={userInfoDetails} />
{/* 设置栏 */}
<AlbumComponent setModalVisible={setModalVisible} />
{/* 资源数据 */}
<View style={styles.resourceContainer}>
<ResourceComponent title={t("generalSetting.usedStorage", { ns: "personal" })} subtitle={`${countData?.counter?.total_count?.video_count || 0}videos/${countData?.counter?.total_count?.photo_count || 0}photos`} data={{ all: countData.total_bytes, used: countData.used_bytes }} icon={<UsedStorageSvg />} style={{ flex: 1 }} isFormatBytes={true} />
<ResourceComponent title={t("generalSetting.remainingPoints", { ns: "personal" })} data={{ all: userInfoDetails.total_points, used: userInfoDetails.remain_points }} icon={<PointsSvg />} style={{ flex: 1 }} />
</View>
{/* 数据统计 */}
<CountComponent
data={[{ title: t("generalSetting.totalVideo", { ns: "personal" }), number: countData?.counter?.total_count?.video_count || 0 }, { title: t("generalSetting.totalPhoto", { ns: "personal" }), number: countData?.counter?.total_count?.photo_count || 0 }, { title: t("generalSetting.live", { ns: "personal" }), number: countData?.counter?.total_count?.live_count || 0 }, { title: t("generalSetting.videoLength", { ns: "personal" }), number: formatDuration(countData?.counter?.total_count?.video_length || 0) }]}
/>
{/* 分类 */}
<View style={{ height: 145 }}>
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 16 }} >
{countData?.counter?.category_count && Object.entries(countData?.counter?.category_count).map(([key, value], index) => {
return (
<CategoryComponent
key={index}
title={key}
data={[{ title: 'Video', number: value.video_count }, { title: 'Photo', number: value.photo_count }, { title: 'Length', number: formatDuration(value.video_length || 0) }]}
bgSvg={value.cover_url}
style={{ aspectRatio: 1, flex: 1 }}
/>
)
})}
</ScrollView>
</View>
{/* 作品数据 */}
<View className='flex flex-row justify-between gap-[1rem]'>
<CreateCountComponent title={t("generalSetting.storiesCreated", { ns: "personal" })} icon={<StoriesSvg />} number={userInfoDetails.stories_count} />
<CreateCountComponent title={t("generalSetting.conversationsWithMemo", { ns: "personal" })} icon={<ConversationsSvg />} number={userInfoDetails.conversations_count} />
</View>
{/* 排行榜 */}
<Ranking data={userInfoDetails.title_rankings} />
</ScrollView>
{/* 设置弹窗 */}
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
{/* 导航栏 */}
<AskNavbar />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingBottom: 86,
},
resourceContainer: {
flexDirection: 'row',
gap: 16
},
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',
},
});