瀏覽代碼

ai format

yblunan@gmail.com 4 周之前
父節點
當前提交
cde7c75b40

+ 19 - 19
src/app/(tabs)/analytics.tsx

@@ -1,9 +1,3 @@
-import type { Customer as CustomerType } from '@/app/(tabs)/customer';
-import { SectionHeader } from '@/components/ui/section-header';
-import { Colors } from '@/constants/theme';
-import type { ListResponse } from '@/utils/api';
-import api from '@/utils/api';
-import { useSWC } from '@/utils/cache';
 import { ActivityIndicator, Modal } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import { BlurView } from 'expo-blur';
@@ -12,7 +6,13 @@ import React, { useCallback, useState } from 'react';
 import { Pressable, Text, View } from 'react-native';
 import Animated, { Extrapolation, interpolate, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { SectionHeader } from '@/components/ui/section-header';
+import { Colors } from '@/constants/theme';
+import api from '@/utils/api';
+import { useSWC } from '@/utils/cache';
 import { UploadComponent } from '../../components/upload';
+import type { Customer as CustomerType } from '@/app/(tabs)/customer';
+import type { ListResponse } from '@/utils/api';
 
 type AnalysisRecord = {
   id: string;
@@ -24,7 +24,7 @@ type AnalysisRecord = {
 };
 
 export default function AnalyticsScreen() {
-  const { data: list, loading, error, load, refresh } = useSWC<ListResponse<AnalysisRecord>>("credit_index_list", async () => {
+  const { data: list, loading, load } = useSWC<ListResponse<AnalysisRecord>>("credit_index_list", async () => {
     return api.post("credit/list", { size: 10 });
   }, {
     cacheOnly: true,
@@ -56,9 +56,9 @@ export default function AnalyticsScreen() {
     navigation.navigate('customer/select', {
       current: selectedCustomer?.id,
       onSelect: async (c: CustomerType| undefined) => {
-        if (c?.loan_status != 'idle' && c?.loan_status != 'unmatch') {
+        if (c?.loan_status !== 'idle' && c?.loan_status !== 'unmatch') {
           const res = await new Promise<boolean | void>((resolve)=>{
-            Modal.alert("注意", `用户${c!.name} ${c!.loan_status == 'pending' ? '正在等待分析征信': '已有分析报告'}, 是否要再提交一份?`, [{
+            Modal.alert("注意", `用户${c!.name} ${c!.loan_status === 'pending' ? '正在等待分析征信': '已有分析报告'}, 是否要再提交一份?`, [{
             text: '取消',
             style: {color: Colors.secondary.DEFAULT},
             onPress: ()=>resolve(false)
@@ -79,7 +79,7 @@ export default function AnalyticsScreen() {
   }, [selectedCustomer, setSelectedCustommer]);
 
   const onUploadComplete = useCallback((s?: 'cancel' | 'break') => {
-    if (s == 'break') {
+    if (s === 'break') {
       handleSelectCustomer();
     }
   }, [handleSelectCustomer]);
@@ -118,14 +118,14 @@ export default function AnalyticsScreen() {
           className="flex-row items-center rounded-2xl bg-surface-container-low px-4 py-3.5 active:opacity-90"
           onPress={handleSelectCustomer}
         >
-          <Ionicons name="person-outline" size={18} color="#737686" />
+          <Ionicons name="person-outline" size={18} color="#94a3b8" />
           <Text className="ml-3 flex-1 text-base font-medium text-on-surface">
             {selectedCustomer ? `${selectedCustomer.name}(${selectedCustomer.mobile})` : '无'}
           </Text>
           {selectedCustomer&&<Pressable className='mx-2' hitSlop={8} onPress={()=>setSelectedCustommer(undefined)}>
-            <Ionicons name="close-circle" size={20} color="#c3c6d7" />
+            <Ionicons name="close-circle" size={20} color="#94a3b8" />
           </Pressable>}
-          <Ionicons name="chevron-down" size={18} color="#c3c6d7" />
+          <Ionicons name="chevron-down" size={18} color="#94a3b8" />
         </Pressable>
       </View>
 
@@ -139,7 +139,7 @@ export default function AnalyticsScreen() {
         {list?.list?.map((record) => (
           <Pressable
             key={record.id}
-            className="flex-row items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3.5 active:opacity-93"
+            className="flex-row items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3.5 active:opacity-90 active:scale-[0.99]"
           >
             <View
               className={`mr-3 h-11 w-11 items-center justify-center rounded-full ${record.status === 'completed'
@@ -160,10 +160,10 @@ export default function AnalyticsScreen() {
                 size={20}
                 color={
                   record.status === 'completed'
-                    ? '#16a34a'
+                    ? Colors.success.DEFAULT
                     : record.status === 'pending'
-                      ? '#2563eb'
-                      : '#ba1a1a'
+                      ? Colors.tint
+                      : Colors.error.DEFAULT
                 }
               />
             </View>
@@ -175,7 +175,7 @@ export default function AnalyticsScreen() {
                 </Text>
                 <Text className="text-xs text-on-surface-variant">{record.createtime}</Text>
               </View>
-              {(record.status === 'pending' || record.status == 'failed') && (
+              {(record.status === 'pending' || record.status === 'failed') && (
                 <View>
                   <View className="mb-2 flex-row items-center justify-between">
                     <Text className="text-sm text-on-surface-variant">...</Text>
@@ -207,7 +207,7 @@ export default function AnalyticsScreen() {
 
             </View>
 
-            <Ionicons name="chevron-forward" size={18} color="#c3c6d7" />
+            <Ionicons name="chevron-forward" size={18} color="#94a3b8" />
           </Pressable>
         ))}
       </View>

+ 13 - 22
src/app/(tabs)/customer.tsx

@@ -1,8 +1,3 @@
-import { pressableStyle } from 'nativewind';
-import { StatusBadge } from '@/components/ui/status-badge';
-import type { ListResponse } from '@/utils/api';
-import api from '@/utils/api';
-import { getApiCache } from '@/utils/storage';
 import { ActivityIndicator, Toast } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import clsx from 'clsx';
@@ -12,6 +7,10 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
 import { Pressable, Text, TextInput, View } from 'react-native';
 import Animated, { Extrapolation, interpolate, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { StatusBadge } from '@/components/ui/status-badge';
+import api from '@/utils/api';
+import { getApiCache } from '@/utils/storage';
+import type { ListResponse } from '@/utils/api';
 
 export type CustomerLoanStatus = 'idle' | 'matched' | 'unmatch' | 'pending' | 'completed' | 'all' | undefined;
 export const CustomerLoanStatusText: Record<NonNullable<CustomerLoanStatus>, string> = {
@@ -40,11 +39,7 @@ const CACHE_KEY = 'customer_first';
 function CustomerCard({ item }: { item: Customer }) {
   return (
     <Pressable
-      className="rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-4"
-      style={pressableStyle(({ pressed }) => ({
-        opacity: pressed ? 0.93 : 1,
-        transform: [{ scale: pressed ? 0.995 : 1 }],
-      }))}
+      className="rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-4 active:opacity-90 active:scale-[0.99]"
     >
       <View className="mb-3 flex-row items-start justify-between gap-3">
         <View className="flex-1 flex-row items-center gap-3">
@@ -63,12 +58,12 @@ function CustomerCard({ item }: { item: Customer }) {
 
       <View className="mb-3 flex-row flex-wrap items-center gap-3">
         <View className="flex-row items-center gap-1">
-          <Ionicons name="document-text-outline" size={14} color="#737686" />
+          <Ionicons name="document-text-outline" size={16} color="#94a3b8" />
           <Text className="text-xs text-on-surface-variant">{item.loan_status}</Text>
         </View>
         {item.score ? (
           <View className="flex-row items-center gap-1">
-            <Ionicons name="analytics-outline" size={14} color="#737686" />
+            <Ionicons name="analytics-outline" size={16} color="#94a3b8" />
             <Text className="text-xs text-on-surface-variant">评分 {item.score}</Text>
           </View>
         ) : null}
@@ -208,17 +203,17 @@ export default function CustomerScreens() {
       </Text>
 
       <View className="mb-3 flex-row items-center rounded-2xl bg-surface-container-low px-4 py-3">
-        <Ionicons name="search-outline" size={20} color="#737686" />
+        <Ionicons name="search-outline" size={20} color="#94a3b8" />
         <TextInput
           value={searchKey}
           onChangeText={handleSearch}
           placeholder="搜索客户姓名 / 手机号"
-          placeholderTextColor="#9ca3af"
+          placeholderTextColor="#94a3b8"
           className="ml-3 flex-1 p-0 text-base text-on-surface"
         />
         {searchKey.length > 0 ? (
           <Pressable hitSlop={8} onPress={handleReset}>
-            <Ionicons name="close-circle" size={20} color="#c3c6d7" />
+            <Ionicons name="close-circle" size={20} color="#94a3b8" />
           </Pressable>
         ) : null}
       </View>
@@ -250,7 +245,7 @@ export default function CustomerScreens() {
 
   const ListEmpty = !loading ? (
     <View className="items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-6 py-14">
-      <Ionicons name="people-outline" size={44} color="#c3c6d7" />
+      <Ionicons name="people-outline" size={44} color="#94a3b8" />
       <Text className="mt-4 text-base text-on-surface-variant">暂无匹配客户</Text>
     </View>
   ) : null;
@@ -307,13 +302,9 @@ export default function CustomerScreens() {
       }} />
       <Link asChild href="/customer/add" style={{bottom: insets.bottom + 44 + 12}} className="absolute pb-2 right-5">
         <Pressable
-          className="h-14 w-14 items-center justify-center rounded-full bg-primary-container"
-          style={pressableStyle(({ pressed }) => ({
-            opacity: pressed ? 0.88 : 1,
-            transform: [{ scale: pressed ? 0.94 : 1 }],
-          }))}
+          className="h-14 w-14 items-center justify-center rounded-full bg-primary-container active:opacity-80 active:scale-[0.94]"
         >
-          <Ionicons name="person-add" size={22} color="#ffffff" />
+          <Ionicons name="person-add" size={20} color="#ffffff" />
         </Pressable>
       </Link>
     </>

+ 2 - 7
src/app/(tabs)/index.tsx

@@ -4,7 +4,6 @@ import { useCallback, useState } from 'react';
 import { Pressable, ScrollView, Text, View } from 'react-native';
 import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
 import { SectionHeader } from '@/components/ui/section-header';
-import { pressableStyle } from 'nativewind';
 import { StatusBadge } from '@/components/ui/status-badge';
 import UIButton from '@/components/ui/ui-button';
 import api from '@/utils/api';
@@ -123,7 +122,7 @@ export default function HomeScreen() {
           </Text>
         </View>
         <Pressable hitSlop={8}>
-          <Ionicons name="notifications-outline" size={24} color="#94a3b8" />
+          <Ionicons name="notifications-outline" size={20} color="#94a3b8" />
         </Pressable>
       </View>
 
@@ -193,11 +192,7 @@ export default function HomeScreen() {
             {RECENT_ACTIVITIES.map((item) => (
               <Pressable
                 key={item.id}
-                className="flex-row items-center gap-3 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3.5"
-                style={pressableStyle(({ pressed }) => ({
-                  opacity: pressed ? 0.92 : 1,
-                  transform: [{ scale: pressed ? 0.99 : 1 }],
-                }))}
+                className="flex-row items-center gap-3 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3.5 active:opacity-90 active:scale-[0.99]"
               >
                 <View
                   className="h-12 w-12 items-center justify-center rounded-full"

+ 7 - 12
src/app/(tabs)/profile.tsx

@@ -1,5 +1,4 @@
 import { ActivityIndicator, Modal, Toast } from '@ant-design/react-native';
-import { pressableStyle } from 'nativewind';
 import { Ionicons } from '@expo/vector-icons';
 import { Image } from 'expo-image';
 import { Pressable, ScrollView, Text, View } from 'react-native';
@@ -31,7 +30,7 @@ export default function ProfileScreen() {
     ]);
   };
 
-  const {data: userInfo, loading, error}: any = useSWC("me", async ()=> {
+  const {data: userInfo, loading}: any = useSWC("me", async ()=> {
     return await api.post('user/profile')
   }, {
     cacheOnly: true,
@@ -52,7 +51,7 @@ export default function ProfileScreen() {
           </Text>
         </View>
         <Pressable hitSlop={8}>
-          <Ionicons name="notifications-outline" size={24} color="#94a3b8" />
+          <Ionicons name="notifications-outline" size={20} color="#94a3b8" />
         </Pressable>
       </View>
 
@@ -81,15 +80,15 @@ export default function ProfileScreen() {
         </View>
 
         <View className="mb-8 flex-row gap-3">
-          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-4">
+          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
             <Text className="text-3xl font-extrabold text-primary">128</Text>
             <Text className="mt-2 text-sm font-bold text-outline">已完成</Text>
           </View>
-          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-4">
+          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
             <Text className="text-3xl font-extrabold text-primary">94%</Text>
             <Text className="mt-2 text-sm font-bold text-outline">成功率</Text>
           </View>
-          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-4">
+          <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
             <Text className="text-3xl font-extrabold text-primary">¥42k</Text>
             <Text className="mt-2 text-sm font-bold text-outline">本月收入</Text>
           </View>
@@ -128,13 +127,9 @@ export default function ProfileScreen() {
 
         <Pressable
           onPress={handleLogout}
-          className="mt-2 flex-row items-center justify-center gap-2 rounded-2xl bg-surface-container-low py-3.5"
-          style={pressableStyle(({ pressed }) => ({
-            opacity: pressed ? 0.86 : 1,
-            transform: [{ scale: pressed ? 0.985 : 1 }],
-          }))}
+          className="mt-2 flex-row items-center justify-center gap-2 rounded-2xl bg-surface-container-low py-3.5 active:opacity-88"
         >
-          <Ionicons name="log-out-outline" size={20} color="#ba1a1a" />
+          <Ionicons name="log-out-outline" size={18} color={Colors.error.DEFAULT} />
           <Text className="text-base font-bold text-error">退出登录</Text>
         </Pressable>
       </ScrollView>

+ 7 - 6
src/app/(tabs)/reports.tsx

@@ -1,4 +1,3 @@
-import { StatusBadge } from '@/components/ui/status-badge';
 import { Ionicons } from '@expo/vector-icons';
 import { BlurView } from 'expo-blur';
 import { Stack } from 'expo-router';
@@ -6,6 +5,8 @@ import React, { useState } from 'react';
 import { Pressable, Text, View } from 'react-native';
 import Animated, { Extrapolation, interpolate, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { StatusBadge } from '@/components/ui/status-badge';
+import { Colors } from '@/constants/theme';
 
 type ReportTab = '全部' | '征信报告' | '匹配结果';
 
@@ -143,19 +144,19 @@ export default function ReportsScreen() {
       </Text>
 
       <View className="mb-5 flex-row gap-2.5">
-        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-3.5">
+        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
           <Text className="text-2xl font-extrabold text-primary">{REPORTS.length}</Text>
           <Text className="mt-2 text-xs font-bold uppercase tracking-widest text-outline">
             总报告数
           </Text>
         </View>
-        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-3.5">
+        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
           <Text className="text-2xl font-extrabold text-primary">{completedCount}</Text>
           <Text className="mt-2 text-xs font-bold uppercase tracking-widest text-outline">
             已完成
           </Text>
         </View>
-        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-3 py-3.5">
+        <View className="flex-1 items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-5">
           <Text className="text-2xl font-extrabold text-primary">92%</Text>
           <Text className="mt-2 text-xs font-bold uppercase tracking-widest text-outline">
             最高匹配
@@ -190,7 +191,7 @@ export default function ReportsScreen() {
         {filteredReports.map((report) => (
           <Pressable
             key={report.id}
-            className="rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-4 active:opacity-93"
+            className="rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-4 active:opacity-90 active:scale-[0.99]"
           >
             <View className="mb-3 flex-row items-start justify-between gap-3">
               <View className="flex-1 flex-row items-center gap-3">
@@ -205,7 +206,7 @@ export default function ReportsScreen() {
                         : 'git-compare-outline'
                     }
                     size={20}
-                    color={report.type === '征信报告' ? '#2563eb' : '#16a34a'}
+                    color={report.type === '征信报告' ? Colors.tint : Colors.success.DEFAULT}
                   />
                 </View>
                 <View className="flex-1">

+ 8 - 8
src/app/_layout.tsx

@@ -1,12 +1,5 @@
-import { AnimatedSplashOverlay } from '@/components/animated-icon';
-import { antdTheme } from '@/constants/antd-theme';
-import { Colors } from '@/constants/theme';
 import '@/global.css';
-import api from '@/utils/api';
-import { AuthProvider } from '@/utils/auth';
-import { getGlobalStorage } from '@/utils/storage';
 import { Modal, Provider, Toast } from '@ant-design/react-native';
-import type { Theme } from '@react-navigation/native';
 import {
   DefaultTheme as ReactNavigationDefaultTheme,
   ThemeProvider,
@@ -19,6 +12,13 @@ import * as SplashScreen from 'expo-splash-screen';
 import * as updates from 'expo-updates';
 import { useEffect, useState } from 'react';
 import { Linking, Platform, View } from 'react-native';
+import { AnimatedSplashOverlay } from '@/components/animated-icon';
+import { antdTheme } from '@/constants/antd-theme';
+import { Colors } from '@/constants/theme';
+import api from '@/utils/api';
+import { AuthProvider } from '@/utils/auth';
+import { getGlobalStorage } from '@/utils/storage';
+import type { Theme } from '@react-navigation/native';
 
 
 SplashScreen.preventAutoHideAsync();
@@ -165,7 +165,7 @@ export default function RootLayout() {
             break;
           }
         }
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
+         
       
       setInitlizing(false);
 

+ 5 - 9
src/app/customer/add.tsx

@@ -1,4 +1,3 @@
-import { pressableStyle } from "nativewind";
 import { DatePicker, Input, Modal, Radio, Toast } from "@ant-design/react-native";
 import { Ionicons } from "@expo/vector-icons";
 import { usePreventRemove, useRoute } from "@react-navigation/native";
@@ -250,13 +249,10 @@ function PickerField({
       <Pressable
         disabled={disabled}
         onPress={onPress}
-        className={`flex-row items-center justify-between rounded-2xl border px-4 py-4 ${error
+        className={`flex-row items-center justify-between rounded-2xl border px-4 py-4 disabled:opacity-55 ${error
           ? "border-red-300 bg-red-50"
           : "border-outline-variant bg-surface-container-low"
-          }`}
-        style={pressableStyle(({ pressed }) => ({
-          opacity: disabled ? 0.55 : pressed ? 0.9 : 1,
-        }))}
+          } active:opacity-90`}
       >
         <Text
           className={`flex-1 text-base ${hasValue ? "text-on-surface" : "text-outline"}`}
@@ -267,7 +263,7 @@ function PickerField({
         <Ionicons
           name="chevron-down"
           size={18}
-          color={error ? "#ef4444" : Colors.color_text_paragraph}
+          color={error ? Colors.error.DEFAULT : Colors.color_text_paragraph}
         />
       </Pressable>
       <FieldMessage error={error} helper={helper} />
@@ -575,7 +571,7 @@ export default function AddCustomerScreen() {
               onChangeText={handleMobileChange}
               placeholder="请输入 11 位手机号"
               keyboardType="phone-pad"
-              placeholderTextColor="#9ca3af"
+              placeholderTextColor="#94a3b8"
               textContentType="telephoneNumber"
               underlineColorAndroid="transparent"
               maxLength={11}
@@ -599,7 +595,7 @@ export default function AddCustomerScreen() {
               placeholder="请输入身份证号"
               autoCapitalize="characters"
               autoCorrect={false}
-              placeholderTextColor="#9ca3af"
+              placeholderTextColor="#94a3b8"
               underlineColorAndroid="transparent"
               maxLength={18}
               style={[

+ 12 - 17
src/app/customer/select.tsx

@@ -1,9 +1,3 @@
-import { pressableStyle } from 'nativewind';
-import { StatusBadge } from '@/components/ui/status-badge';
-import { Colors } from '@/constants/theme';
-import type { ListResponse } from '@/utils/api';
-import api from '@/utils/api';
-import { getApiCache } from '@/utils/storage';
 import { ActivityIndicator, Toast } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import { useRoute } from '@react-navigation/native';
@@ -12,7 +6,12 @@ import { Stack, useNavigation } from 'expo-router';
 import { useCallback, useEffect, useRef, useState } from 'react';
 import { FlatList, Pressable, Text, TextInput, View } from 'react-native';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { type Customer, type CustomerLoanStatus } from '../(tabs)/customer';
+import { StatusBadge } from '@/components/ui/status-badge';
+import { Colors } from '@/constants/theme';
+import api from '@/utils/api';
+import { getApiCache } from '@/utils/storage';
+import type {Customer, CustomerLoanStatus} from '../(tabs)/customer';
+import type { ListResponse } from '@/utils/api';
 
 const PAGE_SIZE = 15;
 const CACHE_KEY = 'customer_first';
@@ -133,13 +132,9 @@ export default function CustomerSelectScreen() {
         ({ item }: { item: Customer }) => (
             <Pressable
                 onPress={() => handlePick(item)}
-                className="mb-2 flex-row items-center gap-3 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3"
-                style={pressableStyle(({ pressed }) => ({
-                    opacity: pressed ? 0.85 : 1,
-                    transform: [{ scale: pressed ? 0.995 : 1 }],
-                }))}
+                className="mb-2 flex-row items-center gap-3 rounded-2xl border border-outline-variant bg-surface-container-lowest px-4 py-3 active:opacity-90 active:scale-[0.99]"
             >
-                {currentId == item.id && <Ionicons name='checkmark-circle-sharp' size={20} color={Colors.tint} />}
+                {currentId === item.id && <Ionicons name='checkmark-circle-sharp' size={20} color={Colors.tint} />}
                 <View className="h-10 w-10 items-center justify-center rounded-full bg-primary-fixed">
                     <Text className="text-base font-bold text-primary">{item.name?.[0] ?? '?'}</Text>
                 </View>
@@ -160,17 +155,17 @@ export default function CustomerSelectScreen() {
     const ListHeader = (
         <>
             <View className="mb-3 flex-row items-center rounded-2xl bg-surface-container-low px-4 py-3">
-                <Ionicons name="search-outline" size={20} color="#737686" />
+                <Ionicons name="search-outline" size={20} color="#94a3b8" />
                 <TextInput
                     value={searchKey}
                     onChangeText={handleSearch}
                     placeholder="搜索客户姓名 / 手机号"
-                    placeholderTextColor="#9ca3af"
+                    placeholderTextColor="#94a3b8"
                     className="ml-3 flex-1 p-0 text-base text-on-surface"
                 />
                 {searchKey.length > 0 ? (
                     <Pressable hitSlop={8} onPress={handleReset}>
-                        <Ionicons name="close-circle" size={20} color="#c3c6d7" />
+                        <Ionicons name="close-circle" size={20} color="#94a3b8" />
                     </Pressable>
                 ) : null}
             </View>
@@ -203,7 +198,7 @@ export default function CustomerSelectScreen() {
     const ListEmpty =
         !loading ? (
             <View className="items-center rounded-2xl border border-outline-variant bg-surface-container-lowest px-6 py-14">
-                <Ionicons name="people-outline" size={44} color="#c3c6d7" />
+                <Ionicons name="people-outline" size={44} color="#94a3b8" />
                 <Text className="mt-4 text-base text-on-surface-variant">暂无匹配客户</Text>
             </View>
         ) : (

+ 19 - 24
src/app/sign-in.tsx

@@ -1,10 +1,3 @@
-import { pressableStyle } from 'nativewind';
-import type { CaptchaRes } from '@/components/captcha-box';
-import CaptchaBox from '@/components/captcha-box';
-import { site } from '@/config.json';
-import { useInterval } from '@/hooks/hooks';
-import api, { ApiError } from '@/utils/api';
-import { signIn, smsSignIn, useAuth } from '@/utils/auth';
 import { Button, Toast } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import { Link, router, useLocalSearchParams } from 'expo-router';
@@ -28,6 +21,12 @@ import Animated, {
   withTiming,
 } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import CaptchaBox from '@/components/captcha-box';
+import { site } from '@/config.json';
+import { useInterval } from '@/hooks/hooks';
+import api, { ApiError } from '@/utils/api';
+import { signIn, smsSignIn, useAuth } from '@/utils/auth';
+import type { CaptchaRes } from '@/components/captcha-box';
 
 function FieldLabel({ children }: { children: React.ReactNode }) {
   return (
@@ -179,7 +178,11 @@ export default function SignInScreen() {
       if (redirectTo) {
         router.replace(redirectTo as never);
       } else {
-        router.canGoBack() ? router.back() : router.replace('/');
+        if (router.canGoBack()) {
+          router.back();
+        } else {
+          router.replace('/');
+        }
       }
     } catch (error) {
       console.error('登录失败:', error);
@@ -234,12 +237,8 @@ export default function SignInScreen() {
                         key={mode}
                         disabled={loading}
                         onPress={() => setAuthMode(mode as 'sms' | 'password')}
-                        className={`flex-1 rounded-xl px-4 py-3 ${active ? 'bg-surface-container-lowest' : ''
-                          }`}
-                        style={pressableStyle(({ pressed }) => ({
-                          opacity: loading ? 0.5 : pressed ? 0.86 : 1,
-                          transform: [{ scale: pressed ? 0.99 : 1 }],
-                        }))}
+                        className={`flex-1 rounded-xl px-4 py-3 disabled:opacity-50 ${active ? 'bg-surface-container-lowest' : ''
+                          } active:opacity-86 active:scale-[0.99]`}
                       >
                         <Text
                           className={`text-center text-base font-bold ${active ? 'text-primary' : 'text-on-surface-variant'
@@ -267,13 +266,13 @@ export default function SignInScreen() {
                       keyboardType="phone-pad"
                       maxLength={11}
                       placeholder="请输入手机号"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
                     <Ionicons
                       name="phone-portrait-outline"
-                      size={22}
-                      color="#c3c6d7"
+                      size={20}
+                      color="#94a3b8"
                     />
                   </View>
 
@@ -291,7 +290,7 @@ export default function SignInScreen() {
                           ? '请输入 6 位验证码'
                           : '请输入 6-20 位登录密码'
                       }
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
                     {authMode === 'sms' ? (
@@ -306,7 +305,7 @@ export default function SignInScreen() {
                         </Text>
                       </Pressable>
                     ) : (
-                      <Ionicons name="lock-closed-outline" size={22} color="#c3c6d7" />
+                      <Ionicons name="lock-closed-outline" size={20} color="#94a3b8" />
                     )}
                   </View>
                 </View>
@@ -346,11 +345,7 @@ export default function SignInScreen() {
                 ].map(([icon, color]) => (
                   <Pressable
                     key={icon}
-                    className="h-14 w-14 items-center justify-center rounded-full bg-surface-container-low"
-                    style={pressableStyle(({ pressed }) => ({
-                      opacity: pressed ? 0.8 : 1,
-                      transform: [{ scale: pressed ? 0.94 : 1 }],
-                    }))}
+                    className="h-14 w-14 items-center justify-center rounded-full bg-surface-container-low active:opacity-80 active:scale-[0.94]"
                   >
                     <Ionicons
                       name={icon as keyof typeof Ionicons.glyphMap}

+ 20 - 20
src/app/sign-up.tsx

@@ -1,9 +1,3 @@
-import type { CaptchaRes } from '@/components/captcha-box';
-import CaptchaBox from '@/components/captcha-box';
-import { site } from '@/config.json';
-import { useInterval } from '@/hooks/hooks';
-import api, { ApiError } from '@/utils/api';
-import { signUp, useAuth } from '@/utils/auth';
 import { Button, Toast } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import { Link, router, useLocalSearchParams } from 'expo-router';
@@ -26,6 +20,12 @@ import Animated, {
   withTiming,
 } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import CaptchaBox from '@/components/captcha-box';
+import { site } from '@/config.json';
+import { useInterval } from '@/hooks/hooks';
+import api, { ApiError } from '@/utils/api';
+import { signUp, useAuth } from '@/utils/auth';
+import type { CaptchaRes } from '@/components/captcha-box';
 
 function FieldLabel({ children }: { children: React.ReactNode }) {
   return (
@@ -258,13 +258,13 @@ export default function SignUpScreen() {
                       keyboardType="phone-pad"
                       maxLength={11}
                       placeholder="请输入手机号"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
                     <Ionicons
                       name="phone-portrait-outline"
-                      size={22}
-                      color="#c3c6d7"
+                      size={20}
+                      color="#94a3b8"
                     />
                   </View>
 
@@ -277,7 +277,7 @@ export default function SignUpScreen() {
                       keyboardType="number-pad"
                       maxLength={6}
                       placeholder="请输入 6 位验证码"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
                     <Pressable
@@ -301,10 +301,10 @@ export default function SignUpScreen() {
                       secureTextEntry
                       maxLength={20}
                       placeholder="请输入不少于 6 位的密码"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
-                    <Ionicons name="lock-closed-outline" size={22} color="#c3c6d7" />
+                    <Ionicons name="lock-closed-outline" size={20} color="#94a3b8" />
                   </View>
                   <FieldLabel>重复密码</FieldLabel>
                   <View className="mb-5 flex-row items-center rounded-2xl bg-surface-container-low px-5 py-4">
@@ -315,10 +315,10 @@ export default function SignUpScreen() {
                       secureTextEntry
                       maxLength={20}
                       placeholder="请再输入一次密码"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
-                    <Ionicons name="lock-closed-outline" size={22} color="#c3c6d7" />
+                    <Ionicons name="lock-closed-outline" size={20} color="#94a3b8" />
                   </View>
 
                   <FieldLabel>邮箱</FieldLabel>
@@ -330,10 +330,10 @@ export default function SignUpScreen() {
                       keyboardType="email-address"
                       autoCapitalize="none"
                       placeholder="请输入常用邮箱"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
-                    <Ionicons name="mail-outline" size={22} color="#c3c6d7" />
+                    <Ionicons name="mail-outline" size={20} color="#94a3b8" />
                   </View>
 
                   <FieldLabel>姓名</FieldLabel>
@@ -343,10 +343,10 @@ export default function SignUpScreen() {
                       onChangeText={setName}
                       editable={!loading}
                       placeholder="请输入姓名"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
-                    <Ionicons name="person-outline" size={22} color="#c3c6d7" />
+                    <Ionicons name="person-outline" size={20} color="#94a3b8" />
                   </View>
 
                   <FieldLabel>所属机构</FieldLabel>
@@ -356,10 +356,10 @@ export default function SignUpScreen() {
                       onChangeText={setOrganization}
                       editable={!loading}
                       placeholder="请输入所属机构"
-                      placeholderTextColor="#9ca3af"
+                      placeholderTextColor="#94a3b8"
                       className="flex-1 p-0 text-xl font-medium text-on-surface"
                     />
-                    <Ionicons name="business-outline" size={22} color="#c3c6d7" />
+                    <Ionicons name="business-outline" size={20} color="#94a3b8" />
                   </View>
                 </View>
               </View>

+ 1 - 1
src/components/captcha-box.tsx

@@ -108,7 +108,7 @@ export default function CaptchaBox({
                         keyboardType="phone-pad"
                         maxLength={6}
                         placeholder="请输入图中字符"
-                        placeholderTextColor="#9ca3af"
+                        placeholderTextColor="#94a3b8"
                         className="flex-1 h-8 text-center p-0 text-sm font-medium text-on-surface"
                     />
                 </View>

+ 2 - 2
src/components/ui/menu-row.tsx

@@ -29,10 +29,10 @@ export function MenuRow({
       className="flex-row items-center px-5 py-4 active:bg-surface-container-low"
     >
       <View className={`w-10 h-10 rounded-lg items-center justify-center mr-4 ${iconBgClass}`}>
-        <Ionicons name={icon} size={22} color={iconColorClass ?? '#004ac6'} />
+        <Ionicons name={icon} size={20} color={iconColorClass ?? '#2563eb'} />
       </View>
       <Text className="flex-1 font-semibold text-on-surface text-base">{label}</Text>
-      {right ?? <Ionicons name="chevron-forward" size={20} color="#c3c6d7" />}
+      {right ?? <Ionicons name="chevron-forward" size={18} color="#94a3b8" />}
     </Pressable>
   );
 }

+ 2 - 2
src/components/ui/ui-button.tsx

@@ -55,7 +55,7 @@ function ButtonLabel({
     if (!loading) return <Text className={labelClass}>{children}</Text>;
     return (
         <View className="flex-row justify-center items-center">
-            <ActivityIndicator color={disabled ? '#888' : Colors['on-primary']['DEFAULT']} />
+            <ActivityIndicator color={disabled ? '#94a3b8' : Colors['on-primary']['DEFAULT']} />
             <Text className={labelClass}>{children}</Text>
         </View>
     );
@@ -95,7 +95,7 @@ export default function UIButton({
     const inner = (
         <Pressable
             className={clsx(
-                'flex-row justify-center items-center rounded-xl py-1.5 border-2 opacity-100 active:opacity-75 active:scale-95',
+                'flex-row justify-center items-center rounded-xl py-1.5 border-2 opacity-100 active:opacity-75 active:scale-[0.95]',
                 className,
                 {
                     'bg-primary border-primary': type === 'primary',

+ 9 - 9
src/components/upload.tsx

@@ -1,16 +1,8 @@
-import UIButton from '@/components/ui/ui-button';
-import { Colors } from '@/constants/theme';
-import api from '@/utils/api';
-import { openSystemSettings } from '@/utils/os';
 import { ActionSheet, ActivityIndicator, Icon, Modal, Toast } from '@ant-design/react-native';
 import { Ionicons } from '@expo/vector-icons';
 import clsx from 'clsx';
-import type { DocumentPickerAsset } from 'expo-document-picker';
 import { getDocumentAsync } from 'expo-document-picker';
 import { File } from 'expo-file-system';
-import type {
-    ImagePickerAsset
-} from 'expo-image-picker';
 import {
     launchCameraAsync,
     launchImageLibraryAsync,
@@ -20,6 +12,14 @@ import {
 import { Link } from 'expo-router';
 import { useCallback, useEffect, useState } from 'react';
 import { Platform, Pressable, Text, View } from 'react-native';
+import UIButton from '@/components/ui/ui-button';
+import { Colors } from '@/constants/theme';
+import api from '@/utils/api';
+import { openSystemSettings } from '@/utils/os';
+import type { DocumentPickerAsset } from 'expo-document-picker';
+import type {
+    ImagePickerAsset
+} from 'expo-image-picker';
 
 type Asset = ImagePickerAsset | DocumentPickerAsset;
 type UploadHandler = (assets: Asset[], customerId?: string) => void;
@@ -269,7 +269,7 @@ export function UploadComponent({ askCustomer, onComplete, customerId }: { askCu
                 className="items-center rounded-2xl border-2 border-dashed border-outline-variant/40 bg-surface-container-low/50 px-6 py-8 disabled:opacity-50"
             >
                 <View className="mb-3 h-14 w-14 items-center justify-center rounded-full bg-primary-fixed">
-                    <Ionicons name="cloud-upload-outline" size={30} color="#004ac6" />
+                    <Ionicons name="cloud-upload-outline" size={30} color="#2563eb" />
                 </View>
                 {isUploading ? (
                     <ActivityIndicator text="正在上传文档" size="small" />

+ 3 - 3
src/utils/api.ts

@@ -1,10 +1,10 @@
-import type { AxiosRequestConfig } from 'axios';
 import axios from 'axios';
-import Constants from 'expo-constants';
-import type { FetchRequestInit } from 'expo/fetch';
 import { fetch } from 'expo/fetch';
+import Constants from 'expo-constants';
 import { Platform } from 'react-native';
 import type { AccessToken } from './auth';
+import type { AxiosRequestConfig } from 'axios';
+import type { FetchRequestInit } from 'expo/fetch';
 
 const { api: apiConfig, jsVersion } = require('@/config.json') as AppConfig;
 let accessToken: AccessToken | undefined | null = null;