diff --git a/code/allapp/allapp-go-v3/internal/middleware/auth.go b/code/allapp/allapp-go-v3/internal/middleware/auth.go index 646f6d48..535d872c 100644 --- a/code/allapp/allapp-go-v3/internal/middleware/auth.go +++ b/code/allapp/allapp-go-v3/internal/middleware/auth.go @@ -20,14 +20,14 @@ func Auth() fiber.Handler { return httpx.Unauthorized(c, "未登录") } - _, ok := jwtx.VerifyToken(c.Context(), token) + verifyToken, ok := jwtx.VerifyToken(c.Context(), token) if !ok { return httpx.Unauthorized(c, "登录已过期") } - //ctx := context.WithValue(c.Context(), CtxUserIDKey, verifyToken.Data.UserID) + ctx := context.WithValue(c.Context(), CtxUserIDKey, verifyToken.Data.UserID) - ctx := context.WithValue(c.Context(), CtxUserIDKey, int64(796541901389893)) + //ctx := context.WithValue(c.Context(), CtxUserIDKey, int64(796541901389893)) c.SetContext(ctx) diff --git a/code/app/app-rn4/package.json b/code/app/app-rn4/package.json index b12a7680..d702e58d 100644 --- a/code/app/app-rn4/package.json +++ b/code/app/app-rn4/package.json @@ -20,6 +20,7 @@ "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/elements": "^2.9.10", "@react-navigation/native": "^7.1.33", + "@yz1311/react-native-wheel-picker": "^0.4.5", "alova": "^3.5.1", "axios": "^1.15.0", "dayjs": "^1.11.20", @@ -46,11 +47,13 @@ "expo-wechat": "^0.2.6", "heroui-native": "^1.0.1", "lucide-react-native": "^1.8.0", + "moment": "^2.30.1", "react": "19.2.0", "react-dom": "19.2.0", "react-native": "0.83.4", "react-native-gesture-handler": "~2.30.0", "react-native-keyboard-controller": "1.20.7", + "react-native-modal": "14.0.0-rc.1", "react-native-reanimated": "4.2.1", "react-native-safe-area-context": "~5.6.2", "react-native-screens": "~4.23.0", diff --git a/code/app/app-rn4/pnpm-lock.yaml b/code/app/app-rn4/pnpm-lock.yaml index 2698767f..d60c4b9a 100644 --- a/code/app/app-rn4/pnpm-lock.yaml +++ b/code/app/app-rn4/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@react-navigation/native': 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) + '@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: specifier: ^3.5.1 version: 3.5.1 @@ -107,6 +110,9 @@ importers: lucide-react-native: specifier: ^1.8.0 version: 1.8.0(react-native-svg@15.15.3(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) + moment: + specifier: ^2.30.1 + version: 2.30.1 react: specifier: 19.2.0 version: 19.2.0 @@ -122,6 +128,9 @@ importers: react-native-keyboard-controller: 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) + react-native-modal: + specifier: 14.0.0-rc.1 + version: 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-reanimated: specifier: 4.2.1 version: 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) @@ -1022,56 +1031,48 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@oxfmt/binding-linux-arm64-musl@0.44.0': resolution: {integrity: sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@oxfmt/binding-linux-ppc64-gnu@0.44.0': resolution: {integrity: sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@oxfmt/binding-linux-riscv64-gnu@0.44.0': resolution: {integrity: sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@oxfmt/binding-linux-riscv64-musl@0.44.0': resolution: {integrity: sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [musl] '@oxfmt/binding-linux-s390x-gnu@0.44.0': resolution: {integrity: sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@oxfmt/binding-linux-x64-gnu@0.44.0': resolution: {integrity: sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@oxfmt/binding-linux-x64-musl@0.44.0': resolution: {integrity: sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@oxfmt/binding-openharmony-arm64@0.44.0': resolution: {integrity: sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw==} @@ -1144,56 +1145,48 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@oxlint/binding-linux-arm64-musl@1.60.0': resolution: {integrity: sha512-eDYDXZGhQAXyn6GwtwiX/qcLS0HlOLPJ/+iiIY8RYr+3P8oKBmgKxADLlniL6FtWfE7pPk7IGN9/xvDEvDvFeg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@oxlint/binding-linux-ppc64-gnu@1.60.0': resolution: {integrity: sha512-nxehly5XYBHUWI9VJX1bqCf9j/B43DaK/aS/T1fcxCpX3PA4Rm9BB54nPD1CKayT8xg6REN1ao+01hSRNgy8OA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@oxlint/binding-linux-riscv64-gnu@1.60.0': resolution: {integrity: sha512-j1qf/NaUfOWQutjeoooNG1Q0zsK0XGmSu1uDLq3cctquRF3j7t9Hxqf/76ehCc5GEUAanth2W4Fa+XT1RFg/nw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@oxlint/binding-linux-riscv64-musl@1.60.0': resolution: {integrity: sha512-YELKPRefQ/q/h3RUmeRfPCUhh2wBvgV1RyZ/F9M9u8cDyXsQW2ojv1DeWQTt466yczDITjZnIOg/s05pk7Ve2A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [musl] '@oxlint/binding-linux-s390x-gnu@1.60.0': resolution: {integrity: sha512-JkO3C6Gki7Y6h/MiIkFKvHFOz98/YWvQ4WYbK9DLXACMP2rjULzkeGyAzorJE5S1dzLQGFgeqvN779kSFwoV1g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@oxlint/binding-linux-x64-gnu@1.60.0': resolution: {integrity: sha512-XjKHdFVCpZZZSWBCKyyqCq65s2AKXykMXkjLoKYODrD+f5toLhlwsMESscu8FbgnJQ4Y/dpR/zdazsahmgBJIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@oxlint/binding-linux-x64-musl@1.60.0': resolution: {integrity: sha512-js29ZWIuPhNWzY8NC7KoffEMEeWG105vbmm+8EOJsC+T/jHBiKIJEUF78+F/IrgEWMMP9N0kRND4Pp75+xAhKg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@oxlint/binding-openharmony-arm64@1.60.0': resolution: {integrity: sha512-H+PUITKHk04stFpWj3x3Kg08Afp/bcXSBi0EhasR5a0Vw7StXHTzdl655PUI0fB4qdh2Wsu6Dsi+3ACxPoyQnA==} @@ -1504,6 +1497,9 @@ packages: resolution: {integrity: sha512-wYUdv0rt4MjhKhQloO1AnGDXhZQOFZHDxm86dEtEA0WcsCdVrFdRULFM+rKUC/QQtJW2rS6WBqtBusgtrsDADg==} engines: {node: '>= 20.19.4'} + '@react-native/normalize-colors@0.73.2': + resolution: {integrity: sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==} + '@react-native/normalize-colors@0.74.89': resolution: {integrity: sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==} @@ -1612,28 +1608,24 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.1': resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.1': resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.1': resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.1': resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} @@ -1712,6 +1704,14 @@ packages: resolution: {integrity: sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==} engines: {node: '>=10.0.0'} + '@yz1311/react-native-wheel-picker@0.4.5': + resolution: {integrity: sha512-07ga/fYdgHYI3JTAd+ntaXcJ1D3VxbgaqCPxABjxigehmFYD3VpBbMMVRhxmZC3oVnpedc+SKJXHTNwGtLriCQ==} + peerDependencies: + deprecated-react-native-prop-types: '*' + moment: '*' + react-native: '*' + react-native-modal: '*' + abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -2134,6 +2134,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + deprecated-react-native-prop-types@5.0.0: + resolution: {integrity: sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==} + engines: {node: '>=18'} + destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -2576,7 +2580,7 @@ packages: glob@7.2.3: 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: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} @@ -2909,84 +2913,72 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-gnu@1.31.1: resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.30.1: resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-arm64-musl@1.31.1: resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.30.1: resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-gnu@1.31.1: resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.30.1: resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-linux-x64-musl@1.31.1: resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.30.1: resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} @@ -3271,6 +3263,9 @@ packages: engines: {node: '>=10'} hasBin: true + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -3479,6 +3474,9 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proxy-from-env@2.1.0: resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} engines: {node: '>=10'} @@ -3523,6 +3521,9 @@ packages: react-is@19.2.5: resolution: {integrity: sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==} + react-native-animatable@1.4.0: + resolution: {integrity: sha512-DZwaDVWm2NBvBxf7I0wXKXLKb/TxDnkV53sWhCvei1pRyTX3MVFpkvdYBknNBqPrxYuAIlPxEp7gJOidIauUkw==} + react-native-gesture-handler@2.30.1: resolution: {integrity: sha512-xIUBDo5ktmJs++0fZlavQNvDEE4PsihWhSeJsJtoz4Q6p0MiTM9TgrTgfEgzRR36qGPytFoeq+ShLrVwGdpUdA==} peerDependencies: @@ -3565,6 +3566,12 @@ packages: react-native: '*' react-native-reanimated: '>=3.0.0' + react-native-modal@14.0.0-rc.1: + resolution: {integrity: sha512-v5pvGyx1FlmBzdHyPqBsYQyS2mIJhVmuXyNo5EarIzxicKhuoul6XasXMviGcXboEUT0dTYWs88/VendojPiVw==} + peerDependencies: + react: '*' + react-native: '>=0.70.0' + react-native-reanimated@4.2.1: resolution: {integrity: sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg==} peerDependencies: @@ -5744,6 +5751,8 @@ snapshots: '@react-native/js-polyfills@0.83.4': {} + '@react-native/normalize-colors@0.73.2': {} + '@react-native/normalize-colors@0.74.89': {} '@react-native/normalize-colors@0.83.4': {} @@ -5948,6 +5957,14 @@ snapshots: '@xmldom/xmldom@0.8.12': {} + '@yz1311/react-native-wheel-picker@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))': + dependencies: + deprecated-react-native-prop-types: 5.0.0 + moment: 2.30.1 + prop-types: 15.8.1 + react-native: 0.83.4(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.2.0) + 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) + abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -6413,6 +6430,12 @@ snapshots: depd@2.0.0: {} + deprecated-react-native-prop-types@5.0.0: + dependencies: + '@react-native/normalize-colors': 0.73.2 + invariant: 2.2.4 + prop-types: 15.8.1 + destroy@1.2.0: {} detect-libc@2.1.2: {} @@ -7729,6 +7752,8 @@ snapshots: mkdirp@1.0.4: {} + moment@2.30.1: {} + ms@2.0.0: {} ms@2.1.3: {} @@ -7938,6 +7963,12 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + proxy-from-env@2.1.0: {} query-string@7.1.3: @@ -7980,6 +8011,10 @@ snapshots: react-is@19.2.5: {} + react-native-animatable@1.4.0: + dependencies: + prop-types: 15.8.1 + react-native-gesture-handler@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): dependencies: '@egjs/hammerjs': 2.0.17 @@ -8027,6 +8062,12 @@ snapshots: react-native-is-edge-to-edge: 1.3.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-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-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): + 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-animatable: 1.4.0 + 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): dependencies: react: 19.2.0 diff --git a/code/app/app-rn4/src/app/(tabs)/chat/BottomSheetKeyboardAwareScrollView.tsx b/code/app/app-rn4/src/app/(tabs)/chat/BottomSheetKeyboardAwareScrollView.tsx deleted file mode 100644 index ca429934..00000000 --- a/code/app/app-rn4/src/app/(tabs)/chat/BottomSheetKeyboardAwareScrollView.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { memo } from "react"; -import { - KeyboardAwareScrollView, - KeyboardAwareScrollViewProps, -} from "react-native-keyboard-controller"; -import { - SCROLLABLE_TYPE, - createBottomSheetScrollableComponent, - type BottomSheetScrollViewMethods, -} from "@gorhom/bottom-sheet"; -import type { BottomSheetScrollViewProps } from "@gorhom/bottom-sheet/src/components/bottomSheetScrollable/types"; -import Reanimated from "react-native-reanimated"; - -const AnimatedScrollView = Reanimated.createAnimatedComponent(KeyboardAwareScrollView); -const BottomSheetScrollViewComponent = createBottomSheetScrollableComponent< - BottomSheetScrollViewMethods, - BottomSheetScrollViewProps ->(SCROLLABLE_TYPE.SCROLLVIEW, AnimatedScrollView); -const BottomSheetKeyboardAwareScrollView = memo(BottomSheetScrollViewComponent); - -BottomSheetKeyboardAwareScrollView.displayName = "BottomSheetKeyboardAwareScrollView"; - -export default BottomSheetKeyboardAwareScrollView as ( - props: BottomSheetScrollViewProps & KeyboardAwareScrollViewProps, -) => ReturnType; diff --git a/code/app/app-rn4/src/app/(tabs)/chat/index.tsx b/code/app/app-rn4/src/app/(tabs)/chat/index.tsx index 399b7b91..5dea6cd5 100644 --- a/code/app/app-rn4/src/app/(tabs)/chat/index.tsx +++ b/code/app/app-rn4/src/app/(tabs)/chat/index.tsx @@ -1,54 +1,79 @@ -import { BottomSheet, Button, TextField, Input, useBottomSheetAwareHandlers } from "heroui-native"; -import { useState, useRef, useEffect } from "react"; -import { Keyboard } from "react-native"; +import React, { useState } from "react"; +import { View, Text } from "react-native"; +import { Button } from "heroui-native"; +import DateRangePicker from "@/components/DateRangePicker"; +import dayjs from "dayjs"; -const BottomSheetTextInput = ({ isOpen }: { isOpen: boolean }) => { - const { onFocus, onBlur } = useBottomSheetAwareHandlers(); - const inputRef = useRef(null); +export default function RangeDemo() { + const [start, setStart] = useState(""); + const [end, setEnd] = useState(""); + const [show, setShow] = useState(false); - useEffect(() => { - if (isOpen) { - inputRef.current?.focus(); - } else { - inputRef.current?.blur(); - } - }, [isOpen]); + // 快捷选择 + const setToday = () => { + const today = dayjs().format("YYYY-MM-DD"); + setStart(today); + setEnd(today); + }; + + const setLast7Days = () => { + const end = dayjs(); + const start = end.subtract(6, "day"); + setStart(start.format("YYYY-MM-DD")); + setEnd(end.format("YYYY-MM-DD")); + }; + + const setThisMonth = () => { + const start = dayjs().startOf("month"); + const end = dayjs().endOf("month"); + setStart(start.format("YYYY-MM-DD")); + setEnd(end.format("YYYY-MM-DD")); + }; return ( - - - - ); -}; + + 日期区间选择 Demo -export default function BottomSheetExample() { - const [isOpen, setIsOpen] = useState(false); + {/* 当前选择展示 */} + 开始:{start || "--"} + 结束:{end || "--"} - return ( - { - setIsOpen(open); + {/* 打开选择器 */} + - if (!open) { - Keyboard.dismiss(); // ✅ 关闭时收键盘 - } - }} - animation="disable-all" - > - - - + + + - - + {/* RangePicker */} + setShow(false)} + onConfirm={(s, e) => { + // 简单校验(开始不能大于结束) + if (dayjs(s).isAfter(dayjs(e))) { + console.warn("开始时间不能大于结束时间"); + return; + } - - - - - + setStart(s); + setEnd(e); + setShow(false); + }} + /> + ); } diff --git a/code/app/app-rn4/src/app/(tabs)/chat/index2.tsx b/code/app/app-rn4/src/app/(tabs)/chat/index2.tsx deleted file mode 100644 index 259aeb19..00000000 --- a/code/app/app-rn4/src/app/(tabs)/chat/index2.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { BottomSheet, Button, TextField, Input, useBottomSheetAwareHandlers } from "heroui-native"; -import { useState } from "react"; - -const BottomSheetTextInput = () => { - const { onFocus, onBlur } = useBottomSheetAwareHandlers(); - - return ( - - - - ); -}; - -export default function BottomSheetExample() { - const [isOpen, setIsOpen] = useState(false); - - return ( - { - setIsOpen(open); - }} - > - - - - - - - - - - - - - ); -} diff --git a/code/app/app-rn4/src/app/(tabs)/home/index.tsx b/code/app/app-rn4/src/app/(tabs)/home/index.tsx index 0fbc164d..94619911 100644 --- a/code/app/app-rn4/src/app/(tabs)/home/index.tsx +++ b/code/app/app-rn4/src/app/(tabs)/home/index.tsx @@ -3,11 +3,7 @@ import LayoutView from "@/components/layout/view"; import { loadDataApi } from "@/request/api"; import { View, Text } from "react-native"; import { useFamilyStore } from "@/store"; -import { - HouseHeartIcon, - LayoutGridIcon, - LayersIcon, -} from "lucide-react-native"; +import { LayoutGridIcon, LayersIcon } from "lucide-react-native"; import { IconAppFinance, IconAppClothes } from "@/components/iconfont"; import { PressableFeedback } from "heroui-native"; @@ -71,15 +67,13 @@ export default function Home() { - {family.name} + + + {family.name || "-"} + + - - - - 家庭已陪伴你 - - {duration.days} 天 diff --git a/code/app/app-rn4/src/app/(tabs)/star/index.tsx b/code/app/app-rn4/src/app/(tabs)/star/index.tsx index 56a0cc41..470646fd 100644 --- a/code/app/app-rn4/src/app/(tabs)/star/index.tsx +++ b/code/app/app-rn4/src/app/(tabs)/star/index.tsx @@ -1,10 +1,24 @@ import React from "react"; import { View, Text } from "react-native"; +import DatePicker from "@/components/DatePicker"; +import { useState } from "react"; +import { Button } from "heroui-native"; export default function Star() { + const [date, setDate] = useState(""); + const [showDate, setShowDate] = useState(false); + return ( Star + + ); } diff --git a/code/app/app-rn4/src/app/auth/login.tsx b/code/app/app-rn4/src/app/auth/login.tsx index 46cb4441..d69ebe6b 100644 --- a/code/app/app-rn4/src/app/auth/login.tsx +++ b/code/app/app-rn4/src/app/auth/login.tsx @@ -1,11 +1,17 @@ +import { useEffect } from "react"; import { Stack } from "expo-router"; import { Image, Text, View } from "react-native"; import { Button, LinkButton, ControlField, Checkbox, Spinner } from "heroui-native"; -import { IconQq } from "@/components/iconfont"; +import { IconQq, IconWeixin } from "@/components/iconfont"; import { useState } from "react"; import { FadeIn } from "react-native-reanimated"; import { useUserStore, useFamilyStore } from "@/store"; import { useRouter } from "expo-router"; +import ExpoQQ from "expo-qq"; +import ExpoWeChat from "expo-wechat"; +import { useEvent } from "expo"; +import { toast } from "sonner-native"; +import { loginQqApi, loginWxApi } from "@/request/api"; export default function Login() { const router = useRouter(); @@ -14,49 +20,190 @@ export default function Login() { const [loading, setLoading] = useState(false); const [isAgreed, setIsAgreed] = useState(true); + const [form, setForm] = useState({ + type: 0, + openid: "", + code: "", + }); - /** - * {"code": 1000, "data": {"avatar": "http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100", - * "nickname": "Zhang", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjo3OTY0NTY3MTI3ODU5ODl9LCJpYXQiOjE3NzY1ODU2MDR9.ZwmN5_0MGrP9dYpn3quK94HXMG3QYKmAq7wnP5X68dY", "userId": 796456712785989}, "isSuccess": true, "message": "success", "track_id": "djIRo23SZlA160zBTH2DX-kxeuLApKTNyZdxqqauSMk"} - */ + // 登录 + const onLoginFinished = useEvent(ExpoQQ, "onLoginFinished"); + const onGetUserInfo = useEvent(ExpoQQ, "onGetUserInfo"); + const authResult = useEvent(ExpoWeChat, "onAuthResult"); - function handleTest() { + useEffect(() => { + ExpoQQ.init("102826474", ""); + ExpoWeChat.registerApp("wxdab3e21a1f7e392f", ""); + }, []); + + // 微信登录 + async function handleLoginWechat() { + if (loading) { + return; + } + setLoading(true); + + // 检查微信是否安装 + const isInstalled = await ExpoWeChat.isWXAppInstalled(); + if (!isInstalled) { + toast.warning(onLoginFinished?.errorMessage || "请先安装微信"); + setLoading(false); + return; + } + + setForm((val) => ({ + ...val, + type: 0, + })); + + ExpoWeChat.sendAuthRequest("snsapi_userinfo", "state123"); + } + + // QQ 登录 + async function handleLoginQQ() { if (loading) { return; } setLoading(true); - setTimeout(() => { - requestAnimationFrame(() => { - userStore.setUserInfo({ - id: 796541901389893, - token: - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjo3OTY0NTY3MTI3ODU5ODl9LCJpYXQiOjE3NzY1ODU2MDR9.ZwmN5_0MGrP9dYpn3quK94HXMG3QYKmAq7wnP5X68dY", - nickname: "Zhang", - avatar: - "http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100", - }); - userStore.setAuthExpired(false); - console.log(familyStore.inFamily()); - - // if (familyStore.inFamily()) { - // router.replace("/(tabs)/home"); - // } else { - // router.replace("/family/entry"); - // return; - // } - - familyStore.setCurrentFamily({ - family_id: 797139042881605, - }); - - router.replace("/(tabs)/home"); - }); - setLoading(false); - }, 500); + setForm((val) => ({ + ...val, + type: 1, + })); + await ExpoQQ.login(["get_user_info"]); } + useEffect(() => { + if (!onLoginFinished) { + return; + } + + if (!onLoginFinished.success) { + toast.warning(onLoginFinished?.errorMessage || "授权失败,请检查手机是否安装 QQ 或确认授权"); + setLoading(false); + return; + } + + const fetchUserInfo = async () => { + try { + const tokenInfo = await ExpoQQ.getLoginTokenInfo(); + if (!tokenInfo.openId) { + toast.warning(tokenInfo?.errorMessage || "授权失败,请检查手机是否安装 QQ 或确认授权"); + setLoading(false); + return; + } + + setForm((val) => ({ + ...val, + openid: String(tokenInfo.openId), + })); + + await ExpoQQ.sendGetUserInfoReq(); + } catch (e) { + console.log(e); + + setLoading(false); + } + }; + + fetchUserInfo(); + }, [onLoginFinished]); + + // QQ登录 + useEffect(() => { + const handleLogin = async () => { + if (!onGetUserInfo) { + setLoading(false); + return; + } + + try { + const loginRes = await loginQqApi({ + openid: form.openid, + nickname: onGetUserInfo.nickname || "", + avatar: onGetUserInfo.figureurlQq_2 || onGetUserInfo.figureurl_2, + }); + + if (loginRes.isSuccess) { + requestAnimationFrame(() => { + userStore.setUserInfo({ + token: loginRes.data.token, + id: loginRes.data.userId, + nickname: loginRes.data.nickname, + avatar: loginRes.data.avatar, + }); + + userStore.setAuthExpired(false); + + if (loginRes.data.family_id === 0) { + router.replace("/family/entry"); + } else { + familyStore.setCurrentFamily({ + family_id: loginRes.data.family_id, + }); + + router.replace("/(tabs)/home"); + } + }); + } + } catch (err) { + console.error("登录接口出错", err); + } finally { + setLoading(false); + } + }; + + handleLogin(); + }, [onGetUserInfo]); + + // 微信登录 + useEffect(() => { + if (!authResult) return; + + const handleLogin = async () => { + if (authResult.errorCode === 0) { + try { + const loginRes = await loginWxApi({ + code: authResult.code, + }); + + if (loginRes.isSuccess) { + requestAnimationFrame(() => { + userStore.setUserInfo({ + token: loginRes.data.token, + id: loginRes.data.userId, + nickname: loginRes.data.nickname, + avatar: loginRes.data.avatar, + }); + + userStore.setAuthExpired(false); + + if (loginRes.data.family_id === 0) { + router.replace("/family/entry"); + } else { + familyStore.setCurrentFamily({ + family_id: loginRes.data.family_id, + }); + + router.replace("/(tabs)/home"); + } + }); + } + } catch (err) { + console.error("登录接口出错", err); + } finally { + setLoading(false); + } + } else { + console.log("授权失败:", authResult.errorMessage); + setLoading(false); + } + }; + + handleLogin(); + }, [authResult]); + return ( <> - {/* */} - - diff --git a/code/app/app-rn4/src/app/auth/login.txt b/code/app/app-rn4/src/app/auth/login.txt new file mode 100644 index 00000000..e811d96d --- /dev/null +++ b/code/app/app-rn4/src/app/auth/login.txt @@ -0,0 +1,119 @@ +import { Stack } from "expo-router"; +import { Image, Text, View } from "react-native"; +import { Button, LinkButton, ControlField, Checkbox, Spinner } from "heroui-native"; +import { IconQq } from "@/components/iconfont"; +import { useState } from "react"; +import { FadeIn } from "react-native-reanimated"; +import { useUserStore, useFamilyStore } from "@/store"; +import { useRouter } from "expo-router"; + +export default function Login() { + const router = useRouter(); + const userStore = useUserStore(); + const familyStore = useFamilyStore(); + + const [loading, setLoading] = useState(false); + const [isAgreed, setIsAgreed] = useState(true); + + /** + * {"code": 1000, "data": {"avatar": "http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100", "family_id": 797225979793477, "nickname": "Zhang", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVzZXJfaWQiOjc5NjU0MTkwMTM4OTg5M30sImlhdCI6MTc3Njc3MTcyOX0.JldxjA-0u2hza3qNx20xgUyVBVVV6hQuVuTW1GcJyr8", "userId": 796541901389893}, "isSuccess": true, "message": "success", "track_id": "hI5gEsPHu1LGwkQaJ6lf1dDQby0rzxGVJj0KcNC3Nxw"} + */ + + function handleTest() { + if (loading) { + return; + } + + setLoading(true); + + setTimeout(() => { + requestAnimationFrame(() => { + userStore.setUserInfo({ + id: 796541901389893, + token: + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVzZXJfaWQiOjc5NjU0MTkwMTM4OTg5M30sImlhdCI6MTc3Njc3MTcyOX0.JldxjA-0u2hza3qNx20xgUyVBVVV6hQuVuTW1GcJyr8", + nickname: "Zhang", + avatar: + "http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100", + }); + userStore.setAuthExpired(false); + console.log(familyStore.inFamily()); + + // if (familyStore.inFamily()) { + // router.replace("/(tabs)/home"); + // } else { + // router.replace("/family/entry"); + // return; + // } + + familyStore.setCurrentFamily({ + family_id: 797225979793477, + }); + + router.replace("/(tabs)/home"); + }); + setLoading(false); + }, 500); + } + + return ( + <> + + + + + Welcome to Allapp + + + + {/* + + */} + + + + + + + + + + 登录即表示你同意我们的 + + 用户协议 + + 和 + + 隐私政策 + + + + + + ); +} diff --git a/code/app/app-rn4/src/app/auth/login_2.txt b/code/app/app-rn4/src/app/auth/login_2.txt deleted file mode 100644 index d69ebe6b..00000000 --- a/code/app/app-rn4/src/app/auth/login_2.txt +++ /dev/null @@ -1,262 +0,0 @@ -import { useEffect } from "react"; -import { Stack } from "expo-router"; -import { Image, Text, View } from "react-native"; -import { Button, LinkButton, ControlField, Checkbox, Spinner } from "heroui-native"; -import { IconQq, IconWeixin } from "@/components/iconfont"; -import { useState } from "react"; -import { FadeIn } from "react-native-reanimated"; -import { useUserStore, useFamilyStore } from "@/store"; -import { useRouter } from "expo-router"; -import ExpoQQ from "expo-qq"; -import ExpoWeChat from "expo-wechat"; -import { useEvent } from "expo"; -import { toast } from "sonner-native"; -import { loginQqApi, loginWxApi } from "@/request/api"; - -export default function Login() { - const router = useRouter(); - const userStore = useUserStore(); - const familyStore = useFamilyStore(); - - const [loading, setLoading] = useState(false); - const [isAgreed, setIsAgreed] = useState(true); - const [form, setForm] = useState({ - type: 0, - openid: "", - code: "", - }); - - // 登录 - const onLoginFinished = useEvent(ExpoQQ, "onLoginFinished"); - const onGetUserInfo = useEvent(ExpoQQ, "onGetUserInfo"); - const authResult = useEvent(ExpoWeChat, "onAuthResult"); - - useEffect(() => { - ExpoQQ.init("102826474", ""); - ExpoWeChat.registerApp("wxdab3e21a1f7e392f", ""); - }, []); - - // 微信登录 - async function handleLoginWechat() { - if (loading) { - return; - } - setLoading(true); - - // 检查微信是否安装 - const isInstalled = await ExpoWeChat.isWXAppInstalled(); - if (!isInstalled) { - toast.warning(onLoginFinished?.errorMessage || "请先安装微信"); - setLoading(false); - return; - } - - setForm((val) => ({ - ...val, - type: 0, - })); - - ExpoWeChat.sendAuthRequest("snsapi_userinfo", "state123"); - } - - // QQ 登录 - async function handleLoginQQ() { - if (loading) { - return; - } - - setLoading(true); - - setForm((val) => ({ - ...val, - type: 1, - })); - await ExpoQQ.login(["get_user_info"]); - } - - useEffect(() => { - if (!onLoginFinished) { - return; - } - - if (!onLoginFinished.success) { - toast.warning(onLoginFinished?.errorMessage || "授权失败,请检查手机是否安装 QQ 或确认授权"); - setLoading(false); - return; - } - - const fetchUserInfo = async () => { - try { - const tokenInfo = await ExpoQQ.getLoginTokenInfo(); - if (!tokenInfo.openId) { - toast.warning(tokenInfo?.errorMessage || "授权失败,请检查手机是否安装 QQ 或确认授权"); - setLoading(false); - return; - } - - setForm((val) => ({ - ...val, - openid: String(tokenInfo.openId), - })); - - await ExpoQQ.sendGetUserInfoReq(); - } catch (e) { - console.log(e); - - setLoading(false); - } - }; - - fetchUserInfo(); - }, [onLoginFinished]); - - // QQ登录 - useEffect(() => { - const handleLogin = async () => { - if (!onGetUserInfo) { - setLoading(false); - return; - } - - try { - const loginRes = await loginQqApi({ - openid: form.openid, - nickname: onGetUserInfo.nickname || "", - avatar: onGetUserInfo.figureurlQq_2 || onGetUserInfo.figureurl_2, - }); - - if (loginRes.isSuccess) { - requestAnimationFrame(() => { - userStore.setUserInfo({ - token: loginRes.data.token, - id: loginRes.data.userId, - nickname: loginRes.data.nickname, - avatar: loginRes.data.avatar, - }); - - userStore.setAuthExpired(false); - - if (loginRes.data.family_id === 0) { - router.replace("/family/entry"); - } else { - familyStore.setCurrentFamily({ - family_id: loginRes.data.family_id, - }); - - router.replace("/(tabs)/home"); - } - }); - } - } catch (err) { - console.error("登录接口出错", err); - } finally { - setLoading(false); - } - }; - - handleLogin(); - }, [onGetUserInfo]); - - // 微信登录 - useEffect(() => { - if (!authResult) return; - - const handleLogin = async () => { - if (authResult.errorCode === 0) { - try { - const loginRes = await loginWxApi({ - code: authResult.code, - }); - - if (loginRes.isSuccess) { - requestAnimationFrame(() => { - userStore.setUserInfo({ - token: loginRes.data.token, - id: loginRes.data.userId, - nickname: loginRes.data.nickname, - avatar: loginRes.data.avatar, - }); - - userStore.setAuthExpired(false); - - if (loginRes.data.family_id === 0) { - router.replace("/family/entry"); - } else { - familyStore.setCurrentFamily({ - family_id: loginRes.data.family_id, - }); - - router.replace("/(tabs)/home"); - } - }); - } - } catch (err) { - console.error("登录接口出错", err); - } finally { - setLoading(false); - } - } else { - console.log("授权失败:", authResult.errorMessage); - setLoading(false); - } - }; - - handleLogin(); - }, [authResult]); - - return ( - <> - - - - - Welcome to Allapp - - - - - - - - - - - - - - 登录即表示你同意我们的 - - 用户协议 - - 和 - - 隐私政策 - - - - - - ); -} diff --git a/code/app/app-rn4/src/components/DatePicker.tsx b/code/app/app-rn4/src/components/DatePicker.tsx new file mode 100644 index 00000000..668074ac --- /dev/null +++ b/code/app/app-rn4/src/components/DatePicker.tsx @@ -0,0 +1,97 @@ +import { DatePicker as YzDatePicker } from "@yz1311/react-native-wheel-picker"; +import dayjs from "dayjs"; +import { BottomSheet, Button } from "heroui-native"; +import { useState, useEffect } from "react"; +import { toDate } from "@/utils/time"; +import { View, Text } from "react-native"; + +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"; + +interface DatePickerProps { + value: Date | string; + show?: boolean; + onClose?: () => void; + onConfirm?: (value: string) => void; + mode?: DatePickerMode; + format?: DateFormatType; +} + +const defaultFormatMap: Record = { + year: "YYYY", + month: "YYYY-MM", + date: "YYYY-MM-DD", + time: "HH:mm:ss", + datetime: "YYYY-MM-DD HH:mm", +}; + +export default function DatePicker({ + value, + show = false, + onClose, + onConfirm, + mode = "date", + format, +}: DatePickerProps) { + const [tempDate, setTempDate] = useState(toDate(value)); + const [isOpen, setIsOpen] = useState(false); + + const finalFormat = format || defaultFormatMap[mode]; + + useEffect(() => { + if (show) { + setTempDate(toDate(value)); + setIsOpen(true); + } else { + setIsOpen(false); + } + }, [show, value]); + + const handleClose = () => { + setIsOpen(false); + onClose?.(); + }; + + const handleCancel = () => { + setTempDate(toDate(value)); + handleClose(); + }; + + const handleConfirm = () => { + const formatted = dayjs(tempDate).format(finalFormat); + onConfirm?.(formatted); + handleClose(); + }; + + return ( + !v && handleClose()}> + + + + + + + + 选择时间 + + + + setTempDate(d)} + /> + + + + + ); +} diff --git a/code/app/app-rn4/src/components/DateRangePicker.tsx b/code/app/app-rn4/src/components/DateRangePicker.tsx new file mode 100644 index 00000000..d5a369c0 --- /dev/null +++ b/code/app/app-rn4/src/components/DateRangePicker.tsx @@ -0,0 +1,97 @@ +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(() => toDate(startDate)); + const [tempEnd, setTempEnd] = useState(() => 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 ( + { + if (!v) handleClose(); + }} + > + + + + + + {/* Header */} + + + + 选择日期区间 + + + + + {/* Range Picker */} + { + setTempStart(start); + setTempEnd(end); + }} + /> + + + + + ); +}