import { Ionicons } from '@expo/vector-icons'; import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect'; import * as Haptics from 'expo-haptics'; import { Image } from 'expo-image'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { ActivityIndicator, Animated, BackHandler, Dimensions, Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import ImageViewing from 'react-native-image-viewing'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useI18n } from '../../hooks/useI18n'; import { triggerLightHaptic } from '../../utils/haptics'; const { height: screenHeight } = Dimensions.get('window'); interface MedicationAiSummaryInfoSheetProps { visible: boolean; onClose: () => void; onConfirm: () => void; loading?: boolean; } /** * AI 用药总结介绍弹窗组件 * 用于展示 AI 用药总结功能的介绍和说明 */ export function MedicationAiSummaryInfoSheet({ visible, onClose, onConfirm, loading = false, }: MedicationAiSummaryInfoSheetProps) { const { t } = useI18n(); const insets = useSafeAreaInsets(); const translateY = useRef(new Animated.Value(screenHeight)).current; const backdropOpacity = useRef(new Animated.Value(0)).current; const [showImagePreview, setShowImagePreview] = useState(false); // 预览图片 - 直接使用 require 资源 const imageSource = require('@/assets/images/medicine/medicine-ai-summary.png'); useEffect(() => { if (visible) { translateY.setValue(screenHeight); backdropOpacity.setValue(0); Animated.parallel([ Animated.timing(backdropOpacity, { toValue: 1, duration: 200, useNativeDriver: true, }), Animated.spring(translateY, { toValue: 0, useNativeDriver: true, bounciness: 6, speed: 12, }), ]).start(); } else { Animated.parallel([ Animated.timing(backdropOpacity, { toValue: 0, duration: 150, useNativeDriver: true, }), Animated.timing(translateY, { toValue: screenHeight, duration: 240, useNativeDriver: true, }), ]).start(() => { translateY.setValue(screenHeight); backdropOpacity.setValue(0); }); } }, [visible, backdropOpacity, translateY]); // 处理Android返回键关闭图片预览 useEffect(() => { const backHandler = BackHandler.addEventListener('hardwareBackPress', () => { if (showImagePreview) { setShowImagePreview(false); return true; // 阻止默认返回行为 } return false; }); return () => backHandler.remove(); }, [showImagePreview]); // 处理图片预览 const handleImagePreview = useCallback(() => { triggerLightHaptic(); setShowImagePreview(true); }, []); const handleClose = () => { // 安全地执行触觉反馈,避免因触觉反馈失败导致页面卡顿 Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light).catch((error) => { console.warn('[AI_SUMMARY] Haptic feedback failed:', error); }); onClose(); }; const handleConfirm = () => { if (loading) return; // 安全地执行触觉反馈,避免因触觉反馈失败导致页面卡顿 Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch((error) => { console.warn('[AI_SUMMARY] Haptic feedback failed:', error); }); onConfirm(); }; if (!visible) { return null; } return ( {/* 图标和标题 */} {t('medications.aiSummaryInfo.title')} {/* 介绍图片区域 */} {/* 右上角查看大图提示按钮 */} {isLiquidGlassAvailable() ? ( ) : ( )} {/* 功能介绍内容 */} {t('medications.aiSummaryInfo.features.intelligent.title')} {t('medications.aiSummaryInfo.features.intelligent.description')} {t('medications.aiSummaryInfo.features.tracking.title')} {t('medications.aiSummaryInfo.features.tracking.description')} {t('medications.aiSummaryInfo.features.professional.title')} {t('medications.aiSummaryInfo.features.professional.description')} {/* 确认按钮 - 支持 Liquid Glass */} {isLiquidGlassAvailable() ? ( {loading ? ( ) : ( <> {t('medications.aiSummaryInfo.confirmButton')} )} ) : ( {loading ? ( ) : ( <> {t('medications.aiSummaryInfo.confirmButton')} )} )} {/* 图片预览 */} setShowImagePreview(false)} swipeToCloseEnabled={true} doubleTapToZoomEnabled={true} FooterComponent={() => ( setShowImagePreview(false)} > {t('medications.detail.imageViewer.close')} )} /> ); } const styles = StyleSheet.create({ overlay: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'transparent', }, backdrop: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(15, 23, 42, 0.45)', }, sheet: { backgroundColor: '#fff', borderTopLeftRadius: 28, borderTopRightRadius: 28, paddingHorizontal: 24, paddingTop: 16, shadowColor: '#000', shadowOpacity: 0.12, shadowRadius: 16, shadowOffset: { width: 0, height: -4 }, elevation: 16, gap: 20, }, handle: { width: 50, height: 4, borderRadius: 2, backgroundColor: '#E5E7EB', alignSelf: 'center', marginBottom: 8, }, header: { flexDirection: 'row', alignItems: 'center', gap: 12, }, iconContainer: { width: 40, height: 40, borderRadius: 20, backgroundColor: '#F3E8FF', alignItems: 'center', justifyContent: 'center', }, title: { fontSize: 20, fontWeight: '700', color: '#111827', }, imageContainer: { width: '100%', height: 380, borderRadius: 16, overflow: 'hidden', backgroundColor: '#F9FAFB', }, introImage: { width: '100%', height: '100%', borderRadius: 16, }, contentContainer: { gap: 16, paddingVertical: 8, }, featureItem: { flexDirection: 'row', gap: 12, alignItems: 'flex-start', }, featureIcon: { width: 36, height: 36, borderRadius: 18, backgroundColor: '#F3E8FF', alignItems: 'center', justifyContent: 'center', }, featureContent: { flex: 1, }, featureTitle: { fontSize: 16, fontWeight: '600', color: '#111827', marginBottom: 4, }, featureDescription: { fontSize: 14, lineHeight: 20, color: '#6B7280', }, actions: { marginTop: 8, }, confirmButton: { height: 56, borderRadius: 18, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 8, overflow: 'hidden', // 保证玻璃边界圆角效果 }, fallbackButton: { backgroundColor: '#8B5CF6', shadowColor: 'rgba(139, 92, 246, 0.45)', shadowOffset: { width: 0, height: 10 }, shadowOpacity: 1, shadowRadius: 20, elevation: 6, }, confirmText: { fontSize: 16, fontWeight: '700', color: '#fff', }, // 图片预览相关样式 viewImageButton: { position: 'absolute', top: 12, right: 12, zIndex: 1, }, glassViewButton: { width: 32, height: 32, borderRadius: 16, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', }, fallbackViewButton: { borderWidth: 1, borderColor: 'rgba(0, 0, 0, 0.1)', backgroundColor: 'rgba(255, 255, 255, 0.8)', }, imageViewerFooter: { position: 'absolute', bottom: 60, left: 20, right: 20, alignItems: 'center', zIndex: 1, }, imageViewerFooterButton: { backgroundColor: 'rgba(0, 0, 0, 0.7)', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 20, }, imageViewerFooterButtonText: { color: '#FFF', fontSize: 16, fontWeight: '500', }, });