2025-08-01 10:49:16 +08:00

167 lines
5.7 KiB
TypeScript

import ImgTotalSvg from "@/assets/icons/svg/imgTotal.svg";
import LiveTotalSvg from "@/assets/icons/svg/liveTotal.svg";
import TimeTotalSvg from "@/assets/icons/svg/timeTotal.svg";
import VideoTotalSvg from "@/assets/icons/svg/videoTotal.svg";
import { Counter, UserCountData } from "@/types/user";
import * as React from "react";
import { Dimensions, StyleSheet, View, ViewStyle } from "react-native";
import Carousel from "react-native-reanimated-carousel";
import { ThemedText } from "../ThemedText";
import { formatDuration } from "../utils/time";
import CategoryComponent from "./category";
interface Props {
data: Counter
}
interface CarouselData {
key: string,
value: UserCountData
}[]
const width = Dimensions.get("window").width;
function CarouselComponent(props: Props) {
const { data } = props;
const [carouselDataValue, setCarouselDataValue] = React.useState<CarouselData[]>([]);
const dataHandle = () => {
const carouselData = { ...data?.category_count, total_count: data?.total_count }
// 1. 转换为数组并过滤掉 'total'
const entries = Object?.entries(carouselData)
?.filter(([key]) => key !== 'total_count')
?.map(([key, value]) => ({ key, value }));
// 2. 找到 total 数据
const totalEntry = {
key: 'total_count',
value: carouselData?.total_count
};
// 3. 插入到中间位置
const middleIndex = Math.floor((entries || [])?.length / 2);
entries?.splice(middleIndex, 0, totalEntry);
setCarouselDataValue(entries)
return entries;
}
const totleItem = (data: UserCountData) => {
return <View style={styles.container}>
{Object?.entries(data)?.filter(([key]) => key !== 'cover_url')?.map((item, index) => (
<View style={styles.item} key={index}>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: "75%", overflow: 'hidden' }}>
<View style={styles.icon}>
{
item?.[0]?.includes('video_count') ? <VideoTotalSvg /> : item?.[0]?.includes('photo') ? <ImgTotalSvg /> : item?.[0]?.includes('live') ? <LiveTotalSvg /> : <TimeTotalSvg />
}
</View>
<ThemedText style={styles.title}>{item[0]}</ThemedText>
</View>
<ThemedText style={styles.number}>{item[1]}</ThemedText>
</View>
))}
</View>
}
React.useEffect(() => {
if (data) {
dataHandle()
}
}, [data]);
return (
<View style={{ flex: 1 }}>
<Carousel
width={width}
height={width * 0.75}
data={carouselDataValue || []}
mode="parallax"
defaultIndex={
carouselDataValue?.length
? Math.max(0, Math.min(
carouselDataValue.length - 1,
carouselDataValue.findIndex((item) => item?.key === 'total_count') - 1
))
: 0
}
modeConfig={{
parallaxScrollingScale: 1,
parallaxScrollingOffset: 150,
parallaxAdjacentItemScale: 0.7
}}
renderItem={({ item, index }) => {
const style: ViewStyle = {
width: width,
height: width * 0.8,
alignItems: "center",
};
return (
<View key={index} style={style}>
{item?.key === 'total_count' ? (
totleItem(item.value)
) : (
<View style={{ flex: 1, width: width * 0.65 }}>
{CategoryComponent({
title: item?.key,
data: [
{ title: 'Video', number: item?.value?.video_count },
{ title: 'Photo', number: item?.value?.photo_count },
{ title: 'Length', number: formatDuration(item?.value?.video_length || 0) }
],
bgSvg: item?.value?.cover_url,
})}
</View>
)}
</View>
)
}}
/>
</View>
);
}
const styles = StyleSheet.create({
icon: {
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
borderRadius: 32,
padding: 4
},
container: {
backgroundColor: "#FFB645",
paddingVertical: 8,
paddingHorizontal: 16,
borderRadius: 16,
display: "flex",
flexDirection: "column",
position: 'relative',
width: width * 0.7
},
image: {
position: 'absolute',
bottom: 0,
right: 0,
left: 0,
alignItems: 'center',
justifyContent: 'flex-end',
},
item: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 16
},
title: {
color: "#4C320C",
fontWeight: "500",
fontSize: 22,
},
number: {
color: "#fff",
fontWeight: "700",
fontSize: 26,
textAlign: 'left',
flex: 1,
paddingTop: 8
}
})
export default CarouselComponent;