diff --git a/README.md b/README.md index 0f33d1e29e203d565ac04ced97b09d8beda676d6..ff706feb35821b12eaed7814dbc0ab4a1f5b374b 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,22 @@ EU-Admin App > 👉 Supports hot updates +## Screenshots + +IOS : + +![image-1](./doc/images/ios/1.png) +![image-2](./doc/images/ios/2.png) +![image-3](./doc/images/ios/3.png) +![image-4](./doc/images/ios/4.png) + +Android : + ![image-1](./doc/images/android/1.png) ![image-2](./doc/images/android/2.png) ![image-3](./doc/images/android/3.png) ![image-4](./doc/images/android/4.png) ![image-5](./doc/images/android/5.png) -![image-6](./doc/images/android/6.png) ## Requirements diff --git a/doc/images/android/1.png b/doc/images/android/1.png index 24306c09f5016520a4c08a17309ee81f27de02c1..d198ac7fd6e31763c2b708110b3c7b1c65315fef 100644 Binary files a/doc/images/android/1.png and b/doc/images/android/1.png differ diff --git a/doc/images/android/2.png b/doc/images/android/2.png index 6ed78994070023c4ff1da5f3ec8c010f79e2b339..51db15ef911939035295da17feeeb25f98cb2dda 100644 Binary files a/doc/images/android/2.png and b/doc/images/android/2.png differ diff --git a/doc/images/android/3.png b/doc/images/android/3.png index 5435cfbdd78c41dc2e417cbc4c5cda2634e1e3f6..0210ba5a861f6f95b2cbafc2b3166bcf8c3ddb67 100644 Binary files a/doc/images/android/3.png and b/doc/images/android/3.png differ diff --git a/doc/images/android/4.png b/doc/images/android/4.png index 7c43f3daee042e447cc982d6b143aee7845d0dbe..4cb327af1a5016eed3bd6c82ba8a69067e6d7d9b 100644 Binary files a/doc/images/android/4.png and b/doc/images/android/4.png differ diff --git a/doc/images/android/5.png b/doc/images/android/5.png index 9a34c1775b1e9ce4e45ee17ea8b02001c09afb9b..8693cd77c469528d053df7590ac89c7fe356f28f 100644 Binary files a/doc/images/android/5.png and b/doc/images/android/5.png differ diff --git a/doc/images/android/6.png b/doc/images/android/6.png deleted file mode 100644 index 470a7b16af98c62991963582f0cbb7c9c88f7ec5..0000000000000000000000000000000000000000 Binary files a/doc/images/android/6.png and /dev/null differ diff --git a/doc/images/ios/1.png b/doc/images/ios/1.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc7baaebc3feedb14b757fd47c8a1557ec12814 Binary files /dev/null and b/doc/images/ios/1.png differ diff --git a/doc/images/ios/2.png b/doc/images/ios/2.png new file mode 100644 index 0000000000000000000000000000000000000000..db8a49ec05abe10889b43330e2eb532f8bf57198 Binary files /dev/null and b/doc/images/ios/2.png differ diff --git a/doc/images/ios/3.png b/doc/images/ios/3.png new file mode 100644 index 0000000000000000000000000000000000000000..6c7a7008a6f7e912f47c41738de3d28482b32f23 Binary files /dev/null and b/doc/images/ios/3.png differ diff --git a/doc/images/ios/4.png b/doc/images/ios/4.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9d223c94b187f1104b70b2163ddc4d9cf0856b Binary files /dev/null and b/doc/images/ios/4.png differ diff --git a/src/app/(app)/index.tsx b/src/app/(app)/index.tsx index bee34c73fb8be6b2d2ece2574bfe1cab29a61232..fb435996b3417f96611f44c8651a057e1a00f614 100644 --- a/src/app/(app)/index.tsx +++ b/src/app/(app)/index.tsx @@ -5,7 +5,6 @@ import { SafeAreaView, ScrollView, StatusBar, - StyleSheet, TouchableOpacity, } from 'react-native'; @@ -29,16 +28,19 @@ const ActivityItem: React.FC = ({ subtitle, time, }) => ( - - + + - - - {title} - {time} + + + {title} + {time} - {subtitle} + {subtitle} ); @@ -57,12 +59,14 @@ const ModuleItem: React.FC = ({ title, onPress, }) => ( - - + + - {/* */} - {title} + {title} ); @@ -75,66 +79,69 @@ const Home: React.FC = () => { const router = useRouter(); return ( - - {/* */} + - {/* */} {/* 顶部导航 */} - navigation.navigate('Notifications')} + className="relative" + onPress={() => router.push('/notification')} > - - 3 + + 3 } /> - + {/* 欢迎信息 */} - - 你好,{userInfo?.UserName} - - 今天是{userInfo?.WeekName},祝您工作顺利 - - + {userInfo?.WeekName && ( + + + 你好,{userInfo?.UserName} + + + 今天是{userInfo?.WeekName},祝您工作顺利 + + + )} {/* 数据概览 */} - - - 今日订单 - 28 - ↑ 12.5% + + + 今日订单 + 28 + ↑ 12.5% - - 生产任务 - 15 - 进行中: 8 + + 生产任务 + 15 + 进行中: 8 - - 库存预警 - 3 - 点击查看详情 + + 库存预警 + 3 + 点击查看详情 - - 质检合格率 - 98.5% - ↑ 1.2% + + 质检合格率 + + 98.5% + + ↑ 1.2% {/* 功能模块 */} - - 功能模块 - + + 功能模块 + { icon="cogs" bgColor="#3b82f6" title="生产管理" - // onPress={() => navigation.navigate('Production')} + onPress={() => router.push('/production')} /> { icon="check-circle" bgColor="#a855f7" title="质量控制" - // onPress={() => navigation.navigate('Quality')} + onPress={() => router.push('/quality')} /> { title="物流管理" onPress={() => {}} /> + router.push('/process')} + /> + router.push('/equipment')} + /> { {/* 最近活动 */} - - - 最近活动 + + + 最近活动 - 查看全部 + 查看全部 - + { {/* 底部空间 - 为底部导航留出空间 */} - + ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#f5f5f5', - }, - notificationButton: { - position: 'relative', - }, - notificationBadge: { - position: 'absolute', - top: -5, - right: -5, - backgroundColor: '#ef4444', - width: 16, - height: 16, - borderRadius: 8, - alignItems: 'center', - justifyContent: 'center', - }, - notificationBadgeText: { - color: 'white', - fontSize: 10, - fontWeight: 'bold', - }, - content: { - flex: 1, - padding: 16, - }, - welcomeSection: { - marginBottom: 24, - }, - welcomeTitle: { - fontSize: 24, - fontWeight: 'bold', - color: '#333', - }, - welcomeSubtitle: { - fontSize: 14, - color: '#6b7280', - marginTop: 4, - }, - statsGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'space-between', - marginBottom: 24, - }, - statCard: { - width: '48%', - backgroundColor: 'white', - borderRadius: 16, - padding: 16, - marginBottom: 12, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 10, - elevation: 2, - }, - statLabel: { - fontSize: 14, - color: '#6b7280', - }, - statValue: { - fontSize: 24, - fontWeight: 'bold', - marginTop: 8, - }, - statTrend: { - fontSize: 12, - color: '#22c55e', - marginTop: 4, - }, - statInfo: { - fontSize: 12, - color: '#6b7280', - marginTop: 4, - }, - card: { - backgroundColor: 'white', - borderRadius: 16, - padding: 16, - marginBottom: 16, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 10, - elevation: 2, - }, - sectionTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 16, - }, - moduleGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'space-between', - }, - moduleItem: { - width: '23%', - alignItems: 'center', - marginBottom: 16, - }, - moduleIcon: { - width: 50, - height: 50, - borderRadius: 12, - alignItems: 'center', - justifyContent: 'center', - marginBottom: 8, - }, - moduleText: { - fontSize: 12, - color: '#6b7280', - textAlign: 'center', - }, - sectionHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 16, - }, - sectionLink: { - fontSize: 14, - color: '#0066ff', - }, - activitiesContainer: { - gap: 16, - }, - activityItem: { - flexDirection: 'row', - alignItems: 'flex-start', - }, - activityIcon: { - width: 36, - height: 36, - borderRadius: 8, - alignItems: 'center', - justifyContent: 'center', - marginRight: 12, - }, - activityContent: { - flex: 1, - }, - activityHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 4, - }, - activityTitle: { - fontSize: 14, - fontWeight: '500', - color: '#333', - }, - activityTime: { - fontSize: 12, - color: '#6b7280', - }, - activitySubtitle: { - fontSize: 13, - color: '#6b7280', - }, - bottomSpace: { - height: 70, - }, - navBar: { - position: 'absolute', - bottom: 0, - left: 0, - right: 0, - height: 70, - backgroundColor: 'white', - flexDirection: 'row', - justifyContent: 'space-around', - alignItems: 'center', - borderTopWidth: 1, - borderTopColor: '#e5e7eb', - paddingBottom: 10, // 为底部安全区域留出空间 - }, - navItem: { - alignItems: 'center', - justifyContent: 'center', - }, - navIcon: { - marginBottom: 4, - }, - navText: { - fontSize: 12, - color: '#6b7280', - }, - navTextActive: { - color: '#0066ff', - }, -}); - export default Home; diff --git a/src/app/(app)/inventory.tsx b/src/app/(app)/inventory.tsx index 5b4576e4801271bba6a9b1ecb4585b30f32b0412..1914260588736132cb19dbfd548e957de4ee463a 100644 --- a/src/app/(app)/inventory.tsx +++ b/src/app/(app)/inventory.tsx @@ -1,81 +1,18 @@ -import { FontAwesome } from '@expo/vector-icons'; +import { useRouter } from 'expo-router'; import React, { useState } from 'react'; +import { TextInput, TouchableOpacity } from 'react-native'; + +import { SegmentedControl, type SegmentedControlOption } from '@/components'; import { - StatusBar, - StyleSheet, + NavHeader, + SafeAreaView, + ScrollView, Text, - TextInput, - TouchableOpacity, View, -} from 'react-native'; - -import { SegmentedControl, type SegmentedControlOption } from '@/components'; -import { NavHeader, SafeAreaView, ScrollView } from '@/components/ui'; - -// 状态徽章组件 -// type StatusBadgeProps = { -// status: string; -// color: string; -// bgColor: string; -// }; - -// const StatusBadge: React.FC = ({ status, color, bgColor }) => ( -// -// {status} -// -// ); - -// 库存项组件 -type InventoryItemProps = { - name: string; - code: string; - quantity: number; - safetyStock: number; - status: 'normal' | 'warning' | 'danger'; -}; - -const InventoryItem: React.FC = ({ - name, - code, - quantity, - safetyStock, - status, -}) => { - let indicatorColor = '#22c55e'; // 绿色 - 正常 - let textColor = 'black'; - - if (status === 'warning') { - indicatorColor = '#eab308'; // 黄色 - 警告 - } else if (status === 'danger') { - indicatorColor = '#ef4444'; // 红色 - 危险 - textColor = '#ef4444'; - } +} from '@/components/ui'; +import { FontAwesome } from '@/components/ui/icons'; - return ( - - - - - {name} - - 编号:{code} - - - - {quantity} - - 安全库存:{safetyStock} - - - ); -}; +import InventoryItem from '../inventory/item'; // 预警项组件 type AlertItemProps = { @@ -85,29 +22,29 @@ type AlertItemProps = { }; const AlertItem: React.FC = ({ name, message, type }) => { - const bgColor = type === 'danger' ? '#fef2f2' : '#fffbeb'; + const bgColor = type === 'danger' ? 'bg-red-50' : 'bg-amber-50'; const iconColor = type === 'danger' ? '#ef4444' : '#eab308'; const icon = type === 'danger' ? 'exclamation-circle' : 'exclamation-triangle'; return ( - - + + - - {name} - {message} + + {name} + {message} - 补货 + 补货 ); }; const Inventory: React.FC = () => { - // const navigation = useNavigation(); + const router = useRouter(); // 分段控制器选项 const tabOptions: SegmentedControlOption[] = [ @@ -240,29 +177,24 @@ const Inventory: React.FC = () => { ]; return ( - - - + {/* 顶部导航 */} - + - + - {/* - - */} } /> - + {/* 分段控制器 */} { /> {/* 库存概览 */} {selectedTabIndex === 0 && ( {/* 库存概览卡片 */} - - 库存概览 - - - + + 库存概览 + + + 152 - 物料种类 + 物料种类 - - + + 87% - 库存健康度 + 库存健康度 - - + + 3 - 库存预警 + 库存预警 - + - 本月库存周转率 - - 4.2 - ↑ 0.3 + + 本月库存周转率 + + + + 4.2 + + + ↑ 0.3 + {/* 库存预警 */} - - - 库存预警 + + + 库存预警 - 查看全部 + + 查看全部 + - + {alertItems.map((item, index) => ( { {/* 库存列表 */} - 库存列表 + + 库存列表 + - - + + @@ -351,7 +293,7 @@ const Inventory: React.FC = () => { name="search" size={16} color="#9ca3af" - style={styles.searchIcon} + className="absolute left-3 top-3" /> @@ -364,6 +306,7 @@ const Inventory: React.FC = () => { quantity={item.quantity} safetyStock={item.safetyStock} status={item.status} + onViewDetail={() => router.push(`/inventory/${index}`)} /> ))} @@ -373,17 +316,17 @@ const Inventory: React.FC = () => { {/* 原材料 */} {selectedTabIndex === 1 && ( - - 原材料库存 - + + 原材料库存 + 此处显示原材料库存信息 - - + + @@ -391,7 +334,7 @@ const Inventory: React.FC = () => { name="search" size={16} color="#9ca3af" - style={styles.searchIcon} + className="absolute left-3 top-3" /> @@ -404,6 +347,7 @@ const Inventory: React.FC = () => { quantity={item.quantity} safetyStock={item.safetyStock} status={item.status} + onViewDetail={() => router.push(`/inventory/${index}`)} /> ))} @@ -413,17 +357,17 @@ const Inventory: React.FC = () => { {/* 半成品 */} {selectedTabIndex === 2 && ( - - 半成品库存 - + + 半成品库存 + 此处显示半成品库存信息 - - + + @@ -431,7 +375,7 @@ const Inventory: React.FC = () => { name="search" size={16} color="#9ca3af" - style={styles.searchIcon} + className="absolute left-3 top-3" /> @@ -444,6 +388,7 @@ const Inventory: React.FC = () => { quantity={item.quantity} safetyStock={item.safetyStock} status={item.status} + onViewDetail={() => router.push(`/inventory/${index}`)} /> ))} @@ -453,15 +398,17 @@ const Inventory: React.FC = () => { {/* 成品 */} {selectedTabIndex === 3 && ( - - 成品库存 - 此处显示成品库存信息 + + 成品库存 + + 此处显示成品库存信息 + - - + + @@ -469,7 +416,7 @@ const Inventory: React.FC = () => { name="search" size={16} color="#9ca3af" - style={styles.searchIcon} + className="absolute left-3 top-3" /> @@ -482,6 +429,7 @@ const Inventory: React.FC = () => { quantity={item.quantity} safetyStock={item.safetyStock} status={item.status} + onViewDetail={() => router.push(`/inventory/${index}`)} /> ))} @@ -491,43 +439,45 @@ const Inventory: React.FC = () => { {/* 库存报表 */} {selectedTabIndex === 4 && ( - - 库存报表 - 此处显示库存报表信息 + + 库存报表 + + 此处显示库存报表信息 + - - 库存周转率 - - - 原材料 - 4.5 + + 库存周转率 + + + 原材料 + 4.5 - - 半成品 - 3.8 + + 半成品 + 3.8 - - 成品 - 5.2 + + 成品 + 5.2 - - 库存价值分布 - - - 原材料 - ¥125,000 + + 库存价值分布 + + + 原材料 + ¥125,000 - - 半成品 - ¥85,000 + + 半成品 + ¥85,000 - - 成品 - ¥210,000 + + 成品 + ¥210,000 @@ -537,315 +487,11 @@ const Inventory: React.FC = () => { {/* 浮动按钮 */} - + ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#f5f5f5', - }, - headerButton: { - marginLeft: 16, - }, - content: { - flex: 1, - paddingHorizontal: 16, - paddingTop: 16, - }, - scrollView: { - flex: 1, - marginTop: 16, - }, - flex1: { - flex: 1, - }, - flexRow: { - flexDirection: 'row', - alignItems: 'center', - }, - stockIndicator: { - width: 8, - height: 8, - borderRadius: 4, - marginRight: 8, - }, - itemName: { - fontSize: 16, - fontWeight: '500', - }, - alertItem: { - flexDirection: 'row', - alignItems: 'center', - padding: 12, - borderRadius: 8, - marginBottom: 8, - }, - alertIconContainer: { - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: 'rgba(0, 0, 0, 0.05)', - justifyContent: 'center', - alignItems: 'center', - marginRight: 12, - }, - alertTitle: { - fontSize: 16, - fontWeight: '500', - marginBottom: 2, - }, - alertMessage: { - fontSize: 14, - color: '#6b7280', - marginTop: 2, - }, - alertAction: { - fontSize: 14, - color: '#0066ff', - fontWeight: '500', - }, - sectionTitle: { - fontSize: 16, - fontWeight: '600', - marginTop: 16, - marginBottom: 8, - }, - searchContainer: { - position: 'relative', - marginBottom: 16, - }, - searchInput: { - backgroundColor: '#f3f4f6', - borderRadius: 8, - paddingHorizontal: 40, - paddingVertical: 10, - fontSize: 14, - }, - searchIcon: { - position: 'absolute', - left: 12, - top: 12, - }, - inventoryItem: { - flexDirection: 'row', - justifyContent: 'space-between', - paddingVertical: 12, - borderBottomWidth: 1, - borderBottomColor: '#f0f0f0', - }, - reportItem: { - marginTop: 12, - }, - card: { - backgroundColor: 'white', - borderRadius: 16, - padding: 16, - marginBottom: 16, - shadowColor: '#000', - shadowOffset: { width: 0, height: 1 }, - shadowOpacity: 0.05, - shadowRadius: 2, - elevation: 1, - }, - cardHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 12, - }, - cardTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 12, - }, - cardSubtitle: { - fontSize: 16, - fontWeight: '500', - }, - cardDescription: { - fontSize: 14, - color: '#6b7280', - marginTop: 4, - }, - cardLink: { - fontSize: 14, - color: '#0066ff', - fontWeight: '500', - }, - alertList: { - marginTop: 8, - }, - statsGrid: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 16, - }, - statItem: { - flex: 1, - alignItems: 'center', - }, - statValue: { - fontSize: 24, - fontWeight: 'bold', - marginBottom: 4, - }, - statLabel: { - fontSize: 14, - color: '#6b7280', - }, - infoBox: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: '#f0f9ff', - padding: 12, - borderRadius: 8, - }, - infoIcon: { - marginRight: 12, - }, - infoTitle: { - fontSize: 14, - color: '#6b7280', - marginBottom: 2, - }, - infoValue: { - fontSize: 18, - fontWeight: '600', - color: '#0066ff', - marginRight: 8, - }, - infoTrend: { - fontSize: 14, - color: '#22c55e', - fontWeight: '500', - }, - itemCode: { - fontSize: 14, - color: '#6b7280', - }, - itemQuantity: { - fontSize: 18, - fontWeight: 'bold', - }, - safetyStockText: { - fontSize: 12, - color: '#6b7280', - }, - textRight: { - alignItems: 'flex-end', - }, - floatingButton: { - position: 'absolute', - right: 16, - bottom: 16, - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: '#0066ff', - justifyContent: 'center', - alignItems: 'center', - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - elevation: 5, - }, - reportContainer: { - marginTop: 12, - }, - reportCard: { - backgroundColor: 'white', - borderRadius: 8, - padding: 16, - marginBottom: 12, - }, - reportHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 12, - }, - reportTitle: { - fontSize: 16, - fontWeight: '600', - }, - reportDate: { - fontSize: 14, - color: '#6b7280', - }, - reportRow: { - flexDirection: 'row', - justifyContent: 'space-between', - paddingVertical: 8, - borderBottomWidth: 1, - borderBottomColor: '#f0f0f0', - }, - reportLabel: { - fontSize: 14, - color: '#6b7280', - }, - reportValue: { - fontSize: 14, - fontWeight: '500', - }, - statusBadge: { - paddingHorizontal: 8, - paddingVertical: 4, - borderRadius: 4, - }, - statusBadgeText: { - fontSize: 12, - fontWeight: '500', - }, - equipmentInfoGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - marginVertical: 12, - }, - equipmentInfoItem: { - width: '50%', - marginBottom: 12, - }, - equipmentInfoLabel: { - fontSize: 12, - color: '#6b7280', - marginBottom: 2, - }, - equipmentInfoValue: { - fontSize: 16, - fontWeight: '500', - }, - equipmentAlert: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: '#f0f9ff', - padding: 12, - borderRadius: 8, - marginBottom: 12, - }, - equipmentAlertIcon: { - marginRight: 12, - }, - equipmentAlertTitle: { - fontSize: 14, - fontWeight: '500', - marginRight: 8, - }, - equipmentAlertText: { - fontSize: 14, - color: '#6b7280', - }, - equipmentAlertError: { - backgroundColor: '#fef2f2', - }, - equipmentAlertTitleError: { - color: '#ef4444', - }, -}); - export default Inventory; diff --git a/src/app/(app)/order.tsx b/src/app/(app)/order.tsx index 9deb625fd1343eaaee6ab19793951a2ba5268a53..6866795bd27b26bc983a8784fca189cd8a86602d 100644 --- a/src/app/(app)/order.tsx +++ b/src/app/(app)/order.tsx @@ -1,8 +1,7 @@ -import { FontAwesome } from '@expo/vector-icons'; +import { useRouter } from 'expo-router'; import React, { useState } from 'react'; import { StatusBar, - StyleSheet, Text, TextInput, TouchableOpacity, @@ -11,6 +10,7 @@ import { import { SegmentedControl, type SegmentedControlOption } from '@/components'; import { NavHeader, SafeAreaView, ScrollView } from '@/components/ui'; +import { FontAwesome } from '@/components/ui/icons'; // 状态徽章组件 type StatusBadgeProps = { @@ -24,8 +24,10 @@ const StatusBadge: React.FC = ({ color, bgColor, }) => ( - - {status} + + + {status} + ); @@ -53,34 +55,34 @@ const OrderItem: React.FC = ({ statusBgColor, onViewDetail, }) => ( - - - 订单 #{orderNumber} + + + 订单 #{orderNumber} - 客户:{customer} - - 订单日期:{orderDate} - 交付日期:{deliveryDate} + 客户:{customer} + + 订单日期:{orderDate} + 交付日期:{deliveryDate} - - - 订单金额: - ¥{amount} + + + 订单金额: + ¥{amount} - 查看详情 + 查看详情 ); const Orders: React.FC = () => { - // const navigation = useNavigation(); + const router = useRouter(); // 分段控制器选项 const tabOptions: SegmentedControlOption[] = [ @@ -169,45 +171,57 @@ const Orders: React.FC = () => { return ( <> {/* 订单概览 */} - - 订单概览 - - - + + 订单概览 + + + {orderStats.total} - 总订单 + 总订单 - - + + {orderStats.pending} - 待处理 + 待处理 - - + + {orderStats.processing} - 生产中 + 生产中 - - + + {orderStats.completed} - 已完成 + 已完成 - - + + - 本月订单完成率 - - + 本月订单完成率 + + {orderStats.completionRate}% - + ↑ {orderStats.rateChange}% @@ -216,16 +230,16 @@ const Orders: React.FC = () => { {/* 搜索框 */} - - + + @@ -233,8 +247,8 @@ const Orders: React.FC = () => { {/* 订单列表 */} - 订单列表 - + 订单列表 + {orderItems.map((item) => ( { status={item.status} statusColor={item.statusColor} statusBgColor={item.statusBgColor} - onViewDetail={() => - console.log(`查看订单 ${item.orderNumber} 详情`) - } + onViewDetail={() => router.push(`/order/${item.id}`)} /> ))} @@ -256,30 +268,30 @@ const Orders: React.FC = () => { ); case 1: // 待处理 return ( - - 待处理订单 - 此处显示待处理订单信息 + + 待处理订单 + 此处显示待处理订单信息 ); case 2: // 生产中 return ( - - 生产中订单 - 此处显示生产中订单信息 + + 生产中订单 + 此处显示生产中订单信息 ); case 3: // 已完成 return ( - - 已完成订单 - 此处显示已完成订单信息 + + 已完成订单 + 此处显示已完成订单信息 ); case 4: // 已取消 return ( - - 已取消订单 - 此处显示已取消订单信息 + + 已取消订单 + 此处显示已取消订单信息 ); default: @@ -288,7 +300,7 @@ const Orders: React.FC = () => { }; return ( - + {/* 顶部导航 */} @@ -297,13 +309,13 @@ const Orders: React.FC = () => { leftShown={false} right={ <> - + - + - + @@ -311,7 +323,7 @@ const Orders: React.FC = () => { /> {/* 内容区域 */} - + {/* 分段控制器 */} { {renderTabContent()} {/* 底部间距 */} - + {/* 浮动按钮 */} - + ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#f5f5f5', - }, - flexRow: { - flexDirection: 'row', - alignItems: 'center', - }, - flexRowBetween: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 8, - }, - headerButton: { - marginLeft: 16, - }, - content: { - flex: 1, - padding: 16, - }, - scrollView: { - flex: 1, - marginTop: 16, - }, - card: { - marginTop: 16, - - backgroundColor: '#ffffff', - borderRadius: 16, - padding: 16, - marginBottom: 16, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 10, - elevation: 2, - }, - cardTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 12, - }, - statsGrid: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 12, - }, - statsItem: { - alignItems: 'center', - flex: 1, - }, - statsValue: { - fontSize: 20, - fontWeight: '700', - }, - statsLabel: { - fontSize: 12, - color: '#6b7280', - }, - completionRateCard: { - flexDirection: 'row', - alignItems: 'center', - backgroundColor: '#ebf5ff', - borderRadius: 8, - padding: 12, - }, - completionRateIcon: { - marginRight: 12, - }, - completionRateTitle: { - fontSize: 14, - fontWeight: '500', - }, - completionRateValue: { - fontSize: 18, - fontWeight: '700', - color: '#0066ff', - marginRight: 8, - }, - completionRateChange: { - fontSize: 12, - color: '#22c55e', - }, - searchContainer: { - marginBottom: 16, - }, - searchInputContainer: { - position: 'relative', - flexDirection: 'row', - alignItems: 'center', - }, - searchIcon: { - position: 'absolute', - left: 12, - zIndex: 1, - }, - searchInput: { - flex: 1, - backgroundColor: '#ffffff', - borderWidth: 1, - borderColor: '#e5e7eb', - borderRadius: 8, - paddingVertical: 8, - paddingLeft: 40, - paddingRight: 16, - fontSize: 14, - }, - sectionTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 12, - }, - orderItem: { - borderBottomWidth: 1, - borderBottomColor: '#f0f0f0', - paddingVertical: 16, - }, - orderTitle: { - fontSize: 16, - fontWeight: '500', - }, - customerText: { - fontSize: 14, - color: '#6b7280', - marginBottom: 8, - }, - dateText: { - fontSize: 14, - color: '#6b7280', - }, - amountLabel: { - fontSize: 14, - color: '#6b7280', - }, - amountValue: { - fontSize: 14, - fontWeight: '500', - }, - detailLink: { - fontSize: 14, - color: '#0066ff', - }, - statusBadge: { - paddingHorizontal: 8, - paddingVertical: 4, - borderRadius: 9999, - }, - statusBadgeText: { - fontSize: 12, - fontWeight: '500', - }, - placeholderText: { - color: '#6b7280', - }, - floatingButton: { - position: 'absolute', - right: 24, - bottom: 80, - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: '#0066ff', - alignItems: 'center', - justifyContent: 'center', - shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.2, - shadowRadius: 8, - elevation: 4, - }, - bottomSpacer: { - height: 80, - }, -}); - export default Orders; diff --git a/src/app/(app)/production.tsx b/src/app/(app)/production.tsx index fcba93d3e5183eb9f8b2140fcf450eb246f7bbdb..98f172e1ff0142dedfbe3c6f0dee439e352e5e7c 100644 --- a/src/app/(app)/production.tsx +++ b/src/app/(app)/production.tsx @@ -1,168 +1,20 @@ -import { FontAwesome } from '@expo/vector-icons'; +// import { useRouter } from 'expo-router'; import React, { useState } from 'react'; -import { - StatusBar, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; +import { TouchableOpacity, View } from 'react-native'; import { SegmentedControl, type SegmentedControlOption } from '@/components'; +import { + Equipment, + Plans, + Process, + Report, + Task, +} from '@/components/production'; import { NavHeader, SafeAreaView, ScrollView } from '@/components/ui'; - -import ReportDateSelector from '../report-date-selector'; - -// 进度条组件 -type ProgressBarProps = { - progress: number; - color: string; -}; - -const ProgressBar: React.FC = ({ progress, color }) => ( - - - -); - -// 状态徽章组件 -type StatusBadgeProps = { - status: string; - color: string; - bgColor: string; -}; - -const StatusBadge: React.FC = ({ - status, - color, - bgColor, -}) => ( - - {status} - -); - -// 生产计划项组件 -type PlanItemProps = { - title: string; - code: string; - manager: string; - deadline: string; - progress: number; - total: number; - completed: number; - status: string; - statusColor: string; - statusBgColor: string; -}; - -const PlanItem: React.FC = ({ - title, - code, - manager, - deadline, - progress, - total, - completed, - status, - statusColor, - statusBgColor, -}) => ( - - - {title} - - - 计划编号:{code} - - 负责人:{manager} - 截止日期:{deadline} - - - - 完成进度 - {progress}% - - - - - - 计划产量: - {total} - 已完成: - {completed} - - - 详情 - - - -); - -// 工序流程节点组件 -type ProcessNodeProps = { - icon: string; - label: string; - status: 'completed' | 'inProgress' | 'pending'; -}; - -const ProcessNode: React.FC = ({ icon, label, status }) => { - let statusIcon = null; - let statusText = ''; - let bgColor = '#ebf5ff'; - let iconColor = '#0066ff'; - - if (status === 'completed') { - statusIcon = ( - - - - ); - statusText = '已完成'; - bgColor = '#ebf5ff'; - } else if (status === 'inProgress') { - statusIcon = ( - - - - ); - statusText = '进行中'; - bgColor = '#dcfce7'; - iconColor = '#22c55e'; - } else { - statusText = '待开始'; - } - - return ( - - - - {statusIcon} - - {label} - - {statusText} - - - ); -}; +import { FontAwesome } from '@/components/ui/icons'; const Production: React.FC = () => { - // const navigation = useNavigation(); + // const router = useRouter(); // 分段控制器状态 const [selectedTabIndex, setSelectedTabIndex] = useState(0); @@ -175,28 +27,26 @@ const Production: React.FC = () => { ]; return ( - - - + {/* 顶部导航 */} - + - + - + } /> - + {/* 分段控制器 */} { {/* 选项卡内容 */} - {selectedTabIndex === 0 && ( - - {/* 生产概览 */} - - 生产概览 - - - - 15 - - 计划总数 - - - - 8 - - 进行中 - - - - 3 - - 待开始 - - - - - - - 本月生产完成率 - - - 78.5% - ↑ 5.2% - - - - - - {/* 生产计划列表 */} - 生产计划列表 - - {/* 计划项目1 */} - - - {/* 计划项目2 */} - - - {/* 计划项目3 */} - - - )} - - {selectedTabIndex === 1 && ( - - {/* 任务概览 */} - - 任务概览 - - - - 24 - - 任务总数 - - - - 12 - - 进行中 - - - - 5 - - 待分配 - - - - - - - 员工任务完成率 - - - 82.3% - ↑ 3.7% - - - - - - {/* 生产任务列表 */} - 生产任务列表 - - {/* 任务项目1 */} - - - 主板元器件贴装任务 - - - 任务编号:TA20231205-01 - - 负责人:李技术员 - - 截止日期:2023-12-10 - - - - - 完成进度 - 70% - - - - - - 所属计划: - PP20231128-01 - - - 详情 - - - + {selectedTabIndex === 0 && } - {/* 任务项目2 */} - - - 电路板焊接任务 - - - 任务编号:TA20231205-02 - - 负责人:待分配 - - 截止日期:2023-12-12 - - - - - 完成进度 - 0% - - - - - - 所属计划: - PP20231128-01 - - - 详情 - - - + {selectedTabIndex === 1 && } - {/* 任务项目3 */} - - - 音箱外壳注塑任务 - - - 任务编号:TA20231204-03 - - 负责人:王技术员 - - 截止日期:2023-12-15 - - - - - 完成进度 - 45% - - - - - - 所属计划: - PP20231130-02 - - - 详情 - - - - - )} + {selectedTabIndex === 2 && } - {selectedTabIndex === 2 && ( - - {/* 工序概览 */} - - 工序概览 - - - - 18 - - 工序总数 - - - - 10 - - 使用中 - - - - 2 - - 待优化 - - - + {selectedTabIndex === 3 && } - {/* 工序流程图 */} - - - - 智能手表生产工序流程 - - - 当前批次: - - B20231204-01 - - - - - - - - - - - - - - - - - - - - - - - 当前进度: - 40% | - 预计完成时间: - - 2023-12-05 18:00 - - - - - - - {/* 工序列表 */} - 工序列表 - - {/* 工序项目1 */} - - - 元器件贴装 - - - 工序编号:PR20231201-03 - - - - 负责人 - 王工程师 - - - 标准工时 - 45分钟/批次 - - - - - - 设备利用率 - 85% - - - - - - 关联设备 - - - SMT贴片机#2 - - - - - - 良品率: - 98.3% - - - 详情 - - - - - {/* 工序项目2 */} - - - 电路板焊接 - - - 工序编号:PR20231201-04 - - - - 负责人 - 李工程师 - - - 标准工时 - 60分钟/批次 - - - - - - 设备利用率 - 75% - - - - - - 关联设备 - - - - 波峰焊接机#1 - - - - - - - 良品率: - 97.5% - - - 详情 - - - - - )} - - {selectedTabIndex === 3 && ( - - {/* 设备概览 */} - - 设备概览 - - - - 32 - - 设备总数 - - - - 25 - - 运行中 - - - - 2 - - 故障 - - - - - - - 设备综合效率(OEE) - - - 87.2% - ↑ 2.1% - - - - - - {/* 设备列表 */} - 设备列表 - - {/* 设备项目1 */} - - - SMT贴片机#2 - - - 设备编号:EQ20230501-02 - - - - 设备温度 - 42°C - - - 电机转速 - 1200 RPM - - - 电压 - 220V - - - 电流 - 5.2A - - - - - - - 设备警报 - 无异常警报 - - - - - - 今日运行: - 8.5小时 - - - 详情 - - - - - {/* 设备项目2 */} - - - 波峰焊接机#1 - - - 设备编号:EQ20230602-05 - - - - 设备温度 - 68°C - - - 电机转速 - 0 RPM - - - 电压 - 0V - - - 电流 - 0A - - - - - - - - 设备警报 - - - 温控系统异常,需要维修 - - - - - - - 停机时间: - 2.5小时 - - - 详情 - - - - - {/* 设备维护计划 */} - 设备维护计划 - - - - - - 设备名称 - - - 维护类型 - - - 计划日期 - - - 负责人 - - - 状态 - - - - - SMT贴片机#2 - - 例行保养 - - 2023-12-15 - - 王工程师 - - - - - - - 回流焊机#3 - - 故障维修 - - 2023-12-05 - - 张工程师 - - - - - - - PCB切割机#1 - - 例行保养 - - 2023-12-20 - - 李工程师 - - - - - - - - - )} - - {selectedTabIndex === 4 && ( - - {/* 报表概览 */} - - 生产报表 - - - - {/* 生产数据 */} - - - 生产数据 - 2023-12-05 - - - - - 1,250 - 计划产量 - - - 1,180 - 实际产量 - - - 94.4% - 计划完成率 - - - 98.3% - 良品率 - - - - - 各产品线产量对比 - - - - 产量数据图表 - - - - - - {/* 设备运行报表 */} - - - 设备运行报表 - 2023-12-05 - - - - - 32 - 设备总数 - - - 28 - 运行设备 - - - 87.5% - 设备利用率 - - - 4.2h - 平均运行 - - - - - 设备运行状态分布 - - - - 设备状态图表 - - - - - - {/* 报表下载 */} - - 生产报表 - - - - 下载本月生产报表 - - - - - )} + {selectedTabIndex === 4 && } {/* 浮动按钮 */} - + ); }; -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#f5f5f5', - }, - headerButton: { - marginLeft: 16, - }, - - scrollView: { - flex: 1, - marginTop: 16, - }, - floatingButton: { - position: 'absolute', - right: 24, - bottom: 80, - width: 56, - height: 56, - borderRadius: 28, - backgroundColor: '#0066ff', - alignItems: 'center', - justifyContent: 'center', - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.25, - shadowRadius: 3.84, - elevation: 5, - }, - content: { - flex: 1, - paddingHorizontal: 16, - paddingTop: 16, - paddingBottom: 16, - }, - card: { - backgroundColor: 'white', - borderRadius: 16, - padding: 16, - marginBottom: 16, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 8, - elevation: 2, - }, - sectionTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 12, - color: '#333', - }, - statsGrid: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 12, - }, - statItem: { - alignItems: 'center', - flex: 1, - }, - statValue: { - fontSize: 24, - fontWeight: 'bold', - }, - statLabel: { - fontSize: 12, - color: '#6b7280', - marginTop: 4, - }, - completionRateCard: { - backgroundColor: '#ebf5ff', - borderRadius: 12, - padding: 12, - flexDirection: 'row', - alignItems: 'center', - }, - completionRateIcon: { - marginRight: 12, - }, - completionRateContent: { - flex: 1, - }, - completionRateLabel: { - fontSize: 14, - fontWeight: '500', - }, - completionRateValue: { - flexDirection: 'row', - alignItems: 'center', - }, - completionRatePercentage: { - fontSize: 18, - fontWeight: 'bold', - color: '#0066ff', - marginRight: 8, - }, - completionRateTrend: { - fontSize: 12, - color: '#22c55e', - }, - planItemHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'flex-start', - marginBottom: 8, - }, - planItemTitle: { - fontSize: 16, - fontWeight: '500', - color: '#333', - }, - statusBadge: { - paddingHorizontal: 8, - paddingVertical: 4, - borderRadius: 999, - }, - statusBadgeText: { - fontSize: 12, - fontWeight: '500', - }, - planItemCode: { - fontSize: 14, - color: '#6b7280', - marginBottom: 8, - }, - planItemInfo: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 12, - }, - planItemInfoText: { - fontSize: 14, - color: '#6b7280', - }, - progressContainer: { - marginBottom: 8, - }, - progressHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 4, - }, - progressLabel: { - fontSize: 14, - color: '#6b7280', - }, - progressBar: { - height: 6, - backgroundColor: '#e5e7eb', - borderRadius: 3, - overflow: 'hidden', - }, - progressValue: { - height: '100%', - borderRadius: 3, - }, - planItemFooter: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - }, - planItemStats: { - flexDirection: 'row', - alignItems: 'center', - }, - planItemStatsText: { - fontSize: 14, - color: '#6b7280', - }, - planItemStatsValue: { - fontSize: 14, - fontWeight: '500', - marginRight: 12, - }, - planItemLink: { - color: '#0066ff', - fontSize: 14, - }, - tabContent: { - padding: 16, - backgroundColor: 'white', - borderRadius: 16, - alignItems: 'center', - justifyContent: 'center', - minHeight: 200, - }, - tabContentText: { - fontSize: 16, - color: '#6b7280', - }, - // 工序流程图样式 - processFlowHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 12, - }, - processFlowTitle: { - fontSize: 16, - fontWeight: '500', - }, - processFlowBatch: { - flexDirection: 'row', - alignItems: 'center', - }, - processFlowBatchLabel: { - fontSize: 14, - color: '#0066ff', - fontWeight: '500', - }, - processFlowBatchValue: { - fontSize: 14, - }, - processFlowScroll: { - marginBottom: 12, - }, - processFlow: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: 8, - minWidth: '100%', - }, - processNode: { - alignItems: 'center', - width: 64, - marginHorizontal: 8, - }, - processNodeCircle: { - width: 64, - height: 64, - borderRadius: 32, - alignItems: 'center', - justifyContent: 'center', - marginBottom: 8, - position: 'relative', - }, - statusIconCompleted: { - position: 'absolute', - top: -4, - right: -4, - width: 24, - height: 24, - borderRadius: 12, - backgroundColor: '#22c55e', - alignItems: 'center', - justifyContent: 'center', - }, - statusIconInProgress: { - position: 'absolute', - top: -4, - right: -4, - width: 24, - height: 24, - borderRadius: 12, - backgroundColor: '#0066ff', - alignItems: 'center', - justifyContent: 'center', - }, - processNodeLabel: { - fontSize: 12, - fontWeight: '500', - marginBottom: 2, - }, - processNodeStatus: { - fontSize: 12, - color: '#6b7280', - }, - processNodeStatusInProgress: { - color: '#0066ff', - }, - processFlowLineCompleted: { - width: 48, - height: 2, - backgroundColor: '#22c55e', - }, - processFlowLinePending: { - width: 48, - height: 2, - backgroundColor: '#e5e7eb', - }, - processFlowInfo: { - backgroundColor: '#ebf5ff', - borderRadius: 12, - padding: 12, - flexDirection: 'row', - alignItems: 'center', - }, - processFlowInfoIcon: { - marginRight: 8, - }, - processFlowInfoText: { - fontSize: 14, - }, - processFlowInfoValue: { - fontWeight: '500', - }, - // 工序管理样式 - processInfoGrid: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 12, - }, - processInfoItem: { - flex: 1, - }, - processInfoLabel: { - fontSize: 12, - color: '#6b7280', - marginBottom: 4, - }, - processInfoValue: { - fontSize: 14, - fontWeight: '500', - }, - processEquipment: { - backgroundColor: '#ebf5ff', - borderRadius: 12, - padding: 12, - marginBottom: 12, - }, - processEquipmentLabel: { - fontSize: 14, - fontWeight: '500', - marginBottom: 8, - }, - processEquipmentItem: { - flexDirection: 'row', - alignItems: 'center', - }, - processEquipmentIcon: { - marginRight: 8, - }, - processEquipmentText: { - fontSize: 14, - }, - // 设备管理样式 - equipmentInfoGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - marginBottom: 12, - }, - equipmentInfoItem: { - width: '50%', - marginBottom: 8, - }, - equipmentInfoLabel: { - fontSize: 12, - color: '#6b7280', - marginBottom: 4, - }, - equipmentInfoValue: { - fontSize: 14, - fontWeight: '500', - }, - equipmentAlert: { - backgroundColor: '#ebf5ff', - borderRadius: 12, - padding: 12, - marginBottom: 12, - flexDirection: 'row', - alignItems: 'flex-start', - }, - equipmentAlertError: { - backgroundColor: '#fee2e2', - }, - equipmentAlertIcon: { - marginRight: 8, - marginTop: 2, - }, - equipmentAlertTitle: { - fontSize: 14, - fontWeight: '500', - marginBottom: 4, - }, - equipmentAlertTitleError: { - color: '#ef4444', - }, - equipmentAlertText: { - fontSize: 14, - }, - // 设备维护计划表格样式 - maintenanceTable: { - width: '100%', - }, - maintenanceTableHeader: { - flexDirection: 'row', - backgroundColor: '#f3f4f6', - paddingVertical: 8, - borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', - }, - maintenanceTableHeaderCell: { - width: 120, - paddingHorizontal: 8, - fontSize: 12, - fontWeight: '500', - color: '#6b7280', - textTransform: 'uppercase', - }, - maintenanceTableRow: { - flexDirection: 'row', - borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', - paddingVertical: 8, - }, - maintenanceTableCell: { - width: 120, - paddingHorizontal: 8, - fontSize: 14, - }, - maintenanceTableCellStatus: { - width: 120, - paddingHorizontal: 8, - justifyContent: 'center', - }, - // 报表样式 - reportDateSelector: { - flexDirection: 'row', - backgroundColor: '#f3f4f6', - borderRadius: 8, - padding: 4, - marginTop: 12, - }, - reportDateButton: { - flex: 1, - paddingVertical: 8, - alignItems: 'center', - borderRadius: 6, - }, - reportDateButtonActive: { - backgroundColor: 'white', - shadowColor: '#000', - shadowOffset: { width: 0, height: 1 }, - shadowOpacity: 0.1, - shadowRadius: 2, - elevation: 1, - }, - reportDateButtonText: { - fontSize: 14, - color: '#6b7280', - }, - reportDateButtonTextActive: { - color: '#0066ff', - fontWeight: '500', - }, - reportHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - marginBottom: 12, - }, - reportTitle: { - fontSize: 16, - fontWeight: '600', - }, - reportDate: { - fontSize: 14, - color: '#6b7280', - }, - reportGrid: { - flexDirection: 'row', - flexWrap: 'wrap', - marginBottom: 16, - }, - reportItem: { - width: '50%', - marginBottom: 12, - }, - reportItemValue: { - fontSize: 18, - fontWeight: 'bold', - color: '#0066ff', - marginBottom: 4, - }, - reportItemLabel: { - fontSize: 12, - color: '#6b7280', - }, - reportChart: { - marginBottom: 12, - }, - reportChartTitle: { - fontSize: 14, - fontWeight: '500', - marginBottom: 8, - }, - chartPlaceholder: { - height: 160, - backgroundColor: '#f9fafb', - borderRadius: 12, - alignItems: 'center', - justifyContent: 'center', - }, - chartPlaceholderText: { - fontSize: 14, - color: '#6b7280', - marginTop: 8, - }, - reportDownloadButton: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: 12, - borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', - }, - reportDownloadIcon: { - marginRight: 12, - }, - reportDownloadText: { - fontSize: 14, - color: '#333', - }, -}); - export default Production; diff --git a/src/app/(app)/profile.tsx b/src/app/(app)/profile.tsx index de2d2cc9a12f2ffc8aa79af886f5d2a2cd2a2f0f..99379d8e87aff4f48a8164714803e164508cff3c 100644 --- a/src/app/(app)/profile.tsx +++ b/src/app/(app)/profile.tsx @@ -1,12 +1,6 @@ import { Env } from '@env'; -import { Link } from 'expo-router'; -import { useRouter } from 'expo-router'; -import { - Image, - SafeAreaView, - StyleSheet, - TouchableOpacity, -} from 'react-native'; +import { Link, useRouter } from 'expo-router'; +import { Image, SafeAreaView, TouchableOpacity } from 'react-native'; import { NavHeader, ScrollView, Text, View } from '@/components/ui'; import { FontAwesome } from '@/components/ui/icons'; @@ -15,6 +9,15 @@ import { userInfo as user } from '@/lib/user'; import SettingItem from '../settings/components/setting-item'; +/** + * 个人资料页面 + * + * 展示用户信息、工作统计和功能菜单,包括: + * 1. 用户信息卡片:头像、姓名、角色、徽章和统计数据 + * 2. 功能菜单:个人资料、账号安全、消息通知等 + * 3. 工作统计:任务完成率、计划执行率、质检合格率 + * 4. 退出登录按钮 + */ export default function Settings() { const signOut = useAuth.use.signOut(); const userInfo = user.use.userInfo(); @@ -30,9 +33,8 @@ export default function Settings() { return ( <> {/* */} - + {/* 顶部导航 */} - } /> - + {/* 用户信息卡片 */} - - + + - - {userInfo?.UserName} - 生产部门 · 经理 - - - 管理员 + + {userInfo?.UserName} + 生产部门 · 经理 + + + 管理员 - - 已认证 + + 已认证 - - - 28 - 待处理任务 + + + 28 + 待处理任务 - - 15 - 今日完成 + + 15 + 今日完成 - - 98% - 任务完成率 + + 98% + 任务完成率 {/* 功能菜单 */} - + { - router.push('/test/device'); - }} + onPress={() => router.push('/test/device')} /> {}} - // text="profile.about" + onPress={() => router.push('/notification')} isLast={true} /> {/* 工作统计 */} - - 工作统计 - + + 工作统计 + @@ -133,11 +132,10 @@ export default function Settings() { {/* 退出登录按钮 */} signOut()} - className="m-10" > - + @@ -145,7 +143,13 @@ export default function Settings() { ); } -// 进度条组件 +/** + * 进度条组件 + * + * @param label - 进度条标签 + * @param value - 进度值(0-100) + * @param color - 进度条颜色 + */ type ProgressBarProps = { label: string; value: number; @@ -153,154 +157,16 @@ type ProgressBarProps = { }; const ProgressBar: React.FC = ({ label, value, color }) => ( - - - {label} - {value}% + + + {label} + {value}% - + ); -// 样式 -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#f5f5f5', - }, - content: { - flex: 1, - padding: 16, - paddingBottom: 86, // 为底部导航留出空间 - }, - card: { - backgroundColor: 'white', - borderRadius: 16, - padding: 16, - marginBottom: 16, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 10, - elevation: 2, - }, - userInfoContainer: { - flexDirection: 'row', - alignItems: 'center', - }, - avatar: { - width: 64, - height: 64, - borderRadius: 32, - marginRight: 16, - }, - userInfo: { - flex: 1, - }, - userName: { - fontSize: 20, - fontWeight: 'bold', - }, - userRole: { - fontSize: 14, - color: '#6b7280', - }, - badgeContainer: { - flexDirection: 'row', - marginTop: 4, - }, - adminBadge: { - backgroundColor: '#dbeafe', - paddingHorizontal: 8, - paddingVertical: 2, - borderRadius: 12, - }, - adminBadgeText: { - fontSize: 12, - color: '#1e40af', - }, - verifiedBadge: { - backgroundColor: '#dcfce7', - paddingHorizontal: 8, - paddingVertical: 2, - borderRadius: 12, - marginLeft: 8, - }, - verifiedBadgeText: { - fontSize: 12, - color: '#166534', - }, - statsContainer: { - flexDirection: 'row', - marginTop: 16, - paddingTop: 16, - borderTopWidth: 1, - borderTopColor: '#f3f4f6', - }, - statItem: { - flex: 1, - alignItems: 'center', - }, - statValue: { - fontSize: 18, - fontWeight: 'bold', - }, - statLabel: { - fontSize: 12, - color: '#6b7280', - }, - sectionTitle: { - fontSize: 18, - fontWeight: '600', - marginBottom: 12, - }, - progressContainer: { - marginTop: 4, - }, - progressItem: { - marginBottom: 12, - }, - progressHeader: { - flexDirection: 'row', - justifyContent: 'space-between', - marginBottom: 4, - }, - progressLabel: { - fontSize: 14, - }, - progressValue: { - fontSize: 14, - fontWeight: '500', - }, - progressTrack: { - height: 8, - backgroundColor: '#e5e7eb', - borderRadius: 4, - overflow: 'hidden', - }, - progressFill: { - height: '100%', - borderRadius: 4, - }, - logoutButton: { - backgroundColor: '#dc2626', - borderWidth: 1, - borderColor: '#e5e7eb', - borderRadius: 12, - paddingVertical: 12, - alignItems: 'center', - marginTop: 24, - marginBottom: 30, - }, - logoutButtonText: { - color: '#FFFFFF', - fontWeight: '500', - // fontSize: 16, - }, -}); diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 1f61ee51d293174419231d6d73888c54479ef3cb..b1ef2ab8eb3da0484b514c2cabc5fbdabbd5154e 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -1,5 +1,5 @@ /* eslint-disable max-lines-per-function */ -// Import global CSS file +// 导入全局CSS文件 import '../../global.css'; import { Provider, Toast } from '@ant-design/react-native'; @@ -9,7 +9,7 @@ import { Stack } from 'expo-router'; import * as SplashScreen from 'expo-splash-screen'; import * as Updates from 'expo-updates'; import React, { useEffect } from 'react'; -import { Platform, StyleSheet } from 'react-native'; +import { Platform } from 'react-native'; import { getUniqueId } from 'react-native-device-info'; import FlashMessage from 'react-native-flash-message'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; @@ -23,22 +23,34 @@ import { useThemeConfig } from '@/lib/use-theme-config'; export { ErrorBoundary } from 'expo-router'; +// 路由设置 export const unstable_settings = { initialRouteName: '(app)', }; -hydrateAuth(); -loadSelectedTheme(); -// Prevent the splash screen from auto-hiding before asset loading is complete. +// 初始化应用状态 +hydrateAuth(); // 恢复认证状态 +loadSelectedTheme(); // 加载用户选择的主题 + +// 防止启动屏幕在资源加载完成前自动隐藏 SplashScreen.preventAutoHideAsync(); -// Set the animation options. This is optional. +// 设置动画选项(可选) SplashScreen.setOptions({ duration: 500, fade: true, }); +// 配置Toast提示的默认持续时间 Toast.config({ duration: 2 }); +/** + * 应用根布局组件 + * 负责初始化应用环境、检查更新和设置全局提供者 + */ export default function RootLayout() { + /** + * 检查应用更新 + * 如果有可用更新,自动下载并重新加载应用 + */ const checkForUpdate = async () => { try { const update = await Updates.checkForUpdateAsync(); @@ -49,6 +61,7 @@ export default function RootLayout() { await Updates.reloadAsync(); } } catch (error) { + // 错误处理(已注释) // alert('检查更新失败:' + error); // if (error instanceof Error) { // alert('错误信息:' + error.message); @@ -56,15 +69,20 @@ export default function RootLayout() { // } } }; + + // 应用启动时执行的操作 useEffect(() => { if (Platform.OS !== 'web') { + // 检查应用更新 checkForUpdate(); + // 获取设备唯一ID并记录设备信息 getUniqueId().then((uniqueId) => { setUniqueId(uniqueId); recordDevice(uniqueId); }); } }); + return ( @@ -85,13 +103,16 @@ export default function RootLayout() { ); } +/** + * 全局提供者组件 + * 包装所有需要的上下文提供者,如主题、API、键盘等 + * @param {Object} props - 组件属性 + * @param {React.ReactNode} props.children - 子组件 + */ function Providers({ children }: { children: React.ReactNode }) { const theme = useThemeConfig(); return ( - + @@ -105,9 +126,3 @@ function Providers({ children }: { children: React.ReactNode }) { ); } - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, -}); diff --git a/src/app/equipment/[id].tsx b/src/app/equipment/[id].tsx new file mode 100644 index 0000000000000000000000000000000000000000..cffbe31610780f4932545bf3afb49d4125e89887 --- /dev/null +++ b/src/app/equipment/[id].tsx @@ -0,0 +1,367 @@ +import React, { useState } from 'react'; +import { SafeAreaView, TouchableOpacity } from 'react-native'; + +import { NavHeader, ScrollView, Text, View } from '@/components/ui'; +import { FontAwesome } from '@/components/ui/icons'; + +const EquipmentDetail = () => { + const [activeTab, setActiveTab] = useState('running-data'); + + // 切换选项卡 + const handleTabChange = (tabId: string) => { + setActiveTab(tabId); + }; + + return ( + + + + {/* 设备基本信息卡片 */} + + + 贴片机 #SMT-2023-01 + + 运行中 + + + + + + 负责人 + 张工程师 + + + 位置 + 生产车间A区 + + + 品牌型号 + 松下 NPM-W2 + + + 购入日期 + 2022-05-15 + + + 运行状态 + 正常 + + + 今日产能 + 850件 + + + + + + + + 设备警报 + 无异常警报 + + + + + + {/* 选项卡 - 分段控制器样式 */} + + handleTabChange('running-data')} + > + + 运行数据 + + + handleTabChange('maintenance-records')} + > + + 维护记录 + + + handleTabChange('performance-params')} + > + + 性能参数 + + + handleTabChange('fault-records')} + > + + 故障记录 + + + + + {/* 选项卡内容区域 */} + {/* 运行数据 */} + {activeTab === 'running-data' && ( + + {/* 设备监控 */} + + 设备监控 + + + 实时监控 + + + + + 设备实时监控画面 + + + + + + + + + 今日运行时长 + + 8.5小时 + + + 今日产能 + 850件 + + + + 平均贴片速度 + + 0.1秒/个 + + + 良品率 + 99.2% + + + + + + + + 设备状态良好 + + 下次计划维护时间:2023-12-15 + + + + + + + )} + + {/* 维护记录 */} + {activeTab === 'maintenance-records' && ( + + 维护记录 + + + + + + 日期 + + + 维护类型 + + + 维护人员 + + + 维护内容 + + + 状态 + + + + + + 2023-11-15 + 例行保养 + 王工程师 + + 清洁、润滑、校准 + + + + + 已完成 + + + + + + + + + 2023-10-20 + 部件更换 + 李工程师 + 更换吸嘴组件 + + + + 已完成 + + + + + + + + + 2023-09-10 + 例行保养 + 王工程师 + + 清洁、润滑、校准 + + + + + 已完成 + + + + + + + + + )} + + {/* 性能参数 */} + {activeTab === 'performance-params' && ( + + 性能参数 + + + + 设备温度 + 42°C + + + 电机转速 + 1200 RPM + + + 电压 + 220V + + + 电流 + 5.2A + + + + + + + + 设备警报 + 无异常警报 + + + + + )} + + {/* 故障记录 */} + {activeTab === 'fault-records' && ( + + 故障记录 + + + + + + 日期 + + + 故障类型 + + + 处理人员 + + + 处理方法 + + + 停机时长 + + + + + + 2023-11-05 + 吸嘴堵塞 + 王工程师 + 清洗吸嘴 + 2小时 + + + + + + 2023-10-12 + 供料器卡料 + 李工程师 + 调整供料器 + 1.5小时 + + + + + + 2023-09-25 + 视觉系统异常 + 张工程师 + 重新校准 + 3小时 + + + + + + )} + + + ); +}; + +export default EquipmentDetail; diff --git a/src/app/equipment/index.tsx b/src/app/equipment/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1f626e6cf7dcb4b156bdd4c78aa351e0a192eb7a --- /dev/null +++ b/src/app/equipment/index.tsx @@ -0,0 +1,344 @@ +import { useRouter } from 'expo-router'; +import React, { useState } from 'react'; +import { SafeAreaView, TextInput, TouchableOpacity } from 'react-native'; + +import { NavHeader, ScrollView, Text, View } from '@/components/ui'; +import { FontAwesome } from '@/components/ui/icons'; + +const Equipment = () => { + const [activeTab, setActiveTab] = useState('all'); + const router = useRouter(); + + // 切换选项卡 + const handleTabChange = (tabId: string) => { + setActiveTab(tabId); + }; + + type EquipmentProps = { + id: string; + name: string; + code: string; + projectManager: string; + location: string; + duration: number; + status: string; + capacity: number; + }; + // 模拟物料数据 + const data: EquipmentProps[] = [ + { + id: '1', + name: 'SMT贴片机#2', + code: 'EQ20230501-02', + status: '运行中', + projectManager: '王工程师', + location: 'A区生产线', + duration: 1245, + capacity: 850, + }, + { + id: '2', + name: 'AOI检测仪', + code: 'EQ20230315-05', + status: '运行中', + projectManager: '李工程师', + location: 'B区检测线', + duration: 985, + capacity: 1200, + }, + { + id: '4', + name: '自动化机械臂', + code: 'EQ20230610-08', + status: '故障中', + projectManager: '赵工程师', + location: 'C区装配线', + duration: 520, + capacity: 1560, + }, + ]; + + interface EquipmentItemProps { + equipment: EquipmentProps; + } + + const EquipmentItemItem = ({ equipment }: EquipmentItemProps) => ( + router.push(`/equipment/1`)} + > + + + {equipment.status === '运行中' && ( + + + + )} + {equipment.status === '待机中' && ( + + + + )} + {equipment.status === '故障中' && ( + + + + )} + + {equipment.name} + + 设备编号:{equipment.code} + + + + + {equipment.status === '运行中' && ( + + {equipment.status} + + )} + {equipment.status === '待机中' && ( + + {equipment.status} + + )} + {equipment.status === '故障中' && ( + + {equipment.status} + + )} + + + + + + 负责人 + {equipment.projectManager} + + + 位置 + {equipment.location} + + + 运行时长 + {equipment.duration}小时 + + + + + {equipment.status === '故障中' ? ( + + 故障:控制系统异常 + + ) : ( + + 今日产能:{equipment.capacity}件 + + )} + + + + + ); + return ( + + + + + + + } + /> + + + {/* 设备状态概览 */} + + 设备状态概览 + + + + 24 + 设备总数 + + + + 18 + + 运行中 + + + + 4 + + 待机中 + + + 2 + 故障中 + + + + + + 设备利用率 + 75% + + + + + + + + + + + 设备状态 + + 今日设备平均运行时长:7.5小时 | 本周维护计划:3台 + + + + + + + {/* 筛选和搜索 */} + + + handleTabChange('all')} + > + + 全部设备 + + + handleTabChange('production')} + > + + 生产设备 + + + handleTabChange('testing')} + > + + 检测设备 + + + handleTabChange('auxiliary')} + > + + 辅助设备 + + + + + + + + + + {/* 设备列表 */} + + {data.map((material, index) => ( + + ))} + + + {/* 维护计划 */} + + + 近期维护计划 + + 查看全部 + + + + + + + + SMT贴片机#1 - 例行保养 + + + + 待处理 + + + + + 计划时间:2023-12-10 | 负责人:王工程师 + + + + + 回流焊炉 - 温度校准 + + + 待处理 + + + + + 计划时间:2023-12-12 | 负责人:张工程师 + + + + + + 自动化机械臂 - 控制系统维修 + + + + 进行中 + + + + + 计划时间:2023-12-08 | 负责人:赵工程师 + + + + + + + ); +}; + +export default Equipment; diff --git a/src/app/inventory/[id].tsx b/src/app/inventory/[id].tsx new file mode 100644 index 0000000000000000000000000000000000000000..faa1c21f101e31ec5b3369ba13450c75aee09cb3 --- /dev/null +++ b/src/app/inventory/[id].tsx @@ -0,0 +1,517 @@ +import React, { useState } from 'react'; +import { + // Dimensions, + TouchableOpacity, +} from 'react-native'; + +import { NavHeader, ScrollView, Text, View } from '@/components/ui'; +// import { LineChart } from 'react-native-chart-kit'; +import { FontAwesome } from '@/components/ui/icons'; + +type TabType = 'info' | 'records' | 'usage'; + +interface RecordItem { + type: string; + date: string; + quantity: string; + operator: string; + document: string; + isInbound: boolean; +} + +interface UsageProduct { + name: string; + quantityPerUnit: string; + monthlyConsumption: string; +} + +interface RelatedMaterial { + name: string; + code: string; + quantity: number; + safetyStock: number; + status: 'normal' | 'warning' | 'danger'; +} + +const InventoryDetail: React.FC = () => { + const [activeTab, setActiveTab] = useState('info'); + + // 模拟数据 + const materialData = { + id: 'RM-10K-0805', + name: '电阻 10kΩ', + category: '原材料', + tag: '常用', + currentStock: 5000, + unit: '个', + safetyStock: 1000, + status: '充足', + spec: '0805封装 10kΩ ±1%', + category_detail: '电子元件 / 电阻', + supplier: '深圳市电子元件有限公司', + purchaseCycle: '3天', + price: 0.05, + stockValue: 250.0, + location: 'A区-03-12', + remark: '主板电路常用电阻', + }; + + const records: RecordItem[] = [ + { + type: '入库', + date: '2023-06-15 14:30', + quantity: '+2,000个', + operator: '张工', + document: 'PO-20230610-001', + isInbound: true, + }, + { + type: '出库', + date: '2023-06-10 09:15', + quantity: '-500个', + operator: '李工', + document: 'WO-20230608-002', + isInbound: false, + }, + { + type: '入库', + date: '2023-06-01 11:20', + quantity: '+3,500个', + operator: '张工', + document: 'PO-20230525-003', + isInbound: true, + }, + ]; + + const usageProducts: UsageProduct[] = [ + { + name: '智能控制器 A1', + quantityPerUnit: '每件用量: 8个', + monthlyConsumption: '月消耗: 约2,400个', + }, + { + name: '电源模块', + quantityPerUnit: '每件用量: 4个', + monthlyConsumption: '月消耗: 约800个', + }, + { + name: '主板组件', + quantityPerUnit: '每件用量: 12个', + monthlyConsumption: '月消耗: 约1,200个', + }, + ]; + + const relatedMaterials: RelatedMaterial[] = [ + { + name: '电阻 1kΩ', + code: 'RM-1K-0805', + quantity: 4200, + safetyStock: 1000, + status: 'normal', + }, + { + name: '电阻 100kΩ', + code: 'RM-100K-0805', + quantity: 3800, + safetyStock: 1000, + status: 'normal', + }, + { + name: '电容 0.1uF', + code: 'CM-0.1UF-0805', + quantity: 1500, + safetyStock: 1200, + status: 'warning', + }, + ]; + + // 库存趋势图数据 + // const stockData = { + // labels: ['1月', '2月', '3月', '4月', '5月', '6月'], + // datasets: [ + // { + // data: [3000, 4500, 2800, 5000, 3500, 5000], + // color: () => `rgba(59, 130, 246, 1)`, + // strokeWidth: 2, + // }, + // { + // data: [1000, 1000, 1000, 1000, 1000, 1000], + // color: () => `rgba(239, 68, 68, 1)`, + // strokeWidth: 2, + // withDots: false, + // }, + // ], + // }; + + // const chartConfig = { + // backgroundGradientFrom: '#ffffff', + // backgroundGradientTo: '#ffffff', + // decimalPlaces: 0, + // color: () => `rgba(59, 130, 246, 0.6)`, + // labelColor: () => `rgba(107, 114, 128, 1)`, + // style: { + // borderRadius: 16, + // }, + // propsForDots: { + // r: '4', + // strokeWidth: '2', + // stroke: '#3b82f6', + // }, + // }; + + // const screenWidth = Dimensions.get('window').width - 40; // 考虑内边距 + + // 详情行组件 + const DetailRow = ({ label = '', value = '', isLast = false }) => ( + + {label} + {value} + + ); + + // 获取库存状态颜色 + const getStatusColor = (status: string) => { + switch (status) { + case '充足': + return { bg: 'bg-green-500', text: 'text-green-600' }; + case '警告': + return { bg: 'bg-yellow-500', text: 'text-yellow-600' }; + case '不足': + return { bg: 'bg-red-500', text: 'text-red-600' }; + default: + return { bg: 'bg-green-500', text: 'text-green-600' }; + } + }; + + const statusColor = getStatusColor(materialData.status); + + const renderTabContent = () => { + switch (activeTab) { + case 'info': + return ( + + + + + + + + + + + + ); + case 'records': + return ( + + {records.map((record, index) => ( + + + {record.type} + {record.date} + + + 数量: {record.quantity} + + + 操作人: {record.operator} + + + 关联单据: {record.document} + + + ))} + + ); + case 'usage': + return ( + + 近期使用产品 + + {usageProducts.map((product, index) => ( + + + + + {product.name} + + {product.quantityPerUnit} + + + + {product.monthlyConsumption} + + ))} + + + 消耗预测 + + + 预计月消耗 + 约4,500个 + + + 当前库存可用 + 约1.1个月 + + + 建议补货时间 + 2周内 + + + + ); + default: + return null; + } + }; + + return ( + + + + + + + } + /> + + + {/* 物料基本信息卡片 */} + + + + + + + {materialData.name} + + 编号: {materialData.id} + + + + + {materialData.category} + + + + + {materialData.tag} + + + + + + + {/* 库存状态 */} + + + 当前库存 + + {materialData.currentStock.toLocaleString()} + + {materialData.unit} + + + + + 安全库存 + + {materialData.safetyStock.toLocaleString()} + + {materialData.unit} + + + + + 状态 + + + + {materialData.status} + + + + + + {/* 快捷操作按钮 */} + + + + 入库 + + + + 出库 + + + + 调拨 + + + + 扫码 + + + + + {/* 库存趋势图 */} + + 库存趋势 + {/* */} + + + {/* 详细信息选项卡 */} + + + setActiveTab('info')} + > + + 基本信息 + + + setActiveTab('records')} + > + + 出入库记录 + + + setActiveTab('usage')} + > + + 使用情况 + + + + + {renderTabContent()} + + + {/* 相关物料 */} + + + 相关物料 + + 查看全部 + + + + + {relatedMaterials.map((material, index) => { + let indicatorColor = 'bg-green-500'; + if (material.status === 'warning') { + indicatorColor = 'bg-yellow-500'; + } else if (material.status === 'danger') { + indicatorColor = 'bg-red-500'; + } + + return ( + + + + + {material.name} + + 编号: {material.code} + + + + + + {material.quantity.toLocaleString()} + + + 安全库存: {material.safetyStock.toLocaleString()} + + + + ); + })} + + + + + ); +}; + +export default InventoryDetail; diff --git a/src/app/inventory/item.tsx b/src/app/inventory/item.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d2402815f187a11e3c512eb2a7d02c3751fb9c75 --- /dev/null +++ b/src/app/inventory/item.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { TouchableOpacity } from 'react-native'; + +import { Text, View } from '@/components/ui'; + +type InventoryItemProps = { + name: string; + code: string; + quantity: number; + safetyStock: number; + status: 'normal' | 'warning' | 'danger'; + onViewDetail?: () => void; +}; + +const Item = ({ + name, + code, + quantity, + safetyStock, + status, + onViewDetail, +}: InventoryItemProps) => { + let indicatorColor = '#22c55e'; // 绿色 - 正常 + let textColor = 'text-black'; + + if (status === 'warning') { + indicatorColor = '#eab308'; // 黄色 - 警告 + } else if (status === 'danger') { + indicatorColor = '#ef4444'; // 红色 - 危险 + textColor = 'text-red-500'; + } + + return ( + + + + + + {name} + + 编号:{code} + + + + {quantity} + + 安全库存:{safetyStock} + + + + ); +}; + +export default Item; diff --git a/src/app/notification/[id].tsx b/src/app/notification/[id].tsx new file mode 100644 index 0000000000000000000000000000000000000000..7a365f982e715af4fbe349e904de6761023da4f1 --- /dev/null +++ b/src/app/notification/[id].tsx @@ -0,0 +1,338 @@ +import { useLocalSearchParams } from 'expo-router'; +import React, { useEffect, useState } from 'react'; +import { StyleSheet, TouchableOpacity } from 'react-native'; + +import { NavHeader, ScrollView, Text, View } from '@/components/ui'; +import { FontAwesome, GroupEnum } from '@/components/ui/icons'; + +interface RelatedNotification { + id: string; + title: string; + message: string; + time: string; + icon: string; + iconBgColor: string; +} + +const NotificationDetail = () => { + // const notificationType1 = route.params?.type || 'warning'; + const local = useLocalSearchParams<{ type: string }>(); + const notificationType = local.type; + + // 通知详情状态 + const [notificationInfo, setNotificationInfo] = useState({ + title: '库存预警', + time: '今天 10:30', + date: '2023年11月29日', + content: + 'PCB板库存低于安全库存,当前库存数量为25个,安全库存为50个,请及时补货。\n\n低库存可能导致生产计划延误,建议在3天内完成补货。', + icon: 'exclamation-triangle', + iconBgColor: '#ef4444', // red-500 + badgeBg: 'bg-red-100', + badgeText: 'text-red-800', + badgeContent: '预警信息', + actionText: '查看物料详情', + relatedInfo: [ + { label: '物料编号', value: 'PCB-2023-1105' }, + { label: '当前库存', value: '25个', isAlert: true }, + { label: '安全库存', value: '50个' }, + { label: '最近一次入库', value: '2023-11-15' }, + ], + }); + + // 相关通知 + const relatedNotifications: RelatedNotification[] = [ + { + id: '1', + title: '库存预警', + message: '电阻R0805库存不足,请及时补货。', + time: '11-20', + icon: 'exclamation-circle', + iconBgColor: '#eab308', // yellow-500 + }, + { + id: '2', + title: '物料入库', + message: 'PCB板已完成入库,入库数量100个。', + time: '11-15', + icon: 'truck', + iconBgColor: '#3b82f6', // blue-500 + }, + ]; + + // 根据通知类型设置样式和内容 + useEffect(() => { + let updatedInfo = { ...notificationInfo }; + + switch (notificationType) { + case 'warning': + updatedInfo = { + ...updatedInfo, + title: '库存预警', + icon: 'exclamation-triangle', + iconBgColor: '#ef4444', // red-500 + badgeBg: 'bg-red-100', + badgeText: 'text-red-800', + badgeContent: '预警信息', + actionText: '查看物料详情', + }; + break; + case 'task': + updatedInfo = { + ...updatedInfo, + title: '任务分配', + content: + '您有一个新的生产任务 #PT20231129-02 需要处理。请在今天下午3点前完成相关准备工作。', + icon: 'tasks', + iconBgColor: '#22c55e', // green-500 + badgeBg: 'bg-green-100', + badgeText: 'text-green-800', + badgeContent: '任务提醒', + actionText: '处理任务', + }; + break; + case 'order': + updatedInfo = { + ...updatedInfo, + title: '订单完成', + content: + '订单 #2023112801 已完成生产,等待发货。请安排物流部门进行后续处理。', + icon: 'clipboard-check', + iconBgColor: '#3b82f6', // blue-500 + badgeBg: 'bg-blue-100', + badgeText: 'text-blue-800', + badgeContent: '订单通知', + actionText: '查看订单', + }; + break; + case 'system': + updatedInfo = { + ...updatedInfo, + title: '系统维护', + content: + '系统将于今晚22:00-23:00进行例行维护,请提前做好准备。维护期间系统将暂停服务。', + icon: 'bell', + iconBgColor: '#eab308', // yellow-500 + badgeBg: 'bg-yellow-100', + badgeText: 'text-yellow-800', + badgeContent: '系统通知', + actionText: '了解详情', + }; + break; + case 'report': + updatedInfo = { + ...updatedInfo, + title: '数据报表', + content: + '11月生产效率分析报表已生成,请查看。本月生产效率较上月提升5.2%。', + icon: 'chart-line', + iconBgColor: '#a855f7', // purple-500 + badgeBg: 'bg-purple-100', + badgeText: 'text-purple-800', + badgeContent: '数据报表', + actionText: '查看报表', + }; + break; + case 'team': + updatedInfo = { + ...updatedInfo, + title: '新成员加入', + content: '李工程师已加入您的生产团队,请及时安排工作。', + icon: 'user-plus', + iconBgColor: '#6366f1', // indigo-500 + badgeBg: 'bg-indigo-100', + badgeText: 'text-indigo-800', + badgeContent: '团队通知', + actionText: '查看团队', + }; + break; + case 'update': + updatedInfo = { + ...updatedInfo, + title: '系统更新', + content: + '系统已更新至v1.0.5版本,新增多项功能和优化。主要更新内容包括:生产计划优化、库存预警阈值自定义、报表导出功能等。', + icon: 'cogs', + iconBgColor: '#f97316', // orange-500 + badgeBg: 'bg-orange-100', + badgeText: 'text-orange-800', + badgeContent: '系统更新', + actionText: '查看更新', + }; + break; + } + + setNotificationInfo(updatedInfo); + }, [notificationType]); + + // 处理主要操作按钮点击 + const handlePrimaryAction = () => { + switch (notificationType) { + case 'warning': + // navigation.navigate('MaterialDetail', { id: 'PCB-2023-1105' }); + break; + case 'order': + // navigation.navigate('Orders'); + break; + case 'task': + // navigation.navigate('Production'); + break; + case 'report': + // navigation.navigate('Analytics'); + break; + default: + // navigation.navigate('Notifications'); + } + }; + + // 处理标记为已读 + const handleMarkAsRead = () => { + // 实际应用中这里会更新通知状态 + console.log('标记为已读'); + }; + + return ( + + + + + + + + + + } + /> + + + {/* 通知类型标签 */} + + + {notificationInfo.badgeContent} + + + + {/* 通知详情卡片 */} + + + + + + + + + {notificationInfo.title} + + + {notificationInfo.time} + + + + {notificationInfo.date} + + + + + + 详细内容 + + {notificationInfo.content} + + + + {/* 相关信息 */} + + 相关信息 + {notificationInfo.relatedInfo.map((item, index) => ( + + + {item.label} + + {item.value} + + + + ))} + + + + {/* 操作按钮 */} + + + + {notificationInfo.actionText} + + + + 标记为已读 + + + + {/* 相关通知 */} + 相关通知 + + {relatedNotifications.map((item, index) => ( + + + + + + + + {item.title} + {item.time} + + + {item.message} + + + + + ))} + + + + ); +}; + +const styles = StyleSheet.create({ + headerButton: { + marginLeft: 16, + }, +}); +export default NotificationDetail; diff --git a/src/app/notification/index.tsx b/src/app/notification/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4cc6599d4789aa9c2afec37523cf3098ec0e3b10 --- /dev/null +++ b/src/app/notification/index.tsx @@ -0,0 +1,263 @@ +import { useRouter } from 'expo-router'; +import React, { useState } from 'react'; +import { StyleSheet, TouchableOpacity } from 'react-native'; + +import { SegmentedControl, type SegmentedControlOption } from '@/components'; +import { NavHeader, ScrollView, Text, View } from '@/components/ui'; +import { FontAwesome, GroupEnum } from '@/components/ui/icons'; + +// type TabType = 0 | 1 | 2 | 3; + +interface NotificationItem { + id: string; + type: number; + title: string; + message: string; + time: string; + icon: string; + iconBgColor: string; + isUnread: boolean; + date: 'today' | 'yesterday' | 'earlier'; +} + +const Notification = () => { + const [selectedTabIndex, setSelectedTabIndex] = useState(0); + const router = useRouter(); + + // 模拟通知数据 + const notifications: NotificationItem[] = [ + { + id: '1', + type: 0, + title: '库存预警', + message: 'PCB板库存低于安全库存,请及时补货。', + time: '10:30', + icon: 'exclamation-triangle', + iconBgColor: '#ef4444', // red-500 + isUnread: true, + date: 'today', + }, + { + id: '2', + type: 1, + title: '订单完成', + message: '订单 #2023112801 已完成生产,等待发货。', + time: '09:45', + icon: 'clipboard-check', + iconBgColor: '#3b82f6', // blue-500 + isUnread: true, + date: 'today', + }, + { + id: '3', + type: 1, + title: '任务分配', + message: '您有一个新的生产任务 #PT20231129-02 需要处理。', + time: '08:20', + icon: 'tasks', + iconBgColor: '#22c55e', // green-500 + isUnread: true, + date: 'today', + }, + { + id: '4', + type: 2, + title: '数据报表', + message: '11月生产效率分析报表已生成,请查看。', + time: '昨天 16:30', + icon: 'chart-line', + iconBgColor: '#a855f7', // purple-500 + isUnread: false, + date: 'yesterday', + }, + { + id: '5', + type: 2, + title: '系统维护', + message: '系统将于今晚22:00-23:00进行例行维护,请提前做好准备。', + time: '昨天 14:15', + icon: 'bell', + iconBgColor: '#eab308', // yellow-500 + isUnread: false, + date: 'yesterday', + }, + { + id: '6', + type: 2, + title: '新成员加入', + message: '李工程师已加入您的生产团队,请及时安排工作。', + time: '11-27', + icon: 'user-plus', + iconBgColor: '#6366f1', // indigo-500 + isUnread: false, + date: 'earlier', + }, + { + id: '7', + type: 2, + title: '系统更新', + message: '系统已更新至v1.0.5版本,新增多项功能和优化,点击查看详情。', + time: '11-25', + icon: 'cogs', + iconBgColor: '#f97316', // orange-500 + isUnread: false, + date: 'earlier', + }, + ]; + + // 根据选中的选项卡筛选通知 + const filteredNotifications = + selectedTabIndex === 0 + ? notifications + : notifications.filter((item) => item.type === selectedTabIndex); + + // 按日期分组通知 + const todayNotifications = filteredNotifications.filter( + (item) => item.date === 'today' + ); + const yesterdayNotifications = filteredNotifications.filter( + (item) => item.date === 'yesterday' + ); + const earlierNotifications = filteredNotifications.filter( + (item) => item.date === 'earlier' + ); + + // 处理查看详情 + const handleViewDetail = (id: string) => { + router.push(`/notification/${id}`); + }; + // 处理忽略通知 + const handleIgnore = (id: string) => { + // 实际应用中这里会更新状态 + console.log('忽略通知:', id); + }; + + // 处理清除所有通知 + // const handleClearAll = () => { + // // 实际应用中这里会清除所有通知 + // console.log('清除所有通知'); + // }; + + // 渲染通知项 + const renderNotificationItem = (item: NotificationItem) => ( + handleViewDetail(item.id)} + > + + + + + + + {item.isUnread && ( + + )} + + + + {item.title} + {item.time} + + {item.message} + + {/* 查看详情 */} + handleIgnore(item.id)} + > + 忽略 + + + + + + + ); + const tabOptions: SegmentedControlOption[] = [ + { key: 'production-plan', label: '全部' }, + { key: 'production-task', label: '系统通知' }, + { key: 'process-management', label: '任务提醒' }, + { key: 'process-management1', label: '预警信息' }, + ]; + return ( + + + + + + + } + /> + + + + + {/* 今日通知 */} + {todayNotifications.length > 0 && ( + <> + 今日通知 + + {todayNotifications.map(renderNotificationItem)} + + + )} + + {/* 昨日通知 */} + {yesterdayNotifications.length > 0 && ( + <> + 昨日通知 + + {yesterdayNotifications.map(renderNotificationItem)} + + + )} + + {/* 更早通知 */} + {earlierNotifications.length > 0 && ( + <> + 更早 + + {earlierNotifications.map(renderNotificationItem)} + + + )} + + {/* 清除按钮 */} + {/* + + 清除所有通知 + + */} + + + ); +}; +const styles = StyleSheet.create({ + headerButton: { + marginLeft: 16, + }, +}); +export default Notification; diff --git a/src/app/onboarding.tsx b/src/app/onboarding.tsx index 3d49fcf9f236381371353b83d7642ec05e1059b3..c768683bb63d121c2a0a75984ae9e088cdb87a1b 100644 --- a/src/app/onboarding.tsx +++ b/src/app/onboarding.tsx @@ -1,4 +1,4 @@ -/* eslint-disable react/react-in-jsx-scope */ +import { Env } from '@env'; import { FontAwesome } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { useRouter } from 'expo-router'; @@ -6,9 +6,11 @@ import React, { useEffect, useRef } from 'react'; import { Animated, Dimensions, + Platform, StyleSheet, TouchableOpacity, } from 'react-native'; +import { getVersion } from 'react-native-device-info'; import { FocusAwareStatusBar, @@ -19,6 +21,7 @@ import { View, } from '@/components/ui'; import { useIsFirstTime } from '@/lib/hooks'; +import { translate } from '@/lib/i18n'; const { width, height } = Dimensions.get('window'); @@ -79,7 +82,7 @@ const Welcome: React.FC = () => { }), ]) ).start(); - }, []); + }); // 处理开始使用按钮点击 const handleGetStarted = () => { @@ -92,9 +95,9 @@ const Welcome: React.FC = () => { <> - + {/* 背景粒子效果 */} - + {particles.map((particle) => ( { ))} - + {/* 版本标识 */} - - v2.0.1 - + {(Platform.OS === 'ios' || Platform.OS === 'android') && ( + + + V{getVersion()} + + + )} {/* 顶部空间 */} @@ -140,12 +149,11 @@ const Welcome: React.FC = () => { ]} > + { /> - 优智云 - 智能制造管理系统 + + + {Env.NAME} + + + {translate('login.sub_title')} + {/* 欢迎信息 */} @@ -171,14 +184,16 @@ const Welcome: React.FC = () => { }, ]} > - 欢迎使用轻智造ERP系统 - + + 欢迎使用轻智造ERP系统 + + 高效、智能的制造业管理解决方案,助力企业数字化转型,提升生产效率 {/* 功能特点 */} - + { ]} > - 开始使用 + + 开始使用 + { style={{ marginLeft: 8 }} /> - {/*