lv il y a 1 mois
Parent
commit
19bb6ae1ab

+ 13 - 1
.vscode/settings.json

@@ -3,5 +3,17 @@
     "source.fixAll": "explicit",
     "source.organizeImports": "explicit",
     "source.sortMembers": "explicit"
-  }
+  },
+  "editor.quickSuggestions": {
+    "other": "on",
+    "comments": "off",
+    "strings": "on" 
+  },
+
+  // 2. 确保在输入特定字符(如引号、等号)时立即触发提示
+  "editor.suggestOnTriggerCharacters": true,
+
+  // 3. 如果你在写属性名后进入了 Snippet 模式(光标在引号内),
+  // 下面这一项设置为 false 可以防止 Snippet 模式阻塞建议列表
+  "editor.suggest.snippetsPreventQuickSuggestions": false
 }

+ 6 - 6
ios/LoanAssistant.xcodeproj/project.pbxproj

@@ -299,13 +299,13 @@
 			);
 			inputPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-LoanAssistant/Pods-LoanAssistant-resources.sh",
+				"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates/EXUpdates.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
-				"${PODS_CONFIGURATION_BUILD_DIR}/RNFSTurbo/RNFSTurbo_PrivacyInfo.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/ReachabilitySwift.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
 				"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
@@ -313,13 +313,13 @@
 			);
 			name = "[CP] Copy Pods Resources";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXUpdates.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
-				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNFSTurbo_PrivacyInfo.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReachabilitySwift.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
 				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
@@ -372,11 +372,11 @@
 				);
 				OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
 				PRODUCT_BUNDLE_IDENTIFIER = com.cdloan.assistant;
-				PRODUCT_NAME = "LoanAssistant";
+				PRODUCT_NAME = LoanAssistant;
 				SWIFT_OBJC_BRIDGING_HEADER = "LoanAssistant/LoanAssistant-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1";
+				TARGETED_DEVICE_FAMILY = 1;
 				VERSIONING_SYSTEM = "apple-generic";
 			};
 			name = Debug;
@@ -403,10 +403,10 @@
 				);
 				OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
 				PRODUCT_BUNDLE_IDENTIFIER = com.cdloan.assistant;
-				PRODUCT_NAME = "LoanAssistant";
+				PRODUCT_NAME = LoanAssistant;
 				SWIFT_OBJC_BRIDGING_HEADER = "LoanAssistant/LoanAssistant-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1";
+				TARGETED_DEVICE_FAMILY = 1;
 				VERSIONING_SYSTEM = "apple-generic";
 			};
 			name = Release;

+ 8 - 8
ios/LoanAssistant/PrivacyInfo.xcprivacy

@@ -6,28 +6,28 @@
 	<array>
 		<dict>
 			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
+			<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
 			<key>NSPrivacyAccessedAPITypeReasons</key>
 			<array>
-				<string>CA92.1</string>
+				<string>C617.1</string>
+				<string>0A2A.1</string>
+				<string>3B52.1</string>
 			</array>
 		</dict>
 		<dict>
 			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
+			<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
 			<key>NSPrivacyAccessedAPITypeReasons</key>
 			<array>
-				<string>35F9.1</string>
+				<string>CA92.1</string>
 			</array>
 		</dict>
 		<dict>
 			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
+			<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
 			<key>NSPrivacyAccessedAPITypeReasons</key>
 			<array>
-				<string>0A2A.1</string>
-				<string>3B52.1</string>
-				<string>C617.1</string>
+				<string>35F9.1</string>
 			</array>
 		</dict>
 		<dict>

+ 14 - 28
ios/Podfile.lock

@@ -1,6 +1,8 @@
 PODS:
   - EASClient (55.0.5):
     - ExpoModulesCore
+  - EXApplication (55.0.14):
+    - ExpoModulesCore
   - EXConstants (55.0.12):
     - ExpoModulesCore
   - EXJSONUtils (55.0.2)
