u
This commit is contained in:
1 parent
18e9d94b77
commit
1f82f1dd1f
16 files changed
+1048
-297
No files matched your search
@@ -1,5 +1,4 @@
|
||||
import type { MoneyRecordGroup, MoneyRecordItem, QueryMoneyRecordsResult } from '@/types/money/record'
|
||||
import Big from 'big.js'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Text, TouchableOpacity, View } from 'react-native'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
@@ -7,9 +6,9 @@ import { ADatePicker, LucideIcon } from '@/components/common/ao'
|
||||
import { Fab, FabIcon } from '@/components/ui/fab'
|
||||
import { AddIcon } from '@/components/ui/icon'
|
||||
import { Progress, ProgressFilledTrack } from '@/components/ui/progress'
|
||||
import { queryMoneyRecordsApi } from '@/request/api/money/record'
|
||||
import { deleteMoneyRecordApi, queryMoneyRecordsApi } from '@/request/api/money/record'
|
||||
import { add, sub } from '@/utils/math'
|
||||
import { getCurrentYearMonth } from '@/utils/time'
|
||||
import { getCurrentYearMonth, isInMonth } from '@/utils/time'
|
||||
import { toast } from '@/utils/toast'
|
||||
import AddMoneyDrawer from './components/AddDrawer'
|
||||
import TransactionsList from './components/TransactionsList'
|
||||
@@ -30,6 +29,8 @@ export default function Money() {
|
||||
total_income: '0',
|
||||
records: [],
|
||||
})
|
||||
// 更新
|
||||
const [updateItem, setUpdateItem] = useState<MoneyRecordItem | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
queryMoneyRecordsApi({
|
||||
@@ -53,6 +54,11 @@ export default function Money() {
|
||||
const recordTime = data.record_time
|
||||
|
||||
setMoneyRecords((prev) => {
|
||||
// 不在当前月份 → 不添加,直接返回
|
||||
if (!isInMonth(recordTime, searchParams.record_time)) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const next = structuredClone(prev)
|
||||
|
||||
// 查找分组
|
||||
@@ -64,12 +70,12 @@ export default function Money() {
|
||||
group.records.unshift(data)
|
||||
|
||||
// 更新分组 & 总计
|
||||
if (data.category_type === 0) {
|
||||
if (data.category_type === 1) {
|
||||
// 收入
|
||||
group.income = add(group.income, data.amount)
|
||||
next.total_income = add(next.total_income, data.amount)
|
||||
}
|
||||
else if (data.category_type === 1) {
|
||||
else if (data.category_type === 0) {
|
||||
// 支出
|
||||
group.expense = add(group.expense, data.amount)
|
||||
next.total_expense = add(next.total_expense, data.amount)
|
||||
@@ -79,8 +85,8 @@ export default function Money() {
|
||||
}
|
||||
|
||||
// === 无分组,新建 ===
|
||||
const income = data.category_type === 0 ? data.amount : '0'
|
||||
const expense = data.category_type === 1 ? data.amount : '0'
|
||||
const expense = data.category_type === 0 ? data.amount : '0'
|
||||
const income = data.category_type === 1 ? data.amount : '0'
|
||||
|
||||
const newGroup: MoneyRecordGroup = {
|
||||
record_time: recordTime,
|
||||
@@ -94,11 +100,9 @@ export default function Money() {
|
||||
const index = next.records.findIndex(g => g.record_time < recordTime)
|
||||
|
||||
if (index === -1) {
|
||||
// 所有日期都比它大 → 插入最后
|
||||
next.records.push(newGroup)
|
||||
}
|
||||
else {
|
||||
// 插入正确位置
|
||||
next.records.splice(index, 0, newGroup)
|
||||
}
|
||||
|
||||
@@ -114,6 +118,164 @@ export default function Money() {
|
||||
})
|
||||
}
|
||||
|
||||
function handleUpdateMoneyRecord(updated: MoneyRecordItem) {
|
||||
setMoneyRecords((prev) => {
|
||||
const next = structuredClone(prev)
|
||||
|
||||
// 找到旧记录
|
||||
const oldGroupIndex = next.records.findIndex(g =>
|
||||
g.records.some(r => r.id === updated.id),
|
||||
)
|
||||
if (oldGroupIndex === -1)
|
||||
return next
|
||||
|
||||
const oldGroup = next.records[oldGroupIndex]
|
||||
const oldRecordIndex = oldGroup.records.findIndex(r => r.id === updated.id)
|
||||
const oldRecord = oldGroup.records[oldRecordIndex]
|
||||
|
||||
const oldAmount = oldRecord.amount
|
||||
const newAmount = updated.amount
|
||||
const oldType = oldRecord.category_type
|
||||
const newType = updated.category_type
|
||||
const oldDate = oldRecord.record_time
|
||||
const newDate = updated.record_time
|
||||
|
||||
// record_time 没变 → 同分组更新
|
||||
if (oldDate === newDate) {
|
||||
oldGroup.records[oldRecordIndex] = updated
|
||||
|
||||
// 调整分组金额
|
||||
if (oldType === 1)
|
||||
oldGroup.income = sub(oldGroup.income, oldAmount)
|
||||
if (oldType === 0)
|
||||
oldGroup.expense = sub(oldGroup.expense, oldAmount)
|
||||
|
||||
if (newType === 1)
|
||||
oldGroup.income = add(oldGroup.income, newAmount)
|
||||
if (newType === 0)
|
||||
oldGroup.expense = add(oldGroup.expense, newAmount)
|
||||
|
||||
// 调整总计
|
||||
if (oldType === 1)
|
||||
next.total_income = sub(next.total_income, oldAmount)
|
||||
if (oldType === 0)
|
||||
next.total_expense = sub(next.total_expense, oldAmount)
|
||||
|
||||
if (newType === 1)
|
||||
next.total_income = add(next.total_income, newAmount)
|
||||
if (newType === 0)
|
||||
next.total_expense = add(next.total_expense, newAmount)
|
||||
|
||||
return next
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// 判断是否在当前月份内
|
||||
// -------------------------
|
||||
const currentMonth = searchParams.record_time // 例如 "2025-01"
|
||||
|
||||
const isInCurrentMonth = isInMonth(newDate, currentMonth)
|
||||
|
||||
// 1. 先移除旧分组 & 调整金额(无论是否在当前月份,都要做)
|
||||
if (oldType === 1)
|
||||
oldGroup.income = sub(oldGroup.income, oldAmount)
|
||||
if (oldType === 0)
|
||||
oldGroup.expense = sub(oldGroup.expense, oldAmount)
|
||||
|
||||
if (oldType === 1)
|
||||
next.total_income = sub(next.total_income, oldAmount)
|
||||
if (oldType === 0)
|
||||
next.total_expense = sub(next.total_expense, oldAmount)
|
||||
|
||||
oldGroup.records.splice(oldRecordIndex, 1)
|
||||
if (oldGroup.records.length === 0) {
|
||||
next.records.splice(oldGroupIndex, 1)
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// 不在当前月份 → 不显示,直接返回 next
|
||||
// -------------------------
|
||||
if (!isInCurrentMonth) {
|
||||
return next
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// 在当前月份 → 移动到新分组
|
||||
// -------------------------
|
||||
|
||||
// 找新分组,如果没有就创建
|
||||
let newGroup = next.records.find(g => g.record_time === newDate)
|
||||
if (!newGroup) {
|
||||
newGroup = {
|
||||
record_time: newDate,
|
||||
income: '0.00',
|
||||
expense: '0.00',
|
||||
records: [],
|
||||
}
|
||||
// 按日期倒序插入
|
||||
const insertIndex = next.records.findIndex(g => g.record_time < newDate)
|
||||
if (insertIndex === -1)
|
||||
next.records.push(newGroup)
|
||||
else
|
||||
next.records.splice(insertIndex, 0, newGroup)
|
||||
}
|
||||
|
||||
// 添加到新分组
|
||||
newGroup.records.unshift(updated)
|
||||
|
||||
// 加金额
|
||||
if (newType === 1)
|
||||
newGroup.income = add(newGroup.income, newAmount)
|
||||
if (newType === 0)
|
||||
newGroup.expense = add(newGroup.expense, newAmount)
|
||||
|
||||
if (newType === 1)
|
||||
next.total_income = add(next.total_income, newAmount)
|
||||
if (newType === 0)
|
||||
next.total_expense = add(next.total_expense, newAmount)
|
||||
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
function handleDeleteRecord(id: number) {
|
||||
// 直接更新本地状态
|
||||
setMoneyRecords((prev) => {
|
||||
const next = structuredClone(prev)
|
||||
|
||||
// 遍历每个分组
|
||||
next.records.forEach((group) => {
|
||||
const index = group.records.findIndex(r => r.id === id)
|
||||
if (index !== -1) {
|
||||
const record = group.records[index]
|
||||
|
||||
// 更新分组金额
|
||||
if (record.category_type === 1) {
|
||||
group.income = sub(group.income, record.amount)
|
||||
next.total_income = sub(next.total_income, record.amount)
|
||||
}
|
||||
else if (record.category_type === 0) {
|
||||
group.expense = sub(group.expense, record.amount)
|
||||
next.total_expense = sub(next.total_expense, record.amount)
|
||||
}
|
||||
|
||||
// 删除记录
|
||||
group.records.splice(index, 1)
|
||||
}
|
||||
})
|
||||
|
||||
// 删除空分组
|
||||
next.records = next.records.filter(g => g.records.length > 0)
|
||||
|
||||
return next
|
||||
})
|
||||
|
||||
// 异步请求删除 API
|
||||
deleteMoneyRecordApi({ id }).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex-1"
|
||||
@@ -122,7 +284,7 @@ export default function Money() {
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<View className="flex flex-row justify-between items-center px-4">
|
||||
<View className="flex flex-row justify-between items-center px-3">
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowDatePicker(true)}
|
||||
className="flex flex-row items-center gap-1"
|
||||
@@ -198,8 +360,17 @@ export default function Money() {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="flex-1 px-4 mt-2">
|
||||
<TransactionsList records={moneyRecords.records} />
|
||||
<View className="flex-1 mt-2">
|
||||
<TransactionsList
|
||||
records={moneyRecords.records}
|
||||
onUpdate={(data) => {
|
||||
setUpdateItem(data)
|
||||
setShowAddDrawer(true)
|
||||
}}
|
||||
onDelete={(id) => {
|
||||
handleDeleteRecord(id)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<Fab
|
||||
@@ -213,12 +384,20 @@ export default function Money() {
|
||||
|
||||
<AddMoneyDrawer
|
||||
isOpen={showAddDrawer}
|
||||
updateData={updateItem}
|
||||
onClose={() => {
|
||||
setShowAddDrawer(false)
|
||||
setUpdateItem(null)
|
||||
}}
|
||||
onConfirm={(res) => {
|
||||
setShowAddDrawer(false)
|
||||
handleAddMoneyRecord(res)
|
||||
if (updateItem !== null) {
|
||||
setUpdateItem(null)
|
||||
handleUpdateMoneyRecord(res)
|
||||
}
|
||||
else {
|
||||
handleAddMoneyRecord(res)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
Reference in new issue
Block a user