修复了课表周数硬编码

This commit is contained in:
2026-03-17 12:29:04 +08:00
parent 582589d252
commit b50bd9abb3
10 changed files with 605 additions and 43 deletions

View File

@@ -13,6 +13,7 @@ import {
TouchableOpacity,
RefreshControl,
ActivityIndicator,
Dimensions,
} from 'react-native';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { useIsFocused } from '@react-navigation/native';
@@ -25,7 +26,6 @@ import { messageService } from '../../services/messageService';
import { commentService } from '../../services/commentService';
import { SystemMessageItem } from '../../components/business';
import { Text, EmptyState, ResponsiveContainer } from '../../components/common';
import { useResponsive, useBreakpointGTE } from '../../hooks/useResponsive';
import { RootStackParamList } from '../../navigation/types';
import { useMessageManagerSystemUnreadCount, useUserStore } from '../../stores';
@@ -48,9 +48,27 @@ export const NotificationsScreen: React.FC<{ onBack?: () => void }> = ({ onBack
const { setSystemUnreadCount, decrementSystemUnreadCount } = useMessageManagerSystemUnreadCount();
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
// 响应式布局
const { isDesktop, isTablet } = useResponsive();
const isWideScreen = useBreakpointGTE('lg');
// 修复竞态条件:使用本地状态管理窗口尺寸,避免 hydration 问题
const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
const [isHydrated, setIsHydrated] = useState(false);
useEffect(() => {
// 延迟设置窗口尺寸,确保在客户端完全加载后再获取
const timer = setTimeout(() => {
const { width, height } = Dimensions.get('window');
setWindowSize({ width, height });
setIsHydrated(true);
}, 100);
return () => clearTimeout(timer);
}, []);
// 使用本地尺寸状态计算断点 (lg = 768)
const isWideScreen = windowSize.width >= 768;
const isDesktop = windowSize.width >= 1024;
const isTablet = windowSize.width >= 768 && windowSize.width < 1024;
// Web端使用更大的容器宽度
const containerMaxWidth = isDesktop ? 1200 : isTablet ? 1000 : 900;
const [messages, setMessages] = useState<SystemMessageResponse[]>([]);
const [activeType, setActiveType] = useState('all');
@@ -320,7 +338,7 @@ export const NotificationsScreen: React.FC<{ onBack?: () => void }> = ({ onBack
const shouldShowBackButton = onBack && !isWideScreen;
return (
<View style={[styles.header, isWideScreen && styles.headerWide]}>
<View style={[styles.header, isWideScreen ? styles.headerWide : null]}>
{shouldShowBackButton ? (
<TouchableOpacity
style={styles.backButton}
@@ -342,21 +360,34 @@ export const NotificationsScreen: React.FC<{ onBack?: () => void }> = ({ onBack
// 渲染空状态
const renderEmpty = () => (
<EmptyState
title="暂无通知"
description="关注一些用户来获取通知"
icon="bell-outline"
/>
<View style={[styles.emptyContainer, isWideScreen && styles.emptyContainerWeb]}>
<EmptyState
title="暂无通知"
description="关注一些用户来获取通知吧"
icon="bell-outline"
/>
</View>
);
// 如果还未hydrated显示加载占位符避免竞态条件导致的渲染问题
if (!isHydrated) {
return (
<SafeAreaView style={styles.container} edges={[]}>
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={colors.primary.main} />
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={styles.container} edges={[]}>
{isWideScreen ? (
<ResponsiveContainer maxWidth={900}>
<ResponsiveContainer maxWidth={containerMaxWidth}>
{/* 头部 - 大屏模式下隐藏返回按钮 */}
{renderHeader()}
{/* 分类筛选 */}
<View style={[styles.filterContainer, isWideScreen && styles.filterContainerWide]}>
<View style={[styles.filterContainer, isWideScreen && styles.filterContainerWideWeb]}>
{MESSAGE_TYPES.map(type => {
const count = type.key === 'all'
? displayMessages.length
@@ -518,10 +549,11 @@ const styles = StyleSheet.create({
borderBottomWidth: 1,
borderBottomColor: colors.divider,
},
filterContainerWide: {
filterContainerWideWeb: {
paddingHorizontal: spacing.xl,
paddingVertical: spacing.md,
justifyContent: 'center',
backgroundColor: colors.background.paper,
},
filterTag: {
flexDirection: 'row',
@@ -596,4 +628,14 @@ const styles = StyleSheet.create({
loadingMoreText: {
marginLeft: spacing.sm,
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
emptyContainerWeb: {
minHeight: 500,
justifyContent: 'center',
paddingTop: 100,
},
});