@@ -33,11 +35,13 @@ PODS:
     - Yoga
   - ExpoAsset (55.0.13):
     - ExpoModulesCore
+  - ExpoBlur (55.0.14):
+    - ExpoModulesCore
   - ExpoDevice (55.0.13):
     - ExpoModulesCore
   - ExpoDomWebView (55.0.5):
     - ExpoModulesCore
-  - ExpoFileSystem (55.0.15):
+  - ExpoFileSystem (55.0.16):
     - ExpoModulesCore
   - ExpoFont (55.0.6):
     - ExpoModulesCore
@@ -2067,28 +2071,6 @@ PODS:
     - React-utils (= 0.83.4)
     - ReactNativeDependencies
   - ReactNativeDependencies (0.83.4)
-  - RNFSTurbo (0.5.1):
-    - hermes-engine
-    - RCTRequired
-    - RCTTypeSafety
-    - React-Core
-    - React-Core-prebuilt
-    - React-debug
-    - React-Fabric
-    - React-featureflags
-    - React-graphics
-    - React-ImageManager
-    - React-jsi
-    - React-NativeModulesApple
-    - React-RCTFabric
-    - React-renderercss
-    - React-rendererdebug
-    - React-utils
-    - ReactCodegen
-    - ReactCommon/turbomodule/bridging
-    - ReactCommon/turbomodule/core
-    - ReactNativeDependencies
-    - Yoga
   - RNGestureHandler (2.30.1):
     - hermes-engine
     - RCTRequired
@@ -2318,11 +2300,13 @@ PODS:
 
 DEPENDENCIES:
   - EASClient (from `../node_modules/expo-eas-client/ios`)
+  - EXApplication (from `../node_modules/expo-application/ios`)
   - EXConstants (from `../node_modules/expo-constants/ios`)
   - EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
   - EXManifests (from `../node_modules/expo-manifests/ios`)
   - Expo (from `../node_modules/expo`)
   - ExpoAsset (from `../node_modules/expo-asset/ios`)
+  - ExpoBlur (from `../node_modules/expo-blur/ios`)
   - ExpoDevice (from `../node_modules/expo-device/ios`)
   - "ExpoDomWebView (from `../node_modules/@expo/dom-webview/ios`)"
   - ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
@@ -2419,7 +2403,6 @@ DEPENDENCIES:
   - ReactCodegen (from `build/generated/ios/ReactCodegen`)
   - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
   - ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
-  - RNFSTurbo (from `../node_modules/react-native-fs-turbo`)
   - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
   - RNReanimated (from `../node_modules/react-native-reanimated`)
   - RNScreens (from `../node_modules/react-native-screens`)
@@ -2441,6 +2424,8 @@ SPEC REPOS:
 EXTERNAL SOURCES:
   EASClient:
     :path: "../node_modules/expo-eas-client/ios"
+  EXApplication:
+    :path: "../node_modules/expo-application/ios"
   EXConstants:
     :path: "../node_modules/expo-constants/ios"
   EXJSONUtils:
@@ -2451,6 +2436,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/expo"
   ExpoAsset:
     :path: "../node_modules/expo-asset/ios"
+  ExpoBlur:
+    :path: "../node_modules/expo-blur/ios"
   ExpoDevice:
     :path: "../node_modules/expo-device/ios"
   ExpoDomWebView:
@@ -2642,8 +2629,6 @@ EXTERNAL SOURCES:
     :path: "../node_modules/react-native/ReactCommon"
   ReactNativeDependencies:
     :podspec: "../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
-  RNFSTurbo:
-    :path: "../node_modules/react-native-fs-turbo"
   RNGestureHandler:
     :path: "../node_modules/react-native-gesture-handler"
   RNReanimated:
@@ -2657,14 +2642,16 @@ EXTERNAL SOURCES:
 
 SPEC CHECKSUMS:
   EASClient: 8077eb9af46cc7ad3ad216cec12d2bf5763cca13
