324 lines
8.3 KiB
TypeScript
324 lines
8.3 KiB
TypeScript
import React, {useState} from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
TextInput,
|
|
TouchableOpacity,
|
|
SafeAreaView,
|
|
ActivityIndicator,
|
|
} from 'react-native';
|
|
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';
|
|
import axios from 'axios';
|
|
import {DialogUtils} from '../../utils';
|
|
|
|
interface StockInEmptyResponse {
|
|
code: number;
|
|
message: string;
|
|
data: {
|
|
code: number;
|
|
message: 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()) {
|
|
DialogUtils.showWarningMessage('警告', '请先填写载具号', '返回填写');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
setLoading(true);
|
|
const response = await axios.post<StockInEmptyResponse>(
|
|
'/api/vehicle/empty-in',
|
|
{vehicleNo: vehicleNo.trim()},
|
|
);
|
|
|
|
if (response.status !== 200) {
|
|
DialogUtils.showWarningMessage('警告', '服务器请求失败', '我知道了');
|
|
return;
|
|
}
|
|
|
|
const responseData = response.data;
|
|
|
|
if (responseData.code === 200) {
|
|
DialogUtils.showSuccessMessage('成功', '空载具入库成功', '我知道了');
|
|
setVehicleNo('');
|
|
} else {
|
|
DialogUtils.showWarningMessage(
|
|
'警告',
|
|
`服务器返回失败:${responseData.message}`,
|
|
'我知道了',
|
|
);
|
|
}
|
|
} catch (error) {
|
|
DialogUtils.showErrorMessage(
|
|
'请求发生错误',
|
|
`请求服务器发生错误:${
|
|
error instanceof Error ? error.message : String(error)
|
|
}`,
|
|
'我知道了',
|
|
);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<SafeAreaView
|
|
style={[styles.container, {backgroundColor: theme.colors.background}]}>
|
|
{/* 头部导航栏 */}
|
|
<LinearGradient
|
|
colors={theme.colors.gradients.primary}
|
|
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.aqua}30`}
|
|
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,
|
|
{backgroundColor: theme.colors.backgroundGray},
|
|
]}>
|
|
{/* 说明文字 */}
|
|
<View
|
|
style={[
|
|
styles.infoSection,
|
|
{backgroundColor: `${theme.colors.aqua}15`},
|
|
]}>
|
|
<Icon name="info-outline" size={24} color={theme.colors.aqua} />
|
|
<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.aqua}
|
|
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.gradients.button}
|
|
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',
|
|
},
|
|
});
|