This commit is contained in:
oneao committed 2026-04-22 22:05:07 +08:00
1 parent cc88205cba
commit bddbb49e19
8 files changed
+237 -179

No files matched your search

+2 -1
View File
@@ -20,6 +20,7 @@
"@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/bottom-tabs": "^7.15.5",
"@react-navigation/elements": "^2.9.10", "@react-navigation/elements": "^2.9.10",
"@react-navigation/native": "^7.1.33", "@react-navigation/native": "^7.1.33",
"@yz1311/react-native-wheel-picker": "^0.4.5",
"alova": "^3.5.1", "alova": "^3.5.1",
"axios": "^1.15.0", "axios": "^1.15.0",
"dayjs": "^1.11.20", "dayjs": "^1.11.20",
@@ -50,6 +51,7 @@
"react-dom": "19.2.0", "react-dom": "19.2.0",
"react-native": "0.83.4", "react-native": "0.83.4",
"react-native-gesture-handler": "~2.30.0", "react-native-gesture-handler": "~2.30.0",
"react-native-image-crop-picker": "^0.51.1",
"react-native-keyboard-controller": "1.20.7", "react-native-keyboard-controller": "1.20.7",
"react-native-reanimated": "4.2.1", "react-native-reanimated": "4.2.1",
"react-native-safe-area-context": "~5.6.2", "react-native-safe-area-context": "~5.6.2",
@@ -69,7 +71,6 @@
}, },
"devDependencies": { "devDependencies": {
"@types/react": "~19.2.2", "@types/react": "~19.2.2",
"@yz1311/react-native-wheel-picker": "^0.4.5",
"babel-preset-expo": "^55.0.16", "babel-preset-expo": "^55.0.16",
"oxfmt": "^0.44.0", "oxfmt": "^0.44.0",
"oxlint": "^1.59.0", "oxlint": "^1.59.0",
+18 -36
View File
@@ -29,6 +29,9 @@ importers:
'@react-navigation/native': '@react-navigation/native':
specifier: ^7.1.33 specifier: ^7.1.33
version: 7.2.2(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) version: 7.2.2(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)
'@yz1311/react-native-wheel-picker':
specifier: ^0.4.5
version: 0.4.5(deprecated-react-native-prop-types@5.0.0)(moment@2.30.1)(react-native-modal@14.0.0-rc.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))
alova: alova:
specifier: ^3.5.1 specifier: ^3.5.1
version: 3.5.1 version: 3.5.1
@@ -119,6 +122,9 @@ importers:
react-native-gesture-handler: react-native-gesture-handler:
specifier: ~2.30.0 specifier: ~2.30.0
version: 2.30.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) version: 2.30.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)
react-native-image-crop-picker:
specifier: ^0.51.1
version: 0.51.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)
react-native-keyboard-controller: react-native-keyboard-controller:
specifier: 1.20.7 specifier: 1.20.7
version: 1.20.7(react-native-reanimated@4.2.1(react-native-worklets@0.7.2(@babel/core@7.29.0)(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0) version: 1.20.7(react-native-reanimated@4.2.1(react-native-worklets@0.7.2(@babel/core@7.29.0)(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0)
@@ -171,9 +177,6 @@ importers:
'@types/react': '@types/react':
specifier: ~19.2.2 specifier: ~19.2.2
version: 19.2.14 version: 19.2.14
'@yz1311/react-native-wheel-picker':
specifier: ^0.4.5
version: 0.4.5(deprecated-react-native-prop-types@5.0.0)(moment@2.30.1)(react-native-modal@14.0.0-rc.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0))(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))
babel-preset-expo: babel-preset-expo:
specifier: ^55.0.16 specifier: ^55.0.16
version: 55.0.17(@babel/core@7.29.0)(@babel/runtime@7.29.2)(expo@55.0.15)(react-refresh@0.14.2) version: 55.0.17(@babel/core@7.29.0)(@babel/runtime@7.29.2)(expo@55.0.15)(react-refresh@0.14.2)
@@ -1028,56 +1031,48 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-arm64-musl@0.44.0': '@oxfmt/binding-linux-arm64-musl@0.44.0':
resolution: {integrity: sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg==} resolution: {integrity: sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl]
'@oxfmt/binding-linux-ppc64-gnu@0.44.0': '@oxfmt/binding-linux-ppc64-gnu@0.44.0':
resolution: {integrity: sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A==} resolution: {integrity: sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-riscv64-gnu@0.44.0': '@oxfmt/binding-linux-riscv64-gnu@0.44.0':
resolution: {integrity: sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ==} resolution: {integrity: sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-riscv64-musl@0.44.0': '@oxfmt/binding-linux-riscv64-musl@0.44.0':
resolution: {integrity: sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw==} resolution: {integrity: sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [musl]
'@oxfmt/binding-linux-s390x-gnu@0.44.0': '@oxfmt/binding-linux-s390x-gnu@0.44.0':
resolution: {integrity: sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA==} resolution: {integrity: sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-x64-gnu@0.44.0': '@oxfmt/binding-linux-x64-gnu@0.44.0':
resolution: {integrity: sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA==} resolution: {integrity: sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-x64-musl@0.44.0': '@oxfmt/binding-linux-x64-musl@0.44.0':
resolution: {integrity: sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A==} resolution: {integrity: sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl]
'@oxfmt/binding-openharmony-arm64@0.44.0': '@oxfmt/binding-openharmony-arm64@0.44.0':
resolution: {integrity: sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw==} resolution: {integrity: sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw==}
@@ -1150,56 +1145,48 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc]
'@oxlint/binding-linux-arm64-musl@1.60.0': '@oxlint/binding-linux-arm64-musl@1.60.0':
resolution: {integrity: sha512-eDYDXZGhQAXyn6GwtwiX/qcLS0HlOLPJ/+iiIY8RYr+3P8oKBmgKxADLlniL6FtWfE7pPk7IGN9/xvDEvDvFeg==} resolution: {integrity: sha512-eDYDXZGhQAXyn6GwtwiX/qcLS0HlOLPJ/+iiIY8RYr+3P8oKBmgKxADLlniL6FtWfE7pPk7IGN9/xvDEvDvFeg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl]
'@oxlint/binding-linux-ppc64-gnu@1.60.0': '@oxlint/binding-linux-ppc64-gnu@1.60.0':
resolution: {integrity: sha512-nxehly5XYBHUWI9VJX1bqCf9j/B43DaK/aS/T1fcxCpX3PA4Rm9BB54nPD1CKayT8xg6REN1ao+01hSRNgy8OA==} resolution: {integrity: sha512-nxehly5XYBHUWI9VJX1bqCf9j/B43DaK/aS/T1fcxCpX3PA4Rm9BB54nPD1CKayT8xg6REN1ao+01hSRNgy8OA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc]
'@oxlint/binding-linux-riscv64-gnu@1.60.0': '@oxlint/binding-linux-riscv64-gnu@1.60.0':
resolution: {integrity: sha512-j1qf/NaUfOWQutjeoooNG1Q0zsK0XGmSu1uDLq3cctquRF3j7t9Hxqf/76ehCc5GEUAanth2W4Fa+XT1RFg/nw==} resolution: {integrity: sha512-j1qf/NaUfOWQutjeoooNG1Q0zsK0XGmSu1uDLq3cctquRF3j7t9Hxqf/76ehCc5GEUAanth2W4Fa+XT1RFg/nw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [glibc]
'@oxlint/binding-linux-riscv64-musl@1.60.0': '@oxlint/binding-linux-riscv64-musl@1.60.0':
resolution: {integrity: sha512-YELKPRefQ/q/h3RUmeRfPCUhh2wBvgV1RyZ/F9M9u8cDyXsQW2ojv1DeWQTt466yczDITjZnIOg/s05pk7Ve2A==} resolution: {integrity: sha512-YELKPRefQ/q/h3RUmeRfPCUhh2wBvgV1RyZ/F9M9u8cDyXsQW2ojv1DeWQTt466yczDITjZnIOg/s05pk7Ve2A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [musl]
'@oxlint/binding-linux-s390x-gnu@1.60.0': '@oxlint/binding-linux-s390x-gnu@1.60.0':
resolution: {integrity: sha512-JkO3C6Gki7Y6h/MiIkFKvHFOz98/YWvQ4WYbK9DLXACMP2rjULzkeGyAzorJE5S1dzLQGFgeqvN779kSFwoV1g==} resolution: {integrity: sha512-JkO3C6Gki7Y6h/MiIkFKvHFOz98/YWvQ4WYbK9DLXACMP2rjULzkeGyAzorJE5S1dzLQGFgeqvN779kSFwoV1g==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc]
'@oxlint/binding-linux-x64-gnu@1.60.0': '@oxlint/binding-linux-x64-gnu@1.60.0':
resolution: {integrity: sha512-XjKHdFVCpZZZSWBCKyyqCq65s2AKXykMXkjLoKYODrD+f5toLhlwsMESscu8FbgnJQ4Y/dpR/zdazsahmgBJIA==} resolution: {integrity: sha512-XjKHdFVCpZZZSWBCKyyqCq65s2AKXykMXkjLoKYODrD+f5toLhlwsMESscu8FbgnJQ4Y/dpR/zdazsahmgBJIA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc]
'@oxlint/binding-linux-x64-musl@1.60.0': '@oxlint/binding-linux-x64-musl@1.60.0':
resolution: {integrity: sha512-js29ZWIuPhNWzY8NC7KoffEMEeWG105vbmm+8EOJsC+T/jHBiKIJEUF78+F/IrgEWMMP9N0kRND4Pp75+xAhKg==} resolution: {integrity: sha512-js29ZWIuPhNWzY8NC7KoffEMEeWG105vbmm+8EOJsC+T/jHBiKIJEUF78+F/IrgEWMMP9N0kRND4Pp75+xAhKg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl]
'@oxlint/binding-openharmony-arm64@1.60.0': '@oxlint/binding-openharmony-arm64@1.60.0':
resolution: {integrity: sha512-H+PUITKHk04stFpWj3x3Kg08Afp/bcXSBi0EhasR5a0Vw7StXHTzdl655PUI0fB4qdh2Wsu6Dsi+3ACxPoyQnA==} resolution: {integrity: sha512-H+PUITKHk04stFpWj3x3Kg08Afp/bcXSBi0EhasR5a0Vw7StXHTzdl655PUI0fB4qdh2Wsu6Dsi+3ACxPoyQnA==}
@@ -1621,28 +1608,24 @@ packages:
engines: {node: '>= 20'} engines: {node: '>= 20'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.2.1': '@tailwindcss/oxide-linux-arm64-musl@4.2.1':
resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.2.1': '@tailwindcss/oxide-linux-x64-gnu@4.2.1':
resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.2.1': '@tailwindcss/oxide-linux-x64-musl@4.2.1':
resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.2.1': '@tailwindcss/oxide-wasm32-wasi@4.2.1':
resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==}
@@ -2601,7 +2584,7 @@ packages:
glob@7.2.3: glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
gopd@1.2.0: gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
@@ -2937,84 +2920,72 @@ 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.31.1: lightningcss-linux-arm64-gnu@1.31.1:
resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
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.32.0: lightningcss-linux-arm64-gnu@1.32.0:
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
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.30.1: lightningcss-linux-arm64-musl@1.30.1:
resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
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.31.1: lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
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.32.0: lightningcss-linux-arm64-musl@1.32.0:
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
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.30.1: lightningcss-linux-x64-gnu@1.30.1:
resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
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.31.1: lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
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.32.0: lightningcss-linux-x64-gnu@1.32.0:
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
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.30.1: lightningcss-linux-x64-musl@1.30.1:
resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
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.31.1: lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
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.32.0: lightningcss-linux-x64-musl@1.32.0:
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
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.30.1: lightningcss-win32-arm64-msvc@1.30.1:
resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
@@ -3583,6 +3554,12 @@ packages:
react-native: '*' react-native: '*'
react-native-svg: '>=9.7.0' react-native-svg: '>=9.7.0'
react-native-image-crop-picker@0.51.1:
resolution: {integrity: sha512-GIFRyXJgv1dPceKd/hraK9q9V38v45rSg2ONR6RiSePcOJemkHpc/PMU86pq6lWPilDYHSxbZmea2pNMk85ayw==}
peerDependencies:
react: '*'
react-native: '*'
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:
@@ -8092,6 +8069,11 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
react-native-image-crop-picker@0.51.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0):
dependencies:
react: 19.2.0
react-native: 0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0)
react-native-is-edge-to-edge@1.2.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0): react-native-is-edge-to-edge@1.2.1(react-native@0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0))(react@19.2.0):
dependencies: dependencies:
react: 19.2.0 react: 19.2.0
+48 -9
View File
@@ -1,13 +1,52 @@
import React from "react"; import { useState } from "react";
import LayoutView from "@/components/layout/view"; import { Alert, Button, Image, View, StyleSheet } from "react-native";
import { Text } from "react-native"; import * as ImagePicker from "expo-image-picker";
export default function ImagePickerExample() {
const [image, setImage] = useState<string | null>(null);
const pickImage = async () => {
// No permissions request is necessary for launching the image library.
// Manually request permissions for videos on iOS when `allowsEditing` is set to `false`
// and `videoExportPreset` is `'Passthrough'` (the default), ideally before launching the picker
// so the app users aren't surprised by a system dialog after picking a video.
// See "Invoke permissions for videos" sub section for more details.
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permissionResult.granted) {
Alert.alert("Permission required", "Permission to access the media library is required.");
return;
}
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images", "videos"],
allowsEditing: true,
quality: 1,
});
console.log(result);
if (!result.canceled) {
setImage(result.assets[0].uri);
}
};
export default function Chat() {
return ( return (
<LayoutView> <View style={styles.container}>
<LayoutView.ScrollView> <Button title="Pick an image from camera roll" onPress={pickImage} />
<Text className="text-base text-black">Hello</Text> {image && <Image source={{ uri: image }} style={styles.image} />}
</LayoutView.ScrollView> </View>
</LayoutView>
); );
} }
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
image: {
width: 200,
height: 200,
},
});
+3 -1
View File
@@ -65,7 +65,9 @@ export default function RootLayout() {
headerShown: false, headerShown: false,
}} }}
/> />
{!isDev && <StatusBar style={isDark ? "light" : "dark"} />} {/* {!isDev && <StatusBar style={isDark ? "light" : "dark"} />} */}
<StatusBar style={"auto"} />
</HeroUINativeProvider> </HeroUINativeProvider>
</KeyboardProvider> </KeyboardProvider>
</ThemeProvider> </ThemeProvider>
@@ -1,97 +0,0 @@
import React, { useState, useEffect, useMemo } from "react";
import { DateRangePicker as YzDateRangePicker } from "@yz1311/react-native-wheel-picker";
import { BottomSheet, Button } from "heroui-native";
import { View, Text } from "react-native";
import dayjs from "dayjs";
import { toDate } from "@/utils/time";
interface DateRangePickerProps {
startDate: Date | string;
endDate: Date | string;
show?: boolean;
onClose?: () => void;
onConfirm?: (start: string, end: string) => void;
}
export default function DateRangePicker({
startDate,
endDate,
show = false,
onClose,
onConfirm,
}: DateRangePickerProps) {
const [tempStart, setTempStart] = useState<Date | undefined>(() => toDate(startDate));
const [tempEnd, setTempEnd] = useState<Date | undefined>(() => toDate(endDate));
useEffect(() => {
setTempStart(toDate(startDate));
setTempEnd(toDate(endDate));
}, [startDate, endDate]);
const isOpen = show;
const handleClose = () => {
onClose?.();
};
const handleCancel = () => {
setTempStart(toDate(startDate));
setTempEnd(toDate(endDate));
handleClose();
};
const handleConfirm = () => {
const start = dayjs(tempStart).format("YYYY-MM-DD");
const end = dayjs(tempEnd).format("YYYY-MM-DD");
onConfirm?.(start, end);
handleClose();
};
const key = useMemo(
() => `${dayjs(startDate).format("YYYY-MM-DD")}_${dayjs(endDate).format("YYYY-MM-DD")}`,
[startDate, endDate],
);
return (
<BottomSheet
isOpen={isOpen}
onOpenChange={(v) => {
if (!v) handleClose();
}}
>
<BottomSheet.Portal>
<BottomSheet.Overlay />
<BottomSheet.Content>
<View style={{ width: "100%" }}>
{/* Header */}
<View className="flex-row items-center justify-between w-full">
<Button size="sm" variant="tertiary" onPress={handleCancel}>
取消
</Button>
<Text className="text-gray-800 text-base font-medium">选择日期区间</Text>
<Button size="sm" onPress={handleConfirm}>
确认
</Button>
</View>
{/* Range Picker */}
<YzDateRangePicker
key={`${dayjs(startDate).valueOf()}_${dayjs(endDate).valueOf()}`}
showHeader={false}
startDate={tempStart}
endDate={tempEnd}
onValueChange={(start: Date, end: Date) => {
setTempStart(start);
setTempEnd(end);
}}
/>
</View>
</BottomSheet.Content>
</BottomSheet.Portal>
</BottomSheet>
);
}
+17 -31
View File
@@ -3,9 +3,11 @@ import dayjs from "dayjs";
import { BottomSheet, Button } from "heroui-native"; import { BottomSheet, Button } from "heroui-native";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { toDate } from "@/utils/time"; import { toDate } from "@/utils/time";
import { View, Text } from "react-native"; import { View } from "react-native";
import { CheckIcon } from "lucide-react-native";
export type DatePickerMode = "year" | "month" | "date" | "time" | "datetime"; export type DatePickerMode = "year" | "month" | "date" | "time" | "datetime";
export type DateFormatType = "YYYY" | "YYYY-MM" | "YYYY-MM-DD" | "HH:mm:ss" | "YYYY-MM-DD HH:mm"; export type DateFormatType = "YYYY" | "YYYY-MM" | "YYYY-MM-DD" | "HH:mm:ss" | "YYYY-MM-DD HH:mm";
interface DatePickerProps { interface DatePickerProps {
@@ -25,7 +27,7 @@ const defaultFormatMap: Record<DatePickerMode, DateFormatType> = {
datetime: "YYYY-MM-DD HH:mm", datetime: "YYYY-MM-DD HH:mm",
}; };
export default function DatePicker({ export default function DateTime({
value, value,
show = false, show = false,
onClose, onClose,
@@ -33,62 +35,46 @@ export default function DatePicker({
mode = "date", mode = "date",
format, format,
}: DatePickerProps) { }: DatePickerProps) {
const [tempDate, setTempDate] = useState<Date>(toDate(value)); const finalFormat = format ?? defaultFormatMap[mode] ?? "YYYY-MM-DD";
const [isOpen, setIsOpen] = useState(false);
const finalFormat = format || defaultFormatMap[mode]; const [tempDate, setTempDate] = useState<Date>(toDate(value) ?? new Date());
useEffect(() => { useEffect(() => {
if (show) { if (show) {
setTempDate(toDate(value)); setTempDate(toDate(value) ?? new Date());
setIsOpen(true);
} else {
setIsOpen(false);
} }
}, [show, value]); }, [show, value]);
const handleClose = () => { const handleClose = () => {
setIsOpen(false);
onClose?.(); onClose?.();
}; };
const handleCancel = () => {
setTempDate(toDate(value));
handleClose();
};
const handleConfirm = () => { const handleConfirm = () => {
const formatted = dayjs(tempDate).format(finalFormat); if (!tempDate) return;
onConfirm?.(formatted);
onConfirm?.(dayjs(tempDate).format(finalFormat));
handleClose(); handleClose();
}; };
return ( return (
<BottomSheet isOpen={isOpen} onOpenChange={(v) => !v && handleClose()}> <BottomSheet isOpen={show} onOpenChange={(v) => !v && handleClose()}>
<BottomSheet.Portal> <BottomSheet.Portal>
<BottomSheet.Overlay /> <BottomSheet.Overlay />
<BottomSheet.Content> <BottomSheet.Content>
<View style={{ width: "100%", alignItems: "center" }}> <View style={{ width: "100%", alignItems: "center" }}>
<View className="flex-row items-center justify-between w-full">
<Button size="sm" variant="tertiary" onPress={handleCancel}>
取消
</Button>
<Text className="text-gray-800 text-base font-medium">选择时间</Text>
<Button size="sm" onPress={handleConfirm}>
确认
</Button>
</View>
<YzDatePicker <YzDatePicker
showHeader={false} showHeader={false}
date={tempDate} date={tempDate}
mode={mode} mode={mode}
isModal={false} isModal={false}
onPickerCancel={handleCancel}
onPickerConfirm={handleConfirm}
onDateChange={(d: Date) => setTempDate(d)} onDateChange={(d: Date) => setTempDate(d)}
/> />
<Button className="w-full" onPress={handleConfirm}>
<CheckIcon color="#fff" />
<Button.Label>确认</Button.Label>
</Button>
</View> </View>
</BottomSheet.Content> </BottomSheet.Content>
</BottomSheet.Portal> </BottomSheet.Portal>
@@ -0,0 +1,145 @@
import React, { useState, useEffect } from "react";
import { DatePicker as YzDatePicker } from "@yz1311/react-native-wheel-picker";
import { BottomSheet, Button } from "heroui-native";
import { View, Text, TouchableOpacity } from "react-native";
import dayjs from "dayjs";
import { toDate } from "@/utils/time";
import { CheckIcon } from "lucide-react-native";
interface DateRangePickerProps {
startDate?: Date | string;
endDate?: Date | string;
show?: boolean;
onClose?: () => void;
onConfirm?: (start: string, end: string) => void;
}
export default function DateTimeRange({
startDate,
endDate,
show = false,
onClose,
onConfirm,
}: DateRangePickerProps) {
const [tempStart, setTempStart] = useState<Date | undefined>(undefined);
const [tempEnd, setTempEnd] = useState<Date | undefined>(undefined);
const [active, setActive] = useState<"start" | "end">("start");
// ✅ 每次打开重置
useEffect(() => {
if (show) {
setTempStart(toDate(startDate) ?? new Date());
setTempEnd(toDate(endDate) ?? undefined);
setActive("start");
}
}, [show, startDate, endDate]);
const handleClose = () => {
onClose?.();
};
const handleConfirm = () => {
if (!tempStart) return;
onConfirm?.(
dayjs(tempStart).format("YYYY-MM-DD"),
tempEnd ? dayjs(tempEnd).format("YYYY-MM-DD") : "",
);
handleClose();
};
// ❗ start 修改 → 清空 end
const handleStartChange = (date: Date) => {
setTempStart(date);
setTempEnd(undefined);
};
// ❗ end 修改
const handleEndChange = (date: Date) => {
if (!tempStart) return;
setTempEnd(date);
};
const formatDate = (date?: Date) => (date ? dayjs(date).format("YYYY-MM-DD") : "请选择");
return (
<BottomSheet isOpen={show} onOpenChange={(v) => !v && handleClose()}>
<BottomSheet.Portal>
<BottomSheet.Overlay />
<BottomSheet.Content>
<View className="w-full items-center">
{/* 顶部选择区 */}
<View className="flex-row items-center justify-between w-full">
{/* start */}
<TouchableOpacity className="flex-1 items-center" onPress={() => setActive("start")}>
<Text>开始时间</Text>
<Text
className={`text-base ${
active === "start" ? "text-accent font-bold" : "text-gray-400"
}`}
>
{formatDate(tempStart)}
</Text>
</TouchableOpacity>
<View className="w-px h-10 bg-gray-300 mx-2" />
{/* end */}
<TouchableOpacity
className="flex-1 items-center"
style={{ opacity: tempStart ? 1 : 0.4 }}
disabled={!tempStart}
onPress={() => {
if (!tempStart) return;
// ✅ 核心优化:未选 end → 自动补 start
if (!tempEnd) {
setTempEnd(tempStart);
}
setActive("end");
}}
>
<Text>结束时间</Text>
<Text
className={`text-base ${
active === "end" ? "text-accent font-bold" : "text-gray-400"
}`}
>
{formatDate(tempEnd)}
</Text>
</TouchableOpacity>
</View>
{/* Picker */}
{active === "start" ? (
<YzDatePicker
showHeader={false}
mode="date"
date={tempStart ?? new Date()}
onDateChange={handleStartChange}
/>
) : (
<YzDatePicker
showHeader={false}
mode="date"
date={tempEnd ?? tempStart ?? new Date()}
minDate={tempStart}
onDateChange={handleEndChange}
/>
)}
{/* confirm */}
<Button className="w-full" onPress={handleConfirm}>
<CheckIcon color="#fff" />
<Button.Label>确认</Button.Label>
</Button>
</View>
</BottomSheet.Content>
</BottomSheet.Portal>
</BottomSheet>
);
}
+4 -4
View File
@@ -33,14 +33,14 @@ export function getCurrentYear(): string {
} }
/** 字符串 / 数字 / Date → Date(无效返回 null) */ /** 字符串 / 数字 / Date → Date(无效返回 null) */
export function toDate(input: string | number | Date | undefined | null): Date { export function toDate(input: string | number | Date | undefined | null): Date | undefined {
if (!input) return new Date(); if (!input) return undefined;
if (input instanceof Date) return input; if (input instanceof Date) return input;
const d = dayjs(input); const d = dayjs(input);
return d.isValid() ? d.toDate() : new Date(); return d.isValid() ? d.toDate() : undefined;
} }
/** Date → YYYY-MM-DD */ /** Date → YYYY-MM-DD */
export function toDateString(date: string | number | Date): string { export function toDateString(date: string | number | Date): string {
const d = dayjs(toDate(date)); const d = dayjs(toDate(date));