u
This commit is contained in:
1 parent
295b3306a3
commit
c62c9d080b
8 files changed
+878
-136
No files matched your search
@@ -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 */}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user