index.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import { useLocalSearchParams, useRouter } from 'expo-router';
  2. import React, { useEffect, useState } from 'react';
  3. import {
  4. ActivityIndicator,
  5. ScrollView,
  6. StatusBar,
  7. StyleSheet,
  8. Text,
  9. TouchableOpacity,
  10. View
  11. } from 'react-native';
  12. import { useSafeAreaInsets } from 'react-native-safe-area-context';
  13. import { getParamConfig } from '@/services/user';
  14. // 简单的HTML标签清理函数
  15. const stripHtmlTags = (html: string): string => {
  16. if (!html) return '';
  17. // 移除HTML标签,保留文本内容
  18. return html
  19. .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
  20. .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
  21. .replace(/<[^>]+>/g, '\n')
  22. .replace(/&nbsp;/g, ' ')
  23. .replace(/&lt;/g, '<')
  24. .replace(/&gt;/g, '>')
  25. .replace(/&amp;/g, '&')
  26. .replace(/&quot;/g, '"')
  27. .replace(/\n\s*\n/g, '\n\n')
  28. .trim();
  29. };
  30. export default function AgreementScreen() {
  31. const router = useRouter();
  32. const insets = useSafeAreaInsets();
  33. const params = useLocalSearchParams<{ type: string }>();
  34. const [loading, setLoading] = useState(true);
  35. const [title, setTitle] = useState('');
  36. const [content, setContent] = useState('');
  37. useEffect(() => {
  38. loadContent();
  39. }, [params.type]);
  40. const loadContent = async () => {
  41. try {
  42. setLoading(true);
  43. const type = params.type || 'user.html';
  44. console.log('加载协议类型:', type);
  45. const res = await getParamConfig(type) as any;
  46. console.log('协议内容返回:', res);
  47. if (res) {
  48. // API返回的数据结构: { title: string, data: string (HTML内容) }
  49. const titleText = res.title || (type === 'user.html' ? '用户协议' : '隐私协议');
  50. setTitle(titleText);
  51. // 清理HTML标签,只保留纯文本
  52. const rawContent = res.data || res || '';
  53. setContent(stripHtmlTags(typeof rawContent === 'string' ? rawContent : JSON.stringify(rawContent)));
  54. }
  55. } catch (error) {
  56. console.error('获取协议内容失败:', error);
  57. } finally {
  58. setLoading(false);
  59. }
  60. };
  61. const handleBack = () => {
  62. router.back();
  63. };
  64. return (
  65. <View style={styles.container}>
  66. <StatusBar barStyle="light-content" />
  67. {/* 顶部导航 */}
  68. <View style={[styles.header, { paddingTop: insets.top }]}>
  69. <TouchableOpacity style={styles.backBtn} onPress={handleBack}>
  70. <Text style={styles.backIcon}>‹</Text>
  71. </TouchableOpacity>
  72. <Text style={styles.headerTitle}>{title || '协议'}</Text>
  73. <View style={styles.placeholder} />
  74. </View>
  75. {loading ? (
  76. <View style={styles.loadingBox}>
  77. <ActivityIndicator size="large" color="#FC7D2E" />
  78. </View>
  79. ) : content ? (
  80. <ScrollView
  81. style={styles.scrollView}
  82. contentContainerStyle={styles.scrollContent}
  83. showsVerticalScrollIndicator={false}
  84. >
  85. <Text style={styles.contentText}>{content}</Text>
  86. </ScrollView>
  87. ) : (
  88. <View style={styles.emptyBox}>
  89. <Text style={styles.emptyText}>暂无内容</Text>
  90. </View>
  91. )}
  92. </View>
  93. );
  94. }
  95. const styles = StyleSheet.create({
  96. container: {
  97. flex: 1,
  98. backgroundColor: '#333',
  99. },
  100. header: {
  101. flexDirection: 'row',
  102. alignItems: 'center',
  103. justifyContent: 'space-between',
  104. paddingHorizontal: 10,
  105. height: 80,
  106. backgroundColor: '#333',
  107. },
  108. backBtn: {
  109. width: 40,
  110. height: 40,
  111. justifyContent: 'center',
  112. alignItems: 'center',
  113. },
  114. backIcon: {
  115. fontSize: 32,
  116. color: '#fff',
  117. fontWeight: 'bold',
  118. },
  119. headerTitle: {
  120. fontSize: 16,
  121. fontWeight: 'bold',
  122. color: '#fff',
  123. },
  124. placeholder: {
  125. width: 40,
  126. },
  127. loadingBox: {
  128. flex: 1,
  129. justifyContent: 'center',
  130. alignItems: 'center',
  131. backgroundColor: '#fff',
  132. },
  133. scrollView: {
  134. flex: 1,
  135. backgroundColor: '#fff',
  136. },
  137. scrollContent: {
  138. padding: 15,
  139. paddingBottom: 50,
  140. },
  141. contentText: {
  142. fontSize: 14,
  143. lineHeight: 22,
  144. color: '#333',
  145. },
  146. emptyBox: {
  147. flex: 1,
  148. justifyContent: 'center',
  149. alignItems: 'center',
  150. backgroundColor: '#fff',
  151. },
  152. emptyText: {
  153. fontSize: 14,
  154. color: '#999',
  155. },
  156. });