/** * 公告栏组件 - 增强版 * * 基于 xinyong-web 的 NoticeBar 组件重建 * 功能包括: * - 顶部通知栏(自动轮播) * - 消息和客服按钮 * - 公告详情弹窗(支持文本、图片、链接) * - 主题适配(light/dark/orange) */ import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'; import { View, Text, StyleSheet, Animated, TouchableOpacity, Dimensions, ScrollView, Modal, Linking, Image as RNImage, ActivityIndicator, } from 'react-native'; // import { Button } from 'react-native-paper'; import { useThemeColors, useColorScheme } from '@/theme'; // import { mockNotices } from '@/services/mockHomeService'; // import type { Notice } from '@/types/home'; import useMsgStore, { useUnreadMessageTotal } from '@/stores/msgStore'; import { filter, map } from 'lodash-es'; import { styles } from './styles'; import { Ionicons } from '@expo/vector-icons'; interface NoticeBarProps { onNoticePress?: (notice: Record) => void; onMessagePress?: () => void; onServicePress?: () => void; unreadCount?: number; } /** * 公告栏组件 - 增强版 */ export default function NoticeBar({ onNoticePress, onMessagePress, onServicePress, unreadCount = 0, }: NoticeBarProps) { const colorScheme = useColorScheme(); const s = styles[colorScheme]; const themeColors = useThemeColors(); const [currentNotice, setCurrentNotice] = useState(0); const [visible, setVisible] = useState(true); const [showDetailModal, setShowDetailModal] = useState(false); const [imageLoading, setImageLoading] = useState(true); const animatedValue = useRef(new Animated.Value(1)).current; const { notices } = useMsgStore(); const unreadMessageTotal = useUnreadMessageTotal(); const noticeList = useMemo(() => { return map( filter(notices, (item) => item.message_id == 13 && !!item.content), (notice) => { return { ...notice, content: notice.content.replace( /<(\/?)(p|span|div|br|strong|em|b|i|u|s|ul|li|ol|h1|h2|h3|h4|h5|h6|a|img|table|tr|td|th|tbody|thead|tfoot|style|script)[^>]*>/gi, '' ), }; } ); }, [notices]); // 自动切换公告 useEffect(() => { if (noticeList.length === 0) return; const timer = setInterval(() => { setCurrentNotice((prev) => (prev + 1) % noticeList.length); }, 5000); return () => clearInterval(timer); }, [noticeList.length]); // 处理关闭公告 const handleClose = useCallback(() => { Animated.timing(animatedValue, { toValue: 0, duration: 300, useNativeDriver: true, }).start(() => { setVisible(false); }); }, [animatedValue]); // 处理公告点击 - 打开详情弹窗 const handleNoticePress = useCallback(() => { if (noticeList.length > 0) { setShowDetailModal(true); onNoticePress?.(noticeList[currentNotice]); } }, [noticeList, currentNotice, onNoticePress]); // 处理链接点击 const handleLinkPress = useCallback((url: string) => { Linking.openURL(url).catch((err) => { console.error('打开链接失败:', err); }); }, []); if (!visible || noticeList.length === 0) { return null; } const currentNoticeData = noticeList[currentNotice] as Record; return ( <> {/* 顶部通知栏 */} {currentNoticeData.content} {/* 右侧按钮组 */} {/*{unreadCount > 0 && (*/} {/* {unreadCount}*/} {/*)}*/} 消息 客服 {/**/} {/* */} {/**/} {/* 公告详情弹窗 */} setShowDetailModal(false)} > {/* 弹窗头部 */} 公告详情 setShowDetailModal(false)} > {/* 弹窗内容 */} {currentNoticeData.title && ( {currentNoticeData.title} )} {currentNoticeData.create_time && ( {currentNoticeData.formatDate || currentNoticeData.create_time} )} {/* 根据内容类型渲染不同的内容 */} {currentNoticeData.content_type === 1 && ( {currentNoticeData.content} )} {currentNoticeData.content_type === 2 && currentNoticeData.content && ( {imageLoading && ( )} { setImageLoading(true); }} onLoadEnd={() => { setImageLoading(false); }} onError={(error) => { console.error('图片加载失败:', error); setImageLoading(false); }} /> )} {currentNoticeData.content_type === 3 && ( handleLinkPress(currentNoticeData.content)}> {currentNoticeData.content} )} ); }