index.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import { useRouter } from 'expo-router';
  2. import React, { useState } from 'react';
  3. import {
  4. Alert,
  5. ImageBackground,
  6. StatusBar,
  7. StyleSheet,
  8. Text,
  9. TextInput,
  10. TouchableOpacity,
  11. View,
  12. } from 'react-native';
  13. import { useSafeAreaInsets } from 'react-native-safe-area-context';
  14. import { Images } from '@/constants/images';
  15. import { harryExchange } from '@/services/award';
  16. export default function ExchangeScreen() {
  17. const router = useRouter();
  18. const insets = useSafeAreaInsets();
  19. const [code, setCode] = useState('');
  20. const [loading, setLoading] = useState(false);
  21. const handleBack = () => {
  22. router.back();
  23. };
  24. const handleSubmit = async () => {
  25. if (!code.trim()) {
  26. Alert.alert('提示', '请输入兑换码');
  27. return;
  28. }
  29. try {
  30. setLoading(true);
  31. const res = await harryExchange({ code: code.trim() });
  32. if (res?.success) {
  33. let rewardType = '';
  34. const data = res.data;
  35. switch (data?.rewardType) {
  36. case 'USER_CREDIT':
  37. rewardType = '积分';
  38. break;
  39. case 'CASH':
  40. rewardType = '现金';
  41. break;
  42. case 'MAGIC':
  43. rewardType = '果实';
  44. break;
  45. case 'MAGIC_POWER_COIN':
  46. rewardType = '源力币';
  47. break;
  48. case 'COUPON':
  49. rewardType = '优惠券';
  50. break;
  51. case 'SPU_ID':
  52. rewardType = '商品';
  53. break;
  54. default:
  55. rewardType = '奖励';
  56. }
  57. const text = data?.rewardType === 'COUPON' || data?.rewardType === 'SPU_ID'
  58. ? `成功获得${rewardType}`
  59. : `成功获得${rewardType}${data?.rewardAmount || ''}`;
  60. Alert.alert('提示', text, [
  61. { text: '确定', onPress: () => router.back() }
  62. ]);
  63. setCode('');
  64. } else {
  65. Alert.alert('提示', res?.msg || '兑换失败');
  66. }
  67. } catch (error) {
  68. console.error('兑换失败:', error);
  69. Alert.alert('提示', '兑换失败');
  70. } finally {
  71. setLoading(false);
  72. }
  73. };
  74. return (
  75. <ImageBackground
  76. source={{ uri: Images.mine.kaixinMineBg }}
  77. style={styles.container}
  78. resizeMode="cover"
  79. >
  80. <StatusBar barStyle="light-content" />
  81. {/* 顶部导航 */}
  82. <View style={[styles.header, { paddingTop: insets.top }]}>
  83. <TouchableOpacity style={styles.backBtn} onPress={handleBack}>
  84. <Text style={styles.backIcon}>‹</Text>
  85. </TouchableOpacity>
  86. <Text style={styles.headerTitle}>兑换码</Text>
  87. <View style={styles.placeholder} />
  88. </View>
  89. <View style={styles.content}>
  90. <View style={styles.card}>
  91. <Text style={styles.describe}>请在下方输入您的兑换码</Text>
  92. <View style={styles.inputWrapper}>
  93. <TextInput
  94. style={styles.input}
  95. value={code}
  96. onChangeText={setCode}
  97. placeholder="请输入兑换码"
  98. placeholderTextColor="#999"
  99. multiline
  100. />
  101. </View>
  102. <View style={styles.btnsWrapper}>
  103. <TouchableOpacity
  104. style={[styles.btn, styles.cancelBtn]}
  105. onPress={handleBack}
  106. >
  107. <Text style={styles.cancelBtnText}>取消</Text>
  108. </TouchableOpacity>
  109. <TouchableOpacity
  110. style={[styles.btn, styles.confirmBtn]}
  111. onPress={handleSubmit}
  112. disabled={loading}
  113. >
  114. <Text style={styles.confirmBtnText}>
  115. {loading ? '兑换中...' : '确定'}
  116. </Text>
  117. </TouchableOpacity>
  118. </View>
  119. </View>
  120. </View>
  121. </ImageBackground>
  122. );
  123. }
  124. const styles = StyleSheet.create({
  125. container: {
  126. flex: 1,
  127. },
  128. header: {
  129. flexDirection: 'row',
  130. alignItems: 'center',
  131. justifyContent: 'space-between',
  132. paddingHorizontal: 10,
  133. height: 80,
  134. },
  135. backBtn: {
  136. width: 40,
  137. height: 40,
  138. justifyContent: 'center',
  139. alignItems: 'center',
  140. },
  141. backIcon: {
  142. fontSize: 32,
  143. color: '#fff',
  144. fontWeight: 'bold',
  145. },
  146. headerTitle: {
  147. fontSize: 16,
  148. fontWeight: 'bold',
  149. color: '#fff',
  150. },
  151. placeholder: {
  152. width: 40,
  153. },
  154. content: {
  155. flex: 1,
  156. paddingHorizontal: 15,
  157. paddingTop: 20,
  158. },
  159. card: {
  160. backgroundColor: '#fff',
  161. borderRadius: 15,
  162. padding: 20,
  163. },
  164. describe: {
  165. fontSize: 14,
  166. color: '#333',
  167. marginBottom: 15,
  168. textAlign: 'center',
  169. },
  170. inputWrapper: {
  171. backgroundColor: '#f5f5f5',
  172. borderRadius: 8,
  173. padding: 10,
  174. marginBottom: 20,
  175. },
  176. input: {
  177. height: 80,
  178. fontSize: 16,
  179. color: '#333',
  180. textAlignVertical: 'top',
  181. },
  182. btnsWrapper: {
  183. flexDirection: 'row',
  184. justifyContent: 'space-between',
  185. },
  186. btn: {
  187. width: '45%',
  188. height: 44,
  189. borderRadius: 22,
  190. justifyContent: 'center',
  191. alignItems: 'center',
  192. },
  193. cancelBtn: {
  194. backgroundColor: '#e0e0e0',
  195. },
  196. cancelBtnText: {
  197. fontSize: 16,
  198. color: '#666',
  199. },
  200. confirmBtn: {
  201. backgroundColor: '#FC7D2E',
  202. },
  203. confirmBtnText: {
  204. fontSize: 16,
  205. color: '#fff',
  206. },
  207. });