u
This commit is contained in:
1 parent
78c7a812be
commit
1934225c53
24 files changed
+711
-654
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { useRouter } from 'expo-router'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useFocusEffect, useRouter } from 'expo-router'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { Image, Text, TouchableOpacity, View } from 'react-native'
|
||||
import { Drawer } from 'react-native-drawer-layout'
|
||||
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
@@ -52,6 +52,17 @@ export default function Money() {
|
||||
getMoneyRecords()
|
||||
}, [appStore.ready, searchParams])
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
// 页面显示 / 返回时
|
||||
console.log('===shohw===')
|
||||
|
||||
return () => {
|
||||
// 页面离开(可选)
|
||||
}
|
||||
}, []),
|
||||
)
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex-1"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { MoneyCategoryItem } from '@/types/money/category'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Pressable, Text, View } from 'react-native'
|
||||
import { AButton, AInput } from '@/components/common/ao'
|
||||
@@ -23,7 +24,7 @@ interface EditCategoryProps {
|
||||
open: boolean
|
||||
onClose?: () => void
|
||||
type: MoneyCategoryEnum
|
||||
|
||||
category: MoneyCategoryItem | null
|
||||
onConfirm?: (form: EditCategoryForm) => Promise<void>
|
||||
}
|
||||
|
||||
@@ -32,6 +33,7 @@ export default function CreateCategory({
|
||||
onClose,
|
||||
type,
|
||||
onConfirm,
|
||||
category,
|
||||
}: EditCategoryProps) {
|
||||
const moneyCategoryStore = useMoneyCategoryStore()
|
||||
|
||||
@@ -58,6 +60,12 @@ export default function CreateCategory({
|
||||
}
|
||||
}, [form.name, form.icon])
|
||||
|
||||
useEffect(() => {
|
||||
if (category !== null) {
|
||||
setForm(category)
|
||||
}
|
||||
}, [category])
|
||||
|
||||
function handleClose() {
|
||||
setIsOpen(false)
|
||||
onClose && onClose()
|
||||
@@ -116,6 +124,7 @@ export default function CreateCategory({
|
||||
</View>
|
||||
|
||||
<AInput
|
||||
value={form.name}
|
||||
placeholder="请输入名称(不超过5个字符)"
|
||||
onChangeText={(text) => {
|
||||
setForm((val) => {
|
||||
|
||||
@@ -25,7 +25,9 @@ export default function MoneyCategorySetting() {
|
||||
const [draggingDeleteZone, setDraggingDeleteZone] = useState<boolean>(false)
|
||||
const [deleteTimer, setDeleteTimer] = useState<number | null>(null)
|
||||
|
||||
const [openCreateCategory, setOpenCreateCategory] = useState<boolean>(false)
|
||||
const [showEditCategory, setshowEditCategory] = useState<boolean>(false)
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<MoneyCategoryItem | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setCategories(selectedTab === MoneyCategoryEnum.Expense ? moneyCategoryStore.getExpenseCategories() : moneyCategoryStore.getIncomeCategories())
|
||||
@@ -35,7 +37,8 @@ export default function MoneyCategorySetting() {
|
||||
({ item }) => (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
console.log('点击进入编辑')
|
||||
setSelectedCategory(item)
|
||||
setshowEditCategory(true)
|
||||
}}
|
||||
className="flex flex-col items-center justify-center"
|
||||
>
|
||||
@@ -64,33 +67,49 @@ export default function MoneyCategorySetting() {
|
||||
)
|
||||
|
||||
async function handleConfirmEdit(form: EditCategoryForm) {
|
||||
const isDuplicate = moneyCategoryStore.isDuplicateCategory(form.name, selectedTab)
|
||||
const isDuplicate = moneyCategoryStore.isDuplicateCategory(
|
||||
form.name,
|
||||
selectedTab,
|
||||
form.id ?? null,
|
||||
)
|
||||
|
||||
if (isDuplicate) {
|
||||
toast.show({
|
||||
type: 'warning',
|
||||
title: '类别不能重复',
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await moneyCategoryStore.createCategory({
|
||||
id: 0,
|
||||
name: form.name,
|
||||
icon: form.icon,
|
||||
sort_number: 0,
|
||||
type: selectedTab,
|
||||
})
|
||||
if (form.id != null) {
|
||||
await moneyCategoryStore.updateCategory({
|
||||
id: form.id,
|
||||
name: form.name,
|
||||
icon: form.icon,
|
||||
type: selectedTab,
|
||||
sort_number: 0,
|
||||
})
|
||||
}
|
||||
else {
|
||||
await moneyCategoryStore.createCategory({
|
||||
id: 0,
|
||||
name: form.name,
|
||||
icon: form.icon,
|
||||
sort_number: 0,
|
||||
type: selectedTab,
|
||||
})
|
||||
}
|
||||
|
||||
setOpenCreateCategory(false)
|
||||
setshowEditCategory(false)
|
||||
}
|
||||
catch (err) {
|
||||
const message
|
||||
= err instanceof Error
|
||||
? err.message
|
||||
: '新增失败,请稍后再试'
|
||||
: form.id != null
|
||||
? '更新失败,请稍后再试'
|
||||
: '新增失败,请稍后再试'
|
||||
|
||||
toast.show({
|
||||
type: 'error',
|
||||
@@ -133,7 +152,7 @@ export default function MoneyCategorySetting() {
|
||||
clickable: false,
|
||||
}}
|
||||
onPress={(() =>
|
||||
setOpenCreateCategory(true)
|
||||
setshowEditCategory(true)
|
||||
)}
|
||||
>
|
||||
新增
|
||||
@@ -228,8 +247,12 @@ export default function MoneyCategorySetting() {
|
||||
|
||||
<EditCategory
|
||||
type={selectedTab}
|
||||
open={openCreateCategory}
|
||||
onClose={() => setOpenCreateCategory(false)}
|
||||
open={showEditCategory}
|
||||
onClose={() => {
|
||||
setshowEditCategory(false)
|
||||
setSelectedCategory(null)
|
||||
}}
|
||||
category={selectedCategory}
|
||||
onConfirm={handleConfirmEdit}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CreateMoneyCategoryParams, CreateMoneyCategoryResult, DeleteMoneyCategoryParams, QueryMoneyCategoryResult, UpdateMoneyCategorySortParams } from '@/types/money/category'
|
||||
import type { CreateMoneyCategoryParams, CreateMoneyCategoryResult, DeleteMoneyCategoryParams, QueryMoneyCategoryResult, UpdateMoneyCategoryParams, UpdateMoneyCategoryResult, UpdateMoneyCategorySortParams } from '@/types/money/category'
|
||||
import alovaInstance from '../../index'
|
||||
|
||||
const API_PREFIX = '/money/category'
|
||||
@@ -18,3 +18,7 @@ export function updateMoneyCategorySortApi(params: UpdateMoneyCategorySortParams
|
||||
export function createMoneyCategoryApi(params: CreateMoneyCategoryParams) {
|
||||
return alovaInstance.Post<ResponseData<CreateMoneyCategoryResult>>(`${API_PREFIX}/create`, params)
|
||||
}
|
||||
|
||||
export function updateMoneyCategoryApi(params: UpdateMoneyCategoryParams) {
|
||||
return alovaInstance.Post<ResponseData<UpdateMoneyCategoryResult>>(`${API_PREFIX}/update`, params)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { MoneyCategoryItem, UpdateMoneyCategorySortItem } from '@/types/money/category'
|
||||
import type { MoneyCategoryItem } from '@/types/money/category'
|
||||
import { create } from 'zustand'
|
||||
import { createMoneyCategoryApi, deleteMoneyCategoryApi, queryMoneyCategoryApi, updateMoneyCategorySortApi } from '@/request/api/money/category'
|
||||
import { createMoneyCategoryApi, deleteMoneyCategoryApi, queryMoneyCategoryApi, updateMoneyCategoryApi, updateMoneyCategorySortApi } from '@/request/api/money/category'
|
||||
import { MoneyCategoryEnum } from '@/types/money/category'
|
||||
|
||||
interface MoneyCategoryStore {
|
||||
@@ -16,10 +16,11 @@ interface MoneyCategoryStore {
|
||||
getCategoryById: (id: number) => MoneyCategoryItem | null
|
||||
|
||||
createCategory: (category: MoneyCategoryItem) => Promise<void>
|
||||
updateCategory: (category: MoneyCategoryItem) => Promise<void>
|
||||
updateSortNumbers: (data: MoneyCategoryItem[], type: number) => Promise<void>
|
||||
deleteCategoryById: (id: number) => Promise<void>
|
||||
|
||||
isDuplicateCategory: (name: string, type: number) => boolean
|
||||
isDuplicateCategory: (name: string, type: number, excludeId: number | null) => boolean
|
||||
|
||||
clear: () => void
|
||||
}
|
||||
@@ -162,6 +163,36 @@ export const useMoneyCategoryStore = create<MoneyCategoryStore>()(
|
||||
}
|
||||
},
|
||||
|
||||
updateCategory: async (category) => {
|
||||
try {
|
||||
const res = await updateMoneyCategoryApi({
|
||||
id: category.id,
|
||||
name: category.name,
|
||||
icon: category.icon,
|
||||
})
|
||||
|
||||
if (!res.isSuccess) {
|
||||
throw new Error(res.message)
|
||||
}
|
||||
|
||||
// 更新本地 categories
|
||||
set(state => ({
|
||||
categories: state.categories.map(c =>
|
||||
c.id !== category.id
|
||||
? c
|
||||
: {
|
||||
...c,
|
||||
...category,
|
||||
},
|
||||
),
|
||||
}))
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
updateSortNumbers: async (data, type) => {
|
||||
const payload = data.map((item, index) => ({
|
||||
id: item.id,
|
||||
@@ -207,9 +238,13 @@ export const useMoneyCategoryStore = create<MoneyCategoryStore>()(
|
||||
}
|
||||
},
|
||||
|
||||
isDuplicateCategory: (name, type) => {
|
||||
isDuplicateCategory: (name, type, excludeId) => {
|
||||
const categories = get().categories || []
|
||||
return categories.some(c => c.name === name && c.type === type)
|
||||
return categories.some(c =>
|
||||
c.name === name
|
||||
&& c.type === type
|
||||
&& c.id !== excludeId,
|
||||
)
|
||||
},
|
||||
}),
|
||||
)
|
||||
@@ -44,3 +44,11 @@ export interface CreateMoneyCategoryParams {
|
||||
export interface CreateMoneyCategoryResult {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface UpdateMoneyCategoryParams {
|
||||
id: number
|
||||
name: string
|
||||
icon: string
|
||||
}
|
||||
export interface UpdateMoneyCategoryResult {
|
||||
}
|
||||
Reference in new issue
Block a user