You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
3.8 KiB

/**
*
*
* 使
*/
import React, { useState, useEffect, useRef } from 'react';
import {
View,
Text,
StyleSheet,
Animated,
TouchableOpacity,
Dimensions,
} from 'react-native';
import { createThemeStyles } from '@/theme';
import Colors from '@/constants/Colors';
import { mockNotices } from '@/services/mockHomeService';
import type { Notice } from '@/types/home';
const { width } = Dimensions.get('window');
/**
*
*/
const styles = createThemeStyles((colors) => ({
container: {
backgroundColor: colors.backgroundSecondary,
paddingVertical: 10,
paddingHorizontal: 12,
marginHorizontal: 12,
marginBottom: 12,
borderRadius: 8,
flexDirection: 'row',
alignItems: 'center',
elevation: 2,
shadowColor: colors.cardShadow,
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 3,
},
label: {
fontSize: 12,
fontWeight: 'bold',
color: '#FFFFFF',
marginRight: 8,
backgroundColor: colors.primary,
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 4,
},
content: {
flex: 1,
fontSize: 12,
color: colors.text,
overflow: 'hidden',
},
closeButton: {
marginLeft: 8,
padding: 4,
},
closeText: {
fontSize: 16,
color: colors.textSecondary,
},
}));
interface NoticeBarProps {
theme: 'light' | 'dark';
notices?: Notice[];
onNoticePress?: (notice: Notice) => void;
}
/**
*
*/
export default function NoticeBar({ theme, notices: propNotices, onNoticePress }: NoticeBarProps) {
const s = styles[theme];
const [notices, setNotices] = useState<Notice[]>(propNotices || []);
const [currentNotice, setCurrentNotice] = useState(0);
const [visible, setVisible] = useState(true);
const animatedValue = useRef(new Animated.Value(1)).current;
// 加载公告数据
useEffect(() => {
if (propNotices && propNotices.length > 0) {
setNotices(propNotices);
return;
}
const loadNotices = async () => {
try {
// const data = await getNotices();
// setNotices(data.length > 0 ? data : mockNotices);
} catch (error) {
console.error('加载公告失败:', error);
setNotices(mockNotices);
}
};
loadNotices();
}, [propNotices]);
// 自动切换公告
useEffect(() => {
if (notices.length === 0) return;
const timer = setInterval(() => {
setCurrentNotice((prev) => (prev + 1) % notices.length);
}, 5000);
return () => clearInterval(timer);
}, [notices.length]);
// 处理关闭公告
const handleClose = () => {
Animated.timing(animatedValue, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start(() => {
setVisible(false);
});
};
// 处理公告点击
const handleNoticePress = () => {
if (notices.length > 0) {
onNoticePress?.(notices[currentNotice]);
}
};
if (!visible || notices.length === 0) {
return null;
}
const currentNoticeData = notices[currentNotice];
return (
<Animated.View
style={[
s.container,
{
opacity: animatedValue,
transform: [
{
scaleY: animatedValue,
},
],
},
]}
>
<Text style={s.label}>📢</Text>
<TouchableOpacity
style={{ flex: 1 }}
onPress={handleNoticePress}
activeOpacity={0.7}
>
<Text style={s.content} numberOfLines={1}>
{currentNoticeData.title || currentNoticeData.content}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={s.closeButton}
onPress={handleClose}
>
<Text style={s.closeText}></Text>
</TouchableOpacity>
</Animated.View>
);
}