diff --git a/app/(tabs)/owner.tsx b/app/(tabs)/owner.tsx
index 19dcac5..1486e8a 100644
--- a/app/(tabs)/owner.tsx
+++ b/app/(tabs)/owner.tsx
@@ -5,21 +5,19 @@ 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 CarouselComponent from '@/components/owner/carousel';
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 { 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, ScrollView, StyleSheet, View } from 'react-native';
+import { FlatList, StyleSheet, View } from 'react-native';
import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function OwnerPage() {
@@ -97,27 +95,8 @@ export default function OwnerPage() {
- {/* 数据统计 */}
-
-
{/* 分类 */}
-
-
- {countData?.counter?.category_count && Object.entries(countData?.counter?.category_count).map(([key, value], index) => {
- return (
-
- )
- })}
-
-
+
{/* 作品数据 */}
diff --git a/components/owner/carousel.tsx b/components/owner/carousel.tsx
new file mode 100644
index 0000000..9d2e76d
--- /dev/null
+++ b/components/owner/carousel.tsx
@@ -0,0 +1,127 @@
+import { Counter, UserCountData } from "@/types/user";
+import * as React from "react";
+import { Dimensions, StyleSheet, View } from "react-native";
+import { useSharedValue } from "react-native-reanimated";
+import Carousel, {
+ ICarouselInstance
+} 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 ref = React.useRef(null);
+ const progress = useSharedValue(0);
+ const [carouselDataValue, setCarouselDataValue] = React.useState([]);
+ 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
+ {Object?.entries(data)?.filter(([key]) => key !== 'cover_url')?.map((item, index) => (
+
+ {item[0]}
+ {item[1]}
+
+ ))}
+
+ }
+
+ React.useEffect(() => {
+ if (data) {
+ dataHandle()
+ }
+ }, [data]);
+
+ return (
+
+ item?.key === 'total_count') - 1 || 0}
+ renderItem={({ item }) => {
+ if (item?.key === 'total_count') {
+ return totleItem(item.value)
+ }
+ return 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,
+ })
+ }}
+ />
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: "#FFB645",
+ padding: 16,
+ borderRadius: 20,
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "space-between",
+ height: '100%',
+ },
+ item: {
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "space-between",
+ paddingVertical: 8
+ },
+ title: {
+ color: "#4C320C",
+ fontWeight: "700",
+ fontSize: 14,
+ },
+ number: {
+ color: "#fff",
+ fontWeight: "700",
+ fontSize: 32,
+ textAlign: 'right',
+ flex: 1,
+ paddingTop: 8
+ }
+})
+
+export default CarouselComponent;
\ No newline at end of file
diff --git a/components/owner/category.tsx b/components/owner/category.tsx
index 06a0a15..f3f79ce 100644
--- a/components/owner/category.tsx
+++ b/components/owner/category.tsx
@@ -14,8 +14,11 @@ const CategoryComponent = ({ title, data, bgSvg, style }: CategoryProps) => {
@@ -37,11 +40,12 @@ const styles = StyleSheet.create({
borderRadius: 32,
overflow: 'hidden',
position: 'relative',
+ aspectRatio: 1,
},
backgroundContainer: {
...StyleSheet.absoluteFillObject,
- width: '100%',
- height: '100%',
+ width: "100%",
+ height: "100%",
},
overlay: {
...StyleSheet.absoluteFillObject,
diff --git a/package-lock.json b/package-lock.json
index 2d3c8d1..66a15e1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -60,6 +60,7 @@
"react-native-picker-select": "^9.3.1",
"react-native-progress": "^5.0.1",
"react-native-reanimated": "~3.17.4",
+ "react-native-reanimated-carousel": "^4.0.2",
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
@@ -14826,6 +14827,18 @@
"react-native": "*"
}
},
+ "node_modules/react-native-reanimated-carousel": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.2.tgz",
+ "integrity": "sha512-vNpCfPlFoOVKHd+oB7B0luoJswp+nyz0NdJD8+LCrf25JiNQXfM22RSJhLaksBHqk3fm8R4fKWPNcfy5w7wL1Q==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-native": ">=0.70.3",
+ "react-native-gesture-handler": ">=2.9.0",
+ "react-native-reanimated": ">=3.0.0"
+ }
+ },
"node_modules/react-native-reanimated/node_modules/react-native-is-edge-to-edge": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.1.7.tgz",
diff --git a/package.json b/package.json
index 50c1a34..bf8c777 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"expo-audio": "~0.4.8",
"expo-background-task": "^0.2.8",
"expo-blur": "~14.1.5",
+ "expo-clipboard": "~7.1.5",
"expo-constants": "~17.1.6",
"expo-dev-client": "~5.2.4",
"expo-device": "~7.1.4",
@@ -33,6 +34,7 @@
"expo-haptics": "~14.1.4",
"expo-image-manipulator": "~13.1.7",
"expo-image-picker": "~16.1.4",
+ "expo-linear-gradient": "~14.1.5",
"expo-linking": "~7.1.7",
"expo-localization": "^16.1.5",
"expo-location": "~18.1.5",
@@ -64,6 +66,7 @@
"react-native-picker-select": "^9.3.1",
"react-native-progress": "^5.0.1",
"react-native-reanimated": "~3.17.4",
+ "react-native-reanimated-carousel": "^4.0.2",
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
@@ -72,9 +75,7 @@
"react-native-uuid": "^2.0.3",
"react-native-web": "~0.20.0",
"react-native-webview": "13.13.5",
- "react-redux": "^9.2.0",
- "expo-clipboard": "~7.1.5",
- "expo-linear-gradient": "~14.1.5"
+ "react-redux": "^9.2.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
diff --git a/types/user.ts b/types/user.ts
index ff1665d..bb3a291 100644
--- a/types/user.ts
+++ b/types/user.ts
@@ -12,7 +12,7 @@ export interface User {
avatar_file_url?: string
}
-interface UserCountData {
+export interface UserCountData {
video_count: number,
photo_count: number,
live_count: number,
@@ -31,7 +31,7 @@ export interface CountData {
}
}
-interface Counter {
+export interface Counter {
user_id: number,
total_count: UserCountData,
category_count: {