WishRuleModal.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { Images } from '@/constants/images';
  2. import { getParamConfig } from '@/services/user';
  3. import React, { forwardRef, useImperativeHandle, useState } from 'react';
  4. import { Dimensions, ImageBackground, Modal, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
  5. const { width: SCREEN_WIDTH } = Dimensions.get('window');
  6. export interface WishRuleModalRef {
  7. show: () => void;
  8. close: () => void;
  9. }
  10. // 简单的HTML标签清理函数
  11. const stripHtmlTags = (html: string): string => {
  12. if (!html) return '';
  13. return html
  14. .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
  15. .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
  16. .replace(/<[^>]+>/g, '\n')
  17. .replace(/&nbsp;/g, ' ')
  18. .replace(/&lt;/g, '<')
  19. .replace(/&gt;/g, '>')
  20. .replace(/&amp;/g, '&')
  21. .replace(/\n\s*\n/g, '\n\n') // Merge multiple newlines
  22. .trim();
  23. };
  24. export const WishRuleModal = forwardRef<WishRuleModalRef, {}>((props, ref) => {
  25. const [visible, setVisible] = useState(false);
  26. const [content, setContent] = useState('');
  27. useImperativeHandle(ref, () => ({
  28. show: () => {
  29. setVisible(true);
  30. loadRule();
  31. },
  32. close: () => setVisible(false),
  33. }));
  34. const loadRule = async () => {
  35. try {
  36. const res = await getParamConfig('wish_rule');
  37. if (res && res.data) {
  38. setContent(stripHtmlTags(res.data));
  39. }
  40. } catch (error) {
  41. console.error('加载祈愿规则失败:', error);
  42. }
  43. };
  44. if (!visible) return null;
  45. return (
  46. <Modal visible={visible} transparent animationType="fade" onRequestClose={() => setVisible(false)}>
  47. <View style={styles.overlay}>
  48. <View style={styles.windowSection}>
  49. <ImageBackground style={styles.main} source={{ uri: Images.common.windBg }} resizeMode="stretch">
  50. <ScrollView
  51. style={styles.scrollView}
  52. contentContainerStyle={styles.scrollContent}
  53. showsVerticalScrollIndicator={false}
  54. >
  55. <Text style={styles.text}>{content || '暂无规则内容'}</Text>
  56. </ScrollView>
  57. </ImageBackground>
  58. {/* 关闭按钮 - 移到底部 */}
  59. <TouchableOpacity style={styles.closeBtn} onPress={() => setVisible(false)}>
  60. <ImageBackground source={{ uri: Images.common.closeBut }} style={styles.closeIcon} resizeMode="contain" />
  61. </TouchableOpacity>
  62. </View>
  63. </View>
  64. </Modal>
  65. );
  66. });
  67. export default WishRuleModal;
  68. const styles = StyleSheet.create({
  69. overlay: {
  70. flex: 1,
  71. backgroundColor: 'rgba(0,0,0,0.7)',
  72. justifyContent: 'center',
  73. alignItems: 'center',
  74. },
  75. windowSection: {
  76. width: SCREEN_WIDTH,
  77. alignItems: 'center',
  78. },
  79. main: {
  80. width: 360, // 720rpx
  81. height: 302, // 604rpx
  82. paddingTop: 90, // 180rpx
  83. paddingHorizontal: 30, // 60rpx
  84. alignItems: 'center',
  85. zIndex: 1,
  86. marginBottom: 20, // Space between modal and close button
  87. },
  88. scrollView: {
  89. width: '100%',
  90. height: 190, // 380rpx
  91. },
  92. scrollContent: {
  93. paddingBottom: 20,
  94. },
  95. text: {
  96. fontSize: 14,
  97. color: '#8B4513',
  98. lineHeight: 22,
  99. },
  100. closeBtn: {
  101. width: 35,
  102. height: 35,
  103. },
  104. closeIcon: {
  105. width: '100%',
  106. height: '100%',
  107. },
  108. });