+  EXApplication: ab5a9ca485adce8be81309a5172d1565e9d7467f
   EXConstants: 97e4a5b18e38331acce952f0e4a6817b0418408f
   EXJSONUtils: 04bc3807d351331a5fe154ce1da596ec15d99169
   EXManifests: a4e214e6a66372e662ef38adf2afca773bbd0c18
   Expo: 04f5391a7affe866de03b928cf40d683ec4a3463
   ExpoAsset: 3636e70a874487efd0a677f6c064dbc9fc8f174b
+  ExpoBlur: 7a86e84e7728108fa6908d7103fa527705a3dbbf
   ExpoDevice: 221ea185adcd21845c5911d370b03af84a493413
   ExpoDomWebView: 2b2fbd9a07de8790569257cbf9dfdaa31cf95c70
-  ExpoFileSystem: d40374bc7b6e990e2640e5dc3350fc83b1d74a40
+  ExpoFileSystem: 310d367cccbd30b9bda13c5865fe3d8d581dcf2a
   ExpoFont: cdd7a1d574a376fa003c713eff49e0a4df8672c7
   ExpoGlassEffect: 72bcb9dc634262c59897ff7c53c16e2ff03990d0
   ExpoImage: ef931bba1fd3e907c2262216d17eb21095c9ac2b
@@ -2762,7 +2749,6 @@ SPEC CHECKSUMS:
   ReactCodegen: 43f0948182edee9407c7b977fb059455dfeb9361
   ReactCommon: c6e81cc1ae185fa84863f3ea1d58caac4be741d7
   ReactNativeDependencies: e3081feec6a8266d996ca8ce3d5707360258baf8
-  RNFSTurbo: 8d1d8640c0c78c11f65a1af028ac11b66642efcf
   RNGestureHandler: 0ea8153746a92b3744d4eaadade647debedf646e
   RNReanimated: 86e5991396f1aa514db90d6c79d4c3e37a37bb10
   RNScreens: 02e62f995ceb94ea465864b3bf4d4767b87f0362

+ 1 - 0
package.json

@@ -25,6 +25,7 @@
     "axios": "^1.14.0",
     "expo": "~55.0.12",
     "expo-application": "~55.0.14",
+    "expo-blur": "~55.0.14",
     "expo-build-properties": "~55.0.13",
     "expo-constants": "~55.0.12",
     "expo-device": "~55.0.13",

+ 16 - 0
pnpm-lock.yaml

@@ -37,6 +37,9 @@ importers:
       expo-application:
         specifier: ~55.0.14
         version: 55.0.14(expo@55.0.12)
+      expo-blur:
+        specifier: ~55.0.14
+        version: 55.0.14(expo@55.0.12)(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)
       expo-build-properties:
         specifier: ~55.0.13
         version: 55.0.13(expo@55.0.12)
@@ -2660,6 +2663,13 @@ packages:
       react: '*'
       react-native: '*'
 
+  expo-blur@55.0.14:
+    resolution: {integrity: sha512-NKyCKFWTNpX4CZSsiE1sgkqk/yvR1K0UTukuIbxVKoobB+yALLg1CFav0NqfdQqjhtoj5oEzP0Brlq92Z08Zfg==}
+    peerDependencies:
+      expo: '*'
+      react: '*'
+      react-native: '*'
+
   expo-build-properties@55.0.13:
     resolution: {integrity: sha512-UYZhUKyh7YQhbJdkBvo68WUQ7fOtZeSV7F8kfYkjEiN/ADRHG0WfEIiddvGfi9cH/5iwpptv/+Lu5cx6uvfegA==}
     peerDependencies:
@@ -8455,6 +8465,12 @@ snapshots:
       - supports-color
       - typescript
 
+  expo-blur@55.0.14(expo@55.0.12)(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0):
+    dependencies:
+      expo: 55.0.12(@babel/core@7.29.0)(@expo/dom-webview@55.0.5)(@expo/metro-runtime@55.0.9)(expo-router@55.0.11)(react-dom@19.2.0(react@19.2.0))(react-native-webview@13.16.0(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)(typescript@5.9.3)
+      react: 19.2.0
+      react-native: 0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0)
+
   expo-build-properties@55.0.13(expo@55.0.12):
     dependencies:
       '@expo/schema-utils': 55.0.3

