From 1ccdc2335592dcddadb88fd0a1e05ef9c0036d19 Mon Sep 17 00:00:00 2001 From: imeepos Date: Thu, 29 Jan 2026 16:20:01 +0800 Subject: [PATCH] fix: bug --- app/(tabs)/message.tsx | 11 +- app/(tabs)/my.tsx | 473 +++++++++++++++++------------ components/message/MessageCard.tsx | 12 - hooks/use-messages.ts | 16 +- hooks/use-user-favorites.ts | 16 +- hooks/use-user-likes.ts | 16 +- 6 files changed, 315 insertions(+), 229 deletions(-) diff --git a/app/(tabs)/message.tsx b/app/(tabs)/message.tsx index 64abae3..8ae1399 100644 --- a/app/(tabs)/message.tsx +++ b/app/(tabs)/message.tsx @@ -155,12 +155,10 @@ export default function MessageScreen() { // Render message item const renderMessageItem = useCallback(({ item }: { item: Message }) => ( - handleDeleteMessage(item.id)}> - - + ), [handleDeleteMessage, handleMessagePress]) // Render list footer @@ -288,6 +286,7 @@ const styles = StyleSheet.create({ listContent: { paddingHorizontal: 4, paddingTop: 12, + paddingBottom: 100, }, emptyListContent: { flex: 1, diff --git a/app/(tabs)/my.tsx b/app/(tabs)/my.tsx index 24a2454..23b7c04 100644 --- a/app/(tabs)/my.tsx +++ b/app/(tabs)/my.tsx @@ -32,7 +32,6 @@ import { MySkeleton } from '@/components/skeleton/MySkeleton' import { TabNavigation } from '@/components/blocks/home/TabNavigation' import { useUserBalance } from '@/hooks/use-user-balance' -import { KeyboardAwareScrollView } from 'react-native-keyboard-controller' const { width: screenWidth } = Dimensions.get('window') const GALLERY_GAP = 2 @@ -136,9 +135,13 @@ export default function My() { // 下拉刷新状态 const [refreshing, setRefreshing] = useState(false) + const [favoritesRefreshing, setFavoritesRefreshing] = useState(false) + const [likesRefreshing, setLikesRefreshing] = useState(false) // 防止重复触发加载更多 const isLoadingMoreRef = useRef(false) + const isFavoritesLoadingMoreRef = useRef(false) + const isLikesLoadingMoreRef = useRef(false) // 下拉刷新处理 const onRefresh = useCallback(async () => { @@ -150,6 +153,26 @@ export default function My() { } }, [refetch]) + // 收藏Tab下拉刷新处理 + const onFavoritesRefresh = useCallback(async () => { + setFavoritesRefreshing(true) + try { + await favoritesRefetch() + } finally { + setFavoritesRefreshing(false) + } + }, [favoritesRefetch]) + + // 点赞Tab下拉刷新处理 + const onLikesRefresh = useCallback(async () => { + setLikesRefreshing(true) + try { + await likesRefetch() + } finally { + setLikesRefreshing(false) + } + }, [likesRefetch]) + // 加载更多处理 const handleScroll = useCallback((event: NativeSyntheticEvent) => { const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent @@ -173,6 +196,40 @@ export default function My() { } }, [loadingMore, hasMore, loadMore, loading]) + // 收藏Tab加载更多处理 + const handleFavoritesScroll = useCallback((event: NativeSyntheticEvent) => { + const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent + const paddingToBottom = 200 + + const isCloseToBottom = + layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom + + if (isCloseToBottom && !favoritesLoadingMore && favoritesHasMore && !favoritesLoading && !isFavoritesLoadingMoreRef.current) { + console.log('🔄 收藏Tab触发加载更多') + isFavoritesLoadingMoreRef.current = true + favoritesLoadMore().finally(() => { + isFavoritesLoadingMoreRef.current = false + }) + } + }, [favoritesLoadingMore, favoritesHasMore, favoritesLoadMore, favoritesLoading]) + + // 点赞Tab加载更多处理 + const handleLikesScroll = useCallback((event: NativeSyntheticEvent) => { + const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent + const paddingToBottom = 200 + + const isCloseToBottom = + layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom + + if (isCloseToBottom && !likesLoadingMore && likesHasMore && !likesLoading && !isLikesLoadingMoreRef.current) { + console.log('🔄 点赞Tab触发加载更多') + isLikesLoadingMoreRef.current = true + likesLoadMore().finally(() => { + isLikesLoadingMoreRef.current = false + }) + } + }, [likesLoadingMore, likesHasMore, likesLoadMore, likesLoading]) + // 处理设置菜单选择 const handleSettingsSelect = async (value: string) => { if (value === 'changePassword') { @@ -231,81 +288,169 @@ export default function My() { ] return ( - - + + + - - - - {/* 顶部积分与设置 */} - - router.push('/membership' as any)} - > - - {balance} - - handleSettingsSelect(value)} - renderTrigger={(selectedOption, isOpen, toggle) => ( - - - - )} - dropdownStyle={{ - minWidth: 160, - right: 10, - backgroundColor: '#2A2A2A80', - }} - /> - - - {/* 个人信息区 */} - - - - {profileName} - ID {session?.user?.id?.slice(0, 8) || '--------'} - - { - console.log('[my.tsx] Edit Profile button pressed') - setEditDrawerVisible(true) - }} - > - {t('my.editProfile')} - - - - {/* Tab 导航 */} - + router.push('/membership' as any)} + > + + {balance} + + handleSettingsSelect(value)} + renderTrigger={(selectedOption, isOpen, toggle) => ( + + + + )} + dropdownStyle={{ + minWidth: 160, + right: 10, + backgroundColor: '#2A2A2A80', + }} /> + - {/* 作品九宫格 */} - {activeTab === 'works' && loading ? ( + {/* 个人信息区 */} + + + + {profileName} + ID {session?.user?.id?.slice(0, 8) || '--------'} + + { + console.log('[my.tsx] Edit Profile button pressed') + setEditDrawerVisible(true) + }} + > + {t('my.editProfile')} + + + + {/* Tab 导航 */} + + + {/* 作品九宫格 */} + {activeTab === 'works' && loading ? ( + + ) : activeTab === 'works' ? ( + + } + > + + {generations.map((item, index) => ( + { + if (item.status === 'completed') { + router.push({ + pathname: '/generationRecord' as any, + params: { id: item.id }, + }) + } + }} + disabled={item.status !== 'completed'} + > + + + {/* 遮罩:非完成状态 */} + {item.status !== 'completed' && ( + + )} + + {/* 数量角标:已完成且有结果 */} + {item.status === 'completed' && (item.resultUrl?.length || 0) > 0 && ( + + + {item.resultUrl?.length || 1} + + + )} + + {/* 状态角标 */} + {item.status === 'running' && ( + + {t('my.generating')} + + )} + {item.status === 'pending' && ( + + {t('my.queuing')} + + )} + + ))} + + {/* 加载更多指示器 */} + {loadingMore && ( + + + + )} + + {/* 空状态提示 */} + {!loading && generations.length === 0 && ( + + + {t('my.noWorks')} + + + )} + + + ) : activeTab === 'favorites' && favoritesLoading ? ( - ) : activeTab === 'works' ? ( + ) : activeTab === 'favorites' ? ( - {generations.map((item, index) => ( - { - if (item.status === 'completed') { - router.push({ - pathname: '/generationRecord' as any, - params: { id: item.id }, - }) - } - }} - disabled={item.status !== 'completed'} - > - - - {/* 遮罩:非完成状态 */} - {item.status !== 'completed' && ( - - )} - - {/* 数量角标:已完成且有结果 */} - {item.status === 'completed' && (item.resultUrl?.length || 0) > 0 && ( - - - {item.resultUrl?.length || 1} - - - )} - - {/* 状态角标 */} - {item.status === 'running' && ( - - {t('my.generating')} - - )} - {item.status === 'pending' && ( - - {t('my.queuing')} - - )} - - ))} - - {/* 加载更多指示器 */} - {loadingMore && ( - - - - )} - - {/* 空状态提示 */} - {!loading && generations.length === 0 && ( - - - {t('my.noWorks')} - - - )} - - - ) : activeTab === 'favorites' && favoritesLoading ? ( - - ) : activeTab === 'favorites' ? ( - - - {favorites.length === 0 ? ( + {favorites.length === 0 && !favoritesLoading ? ( {t('my.noFavorites')} ) : ( - favorites.map((item, index) => ( - - - - )) + <> + {favorites.map((item, index) => ( + + + + ))} + {/* 加载更多指示器 */} + {favoritesLoadingMore && ( + + + + )} + )} @@ -425,48 +500,66 @@ export default function My() { style={styles.scrollView} contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false} + onScroll={handleLikesScroll} + scrollEventThrottle={16} + refreshControl={ + + } > - {likes.length === 0 ? ( + {likes.length === 0 && !likesLoading ? ( {t('my.noLikes')} ) : ( - likes.map((item, index) => ( - - - - )) + <> + {likes.map((item, index) => ( + + + + ))} + {/* 加载更多指示器 */} + {likesLoadingMore && ( + + + + )} + )} ) : null} - {/* 编辑资料抽屉 */} - - setEditDrawerVisible(false)} - initialName={profileName} - initialAvatar={session?.user?.image} - onSave={(data) => { - setProfileName(data.name) - }} - /> - + {/* 编辑资料抽屉 */} + setEditDrawerVisible(false)} + initialName={profileName} + initialAvatar={session?.user?.image} + onSave={(data) => { + setProfileName(data.name) + }} + /> ) } @@ -506,7 +599,7 @@ const styles = StyleSheet.create({ scrollContent: { backgroundColor: '#090A0B', paddingHorizontal: GALLERY_HORIZONTAL_PADDING, - paddingBottom: 20, + paddingBottom: 100, }, profileSection: { flexDirection: 'row', diff --git a/components/message/MessageCard.tsx b/components/message/MessageCard.tsx index 3680b89..c456b7a 100644 --- a/components/message/MessageCard.tsx +++ b/components/message/MessageCard.tsx @@ -112,9 +112,6 @@ export const MessageCard: React.FC = ({ onDelete, }) => { const config = getMessageConfig(message.data?.subType) - const icon = getMessageIcon(message.data?.subType) - const showAvatar = config.showAvatar && message.data?.likerAvatar - const showPreview = config.showPreview && message.data?.webpPreviewUrl const showQuote = config.showQuote && message.data?.originalComment const handlePress = () => { @@ -148,15 +145,6 @@ export const MessageCard: React.FC = ({ {message.content} - {/* Preview Image */} - {showPreview && ( - - )} - {/* Quote */} {showQuote && ( diff --git a/hooks/use-messages.ts b/hooks/use-messages.ts index ec653ae..bbf1996 100644 --- a/hooks/use-messages.ts +++ b/hooks/use-messages.ts @@ -25,8 +25,8 @@ export const useMessages = (initialParams?: ListMessagesParams) => { const [refreshing, setRefreshing] = useState(false) const [error, setError] = useState(null) const [data, setData] = useState() + const [hasMore, setHasMore] = useState(true) const currentPageRef = useRef(1) - const hasMoreRef = useRef(true) const execute = useCallback(async (params?: ListMessagesParams) => { setLoading(true) @@ -53,14 +53,15 @@ export const useMessages = (initialParams?: ListMessagesParams) => { const currentPage = requestParams.page || 1 const totalPages = data?.totalPages || 1 - hasMoreRef.current = currentPage < totalPages + const hasMoreValue = currentPage < totalPages + setHasMore(hasMoreValue) setData(data) setLoading(false) return { data, error: null } }, [initialParams]) const loadMore = useCallback(async () => { - if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null } + if (loadingMore || loading || !hasMore) return { data: undefined, error: null } setLoadingMore(true) const nextPage = currentPageRef.current + 1 @@ -83,7 +84,8 @@ export const useMessages = (initialParams?: ListMessagesParams) => { const newMessages = newData?.messages || [] const totalPages = newData?.totalPages || 1 - hasMoreRef.current = nextPage < totalPages + const hasMoreValue = nextPage < totalPages + setHasMore(hasMoreValue) currentPageRef.current = nextPage setData((prev) => ({ @@ -92,10 +94,10 @@ export const useMessages = (initialParams?: ListMessagesParams) => { })) setLoadingMore(false) return { data: newData, error: null } - }, [loading, loadingMore, initialParams]) + }, [loading, loadingMore, hasMore, initialParams]) const refetch = useCallback(async () => { - hasMoreRef.current = true + setHasMore(true) setRefreshing(true) const result = await execute() setRefreshing(false) @@ -108,11 +110,11 @@ export const useMessages = (initialParams?: ListMessagesParams) => { loading, loadingMore, refreshing, + hasMore, error, execute, refetch, loadMore, - hasMore: hasMoreRef.current, } } diff --git a/hooks/use-user-favorites.ts b/hooks/use-user-favorites.ts index 5d971e7..9d95932 100644 --- a/hooks/use-user-favorites.ts +++ b/hooks/use-user-favorites.ts @@ -24,8 +24,8 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => { const [loadingMore, setLoadingMore] = useState(false) const [error, setError] = useState(null) const [data, setData] = useState() + const [hasMore, setHasMore] = useState(true) const currentPageRef = useRef(1) - const hasMoreRef = useRef(true) const execute = useCallback(async (params?: GetUserFavoritesParams) => { setLoading(true) @@ -55,14 +55,15 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => { const total = data?.total || 0 const limit = requestParams.limit || 20 const totalPages = Math.ceil(total / limit) - hasMoreRef.current = currentPage < totalPages + const hasMoreValue = currentPage < totalPages + setHasMore(hasMoreValue) setData(data) setLoading(false) return { data, error: null } }, [initialParams]) const loadMore = useCallback(async () => { - if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null } + if (loadingMore || loading || !hasMore) return { data: undefined, error: null } setLoadingMore(true) const nextPage = currentPageRef.current + 1 @@ -87,7 +88,8 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => { const total = newData?.total || 0 const limit = requestParams.limit || 20 const totalPages = Math.ceil(total / limit) - hasMoreRef.current = nextPage < totalPages + const hasMoreValue = nextPage < totalPages + setHasMore(hasMoreValue) currentPageRef.current = nextPage setData((prev) => ({ @@ -98,10 +100,10 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => { })) setLoadingMore(false) return { data: newData, error: null } - }, [loading, loadingMore, initialParams]) + }, [loading, loadingMore, hasMore, initialParams]) const refetch = useCallback(() => { - hasMoreRef.current = true + setHasMore(true) return execute() }, [execute]) @@ -110,11 +112,11 @@ export const useUserFavorites = (initialParams?: GetUserFavoritesParams) => { favorites: data?.favorites || [], loading, loadingMore, + hasMore, error, execute, refetch, loadMore, - hasMore: hasMoreRef.current, } } diff --git a/hooks/use-user-likes.ts b/hooks/use-user-likes.ts index cb41ff7..0e2a602 100644 --- a/hooks/use-user-likes.ts +++ b/hooks/use-user-likes.ts @@ -21,8 +21,8 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => { const [loadingMore, setLoadingMore] = useState(false) const [error, setError] = useState(null) const [data, setData] = useState() + const [hasMore, setHasMore] = useState(true) const currentPageRef = useRef(1) - const hasMoreRef = useRef(true) const execute = useCallback(async (params?: GetUserLikesParams) => { setLoading(true) @@ -52,14 +52,15 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => { const total = data?.total || 0 const limit = requestParams.limit || 20 const totalPages = Math.ceil(total / limit) - hasMoreRef.current = currentPage < totalPages + const hasMoreValue = currentPage < totalPages + setHasMore(hasMoreValue) setData(data) setLoading(false) return { data, error: null } }, [initialParams]) const loadMore = useCallback(async () => { - if (loadingMore || loading || !hasMoreRef.current) return { data: undefined, error: null } + if (loadingMore || loading || !hasMore) return { data: undefined, error: null } setLoadingMore(true) const nextPage = currentPageRef.current + 1 @@ -84,7 +85,8 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => { const total = newData?.total || 0 const limit = requestParams.limit || 20 const totalPages = Math.ceil(total / limit) - hasMoreRef.current = nextPage < totalPages + const hasMoreValue = nextPage < totalPages + setHasMore(hasMoreValue) currentPageRef.current = nextPage setData((prev) => ({ @@ -93,10 +95,10 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => { })) setLoadingMore(false) return { data: newData, error: null } - }, [loading, loadingMore, initialParams]) + }, [loading, loadingMore, hasMore, initialParams]) const refetch = useCallback(() => { - hasMoreRef.current = true + setHasMore(true) return execute() }, [execute]) @@ -105,10 +107,10 @@ export const useUserLikes = (initialParams?: GetUserLikesParams) => { likes: data?.likes || [], loading, loadingMore, + hasMore, error, execute, refetch, loadMore, - hasMore: hasMoreRef.current, } }