|
|
@@ -2,14 +2,14 @@ import { Image } from 'expo-image';
|
|
|
import { useRouter } from 'expo-router';
|
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
|
import {
|
|
|
- Dimensions,
|
|
|
- ImageBackground,
|
|
|
- ScrollView,
|
|
|
- StatusBar,
|
|
|
- StyleSheet,
|
|
|
- Text,
|
|
|
- TouchableOpacity,
|
|
|
- View,
|
|
|
+ Dimensions,
|
|
|
+ ImageBackground,
|
|
|
+ ScrollView,
|
|
|
+ StatusBar,
|
|
|
+ StyleSheet,
|
|
|
+ Text,
|
|
|
+ TouchableOpacity,
|
|
|
+ View,
|
|
|
} from 'react-native';
|
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
|
|
|
|
@@ -27,8 +27,10 @@ const wishImages = {
|
|
|
addLiBg: `${CDN_BASE}/welfare/addLiBg.png`,
|
|
|
addClose: `${CDN_BASE}/welfare/addClose.png`,
|
|
|
addSectionBg: `${CDN_BASE}/welfare/toys/addSectionBg.png`,
|
|
|
+ add: `${CDN_BASE}/welfare/add.png`,
|
|
|
left: `${CDN_BASE}/box/detail/left.png`,
|
|
|
right: `${CDN_BASE}/box/detail/right.png`,
|
|
|
+ progressBar: `${CDN_BASE}/welfare/toys/wishProgressBar.png`,
|
|
|
};
|
|
|
|
|
|
interface WishItem {
|
|
|
@@ -78,54 +80,70 @@ export default function WishScreen() {
|
|
|
const currentItem = tableData[active];
|
|
|
const remaining = currentItem ? currentItem.quantity - currentItem.completeQuantity : 0;
|
|
|
|
|
|
+ const removeGoods = (item: GoodsItem) => {
|
|
|
+ setGoodsList(goodsList.filter((g) => g.id !== item.id));
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
<View style={styles.container}>
|
|
|
<StatusBar barStyle="light-content" />
|
|
|
<ImageBackground source={{ uri: wishImages.bg }} style={styles.background} resizeMode="cover">
|
|
|
- {/* 顶部导航 */}
|
|
|
+ {/* 头部导航 */}
|
|
|
<View style={[styles.header, { paddingTop: insets.top }]}>
|
|
|
<TouchableOpacity style={styles.backBtn} onPress={() => router.back()}>
|
|
|
<Text style={styles.backText}>←</Text>
|
|
|
</TouchableOpacity>
|
|
|
- <Text style={styles.title}>艾斯祈福</Text>
|
|
|
+ <Text style={styles.title}>祈愿</Text>
|
|
|
<View style={styles.placeholder} />
|
|
|
</View>
|
|
|
|
|
|
+ {/* 规则按钮 */}
|
|
|
+ <TouchableOpacity style={[styles.ruleBtn, { top: insets.top + 160 }]}>
|
|
|
+ <Image source={{ uri: wishImages.rule }} style={styles.ruleBtnImg} contentFit="contain" />
|
|
|
+ </TouchableOpacity>
|
|
|
+
|
|
|
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
|
|
|
<View style={{ height: insets.top + 50 }} />
|
|
|
|
|
|
- {/* 标题 */}
|
|
|
+ {/* 标题图片 */}
|
|
|
<View style={styles.titleBox}>
|
|
|
<Image source={{ uri: wishImages.title }} style={styles.titleImg} contentFit="contain" />
|
|
|
</View>
|
|
|
|
|
|
- {/* 规则按钮 */}
|
|
|
- <TouchableOpacity style={styles.ruleBtn}>
|
|
|
- <Image source={{ uri: wishImages.rule }} style={styles.ruleBtnImg} contentFit="contain" />
|
|
|
- </TouchableOpacity>
|
|
|
-
|
|
|
- {/* 商品轮播 */}
|
|
|
+ {/* 卡片轮播区域 */}
|
|
|
<View style={styles.swiperBox}>
|
|
|
+ {/* 左箭头 */}
|
|
|
{active > 0 && (
|
|
|
<TouchableOpacity style={styles.prevBtn} onPress={handlePrev}>
|
|
|
<Image source={{ uri: wishImages.left }} style={styles.arrowImg} contentFit="contain" />
|
|
|
</TouchableOpacity>
|
|
|
)}
|
|
|
|
|
|
+ {/* 卡片 */}
|
|
|
<View style={styles.cardBox}>
|
|
|
- {currentItem && (
|
|
|
+ {currentItem ? (
|
|
|
<View style={styles.card}>
|
|
|
<View style={styles.imgBox}>
|
|
|
<Image source={{ uri: currentItem.spu?.cover }} style={styles.spuImage} contentFit="contain" />
|
|
|
+ {/* 仅剩标签 */}
|
|
|
<View style={styles.remainingBox}>
|
|
|
<Text style={styles.remainingText}>仅剩:{remaining}</Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
- <Text style={styles.cardName} numberOfLines={1}>{currentItem.name}</Text>
|
|
|
+ <Text style={styles.cardName} numberOfLines={1}>
|
|
|
+ {currentItem.name}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ ) : (
|
|
|
+ <View style={styles.card}>
|
|
|
+ <View style={styles.imgBox}>
|
|
|
+ <Text style={styles.emptyText}>暂无祈愿商品</Text>
|
|
|
+ </View>
|
|
|
</View>
|
|
|
)}
|
|
|
</View>
|
|
|
|
|
|
+ {/* 右箭头 */}
|
|
|
{active < tableData.length - 1 && (
|
|
|
<TouchableOpacity style={styles.nextBtn} onPress={handleNext}>
|
|
|
<Image source={{ uri: wishImages.right }} style={styles.arrowImg} contentFit="contain" />
|
|
|
@@ -133,41 +151,49 @@ export default function WishScreen() {
|
|
|
)}
|
|
|
</View>
|
|
|
|
|
|
- {/* 进度条 */}
|
|
|
+ {/* 指示点 */}
|
|
|
+ {tableData.length > 1 && (
|
|
|
+ <View style={styles.dotsBox}>
|
|
|
+ {tableData.map((_, i) => (
|
|
|
+ <View key={i} style={[styles.dot, i === active && styles.dotActive]} />
|
|
|
+ ))}
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 进度条区域 */}
|
|
|
<View style={styles.progressSection}>
|
|
|
<Text style={styles.progressLabel}>进度:</Text>
|
|
|
<View style={styles.progressBar}>
|
|
|
<View style={[styles.progressFill, { width: `${progress}%` }]} />
|
|
|
</View>
|
|
|
- <Text style={styles.progressText}>{progress}%</Text>
|
|
|
+ <Text style={styles.progressText}>{progress > 0 ? progress.toFixed(1) : progress}%</Text>
|
|
|
</View>
|
|
|
|
|
|
{/* 材料添加区域 */}
|
|
|
<ImageBackground source={{ uri: wishImages.addSectionBg }} style={styles.addSection} resizeMode="stretch">
|
|
|
<Text style={styles.addTitle}>材料添加</Text>
|
|
|
<View style={styles.addMain}>
|
|
|
+ {/* 添加按钮 */}
|
|
|
<TouchableOpacity style={styles.addBtn}>
|
|
|
<ImageBackground source={{ uri: wishImages.addBg }} style={styles.addBtnBg} resizeMode="contain">
|
|
|
- <Image source={{ uri: `${CDN_BASE}/welfare/add.png` }} style={styles.addIcon} contentFit="contain" />
|
|
|
+ <Image source={{ uri: wishImages.add }} style={styles.addIcon} contentFit="contain" />
|
|
|
<Text style={styles.addBtnText}>添加</Text>
|
|
|
</ImageBackground>
|
|
|
</TouchableOpacity>
|
|
|
+
|
|
|
+ {/* 已添加的材料列表 */}
|
|
|
<View style={styles.addCenter}>
|
|
|
- <ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
|
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.addScrollContent}>
|
|
|
{goodsList.map((item, index) => (
|
|
|
<View key={item.id || index} style={styles.addItem}>
|
|
|
<ImageBackground source={{ uri: wishImages.addLiBg }} style={styles.addItemBg} resizeMode="contain">
|
|
|
<Image source={{ uri: item.spu?.cover }} style={styles.addItemImg} contentFit="cover" />
|
|
|
</ImageBackground>
|
|
|
- <TouchableOpacity style={styles.closeBtn}>
|
|
|
+ <TouchableOpacity style={styles.closeBtn} onPress={() => removeGoods(item)}>
|
|
|
<Image source={{ uri: wishImages.addClose }} style={styles.closeIcon} contentFit="contain" />
|
|
|
</TouchableOpacity>
|
|
|
</View>
|
|
|
))}
|
|
|
- {/* 空位占位 */}
|
|
|
- {Array.from({ length: Math.max(0, 6 - goodsList.length) }).map((_, i) => (
|
|
|
- <View key={`empty-${i}`} style={styles.emptySlot} />
|
|
|
- ))}
|
|
|
</ScrollView>
|
|
|
</View>
|
|
|
</View>
|
|
|
@@ -176,12 +202,11 @@ export default function WishScreen() {
|
|
|
{/* 底部按钮 */}
|
|
|
<TouchableOpacity style={styles.bottomBtn}>
|
|
|
<ImageBackground source={{ uri: Images.common.butBgHui }} style={styles.bottomBtnBg} resizeMode="contain">
|
|
|
- <Text style={styles.bottomBtnText}>还差一点点,去收集</Text>
|
|
|
+ <Text style={styles.bottomBtnText}>{progress >= 100 ? '点亮心愿' : '等待参与'}</Text>
|
|
|
</ImageBackground>
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
<Text style={styles.bottomTip}>*本活动最终解释权归本平台所有</Text>
|
|
|
-
|
|
|
<View style={{ height: 100 }} />
|
|
|
</ScrollView>
|
|
|
</ImageBackground>
|
|
|
@@ -210,17 +235,28 @@ const styles = StyleSheet.create({
|
|
|
placeholder: { width: 40 },
|
|
|
scrollView: { flex: 1 },
|
|
|
|
|
|
+ // 规则按钮
|
|
|
+ ruleBtn: { position: 'absolute', left: 0, zIndex: 99 },
|
|
|
+ ruleBtnImg: { width: 39, height: 20 },
|
|
|
+
|
|
|
+ // 标题
|
|
|
titleBox: { alignItems: 'center', marginBottom: 10 },
|
|
|
titleImg: { width: 288, height: 86 },
|
|
|
|
|
|
- ruleBtn: { position: 'absolute', left: 0, top: 180, zIndex: 10 },
|
|
|
- ruleBtnImg: { width: 39, height: 20 },
|
|
|
-
|
|
|
- swiperBox: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingHorizontal: 20 },
|
|
|
+ // 轮播区域
|
|
|
+ swiperBox: {
|
|
|
+ flexDirection: 'row',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ paddingHorizontal: 20,
|
|
|
+ minHeight: 350,
|
|
|
+ position: 'relative',
|
|
|
+ },
|
|
|
prevBtn: { position: 'absolute', left: 15, zIndex: 10 },
|
|
|
nextBtn: { position: 'absolute', right: 15, zIndex: 10 },
|
|
|
arrowImg: { width: 51, height: 49 },
|
|
|
|
|
|
+ // 卡片
|
|
|
cardBox: { alignItems: 'center' },
|
|
|
card: { alignItems: 'center' },
|
|
|
imgBox: {
|
|
|
@@ -233,7 +269,8 @@ const styles = StyleSheet.create({
|
|
|
alignItems: 'center',
|
|
|
position: 'relative',
|
|
|
},
|
|
|
- spuImage: { width: 200, height: 275 },
|
|
|
+ spuImage: { width: 200, height: 260 },
|
|
|
+ emptyText: { color: '#999', fontSize: 14 },
|
|
|
remainingBox: {
|
|
|
position: 'absolute',
|
|
|
bottom: '15%',
|
|
|
@@ -244,32 +281,113 @@ const styles = StyleSheet.create({
|
|
|
paddingVertical: 5,
|
|
|
},
|
|
|
remainingText: { fontSize: 13, fontWeight: 'bold', color: '#000' },
|
|
|
- cardName: { color: '#D0D0D0', fontSize: 12, marginTop: 13, textAlign: 'center', maxWidth: 200 },
|
|
|
+ cardName: {
|
|
|
+ color: '#D0D0D0',
|
|
|
+ fontSize: 12,
|
|
|
+ marginTop: 13,
|
|
|
+ textAlign: 'center',
|
|
|
+ maxWidth: 200,
|
|
|
+ },
|
|
|
|
|
|
- progressSection: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: 5, paddingHorizontal: 20 },
|
|
|
+ // 指示点
|
|
|
+ dotsBox: { flexDirection: 'row', justifyContent: 'center', marginTop: 10 },
|
|
|
+ dot: { width: 8, height: 8, borderRadius: 4, backgroundColor: '#666', marginHorizontal: 3 },
|
|
|
+ dotActive: { backgroundColor: '#fff' },
|
|
|
+
|
|
|
+ // 进度条
|
|
|
+ progressSection: {
|
|
|
+ flexDirection: 'row',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ marginTop: 5,
|
|
|
+ paddingHorizontal: 20,
|
|
|
+ },
|
|
|
progressLabel: { color: '#fff', fontSize: 12, width: 40 },
|
|
|
- progressBar: { flex: 1, height: 14, backgroundColor: '#FFEABE', borderWidth: 2, borderColor: '#000', marginHorizontal: 5 },
|
|
|
- progressFill: { height: '100%', backgroundColor: '#FFAD00', borderRightWidth: 2, borderRightColor: '#000' },
|
|
|
+ progressBar: {
|
|
|
+ flex: 1,
|
|
|
+ height: 14,
|
|
|
+ backgroundColor: '#FFEABE',
|
|
|
+ borderWidth: 2,
|
|
|
+ borderColor: '#000',
|
|
|
+ marginHorizontal: 5,
|
|
|
+ position: 'relative',
|
|
|
+ },
|
|
|
+ progressFill: {
|
|
|
+ height: '100%',
|
|
|
+ backgroundColor: '#FFAD00',
|
|
|
+ borderRightWidth: 2,
|
|
|
+ borderRightColor: '#000',
|
|
|
+ },
|
|
|
progressText: { color: '#fff', fontSize: 12, width: 40, textAlign: 'right' },
|
|
|
|
|
|
- addSection: { width: SCREEN_WIDTH - 20, height: 124, marginHorizontal: 10, marginTop: 10, paddingTop: 10 },
|
|
|
- addTitle: { color: '#fff', fontSize: 14, textAlign: 'center', fontWeight: '400', textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1, marginBottom: 7 },
|
|
|
- addMain: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 25 },
|
|
|
+ // 材料添加区域
|
|
|
+ addSection: {
|
|
|
+ width: SCREEN_WIDTH - 20,
|
|
|
+ height: 124,
|
|
|
+ marginHorizontal: 10,
|
|
|
+ marginTop: 10,
|
|
|
+ paddingTop: 10,
|
|
|
+ },
|
|
|
+ addTitle: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 14,
|
|
|
+ textAlign: 'center',
|
|
|
+ fontWeight: '400',
|
|
|
+ textShadowColor: '#000',
|
|
|
+ textShadowOffset: { width: 1, height: 1 },
|
|
|
+ textShadowRadius: 1,
|
|
|
+ marginBottom: 7,
|
|
|
+ },
|
|
|
+ addMain: {
|
|
|
+ flexDirection: 'row',
|
|
|
+ alignItems: 'center',
|
|
|
+ paddingHorizontal: 25,
|
|
|
+ },
|
|
|
addBtn: { marginRight: 10 },
|
|
|
- addBtnBg: { width: 42, height: 42, justifyContent: 'center', alignItems: 'center', paddingTop: 5 },
|
|
|
+ addBtnBg: {
|
|
|
+ width: 42,
|
|
|
+ height: 42,
|
|
|
+ justifyContent: 'center',
|
|
|
+ alignItems: 'center',
|
|
|
+ paddingTop: 5,
|
|
|
+ },
|
|
|
addIcon: { width: 16, height: 16 },
|
|
|
addBtnText: { fontSize: 12, color: '#000', fontWeight: '500' },
|
|
|
- addCenter: { flex: 1, height: 60, backgroundColor: '#FFFBEA', paddingLeft: 20, paddingTop: 7 },
|
|
|
+ addCenter: {
|
|
|
+ flex: 1,
|
|
|
+ height: 60,
|
|
|
+ backgroundColor: '#FFFBEA',
|
|
|
+ paddingTop: 7,
|
|
|
+ paddingLeft: 20,
|
|
|
+ },
|
|
|
+ addScrollContent: { paddingRight: 10 },
|
|
|
addItem: { position: 'relative', marginRight: 10 },
|
|
|
addItemBg: { width: 42, height: 42, justifyContent: 'center', alignItems: 'center' },
|
|
|
addItemImg: { width: '80%', height: '80%' },
|
|
|
closeBtn: { position: 'absolute', right: 0, top: 0, width: 13, height: 13 },
|
|
|
closeIcon: { width: '100%', height: '100%' },
|
|
|
- emptySlot: { width: 42, height: 42, backgroundColor: '#f0f0f0', borderWidth: 1, borderColor: '#ddd', marginRight: 10 },
|
|
|
|
|
|
+ // 底部按钮
|
|
|
bottomBtn: { alignItems: 'center', marginTop: -10 },
|
|
|
- bottomBtnBg: { width: 160, height: 60, justifyContent: 'center', alignItems: 'center', paddingTop: 4 },
|
|
|
- bottomBtnText: { color: '#fff', fontSize: 15, fontWeight: 'bold', textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1 },
|
|
|
-
|
|
|
- bottomTip: { color: 'rgba(255,255,255,0.67)', fontSize: 10, textAlign: 'center', marginTop: 5 },
|
|
|
+ bottomBtnBg: {
|
|
|
+ width: 160,
|
|
|
+ height: 60,
|
|
|
+ justifyContent: 'center',
|
|
|
+ alignItems: 'center',
|
|
|
+ paddingTop: 4,
|
|
|
+ },
|
|
|
+ bottomBtnText: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 15,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ textShadowColor: '#000',
|
|
|
+ textShadowOffset: { width: 1, height: 1 },
|
|
|
+ textShadowRadius: 1,
|
|
|
+ },
|
|
|
+ bottomTip: {
|
|
|
+ color: 'rgba(255,255,255,0.67)',
|
|
|
+ fontSize: 10,
|
|
|
+ textAlign: 'center',
|
|
|
+ marginTop: 5,
|
|
|
+ },
|
|
|
});
|