优化项目结构

This commit is contained in:
李宇奇 2025-07-09 16:21:15 +08:00
parent e937988771
commit b6c8db84a8
4 changed files with 318 additions and 119 deletions

View File

@ -28,7 +28,7 @@ export const LoginScreen: React.FC = () => {
const theme = useTheme();
const handleLogin = useCallback(() => {
if (!isFocused) return;
if (!isFocused) {return;}
InteractionManager.runAfterInteractions(() => {
if (isFocused) {
@ -51,7 +51,7 @@ export const LoginScreen: React.FC = () => {
<View style={styles.contentContainer}>
{/* 标题区域 */}
<View style={styles.titleContainer}>
<Text style={styles.title}></Text>
<Text style={styles.title}></Text>
<Text style={styles.subtitle}></Text>
</View>
@ -60,8 +60,8 @@ export const LoginScreen: React.FC = () => {
{/* Logo */}
<View style={styles.logoWrapper}>
<View style={[styles.logoCircle, theme.shadow.medium]}>
<Text style={[styles.logoText, {color: theme.colors.primary}]}>
JW
<Text style={[styles.logoText, {color: theme.colors.aqua}]}>
BK
</Text>
</View>
</View>
@ -83,7 +83,7 @@ export const LoginScreen: React.FC = () => {
{/* 底部版权信息 */}
<View style={styles.footer}>
<Text style={[styles.footerText, {color: theme.colors.textLight}]}>
© 2024
© 2025
</Text>
</View>
</View>

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, {useState, useEffect} from 'react';
import {
View,
Text,
@ -8,16 +8,16 @@ import {
ScrollView,
Dimensions,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { RootStackParamList } from '../../navigation/types';
import { PieChart } from 'react-native-chart-kit';
import {useNavigation} from '@react-navigation/native';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
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 {useTheme} from '../../contexts/ThemeContext';
import LinearGradient from 'react-native-linear-gradient';
import Svg, { Path } from 'react-native-svg';
import Svg, {Path} from 'react-native-svg';
const { width } = Dimensions.get('window');
const {width} = Dimensions.get('window');
type HomeScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
@ -48,8 +48,8 @@ export const HomeScreen: React.FC = () => {
}, []);
const menuItems: MenuItem[] = [
{ title: '空载具入库', icon: 'local-shipping', route: 'StockInEmpty' },
{ title: '手动码盘入库', icon: 'inventory', route: 'StockInManual' },
{title: '空载具入库', icon: 'local-shipping', route: 'StockInEmpty'},
{title: '手动码盘入库', icon: 'inventory', route: 'StockInManual'},
];
const stockData = [
@ -77,23 +77,30 @@ export const HomeScreen: React.FC = () => {
if (!fontLoaded) {
return (
<View style={[styles.loadingContainer, { backgroundColor: theme.colors.backgroundGray }]}>
<Text style={{ color: theme.colors.text }}>...</Text>
<View
style={[
styles.loadingContainer,
{backgroundColor: theme.colors.backgroundGray},
]}>
<Text style={{color: theme.colors.text}}>...</Text>
</View>
);
}
return (
<SafeAreaView style={[styles.container, { backgroundColor: theme.colors.backgroundGray }]}>
<SafeAreaView
style={[
styles.container,
{backgroundColor: theme.colors.backgroundGray},
]}>
{/* 头部区域 */}
<View style={styles.headerSection}>
{/* 渐变背景 */}
<LinearGradient
colors={theme.colors.gradients.primary}
style={StyleSheet.absoluteFill}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
>
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}>
{/* 半透明波浪效果 */}
<View style={styles.waveOverlay}>
<Svg height="100%" width={width} style={styles.waveSvg}>
@ -131,17 +138,25 @@ export const HomeScreen: React.FC = () => {
style={styles.menuButton}>
<Icon name="menu" size={24} color={theme.colors.background} />
</TouchableOpacity>
<Text style={[styles.headerTitle, { color: theme.colors.background }]}>
WMS移动终端
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>
WMS移动终端
</Text>
<TouchableOpacity style={styles.iconButton}>
<Icon name="notifications" size={24} color={theme.colors.background} />
<Icon
name="notifications"
size={24}
color={theme.colors.background}
/>
</TouchableOpacity>
</View>
</View>
{/* 主体内容 */}
<View style={[styles.mainContent, { backgroundColor: theme.colors.backgroundGray }]}>
<View
style={[
styles.mainContent,
{backgroundColor: theme.colors.backgroundGray},
]}>
<ScrollView contentContainerStyle={styles.scrollContent}>
{/* 快捷操作区 */}
<View style={styles.quickActions}>
@ -157,9 +172,17 @@ export const HomeScreen: React.FC = () => {
end={{x: 1, y: 0}}
/>
<View style={styles.iconContainer}>
<Icon name={item.icon} size={32} color={theme.colors.background} />
<Icon
name={item.icon}
size={32}
color={theme.colors.background}
/>
</View>
<Text style={[styles.actionTitle, {color: theme.colors.background}]}>
<Text
style={[
styles.actionTitle,
{color: theme.colors.background},
]}>
{item.title}
</Text>
</TouchableOpacity>
@ -190,21 +213,30 @@ export const HomeScreen: React.FC = () => {
{/* 侧边菜单 */}
{isDrawerOpen && (
<>
<View style={[styles.drawer, { backgroundColor: theme.colors.background }]}>
<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
style={[styles.drawerTitle, {color: theme.colors.background}]}>
</Text>
<Text style={[styles.drawerSubtitle, { color: theme.colors.background }]}>
<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 }]}
style={[
styles.drawerItem,
{borderBottomColor: theme.colors.border},
]}
onPress={() => {
setIsDrawerOpen(false);
navigation.navigate(item.route);
@ -212,7 +244,8 @@ export const HomeScreen: React.FC = () => {
<View style={styles.drawerIconContainer}>
<Icon name={item.icon} size={28} color={theme.colors.aqua} />
</View>
<Text style={[styles.drawerItemText, { color: theme.colors.text }]}>
<Text
style={[styles.drawerItemText, {color: theme.colors.text}]}>
{item.title}
</Text>
</TouchableOpacity>

View File

@ -51,7 +51,7 @@ export const StockInEmpty: React.FC = () => {
setLoading(true);
const response = await axios.post<StockInEmptyResponse>(
'/api/vehicle/empty-in',
{vehicleNo: vehicleNo.trim()}
{vehicleNo: vehicleNo.trim()},
);
if (response.status !== 200) {
@ -64,9 +64,7 @@ export const StockInEmpty: React.FC = () => {
const responseData = response.data;
if (responseData.code === 200) {
Alert.alert('成功', '', [
{text: '我知道了', style: 'default'},
]);
Alert.alert('成功', '', [{text: '我知道了', style: 'default'}]);
setVehicleNo('');
} else {
Alert.alert('警告', `服务器返回失败:${responseData.message}`, [
@ -74,16 +72,21 @@ export const StockInEmpty: React.FC = () => {
]);
}
} catch (error) {
Alert.alert('请求发生错误', `请求服务器发生错误:${error instanceof Error ? error.message : String(error)}`, [
{text: '我知道了', style: 'cancel'},
]);
Alert.alert(
'请求发生错误',
`请求服务器发生错误:${
error instanceof Error ? error.message : String(error)
}`,
[{text: '我知道了', style: 'cancel'}],
);
} finally {
setLoading(false);
}
};
return (
<SafeAreaView style={[styles.container, {backgroundColor: theme.colors.background}]}>
<SafeAreaView
style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<LinearGradient
colors={theme.colors.gradients.primary}
@ -95,7 +98,9 @@ export const StockInEmpty: React.FC = () => {
style={styles.backButton}>
<Icon name="arrow-back" size={24} color={theme.colors.background} />
</TouchableOpacity>
<Text style={[styles.headerTitle, {color: theme.colors.background}]}></Text>
<Text style={[styles.headerTitle, {color: theme.colors.background}]}>
</Text>
<View style={styles.headerRight} />
</LinearGradient>
@ -115,9 +120,17 @@ export const StockInEmpty: React.FC = () => {
</View>
{/* 主体内容 */}
<View style={[styles.content, { backgroundColor: theme.colors.backgroundGray }]}>
<View
style={[
styles.content,
{backgroundColor: theme.colors.backgroundGray},
]}>
{/* 说明文字 */}
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.aqua}15`}]}>
<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}]}>
@ -129,11 +142,20 @@ export const StockInEmpty: React.FC = () => {
<Text style={[styles.inputLabel, {color: theme.colors.text}]}>
<Text style={styles.required}>*</Text>
</Text>
<View style={[styles.inputWrapper, {
<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} />
},
]}>
<Icon
name="qr-code-scanner"
size={24}
color={theme.colors.aqua}
style={styles.inputIcon}
/>
<TextInput
style={[styles.input, {color: theme.colors.text}]}
value={vehicleNo}
@ -166,8 +188,17 @@ export const StockInEmpty: React.FC = () => {
<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}]}>
<Icon
name="save"
size={24}
color={theme.colors.background}
style={styles.submitIcon}
/>
<Text
style={[
styles.submitButtonText,
{color: theme.colors.background},
]}>
</Text>
</>

View File

@ -49,7 +49,9 @@ export const StockInManual: React.FC = () => {
const resolveVehicle = useCallback(() => {
const code = vehicleCode.trim();
if (code.length === 0 || code === lastProcessedVehicleCode) {return;}
if (code.length === 0 || code === lastProcessedVehicleCode) {
return;
}
if (code.length === 15) {
setLastProcessedVehicleCode(code);
@ -128,10 +130,7 @@ export const StockInManual: React.FC = () => {
};
const modifyNumber = (_id: string) => {
Alert.alert(
'修改数量',
'请输入新的数量',
[
Alert.alert('修改数量', '请输入新的数量', [
{text: '取消', style: 'cancel'},
{
text: '确定',
@ -140,8 +139,7 @@ export const StockInManual: React.FC = () => {
Alert.alert('提示', '此功能暂不可用,请稍后再试');
},
},
],
);
]);
};
const showDetails = (item: PackageDataItem) => {
@ -218,16 +216,21 @@ export const StockInManual: React.FC = () => {
Alert.alert('警告', `服务器返回失败:${data.message}`);
}
} catch (error) {
Alert.alert('请求发生错误', `请求服务器发生错误:${error instanceof Error ? error.message : String(error)}`, [
{text: '我知道了', style: 'cancel'},
]);
Alert.alert(
'请求发生错误',
`请求服务器发生错误:${
error instanceof Error ? error.message : String(error)
}`,
[{text: '我知道了', style: 'cancel'}],
);
} finally {
setLoading(false);
}
};
return (
<View style={[styles.container, {backgroundColor: theme.colors.background}]}>
<View
style={[styles.container, {backgroundColor: theme.colors.background}]}>
{/* 头部导航栏 */}
<LinearGradient
colors={theme.colors.gradients.primary}
@ -260,10 +263,18 @@ export const StockInManual: React.FC = () => {
</Svg>
</View>
<View style={[styles.mainContent, { backgroundColor: theme.colors.backgroundGray }]}>
<View
style={[
styles.mainContent,
{backgroundColor: theme.colors.backgroundGray},
]}>
<ScrollView contentContainerStyle={styles.scrollContent}>
{/* 信息提示区 */}
<View style={[styles.infoSection, {backgroundColor: `${theme.colors.aqua}15`}]}>
<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}]}>
@ -272,12 +283,23 @@ export const StockInManual: React.FC = () => {
{/* 载具号输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {
<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.aqua} style={styles.inputIcon} />
},
]}>
<Icon
name="qr-code-scanner"
size={24}
color={theme.colors.aqua}
style={styles.inputIcon}
/>
<TextInput
ref={vehicleInputRef}
style={[styles.input, {color: theme.colors.text}]}
@ -290,7 +312,11 @@ export const StockInManual: React.FC = () => {
<TouchableOpacity
onPress={() => setVehicleCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
<Icon
name="cancel"
size={20}
color={theme.colors.textLight}
/>
</TouchableOpacity>
)}
</View>
@ -298,12 +324,23 @@ export const StockInManual: React.FC = () => {
{/* 条码输入区 */}
<View style={styles.inputContainer}>
<Text style={[styles.label, {color: theme.colors.text}]}></Text>
<View style={[styles.inputWrapper, {
<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.aqua} style={styles.inputIcon} />
},
]}>
<Icon
name="qr-code-2"
size={24}
color={theme.colors.aqua}
style={styles.inputIcon}
/>
<TextInput
ref={goodsInputRef}
style={[styles.input, {color: theme.colors.text}]}
@ -316,7 +353,11 @@ export const StockInManual: React.FC = () => {
<TouchableOpacity
onPress={() => setGoodsCode('')}
style={styles.clearButton}>
<Icon name="cancel" size={20} color={theme.colors.textLight} />
<Icon
name="cancel"
size={20}
color={theme.colors.textLight}
/>
</TouchableOpacity>
)}
</View>
@ -332,8 +373,14 @@ export const StockInManual: React.FC = () => {
<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}]}>
<Icon
name="add-circle-outline"
size={24}
color={theme.colors.background}
style={styles.buttonIcon}
/>
<Text
style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
@ -347,8 +394,14 @@ export const StockInManual: React.FC = () => {
<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}]}>
<Icon
name="check-circle-outline"
size={24}
color={theme.colors.background}
style={styles.buttonIcon}
/>
<Text
style={[styles.buttonText, {color: theme.colors.background}]}>
</Text>
</TouchableOpacity>
@ -364,31 +417,59 @@ export const StockInManual: React.FC = () => {
</Text>
</View>
{packageData.map((item) => (
{packageData.map(item => (
<View key={item.id} style={[styles.card]}>
<View
key={item.id}
style={[styles.card]}>
<View style={[StyleSheet.absoluteFill, {borderRadius: 12, backgroundColor: theme.colors.background}]} />
style={[
StyleSheet.absoluteFill,
{
borderRadius: 12,
backgroundColor: theme.colors.background,
},
]}
/>
{/* 卡片头部 */}
<View style={styles.cardHeader}>
<View style={styles.cardHeaderLeft}>
<Text style={[styles.cardHeaderText, {color: theme.colors.text}]}>
<Text
style={[
styles.cardHeaderText,
{color: theme.colors.text},
]}>
{item.id}
</Text>
<Text style={[styles.cardHeaderText, {color: theme.colors.text}]}>
<Text
style={[
styles.cardHeaderText,
{color: theme.colors.text},
]}>
{item.segment1}
</Text>
</View>
<View style={styles.cardActions}>
<TouchableOpacity
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.aqua}15`}]}
style={[
styles.cardActionButton,
{backgroundColor: `${theme.colors.aqua}15`},
]}
onPress={() => showDetails(item)}>
<Icon name="info-outline" size={20} color={theme.colors.aqua} />
<Icon
name="info-outline"
size={20}
color={theme.colors.aqua}
/>
</TouchableOpacity>
<TouchableOpacity
style={[styles.cardActionButton, {backgroundColor: `${theme.colors.error}15`}]}
style={[
styles.cardActionButton,
{backgroundColor: `${theme.colors.error}15`},
]}
onPress={() => deleteItem(item.id)}>
<Icon name="delete-outline" size={20} color={theme.colors.error} />
<Icon
name="delete-outline"
size={20}
color={theme.colors.error}
/>
</TouchableOpacity>
</View>
</View>
@ -397,37 +478,83 @@ export const StockInManual: React.FC = () => {
<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>
<Text
style={[
styles.cardLabel,
{color: theme.colors.textLight},
]}>
</Text>
<Text
style={[styles.cardValue, {color: theme.colors.text}]}>
{item.itemId}
</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>
<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>
<Text
style={[
styles.cardLabel,
{color: theme.colors.textLight},
]}>
</Text>
<TouchableOpacity
style={styles.editableValue}
onPress={() => modifyNumber(item.id)}>
<Text style={[styles.cardValue, {color: theme.colors.text}]}>
<Text
style={[
styles.cardValue,
{color: theme.colors.text},
]}>
{item.quantity}
</Text>
<Icon name="edit" size={16} color={theme.colors.text} />
</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>
<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>
<Text
style={[
styles.cardLabel,
{color: theme.colors.textLight},
]}>
</Text>
<Text
style={[styles.cardValue, {color: theme.colors.text}]}>
{item.productData}
</Text>
</View>
</View>
</View>
@ -438,8 +565,16 @@ export const StockInManual: React.FC = () => {
</View>
{loading && (
<View style={[styles.loadingOverlay, {backgroundColor: 'rgba(0, 0, 0, 0.7)'}]}>
<View style={[styles.loadingCard, {backgroundColor: theme.colors.background}]}>
<View
style={[
styles.loadingOverlay,
{backgroundColor: 'rgba(0, 0, 0, 0.7)'},
]}>
<View
style={[
styles.loadingCard,
{backgroundColor: theme.colors.background},
]}>
<ActivityIndicator size="large" color={theme.colors.aqua} />
<Text style={[styles.loadingText, {color: theme.colors.text}]}>
...