美化页面
This commit is contained in:
parent
342dba7ba0
commit
c0a0eed3c0
11
package-lock.json
generated
11
package-lock.json
generated
|
|
@ -19,6 +19,7 @@
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-native": "0.75.5",
|
"react-native": "0.75.5",
|
||||||
"react-native-chart-kit": "^6.12.0",
|
"react-native-chart-kit": "^6.12.0",
|
||||||
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
"react-native-safe-area-context": "^5.5.1",
|
"react-native-safe-area-context": "^5.5.1",
|
||||||
"react-native-screens": "^4.5.0",
|
"react-native-screens": "^4.5.0",
|
||||||
"react-native-svg": "^15.12.0",
|
"react-native-svg": "^15.12.0",
|
||||||
|
|
@ -13357,6 +13358,16 @@
|
||||||
"react-native": "*"
|
"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": {
|
"node_modules/react-native-safe-area-context": {
|
||||||
"version": "5.5.1",
|
"version": "5.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.5.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-native": "0.75.5",
|
"react-native": "0.75.5",
|
||||||
"react-native-chart-kit": "^6.12.0",
|
"react-native-chart-kit": "^6.12.0",
|
||||||
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
"react-native-safe-area-context": "^5.5.1",
|
"react-native-safe-area-context": "^5.5.1",
|
||||||
"react-native-screens": "^4.5.0",
|
"react-native-screens": "^4.5.0",
|
||||||
"react-native-svg": "^15.12.0",
|
"react-native-svg": "^15.12.0",
|
||||||
|
|
|
||||||
73
src/components/common/WaveBackground.tsx
Normal file
73
src/components/common/WaveBackground.tsx
Normal 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,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -3,19 +3,41 @@
|
||||||
|
|
||||||
export const theme = {
|
export const theme = {
|
||||||
colors: {
|
colors: {
|
||||||
primary: '#05dcef', // 主题色 (0xff05dcef)
|
// 基础颜色
|
||||||
background: '#ffffff', // 背景色 (0xffffffff)
|
primary: '#4158D0', // 主色调
|
||||||
text: '#333333', // 文本颜色 (0xff333333)
|
secondary: '#C850C0', // 次要色调
|
||||||
accent: '#03a9f4', // 强调色 (0xff03a9f4)
|
tertiary: '#FFCC70', // 第三色调
|
||||||
|
background: '#ffffff', // 背景色
|
||||||
// 派生的颜色
|
text: '#333333', // 文本颜色
|
||||||
primaryLight: '#66e5f3', // 主题色亮色版
|
|
||||||
primaryDark: '#04b0be', // 主题色暗色版
|
|
||||||
textLight: '#666666', // 次要文本颜色
|
textLight: '#666666', // 次要文本颜色
|
||||||
border: '#dddddd', // 边框颜色
|
border: '#dddddd', // 边框颜色
|
||||||
error: '#ff3b30', // 错误颜色
|
error: '#ff3b30', // 错误颜色
|
||||||
success: '#4cd964', // 成功颜色
|
success: '#4cd964', // 成功颜色
|
||||||
warning: '#ff9500', // 警告颜色
|
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,
|
medium: 16,
|
||||||
large: 18,
|
large: 18,
|
||||||
xlarge: 20,
|
xlarge: 20,
|
||||||
|
xxlarge: 24,
|
||||||
|
title: 32,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 间距
|
// 间距
|
||||||
|
|
@ -41,7 +65,8 @@ export const theme = {
|
||||||
small: 4,
|
small: 4,
|
||||||
medium: 8,
|
medium: 8,
|
||||||
large: 12,
|
large: 12,
|
||||||
round: 999,
|
xl: 16,
|
||||||
|
circle: 999,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 阴影
|
// 阴影
|
||||||
|
|
@ -77,6 +102,12 @@ export const theme = {
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 波浪效果配置
|
||||||
|
wave: {
|
||||||
|
height: 60,
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 类型定义
|
// 类型定义
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,19 @@ import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
InteractionManager,
|
InteractionManager,
|
||||||
|
Image,
|
||||||
|
Dimensions,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import {useNavigation, useIsFocused} from '@react-navigation/native';
|
import {useNavigation, useIsFocused} from '@react-navigation/native';
|
||||||
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
|
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
|
||||||
import {RootStackParamList} from '../../navigation/types';
|
import {RootStackParamList} from '../../navigation/types';
|
||||||
import {Screen} from '../../components/common/Screen';
|
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<
|
type LoginScreenNavigationProp = NativeStackNavigationProp<
|
||||||
RootStackParamList,
|
RootStackParamList,
|
||||||
|
|
@ -19,6 +27,7 @@ type LoginScreenNavigationProp = NativeStackNavigationProp<
|
||||||
export const LoginScreen: React.FC = () => {
|
export const LoginScreen: React.FC = () => {
|
||||||
const navigation = useNavigation<LoginScreenNavigationProp>();
|
const navigation = useNavigation<LoginScreenNavigationProp>();
|
||||||
const isFocused = useIsFocused();
|
const isFocused = useIsFocused();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
const handleLogin = useCallback(() => {
|
const handleLogin = useCallback(() => {
|
||||||
if (!isFocused) return;
|
if (!isFocused) return;
|
||||||
|
|
@ -32,53 +41,219 @@ export const LoginScreen: React.FC = () => {
|
||||||
}, [navigation, isFocused]);
|
}, [navigation, isFocused]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Screen>
|
<Screen style={[styles.screen, {backgroundColor: theme.colors.background}]}>
|
||||||
{/* 头部导航栏 */}
|
{/* 头部背景 */}
|
||||||
<View style={styles.header}>
|
<View style={styles.headerContainer}>
|
||||||
<Text style={styles.headerTitle}>请登录(景旺冷冻仓)</Text>
|
<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>
|
||||||
|
|
||||||
{/* 主体内容 */}
|
{/* 主体内容 */}
|
||||||
|
<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}>
|
<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
|
<TouchableOpacity
|
||||||
style={styles.loginButton}
|
style={[styles.loginButtonContainer, theme.shadow.medium]}
|
||||||
onPress={handleLogin}>
|
onPress={handleLogin}>
|
||||||
<Text style={styles.loginButtonText}>进入系统</Text>
|
<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>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* 底部版权信息 */}
|
||||||
|
<View style={styles.footer}>
|
||||||
|
<Text style={[styles.footerText, {color: theme.colors.textLight}]}>
|
||||||
|
© 2024 景旺电子
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</Screen>
|
</Screen>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
header: {
|
screen: {
|
||||||
height: 56,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
},
|
||||||
|
headerContainer: {
|
||||||
|
height: 280,
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
headerContent: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 60,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: '#1890ff',
|
|
||||||
},
|
},
|
||||||
headerTitle: {
|
headerTitle: {
|
||||||
color: '#fff',
|
fontSize: 32,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textShadowColor: 'rgba(0, 0, 0, 0.2)',
|
||||||
|
textShadowOffset: {width: 1, height: 1},
|
||||||
|
textShadowRadius: 3,
|
||||||
|
},
|
||||||
|
headerSubtitle: {
|
||||||
fontSize: 18,
|
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: {
|
content: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
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: {
|
loginButton: {
|
||||||
backgroundColor: '#1890ff',
|
width: '100%',
|
||||||
width: 250,
|
height: '100%',
|
||||||
height: 44,
|
|
||||||
borderRadius: 4,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
loginButtonText: {
|
loginButtonText: {
|
||||||
color: '#fff',
|
fontSize: 18,
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: '600',
|
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,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -14,6 +14,10 @@ import { RootStackParamList } from '../../navigation/types';
|
||||||
import { PieChart } from 'react-native-chart-kit';
|
import { PieChart } from 'react-native-chart-kit';
|
||||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||||
import { useTheme } from '../../contexts/ThemeContext';
|
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<
|
type HomeScreenNavigationProp = NativeStackNavigationProp<
|
||||||
RootStackParamList,
|
RootStackParamList,
|
||||||
|
|
@ -33,10 +37,12 @@ export const HomeScreen: React.FC = () => {
|
||||||
const [fontLoaded, setFontLoaded] = useState(false);
|
const [fontLoaded, setFontLoaded] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Icon.loadFont().then(() => {
|
Icon.loadFont()
|
||||||
|
.then(() => {
|
||||||
console.log('Icon fonts loaded');
|
console.log('Icon fonts loaded');
|
||||||
setFontLoaded(true);
|
setFontLoaded(true);
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch(error => {
|
||||||
console.error('Failed to load icon fonts:', error);
|
console.error('Failed to load icon fonts:', error);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -50,16 +56,16 @@ export const HomeScreen: React.FC = () => {
|
||||||
{
|
{
|
||||||
name: '空闲',
|
name: '空闲',
|
||||||
population: 40,
|
population: 40,
|
||||||
color: theme.colors.success || '#4CAF50',
|
color: theme.colors.chart.blue,
|
||||||
legendFontColor: theme.colors.textLight,
|
legendFontColor: theme.colors.textLight,
|
||||||
legendFontSize: 15,
|
legendFontSize: theme.fontSize.regular,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '占用',
|
name: '占用',
|
||||||
population: 60,
|
population: 60,
|
||||||
color: theme.colors.warning || '#FF9800',
|
color: theme.colors.chart.orange,
|
||||||
legendFontColor: theme.colors.textLight,
|
legendFontColor: theme.colors.textLight,
|
||||||
legendFontSize: 15,
|
legendFontSize: theme.fontSize.regular,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -69,78 +75,114 @@ export const HomeScreen: React.FC = () => {
|
||||||
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const screenWidth = Dimensions.get('window').width;
|
|
||||||
|
|
||||||
if (!fontLoaded) {
|
if (!fontLoaded) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.loadingContainer, {backgroundColor: theme.colors.background}]}>
|
<View style={[styles.loadingContainer, { backgroundColor: theme.colors.background }]}>
|
||||||
<Text style={{color: theme.colors.text}}>加载图标中...</Text>
|
<Text style={{ color: theme.colors.text }}>加载图标中...</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
|
<SafeAreaView style={[styles.container, { backgroundColor: theme.colors.background }]}>
|
||||||
{/* 头部导航栏 */}
|
{/* 头部区域 */}
|
||||||
<View style={[styles.header, {backgroundColor: theme.colors.primary}]}>
|
<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
|
<TouchableOpacity
|
||||||
onPress={() => setIsDrawerOpen(!isDrawerOpen)}
|
onPress={() => setIsDrawerOpen(!isDrawerOpen)}
|
||||||
style={styles.menuButton}>
|
style={styles.menuButton}>
|
||||||
<Icon name="menu" size={24} color={theme.colors.background} />
|
<Icon name="menu" size={24} color={theme.colors.background} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>
|
<Text style={[styles.headerTitle, { color: theme.colors.background }]}>
|
||||||
景旺WMS移动终端(冷冻)
|
景旺WMS移动终端(冷冻)
|
||||||
</Text>
|
</Text>
|
||||||
<View style={styles.headerRight}>
|
|
||||||
<TouchableOpacity style={styles.iconButton}>
|
<TouchableOpacity style={styles.iconButton}>
|
||||||
<Icon name="notifications" size={24} color={theme.colors.background} />
|
<Icon name="notifications" size={24} color={theme.colors.background} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 侧边菜单 */}
|
{/* 主体内容 */}
|
||||||
{isDrawerOpen && (
|
<View style={styles.mainContent}>
|
||||||
<View style={[styles.drawer, {backgroundColor: theme.colors.background}]}>
|
<LinearGradient
|
||||||
<View style={[styles.drawerHeader, {backgroundColor: theme.colors.primary}]}>
|
colors={theme.colors.gradients.contrast}
|
||||||
<Text style={[styles.drawerTitle, {color: theme.colors.background}]}>
|
style={StyleSheet.absoluteFill}
|
||||||
景旺电子
|
start={{x: 0, y: 0}}
|
||||||
</Text>
|
end={{x: 1, y: 0}}
|
||||||
<Text style={[styles.drawerSubtitle, {color: theme.colors.background}]}>
|
/>
|
||||||
欢迎使用WMS移动终端
|
<ScrollView contentContainerStyle={styles.scrollContent}>
|
||||||
</Text>
|
{/* 快捷操作区 */}
|
||||||
</View>
|
<View style={styles.quickActions}>
|
||||||
{menuItems.map((item, index) => (
|
{menuItems.map((item, index) => (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={index}
|
key={index}
|
||||||
style={[styles.drawerItem, {borderBottomColor: theme.colors.border}]}
|
style={[styles.actionCard]}
|
||||||
onPress={() => {
|
onPress={() => navigation.navigate(item.route)}>
|
||||||
setIsDrawerOpen(false);
|
<LinearGradient
|
||||||
navigation.navigate(item.route);
|
colors={theme.colors.gradients.card}
|
||||||
}}>
|
style={[StyleSheet.absoluteFill, {borderRadius: 12}]}
|
||||||
<View style={styles.iconContainer}>
|
start={{x: 0, y: 0}}
|
||||||
<Icon
|
end={{x: 1, y: 1}}
|
||||||
name={item.icon}
|
|
||||||
size={28}
|
|
||||||
color={theme.colors.primary}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
<LinearGradient
|
||||||
<Text style={[styles.drawerItemText, {color: theme.colors.text}]}>
|
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}
|
{item.title}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 主体内容 */}
|
{/* 图表区域 */}
|
||||||
<ScrollView style={[styles.content, {backgroundColor: theme.colors.background}]}>
|
<View style={styles.chartSection}>
|
||||||
<Text style={[styles.chartTitle, {color: theme.colors.text}]}>
|
<Text style={[styles.chartTitle, {color: theme.colors.background}]}>
|
||||||
库存占用情况:
|
库存占用情况
|
||||||
</Text>
|
</Text>
|
||||||
<View style={styles.chartContainer}>
|
<View style={styles.chartContainer}>
|
||||||
<PieChart
|
<PieChart
|
||||||
data={stockData}
|
data={stockData}
|
||||||
width={screenWidth - 40}
|
width={width - 48}
|
||||||
height={220}
|
height={220}
|
||||||
chartConfig={chartConfig}
|
chartConfig={chartConfig}
|
||||||
accessor="population"
|
accessor="population"
|
||||||
|
|
@ -149,14 +191,46 @@ export const HomeScreen: React.FC = () => {
|
||||||
absolute
|
absolute
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* 遮罩层 */}
|
{/* 侧边菜单 */}
|
||||||
{isDrawerOpen && (
|
{isDrawerOpen && (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
<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
|
<TouchableOpacity
|
||||||
style={styles.overlay}
|
style={styles.overlay}
|
||||||
onPress={() => setIsDrawerOpen(false)}
|
onPress={() => setIsDrawerOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
|
@ -166,45 +240,96 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
mainContent: {
|
||||||
|
flex: 1,
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
scrollContent: {
|
||||||
|
flexGrow: 1,
|
||||||
|
paddingVertical: 20,
|
||||||
|
},
|
||||||
loadingContainer: {
|
loadingContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
header: {
|
headerSection: {
|
||||||
height: 56,
|
height: 160,
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
waveOverlay: {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
opacity: 0.6,
|
||||||
|
},
|
||||||
|
waveSvg: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
headerContent: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
|
paddingTop: 16,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
height: 160,
|
||||||
},
|
},
|
||||||
menuButton: {
|
menuButton: {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
},
|
},
|
||||||
headerTitle: {
|
headerTitle: {
|
||||||
|
flex: 1,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
headerRight: {
|
|
||||||
width: 40,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
},
|
|
||||||
iconButton: {
|
iconButton: {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
marginTop: -20,
|
||||||
|
},
|
||||||
|
quickActions: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 20,
|
||||||
|
},
|
||||||
|
actionCard: {
|
||||||
|
width: width / 2 - 24,
|
||||||
|
borderRadius: 12,
|
||||||
padding: 20,
|
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: {
|
chartTitle: {
|
||||||
fontSize: 16,
|
fontSize: 18,
|
||||||
marginBottom: 10,
|
fontWeight: '600',
|
||||||
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
chartContainer: {
|
chartContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginTop: 20,
|
|
||||||
},
|
},
|
||||||
drawer: {
|
drawer: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
@ -227,6 +352,7 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
drawerSubtitle: {
|
drawerSubtitle: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
opacity: 0.9,
|
||||||
},
|
},
|
||||||
drawerItem: {
|
drawerItem: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -234,7 +360,7 @@ const styles = StyleSheet.create({
|
||||||
padding: 16,
|
padding: 16,
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
},
|
},
|
||||||
iconContainer: {
|
drawerIconContainer: {
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ import {useNavigation} from '@react-navigation/native';
|
||||||
import {RootStackParamList} from '../../navigation/types';
|
import {RootStackParamList} from '../../navigation/types';
|
||||||
import {useTheme} from '../../contexts/ThemeContext';
|
import {useTheme} from '../../contexts/ThemeContext';
|
||||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||||
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
import Svg, {Path} from 'react-native-svg';
|
||||||
|
|
||||||
interface StockInEmptyResponse {
|
interface StockInEmptyResponse {
|
||||||
code: number;
|
code: number;
|
||||||
|
|
@ -83,7 +85,11 @@ export const StockInEmpty: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
|
<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
|
<TouchableOpacity
|
||||||
onPress={() => navigation.goBack()}
|
onPress={() => navigation.goBack()}
|
||||||
style={styles.backButton}>
|
style={styles.backButton}>
|
||||||
|
|
@ -91,12 +97,33 @@ export const StockInEmpty: React.FC = () => {
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>空载具入库</Text>
|
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>空载具入库</Text>
|
||||||
<View style={styles.headerRight} />
|
<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>
|
||||||
|
|
||||||
{/* 主体内容 */}
|
{/* 主体内容 */}
|
||||||
<View style={styles.content}>
|
<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} />
|
<Icon name="info-outline" size={24} color={theme.colors.primary} />
|
||||||
<Text style={[styles.infoText, {color: theme.colors.text}]}>
|
<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.inputLabel, {color: theme.colors.text}]}>
|
||||||
载具号 <Text style={styles.required}>*</Text>
|
载具号 <Text style={styles.required}>*</Text>
|
||||||
</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} />
|
<Icon name="qr-code-scanner" size={24} color={theme.colors.primary} style={styles.inputIcon} />
|
||||||
<TextInput
|
<TextInput
|
||||||
style={[styles.input, {color: theme.colors.text}]}
|
style={[styles.input, {color: theme.colors.text}]}
|
||||||
|
|
@ -129,12 +159,13 @@ export const StockInEmpty: React.FC = () => {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 提交按钮 */}
|
{/* 提交按钮 */}
|
||||||
|
<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
|
<TouchableOpacity
|
||||||
style={[
|
style={styles.submitButtonContent}
|
||||||
styles.submitButton,
|
|
||||||
{backgroundColor: theme.colors.primary},
|
|
||||||
loading && styles.submitButtonDisabled,
|
|
||||||
]}
|
|
||||||
onPress={handleEmptyIn}
|
onPress={handleEmptyIn}
|
||||||
disabled={loading}>
|
disabled={loading}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|
@ -148,6 +179,7 @@ export const StockInEmpty: React.FC = () => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</LinearGradient>
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
|
@ -169,6 +201,19 @@ const styles = StyleSheet.create({
|
||||||
shadowOpacity: 0.2,
|
shadowOpacity: 0.2,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
},
|
},
|
||||||
|
waveContainer: {
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 56,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
zIndex: -1,
|
||||||
|
},
|
||||||
|
waveSvg: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
backButton: {
|
backButton: {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
},
|
},
|
||||||
|
|
@ -186,7 +231,6 @@ const styles = StyleSheet.create({
|
||||||
infoSection: {
|
infoSection: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: 'rgba(24, 144, 255, 0.1)',
|
|
||||||
padding: 16,
|
padding: 16,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
marginBottom: 24,
|
marginBottom: 24,
|
||||||
|
|
@ -214,7 +258,6 @@ const styles = StyleSheet.create({
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
height: 48,
|
height: 48,
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
||||||
},
|
},
|
||||||
inputIcon: {
|
inputIcon: {
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
|
|
@ -231,9 +274,6 @@ const styles = StyleSheet.create({
|
||||||
submitButton: {
|
submitButton: {
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
marginTop: 32,
|
marginTop: 32,
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
shadowColor: '#000',
|
shadowColor: '#000',
|
||||||
|
|
@ -241,6 +281,12 @@ const styles = StyleSheet.create({
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.1,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
},
|
},
|
||||||
|
submitButtonContent: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
submitButtonDisabled: {
|
submitButtonDisabled: {
|
||||||
opacity: 0.6,
|
opacity: 0.6,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ import {
|
||||||
import {useNavigation} from '@react-navigation/native';
|
import {useNavigation} from '@react-navigation/native';
|
||||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||||
import {useTheme} from '../../contexts/ThemeContext';
|
import {useTheme} from '../../contexts/ThemeContext';
|
||||||
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
import Svg, {Path} from 'react-native-svg';
|
||||||
|
|
||||||
interface PackageDataItem {
|
interface PackageDataItem {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -236,7 +238,11 @@ const StockInWheelManual: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, {backgroundColor: theme.colors.background}]}>
|
<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
|
<TouchableOpacity
|
||||||
style={styles.backButton}
|
style={styles.backButton}
|
||||||
onPress={() => navigation.goBack()}>
|
onPress={() => navigation.goBack()}>
|
||||||
|
|
@ -246,9 +252,31 @@ const StockInWheelManual: React.FC = () => {
|
||||||
手动码盘入库
|
手动码盘入库
|
||||||
</Text>
|
</Text>
|
||||||
<View style={styles.headerRight} />
|
<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>
|
||||||
|
|
||||||
<ScrollView style={[styles.content, {backgroundColor: theme.colors.background}]}>
|
<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`}]}>
|
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.primary}15`}]}>
|
||||||
<Icon name="info-outline" size={24} color={theme.colors.primary} />
|
<Icon name="info-outline" size={24} color={theme.colors.primary} />
|
||||||
|
|
@ -260,7 +288,10 @@ const StockInWheelManual: React.FC = () => {
|
||||||
{/* 载具号输入区 */}
|
{/* 载具号输入区 */}
|
||||||
<View style={styles.inputContainer}>
|
<View style={styles.inputContainer}>
|
||||||
<Text style={[styles.label, {color: theme.colors.text}]}>载具号</Text>
|
<Text style={[styles.label, {color: theme.colors.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} />
|
<Icon name="qr-code-scanner" size={24} color={theme.colors.primary} style={styles.inputIcon} />
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={vehicleInputRef}
|
ref={vehicleInputRef}
|
||||||
|
|
@ -283,7 +314,10 @@ const StockInWheelManual: React.FC = () => {
|
||||||
{/* 条码输入区 */}
|
{/* 条码输入区 */}
|
||||||
<View style={styles.inputContainer}>
|
<View style={styles.inputContainer}>
|
||||||
<Text style={[styles.label, {color: theme.colors.text}]}>物料条码</Text>
|
<Text style={[styles.label, {color: theme.colors.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-2" size={24} color={theme.colors.primary} style={styles.inputIcon} />
|
<Icon name="qr-code-2" size={24} color={theme.colors.primary} style={styles.inputIcon} />
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={goodsInputRef}
|
ref={goodsInputRef}
|
||||||
|
|
@ -421,23 +455,35 @@ const StockInWheelManual: React.FC = () => {
|
||||||
|
|
||||||
{/* 操作按钮区 */}
|
{/* 操作按钮区 */}
|
||||||
<View style={styles.buttonGroup}>
|
<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
|
<TouchableOpacity
|
||||||
style={[styles.button, styles.addButton, {backgroundColor: theme.colors.primary}]}
|
style={styles.buttonContent}
|
||||||
onPress={resolveCode}>
|
onPress={resolveCode}>
|
||||||
<Icon name="add-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
|
<Icon name="add-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
|
||||||
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
|
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
|
||||||
添加物料
|
添加物料
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</LinearGradient>
|
||||||
|
|
||||||
|
<LinearGradient
|
||||||
|
colors={[theme.colors.success, theme.colors.secondary]}
|
||||||
|
start={{x: 0, y: 0}}
|
||||||
|
end={{x: 1, y: 0}}
|
||||||
|
style={styles.button}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.button, styles.completeButton, {backgroundColor: theme.colors.success}]}
|
style={styles.buttonContent}
|
||||||
onPress={wheelComplete}>
|
onPress={wheelComplete}>
|
||||||
<Icon name="check-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
|
<Icon name="check-circle-outline" size={24} color={theme.colors.background} style={styles.buttonIcon} />
|
||||||
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
|
<Text style={[styles.buttonText, {color: theme.colors.background}]}>
|
||||||
码盘完成
|
码盘完成
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</LinearGradient>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 物料列表 */}
|
{/* 物料列表 */}
|
||||||
|
|
@ -452,20 +498,20 @@ const StockInWheelManual: React.FC = () => {
|
||||||
{packageData.map((item, index) => (
|
{packageData.map((item, index) => (
|
||||||
<View
|
<View
|
||||||
key={item.id}
|
key={item.id}
|
||||||
style={[
|
style={[styles.card]}>
|
||||||
styles.card,
|
<LinearGradient
|
||||||
{
|
colors={theme.colors.gradients.contrast}
|
||||||
backgroundColor: theme.colors.background,
|
style={[StyleSheet.absoluteFill, {borderRadius: 12}]}
|
||||||
borderColor: theme.colors.border,
|
start={{x: 0, y: 0}}
|
||||||
},
|
end={{x: 1, y: 0}}
|
||||||
]}>
|
/>
|
||||||
{/* 卡片头部 */}
|
{/* 卡片头部 */}
|
||||||
<View style={styles.cardHeader}>
|
<View style={styles.cardHeader}>
|
||||||
<View style={styles.cardHeaderLeft}>
|
<View style={styles.cardHeaderLeft}>
|
||||||
<Text style={[styles.cardHeaderText, {color: theme.colors.text}]}>
|
<Text style={[styles.cardHeaderText, {color: theme.colors.background}]}>
|
||||||
序号:{item.id}
|
序号:{item.id}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[styles.cardHeaderText, {color: theme.colors.textLight}]}>
|
<Text style={[styles.cardHeaderText, {color: theme.colors.background}]}>
|
||||||
采购单号:{item.segment1}
|
采购单号:{item.segment1}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -487,37 +533,37 @@ const StockInWheelManual: React.FC = () => {
|
||||||
<View style={styles.cardContent}>
|
<View style={styles.cardContent}>
|
||||||
<View style={styles.cardRow}>
|
<View style={styles.cardRow}>
|
||||||
<View style={styles.cardField}>
|
<View style={styles.cardField}>
|
||||||
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}>物料号</Text>
|
<Text style={[styles.cardLabel, {color: theme.colors.background}]}>物料号</Text>
|
||||||
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.itemId}</Text>
|
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.itemId}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.cardField}>
|
<View style={styles.cardField}>
|
||||||
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}>批次号</Text>
|
<Text style={[styles.cardLabel, {color: theme.colors.background}]}>批次号</Text>
|
||||||
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.batch}</Text>
|
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.batch}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.cardRow}>
|
<View style={styles.cardRow}>
|
||||||
<View style={styles.cardField}>
|
<View style={styles.cardField}>
|
||||||
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}>数量</Text>
|
<Text style={[styles.cardLabel, {color: theme.colors.background}]}>数量</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.editableValue}
|
style={styles.editableValue}
|
||||||
onPress={() => modifyNumber(item.id)}>
|
onPress={() => modifyNumber(item.id)}>
|
||||||
<Text style={[styles.cardValue, {color: theme.colors.primary}]}>
|
<Text style={[styles.cardValue, {color: theme.colors.background}]}>
|
||||||
{item.quantity}
|
{item.quantity}
|
||||||
</Text>
|
</Text>
|
||||||
<Icon name="edit" size={16} color={theme.colors.primary} />
|
<Icon name="edit" size={16} color={theme.colors.background} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.cardField}>
|
<View style={styles.cardField}>
|
||||||
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}>重量</Text>
|
<Text style={[styles.cardLabel, {color: theme.colors.background}]}>重量</Text>
|
||||||
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.weight}</Text>
|
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.weight}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.cardRow}>
|
<View style={styles.cardRow}>
|
||||||
<View style={styles.cardField}>
|
<View style={styles.cardField}>
|
||||||
<Text style={[styles.cardLabel, {color: theme.colors.textLight}]}>生产日期</Text>
|
<Text style={[styles.cardLabel, {color: theme.colors.background}]}>生产日期</Text>
|
||||||
<Text style={[styles.cardValue, {color: theme.colors.text}]}>{item.productData}</Text>
|
<Text style={[styles.cardValue, {color: theme.colors.background}]}>{item.productData}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -525,6 +571,7 @@ const StockInWheelManual: React.FC = () => {
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
|
||||||
{loading && (
|
{loading && (
|
||||||
<View style={[styles.loadingOverlay, {backgroundColor: 'rgba(0, 0, 0, 0.7)'}]}>
|
<View style={[styles.loadingOverlay, {backgroundColor: 'rgba(0, 0, 0, 0.7)'}]}>
|
||||||
|
|
@ -544,6 +591,14 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
|
mainContent: {
|
||||||
|
flex: 1,
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
scrollContent: {
|
||||||
|
flexGrow: 1,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
header: {
|
header: {
|
||||||
height: 56,
|
height: 56,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -556,6 +611,19 @@ const styles = StyleSheet.create({
|
||||||
shadowOpacity: 0.2,
|
shadowOpacity: 0.2,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
},
|
},
|
||||||
|
waveContainer: {
|
||||||
|
height: 100,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 56,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
zIndex: -1,
|
||||||
|
},
|
||||||
|
waveSvg: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
backButton: {
|
backButton: {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
},
|
},
|
||||||
|
|
@ -566,10 +634,6 @@ const styles = StyleSheet.create({
|
||||||
headerRight: {
|
headerRight: {
|
||||||
width: 40,
|
width: 40,
|
||||||
},
|
},
|
||||||
content: {
|
|
||||||
flex: 1,
|
|
||||||
padding: 16,
|
|
||||||
},
|
|
||||||
infoSection: {
|
infoSection: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
@ -650,15 +714,18 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
shadowColor: '#000',
|
shadowColor: '#000',
|
||||||
shadowOffset: {width: 0, height: 2},
|
shadowOffset: {width: 0, height: 2},
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.1,
|
||||||
shadowRadius: 2,
|
shadowRadius: 2,
|
||||||
},
|
},
|
||||||
|
buttonContent: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
buttonIcon: {
|
buttonIcon: {
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
|
|
@ -683,13 +750,8 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
borderWidth: 1,
|
|
||||||
marginBottom: 12,
|
marginBottom: 12,
|
||||||
elevation: 2,
|
overflow: 'hidden',
|
||||||
shadowColor: '#000',
|
|
||||||
shadowOffset: {width: 0, height: 2},
|
|
||||||
shadowOpacity: 0.1,
|
|
||||||
shadowRadius: 2,
|
|
||||||
},
|
},
|
||||||
cardHeader: {
|
cardHeader: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user