+ 1 - 1
src/app/(tabs)/customer.tsx

@@ -97,7 +97,7 @@ function getPrimaryAction(status: Customer['status']) {
   }
 }
 
-export default function CustomerScreen() {
+export default function CustomerScreens() {
   const [search, setSearch] = useState('');
   const [activeFilter, setActiveFilter] = useState<CustomerStatus>('全部');
 

+ 49 - 36
src/app/(tabs)/index.tsx

@@ -1,6 +1,12 @@
 import { SectionHeader } from '@/components/ui/section-header';
 import { StatusBadge } from '@/components/ui/status-badge';
+import { Colors } from '@/constants/theme';
+import api from '@/utils/api';
+import { useSWC } from '@/utils/cache';
+import { Icon } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
+import { Link } from 'expo-router';
+
 import { Pressable, ScrollView, Text, View } from 'react-native';
 import { SafeAreaView } from 'react-native-safe-area-context';
 type QuickAction = {
@@ -92,7 +98,19 @@ function getGreeting() {
 }
 
 export default function HomeScreen() {
-  
+  const { data: summary, loading: summaryLoding, error } = useSWC<{
+    pendding: number;
+    matched: number;
+    completed: number;
+  }>('home/summary', async () => {
+    return api.get("share/summary");
+  }, {
+    cacheTimeout: 300,
+    cacheOnly: false
+  }
+  );
+
+
   return (
     <SafeAreaView className="flex-1 bg-surface" edges={['top']}>
       <View className="h-14 flex-row items-center justify-between border-b border-outline-variant/20 bg-surface-container-lowest px-5">
@@ -124,23 +142,12 @@ export default function HomeScreen() {
         </View>
 
         <View className="mb-8 gap-3">
-          <View className="rounded-2xl bg-primary-container px-5 py-5">
-            <View className="mb-5 flex-row items-start justify-between">
-              <View className="h-11 w-11 items-center justify-center rounded-2xl bg-white/20">
-                <Ionicons name="briefcase-outline" size={22} color="#ffffff" />
-              </View>
-              <View className="rounded-full bg-white/20 px-3 py-1">
-                <Text className="text-sm font-bold text-on-primary">+12%</Text>
-              </View>
-            </View>
-            <Text className="mb-2 text-base text-on-primary/80">待处理申请</Text>
-            <Text className="text-5xl font-extrabold text-on-primary">24</Text>
-          </View>
+
 
           <View className="flex-row gap-3">
             <View className="flex-1 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
-              <Text className="mb-2 text-base text-on-surface-variant">进行中</Text>
-              <Text className="text-4xl font-bold text-on-surface">156</Text>
+              <Text className="mb-2 text-base text-on-surface-variant">已分析</Text>
+              <Text className="text-4xl font-bold text-on-surface">{summary ? summary.pendding : '...'}</Text>
               <View className="mt-4 h-1.5 rounded-full bg-surface-container">
                 <View
                   className="h-full rounded-full bg-secondary"
@@ -149,11 +156,21 @@ export default function HomeScreen() {
               </View>
             </View>
             <View className="flex-1 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
-              <Text className="mb-2 text-base text-on-surface-variant">成功撮合</Text>
-              <Text className="text-4xl font-bold text-on-surface">1,280</Text>
+              <Text className="mb-2 text-base text-on-surface-variant">待匹配</Text>
+              <Text className="text-4xl font-bold text-on-surface">{summary ? summary.matched : '...'}</Text>
+              <View className="mt-4 h-1.5 rounded-full bg-surface-container">
+                <View
+                  className="h-full rounded-full bg-tertiary-fixed-dim"
+                  style={{ width: '88%' }}
+                />
+              </View>
+            </View>
+            <View className="flex-1 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
+              <Text className="mb-2 text-base text-on-surface-variant">已匹配</Text>
+              <Text className="text-4xl font-bold text-on-surface">{summary ? summary.completed : '...'}</Text>
               <View className="mt-4 h-1.5 rounded-full bg-surface-container">
                 <View
-                  className="h-full rounded-full bg-tertiary-container"
+                  className="h-full rounded-full bg-blue-600"
                   style={{ width: '88%' }}
                 />
               </View>
@@ -162,25 +179,21 @@ export default function HomeScreen() {
         </View>
 
         <View className="mb-8">
-          <SectionHeader title="快捷操作" />
-          <View className="flex-row items-start justify-between">
-            {QUICK_ACTIONS.map((action) => (
-              <Pressable
-                key={action.label}
-                className="items-center"
-                style={({ pressed }) => ({
-                  opacity: pressed ? 0.84 : 1,
-                  transform: [{ scale: pressed ? 0.96 : 1 }],
-                })}
-              >
-                <View className="mb-2.5 h-14 w-14 items-center justify-center rounded-2xl bg-surface-container-high">
-                  <Ionicons name={action.icon} size={26} color="#004ac6" />
-                </View>
-                <Text className="text-sm font-medium text-on-surface-variant">
-                  {action.label}
-                </Text>
+          <SectionHeader title="快捷入口" />
+          <View className="flex-row items-start justify-around">
+              <Link href="/customer/add" asChild >
+                <Pressable className='flex-1 h-12 rounded-lg flex-row justify-center items-center bg-primary'>
+                  <Icon name='user-add' color='#fff' />
+                  <Text className='ml-2 text-lg font-medium text-white'>添加客户</Text>
               </Pressable>
-            ))}
+            </Link>
+            <View className='w-5' />
+            <Link href="/customer/add" asChild>
+                <Pressable className='flex-1 h-12 rounded-lg flex-row justify-center items-center border-2 border-primary/50'>
+                  <Icon name='user-add' color={Colors.primary.DEFAULT} />
+                  <Text className='ml-2 text-lg font-medium text-primary'>添加客户</Text>
+              </Pressable>
+            </Link>
           </View>
         </View>
 

+ 5 - 0
src/app/+not-found.tsx

@@ -0,0 +1,5 @@
+import { Text } from "react-native";
+
+export default function NotFound() {
+  return <Text>not found</Text>
+}

+ 23 - 17
src/app/_layout.tsx

@@ -12,13 +12,15 @@ import {
   ThemeProvider,
 } from '@react-navigation/native';
 import * as application from 'expo-application';
+import { BlurView } from 'expo-blur';
 import { useFonts } from 'expo-font';
 import { Image } from 'expo-image';
 import { Stack, useRouter } from 'expo-router';
 import * as SplashScreen from 'expo-splash-screen';
 import * as updates from 'expo-updates';
 import { useEffect, useState } from 'react';
-import { Linking, Platform } from 'react-native';
+import { Linking, Platform, View } from 'react-native';
+
 
 SplashScreen.preventAutoHideAsync();
 
@@ -52,11 +54,10 @@ export default function RootLayout() {
     async function checkApp() {
       try {
         const lastTime = parseInt(getGlobalStorage().getString('last_update_app') || '0');
-        if (now - lastTime < 900000) {
+        if (now - lastTime < 15*60000) {
+          SplashScreen.hide();
           return true;
         }
-SplashScreen.hide();
-      // setIniting(false);
         const {
           version,
           package: pkg,
@@ -65,13 +66,15 @@ SplashScreen.hide();
         } = await api.post<{ version: string, package: string, type: 'apk' | 'url', force: boolean }>('common/check_version', {
           platform: Platform.OS,
           version: application.nativeApplicationVersion,
-        }, {timeout: 3000});
+        }, { timeout: 5000 });
         getGlobalStorage().set('last_update_app', now);
+
+        SplashScreen.hide();
         if (version === application.nativeApplicationVersion) {
           return true;
         }
         const va = version.split('.');
-        let vb = (application.nativeApplicationVersion||'').split('.');
+        let vb = (application.nativeApplicationVersion || '').split('.');
         let update = false;
         for (let i = 0; i < va.length; i++) {
           if (vb.length <= i || parseInt(va[i]) > parseInt(vb[i])) {
@@ -119,6 +122,8 @@ SplashScreen.hide();
         } while (!ok);
         return true;
       } catch (e) {
+
+        SplashScreen.hide();
         console.warn(e);
         return true;
       }
@@ -126,8 +131,7 @@ SplashScreen.hide();
 
     (async () => {
       if (!await checkApp()) {
-        SplashScreen.hide();
-      setIniting(false);
+        setIniting(false);
         return;
       }
 
@@ -176,18 +180,20 @@ SplashScreen.hide();
           <AuthProvider>
             <AnimatedSplashOverlay />
             <Stack screenOptions={{
-                headerShown: false,
-                headerTransparent: true,
-                headerLeft: ({canGoBack}) => canGoBack && <Icon name="arrow-left" onPress={router.back} />,
-                animation: 'ios_from_right'
-                }}>
-              <Stack.Screen name="(tabs)" />
-              <Stack.Screen name="sign-in" options={{animation: 'fade_from_bottom'}} />
-              <Stack.Screen name="web" options={{ headerShown: true }} />
+              headerShown: true,
+              headerTransparent: true,
+              headerBackground: ()=><BlurView style={{flex: 1}} />,
+              headerLeft: ({ canGoBack }) => canGoBack && <Icon name="arrow-left" size={24} onPress={router.back} />,
+              animation: 'ios_from_right'
+            }}>
+              <Stack.Screen name="(tabs)" options={{headerShown: false}} />
+              <Stack.Screen name="sign-in" options={{ animation: 'fade_from_bottom' }} />
             </Stack>
           </AuthProvider>}
       </Provider>
-      {initing && <Image contentFit='contain' source={require('@/assets/images/uploading.jpg')} />}
+        {initing && <View className='absolute left-0 top-0 right-0 bottom-0 bg-[#f6f6f6] z-50'>
+        <Image contentFit='contain' style={{ flex: 1 }} source={require('@/assets/images/uploading.jpg')} />
+      </View>}
     </ThemeProvider>
   );
 }

+ 23 - 0
src/app/customer/add.tsx

@@ -0,0 +1,23 @@
+import { KeyboardAvoidingView, Platform, ScrollView, View } from "react-native";
+
+export default function AddCustomerScreen() {
+    return <View className="flex-1 bg-red-500">
+      <KeyboardAvoidingView
+        className="flex-1"
+        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
+      >
+        <ScrollView
+          className="flex-1"
+          contentContainerClassName="px-8"
+          
+          keyboardShouldPersistTaps="handled"
+          showsVerticalScrollIndicator={false}
+        >
+          <View className="absolute -top-24 -right-24 h-96 w-96 rounded-full bg-primary-container/10" />
+          <View className="absolute top-32 -left-20 h-64 w-64 rounded-full bg-secondary-container/20" />
+          <View className="absolute -bottom-16 right-0 h-48 w-48 rounded-full bg-primary-fixed/50" />
+
+          </ScrollView>
+          </KeyboardAvoidingView>
+    </View>
+}

+ 1 - 1
src/app/sign-in.tsx

@@ -148,7 +148,7 @@ export default function SignInScreen() {
       if (redirectTo) {
         router.replace(redirectTo as never);
       } else {
-        router.back();
+        router.canGoBack() ? router.back() : router.replace('/');
       }
     } catch (error) {
       console.error('登录失败:', error);

+ 3 - 0
src/constants/theme.ts

@@ -3,11 +3,14 @@
  * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
  */
 
+import theme from '@/../theme';
 import '@/global.css';
 
 import { Platform } from 'react-native';
 import { antdTheme } from './antd-theme';
 export const Colors = {
+
+    ...theme.colors,
     text: antdTheme.color_text_base,
     background: antdTheme.fill_base,
     backgroundElement:  antdTheme.fill_body,

+ 6 - 4
src/utils/cache.ts

@@ -1,4 +1,5 @@
 import { useEffect, useRef, useState } from "react";
+import { Platform } from "react-native";
 import { getApiCache, getGlobalStorage } from "./storage";
 
 
@@ -84,11 +85,11 @@ export function useSWC<T>(key: string, action: () => Promise<T>, options?: UseSW
     return { data, loading, error };
 }
 
-
-
 export const MAX_CACHE_TIME = 99999999999999;
 
-let lastClearTime = parseInt(getGlobalStorage().getString("last_clear_time") || "0");
+if (Platform.OS !== 'web') {
+
+let lastClearTime = parseInt(typeof window == undefined ? "0" : getGlobalStorage().getString("last_clear_time") || "0");
 const clearTimeout = 86400 * 3 * 1000;
 // 开启一直 30 分钏的定时器,用于清理缓存
 setInterval(() => {
@@ -112,4 +113,5 @@ setInterval(() => {
 
         globalStorage.set("last_clear_time", now+"");
     }
-}, 60 * 15 * 1000);
+}, 60 * 15 * 1000);
+}

+ 2 - 100
tailwind.config.js

@@ -1,108 +1,10 @@
 /** @type {import('tailwindcss').Config} */
+const theme = require("./theme").default;
 module.exports = {
   content: ["./src/**/*.{js,jsx,ts,tsx}"],
   presets: [require("nativewind/preset")],
   theme: {
-    extend: {
-      colors: {
-        primary: {
-          DEFAULT: "#2563eb",
-          container: "#2563eb",
-          fixed: "#dbeafe",
-          "fixed-dim": "#bfdbfe",
-        },
-        "on-primary": {
-          DEFAULT: "#ffffff",
-          container: "#ffffff",
-          fixed: "#1e3a8a",
-          "fixed-variant": "#1d4ed8",
-        },
-        secondary: {
-          DEFAULT: "#475569",
-          container: "#eff6ff",
-          fixed: "#f8fafc",
-          "fixed-dim": "#e2e8f0",
-        },
-        "on-secondary": {
-          DEFAULT: "#ffffff",
-          container: "#2158e8",
-          fixed: "#334155",
-          "fixed-variant": "#64748b",
-        },
-        tertiary: {
-          DEFAULT: "#f59e0b",
-          container: "#fef3c7",
-          fixed: "#fef3c7",
-          "fixed-dim": "#fde68a",
-        },
-        "on-tertiary": {
-          DEFAULT: "#ffffff",
-          container: "#92400e",
-          fixed: "#92400e",
-          "fixed-variant": "#b45309",
-        },
-        error: {
-          DEFAULT: "#dc2626",
-          container: "#fee2e2",
-        },
-        "on-error": {
-          DEFAULT: "#ffffff",
-          container: "#991b1b",
-        },
-        success: {
-          DEFAULT: "#16a34a",
-          container: "#dcfce7",
-        },
-        "on-success": {
-          DEFAULT: "#ffffff",
-          container: "#166534",
-        },
-        surface: {
-          DEFAULT: "#f8fafc",
-          dim: "#eef2f7",
-          bright: "#ffffff",
-          variant: "#f1f5f9",
-          tint: "#2158e8",
-          container: {
-            DEFAULT: "#f1f5f9",
-            lowest: "#ffffff",
-            low: "#f8fafc",
-            high: "#eef2f7",
-            highest: "#e2e8f0",
-          },
-        },
-        "on-surface": {
-          DEFAULT: "#0f172a",
-          variant: "#64748b",
-        },
-        outline: {
-          DEFAULT: "#94a3b8",
-          variant: "#e2e8f0",
-        },
-        line: "#e2e8f0",
-        background: "#eef2ff",
-        "on-background": "#0f172a",
-        card: "#ffffff",
-        ok: "#16a34a",
-        warn: "#f59e0b",
-        danger: "#dc2626",
-        "inverse-surface": "#0f172a",
-        "inverse-on-surface": "#f8fafc",
-        "inverse-primary": "#bfdbfe",
-      },
-      borderRadius: {
-        DEFAULT: "0.5rem",
-        lg: "0.625rem",
-        xl: "0.75rem",
-        "2xl": "0.75rem",
-        full: "9999px",
-      },
-      fontFamily: {
-        headline: ["System", "PingFang SC", "sans-serif"],
-        body: ["System", "PingFang SC", "sans-serif"],
-        label: ["System", "PingFang SC", "sans-serif"],
-      },
-    },
+    extend: theme,
   },
   plugins: [],
 };

+ 100 - 0
theme.js

@@ -0,0 +1,100 @@
+export default {
+  colors: {
+    primary: {
+      DEFAULT: "#2563eb",
+      container: "#2563eb",
+      fixed: "#dbeafe",
+      "fixed-dim": "#bfdbfe",
+    },
+    "on-primary": {
+      DEFAULT: "#ffffff",
+      container: "#ffffff",
+      fixed: "#1e3a8a",
+      "fixed-variant": "#1d4ed8",
+    },
+    secondary: {
+      DEFAULT: "#475569",
+      container: "#eff6ff",
+      fixed: "#f8fafc",
+      "fixed-dim": "#e2e8f0",
+    },
+    "on-secondary": {
+      DEFAULT: "#ffffff",
+      container: "#2158e8",
+      fixed: "#334155",
+      "fixed-variant": "#64748b",
+    },
+    tertiary: {
+      DEFAULT: "#f59e0b",
+      container: "#fef3c7",
+      fixed: "#fef3c7",
+      "fixed-dim": "#fde68a",
+    },
+    "on-tertiary": {
+      DEFAULT: "#ffffff",
+      container: "#92400e",
+      fixed: "#92400e",
+      "fixed-variant": "#b45309",
+    },
+    error: {
+      DEFAULT: "#dc2626",
+      container: "#fee2e2",
+    },
+    "on-error": {
+      DEFAULT: "#ffffff",
+      container: "#991b1b",
+    },
+    success: {
+      DEFAULT: "#16a34a",
+      container: "#dcfce7",
+    },
+    "on-success": {
+      DEFAULT: "#ffffff",
+      container: "#166534",
+    },
+    surface: {
+      DEFAULT: "#f8fafc",
+      dim: "#eef2f7",
+      bright: "#ffffff",
+      variant: "#f1f5f9",
+      tint: "#2158e8",
+      container: {
+        DEFAULT: "#f1f5f9",
+        lowest: "#ffffff",
+        low: "#f8fafc",
+        high: "#eef2f7",
+        highest: "#e2e8f0",
+      },
+    },
+    "on-surface": {
+      DEFAULT: "#0f172a",
+      variant: "#64748b",
+    },
+    outline: {
+      DEFAULT: "#94a3b8",
+      variant: "#e2e8f0",
+    },
+    line: "#e2e8f0",
+    background: "#eef2ff",
+    "on-background": "#0f172a",
+    card: "#ffffff",
+    ok: "#16a34a",
+    warn: "#f59e0b",
+    danger: "#dc2626",
+    "inverse-surface": "#0f172a",
+    "inverse-on-surface": "#f8fafc",
+    "inverse-primary": "#bfdbfe",
+  },
+  borderRadius: {
+    DEFAULT: "0.5rem",
+    lg: "0.625rem",
+    xl: "0.75rem",
+    "2xl": "0.75rem",
+    full: "9999px",
+  },
+  fontFamily: {
+    headline: ["System", "PingFang SC", "sans-serif"],
+    body: ["System", "PingFang SC", "sans-serif"],
+    label: ["System", "PingFang SC", "sans-serif"],
+  },
+};