u
This commit is contained in:
1 parent
95d645f572
commit
68a834dd18
6 files changed
+330
-217
No files matched your search
@@ -35,8 +35,11 @@
|
|||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-native": "0.81.5",
|
"react-native": "0.81.5",
|
||||||
"react-native-calendars": "^1.1313.0",
|
"react-native-calendars": "^1.1313.0",
|
||||||
|
"react-native-date-picker": "^5.0.13",
|
||||||
"react-native-dates-picker": "^0.2.0",
|
"react-native-dates-picker": "^0.2.0",
|
||||||
"react-native-gesture-handler": "~2.28.0",
|
"react-native-gesture-handler": "~2.28.0",
|
||||||
|
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||||
|
"react-native-keyboard-controller": "1.18.5",
|
||||||
"react-native-reanimated": "~4.1.3",
|
"react-native-reanimated": "~4.1.3",
|
||||||
"react-native-safe-area-context": "~5.6.1",
|
"react-native-safe-area-context": "~5.6.1",
|
||||||
"react-native-screens": "~4.16.0",
|
"react-native-screens": "~4.16.0",
|
||||||
|
|||||||
+54
-8
@@ -83,12 +83,21 @@ importers:
|
|||||||
react-native-calendars:
|
react-native-calendars:
|
||||||
specifier: ^1.1313.0
|
specifier: ^1.1313.0
|
||||||
version: 1.1313.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 1.1313.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
react-native-date-picker:
|
||||||
|
specifier: ^5.0.13
|
||||||
|
version: 5.0.13(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
react-native-dates-picker:
|
react-native-dates-picker:
|
||||||
specifier: ^0.2.0
|
specifier: ^0.2.0
|
||||||
version: 0.2.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 0.2.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
react-native-gesture-handler:
|
react-native-gesture-handler:
|
||||||
specifier: ~2.28.0
|
specifier: ~2.28.0
|
||||||
version: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
react-native-keyboard-aware-scroll-view:
|
||||||
|
specifier: ^0.9.5
|
||||||
|
version: 0.9.5(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))
|
||||||
|
react-native-keyboard-controller:
|
||||||
|
specifier: 1.18.5
|
||||||
|
version: 1.18.5(react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
react-native-reanimated:
|
react-native-reanimated:
|
||||||
specifier: ~4.1.3
|
specifier: ~4.1.3
|
||||||
version: 4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
@@ -3746,56 +3755,48 @@ packages:
|
|||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
lightningcss-linux-arm64-gnu@1.30.2:
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.27.0:
|
lightningcss-linux-arm64-musl@1.27.0:
|
||||||
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
|
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.30.2:
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.27.0:
|
lightningcss-linux-x64-gnu@1.27.0:
|
||||||
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
|
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.30.2:
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.27.0:
|
lightningcss-linux-x64-musl@1.27.0:
|
||||||
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
|
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.30.2:
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
|
||||||
|
|
||||||
lightningcss-win32-arm64-msvc@1.27.0:
|
lightningcss-win32-arm64-msvc@1.27.0:
|
||||||
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
|
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
|
||||||
@@ -4651,6 +4652,12 @@ packages:
|
|||||||
react-native-svg:
|
react-native-svg:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
react-native-date-picker@5.0.13:
|
||||||
|
resolution: {integrity: sha512-qCLUODZVsJetO5zuoXjw1D39K527XWqBG8sOfhWdHyPzf13h8RXR1/RSKd1N0fdRDi5GdyizYmB0lPAK12/hbw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>= 17.0.1'
|
||||||
|
react-native: '>= 0.64.3'
|
||||||
|
|
||||||
react-native-dates-picker@0.2.0:
|
react-native-dates-picker@0.2.0:
|
||||||
resolution: {integrity: sha512-dO7HGami3fhKa/WVtd5jj0xfekbNJZzka++4+0pBUW8br2/t9YzyJ7DYPcZ7vGdRy6bw/qkBG6EASRq8DJP/5Q==}
|
resolution: {integrity: sha512-dO7HGami3fhKa/WVtd5jj0xfekbNJZzka++4+0pBUW8br2/t9YzyJ7DYPcZ7vGdRy6bw/qkBG6EASRq8DJP/5Q==}
|
||||||
engines: {node: '>= 16.0.0'}
|
engines: {node: '>= 16.0.0'}
|
||||||
@@ -4672,12 +4679,29 @@ packages:
|
|||||||
react-native: '*'
|
react-native: '*'
|
||||||
react-native-svg: '>=9.7.0'
|
react-native-svg: '>=9.7.0'
|
||||||
|
|
||||||
|
react-native-iphone-x-helper@1.3.1:
|
||||||
|
resolution: {integrity: sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==}
|
||||||
|
peerDependencies:
|
||||||
|
react-native: '>=0.42.0'
|
||||||
|
|
||||||
react-native-is-edge-to-edge@1.2.1:
|
react-native-is-edge-to-edge@1.2.1:
|
||||||
resolution: {integrity: sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==}
|
resolution: {integrity: sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '*'
|
react: '*'
|
||||||
react-native: '*'
|
react-native: '*'
|
||||||
|
|
||||||
|
react-native-keyboard-aware-scroll-view@0.9.5:
|
||||||
|
resolution: {integrity: sha512-XwfRn+T/qBH9WjTWIBiJD2hPWg0yJvtaEw6RtPCa5/PYHabzBaWxYBOl0usXN/368BL1XktnZPh8C2lmTpOREA==}
|
||||||
|
peerDependencies:
|
||||||
|
react-native: '>=0.48.4'
|
||||||
|
|
||||||
|
react-native-keyboard-controller@1.18.5:
|
||||||
|
resolution: {integrity: sha512-wbYN6Tcu3G5a05dhRYBgjgd74KqoYWuUmroLpigRg9cXy5uYo7prTMIvMgvLtARQtUF7BOtFggUnzgoBOgk0TQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '*'
|
||||||
|
react-native: '*'
|
||||||
|
react-native-reanimated: '>=3.0.0'
|
||||||
|
|
||||||
react-native-reanimated@4.1.3:
|
react-native-reanimated@4.1.3:
|
||||||
resolution: {integrity: sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==}
|
resolution: {integrity: sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -11441,6 +11465,11 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
react-native-date-picker@5.0.13(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
|
dependencies:
|
||||||
|
react: 19.1.0
|
||||||
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
|
||||||
react-native-dates-picker@0.2.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
react-native-dates-picker@0.2.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
dayjs: 1.11.19
|
dayjs: 1.11.19
|
||||||
@@ -11470,11 +11499,28 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
react-native-iphone-x-helper@1.3.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
||||||
|
dependencies:
|
||||||
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
|
||||||
react-native-is-edge-to-edge@1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
react-native-is-edge-to-edge@1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
|
||||||
|
react-native-keyboard-aware-scroll-view@0.9.5(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
||||||
|
dependencies:
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
react-native-iphone-x-helper: 1.3.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))
|
||||||
|
|
||||||
|
react-native-keyboard-controller@1.18.5(react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
|
dependencies:
|
||||||
|
react: 19.1.0
|
||||||
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
react-native-reanimated: 4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
|
||||||
react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.2(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.5
|
'@babel/core': 7.28.5
|
||||||
|
|||||||
@@ -1,19 +1,39 @@
|
|||||||
import type { DateType } from 'react-native-ui-datepicker'
|
import React, { useState } from 'react'
|
||||||
import { useState } from 'react'
|
import { KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native'
|
||||||
import DateTimePicker, { useDefaultStyles } from 'react-native-ui-datepicker'
|
import { KeyboardProvider } from 'react-native-keyboard-controller'
|
||||||
|
import { AInput } from '@/components/common/ao'
|
||||||
export default function Calendar() {
|
|
||||||
const defaultStyles = useDefaultStyles()
|
|
||||||
const [selected, setSelected] = useState<DateType>()
|
|
||||||
|
|
||||||
|
export default function MyInput() {
|
||||||
return (
|
return (
|
||||||
<DateTimePicker
|
<View style={styles.content}>
|
||||||
mode="single"
|
<View style={styles.topSpace} />
|
||||||
date={selected}
|
|
||||||
onChange={({ date }) => setSelected(date)}
|
{/* 输入框 */}
|
||||||
styles={defaultStyles}
|
<View style={styles.inputWrapper}>
|
||||||
className="mt-22"
|
<AInput
|
||||||
/>
|
value=""
|
||||||
|
placeholder="备注"
|
||||||
|
className="bg-[#f2f3f5] border-0"
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
topSpace: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
inputWrapper: {
|
||||||
|
marginHorizontal: 16,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -2,8 +2,8 @@ import type { MoneyCategoryResult } from '@/request/api/money'
|
|||||||
import type { MoneyCategory } from '@/types/money'
|
import type { MoneyCategory } from '@/types/money'
|
||||||
import Big from 'big.js'
|
import Big from 'big.js'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
import { Keyboard, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
import { AInput, LucideIcon } from '@/components/common/ao'
|
import { AInput, LucideIcon } from '@/components/common/ao'
|
||||||
import SegmentedTabs from '@/components/common/ao/SegmentedTabs'
|
import SegmentedTabs from '@/components/common/ao/SegmentedTabs'
|
||||||
@@ -75,6 +75,44 @@ export default function AddMoneyDrawer({
|
|||||||
setSelectedCategoryId(item.id)
|
setSelectedCategoryId(item.id)
|
||||||
setShowKeydown(true)
|
setShowKeydown(true)
|
||||||
}
|
}
|
||||||
|
const categoryNames = [
|
||||||
|
'餐饮',
|
||||||
|
'交通',
|
||||||
|
'娱乐',
|
||||||
|
'购物',
|
||||||
|
'工资',
|
||||||
|
'投资',
|
||||||
|
'住房',
|
||||||
|
'医疗',
|
||||||
|
'学习',
|
||||||
|
'旅行',
|
||||||
|
'通讯',
|
||||||
|
'宠物',
|
||||||
|
'礼物',
|
||||||
|
'数码',
|
||||||
|
'日用品',
|
||||||
|
'保险',
|
||||||
|
'孩子',
|
||||||
|
'捐赠',
|
||||||
|
'水电',
|
||||||
|
'理发',
|
||||||
|
]
|
||||||
|
|
||||||
|
function generateCategories(count: number, type: number): MoneyCategory[] {
|
||||||
|
const result: MoneyCategory[] = []
|
||||||
|
for (let i = 1; i <= count; i++) {
|
||||||
|
const name = categoryNames[Math.floor(Math.random() * categoryNames.length)]
|
||||||
|
result.push({
|
||||||
|
id: i,
|
||||||
|
user_id: 1,
|
||||||
|
name,
|
||||||
|
icon: `icon_${name}`,
|
||||||
|
sort_number: i,
|
||||||
|
type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -83,6 +121,10 @@ export default function AddMoneyDrawer({
|
|||||||
const res = await getMoneyCategoryApi()
|
const res = await getMoneyCategoryApi()
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
// setCategories(res.data)
|
// setCategories(res.data)
|
||||||
|
setCategories({
|
||||||
|
income: generateCategories(100, 1),
|
||||||
|
expense: generateCategories(100, 2),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@@ -241,92 +283,94 @@ export default function AddMoneyDrawer({
|
|||||||
return total.toFixed(2)
|
return total.toFixed(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const inputRef = useRef<any>(null)
|
||||||
|
|
||||||
|
const [isFocused, setIsFocused] = useState(false)
|
||||||
|
|
||||||
|
// 监听键盘收起
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = Keyboard.addListener('keyboardDidHide', () => {
|
||||||
|
if (inputRef.current) {
|
||||||
|
inputRef.current.blur() // 收起键盘时失去焦点
|
||||||
|
setIsFocused(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => sub.remove()
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<Drawer
|
|
||||||
isOpen={isOpen}
|
|
||||||
size="full"
|
|
||||||
anchor="bottom"
|
|
||||||
onClose={onMainDrawerClose}
|
|
||||||
>
|
|
||||||
<DrawerBackdrop />
|
|
||||||
<DrawerContent style={{ padding: 0, paddingLeft: 16, paddingRight: 16 }}>
|
|
||||||
<DrawerHeader
|
|
||||||
className="flex items-center justify-between"
|
|
||||||
style={{ paddingTop: insets.top + 8, margin: 0, padding: 0 }}
|
|
||||||
>
|
|
||||||
<View className="w-1" />
|
|
||||||
<SegmentedTabs
|
|
||||||
value={selectedIndex}
|
|
||||||
tabs={[{ label: '收入' }, { label: '支出' }]}
|
|
||||||
onChange={setSelectedIndex}
|
|
||||||
style={{ width: 180 }}
|
|
||||||
className="mx-auto"
|
|
||||||
/>
|
|
||||||
<Pressable onPress={onMainDrawerClose}>
|
|
||||||
<Text className="text-gray-500 font-medium">取消</Text>
|
|
||||||
</Pressable>
|
|
||||||
</DrawerHeader>
|
|
||||||
|
|
||||||
<DrawerBody>
|
<Drawer
|
||||||
<Grid className="gap-4" _extra={{ className: 'grid-cols-4' }}>
|
isOpen={isOpen}
|
||||||
{(() => {
|
size="full"
|
||||||
const list = selectedIndex === 0 ? categories.income : categories.expense
|
anchor="bottom"
|
||||||
const items = list.map((item) => {
|
onClose={onMainDrawerClose}
|
||||||
const isSelected = selectedCategoryId === item.id
|
>
|
||||||
return (
|
<DrawerBackdrop />
|
||||||
<GridItem key={item.id} _extra={{ className: 'col-span-1' }}>
|
<DrawerContent style={{ padding: 0, flex: 1 }}>
|
||||||
<Pressable
|
<DrawerHeader
|
||||||
className="flex flex-col items-center justify-center rounded"
|
className="flex items-center justify-between"
|
||||||
onPress={() => selectCategory(item)}
|
style={{ paddingTop: insets.top + 8, paddingLeft: 16, paddingRight: 16 }}
|
||||||
>
|
|
||||||
<View
|
|
||||||
className={`w-14 h-14 rounded-full flex items-center justify-center ${
|
|
||||||
isSelected ? 'bg-blue-100' : 'bg-gray-100'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<MoneyCategoryIcon name={item.icon} size={28} />
|
|
||||||
</View>
|
|
||||||
<Text className="text-sm mt-1">
|
|
||||||
{item.name}
|
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
</GridItem>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const remainder = list.length % 4
|
|
||||||
if (remainder > 0) {
|
|
||||||
const emptyCount = 4 - remainder
|
|
||||||
for (let i = 0; i < emptyCount; i++) {
|
|
||||||
items.push(<GridItem key={`empty-${i}`} _extra={{ className: 'col-span-1' }} />)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items
|
|
||||||
})()}
|
|
||||||
</Grid>
|
|
||||||
</DrawerBody>
|
|
||||||
</DrawerContent>
|
|
||||||
</Drawer>
|
|
||||||
|
|
||||||
<Drawer
|
|
||||||
isOpen={showKeydown}
|
|
||||||
size="md"
|
|
||||||
anchor="bottom"
|
|
||||||
onClose={() => setShowKeydown(false)}
|
|
||||||
>
|
|
||||||
<DrawerContent
|
|
||||||
style={{
|
|
||||||
padding: 0,
|
|
||||||
margin: 0,
|
|
||||||
borderTopWidth: 0,
|
|
||||||
elevation: 30,
|
|
||||||
backgroundColor: 'white',
|
|
||||||
height: 360,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<View className="flex-1">
|
<View className="w-1" />
|
||||||
|
<SegmentedTabs
|
||||||
|
value={selectedIndex}
|
||||||
|
tabs={[{ label: '收入' }, { label: '支出' }]}
|
||||||
|
onChange={setSelectedIndex}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
className="mx-auto"
|
||||||
|
/>
|
||||||
|
<Pressable onPress={onMainDrawerClose}>
|
||||||
|
<Text className="text-gray-500 font-medium">取消</Text>
|
||||||
|
</Pressable>
|
||||||
|
</DrawerHeader>
|
||||||
|
|
||||||
|
<DrawerBody style={{ flex: 1, paddingLeft: 16, paddingRight: 16, marginBottom: 0, backgroundColor: '#fff' }}>
|
||||||
|
<Grid className="gap-4 mb-8" _extra={{ className: 'grid-cols-4' }}>
|
||||||
|
{(() => {
|
||||||
|
const list = selectedIndex === 0 ? categories.income : categories.expense
|
||||||
|
const items = list.map((item) => {
|
||||||
|
const isSelected = selectedCategoryId === item.id
|
||||||
|
return (
|
||||||
|
<GridItem key={item.id} _extra={{ className: 'col-span-1' }}>
|
||||||
|
<Pressable
|
||||||
|
className="flex flex-col items-center justify-center rounded"
|
||||||
|
onPress={() => selectCategory(item)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
className={`w-14 h-14 rounded-full flex items-center justify-center ${
|
||||||
|
isSelected ? 'bg-blue-100' : 'bg-gray-100'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<MoneyCategoryIcon name={item.icon} size={28} />
|
||||||
|
</View>
|
||||||
|
<Text className="text-sm mt-1">
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
</GridItem>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const remainder = list.length % 4
|
||||||
|
if (remainder > 0) {
|
||||||
|
const emptyCount = 4 - remainder
|
||||||
|
for (let i = 0; i < emptyCount; i++) {
|
||||||
|
items.push(<GridItem key={`empty-${i}`} _extra={{ className: 'col-span-1' }} />)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items
|
||||||
|
})()}
|
||||||
|
</Grid>
|
||||||
|
</DrawerBody>
|
||||||
|
|
||||||
|
{showKeydown && (
|
||||||
|
<View style={[{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
elevation: 30,
|
||||||
|
}]}
|
||||||
|
>
|
||||||
<View className="p-4">
|
<View className="p-4">
|
||||||
<View className="flex flex-row items-center justify-between">
|
<View className="flex flex-row items-center justify-between">
|
||||||
<Pressable
|
<Pressable
|
||||||
@@ -339,68 +383,70 @@ export default function AddMoneyDrawer({
|
|||||||
<Text className="text-3xl text-blue-700 text-right">{result}</Text>
|
<Text className="text-3xl text-blue-700 text-right">{result}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className="mt-1">
|
<Text className="text-gray-400 text-right">{keydownInput}</Text>
|
||||||
<Text className="text-gray-400 text-right">{keydownInput}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<AInput
|
<AInput
|
||||||
|
ref={inputRef}
|
||||||
value=""
|
value=""
|
||||||
placeholder="备注"
|
placeholder="备注"
|
||||||
className="bg-[#f2f3f5] border-0 mt-2"
|
className="bg-[#f2f3f5] border-0"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
onFocus={() => setIsFocused(true)}
|
||||||
|
onBlur={() => setIsFocused(false)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className="flex-1">
|
{!isFocused && (
|
||||||
<View className="flex flex-row flex-wrap h-full">
|
<View style={{ height: 240 }}>
|
||||||
{keys.map((item, idx) => {
|
<View className="flex flex-row flex-wrap h-full">
|
||||||
const isFirstCol = idx % 4 === 0
|
{keys.map((item, idx) => {
|
||||||
const isFirstRow = idx < 4
|
const isFirstCol = idx % 4 === 0
|
||||||
const isLastCol = (idx + 1) % 4 === 0
|
const isFirstRow = idx < 4
|
||||||
const isLastRow = idx >= 12
|
const isLastCol = (idx + 1) % 4 === 0
|
||||||
|
const isLastRow = idx >= 12
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
key={item.key}
|
key={item.key}
|
||||||
onPress={() => handlePress(item.key)}
|
onPress={() => handlePress(item.key)}
|
||||||
style={{
|
style={{
|
||||||
width: '25%',
|
width: '25%',
|
||||||
height: '25%',
|
height: '25%',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
borderTopWidth: isFirstRow ? 0.3 : 0,
|
borderTopWidth: isFirstRow ? 0.3 : 0,
|
||||||
borderLeftWidth: isFirstCol ? 0.3 : 0,
|
borderLeftWidth: isFirstCol ? 0.3 : 0,
|
||||||
borderRightWidth: !isLastCol ? 0.3 : 0,
|
borderRightWidth: !isLastCol ? 0.3 : 0,
|
||||||
borderBottomWidth: !isLastRow ? 0.3 : 0,
|
borderBottomWidth: !isLastRow ? 0.3 : 0,
|
||||||
borderColor: '#ddd',
|
borderColor: '#ddd',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{({ pressed }) => {
|
{({ pressed }) => {
|
||||||
const defaultBg = item.key === '/' ? '#e6d7b8' : '#fff'
|
const defaultBg = item.key === '/' ? '#e6d7b8' : '#fff'
|
||||||
const pressedBg = item.key === '/' ? '#f5e9d4' : '#f2f2f2'
|
const pressedBg = item.key === '/' ? '#f5e9d4' : '#f2f2f2'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
...StyleSheet.absoluteFillObject,
|
...StyleSheet.absoluteFillObject,
|
||||||
backgroundColor: pressed ? pressedBg : defaultBg,
|
backgroundColor: pressed ? pressedBg : defaultBg,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{item.content}
|
{item.content}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</DrawerContent>
|
)}
|
||||||
</Drawer>
|
</DrawerContent>
|
||||||
|
</Drawer>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import type { ComponentType } from 'react'
|
import type { ComponentType } from 'react'
|
||||||
import type { StyleProp, ViewStyle } from 'react-native'
|
import type { StyleProp, TextInputProps, ViewStyle } from 'react-native'
|
||||||
import { useState } from 'react'
|
import React, { forwardRef, useState } from 'react'
|
||||||
import { Pressable } from 'react-native'
|
import { Pressable } from 'react-native'
|
||||||
import { EyeIcon, EyeOffIcon } from '@/components/ui/icon'
|
import { EyeIcon, EyeOffIcon } from '@/components/ui/icon'
|
||||||
import { InputField, InputIcon, InputSlot, Input as NativeInput } from '@/components/ui/input'
|
import { InputField, InputIcon, InputSlot, Input as NativeInput } from '@/components/ui/input'
|
||||||
|
|
||||||
export interface AInputProps {
|
export interface AInputProps extends Omit<TextInputProps, 'onChange'> {
|
||||||
value: string
|
|
||||||
onChange?: (text: string) => void
|
|
||||||
isPassword?: boolean
|
isPassword?: boolean
|
||||||
isDisabled?: boolean
|
isDisabled?: boolean
|
||||||
isReadOnly?: boolean
|
isReadOnly?: boolean
|
||||||
@@ -16,62 +14,62 @@ export interface AInputProps {
|
|||||||
isFocused?: boolean
|
isFocused?: boolean
|
||||||
variant?: 'outline' | 'rounded' | 'underlined'
|
variant?: 'outline' | 'rounded' | 'underlined'
|
||||||
size?: 'sm' | 'md' | 'lg' | 'xl'
|
size?: 'sm' | 'md' | 'lg' | 'xl'
|
||||||
placeholder?: string
|
|
||||||
leftIcon?: ComponentType
|
leftIcon?: ComponentType
|
||||||
className?: string
|
className?: string
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Input({
|
const AInput = forwardRef<React.ComponentRef<typeof InputField>, AInputProps>(
|
||||||
value,
|
({
|
||||||
onChange,
|
isPassword = false,
|
||||||
isPassword = false,
|
isDisabled = false,
|
||||||
isDisabled = false,
|
isReadOnly = false,
|
||||||
isReadOnly = false,
|
isInvalid = false,
|
||||||
isInvalid = false,
|
isHovered = false,
|
||||||
isHovered = false,
|
isFocused = false,
|
||||||
isFocused = false,
|
variant = 'outline',
|
||||||
variant = 'outline',
|
size = 'md',
|
||||||
size = 'md',
|
leftIcon,
|
||||||
placeholder,
|
className,
|
||||||
leftIcon,
|
style,
|
||||||
className,
|
...rest
|
||||||
style,
|
}, ref) => {
|
||||||
...rest
|
const [showPassword, setShowPassword] = useState(false)
|
||||||
}: AInputProps) {
|
|
||||||
const [showPassword, setShowPassword] = useState(false)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NativeInput
|
<NativeInput
|
||||||
variant={variant}
|
variant={variant}
|
||||||
size={size}
|
size={size}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
isInvalid={isInvalid}
|
isInvalid={isInvalid}
|
||||||
isHovered={isHovered}
|
isHovered={isHovered}
|
||||||
isFocused={isFocused}
|
isFocused={isFocused}
|
||||||
className={className}
|
className={className}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
{leftIcon && (
|
{leftIcon && (
|
||||||
<InputSlot className="pl-3">
|
<InputSlot className="pl-3">
|
||||||
<InputIcon as={leftIcon} />
|
<InputIcon as={leftIcon} />
|
||||||
</InputSlot>
|
</InputSlot>
|
||||||
)}
|
)}
|
||||||
<InputField
|
|
||||||
value={value}
|
<InputField
|
||||||
onChangeText={onChange}
|
ref={ref} // 这里直接传递给 InputField
|
||||||
placeholder={placeholder}
|
type={isPassword ? (showPassword ? 'text' : 'password') : 'text'}
|
||||||
type={isPassword ? (showPassword ? 'text' : 'password') : 'text'}
|
{...rest}
|
||||||
{...rest}
|
/>
|
||||||
/>
|
|
||||||
{isPassword && (
|
{isPassword && (
|
||||||
<InputSlot className="pr-3">
|
<InputSlot className="pr-3">
|
||||||
<Pressable onPress={() => setShowPassword(prev => !prev)}>
|
<Pressable onPress={() => setShowPassword(prev => !prev)}>
|
||||||
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon} />
|
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</InputSlot>
|
</InputSlot>
|
||||||
)}
|
)}
|
||||||
</NativeInput>
|
</NativeInput>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
export default AInput
|
||||||
@@ -30,8 +30,8 @@ function isWhiteListed(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const alovaInstance = createAlova({
|
const alovaInstance = createAlova({
|
||||||
// baseURL: 'http://192.168.5.6:8085/app',
|
baseURL: 'http://192.168.5.6:8085/app',
|
||||||
baseURL: 'http://192.168.1.136:8085/app',
|
// baseURL: 'http://192.168.1.136:8085/app',
|
||||||
requestAdapter: axiosRequestAdapter(),
|
requestAdapter: axiosRequestAdapter(),
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
cacheFor: null,
|
cacheFor: null,
|
||||||
|
|||||||
Reference in new issue
Block a user