美化页面

This commit is contained in:
李宇奇 2025-07-04 16:51:39 +08:00
parent 342dba7ba0
commit c0a0eed3c0
8 changed files with 950 additions and 425 deletions

11
package-lock.json generated
View File

@ -19,6 +19,7 @@
"react": "18.3.1",
"react-native": "0.75.5",
"react-native-chart-kit": "^6.12.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-safe-area-context": "^5.5.1",
"react-native-screens": "^4.5.0",
"react-native-svg": "^15.12.0",
@ -13357,6 +13358,16 @@
"react-native": "*"
}
},
"node_modules/react-native-linear-gradient": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz",
"integrity": "sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==",
"license": "MIT",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-safe-area-context": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.5.1.tgz",

View File

@ -21,6 +21,7 @@
"react": "18.3.1",
"react-native": "0.75.5",
"react-native-chart-kit": "^6.12.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-safe-area-context": "^5.5.1",
"react-native-screens": "^4.5.0",
"react-native-svg": "^15.12.0",
@ -47,4 +48,4 @@
"engines": {
"node": ">=18"
}
}
}

View File

@ -0,0 +1,73 @@
import React from 'react';
import {View, StyleSheet, Dimensions} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import Svg, {Path} from 'react-native-svg';
const {width} = Dimensions.get('window');
interface WaveBackgroundProps {
height: number;
gradientColors: string[];
}
export const WaveBackground: React.FC<WaveBackgroundProps> = ({
height,
gradientColors,
}) => {
return (
<View style={[styles.container, {height}]}>
<LinearGradient colors={gradientColors} style={StyleSheet.absoluteFill}>
<View style={styles.waveContainer}>
<Svg height={60} width={width} style={styles.wave}>
<Path
d={`M0,20
C${width * 0.25},35
${width * 0.5},5
${width * 0.75},25
C${width * 0.875},35
${width},15
${width},20
L${width},0
L0,0 Z`}
fill="rgba(255, 255, 255, 0.3)"
/>
</Svg>
<Svg height={60} width={width} style={[styles.wave, styles.wave2]}>
<Path
d={`M0,15
C${width * 0.125},5
${width * 0.25},25
${width * 0.5},15
C${width * 0.75},5
${width},25
${width},15
L${width},0
L0,0 Z`}
fill="rgba(255, 255, 255, 0.2)"
/>
</Svg>
</View>
</LinearGradient>
</View>
);
};
const styles = StyleSheet.create({
container: {
width: '100%',
overflow: 'hidden',
},
waveContainer: {
position: 'absolute',
bottom: -1,
left: 0,
right: 0,
},
wave: {
backgroundColor: 'transparent',
},
wave2: {
position: 'absolute',
bottom: 15,
},
});

View File

@ -3,19 +3,41 @@
export const theme = {
colors: {
primary: '#05dcef', // 主题色 (0xff05dcef)
background: '#ffffff', // 背景色 (0xffffffff)
text: '#333333', // 文本颜色 (0xff333333)
accent: '#03a9f4', // 强调色 (0xff03a9f4)
// 派生的颜色
primaryLight: '#66e5f3', // 主题色亮色版
primaryDark: '#04b0be', // 主题色暗色版
textLight: '#666666', // 次要文本颜色
border: '#dddddd', // 边框颜色
error: '#ff3b30', // 错误颜色
success: '#4cd964', // 成功颜色
warning: '#ff9500', // 警告颜色
// 基础颜色
primary: '#4158D0', // 主色调
secondary: '#C850C0', // 次要色调
tertiary: '#FFCC70', // 第三色调
background: '#ffffff', // 背景色
text: '#333333', // 文本颜色
textLight: '#666666', // 次要文本颜色
border: '#dddddd', // 边框颜色
error: '#ff3b30', // 错误颜色
success: '#4cd964', // 成功颜色
warning: '#ff9500', // 警告颜色
cyan: '#00FFFF', // 青色背景
// 渐变色配置
gradients: {
primary: ['#4158D0', '#C850C0', '#FFCC70'], // 主要渐变(蓝紫金)
contrast: ['#00F5A0', '#00D9F5'], // 对比渐变(绿青)
card: ['#9795F0', '#E3C3F1'], // 卡片渐变(柔和紫色)
login: ['#4158D0', '#C850C0', '#FFCC70'], // 登录页面专用渐变
loginWave: ['rgba(255, 255, 255, 0.3)', 'rgba(255, 255, 255, 0.2)'], // 登录页面波浪渐变
header: ['#4158D0', '#C850C0'], // 头部渐变
button: ['#4158D0', '#C850C0'], // 按钮渐变
// 波浪背景渐变
wave: {
start: 'rgba(255, 255, 255, 0.3)',
middle: 'rgba(255, 255, 255, 0.2)',
end: 'rgba(255, 255, 255, 0.1)'
}
},
// 图表颜色
chart: {
blue: '#0077B6', // 深蓝色
orange: '#FB8500', // 明亮的橙色
},
},
// 字体大小
@ -25,6 +47,8 @@ export const theme = {
medium: 16,
large: 18,
xlarge: 20,
xxlarge: 24,
title: 32,
},
// 间距
@ -41,7 +65,8 @@ export const theme = {
small: 4,
medium: 8,
large: 12,
round: 999,
xl: 16,
circle: 999,
},
// 阴影
@ -77,6 +102,12 @@ export const theme = {
elevation: 6,
},
},
// 波浪效果配置
wave: {
height: 60,
opacity: 1,
},
};
// 类型定义

