This commit is contained in:
oneao committed 2026-03-04 22:22:07 +08:00
1 parent 34240d2e16
commit bf350d8d35
21 files changed
+670 -304

No files matched your search

@@ -10,7 +10,7 @@ export default function TestScreen() {
const spaceStore = useSpaceStore()
const navigation = useNavigation()
console.log(navigation.getState()?.routes)
console.log(navigation.getState()?.routeNames)
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
@@ -46,6 +46,7 @@ export default function CategorySheet({
const handleSelect = useCallback(
(item: FinanceCategory) => {
console.log(item)
onSelect?.(item)
onClose?.()
},
@@ -74,9 +75,9 @@ export default function CategorySheet({
{
title: '筛选',
data: [
createVirtualCategory(-1, '全部', -1),
createVirtualCategory(-2, '支出', 0),
createVirtualCategory(-3, '收入', 1),
createVirtualCategory(0, '全部', -1),
createVirtualCategory(-1, '支出', 0),
createVirtualCategory(-2, '收入', 1),
],
},
{
@@ -1,16 +1,15 @@
import type { FinanceRecord, FinanceRecordGroup } from '@/types/finance/record'
import React, { useCallback, useState } from 'react'
import type { FinanceRecord } from '@/types/finance/record'
import React, { useCallback, useEffect, useState } from 'react'
import { Pressable, RefreshControl, SectionList, Text, Vibration, View } from 'react-native'
import { LucideIcon } from '@/components/common/ao'
import EmptyState from '@/components/common/EmptyStatus'
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
import { Menu, MenuItem, MenuItemLabel, MenuSeparator } from '@/components/ui/menu'
import { useMoneyCategoryStore } from '@/store/moneyCategory'
import { useFinanceStore } from '@/store/finance'
import { useUserStore } from '@/store/user'
import { MoneyCategoryEnum } from '@/types/money/category'
import { FinanceCategoryEnum } from '@/types/finance/category'
interface StaticTransactionsProps {
records: FinanceRecordGroup[]
onUpdate?: (data: FinanceRecord) => void
onDelete?: (id: number) => void
onDetail?: (id: number) => void
@@ -19,18 +18,18 @@ interface StaticTransactionsProps {
}
export default function StaticTransactions({
records,
onUpdate,
onDelete,
onDetail,
onLoadMore,
onRefreshData,
}: StaticTransactionsProps) {
const moneyCategoryStore = useMoneyCategoryStore()
const financeStore = useFinanceStore()
const userID = useUserStore().userInfo?.id
const [refreshing, setRefreshing] = useState(false)
const [loadingMore, setLoadingMore] = useState(false)
const [selectedId, setSelectedId] = useState<number | null>(null)
const [sections, setSections] = useState<any[]>([])
const handleRefresh = useCallback(async () => {
if (!onRefreshData)
@@ -56,12 +55,14 @@ export default function StaticTransactions({
}
}, [onLoadMore, loadingMore])
const sections = records.map(group => ({
title: group.record_time,
totalIncome: group.income,
totalExpense: group.expense,
data: group.records,
}))
useEffect(() => {
setSections(financeStore.records.map(group => ({
title: group.record_time,
totalIncome: group.income,
totalExpense: group.expense,
data: group.records,
})))
}, [financeStore.records])
return (
<SectionList
@@ -115,7 +116,7 @@ export default function StaticTransactions({
)}
renderItem={({ item }) => {
const category = moneyCategoryStore.getCategoryById(item.category_id)
const category = financeStore.getCategoryById(item.category_id)
return (
<Menu
style={{
@@ -174,7 +175,7 @@ export default function StaticTransactions({
<Text
className="text-sm text-gray-600 text-right"
>
{category?.type === MoneyCategoryEnum.Income ? '+' : '-'}
{category?.type === FinanceCategoryEnum.Income ? '+' : '-'}
{' '}
{item.amount}
</Text>
@@ -184,32 +185,27 @@ export default function StaticTransactions({
)
}}
>
{
userID === item.member_id && (
<>
<MenuItem
key="update"
textValue="update"
className="flex gap-3"
style={{
minWidth: 150,
height: 42,
paddingTop: 0,
paddingBottom: 0,
alignItems: 'center',
borderRadius: 0,
}}
onPress={() => {
onUpdate?.(item)
}}
>
<LucideIcon icon="Pencil" size={18} />
<MenuItemLabel className="text-lg">更新</MenuItemLabel>
</MenuItem>
<MenuSeparator />
</>
)
}
<MenuItem
key="update"
textValue="update"
className="flex gap-3"
style={{
minWidth: 150,
height: 42,
paddingTop: 0,
paddingBottom: 0,
alignItems: 'center',
borderRadius: 0,
}}
onPress={() => {
onUpdate?.(item)
}}
>
<LucideIcon icon="Pencil" size={18} />
<MenuItemLabel className="text-lg">更新</MenuItemLabel>
</MenuItem>
<MenuSeparator />
<MenuItem
key="delete"
@@ -231,6 +227,7 @@ export default function StaticTransactions({
<MenuItemLabel className="text-lg">删除</MenuItemLabel>
</MenuItem>
<MenuSeparator />
<MenuItem
key="detail"
textValue="detail"
@@ -1,17 +1,17 @@
import type { DateMorePickerMode } from '@/components/common/ao/DateMorePicker'
import type { FinanceCategory } from '@/types/finance/category'
import { useFocusEffect, useRouter } from 'expo-router'
import React, { useCallback, useEffect, useState } from 'react'
import { Image, Text, TouchableOpacity, View } from 'react-native'
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
import { toast } from 'sonner-native'
import { ADateMorePicker, ADatePicker, ADrawer, AListItem, LucideIcon } from '@/components/common/ao'
import { resolveDateRange } from '@/components/common/ao/DateMorePicker'
import { Fab, FabIcon } from '@/components/ui/fab'
import { AddIcon } from '@/components/ui/icon'
import { listFinanceRecordsApi } from '@/request/api/finance/record'
import { deleteMoneyRecordApi, listMoneyRecordsApi } from '@/request/api/money/record'
import { deleteFinanceRecordApi, listFinanceRecordsApi } from '@/request/api/finance/record'
import { useFinanceStore } from '@/store/finance'
import { getCurrentYearMonth, normalizeDateTime } from '@/utils/time'
import { toast } from '@/utils/toast'
import { getCurrentYearMonth } from '@/utils/time'
import CategorySheet from './components/CategorySheet'
import TransactionsList from './components/TransactionsList'
@@ -27,10 +27,14 @@ export default function Money() {
const [showDatePicker, setShowDatePicker] = useState(false)
const [dateMode, setDateMode] = useState<DateMorePickerMode>('month')
const [searchParams, setSearchParams] = useState({
const [searchParams, setSearchParams] = useState<{
startTime: string
endTime: string
category: FinanceCategory | null
}>({
startTime: getCurrentYearMonth(),
endTime: '',
category: -1,
category: null,
})
const [showCategorySheet, setShowCategorySheet] = useState(false)
@@ -41,21 +45,23 @@ export default function Money() {
function fetchFinanceRecords() {
const resolveDate = resolveDateRange(dateMode, searchParams.startTime)
let searchType = 0
if (searchParams.category) {
if (searchParams.category.id === -1 || searchParams.category.id === -2) {
searchType = searchParams.category.type
}
}
listFinanceRecordsApi({
start_time: resolveDate.startTime,
end_time: resolveDate.endTime,
category_id: 0,
category_id: searchParams.category ? searchParams.category.id : 0,
category_type: searchType,
}).then((res) => {
if (res.isSuccess) {
financeStore.setRecords(res.data.records || [])
}
else {
toast.show({
title: res.message || '查询错误,请稍后再试',
})
}
}).catch((err) => {
console.log(err)
})
}
@@ -63,15 +69,25 @@ export default function Money() {
useCallback(() => {
financeStore.ensureCategoriesLoaded()
fetchFinanceRecords()
}, [searchParams.startTime, searchParams.endTime]),
}, [searchParams.startTime, searchParams.endTime, searchParams.category]),
)
async function handleDeleteRecord(id: number) {
await deleteMoneyRecordApi({
id,
const toastId = toast.loading('正在删除...', {
duration: Infinity,
})
fetchFinanceRecords()
await deleteFinanceRecordApi({
id,
}).then((res) => {
if (res.isSuccess) {
toast.success('删除成功')
fetchFinanceRecords()
}
}).finally(() => {
toast.dismiss(toastId)
})
}
function timeModeTip() {
@@ -117,7 +133,11 @@ export default function Money() {
onPress={() => setShowCategorySheet(true)}
className="flex flex-row items-center gap-1"
>
<Text className="font-semibold text-lg">分类</Text>
<Text className="font-semibold text-lg">
{
searchParams.category ? searchParams.category.name : '分类'
}
</Text>
<LucideIcon icon="ChevronDown" size={16} color="#666" clickable={false} />
</TouchableOpacity>
</View>
@@ -180,7 +200,6 @@ export default function Money() {
<View className="flex-1 mt-2">
<TransactionsList
records={financeStore.records}
onUpdate={(data) => {
router.push({
pathname: '/finance/record/editor',
@@ -188,7 +207,7 @@ export default function Money() {
})
}}
onDetail={(id) => {
router.navigate({
router.push({
pathname: '/finance/record/detail',
params: { id },
})
@@ -248,15 +267,16 @@ export default function Money() {
<CategorySheet
open={showCategorySheet}
value={searchParams.category}
value={searchParams.category?.id}
moneyCategories={financeStore.categories}
onClose={() => {
setShowCategorySheet(false)
}}
onSelect={(category) => {
console.log(category)
setSearchParams(prev => ({
...prev,
category: category.id,
category,
}))
}}
/>