u
This commit is contained in:
1 parent
2130be4e49
commit
1ccae92d0f
8 files changed
+96
-55
No files matched your search
@@ -35,7 +35,7 @@ export default function Money() {
|
||||
}).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
console.log(res.data.records)
|
||||
moneyRecordStore.setRecords(res.data.records, searchParams.record_time)
|
||||
moneyRecordStore.setRecords(res.data.records || [], searchParams.record_time)
|
||||
}
|
||||
else {
|
||||
toast.show({
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useRouter } from 'expo-router'
|
||||
import { useEffect } from 'react'
|
||||
import { Image, Text, View } from 'react-native'
|
||||
import * as QQAPI from 'react-native-qq-lib'
|
||||
import CustomHeader from '@/components/custom/Header'
|
||||
import { Button, ButtonText } from '@/components/ui/button'
|
||||
|
||||
@@ -10,6 +12,10 @@ export default function AuthIndex() {
|
||||
router.push(url)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
QQAPI.login()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View className="flex-1">
|
||||
<CustomHeader
|
||||
|
||||
@@ -1,24 +1,40 @@
|
||||
import type { FlatList } from 'react-native'
|
||||
import type { ViewStyle } from 'react-native'
|
||||
import type { MoneyCategoryItem } from '@/types/money/category'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import { Pressable, Text, View } from 'react-native'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import React, { useEffect, useMemo, useRef } from 'react'
|
||||
import { FlatList, Pressable, Text, View } from 'react-native'
|
||||
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
|
||||
import { Grid, GridItem } from '@/components/ui/grid'
|
||||
|
||||
interface CategoryGridProps {
|
||||
data: MoneyCategoryItem[]
|
||||
selectedCategory?: MoneyCategoryItem | null
|
||||
onSelectCategory?: (item: MoneyCategoryItem | null) => void
|
||||
|
||||
className?: string
|
||||
style?: ViewStyle
|
||||
}
|
||||
|
||||
export default function CategoryGrid({
|
||||
data,
|
||||
selectedCategory,
|
||||
onSelectCategory,
|
||||
className,
|
||||
style,
|
||||
}: CategoryGridProps) {
|
||||
const flatListRef = useRef<FlatList<any>>(null)
|
||||
|
||||
// 每行 4 个,补齐空项
|
||||
const memoItems = useMemo(() => {
|
||||
const items = [...data]
|
||||
const remainder = items.length % 4
|
||||
if (remainder > 0) {
|
||||
const emptyCount = 4 - remainder
|
||||
for (let i = 0; i < emptyCount; i++) {
|
||||
items.push({ id: `empty-${i}` } as any)
|
||||
}
|
||||
}
|
||||
return items
|
||||
}, [data])
|
||||
|
||||
// 自动滚动到选中行
|
||||
useEffect(() => {
|
||||
if (!selectedCategory || !flatListRef.current)
|
||||
@@ -41,43 +57,51 @@ export default function CategoryGrid({
|
||||
}, [selectedCategory])
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<Grid className="gap-4 px-2 py-4 justify-start" _extra={{ className: 'grid-cols-12' }}>
|
||||
{data.map((item) => {
|
||||
const isSelected = selectedCategory?.id === item.id
|
||||
return (
|
||||
<GridItem
|
||||
_extra={{ className: 'col-span-3' }}
|
||||
key={item.id}
|
||||
<FlatList
|
||||
ref={flatListRef}
|
||||
data={memoItems}
|
||||
numColumns={4}
|
||||
keyExtractor={item => item.id.toString()}
|
||||
showsVerticalScrollIndicator={false}
|
||||
className={`${className}`}
|
||||
style={[style]}
|
||||
getItemLayout={(data, index) => {
|
||||
return { length: 80, offset: 80 * index, index }
|
||||
}}
|
||||
renderItem={({ item }) => {
|
||||
if (!('name' in item))
|
||||
return <View style={{ flex: 1 / 4, margin: 4 }} />
|
||||
|
||||
const isSelected = selectedCategory?.id === item.id
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
style={{ flex: 1 / 4, height: 80, alignItems: 'center' }}
|
||||
onPress={() => onSelectCategory?.(item)}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
width: 46,
|
||||
height: 46,
|
||||
borderRadius: 28,
|
||||
marginTop: 4,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: isSelected ? '#333' : '#F3F4F6',
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
style={{ alignItems: 'center' }}
|
||||
onPress={() => onSelectCategory?.(item)}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
width: 46,
|
||||
height: 46,
|
||||
borderRadius: 28,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: isSelected ? '#333' : '#F3F4F6',
|
||||
}}
|
||||
>
|
||||
<MoneyCategoryIcon
|
||||
name={item.icon}
|
||||
size={28}
|
||||
color={isSelected ? '#fff' : '#000'}
|
||||
/>
|
||||
</View>
|
||||
<Text style={{ fontSize: 14, textAlign: 'center' }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</GridItem>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</ScrollView>
|
||||
<MoneyCategoryIcon
|
||||
name={item.icon}
|
||||
size={28}
|
||||
color={isSelected ? '#fff' : '#000'}
|
||||
/>
|
||||
</View>
|
||||
<Text style={{ marginBottom: 4, fontSize: 14, textAlign: 'center' }}>
|
||||
{item.name}
|
||||
</Text>
|
||||
</Pressable>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import { useEffect, useState } from 'react'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
|
||||
import Animated, { useAnimatedStyle, useSharedValue, withSequence, withTiming } from 'react-native-reanimated'
|
||||
import { scheduleOnRN } from 'react-native-worklets'
|
||||
|
||||
interface AppTabbarProps {
|
||||
data: TabbarItem[]
|
||||
|
||||
@@ -32,8 +32,8 @@ function isWhiteListed(url: string) {
|
||||
}
|
||||
|
||||
const alovaInstance = createAlova({
|
||||
// baseURL: 'http://192.168.5.6:8086/app',
|
||||
baseURL: 'http://192.168.1.137:8086/app',
|
||||
baseURL: 'http://192.168.5.6:8086/app',
|
||||
// baseURL: 'http://192.168.1.137:8086/app',
|
||||
requestAdapter: axiosRequestAdapter(),
|
||||
timeout: 5000,
|
||||
cacheFor: null,
|
||||
|
||||
Reference in new issue
Block a user