View File

@ -5,11 +5,19 @@ import {
StyleSheet,
TouchableOpacity,
InteractionManager,
Image,
Dimensions,
} from 'react-native';
import {useNavigation, useIsFocused} from '@react-navigation/native';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {RootStackParamList} from '../../navigation/types';
import {Screen} from '../../components/common/Screen';
import {WaveBackground} from '../../components/common/WaveBackground';
import LinearGradient from 'react-native-linear-gradient';
import Svg, {Path, Defs, LinearGradient as SvgLinearGradient, Stop} from 'react-native-svg';
import {useTheme} from '../../contexts/ThemeContext';
const {width} = Dimensions.get('window');
type LoginScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
@ -19,6 +27,7 @@ type LoginScreenNavigationProp = NativeStackNavigationProp<
export const LoginScreen: React.FC = () => {
const navigation = useNavigation<LoginScreenNavigationProp>();
const isFocused = useIsFocused();
const theme = useTheme();
const handleLogin = useCallback(() => {
if (!isFocused) return;
@ -32,53 +41,219 @@ export const LoginScreen: React.FC = () => {
}, [navigation, isFocused]);
return (
<Screen>
{/* 头部导航栏 */}
<View style={styles.header}>
<Text style={styles.headerTitle}></Text>
<Screen style={[styles.screen, {backgroundColor: theme.colors.background}]}>
{/* 头部背景 */}
<View style={styles.headerContainer}>
<LinearGradient
colors={theme.colors.gradients.primary}
style={[StyleSheet.absoluteFill, styles.gradientBackground]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
>
{/* 半透明波浪效果 */}
<View style={styles.waveOverlay}>
<Svg height="100%" width={width} style={styles.waveSvg}>
<Path
d={`M0,50
C${width * 0.2},30
${width * 0.4},70
${width * 0.6},50
C${width * 0.8},30
${width},60
${width},50`}
fill="none"
stroke="rgba(255, 255, 255, 0.2)"
strokeWidth="2"
/>
<Path
d={`M0,70
C${width * 0.2},50
${width * 0.4},90
${width * 0.6},70
C${width * 0.8},50
${width},80
${width},70`}
fill="none"
stroke="rgba(255, 255, 255, 0.15)"
strokeWidth="2"
/>
</Svg>
</View>
</LinearGradient>
<View style={styles.headerContent}>
<Text style={[styles.headerTitle, { color: theme.colors.background }]}>
</Text>
<Text style={[styles.headerSubtitle, { color: theme.colors.background }]}>
</Text>
</View>
</View>
{/* 不规则曲线背景 */}
<View style={styles.curveContainer}>
<Svg height="120" width={width} style={styles.curve}>
<Defs>
<SvgLinearGradient id="contrastGradient" x1="0" y1="0" x2="1" y2="0">
<Stop offset="0" stopColor={theme.colors.gradients.contrast[0]} />
<Stop offset="1" stopColor={theme.colors.gradients.contrast[1]} />
</SvgLinearGradient>
</Defs>
<Path
d={`M0,120
L0,50
C${width * 0.3},20 ${width * 0.7},80 ${width},30
L${width},120
Z`}
fill="url(#contrastGradient)"
/>
</Svg>
</View>
{/* 主体内容 */}
<View style={styles.content}>
{/* 登录按钮 */}
<TouchableOpacity
style={styles.loginButton}
onPress={handleLogin}>
<Text style={styles.loginButtonText}></Text>
</TouchableOpacity>
<View style={[styles.contentWrapper]}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={StyleSheet.absoluteFill}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
/>
<View style={styles.content}>
{/* Logo占位 */}
<View style={styles.logoContainer}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={[styles.logoCircle, theme.shadow.medium]}>
<Text style={[styles.logoText, {color: theme.colors.primary}]}>
JW
</Text>
</LinearGradient>
</View>
{/* 登录按钮 */}
<TouchableOpacity
style={[styles.loginButtonContainer, theme.shadow.medium]}
onPress={handleLogin}>
<LinearGradient
colors={theme.colors.gradients.primary}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.loginButton}>
<Text style={[styles.loginButtonText, {color: theme.colors.background}]}>
</Text>
</LinearGradient>
</TouchableOpacity>
</View>
{/* 底部版权信息 */}
<View style={styles.footer}>
<Text style={[styles.footerText, {color: theme.colors.textLight}]}>
© 2024
</Text>
</View>
</View>
</Screen>
);
};
const styles = StyleSheet.create({
header: {
height: 56,
justifyContent: 'center',
screen: {
flex: 1,
},
headerContainer: {
height: 280,
position: 'relative',
overflow: 'hidden',
},
headerContent: {
position: 'absolute',
top: 60,
left: 0,
right: 0,
alignItems: 'center',
backgroundColor: '#1890ff',
},
headerTitle: {
color: '#fff',
fontSize: 32,
fontWeight: 'bold',
textShadowColor: 'rgba(0, 0, 0, 0.2)',
textShadowOffset: {width: 1, height: 1},
textShadowRadius: 3,
},
headerSubtitle: {
fontSize: 18,
fontWeight: '600',
marginTop: 8,
opacity: 0.9,
},
curveContainer: {
position: 'absolute',
top: 200,
left: 0,
right: 0,
zIndex: 1,
},
curve: {
position: 'absolute',
top: 0,
},
contentWrapper: {
flex: 1,
marginTop: 160,
},
content: {
flex: 1,
alignItems: 'center',
paddingTop: 15,
paddingTop: 40,
},
logoContainer: {
marginBottom: 40,
},
logoCircle: {
width: 120,
height: 120,
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
},
logoText: {
fontSize: 40,
fontWeight: 'bold',
},
loginButtonContainer: {
width: width * 0.8,
maxWidth: 300,
height: 50,
borderRadius: 25,
overflow: 'hidden',
},
loginButton: {
backgroundColor: '#1890ff',
width: 250,
height: 44,
borderRadius: 4,
alignItems: 'center',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
loginButtonText: {
color: '#fff',
fontSize: 16,
fontSize: 18,
fontWeight: '600',
},
footer: {
padding: 20,
alignItems: 'center',
},
footerText: {
fontSize: 12,
},
gradientBackground: {
opacity: 0.95,
},
waveOverlay: {
position: 'absolute',
width: '100%',
height: '100%',
opacity: 0.6,
},
waveSvg: {
position: 'absolute',
top: 0,
},
});

View File

@ -14,6 +14,10 @@ import { RootStackParamList } from '../../navigation/types';
import { PieChart } from 'react-native-chart-kit';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { useTheme } from '../../contexts/ThemeContext';
import LinearGradient from 'react-native-linear-gradient';
import Svg, { Path } from 'react-native-svg';
const { width } = Dimensions.get('window');
type HomeScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
@ -33,12 +37,14 @@ export const HomeScreen: React.FC = () => {
const [fontLoaded, setFontLoaded] = useState(false);
useEffect(() => {
Icon.loadFont().then(() => {
console.log('Icon fonts loaded');
setFontLoaded(true);
}).catch(error => {
console.error('Failed to load icon fonts:', error);
});
Icon.loadFont()
.then(() => {
console.log('Icon fonts loaded');
setFontLoaded(true);
})
.catch(error => {
console.error('Failed to load icon fonts:', error);
});
}, []);
const menuItems: MenuItem[] = [
@ -50,16 +56,16 @@ export const HomeScreen: React.FC = () => {
{
name: '空闲',
population: 40,
color: theme.colors.success || '#4CAF50',
color: theme.colors.chart.blue,
legendFontColor: theme.colors.textLight,
legendFontSize: 15,
legendFontSize: theme.fontSize.regular,
},
{
name: '占用',
population: 60,
color: theme.colors.warning || '#FF9800',
color: theme.colors.chart.orange,
legendFontColor: theme.colors.textLight,
legendFontSize: 15,
legendFontSize: theme.fontSize.regular,
},
];
@ -69,94 +75,162 @@ export const HomeScreen: React.FC = () => {
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
};
const screenWidth = Dimensions.get('window').width;
if (!fontLoaded) {
return (
<View style={[styles.loadingContainer, {backgroundColor: theme.colors.background}]}>
<Text style={{color: theme.colors.text}}>...</Text>
<View style={[styles.loadingContainer, { backgroundColor: theme.colors.background }]}>
<Text style={{ color: theme.colors.text }}>...</Text>
</View>
);
}
return (
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<View style={[styles.header, {backgroundColor: theme.colors.primary}]}>
<TouchableOpacity
onPress={() => setIsDrawerOpen(!isDrawerOpen)}
style={styles.menuButton}>
<Icon name="menu" size={24} color={theme.colors.background} />
</TouchableOpacity>
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>
WMS移动终端
</Text>
<View style={styles.headerRight}>
<SafeAreaView style={[styles.container, { backgroundColor: theme.colors.background }]}>
{/* 头部区域 */}
<View style={styles.headerSection}>
{/* 渐变背景 */}
<LinearGradient
colors={theme.colors.gradients.primary}
style={StyleSheet.absoluteFill}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
>
{/* 半透明波浪效果 */}
<View style={styles.waveOverlay}>
<Svg height="100%" width={width} style={styles.waveSvg}>
<Path
d={`M0,50
C${width * 0.2},30
${width * 0.4},70
${width * 0.6},50
C${width * 0.8},30
${width},60
${width},50`}
fill="none"
stroke="rgba(255, 255, 255, 0.2)"
strokeWidth="2"
/>
<Path
d={`M0,70
C${width * 0.2},50
${width * 0.4},90
${width * 0.6},70
C${width * 0.8},50
${width},80
${width},70`}
fill="none"
stroke="rgba(255, 255, 255, 0.15)"
strokeWidth="2"
/>
</Svg>
</View>
</LinearGradient>
{/* 头部内容 */}
<View style={styles.headerContent}>
<TouchableOpacity
onPress={() => setIsDrawerOpen(!isDrawerOpen)}
style={styles.menuButton}>
<Icon name="menu" size={24} color={theme.colors.background} />
</TouchableOpacity>
<Text style={[styles.headerTitle, { color: theme.colors.background }]}>
WMS移动终端
</Text>
<TouchableOpacity style={styles.iconButton}>
<Icon name="notifications" size={24} color={theme.colors.background} />
</TouchableOpacity>
</View>
</View>
{/* 主体内容 */}
<View style={styles.mainContent}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={StyleSheet.absoluteFill}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
/>
<ScrollView contentContainerStyle={styles.scrollContent}>
{/* 快捷操作区 */}
<View style={styles.quickActions}>
{menuItems.map((item, index) => (
<TouchableOpacity
key={index}
style={[styles.actionCard]}
onPress={() => navigation.navigate(item.route)}>
<LinearGradient
colors={theme.colors.gradients.card}
style={[StyleSheet.absoluteFill, {borderRadius: 12}]}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}
/>
<LinearGradient
colors={theme.colors.gradients.primary}
style={styles.iconGradient}>
<Icon name={item.icon} size={32} color={theme.colors.background} />
</LinearGradient>
<Text style={[styles.actionTitle, {color: theme.colors.background}]}>
{item.title}
</Text>
</TouchableOpacity>
))}
</View>
{/* 图表区域 */}
<View style={styles.chartSection}>
<Text style={[styles.chartTitle, {color: theme.colors.background}]}>
</Text>
<View style={styles.chartContainer}>
<PieChart
data={stockData}
width={width - 48}
height={220}
chartConfig={chartConfig}
accessor="population"
backgroundColor="transparent"
paddingLeft="15"
absolute
/>
</View>
</View>
</ScrollView>
</View>
{/* 侧边菜单 */}
{isDrawerOpen && (
<View style={[styles.drawer, {backgroundColor: theme.colors.background}]}>
<View style={[styles.drawerHeader, {backgroundColor: theme.colors.primary}]}>
<Text style={[styles.drawerTitle, {color: theme.colors.background}]}>
</Text>
<Text style={[styles.drawerSubtitle, {color: theme.colors.background}]}>
使WMS移动终端
</Text>
</View>
{menuItems.map((item, index) => (
<TouchableOpacity
key={index}
style={[styles.drawerItem, {borderBottomColor: theme.colors.border}]}
onPress={() => {
setIsDrawerOpen(false);
navigation.navigate(item.route);
}}>
<View style={styles.iconContainer}>
<Icon
name={item.icon}
size={28}
color={theme.colors.primary}
/>
</View>
<Text style={[styles.drawerItemText, {color: theme.colors.text}]}>
{item.title}
<>
<View style={[styles.drawer, { backgroundColor: theme.colors.background }]}>
<LinearGradient
colors={theme.colors.gradients.primary}
style={styles.drawerHeader}>
<Text style={[styles.drawerTitle, { color: theme.colors.background }]}>
</Text>
</TouchableOpacity>
))}
</View>
)}
{/* 主体内容 */}
<ScrollView style={[styles.content, {backgroundColor: theme.colors.background}]}>
<Text style={[styles.chartTitle, {color: theme.colors.text}]}>
</Text>
<View style={styles.chartContainer}>
<PieChart
data={stockData}
width={screenWidth - 40}
height={220}
chartConfig={chartConfig}
accessor="population"
backgroundColor="transparent"
paddingLeft="15"
absolute
<Text style={[styles.drawerSubtitle, { color: theme.colors.background }]}>
使WMS移动终端
</Text>
</LinearGradient>
{menuItems.map((item, index) => (
<TouchableOpacity
key={index}
style={[styles.drawerItem, { borderBottomColor: theme.colors.border }]}
onPress={() => {
setIsDrawerOpen(false);
navigation.navigate(item.route);
}}>
<View style={styles.drawerIconContainer}>
<Icon name={item.icon} size={28} color={theme.colors.primary} />
</View>
<Text style={[styles.drawerItemText, { color: theme.colors.text }]}>
{item.title}
</Text>
</TouchableOpacity>
))}
</View>
<TouchableOpacity
style={styles.overlay}
onPress={() => setIsDrawerOpen(false)}
/>
</View>
</ScrollView>
{/* 遮罩层 */}
{isDrawerOpen && (
<TouchableOpacity
style={styles.overlay}
onPress={() => setIsDrawerOpen(false)}
/>
</>
)}
</SafeAreaView>
);
@ -166,45 +240,96 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
mainContent: {
flex: 1,
position: 'relative',
},
scrollContent: {
flexGrow: 1,
paddingVertical: 20,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
header: {
height: 56,
headerSection: {
height: 160,
position: 'relative',
overflow: 'hidden',
},
waveOverlay: {
position: 'absolute',
width: '100%',
height: '100%',
opacity: 0.6,
},
waveSvg: {
position: 'absolute',
top: 0,
},
headerContent: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingTop: 16,
justifyContent: 'space-between',
height: 160,
},
menuButton: {
padding: 8,
},
headerTitle: {
flex: 1,
fontSize: 18,
fontWeight: '600',
textAlign: 'center',
},
headerRight: {
width: 40,
flexDirection: 'row',
justifyContent: 'flex-end',
},
iconButton: {
padding: 8,
},
content: {
flex: 1,
marginTop: -20,
},
quickActions: {
flexDirection: 'row',
justifyContent: 'space-around',
paddingHorizontal: 16,
marginTop: 20,
},
actionCard: {
width: width / 2 - 24,
borderRadius: 12,
padding: 20,
alignItems: 'center',
overflow: 'hidden',
},
iconGradient: {
width: 64,
height: 64,
borderRadius: 32,
justifyContent: 'center',
alignItems: 'center',
marginBottom: 12,
},
actionTitle: {
fontSize: 16,
textAlign: 'center',
},
chartSection: {
borderRadius: 12,
margin: 16,
padding: 16,
overflow: 'hidden',
},
chartTitle: {
fontSize: 16,
marginBottom: 10,
fontSize: 18,
fontWeight: '600',
marginBottom: 16,
},
chartContainer: {
alignItems: 'center',
marginTop: 20,
},
drawer: {
position: 'absolute',
@ -227,6 +352,7 @@ const styles = StyleSheet.create({
},
drawerSubtitle: {
fontSize: 14,
opacity: 0.9,
},
drawerItem: {
flexDirection: 'row',
@ -234,7 +360,7 @@ const styles = StyleSheet.create({
padding: 16,
borderBottomWidth: 1,
},
iconContainer: {
drawerIconContainer: {
width: 32,
height: 32,
justifyContent: 'center',

View File

@ -15,6 +15,8 @@ import {useNavigation} from '@react-navigation/native';
import {RootStackParamList} from '../../navigation/types';
import {useTheme} from '../../contexts/ThemeContext';
import Icon from 'react-native-vector-icons/MaterialIcons';
import LinearGradient from 'react-native-linear-gradient';
import Svg, {Path} from 'react-native-svg';
interface StockInEmptyResponse {
code: number;
@ -83,7 +85,11 @@ export const StockInEmpty: React.FC = () => {
return (
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<View style={[styles.header, {backgroundColor: theme.colors.primary}]}>
<LinearGradient
colors={[theme.colors.primary, theme.colors.secondary, theme.colors.tertiary]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.header}>
<TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.backButton}>
@ -91,12 +97,33 @@ export const StockInEmpty: React.FC = () => {
</TouchableOpacity>
<Text style={[styles.headerTitle, {color: theme.colors.background}]}></Text>
<View style={styles.headerRight} />
</LinearGradient>
{/* 波浪效果 */}
<View style={styles.waveContainer}>
<Svg
height="100%"
width="100%"
viewBox="0 0 1440 320"
style={styles.waveSvg}
preserveAspectRatio="none">
<Path
fill={`${theme.colors.tertiary}40`}
d="M0,96L48,112C96,128,192,160,288,186.7C384,213,480,235,576,213.3C672,192,768,128,864,128C960,128,1056,192,1152,213.3C1248,235,1344,213,1392,202.7L1440,192L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"
/>
</Svg>
</View>
{/* 主体内容 */}
<View style={styles.content}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={StyleSheet.absoluteFill}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
/>
{/* 说明文字 */}
<View style={styles.infoSection}>
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.primary}15`}]}>
<Icon name="info-outline" size={24} color={theme.colors.primary} />
<Text style={[styles.infoText, {color: theme.colors.text}]}>
@ -108,7 +135,10 @@ export const StockInEmpty: React.FC = () => {
<Text style={[styles.inputLabel, {color: theme.colors.text}]}>
<Text style={styles.required}>*</Text>
</Text>
<View style={[styles.inputWrapper, {borderColor: theme.colors.border}]}>
<View style={[styles.inputWrapper, {
borderColor: theme.colors.border,
backgroundColor: `${theme.colors.background}CC`,
}]}>
<Icon name="qr-code-scanner" size={24} color={theme.colors.primary} style={styles.inputIcon} />
<TextInput
style={[styles.input, {color: theme.colors.text}]}
@ -129,25 +159,27 @@ export const StockInEmpty: React.FC = () => {
</View>
{/* 提交按钮 */}
<TouchableOpacity
style={[
styles.submitButton,
{backgroundColor: theme.colors.primary},
loading && styles.submitButtonDisabled,
]}
onPress={handleEmptyIn}
disabled={loading}>
{loading ? (
<ActivityIndicator color={theme.colors.background} />
) : (
<>
<Icon name="save" size={24} color={theme.colors.background} style={styles.submitIcon} />
<Text style={[styles.submitButtonText, {color: theme.colors.background}]}>
</Text>
</>
)}
</TouchableOpacity>
<LinearGradient
colors={[theme.colors.primary, theme.colors.secondary]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={[styles.submitButton, loading && styles.submitButtonDisabled]}>
<TouchableOpacity
style={styles.submitButtonContent}
onPress={handleEmptyIn}
disabled={loading}>
{loading ? (
<ActivityIndicator color={theme.colors.background} />
) : (
<>
<Icon name="save" size={24} color={theme.colors.background} style={styles.submitIcon} />
<Text style={[styles.submitButtonText, {color: theme.colors.background}]}>
</Text>
</>
)}
</TouchableOpacity>
</LinearGradient>
</View>
</SafeAreaView>
);
@ -169,6 +201,19 @@ const styles = StyleSheet.create({
shadowOpacity: 0.2,
shadowRadius: 2,
},
waveContainer: {
height: 100,
backgroundColor: 'transparent',
position: 'absolute',
top: 56,
left: 0,
right: 0,
zIndex: -1,
},
waveSvg: {
position: 'absolute',
top: 0,
},
backButton: {
padding: 8,
},
@ -186,7 +231,6 @@ const styles = StyleSheet.create({
infoSection: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'rgba(24, 144, 255, 0.1)',
padding: 16,
borderRadius: 8,
marginBottom: 24,
@ -214,7 +258,6 @@ const styles = StyleSheet.create({
borderRadius: 8,
height: 48,
paddingHorizontal: 12,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
},
inputIcon: {
marginRight: 8,
@ -231,9 +274,6 @@ const styles = StyleSheet.create({
submitButton: {
height: 48,
borderRadius: 24,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginTop: 32,
elevation: 2,
shadowColor: '#000',
@ -241,6 +281,12 @@ const styles = StyleSheet.create({
shadowOpacity: 0.1,
shadowRadius: 2,
},
submitButtonContent: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
submitButtonDisabled: {
opacity: 0.6,
},

View File

@ -12,6 +12,8 @@ import {
import {useNavigation} from '@react-navigation/native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import {useTheme} from '../../contexts/ThemeContext';
import LinearGradient from 'react-native-linear-gradient';
import Svg, {Path} from 'react-native-svg';
interface PackageDataItem {
id: string;
@ -236,7 +238,11 @@ const StockInWheelManual: React.FC = () => {
return (
<View style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<View style={[styles.header, {backgroundColor: theme.colors.primary}]}>
<LinearGradient
colors={[theme.colors.primary, theme.colors.secondary, theme.colors.tertiary]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.header}>
<TouchableOpacity
style={styles.backButton}
onPress={() => navigation.goBack()}>
@ -246,285 +252,326 @@ const StockInWheelManual: React.FC = () => {
</Text>
<View style={styles.headerRight} />
</LinearGradient>
{/* 波浪效果 */}
<View style={styles.waveContainer}>
<Svg
height="100%"
width="100%"
viewBox="0 0 1440 320"
style={styles.waveSvg}
preserveAspectRatio="none">
<Path
fill={`${theme.colors.tertiary}40`}
d="M0,96L48,112C96,128,192,160,288,186.7C384,213,480,235,576,213.3C672,192,768,128,864,128C960,128,1056,192,1152,213.3C1248,235,1344,213,1392,202.7L1440,192L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"
/>
</Svg>
</View>
<ScrollView style={[styles.content, {backgroundColor: theme.colors.background}]}>
{/* 信息提示区 */}
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.primary}15`}]}>
<Icon name="info-outline" size={24} color={theme.colors.primary} />
<Text style={[styles.infoText, {color: theme.colors.text}]}>
</Text>
</View>
{/* 载具号输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {borderColor: theme.colors.border}]}>
<Icon name="qr-code-scanner" size={24} color={theme.colors.primary} style={styles.inputIcon} />
<TextInput
ref={vehicleInputRef}
style={[styles.input, {color: theme.colors.text}]}
value={vehicleCode}
onChangeText={setVehicleCode}
placeholder="请扫描或输入载具号"
placeholderTextColor={theme.colors.textLight}
/>
{vehicleCode.length > 0 && (
<TouchableOpacity
onPress={() => setVehicleCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
</TouchableOpacity>
)}
<View style={styles.mainContent}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={StyleSheet.absoluteFill}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
/>
<ScrollView contentContainerStyle={styles.scrollContent}>
{/* 信息提示区 */}
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.primary}15`}]}>
<Icon name="info-outline" size={24} color={theme.colors.primary} />
<Text style={[styles.infoText, {color: theme.colors.text}]}>
</Text>
</View>
</View>
{/* 条码输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {borderColor: theme.colors.border}]}>
<Icon name="qr-code-2" size={24} color={theme.colors.primary} style={styles.inputIcon} />
<TextInput
ref={goodsInputRef}
style={[styles.input, {color: theme.colors.text}]}
value={goodsCode}
onChangeText={setGoodsCode}
placeholder="请扫描物料二维码"
placeholderTextColor={theme.colors.textLight}
/>
{goodsCode.length > 0 && (
<TouchableOpacity
onPress={() => setGoodsCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
</TouchableOpacity>
)}
</View>
</View>
{/* 选项区域 */}
<View style={styles.optionsContainer}>
{/* 区域选择 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
areaID === '有卤' && styles.radioButtonActive,
areaID === '有卤' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setAreaID('有卤')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
areaID === '有卤' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
areaID === '无卤' && styles.radioButtonActive,
areaID === '无卤' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setAreaID('无卤')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
areaID === '无卤' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
{/* 载具号输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {
borderColor: theme.colors.border,
backgroundColor: `${theme.colors.background}CC`,
}]}>
<Icon name="qr-code-scanner" size={24} color={theme.colors.primary} style={styles.inputIcon} />
<TextInput
ref={vehicleInputRef}
style={[styles.input, {color: theme.colors.text}]}
value={vehicleCode}
onChangeText={setVehicleCode}
placeholder="请扫描或输入载具号"
placeholderTextColor={theme.colors.textLight}
/>
{vehicleCode.length > 0 && (
<TouchableOpacity
onPress={() => setVehicleCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
</TouchableOpacity>
)}
</View>
</View>
{/* 工厂选择 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
factory === '二厂' && styles.radioButtonActive,
factory === '二厂' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setFactory('二厂')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
factory === '二厂' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
factory === '三厂' && styles.radioButtonActive,
factory === '三厂' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setFactory('三厂')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
factory === '三厂' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
{/* 条码输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {
borderColor: theme.colors.border,
backgroundColor: `${theme.colors.background}CC`,
}]}>
<Icon name="qr-code-2" size={24} color={theme.colors.primary} style={styles.inputIcon} />
<TextInput
ref={goodsInputRef}
style={[styles.input, {color: theme.colors.text}]}
value={goodsCode}
onChangeText={setGoodsCode}
placeholder="请扫描物料二维码"
placeholderTextColor={theme.colors.textLight}
/>
{goodsCode.length > 0 && (
<TouchableOpacity
onPress={() => setGoodsCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
</TouchableOpacity>
)}
</View>
</View>
{/* 状态选择 - 改为与区域、工厂相同的样式 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View style={styles.radioGroup}>
{['合格', '不合格', '封存', '待检', '进口物料'].map((item) => (
<TouchableOpacity
key={item}
style={[
styles.radioButton,
{borderColor: theme.colors.border},
status === item && styles.radioButtonActive,
status === item && {backgroundColor: theme.colors.primary},
]}
onPress={() => setStatus(item)}>
<Text
{/* 选项区域 */}
<View style={styles.optionsContainer}>
{/* 区域选择 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
areaID === '有卤' && styles.radioButtonActive,
areaID === '有卤' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setAreaID('有卤')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
areaID === '有卤' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
areaID === '无卤' && styles.radioButtonActive,
areaID === '无卤' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setAreaID('无卤')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
areaID === '无卤' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
</View>
</View>
{/* 工厂选择 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
factory === '二厂' && styles.radioButtonActive,
factory === '二厂' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setFactory('二厂')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
factory === '二厂' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.radioButton,
{borderColor: theme.colors.border},
factory === '三厂' && styles.radioButtonActive,
factory === '三厂' && {backgroundColor: theme.colors.primary},
]}
onPress={() => setFactory('三厂')}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
factory === '三厂' && {color: theme.colors.background},
]}>
</Text>
</TouchableOpacity>
</View>
</View>
{/* 状态选择 - 改为与区域、工厂相同的样式 */}
<View style={styles.optionGroup}>
<Text style={[styles.optionLabel, {color: theme.colors.text}]}></Text>
<View style={styles.radioGroup}>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View style={styles.radioGroup}>
{['合格', '不合格', '封存', '待检', '进口物料'].map((item) => (
<TouchableOpacity
key={item}
style={[
styles.radioText,
{color: theme.colors.text},
status === item && {color: theme.colors.background},
]}>
{item}
</Text>
</TouchableOpacity>
))}
</View>
</ScrollView>
styles.radioButton,
{borderColor: theme.colors.border},
status === item && styles.radioButtonActive,
status === item && {backgroundColor: theme.colors.primary},
]}
onPress={() => setStatus(item)}>
<Text
style={[
styles.radioText,
{color: theme.colors.text},
status === item && {color: theme.colors.background},
]}>
{item}
</Text>
</TouchableOpacity>
))}
</View>
</ScrollView>
</View>
</View>
</View>
</View>
{/* 操作按钮区 */}
<View style={styles.buttonGroup}>
<TouchableOpacity
style={[styles.button, styles.addButton, {backgroundColor: theme.colors.primary}]}
onPress={resolveCode}>
<Icon name="add-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
{/* 操作按钮区 */}
<View style={styles.buttonGroup}>
<LinearGradient
colors={[theme.colors.primary, theme.colors.secondary]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.button}>
<TouchableOpacity
style={styles.buttonContent}
onPress={resolveCode}>
<Icon name="add-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
</LinearGradient>
<TouchableOpacity
style={[styles.button, styles.completeButton, {backgroundColor: theme.colors.success}]}
onPress={wheelComplete}>
<Icon name="check-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
</View>
{/* 物料列表 */}
<View style={styles.tableContainer}>
<View style={styles.tableHeader}>
<Icon name="list-alt" size={24} color={theme.colors.primary} />
<Text style={[styles.tableTitle, {color: theme.colors.text}]}>
({packageData.length})
</Text>
<LinearGradient
colors={[theme.colors.success, theme.colors.secondary]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.button}>
<TouchableOpacity
style={styles.buttonContent}
onPress={wheelComplete}>
<Icon name="check-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
</LinearGradient>
</View>
{packageData.map((item, index) => (
<View
key={item.id}
style={[
styles.card,
{
backgroundColor: theme.colors.background,
borderColor: theme.colors.border,
},
]}>
{/* 卡片头部 */}
<View style={styles.cardHeader}>
<View style={styles.cardHeaderLeft}>
<Text style={[styles.cardHeaderText, {color: theme.colors.text}]}>
{item.id}
</Text>
<Text style={[styles.cardHeaderText, {color: theme.colors.textLight}]}>
{item.segment1}
</Text>
</View>
<View style={styles.cardActions}>
<TouchableOpacity
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.primary}15`}]}
onPress={() => showDetails(item)}>
<Icon name="info-outline" size={20} color={theme.colors.primary} />
</TouchableOpacity>
<TouchableOpacity
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.error}15`}]}
onPress={() => deleteItem(item.id)}>
<Icon name="delete-outline" size={20} color={theme.colors.error} />
</TouchableOpacity>
</View>
</View>
{/* 物料列表 */}
<View style={styles.tableContainer}>
<View style={styles.tableHeader}>
<Icon name="list-alt" size={24} color={theme.colors.primary} />
<Text style={[styles.tableTitle, {color: theme.colors.text}]}>
({packageData.length})
</Text>
</View>
{/* 卡片内容 */}
<View style={styles.cardContent}>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.itemId}</Text>
{packageData.map((item, index) => (
<View
key={item.id}
style={[styles.card]}>
<LinearGradient
colors={theme.colors.gradients.contrast}
style={[StyleSheet.absoluteFill, {borderRadius: 12}]}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
/>
{/* 卡片头部 */}
<View style={styles.cardHeader}>
<View style={styles.cardHeaderLeft}>
<Text style={[styles.cardHeaderText, {color: theme.colors.background}]}>
{item.id}
</Text>
<Text style={[styles.cardHeaderText, {color: theme.colors.background}]}>
{item.segment1}
</Text>
</View>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.batch}</Text>
</View>
</View>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}></Text>
<View style={styles.cardActions}>
<TouchableOpacity
style={styles.editableValue}
onPress={() => modifyNumber(item.id)}>
<Text style={[styles.cardValue, {color: theme.colors.primary}]}>
{item.quantity}
</Text>
<Icon name="edit" size={16} color={theme.colors.primary} />
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.primary}15`}]}
onPress={() => showDetails(item)}>
<Icon name="info-outline" size={20} color={theme.colors.primary} />
</TouchableOpacity>
<TouchableOpacity
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.error}15`}]}
onPress={() => deleteItem(item.id)}>
<Icon name="delete-outline" size={20} color={theme.colors.error} />
</TouchableOpacity>
</View>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.weight}</Text>
</View>
</View>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.productData}</Text>
{/* 卡片内容 */}
<View style={styles.cardContent}>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.background}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.itemId}</Text>
</View>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.background}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.batch}</Text>
</View>
</View>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.background}]}></Text>
<TouchableOpacity
style={styles.editableValue}
onPress={() => modifyNumber(item.id)}>
<Text style={[styles.cardValue, {color: theme.colors.background}]}>
{item.quantity}
</Text>
<Icon name="edit" size={16} color={theme.colors.background} />
</TouchableOpacity>
</View>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.background}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.weight}</Text>
</View>
</View>
<View style={styles.cardRow}>
<View style={styles.cardField}>
<Text style={[styles.cardLabel, {color: theme.colors.background}]}></Text>
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.productData}</Text>
</View>
</View>
</View>
</View>
</View>
))}
</View>
</ScrollView>
))}
</View>
</ScrollView>
</View>
{loading && (
<View style={[styles.loadingOverlay, {backgroundColor: 'rgba(0, 0, 0, 0.7)'}]}>
@ -544,6 +591,14 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
mainContent: {
flex: 1,
position: 'relative',
},
scrollContent: {
flexGrow: 1,
padding: 16,
},
header: {
height: 56,
flexDirection: 'row',
@ -556,6 +611,19 @@ const styles = StyleSheet.create({
shadowOpacity: 0.2,
shadowRadius: 2,
},
waveContainer: {
height: 100,
backgroundColor: 'transparent',
position: 'absolute',
top: 56,
left: 0,
right: 0,
zIndex: -1,
},
waveSvg: {
position: 'absolute',
top: 0,
},
backButton: {
padding: 8,
},
@ -566,10 +634,6 @@ const styles = StyleSheet.create({
headerRight: {
width: 40,
},
content: {
flex: 1,
padding: 16,
},
infoSection: {
flexDirection: 'row',
alignItems: 'center',
@ -650,15 +714,18 @@ const styles = StyleSheet.create({
flex: 1,
height: 48,
borderRadius: 24,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
elevation: 2,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 2,
},
buttonContent: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
buttonIcon: {
marginRight: 8,
},
@ -683,13 +750,8 @@ const styles = StyleSheet.create({
},
card: {
borderRadius: 12,
borderWidth: 1,
marginBottom: 12,
elevation: 2,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 2,
overflow: 'hidden',
},
cardHeader: {
flexDirection: 'row',