This commit is contained in:
oneao committed 2026-01-29 22:54:15 +08:00
1 parent 295b3306a3
commit c62c9d080b
8 files changed
+878 -136

No files matched your search

+21 -40
View File
@@ -1,17 +1,6 @@
import { DateRangePicker } from '@yz1311/react-native-wheel-picker'
import React from 'react'
import { Button, ButtonText } from '@/components/ui/button'
import {
Drawer,
DrawerBackdrop,
DrawerBody,
DrawerCloseButton,
DrawerContent,
DrawerFooter,
DrawerHeader,
} from '@/components/ui/drawer'
import { Heading } from '@/components/ui/heading'
import { CloseIcon, Icon } from '@/components/ui/icon'
import { Text } from '@/components/ui/text'
export default function Example() {
const [showDrawer, setShowDrawer] = React.useState(false)
@@ -21,39 +10,31 @@ export default function Example() {
onPress={() => {
setShowDrawer(true)
}}
className="mt-10"
>
<ButtonText>Open Drawer</ButtonText>
</Button>
<Drawer
isOpen={showDrawer}
anchor="bottom"
size="lg"
onClose={() => {
<DateRangePicker
pickerTitle="预约时间"
pickerCancelBtnText="取消"
pickerConfirmBtnText="确认"
// 开启modal模式
isModal={true}
// 可以自定义modal的一些属性
modalProps={{
}}
modalVisible={showDrawer}
// modalVisible回调函数
onModalVisibleChange={(visible) => {
}}
onPickerCancel={() => {
}}
onPickerConfirm={(date) => {
setShowDrawer(false)
}}
>
<DrawerBackdrop />
<DrawerContent>
<DrawerHeader>
<Text>取消</Text>
<Text>分类设置</Text>
<Text>确认</Text>
</DrawerHeader>
<DrawerBody>
<Text>This is the basic drawer component.</Text>
</DrawerBody>
<DrawerFooter>
<Button
variant="outline"
onPress={() => {
setShowDrawer(false)
}}
>
<ButtonText>Cancel</ButtonText>
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
/>
</>
)
}
@@ -1,5 +1,5 @@
import { useFocusEffect, useRouter } from 'expo-router'
import React, { useCallback, useEffect, useState } from 'react'
import React, { useCallback, useState } from 'react'
import { Image, Text, TouchableOpacity, View } from 'react-native'
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
import { ADatePicker, ADrawer, AListItem, LucideIcon } from '@/components/common/ao'
@@ -84,7 +84,6 @@ export default function Money() {
>
<LucideIcon icon="Menu" size={24} clickable={false} />
</TouchableOpacity>
</View>
<View
@@ -208,6 +207,7 @@ export default function Money() {
text="类别设置"
onPress={() => {
router.navigate('/money/category/setting')
setShowActionsMenu(false)
}}
/>
</View>
@@ -217,7 +217,14 @@ export default function Money() {
<Text className="text-gray-600 font-semibold text-sm">统计分析</Text>
<View className="p-1">
<AListItem icon="ChartSpline" text="图表分析" />
<AListItem
icon="ChartSpline"
text="图表分析"
onPress={() => {
router.navigate('/money/analysis')
setShowActionsMenu(false)
}}
/>
</View>
</View>
</SafeAreaView>
@@ -0,0 +1,126 @@
import dayjs from 'dayjs'
import { useState } from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import { VictoryChart, VictoryLine, VictoryPie, VictoryTheme, VictoryTooltip, VictoryVoronoiContainer } from 'victory-native'
import { ADatePicker, ASegmentedTabs, LucideIcon } from '@/components/common/ao'
import CustomHeader from '@/components/custom/Header'
import PagerTabs from '@/components/custom/PagerTabs'
type GroupBy = 'day' | 'month' | 'year'
type AnalysisType = 'expense' | 'income'
interface AnalysisContentProps {
analysisType: AnalysisType
}
export default function Analysis() {
function AnalysisContent({ analysisType }: AnalysisContentProps) {
const [timeType, setTimeType] = useState<number>(0)
const [groupBy, setGroupBy] = useState<GroupBy>('day')
const [startDate, setStartDate] = useState(
dayjs().format('YYYY-MM'),
)
const [endDate, setEndDate] = useState(
dayjs().format('YYYY-MM'),
)
const [showDatePicker, setShowDatePicker] = useState(false)
return (
<View className="p-4">
<ASegmentedTabs
value={timeType}
onChange={(index) => {
setTimeType(index)
}}
tabs={[
{ key: '1', label: '按月' },
{ key: '2', label: '按年' },
{ key: '3', label: '自定义' },
]}
/>
<TouchableOpacity
className="mt-14 flex flex-row justify-center items-center"
>
<LucideIcon icon="Calendar" size={16} color="#666" clickable={false} />
<Text className="font-semibold text-lg mr-2 ml-1">{startDate}</Text>
{timeType === 2 && (
<>
<Text> - </Text>
<Text className="font-semibold text-lg mx-1">
{endDate}
</Text>
</>
)}
<LucideIcon icon="ChevronDown" size={16} color="#666" clickable={false} />
</TouchableOpacity>
<View className="mt-4">
<Text className="text-lg font-semibold text-gray-700">趋势分析</Text>
<VictoryChart
height={220}
theme={VictoryTheme.material}
padding={{ top: 15, bottom: 30, left: 40, right: 40 }}
>
<VictoryLine
interpolation="catmullRom"
data={[
]}
/>
</VictoryChart>
</View>
<View className="mt-4">
<Text className="text-lg font-semibold text-gray-700">分类构成</Text>
<VictoryPie
height={250}
innerRadius={50}
data={[
]}
theme={VictoryTheme.material}
/>
</View>
<ADatePicker
show={showDatePicker}
mode="month"
onConfirm={(val) => {
setShowDatePicker(false)
}}
onClose={() => {
setShowDatePicker(false)
}}
/>
</View>
)
}
return (
<View className="flex-1">
<CustomHeader
showHeader={false}
/>
<PagerTabs
showCustomHeader={true}
routes={[
{
key: 'expense',
title: '支出',
element: <AnalysisContent analysisType="expense" />,
},
{
key: 'income',
title: '收入',
element: <AnalysisContent analysisType="income" />,
},
]}
/>
</View>
)
}
@@ -1,7 +1,10 @@
import type { ViewStyle } from 'react-native'
import { useRouter } from 'expo-router'
import { useEffect, useRef, useState } from 'react'
import { Animated, Text, TouchableOpacity, View } from 'react-native'
import { Animated, Image, Text, TouchableOpacity, View } from 'react-native'
import PagerView from 'react-native-pager-view'
import { LucideIcon } from '../common/ao'
export interface PagerRoute {
key: string
@@ -16,6 +19,7 @@ interface PagerTabsProps {
selectedIndex?: number // 外部控制选中页
onChange?: (key: string) => void
indicatorWidth?: number
showCustomHeader?: boolean
className?: string
style?: ViewStyle
@@ -28,9 +32,12 @@ export default function PagerTabs({
selectedIndex,
onChange,
indicatorWidth = 38,
showCustomHeader,
className,
style,
}: PagerTabsProps) {
const router = useRouter()
const pagerRef = useRef<PagerView>(null)
const [index, setIndex] = useState(selectedIndex ?? 0)
const [tabWidth, setTabWidth] = useState(0)
@@ -80,7 +87,15 @@ export default function PagerTabs({
>
{/* Header */}
<View className="flex flex-row items-center">
{left}
{left || (showCustomHeader
? (
<View className="w-10 items-center justify-center">
<TouchableOpacity onPress={() => router.back()}>
<LucideIcon icon="ChevronLeft" size={28} clickable={false} />
</TouchableOpacity>
</View>
)
: null)}
{/* Tabs */}
<View
@@ -116,7 +131,16 @@ export default function PagerTabs({
)}
</View>
{right}
{right || (showCustomHeader
? (
<View className="w-10 items-center justify-center">
<Image
source={require('@/static/images/logo.png')}
style={{ width: 22, height: 22 }}
/>
</View>
)
: null)}
</View>
{/* Pager */}
+2 -2
View File
@@ -28,8 +28,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,