diff --git a/code/allapp/allapp-rn/package.json b/code/allapp/allapp-rn/package.json
index 4d9f94bb..d7736a5e 100644
--- a/code/allapp/allapp-rn/package.json
+++ b/code/allapp/allapp-rn/package.json
@@ -55,6 +55,7 @@
"react-native-sortables": "^1.9.3",
"react-native-svg": "15.12.1",
"react-native-web": "^0.21.0",
+ "react-native-worklets": "0.5.1",
"tailwind-merge": "^3.4.0",
"zustand": "^5.0.8"
},
diff --git a/code/allapp/allapp-rn/pnpm-lock.yaml b/code/allapp/allapp-rn/pnpm-lock.yaml
index 50e09a4b..5015a112 100644
--- a/code/allapp/allapp-rn/pnpm-lock.yaml
+++ b/code/allapp/allapp-rn/pnpm-lock.yaml
@@ -143,6 +143,9 @@ importers:
react-native-web:
specifier: ^0.21.0
version: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ react-native-worklets:
+ specifier: 0.5.1
+ version: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
tailwind-merge:
specifier: ^3.4.0
version: 3.4.0
@@ -3964,48 +3967,56 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-gnu@1.30.2:
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.27.0:
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.27.0:
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.27.0:
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.27.0:
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
diff --git a/code/allapp/allapp-rn/src/app/(tabs)/money/index.tsx b/code/allapp/allapp-rn/src/app/(tabs)/money/index.tsx
index c0ff5a37..8c6cb1ec 100644
--- a/code/allapp/allapp-rn/src/app/(tabs)/money/index.tsx
+++ b/code/allapp/allapp-rn/src/app/(tabs)/money/index.tsx
@@ -56,7 +56,7 @@ export default function Money() {
useFocusEffect(
useCallback(() => {
// 页面显示 / 返回时
- console.log('===shohw===')
+ console.log('===show===')
return () => {
// 页面离开(可选)
diff --git a/code/allapp/allapp-rn/src/app/auth/index.tsx b/code/allapp/allapp-rn/src/app/auth/index.tsx
index a6e99cef..0832300a 100644
--- a/code/allapp/allapp-rn/src/app/auth/index.tsx
+++ b/code/allapp/allapp-rn/src/app/auth/index.tsx
@@ -1,7 +1,6 @@
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'
@@ -12,10 +11,6 @@ export default function AuthIndex() {
router.push(url)
}
- useEffect(() => {
- QQAPI.login()
- }, [])
-
return (
({
- icon: '',
- name: '',
- })
-
+ const [form, setForm] = useState({ icon: '', name: '' })
const [confirmDisabled, setConfirmDisabled] = useState(true)
const [confirmLoading, setConfirmLoading] = useState(false)
+ const scrollRef = useRef(null)
+ const iconPositions = useRef>({}) // 记录每个 icon 的 y 坐标
+
+ // Drawer 打开/关闭控制
useEffect(() => {
setIsOpen(open)
- if (!open) {
- setForm({
- icon: '',
- name: '',
- })
- }
+ if (!open)
+ setForm({ icon: '', name: '' })
}, [open])
+ // 确认按钮状态
useEffect(() => {
- if (form.name && form.name.length <= 5 && form.icon) {
- setConfirmDisabled(false)
- }
- else {
- setConfirmDisabled(true)
- }
+ setConfirmDisabled(!(form.name && form.name.length <= 5 && form.icon))
}, [form.name, form.icon])
+ // 编辑已有分类时填充数据
useEffect(() => {
- if (category !== null) {
+ if (category)
setForm(category)
- }
}, [category])
function handleClose() {
- setForm({
- icon: '',
- name: '',
- })
+ setForm({ icon: '', name: '' })
setIsOpen(false)
- onClose && onClose()
+ onClose?.()
}
return (
-
-
-
-
-
- 取消
-
- {type === MoneyCategoryEnum.Expense ? '添加支出分类' : '添加收入分类'}
-
- {
- if (!onConfirm) {
- return
- }
-
- try {
- setConfirmLoading(true)
-
- const trimmedForm = {
- ...form,
- name: form.name.trim(),
- }
-
- await onConfirm(trimmedForm)
- }
- catch (err) {
- console.error(err)
- // 外部报错时,保持弹窗打开,loading 结束
- }
- finally {
- setConfirmLoading(false)
- }
- }}
- >
- 确认
-
-
-
- {
- setForm((val) => {
- return {
- ...val,
- name: text,
- }
- })
- }}
- />
-
-
- {Object.entries(moneyCategoryStore.ICON_GROUPS).map(([groupName, icons]) => (
-
-
- {groupName}
-
-
-
- {icons.map(icon => (
- {
- setForm(val => ({
- ...val,
- icon,
- }))
- }}
- >
-
-
-
-
- ))}
-
-
- ))}
-
-
-
-
+
)
}
+
+//
+//
+//
+//
+//
+//
+// 取消
+//
+//
+// {type === MoneyCategoryEnum.Expense ? '添加支出分类' : '添加收入分类'}
+//
+// {
+// if (!onConfirm)
+// return
+// try {
+// setConfirmLoading(true)
+// await onConfirm({ ...form, name: form.name.trim() })
+// }
+// finally {
+// setConfirmLoading(false)
+// }
+// }}
+// >
+// 确认
+//
+//
+// setForm(val => ({ ...val, name: text }))}
+// />
+//
+
+//
+// {Object.entries(moneyCategoryStore.ICON_GROUPS).map(([groupName, icons]) => (
+//
+// {groupName}
+//
+// {icons.map(icon => (
+// setForm(val => ({ ...val, icon }))}
+// >
+// {
+// console.log(e.nativeEvent.layout)
+// iconPositions.current[icon] = e.nativeEvent.layout.y
+// }}
+// style={{
+// width: 46,
+// height: 46,
+// borderRadius: 28,
+// justifyContent: 'center',
+// alignItems: 'center',
+// backgroundColor: icon === form.icon ? '#333' : '#F3F4F6',
+// }}
+// >
+//
+//
+//
+// ))}
+//
+//
+// ))}
+//
+
+//
+//
+//
diff --git a/code/allapp/allapp-rn/src/app/money/category/setting/index.tsx b/code/allapp/allapp-rn/src/app/money/category/setting/index.tsx
index bbca4451..d55a2537 100644
--- a/code/allapp/allapp-rn/src/app/money/category/setting/index.tsx
+++ b/code/allapp/allapp-rn/src/app/money/category/setting/index.tsx
@@ -54,10 +54,11 @@ export default function MoneyCategorySetting() {
>
-
{item.name}
diff --git a/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid copy.tsx b/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid copy.tsx
deleted file mode 100644
index 4b646707..00000000
--- a/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid copy.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import type { ViewStyle } from 'react-native'
-import type { MoneyCategoryItem } from '@/types/money/category'
-import React, { useEffect, useMemo, useRef } from 'react'
-import { FlatList, Pressable, Text, View } from 'react-native'
-import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
-
-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>(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)
- return
-
- // 找到选中项下标
- const itemIndex = data.findIndex(item => item.id === selectedCategory.id)
- if (itemIndex === -1 || !flatListRef.current)
- return
-
- setTimeout(() => {
- if (flatListRef.current) {
- flatListRef.current.scrollToIndex({
- index: Math.floor(itemIndex / 4),
- animated: true,
- viewPosition: 0.5,
- })
- }
- }, 0)
- }, [selectedCategory])
-
- return (
- 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
-
- const isSelected = selectedCategory?.id === item.id
-
- return (
- onSelectCategory?.(item)}
- onLayout={(event) => {
- const { height } = event.nativeEvent.layout
- console.log('Pressable 高度:', height)
- }}
- >
-
-
-
-
- {item.name}
-
-
- )
- }}
- />
- )
-}
diff --git a/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid.tsx b/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid.tsx
index 76a4a5ae..cffd9076 100644
--- a/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid.tsx
+++ b/code/allapp/allapp-rn/src/app/money/record/editor/components/CategoryGrid.tsx
@@ -1,6 +1,6 @@
import type { ViewStyle } from 'react-native'
import type { MoneyCategoryItem } from '@/types/money/category'
-import React, { useEffect, useMemo, useRef } from 'react'
+import React, { useEffect, useRef } from 'react'
import { FlatList, Pressable, Text, View } from 'react-native'
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
@@ -20,27 +20,15 @@ export default function CategoryGrid({
className,
style,
}: CategoryGridProps) {
- const flatListRef = useRef>(null)
+ const NUM_COLUMNS = 4
- // 每行 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])
+ const flatListRef = useRef>(null)
// 自动滚动到选中行
useEffect(() => {
if (!selectedCategory || !flatListRef.current)
return
- // 找到选中项下标
const itemIndex = data.findIndex(item => item.id === selectedCategory.id)
if (itemIndex === -1 || !flatListRef.current)
return
@@ -59,8 +47,8 @@ export default function CategoryGrid({
return (
item.id.toString()}
showsVerticalScrollIndicator={false}
className={`${className}`}
@@ -69,14 +57,15 @@ export default function CategoryGrid({
return { length: 80, offset: 80 * index, index }
}}
renderItem={({ item }) => {
- if (!('name' in item))
- return
-
const isSelected = selectedCategory?.id === item.id
return (
onSelectCategory?.(item)}
>
-
+
{item.name}
diff --git a/code/allapp/allapp-rn/src/request/index.ts b/code/allapp/allapp-rn/src/request/index.ts
index de7e4c95..476eb11d 100644
--- a/code/allapp/allapp-rn/src/request/index.ts
+++ b/code/allapp/allapp-rn/src/request/index.ts
@@ -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,