diff --git a/README.md b/README.md index ff706feb35821b12eaed7814dbc0ab4a1f5b374b..4a2c4cb99b861e210392a9f09bda2ab2d725af01 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ Android : ![image-4](./doc/images/android/4.png) ![image-5](./doc/images/android/5.png) +## Installer + +> 👉 Android only. For iOS, please use a virtual machine. Test Account: `Admin`, Password: `1` + +![image-1](./doc/images/android-download.png) + ## Requirements - [React Native dev environment ](https://reactnative.dev/docs/environment-setup) diff --git a/doc/images/android-download.png b/doc/images/android-download.png new file mode 100644 index 0000000000000000000000000000000000000000..01a98bc0e084d72cc1325b3b41141a48b2c57a1e Binary files /dev/null and b/doc/images/android-download.png differ diff --git a/src/app/(app)/index.tsx b/src/app/(app)/index.tsx index fb435996b3417f96611f44c8651a057e1a00f614..ca48008b4dc3247ad42221ae76ab53d44ec91b54 100644 --- a/src/app/(app)/index.tsx +++ b/src/app/(app)/index.tsx @@ -158,13 +158,13 @@ const Home: React.FC = () => { icon="boxes" bgColor="#22c55e" title="库存管理" - // onPress={() => navigation.navigate('Inventory')} + onPress={() => router.push('/inventory')} /> navigation.navigate('Orders')} + onPress={() => router.push('/order')} /> { title="物流管理" onPress={() => {}} /> - { bgColor="#7423de" title="设备管理" onPress={() => router.push('/equipment')} - /> + /> */} { const [activeTab, setActiveTab] = useState('product-list'); diff --git a/src/app/process/[id].tsx b/src/app/process/[id].tsx index e292421d60fe7d8b831f5af51567c5eed4e2a355..cfe43ba854e5f33191b051b9cb050fb1fce39d24 100644 --- a/src/app/process/[id].tsx +++ b/src/app/process/[id].tsx @@ -1,4 +1,3 @@ -import { StatusBar } from 'expo-status-bar'; import React, { useState } from 'react'; import { SafeAreaView, @@ -16,8 +15,6 @@ export default function ProcessDetail() { return ( - - { const [activeTab, setActiveTab] = useState('production-process'); return ( - - { - - - + + + @@ -166,10 +163,20 @@ const ProductionDetail = () => { - - - - + + + + 缝制 @@ -179,10 +186,10 @@ const ProductionDetail = () => { - + @@ -193,8 +200,8 @@ const ProductionDetail = () => { - - + + 质检 待开始 @@ -203,8 +210,8 @@ const ProductionDetail = () => { - - + + 包装 待开始 diff --git a/src/app/quality/index.tsx b/src/app/quality/index.tsx index b00e4084f7cb0ff1e4c9cc0533ded816d463345e..759996b5459e0b5c8d534bb6a14ed2de1c93fb4a 100644 --- a/src/app/quality/index.tsx +++ b/src/app/quality/index.tsx @@ -1,6 +1,5 @@ // import { useNavigation } from '@react-navigation/native'; import { useRouter } from 'expo-router'; -import { StatusBar } from 'expo-status-bar'; import React, { useState } from 'react'; import { SafeAreaView, @@ -495,8 +494,6 @@ const Quality = () => { > - - ); }; diff --git a/src/app/inventory/item.tsx b/src/components/inventory/item.tsx similarity index 100% rename from src/app/inventory/item.tsx rename to src/components/inventory/item.tsx diff --git a/src/components/login-form.tsx b/src/components/login-form.tsx index f248949bab9c9f9c55b48b749110bfd4faf3de70..482b4f79c00506cab0d2b213307108691f1750cb 100644 --- a/src/components/login-form.tsx +++ b/src/components/login-form.tsx @@ -1,8 +1,6 @@ /* eslint-disable react/react-in-jsx-scope */ // import { zodResolver } from '@hookform/resolvers/zod'; import { Env } from '@env'; -import { FontAwesome } from '@expo/vector-icons'; -import Entypo from '@expo/vector-icons/Entypo'; import { useRouter } from 'expo-router'; import React, { useState } from 'react'; import { @@ -20,6 +18,7 @@ import * as z from 'zod'; import { loginApi } from '@/api'; import { Image, Text, View } from '@/components/ui'; +import { FontAwesome, GroupEnum } from '@/components/ui/icons'; import { signIn } from '@/lib'; import { translate } from '@/lib/i18n'; import { setUserInfo } from '@/lib/user'; @@ -229,7 +228,12 @@ export const LoginForm = () => { - + diff --git a/src/components/production/equipment.tsx b/src/components/production/equipment.tsx index cfefb685fd83f6443cd112ea2391881a652c4a32..28bade6d60a000db0834115348ed3151b41b3e77 100644 --- a/src/components/production/equipment.tsx +++ b/src/components/production/equipment.tsx @@ -1,6 +1,7 @@ -import { FontAwesome } from '@expo/vector-icons'; import { ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { FontAwesome } from '@/components/ui/icons'; + import { StatusBadge } from './status-badge'; export const Equipment = () => { diff --git a/src/components/production/plan.tsx b/src/components/production/plan.tsx index 16f8a994334a0bec938ce22daf78241d2ef51d88..40976679005cfc1f10b0f6b7e0fa5c9f68d4d8c5 100644 --- a/src/components/production/plan.tsx +++ b/src/components/production/plan.tsx @@ -1,7 +1,8 @@ -import { FontAwesome } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; import { Text, TouchableOpacity, View } from 'react-native'; +import { FontAwesome } from '@/components/ui/icons'; + import { ProgressBar } from './progress-bar'; import { StatusBadge } from './status-badge'; diff --git a/src/components/production/process.tsx b/src/components/production/process.tsx index 849921fc35f345a6f46f161d0ad5e079f71ccc18..a9fdbb72f4bf5f11ce59c4e56da2f2a71b21a7f3 100644 --- a/src/components/production/process.tsx +++ b/src/components/production/process.tsx @@ -1,6 +1,7 @@ -import { FontAwesome } from '@expo/vector-icons'; import { ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { FontAwesome } from '@/components/ui/icons'; + import { ProcessNode } from './process-node'; import { ProgressBar } from './progress-bar'; import { StatusBadge } from './status-badge'; diff --git a/src/components/production/report.tsx b/src/components/production/report.tsx index 08fb16d1d39d860b783a0645ca3baaf94cdee40a..195cd523a79d7d16458b558652b76514c0ce3458 100644 --- a/src/components/production/report.tsx +++ b/src/components/production/report.tsx @@ -1,6 +1,7 @@ -import { FontAwesome } from '@expo/vector-icons'; import { Text, TouchableOpacity, View } from 'react-native'; +import { FontAwesome } from '@/components/ui/icons'; + import ReportDateSelector from './report-date-selector'; /** diff --git a/src/components/production/task.tsx b/src/components/production/task.tsx index ab791750e4597c24fddeb778ca784207ff572310..2166d5c614ff363c278f8411f44ed5b2ac129dd6 100644 --- a/src/components/production/task.tsx +++ b/src/components/production/task.tsx @@ -1,6 +1,7 @@ -import { FontAwesome } from '@expo/vector-icons'; import { Text, TouchableOpacity, View } from 'react-native'; +import { FontAwesome } from '@/components/ui/icons'; + import { ProgressBar } from './progress-bar'; import { StatusBadge } from './status-badge'; diff --git a/src/components/ui/icons/font-awesome.tsx b/src/components/ui/icons/font-awesome.tsx index 2b6bc22ffbb9fd25548cedecc1ce89e4a41ae6ac..44d55b2dc4e4dbd528e9534c89f14e33758bd300 100644 --- a/src/components/ui/icons/font-awesome.tsx +++ b/src/components/ui/icons/font-awesome.tsx @@ -1,10 +1,12 @@ import { + AntDesign, Entypo, EvilIcons, FontAwesome as FontAwesomeIcon, FontAwesome5, } from '@expo/vector-icons'; import React from 'react'; +import { type StyleProp, type TextStyle } from 'react-native'; /** * 图标组类型枚举 @@ -15,6 +17,7 @@ export enum GroupEnum { Entypo = 'Entypo', FontAwesome5 = 'FontAwesome5', EvilIcons = 'EvilIcons', + AntDesign = 'AntDesign', } /** @@ -25,23 +28,48 @@ type Group = | GroupEnum.Entypo | GroupEnum.FontAwesome5 | GroupEnum.FontAwesome - | GroupEnum.EvilIcons; + | GroupEnum.EvilIcons + | GroupEnum.AntDesign; + +/** + * 各图标库的图标名称类型 + * 用于提供更好的类型检查 + */ +type EntypoIconNames = React.ComponentProps['name']; +type FontAwesome5IconNames = React.ComponentProps['name']; +type FontAwesomeIconNames = React.ComponentProps< + typeof FontAwesomeIcon +>['name']; +type EvilIconsNames = React.ComponentProps['name']; +type AntDesignIconNames = React.ComponentProps['name']; + +/** + * 统一的图标名称类型 + * 包含所有支持的图标库的图标名称 + */ +type IconName = + | EntypoIconNames + | FontAwesome5IconNames + | FontAwesomeIconNames + | EvilIconsNames + | AntDesignIconNames + | string; // 保留string类型以兼容可能的自定义图标 /** * FontAwesome图标组件的属性接口 - * @property {string} name - 图标名称 - * @property {number} [size=24] - 图标大小 + * @property {IconName} name - 图标名称 + * @property {number} [size=24] - 图标大小,默认为24 * @property {string} [color] - 图标颜色 - * @property {React.CSSProperties} [style] - 自定义样式 - * @property {string} [className] - 自定义CSS类名 + * @property {StyleProp} [style] - 自定义样式,使用React Native的样式类型 + * @property {string} [className] - 自定义CSS类名,用于Tailwind样式 * @property {Group} [group] - 指定图标组,不指定时会自动判断 */ type FontAwesomeIconProps = { - name: string; + name: IconName; size?: number; color?: string; - style?: React.CSSProperties; - className?: string; // 添加className属性 + style?: StyleProp; // 修改为React Native的样式类型 + className?: string; group?: Group; }; @@ -49,8 +77,8 @@ type FontAwesomeIconProps = { * FontAwesome5专用图标列表 * 当图标名称在此列表中时,将自动使用FontAwesome5库 */ -const FA5_ICONS = [ - // 原有图标 +const FA5_ICONS: string[] = [ + // 基础图标 'palette', 'shield-alt', 'cloud-download-alt', @@ -94,16 +122,25 @@ const isFA5Icon = (iconName: string): boolean => { * 统一的FontAwesome图标组件 * 根据图标名称或指定的组类型自动选择正确的图标库 * + * 组件会按照以下优先级选择图标库: + * 1. 如果图标名称在FA5_ICONS列表中,使用FontAwesome5 + * 2. 如果指定了group参数,使用指定的图标库 + * 3. 默认使用FontAwesome + * * @example * // 基本用法 * * - * // 使用className设置样式 - * + * // 使用className设置Tailwind样式 + * * * // 指定图标组 * * + * // 在不同场景下使用 + * // 自动使用FontAwesome5 + * // 自动使用FontAwesome + * * @param {FontAwesomeIconProps} props - 组件属性 * @returns {React.ReactElement} 渲染的图标组件 */ @@ -115,60 +152,35 @@ export const FontAwesome: React.FC = ({ className, group, }) => { + // 创建通用的图标属性 + const iconProps = { + size, + color, + style, + className, + }; + // 优先根据图标名称自动判断图标库 if (isFA5Icon(name)) { - return ( - - ); + return ; } // 其次根据指定的组类型选择图标库 - if (group === GroupEnum.Entypo) { - return ( - - ); - } else if (group === GroupEnum.FontAwesome5) { - return ( - - ); - } else if (group === GroupEnum.EvilIcons) { - return ( - - ); + switch (group) { + case GroupEnum.Entypo: + return ; + case GroupEnum.FontAwesome5: + return ( + + ); + case GroupEnum.EvilIcons: + return ; + case GroupEnum.AntDesign: + return ; + default: + // 默认使用FontAwesome + return ( + + ); } - - // 默认使用FontAwesome - return ( - - ); }; diff --git a/src/components/ui/nav-header.tsx b/src/components/ui/nav-header.tsx index 083112332aa3cb0e36dbba14a8def2101a6356db..0e649553319be3faa0db8ef69f05ace78ed7c679 100644 --- a/src/components/ui/nav-header.tsx +++ b/src/components/ui/nav-header.tsx @@ -1,4 +1,3 @@ -import AntDesign from '@expo/vector-icons/AntDesign'; import { Stack, useRouter } from 'expo-router'; import React from 'react'; import { @@ -10,8 +9,10 @@ import { } from 'react-native'; import { Platform } from 'react-native'; +import { FontAwesome, GroupEnum } from '@/components/ui/icons'; import type { TxKeyPath } from '@/lib/i18n'; import { translate } from '@/lib/i18n'; + export type NavHeaderProps = { leftShown?: boolean; title?: string; @@ -59,7 +60,12 @@ export const NavHeader = ({ {leftShown && ( router.back()}> - + )}