pda_react_native_template/src/screens/stockIn/StockInEmpty.tsx
2025-07-04 16:51:39 +08:00

301 lines
8.2 KiB
TypeScript

import React, {useState} from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
TouchableOpacity,
Alert,
SafeAreaView,
ActivityIndicator,
} from 'react-native';
import {httpService} from '../../services/http';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
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;
message: string;
data: string;
}
type StockInEmptyScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
'StockInEmpty'
>;
export const StockInEmpty: React.FC = () => {
const navigation = useNavigation<StockInEmptyScreenNavigationProp>();
const theme = useTheme();
const [vehicleNo, setVehicleNo] = useState('');
const [loading, setLoading] = useState(false);
// 空托入库方法
const handleEmptyIn = async () => {
if (!vehicleNo.trim()) {
Alert.alert('警告', '请先填写载具号', [
{text: '返回填写', style: 'cancel'},
]);
return;
}
try {
setLoading(true);
const response = await httpService.post<StockInEmptyResponse>(
'/api/vehicle/empty-in',
{vehicleNo: vehicleNo.trim()}
);
if (response.code !== 200) {
Alert.alert('警告', '服务器请求失败', [
{text: '我知道了', style: 'cancel'},
]);
return;
}
// 确保response.data是字符串类型
const responseData = typeof response.data === 'string'
? JSON.parse(response.data)
: response.data;
if (responseData.code === 200) {
Alert.alert('成功', '', [
{text: '我知道了', style: 'default'},
]);
setVehicleNo('');
} else {
Alert.alert('警告', `服务器返回失败:${responseData.message}`, [
{text: '我知道了', style: 'cancel'},
]);
}
} catch (error) {
Alert.alert('请求发生错误', `请求服务器发生错误:${error}`, [
{text: '我知道了', style: 'cancel'},
]);
} finally {
setLoading(false);
}
};
return (
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<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}>
<Icon name="arrow-back" size={24} color={theme.colors.background} />
</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, {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.inputLabel, {color: theme.colors.text}]}>
<Text style={styles.required}>*</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
style={[styles.input, {color: theme.colors.text}]}
value={vehicleNo}
onChangeText={setVehicleNo}
placeholder="请扫描或输入载具号"
placeholderTextColor={theme.colors.textLight}
autoCapitalize="none"
/>
{vehicleNo.length > 0 && (
<TouchableOpacity
onPress={() => setVehicleNo('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
</TouchableOpacity>
)}
</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
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>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
height: 56,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
elevation: 4,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
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,
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
},
headerRight: {
width: 40,
},
content: {
flex: 1,
padding: 20,
},
infoSection: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
borderRadius: 8,
marginBottom: 24,
},
infoText: {
marginLeft: 12,
fontSize: 14,
flex: 1,
},
inputContainer: {
marginBottom: 24,
},
inputLabel: {
fontSize: 16,
marginBottom: 8,
fontWeight: '500',
},
required: {
color: '#ff4d4f',
},
inputWrapper: {
flexDirection: 'row',
alignItems: 'center',
borderWidth: 1,
borderRadius: 8,
height: 48,
paddingHorizontal: 12,
},
inputIcon: {
marginRight: 8,
},
input: {
flex: 1,
fontSize: 16,
padding: 0,
height: '100%',
},
clearButton: {
padding: 4,
},
submitButton: {
height: 48,
borderRadius: 24,
marginTop: 32,
elevation: 2,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 2,
},
submitButtonContent: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
submitButtonDisabled: {
opacity: 0.6,
},
submitIcon: {
marginRight: 8,
},
submitButtonText: {
fontSize: 16,
fontWeight: '600',
},
});