This commit is contained in:
oneao committed 2025-11-04 17:32:32 +08:00
1 parent c0ff3ce883
commit 69d03709ba
41 files changed
+5352 -67

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
{
"symbol_url": "//at.alicdn.com/t/c/font_5056764_6s6rld1vyq.js",
"use_typescript": true,
"save_dir": "./src/components/iconfont",
"trim_icon_prefix": "icon",
"default_icon_size": 18,
"local_svgs": ""
}
+3 -2
View File
@@ -22,7 +22,7 @@
"expo-router": "~6.0.14",
"expo-splash-screen": "~31.0.10",
"expo-status-bar": "~3.0.8",
"lucide-react-native": "^0.552.0",
"lucide-react-native": "^0.510.0",
"nativewind": "^4.2.1",
"react": "19.1.0",
"react-native": "0.81.5",
@@ -30,13 +30,14 @@
"react-native-reanimated": "~4.1.3",
"react-native-safe-area-context": "~5.6.1",
"react-native-screens": "~4.16.0",
"react-native-svg": "15.12.1",
"react-native-svg": "15.12.0",
"zustand": "^5.0.8"
},
"devDependencies": {
"@antfu/eslint-config": "^6.2.0",
"@types/react": "~19.1.0",
"eslint": "^9.38.0",
"react-native-iconfont-cli": "^2.2.4",
"tailwindcss": "^3.4.17",
"typescript": "~5.9.2"
}
+129 -23
View File
@@ -10,7 +10,7 @@ importers:
dependencies:
'@gluestack-ui/core':
specifier: ^3.0.12
version: 3.0.12(@gluestack-ui/utils@3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1)))(react-native-safe-area-context@5.6.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-svg@15.12.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-web@0.21.2(react-dom@19.2.0(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: 3.0.12(@gluestack-ui/utils@3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1)))(react-native-safe-area-context@5.6.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-svg@15.12.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-web@0.21.2(react-dom@19.2.0(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)
'@gluestack-ui/utils':
specifier: ^3.0.11
version: 3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1))
@@ -19,7 +19,7 @@ importers:
version: 3.0.3
'@legendapp/motion':
specifier: ^2.4.0
version: 2.4.0(nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1)))(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.4.0(nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.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-async-storage/async-storage':
specifier: 2.2.0
version: 2.2.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))
@@ -45,11 +45,11 @@ importers:
specifier: ~3.0.8
version: 3.0.8(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
lucide-react-native:
specifier: ^0.552.0
version: 0.552.0(react-native-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
specifier: ^0.510.0
version: 0.510.0(react-native-svg@15.12.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)
nativewind:
specifier: ^4.2.1
version: 4.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1))
version: 4.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.1))
react:
specifier: 19.1.0
version: 19.1.0
@@ -69,8 +69,8 @@ importers:
specifier: ~4.16.0
version: 4.16.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-svg:
specifier: 15.12.1
version: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
specifier: 15.12.0
version: 15.12.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
zustand:
specifier: ^5.0.8
version: 5.0.8(@types/react@19.1.17)(react@19.1.0)(use-sync-external-store@1.6.0(react@19.1.0))
@@ -84,6 +84,9 @@ importers:
eslint:
specifier: ^9.38.0
version: 9.39.0(jiti@1.21.7)
react-native-iconfont-cli:
specifier: ^2.2.4
version: 2.2.4(react-native-svg@15.12.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)
tailwindcss:
specifier: ^3.4.17
version: 3.4.18(yaml@2.8.1)
@@ -2202,6 +2205,10 @@ packages:
async-limiter@1.0.1:
resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
axios@0.19.2:
resolution: {integrity: sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==}
deprecated: Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410
babel-jest@29.7.0:
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -2448,6 +2455,10 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
colors@1.4.0:
resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==}
engines: {node: '>=0.1.90'}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
@@ -2542,6 +2553,14 @@ packages:
supports-color:
optional: true
debug@3.1.0:
resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@@ -3124,6 +3143,10 @@ packages:
flow-enums-runtime@0.0.6:
resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==}
follow-redirects@1.5.10:
resolution: {integrity: sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==}
engines: {node: '>=4.0'}
fontfaceobserver@2.3.0:
resolution: {integrity: sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==}
@@ -3270,6 +3293,9 @@ packages:
hyphenate-style-name@1.1.0:
resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==}
iconfont-parser@1.0.0:
resolution: {integrity: sha512-3RJceYHEjaqYyeDdfSAb1vP1x1Eb7ZtC9Xwetj+axm85sBlJU7HMvdNLVpwm/3g5eghYOdkQK+epUITZGAIqKQ==}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
@@ -3551,48 +3577,56 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-gnu@1.30.2:
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.27.0:
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.27.0:
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.27.0:
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.27.0:
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
@@ -3674,10 +3708,10 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
lucide-react-native@0.552.0:
resolution: {integrity: sha512-PWTUYyljcpHNql46wbaFk5lm0fdKg+2TnfsN/1KyuWw9McNNWZKkEqhz1k2n7wO/ZWB7jkM8QJCkZZT/SuQykw==}
lucide-react-native@0.510.0:
resolution: {integrity: sha512-Ggy6NyWNcb/Wp9I0Kguwab5FRjr3GYsxNi0Nmy+skur1yj9TKiF2vcXPL7zWkkcgqk8WWKiIvmN3CntWvaDR1w==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
react: ^16.5.1 || ^17.0.0 || ^18.0.0
react-native: '*'
react-native-svg: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
@@ -3995,6 +4029,10 @@ packages:
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
engines: {node: '>= 18'}
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
@@ -4406,6 +4444,14 @@ packages:
react: '*'
react-native: '*'
react-native-iconfont-cli@2.2.4:
resolution: {integrity: sha512-qTjfHG2f/sc3/YKWZJvIJk/SwiTu8C9/SvtoLxRX+GM/6pvOJq0ge6rcV3vTh4s3QJDuNDOD6+a4hGD6vv2vSg==}
hasBin: true
peerDependencies:
react: '*'
react-native: '*'
react-native-svg: '>=9.7.0'
react-native-is-edge-to-edge@1.2.1:
resolution: {integrity: sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==}
peerDependencies:
@@ -4432,8 +4478,8 @@ packages:
react: '*'
react-native: '*'
react-native-svg@15.12.1:
resolution: {integrity: sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==}
react-native-svg@15.12.0:
resolution: {integrity: sha512-iE25PxIJ6V0C6krReLquVw6R0QTsRTmEQc4K2Co3P6zsimU/jltcDBKYDy1h/5j9S/fqmMeXnpM+9LEWKJKI6A==}
peerDependencies:
react: '*'
react-native: '*'
@@ -4927,6 +4973,9 @@ packages:
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -5174,6 +5223,10 @@ packages:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}
xml2js@0.4.23:
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==}
engines: {node: '>=4.0.0'}
xml2js@0.6.0:
resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==}
engines: {node: '>=4.0.0'}
@@ -6360,13 +6413,13 @@ snapshots:
dependencies:
tslib: 2.8.1
'@gluestack-ui/core@3.0.12(@gluestack-ui/utils@3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1)))(react-native-safe-area-context@5.6.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-svg@15.12.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-web@0.21.2(react-dom@19.2.0(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)':
'@gluestack-ui/core@3.0.12(@gluestack-ui/utils@3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1)))(react-native-safe-area-context@5.6.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-svg@15.12.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-web@0.21.2(react-dom@19.2.0(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:
'@gluestack-ui/utils': 3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1))
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-safe-area-context: 5.6.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-svg: 15.12.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-svg: 15.12.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-web: 0.21.2(react-dom@19.2.0(react@19.1.0))(react@19.1.0)
'@gluestack-ui/utils@3.0.11(react-dom@19.2.0(react@19.1.0))(react-native-web@0.21.2(react-dom@19.2.0(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)(tailwindcss@3.4.18(yaml@2.8.1))':
@@ -6517,10 +6570,10 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@legendapp/motion@2.4.0(nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)':
'@legendapp/motion@2.4.0(nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.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:
'@legendapp/tools': 2.0.1(react@19.1.0)
nativewind: 4.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1))
nativewind: 4.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.1))
react: 19.1.0
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
@@ -8212,6 +8265,12 @@ snapshots:
async-limiter@1.0.1: {}
axios@0.19.2:
dependencies:
follow-redirects: 1.5.10
transitivePeerDependencies:
- supports-color
babel-jest@29.7.0(@babel/core@7.28.5):
dependencies:
'@babel/core': 7.28.5
@@ -8516,6 +8575,8 @@ snapshots:
color-convert: 2.0.1
color-string: 1.9.1
colors@1.4.0: {}
commander@12.1.0: {}
commander@2.20.3: {}
@@ -8612,6 +8673,10 @@ snapshots:
dependencies:
ms: 2.0.0
debug@3.1.0:
dependencies:
ms: 2.0.0
debug@3.2.7:
dependencies:
ms: 2.1.3
@@ -9271,6 +9336,12 @@ snapshots:
flow-enums-runtime@0.0.6: {}
follow-redirects@1.5.10:
dependencies:
debug: 3.1.0
transitivePeerDependencies:
- supports-color
fontfaceobserver@2.3.0: {}
foreground-child@3.3.1:
@@ -9402,6 +9473,15 @@ snapshots:
hyphenate-style-name@1.1.0: {}
iconfont-parser@1.0.0:
dependencies:
axios: 0.19.2
colors: 1.4.0
tslib: 1.14.1
xml2js: 0.4.23
transitivePeerDependencies:
- supports-color
ieee754@1.2.1: {}
ignore@5.3.2: {}
@@ -9773,11 +9853,11 @@ snapshots:
dependencies:
yallist: 3.1.1
lucide-react-native@0.552.0(react-native-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
lucide-react-native@0.510.0(react-native-svg@15.12.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-svg: 15.12.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-svg: 15.12.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
magic-string@0.30.21:
dependencies:
@@ -10499,6 +10579,10 @@ snapshots:
dependencies:
minipass: 7.1.2
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
mkdirp@1.0.4: {}
mlly@1.8.0:
@@ -10520,11 +10604,11 @@ snapshots:
nanoid@3.3.11: {}
nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1)):
nativewind@4.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.1)):
dependencies:
comment-json: 4.4.1
debug: 4.4.3
react-native-css-interop: 0.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1))
react-native-css-interop: 0.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.1))
tailwindcss: 3.4.18(yaml@2.8.1)
transitivePeerDependencies:
- react
@@ -10894,7 +10978,7 @@ snapshots:
react-is@19.2.0: {}
react-native-css-interop@0.2.1(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-safe-area-context@5.6.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-svg@15.12.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@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.18(yaml@2.8.1)):
react-native-css-interop@0.2.1(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-safe-area-context@5.6.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-svg@15.12.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)(tailwindcss@3.4.18(yaml@2.8.1)):
dependencies:
'@babel/helper-module-imports': 7.27.1
'@babel/traverse': 7.28.5
@@ -10908,7 +10992,7 @@ snapshots:
tailwindcss: 3.4.18(yaml@2.8.1)
optionalDependencies:
react-native-safe-area-context: 5.6.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-svg: 15.12.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-svg: 15.12.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
transitivePeerDependencies:
- supports-color
@@ -10920,6 +11004,21 @@ snapshots:
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-iconfont-cli@2.2.4(react-native-svg@15.12.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:
colors: 1.4.0
glob: 7.2.3
iconfont-parser: 1.0.0
lodash: 4.17.21
minimist: 1.2.8
mkdirp: 0.5.6
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-svg: 15.12.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
tslib: 1.14.1
transitivePeerDependencies:
- supports-color
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:
react: 19.1.0
@@ -10947,7 +11046,7 @@ snapshots:
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)
warn-once: 0.1.1
react-native-svg@15.12.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-svg@15.12.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:
css-select: 5.2.2
css-tree: 1.1.3
@@ -11518,6 +11617,8 @@ snapshots:
ts-interface-checker@0.1.13: {}
tslib@1.14.1: {}
tslib@2.8.1: {}
type-check@0.4.0:
@@ -11713,6 +11814,11 @@ snapshots:
xml-name-validator@4.0.0: {}
xml2js@0.4.23:
dependencies:
sax: 1.4.1
xmlbuilder: 11.0.1
xml2js@0.6.0:
dependencies:
sax: 1.4.1
@@ -1,5 +1,5 @@
import type { TabbarItem } from '@/components/custom/tabbar'
import CustomTabbar from '@/components/custom/tabbar'
import type { TabbarItem } from '@/components/custom/Tabbar'
import CustomTabbar from '@/components/custom/Tabbar'
import { useToast } from '@/utils/toast'
export default function TabsLayout() {
@@ -1,6 +1,6 @@
import { router, Stack } from 'expo-router'
import { ArrowLeft } from 'lucide-react-native'
import { EmptyState } from '@/components/common/empty-status'
import { EmptyState } from '@/components/common/EmptyStatus'
export default function NotFound() {
return (
@@ -6,7 +6,7 @@ import * as SplashScreen from 'expo-splash-screen'
import { StatusBar } from 'expo-status-bar'
import { RefreshCw } from 'lucide-react-native'
import { useEffect, useState } from 'react'
import { EmptyState } from '@/components/common/empty-status'
import EmptyState from '@/components/common/EmptyStatus'
import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider'
import { useUserStore } from '@/store/user'
import { ToastProviderWrapper } from '@/utils/toast'
@@ -56,7 +56,7 @@ export default function RootLayout() {
// 如果没有 token,则跳转登录页
if (token === null) {
// router.replace('/auth/login')
router.replace('/auth')
}
}
}, [fontsLoaded, storeLoaded, token])
@@ -81,7 +81,7 @@ export default function RootLayout() {
options={{ headerShown: false }}
/>
<Stack.Screen
name="auth/login"
name="auth"
options={{
headerShown: false,
}}
@@ -0,0 +1,26 @@
import type { StepLayoutItem } from '@/components/custom/StepLayout'
import { Slot } from 'expo-router'
import StepLayout from '@/components/custom/StepLayout'
const steps: StepLayoutItem[] = [
{
path: '/auth/index',
showHearder: false,
},
{
title: '登录',
path: '/auth/login',
},
{
title: '注册',
path: '/auth/register',
},
]
export default function AuthLayout() {
return (
<StepLayout steps={steps}>
<Slot />
</StepLayout>
)
}
@@ -0,0 +1,42 @@
import { useRouter } from 'expo-router'
import { Image, Text, View } from 'react-native'
import { Button, ButtonText } from '@/components/ui/button'
export default function AuthIndex() {
const router = useRouter()
function toPath(url: string) {
router.push(url)
}
return (
<View className="flex-1 bg-white items-center justify-center">
<Image
source={require('@/static/images/work.png')}
style={{ width: '100%', height: 280 }}
className="mb-6"
/>
<Image
source={require('@/static/images/logo.png')}
style={{ width: 60, height: 60 }}
className="mb-6"
resizeMode="contain"
/>
<Text className="font-bold text-3xl text-[#333] tracking-wide">
ONEAO
</Text>
<View className="w-full flex flex-col gap-3 mt-12 px-3">
<Button onPress={() => toPath('/auth/login')}>
<ButtonText>登录</ButtonText>
</Button>
<Button action="secondary" onPress={() => toPath('/auth/register')}>
<ButtonText>注册</ButtonText>
</Button>
</View>
</View>
)
}
@@ -1,12 +1,141 @@
import { Text, View } from 'react-native'
import CustomLayout from '@/components/custom/layout'
import { Lock, UserRound } from 'lucide-react-native'
import { useState } from 'react'
import { Image, Text, View } from 'react-native'
import { IconQq, IconWeixin, IconZhiwen } from '@/components/iconfont'
import { Button, ButtonText } from '@/components/ui/button'
import {
Checkbox,
CheckboxIcon,
CheckboxIndicator,
CheckboxLabel,
} from '@/components/ui/checkbox'
import { Divider } from '@/components/ui/divider'
import {
FormControl,
FormControlLabel,
FormControlLabelText,
} from '@/components/ui/form-control'
import { CheckIcon, EyeIcon, EyeOffIcon } from '@/components/ui/icon'
import { Input, InputField, InputIcon, InputSlot } from '@/components/ui/input'
import { useToast } from '@/utils/toast'
interface LoginForm {
username: string
password: string
rememberMe?: boolean
socialType?: 'qq' | 'weixin' | 'fingerprint'
}
export default function AuthLogin() {
const toast = useToast()
const [showPassword, setShowPassword] = useState(false)
const [form, setForm] = useState<LoginForm>({
username: '',
password: '',
rememberMe: true,
})
const defaultLogin = () => {
if (form.username === '') {
toast.show({
title: '账号不能为空!',
action: 'error',
})
return
}
if (form.password === '') {
toast.show({
title: '密码不能为空!',
action: 'error',
})
}
//
}
return (
<CustomLayout>
<View>
<Text>登录</Text>
<View className="flex flex-col items-center px-6 h-full">
<Image
source={require('@/static/images/logo.png')}
style={{ width: 120, height: 120 }}
className="my-12"
/>
<FormControl size="md" className="w-full mb-6">
<FormControlLabel>
<FormControlLabelText>账号</FormControlLabelText>
</FormControlLabel>
<Input size="md">
<InputSlot className="pl-3">
<InputIcon as={UserRound} />
</InputSlot>
<InputField
placeholder="请输入账号"
onChangeText={text => setForm(prev => ({ ...prev, username: text }))}
/>
</Input>
</FormControl>
<FormControl size="md" className="w-full mb-6">
<FormControlLabel>
<FormControlLabelText>密码</FormControlLabelText>
</FormControlLabel>
<Input size="md">
<InputSlot className="pl-3">
<InputIcon as={Lock} />
</InputSlot>
<InputField
type={showPassword ? 'text' : 'password'}
placeholder="请输入密码"
onChangeText={text => setForm(prev => ({ ...prev, password: text }))}
/>
<InputSlot className="pr-3" onPress={() => setShowPassword(prev => !prev)}>
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon} />
</InputSlot>
</Input>
</FormControl>
<View className="w-full flex-row justify-between items-center mb-6">
<Checkbox
value="rememberMe"
isChecked={form.rememberMe}
onChange={checked =>
setForm(prev => ({ ...prev, rememberMe: checked }))}
>
<CheckboxIndicator>
<CheckboxIcon as={CheckIcon} />
</CheckboxIndicator>
<CheckboxLabel>记住我</CheckboxLabel>
</Checkbox>
<Text className="text-blue-500">
忘记密码?
</Text>
</View>
<Button className="w-full" onPress={() => defaultLogin()}>
<ButtonText>登录</ButtonText>
</Button>
<View className="flex-row items-center my-8 w-full">
<View className="flex-1">
<Divider />
</View>
<Text className="mx-3 text-gray-500 text-sm">社交账号</Text>
<View className="flex-1">
<Divider />
</View>
</View>
<View className="w-full flex-row justify-between items-center">
<IconQq size={32} />
<IconWeixin size={32} />
<IconZhiwen size={32} />
</View>
</View>
</CustomLayout>
)
}
@@ -0,0 +1,10 @@
import { Text, View } from 'react-native'
export default function Register() {
return (
<View style={{ minHeight: 1000 }}>
<Text>测试内容</Text>
<View style={{ height: 800, backgroundColor: 'red' }} />
</View>
)
}
@@ -10,7 +10,7 @@ interface EmptyStateProps {
onButtonPress: () => void
}
export function EmptyState({
export default function EmptyState({
image,
title,
description,
@@ -0,0 +1,79 @@
import { Ionicons } from '@expo/vector-icons'
import { usePathname, useRouter } from 'expo-router'
import { Image, Pressable, ScrollView, Text, View } from 'react-native'
import Animated, { SlideInRight } from 'react-native-reanimated'
import { SafeAreaView } from 'react-native-safe-area-context'
export interface StepLayoutItem {
path: string // 步骤路径
title?: string // 步骤标题
onBack?: () => void // 可选的返回按钮回调
showHearder?: boolean // 是否显示 header,单独放在每个步骤中
headerRight?: React.ReactNode
}
interface StepLayoutProps {
steps: StepLayoutItem[] // 步骤列表
children: React.ReactNode // 子内容
showHearder?: boolean // 控制整体 header 是否显示
}
export default function StepLayout({ steps, children, showHearder = true }: StepLayoutProps) {
const router = useRouter()
const pathname = usePathname()
// 是否能返回
const canGoBack = router.canGoBack()
// 当前步骤
const currentStep = steps.find(step => step.path === pathname) ?? steps[0]
// 是否显示header
const headerVisible = showHearder !== false && currentStep.showHearder !== false
return (
<SafeAreaView style={{ flex: 1 }}>
<Animated.View
key={pathname}
entering={SlideInRight.duration(300)}
style={{ flex: 1 }}
>
{headerVisible && (
<View className="flex-row items-center h-12 px-2 ">
<Pressable
onPress={canGoBack ? (currentStep.onBack ?? (() => router.back())) : undefined}
style={{ opacity: canGoBack ? 1 : 0 }}
>
<Ionicons
name="arrow-back"
size={22}
/>
</Pressable>
<Text className="flex-1 text-center text-lg font-semibold">
{currentStep.title}
</Text>
<View className="h-full flex items-center justify-center">
{currentStep.headerRight ?? (
<Image
source={require('@/static/images/logo.png')}
style={{ width: 22, height: 22 }}
/>
)}
</View>
</View>
)}
<ScrollView
contentContainerStyle={{ flexGrow: 1 }}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
>
<View style={{ flex: 1 }}>{children}</View>
</ScrollView>
</Animated.View>
</SafeAreaView>
)
}
@@ -1,21 +0,0 @@
import { useRouter } from 'expo-router'
// components/Layout.tsx
import { Pressable, Text, View } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
interface LayoutProps {
title: string
children: React.ReactNode
showBack?: boolean
right?: React.ReactNode
}
export default function CustomLayout({ title, children, showBack = true, right }: LayoutProps) {
const router = useRouter()
return (
<View className="flex-1">
{children}
</View>
)
}
@@ -4,7 +4,7 @@ import { icons } from 'lucide-react-native'
import { useEffect, useState } from 'react'
import { Pressable, View } from 'react-native'
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
import Animated, { SlideInLeft, SlideInRight, SlideOutLeft, SlideOutRight, useAnimatedStyle, useSharedValue, withSequence, withTiming } from 'react-native-reanimated'
import Animated, { SlideInLeft, SlideInRight, useAnimatedStyle, useSharedValue, withSequence, withTiming } from 'react-native-reanimated'
import { scheduleOnRN } from 'react-native-worklets'
interface AppTabbarProps {
@@ -0,0 +1,69 @@
/* eslint-disable */
/* tslint:disable */
import React from 'react';
import type { FunctionComponent } from 'react';
import type { ViewProps } from 'react-native';
import { Svg, GProps, Path } from 'react-native-svg';
import { getIconColor } from './helper';
// ✅ 关键改动:排除 GProps.color
interface Props extends Omit<GProps, 'color'>, ViewProps {
size?: number;
color?: string | string[];
}
const IconQq: FunctionComponent<Props> = ({
size = 18,
color,
...rest
}) => {
return (
<Svg viewBox="0 0 1024 1024" width={size} height={size} {...rest}>
<Path
d="M511.09761 957.257c-80.159 0-153.737-25.019-201.11-62.386-24.057 6.702-54.831 17.489-74.252 30.864-16.617 11.439-14.546 23.106-11.55 27.816 13.15 20.689 225.583 13.211 286.912 6.767v-3.061z"
fill={getIconColor(color, 0, '#FAAD08')}
/>
<Path
d="M496.65061 957.257c80.157 0 153.737-25.019 201.11-62.386 24.057 6.702 54.83 17.489 74.253 30.864 16.616 11.439 14.543 23.106 11.55 27.816-13.15 20.689-225.584 13.211-286.914 6.767v-3.061z"
fill={getIconColor(color, 1, '#FAAD08')}
/>
<Path
d="M497.12861 474.524c131.934-0.876 237.669-25.783 273.497-35.34 8.541-2.28 13.11-6.364 13.11-6.364 0.03-1.172 0.542-20.952 0.542-31.155C784.27761 229.833 701.12561 57.173 496.64061 57.162 292.15661 57.173 209.00061 229.832 209.00061 401.665c0 10.203 0.516 29.983 0.547 31.155 0 0 3.717 3.821 10.529 5.67 33.078 8.98 140.803 35.139 276.08 36.034h0.972z"
fill={getIconColor(color, 2, '#000000')}
/>
<Path
d="M860.28261 619.782c-8.12-26.086-19.204-56.506-30.427-85.72 0 0-6.456-0.795-9.718 0.148-100.71 29.205-222.773 47.818-315.792 46.695h-0.962C410.88561 582.017 289.65061 563.617 189.27961 534.698 185.44461 533.595 177.87261 534.063 177.87261 534.063 166.64961 563.276 155.56661 593.696 147.44761 619.782 108.72961 744.168 121.27261 795.644 130.82461 796.798c20.496 2.474 79.78-93.637 79.78-93.637 0 97.66 88.324 247.617 290.576 248.996a718.01 718.01 0 0 1 5.367 0C708.80161 950.778 797.12261 800.822 797.12261 703.162c0 0 59.284 96.111 79.783 93.637 9.55-1.154 22.093-52.63-16.623-177.017"
fill={getIconColor(color, 3, '#000000')}
/>
<Path
d="M434.38261 316.917c-27.9 1.24-51.745-30.106-53.24-69.956-1.518-39.877 19.858-73.207 47.764-74.454 27.875-1.224 51.703 30.109 53.218 69.974 1.527 39.877-19.853 73.2-47.742 74.436m206.67-69.956c-1.494 39.85-25.34 71.194-53.24 69.956-27.888-1.238-49.269-34.559-47.742-74.435 1.513-39.868 25.341-71.201 53.216-69.974 27.909 1.247 49.285 34.576 47.767 74.453"
fill={getIconColor(color, 4, '#FFFFFF')}
/>
<Path
d="M683.94261 368.627c-7.323-17.609-81.062-37.227-172.353-37.227h-0.98c-91.29 0-165.031 19.618-172.352 37.227a6.244 6.244 0 0 0-0.535 2.505c0 1.269 0.393 2.414 1.006 3.386 6.168 9.765 88.054 58.018 171.882 58.018h0.98c83.827 0 165.71-48.25 171.881-58.016a6.352 6.352 0 0 0 1.002-3.395c0-0.897-0.2-1.736-0.531-2.498"
fill={getIconColor(color, 5, '#FAAD08')}
/>
<Path
d="M467.63161 256.377c1.26 15.886-7.377 30-19.266 31.542-11.907 1.544-22.569-10.083-23.836-25.978-1.243-15.895 7.381-30.008 19.25-31.538 11.927-1.549 22.607 10.088 23.852 25.974m73.097 7.935c2.533-4.118 19.827-25.77 55.62-17.886 9.401 2.07 13.75 5.116 14.668 6.316 1.355 1.77 1.726 4.29 0.352 7.684-2.722 6.725-8.338 6.542-11.454 5.226-2.01-0.85-26.94-15.889-49.905 6.553-1.579 1.545-4.405 2.074-7.085 0.242-2.678-1.834-3.786-5.553-2.196-8.135"
fill={getIconColor(color, 6, '#000000')}
/>
<Path
d="M504.33261 584.495h-0.967c-63.568 0.752-140.646-7.504-215.286-21.92-6.391 36.262-10.25 81.838-6.936 136.196 8.37 137.384 91.62 223.736 220.118 224.996H506.48461c128.498-1.26 211.748-87.612 220.12-224.996 3.314-54.362-0.547-99.938-6.94-136.203-74.654 14.423-151.745 22.684-215.332 21.927"
fill={getIconColor(color, 7, '#FFFFFF')}
/>
<Path
d="M323.27461 577.016v137.468s64.957 12.705 130.031 3.91V591.59c-41.225-2.262-85.688-7.304-130.031-14.574"
fill={getIconColor(color, 8, '#EB1C26')}
/>
<Path
d="M788.09761 432.536s-121.98 40.387-283.743 41.539h-0.962c-161.497-1.147-283.328-41.401-283.744-41.539l-40.854 106.952c102.186 32.31 228.837 53.135 324.598 51.926l0.96-0.002c95.768 1.216 222.4-19.61 324.6-51.924l-40.855-106.952z"
fill={getIconColor(color, 9, '#EB1C26')}
/>
</Svg>
);
};
export default React.memo(IconQq);
@@ -0,0 +1,37 @@
/* eslint-disable */
/* tslint:disable */
import React from 'react';
import type { FunctionComponent } from 'react';
import type { ViewProps } from 'react-native';
import { Svg, GProps, Path } from 'react-native-svg';
import { getIconColor } from './helper';
// ✅ 关键改动:排除 GProps.color
interface Props extends Omit<GProps, 'color'>, ViewProps {
size?: number;
color?: string | string[];
}
const IconWeixin: FunctionComponent<Props> = ({
size = 18,
color,
...rest
}) => {
return (
<Svg viewBox="0 0 1024 1024" width={size} height={size} {...rest}>
<Path
d="M1024 619.52c0-143.36-138.24-256-307.2-256s-307.2 112.64-307.2 256 138.24 256 307.2 256c30.72 0 61.44-5.12 92.16-10.24l97.28 51.2-25.6-76.8c87.04-51.2 143.36-128 143.36-220.16z m-414.72-40.96c-30.72 0-51.2-20.48-51.2-51.2s20.48-51.2 51.2-51.2 51.2 20.48 51.2 51.2c0 25.6-25.6 51.2-51.2 51.2z m209.92 0c-30.72 0-51.2-20.48-51.2-51.2s20.48-51.2 51.2-51.2 51.2 20.48 51.2 51.2c0 25.6-25.6 51.2-51.2 51.2z"
fill={getIconColor(color, 0, '#4CBF00')}
/>
<Path
d="M358.4 609.28c0-158.72 153.6-286.72 348.16-286.72h15.36c-40.96-133.12-179.2-235.52-353.28-235.52-204.8 0-368.64 138.24-368.64 307.2 0 107.52 66.56 204.8 168.96 256l-30.72 92.16L256 686.08c35.84 10.24 71.68 15.36 112.64 15.36h10.24c-15.36-30.72-20.48-61.44-20.48-92.16z m138.24-414.72c35.84 0 66.56 30.72 66.56 66.56s-30.72 66.56-66.56 66.56C460.8 322.56 430.08 291.84 430.08 256S460.8 194.56 496.64 194.56zM245.76 322.56c-35.84 0-61.44-30.72-61.44-66.56s30.72-66.56 66.56-66.56 61.44 30.72 61.44 66.56-30.72 66.56-66.56 66.56z"
fill={getIconColor(color, 1, '#4CBF00')}
/>
</Svg>
);
};
export default React.memo(IconWeixin);
@@ -0,0 +1,45 @@
/* eslint-disable */
/* tslint:disable */
import React from 'react';
import type { FunctionComponent } from 'react';
import type { ViewProps } from 'react-native';
import { Svg, GProps, Path } from 'react-native-svg';
import { getIconColor } from './helper';
// ✅ 关键改动:排除 GProps.color
interface Props extends Omit<GProps, 'color'>, ViewProps {
size?: number;
color?: string | string[];
}
const IconZhiwen: FunctionComponent<Props> = ({
size = 18,
color,
...rest
}) => {
return (
<Svg viewBox="0 0 1024 1024" width={size} height={size} {...rest}>
<Path
d="M671.232 309.248c-3.584-1.536-7.168-2.048-10.752-2.048-11.776 0-22.528 7.168-27.136 18.432-5.632 14.848 1.536 31.744 16.384 37.888 68.096 26.624 126.464 72.704 167.424 133.632 41.472 60.416 62.976 131.584 62.976 204.8 0 10.24 5.632 19.968 14.336 25.088 9.216 5.12 19.968 5.12 29.184 0 9.216-5.12 14.336-14.848 14.336-25.088 1.024-175.104-103.936-329.216-266.752-392.704zM523.776 309.76c0-15.872-13.312-29.184-29.184-29.184-232.448 0-421.376 188.928-421.376 421.376 0 10.752 5.12 20.992 14.336 26.112 9.216 5.12 20.48 5.12 29.696 0 9.216-5.12 14.848-15.36 14.336-25.6 0-200.704 162.816-363.52 363.008-363.52 15.872-0.512 29.184-13.312 29.184-29.184z"
fill={getIconColor(color, 0, '#2E77ED')}
/>
<Path
d="M506.368 438.272c-148.48 0-268.8 120.832-268.8 268.8v130.56c0 10.24 5.632 19.968 14.336 25.088 9.216 5.12 19.968 5.12 29.184 0 9.216-5.12 14.336-14.848 14.336-25.088v-130.56c-1.024-75.776 38.912-146.432 104.448-184.832 32.768-18.944 69.632-28.672 105.984-28.672 36.864 0 73.216 9.728 105.984 28.672 65.536 38.4 105.472 109.056 104.448 184.832v152.576c0 15.872 13.312 29.184 29.184 29.184s29.184-13.312 29.184-29.184v-152.576c0.512-147.968-120.32-268.8-268.288-268.8z"
fill={getIconColor(color, 1, '#FFBB12')}
/>
<Path
d="M945.664 313.856c-109.056-130.048-268.8-204.8-438.784-204.8h-1.024c-162.304 0-317.44 69.12-425.984 189.44-7.168 7.68-9.216 18.432-6.144 28.672 3.072 9.728 11.264 17.408 21.504 19.456 10.24 2.048 20.992-1.024 27.648-9.216 97.28-108.544 236.544-170.496 382.464-170.496h1.024c153.088 0 297.472 67.584 395.264 185.344 10.24 12.288 28.672 13.824 40.96 3.584 12.288-10.24 13.824-28.672 3.584-40.96l-0.512-1.024z"
fill={getIconColor(color, 2, '#2E77ED')}
/>
<Path
d="M553.472 623.616c-29.184-16.896-65.536-16.896-94.72 0-29.184 16.896-47.104 48.128-47.104 81.408l0.512 7.68c0.512 16.896 1.024 124.416 1.024 186.88 0 15.872 13.312 29.184 29.184 29.184 7.68 0 15.36-3.072 20.48-8.704 5.632-5.632 8.704-12.8 8.704-20.48-0.512-112.64-1.024-176.128-1.024-188.416l-0.512-7.168v-0.512c0-18.432 16.896-34.304 36.352-34.304 9.728 0 18.944 4.096 25.6 10.752 6.656 6.656 10.752 15.872 10.752 25.6v194.048c0 10.24 5.632 19.968 14.336 25.088 11.264 6.656 25.088 4.608 34.816-4.096 5.632-5.632 9.216-13.824 9.216-22.528v-193.024c-0.512-32.768-18.432-64.512-47.616-81.408z"
fill={getIconColor(color, 3, '#FFBB12')}
/>
</Svg>
);
};
export default React.memo(IconZhiwen);
@@ -0,0 +1,12 @@
/* tslint:disable */
/* eslint-disable */
export const getIconColor = (color: string | string[] | undefined, index: number, defaultColor: string) => {
return color
? (
typeof color === 'string'
? color
: color[index] || defaultColor
)
: defaultColor;
};
@@ -0,0 +1,37 @@
/* tslint:disable */
/* eslint-disable */
import React, { FunctionComponent } from 'react';
import { ViewProps } from 'react-native';
import { GProps } from 'react-native-svg';
import IconWeixin from './IconWeixin';
import IconZhiwen from './IconZhiwen';
import IconQq from './IconQq';
export { default as IconWeixin } from './IconWeixin';
export { default as IconZhiwen } from './IconZhiwen';
export { default as IconQq } from './IconQq';
export type IconNames = 'weixin' | 'zhiwen' | 'QQ';
interface Props extends GProps, ViewProps {
name: IconNames;
size?: number;
color?: string | string[];
}
let IconFont: FunctionComponent<Props> = ({ name, ...rest }) => {
switch (name) {
case 'weixin':
return <IconWeixin key="1" {...rest} />;
case 'zhiwen':
return <IconZhiwen key="2" {...rest} />;
case 'QQ':
return <IconQq key="3" {...rest} />;
}
return null;
};
IconFont = React.memo ? React.memo(IconFont) : IconFont;
export default IconFont;
@@ -0,0 +1,242 @@
'use client';
import React from 'react';
import { createCheckbox } from '@gluestack-ui/core/checkbox/creator';
import { View, Pressable, Text, Platform } from 'react-native';
import type { TextProps, ViewProps } from 'react-native';
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import {
PrimitiveIcon,
IPrimitiveIcon,
UIIcon,
} from '@gluestack-ui/core/icon/creator';
import {
withStyleContext,
useStyleContext,
} from '@gluestack-ui/utils/nativewind-utils';
import { cssInterop } from 'nativewind';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
const IndicatorWrapper = React.forwardRef<
React.ComponentRef<typeof View>,
ViewProps
>(function IndicatorWrapper({ ...props }, ref) {
return <View {...props} ref={ref} />;
});
const LabelWrapper = React.forwardRef<
React.ComponentRef<typeof Text>,
TextProps
>(function LabelWrapper({ ...props }, ref) {
return <Text {...props} ref={ref} />;
});
const IconWrapper = React.forwardRef<
React.ComponentRef<typeof PrimitiveIcon>,
IPrimitiveIcon
>(function IconWrapper({ ...props }, ref) {
return <UIIcon {...props} ref={ref} />;
});
const SCOPE = 'CHECKBOX';
const UICheckbox = createCheckbox({
// @ts-expect-error : internal implementation for r-19/react-native-web
Root:
Platform.OS === 'web'
? withStyleContext(View, SCOPE)
: withStyleContext(Pressable, SCOPE),
Group: View,
Icon: IconWrapper,
Label: LabelWrapper,
Indicator: IndicatorWrapper,
});
cssInterop(PrimitiveIcon, {
className: {
target: 'style',
nativeStyleToProp: {
height: true,
width: true,
fill: true,
color: 'classNameColor',
stroke: true,
},
},
});
const checkboxStyle = tva({
base: 'group/checkbox flex-row items-center justify-start web:cursor-pointer data-[disabled=true]:cursor-not-allowed',
variants: {
size: {
lg: 'gap-2',
md: 'gap-2',
sm: 'gap-1.5',
},
},
});
const checkboxIndicatorStyle = tva({
base: 'justify-center items-center border-outline-400 bg-transparent rounded web:data-[focus-visible=true]:outline-none web:data-[focus-visible=true]:ring-2 web:data-[focus-visible=true]:ring-indicator-primary data-[checked=true]:bg-primary-600 data-[checked=true]:border-primary-600 data-[hover=true]:data-[checked=false]:border-outline-500 data-[hover=true]:bg-transparent data-[hover=true]:data-[invalid=true]:border-error-700 data-[hover=true]:data-[checked=true]:bg-primary-700 data-[hover=true]:data-[checked=true]:border-primary-700 data-[hover=true]:data-[checked=true]:data-[disabled=true]:border-primary-600 data-[hover=true]:data-[checked=true]:data-[disabled=true]:bg-primary-600 data-[hover=true]:data-[checked=true]:data-[disabled=true]:opacity-40 data-[hover=true]:data-[checked=true]:data-[disabled=true]:data-[invalid=true]:border-error-700 data-[hover=true]:data-[disabled=true]:border-outline-400 data-[hover=true]:data-[disabled=true]:data-[invalid=true]:border-error-700 data-[active=true]:data-[checked=true]:bg-primary-800 data-[active=true]:data-[checked=true]:border-primary-800 data-[invalid=true]:border-error-700 data-[disabled=true]:opacity-40',
parentVariants: {
size: {
lg: 'w-6 h-6 border-[3px]',
md: 'w-5 h-5 border-2',
sm: 'w-4 h-4 border-2',
},
},
});
const checkboxLabelStyle = tva({
base: 'text-typography-600 data-[checked=true]:text-typography-900 data-[hover=true]:text-typography-900 data-[hover=true]:data-[checked=true]:text-typography-900 data-[hover=true]:data-[checked=true]:data-[disabled=true]:text-typography-900 data-[hover=true]:data-[disabled=true]:text-typography-400 data-[active=true]:text-typography-900 data-[active=true]:data-[checked=true]:text-typography-900 data-[disabled=true]:opacity-40 web:select-none',
parentVariants: {
size: {
lg: 'text-lg',
md: 'text-base',
sm: 'text-sm',
},
},
});
const checkboxIconStyle = tva({
base: 'text-typography-50 fill-none',
parentVariants: {
size: {
sm: 'h-3 w-3',
md: 'h-4 w-4',
lg: 'h-5 w-5',
},
},
});
const CheckboxGroup = UICheckbox.Group;
type ICheckboxProps = React.ComponentPropsWithoutRef<typeof UICheckbox> &
VariantProps<typeof checkboxStyle>;
const Checkbox = React.forwardRef<
React.ComponentRef<typeof UICheckbox>,
ICheckboxProps
>(function Checkbox({ className, size = 'md', ...props }, ref) {
return (
<UICheckbox
className={checkboxStyle({
class: className,
size,
})}
{...props}
context={{
size,
}}
ref={ref}
/>
);
});
type ICheckboxIndicatorProps = React.ComponentPropsWithoutRef<
typeof UICheckbox.Indicator
> &
VariantProps<typeof checkboxIndicatorStyle>;
const CheckboxIndicator = React.forwardRef<
React.ComponentRef<typeof UICheckbox.Indicator>,
ICheckboxIndicatorProps
>(function CheckboxIndicator({ className, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<UICheckbox.Indicator
className={checkboxIndicatorStyle({
parentVariants: {
size: parentSize,
},
class: className,
})}
{...props}
ref={ref}
/>
);
});
type ICheckboxLabelProps = React.ComponentPropsWithoutRef<
typeof UICheckbox.Label
> &
VariantProps<typeof checkboxLabelStyle>;
const CheckboxLabel = React.forwardRef<
React.ComponentRef<typeof UICheckbox.Label>,
ICheckboxLabelProps
>(function CheckboxLabel({ className, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<UICheckbox.Label
className={checkboxLabelStyle({
parentVariants: {
size: parentSize,
},
class: className,
})}
{...props}
ref={ref}
/>
);
});
type ICheckboxIconProps = React.ComponentPropsWithoutRef<
typeof UICheckbox.Icon
> &
VariantProps<typeof checkboxIconStyle>;
const CheckboxIcon = React.forwardRef<
React.ComponentRef<typeof UICheckbox.Icon>,
ICheckboxIconProps
>(function CheckboxIcon({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
if (typeof size === 'number') {
return (
<UICheckbox.Icon
ref={ref}
{...props}
className={checkboxIconStyle({ class: className })}
size={size}
/>
);
} else if (
(props.height !== undefined || props.width !== undefined) &&
size === undefined
) {
return (
<UICheckbox.Icon
ref={ref}
{...props}
className={checkboxIconStyle({ class: className })}
/>
);
}
return (
<UICheckbox.Icon
className={checkboxIconStyle({
parentVariants: {
size: parentSize,
},
size,
class: className,
})}
{...props}
ref={ref}
/>
);
});
Checkbox.displayName = 'Checkbox';
CheckboxIndicator.displayName = 'CheckboxIndicator';
CheckboxLabel.displayName = 'CheckboxLabel';
CheckboxIcon.displayName = 'CheckboxIcon';
export {
Checkbox,
CheckboxIndicator,
CheckboxLabel,
CheckboxIcon,
CheckboxGroup,
};
@@ -0,0 +1,40 @@
'use client';
import React from 'react';
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import { Platform, View } from 'react-native';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
const dividerStyle = tva({
base: 'bg-background-200',
variants: {
orientation: {
vertical: 'w-px h-full',
horizontal: 'h-px w-full',
},
},
});
type IUIDividerProps = React.ComponentPropsWithoutRef<typeof View> &
VariantProps<typeof dividerStyle>;
const Divider = React.forwardRef<
React.ComponentRef<typeof View>,
IUIDividerProps
>(function Divider({ className, orientation = 'horizontal', ...props }, ref) {
return (
<View
ref={ref}
{...props}
aria-orientation={orientation}
role={Platform.OS === 'web' ? 'separator' : undefined}
className={dividerStyle({
orientation,
class: className,
})}
/>
);
});
Divider.displayName = 'Divider';
export { Divider };
@@ -0,0 +1,468 @@
'use client';
import { Text, View } from 'react-native';
import React from 'react';
import { createFormControl } from '@gluestack-ui/core/form-control/creator';
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import {
withStyleContext,
useStyleContext,
} from '@gluestack-ui/utils/nativewind-utils';
import { cssInterop } from 'nativewind';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
import { PrimitiveIcon, UIIcon } from '@gluestack-ui/core/icon/creator';
const SCOPE = 'FORM_CONTROL';
const formControlStyle = tva({
base: 'flex flex-col',
variants: {
size: {
sm: '',
md: '',
lg: '',
},
},
});
const formControlErrorIconStyle = tva({
base: 'text-error-700 fill-none',
variants: {
size: {
'2xs': 'h-3 w-3',
'xs': 'h-3.5 w-3.5',
'sm': 'h-4 w-4',
'md': 'h-[18px] w-[18px]',
'lg': 'h-5 w-5',
'xl': 'h-6 w-6',
},
},
});
const formControlErrorStyle = tva({
base: 'flex flex-row justify-start items-center mt-1 gap-1',
});
const formControlErrorTextStyle = tva({
base: 'text-error-700',
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});
const formControlHelperStyle = tva({
base: 'flex flex-row justify-start items-center mt-1',
});
const formControlHelperTextStyle = tva({
base: 'text-typography-500',
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-xs',
'md': 'text-sm',
'lg': 'text-base',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});
const formControlLabelStyle = tva({
base: 'flex flex-row justify-start items-center mb-1',
});
const formControlLabelTextStyle = tva({
base: 'font-medium text-typography-900',
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});
const formControlLabelAstrickStyle = tva({
base: 'font-medium text-typography-900',
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});
type IFormControlLabelAstrickProps = React.ComponentPropsWithoutRef<
typeof Text
> &
VariantProps<typeof formControlLabelAstrickStyle>;
const FormControlLabelAstrick = React.forwardRef<
React.ComponentRef<typeof Text>,
IFormControlLabelAstrickProps
>(function FormControlLabelAstrick({ className, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<Text
ref={ref}
className={formControlLabelAstrickStyle({
parentVariants: { size: parentSize },
class: className,
})}
{...props}
/>
);
});
export const UIFormControl = createFormControl({
Root: withStyleContext(View, SCOPE),
Error: View,
ErrorText: Text,
ErrorIcon: UIIcon,
Label: View,
LabelText: Text,
LabelAstrick: FormControlLabelAstrick,
Helper: View,
HelperText: Text,
});
cssInterop(PrimitiveIcon, {
className: {
target: 'style',
nativeStyleToProp: {
height: true,
width: true,
fill: true,
color: true,
stroke: true,
},
},
});
type IFormControlProps = React.ComponentProps<typeof UIFormControl> &
VariantProps<typeof formControlStyle>;
const FormControl = React.forwardRef<
React.ComponentRef<typeof UIFormControl>,
IFormControlProps
>(function FormControl({ className, size = 'md', ...props }, ref) {
return (
<UIFormControl
ref={ref}
className={formControlStyle({ size, class: className })}
{...props}
context={{ size }}
/>
);
});
type IFormControlErrorProps = React.ComponentProps<typeof UIFormControl.Error> &
VariantProps<typeof formControlErrorStyle>;
const FormControlError = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Error>,
IFormControlErrorProps
>(function FormControlError({ className, ...props }, ref) {
return (
<UIFormControl.Error
ref={ref}
className={formControlErrorStyle({ class: className })}
{...props}
/>
);
});
type IFormControlErrorTextProps = React.ComponentProps<
typeof UIFormControl.Error.Text
> &
VariantProps<typeof formControlErrorTextStyle>;
const FormControlErrorText = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Error.Text>,
IFormControlErrorTextProps
>(function FormControlErrorText({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<UIFormControl.Error.Text
className={formControlErrorTextStyle({
parentVariants: { size: parentSize },
size,
class: className,
})}
ref={ref}
{...props}
/>
);
});
type IFormControlErrorIconProps = React.ComponentProps<
typeof UIFormControl.Error.Icon
> &
VariantProps<typeof formControlErrorIconStyle> & {
height?: number;
width?: number;
};
const FormControlErrorIcon = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Error.Icon>,
IFormControlErrorIconProps
>(function FormControlErrorIcon({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
if (typeof size === 'number') {
return (
<UIFormControl.Error.Icon
ref={ref}
{...props}
className={formControlErrorIconStyle({ class: className })}
size={size}
/>
);
} else if (
(props.height !== undefined || props.width !== undefined) &&
size === undefined
) {
return (
<UIFormControl.Error.Icon
ref={ref}
{...props}
className={formControlErrorIconStyle({ class: className })}
/>
);
}
return (
<UIFormControl.Error.Icon
className={formControlErrorIconStyle({
parentVariants: { size: parentSize },
size,
class: className,
})}
{...props}
/>
);
});
type IFormControlLabelProps = React.ComponentProps<typeof UIFormControl.Label> &
VariantProps<typeof formControlLabelStyle>;
const FormControlLabel = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Label>,
IFormControlLabelProps
>(function FormControlLabel({ className, ...props }, ref) {
return (
<UIFormControl.Label
ref={ref}
className={formControlLabelStyle({ class: className })}
{...props}
/>
);
});
type IFormControlLabelTextProps = React.ComponentProps<
typeof UIFormControl.Label.Text
> &
VariantProps<typeof formControlLabelTextStyle>;
const FormControlLabelText = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Label.Text>,
IFormControlLabelTextProps
>(function FormControlLabelText({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<UIFormControl.Label.Text
className={formControlLabelTextStyle({
parentVariants: { size: parentSize },
size,
class: className,
})}
ref={ref}
{...props}
/>
);
});
type IFormControlHelperProps = React.ComponentProps<
typeof UIFormControl.Helper
> &
VariantProps<typeof formControlHelperStyle>;
const FormControlHelper = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Helper>,
IFormControlHelperProps
>(function FormControlHelper({ className, ...props }, ref) {
return (
<UIFormControl.Helper
ref={ref}
className={formControlHelperStyle({
class: className,
})}
{...props}
/>
);
});
type IFormControlHelperTextProps = React.ComponentProps<
typeof UIFormControl.Helper.Text
> &
VariantProps<typeof formControlHelperTextStyle>;
const FormControlHelperText = React.forwardRef<
React.ComponentRef<typeof UIFormControl.Helper.Text>,
IFormControlHelperTextProps
>(function FormControlHelperText({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
return (
<UIFormControl.Helper.Text
className={formControlHelperTextStyle({
parentVariants: { size: parentSize },
size,
class: className,
})}
ref={ref}
{...props}
/>
);
});
FormControl.displayName = 'FormControl';
FormControlError.displayName = 'FormControlError';
FormControlErrorText.displayName = 'FormControlErrorText';
FormControlErrorIcon.displayName = 'FormControlErrorIcon';
FormControlLabel.displayName = 'FormControlLabel';
FormControlLabelText.displayName = 'FormControlLabelText';
FormControlLabelAstrick.displayName = 'FormControlLabelAstrick';
FormControlHelper.displayName = 'FormControlHelper';
FormControlHelperText.displayName = 'FormControlHelperText';
export {
FormControl,
FormControlError,
FormControlErrorText,
FormControlErrorIcon,
FormControlLabel,
FormControlLabelText,
FormControlLabelAstrick,
FormControlHelper,
FormControlHelperText,
};
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,217 @@
'use client';
import React from 'react';
import { createInput } from '@gluestack-ui/core/input/creator';
import { View, Pressable, TextInput } from 'react-native';
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import {
withStyleContext,
useStyleContext,
} from '@gluestack-ui/utils/nativewind-utils';
import { cssInterop } from 'nativewind';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
import { PrimitiveIcon, UIIcon } from '@gluestack-ui/core/icon/creator';
const SCOPE = 'INPUT';
const UIInput = createInput({
Root: withStyleContext(View, SCOPE),
Icon: UIIcon,
Slot: Pressable,
Input: TextInput,
});
cssInterop(PrimitiveIcon, {
className: {
target: 'style',
nativeStyleToProp: {
height: true,
width: true,
fill: true,
color: 'classNameColor',
stroke: true,
},
},
});
const inputStyle = tva({
base: 'border-background-300 flex-row overflow-hidden content-center data-[hover=true]:border-outline-400 data-[focus=true]:border-primary-700 data-[focus=true]:hover:border-primary-700 data-[disabled=true]:opacity-40 data-[disabled=true]:hover:border-background-300 items-center',
variants: {
size: {
xl: 'h-12',
lg: 'h-11',
md: 'h-10',
sm: 'h-9',
},
variant: {
underlined:
'rounded-none border-b data-[invalid=true]:border-b-2 data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700',
outline:
'rounded border data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700 data-[focus=true]:web:ring-1 data-[focus=true]:web:ring-inset data-[focus=true]:web:ring-indicator-primary data-[invalid=true]:web:ring-1 data-[invalid=true]:web:ring-inset data-[invalid=true]:web:ring-indicator-error data-[invalid=true]:data-[focus=true]:hover:web:ring-1 data-[invalid=true]:data-[focus=true]:hover:web:ring-inset data-[invalid=true]:data-[focus=true]:hover:web:ring-indicator-error data-[invalid=true]:data-[disabled=true]:hover:web:ring-1 data-[invalid=true]:data-[disabled=true]:hover:web:ring-inset data-[invalid=true]:data-[disabled=true]:hover:web:ring-indicator-error',
rounded:
'rounded-full border data-[invalid=true]:border-error-700 data-[invalid=true]:hover:border-error-700 data-[invalid=true]:data-[focus=true]:border-error-700 data-[invalid=true]:data-[focus=true]:hover:border-error-700 data-[invalid=true]:data-[disabled=true]:hover:border-error-700 data-[focus=true]:web:ring-1 data-[focus=true]:web:ring-inset data-[focus=true]:web:ring-indicator-primary data-[invalid=true]:web:ring-1 data-[invalid=true]:web:ring-inset data-[invalid=true]:web:ring-indicator-error data-[invalid=true]:data-[focus=true]:hover:web:ring-1 data-[invalid=true]:data-[focus=true]:hover:web:ring-inset data-[invalid=true]:data-[focus=true]:hover:web:ring-indicator-error data-[invalid=true]:data-[disabled=true]:hover:web:ring-1 data-[invalid=true]:data-[disabled=true]:hover:web:ring-inset data-[invalid=true]:data-[disabled=true]:hover:web:ring-indicator-error',
},
},
});
const inputIconStyle = tva({
base: 'justify-center items-center text-typography-400 fill-none',
parentVariants: {
size: {
'2xs': 'h-3 w-3',
'xs': 'h-3.5 w-3.5',
'sm': 'h-4 w-4',
'md': 'h-[18px] w-[18px]',
'lg': 'h-5 w-5',
'xl': 'h-6 w-6',
},
},
});
const inputSlotStyle = tva({
base: 'justify-center items-center web:disabled:cursor-not-allowed',
});
const inputFieldStyle = tva({
base: 'flex-1 text-typography-900 py-0 px-3 placeholder:text-typography-500 h-full ios:leading-[0px] web:cursor-text web:data-[disabled=true]:cursor-not-allowed',
parentVariants: {
variant: {
underlined: 'web:outline-0 web:outline-none px-0',
outline: 'web:outline-0 web:outline-none',
rounded: 'web:outline-0 web:outline-none px-4',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
},
});
type IInputProps = React.ComponentProps<typeof UIInput> &
VariantProps<typeof inputStyle> & { className?: string };
const Input = React.forwardRef<React.ComponentRef<typeof UIInput>, IInputProps>(
function Input(
{ className, variant = 'outline', size = 'md', ...props },
ref
) {
return (
<UIInput
ref={ref}
{...props}
className={inputStyle({ variant, size, class: className })}
context={{ variant, size }}
/>
);
}
);
type IInputIconProps = React.ComponentProps<typeof UIInput.Icon> &
VariantProps<typeof inputIconStyle> & {
className?: string;
height?: number;
width?: number;
};
const InputIcon = React.forwardRef<
React.ComponentRef<typeof UIInput.Icon>,
IInputIconProps
>(function InputIcon({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
if (typeof size === 'number') {
return (
<UIInput.Icon
ref={ref}
{...props}
className={inputIconStyle({ class: className })}
size={size}
/>
);
} else if (
(props.height !== undefined || props.width !== undefined) &&
size === undefined
) {
return (
<UIInput.Icon
ref={ref}
{...props}
className={inputIconStyle({ class: className })}
/>
);
}
return (
<UIInput.Icon
ref={ref}
{...props}
className={inputIconStyle({
parentVariants: {
size: parentSize,
},
class: className,
})}
/>
);
});
type IInputSlotProps = React.ComponentProps<typeof UIInput.Slot> &
VariantProps<typeof inputSlotStyle> & { className?: string };
const InputSlot = React.forwardRef<
React.ComponentRef<typeof UIInput.Slot>,
IInputSlotProps
>(function InputSlot({ className, ...props }, ref) {
return (
<UIInput.Slot
ref={ref}
{...props}
className={inputSlotStyle({
class: className,
})}
/>
);
});
type IInputFieldProps = React.ComponentProps<typeof UIInput.Input> &
VariantProps<typeof inputFieldStyle> & { className?: string };
const InputField = React.forwardRef<
React.ComponentRef<typeof UIInput.Input>,
IInputFieldProps
>(function InputField({ className, ...props }, ref) {
const { variant: parentVariant, size: parentSize } = useStyleContext(SCOPE);
return (
<UIInput.Input
ref={ref}
{...props}
className={inputFieldStyle({
parentVariants: {
variant: parentVariant,
size: parentSize,
},
class: className,
})}
/>
);
});
Input.displayName = 'Input';
InputIcon.displayName = 'InputIcon';
InputSlot.displayName = 'InputSlot';
InputField.displayName = 'InputField';
export { Input, InputField, InputIcon, InputSlot };
@@ -0,0 +1,102 @@
'use client';
import { createLink } from '@gluestack-ui/core/link/creator';
import { Pressable } from 'react-native';
import { Text } from 'react-native';
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import { withStyleContext } from '@gluestack-ui/utils/nativewind-utils';
import { cssInterop } from 'nativewind';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
import React from 'react';
export const UILink = createLink({
Root: withStyleContext(Pressable),
Text: Text,
});
cssInterop(UILink, { className: 'style' });
cssInterop(UILink.Text, { className: 'style' });
const linkStyle = tva({
base: 'group/link web:outline-0 data-[disabled=true]:web:cursor-not-allowed data-[focus-visible=true]:web:ring-2 data-[focus-visible=true]:web:ring-indicator-primary data-[focus-visible=true]:web:outline-0 data-[disabled=true]:opacity-4 ',
});
const linkTextStyle = tva({
base: 'underline text-info-700 data-[hover=true]:text-info-600 data-[hover=true]:no-underline data-[active=true]:text-info-700 font-normal font-body web:font-sans web:tracking-sm web:my-0 web:bg-transparent web:border-0 web:box-border web:display-inline web:list-none web:margin-0 web:padding-0 web:position-relative web:text-start web:whitespace-pre-wrap web:word-wrap-break-word',
variants: {
isTruncated: {
true: 'web:truncate',
},
bold: {
true: 'font-bold',
},
underline: {
true: 'underline',
},
strikeThrough: {
true: 'line-through',
},
size: {
'2xs': 'text-2xs',
'xs': 'text-xs',
'sm': 'text-sm',
'md': 'text-base',
'lg': 'text-lg',
'xl': 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl',
'5xl': 'text-5xl',
'6xl': 'text-6xl',
},
sub: {
true: 'text-xs',
},
italic: {
true: 'italic',
},
highlight: {
true: 'bg-yellow-500',
},
},
});
type ILinkProps = React.ComponentProps<typeof UILink> &
VariantProps<typeof linkStyle> & { className?: string };
const Link = React.forwardRef<React.ComponentRef<typeof UILink>, ILinkProps>(
function Link({ className, ...props }, ref) {
return (
<UILink
ref={ref}
{...props}
className={linkStyle({ class: className })}
/>
);
}
);
type ILinkTextProps = React.ComponentProps<typeof UILink.Text> &
VariantProps<typeof linkTextStyle> & { className?: string };
const LinkText = React.forwardRef<
React.ComponentRef<typeof UILink.Text>,
ILinkTextProps
>(function LinkText({ className, size = 'md', ...props }, ref) {
return (
<UILink.Text
ref={ref}
{...props}
className={linkTextStyle({
class: className,
size,
})}
/>
);
});
Link.displayName = 'Link';
LinkText.displayName = 'LinkText';
export { Link, LinkText };
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

+2 -2
View File
@@ -3,7 +3,7 @@ package main
import (
"base-go-v2/internal/api"
"base-go-v2/internal/config"
"base-go-v2/internal/database"
"base-go-v2/internal/db"
"base-go-v2/internal/logx"
"fmt"
"github.com/valyala/fasthttp"
@@ -17,7 +17,7 @@ func main() {
}
// 初始化数据库
if err := database.InitDb(); err != nil {
if err := db.InitDb(); err != nil {
log.Fatalf("加载数据库配置失败: %v", err)
}
+1
View File
@@ -13,6 +13,7 @@ require (
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
+5
View File
@@ -1,15 +1,20 @@
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
@@ -1,5 +1,27 @@
package auth
func InitAuthRouter() {
import (
response "base-go-v2/internal/reponse"
"base-go-v2/internal/router"
)
func InitAuthRouter(r *router.Router) {
group := r.Group("auth")
group.POST("/login/default", loginDefault)
}
// 默认登录
func loginDefault(c *router.Context) error {
return response.Success(c).Send()
}
// 注册
func registerDefault(c *router.Context) error {
var req struct {
Email string `json:"email"`
Password string `json:"password"`
}
if err := c.BindJSON(&req); err != nil {
}
}
@@ -1,15 +1,15 @@
package database
package db
import (
"base-go-v2/internal/config"
"database/sql"
"fmt"
"time"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
var DB *sql.DB
var DB *sqlx.DB
var defaultPoolConfig = struct {
MaxOpenConns int
@@ -28,7 +28,7 @@ func InitDb() error {
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
d.Host, d.Port, d.User, d.Password, d.Dbname)
db, err := sql.Open("postgres", dsn)
db, err := sqlx.Connect("postgres", dsn)
if err != nil {
return fmt.Errorf("打开数据库失败: %w", err)
}
@@ -60,5 +60,6 @@ func InitDb() error {
fmt.Printf("✅ 数据库连接成功:%s:%d/%s\n", d.Host, d.Port, d.Dbname)
DB = db
return nil
}
@@ -0,0 +1,61 @@
package db
import (
"fmt"
)
// DeleteOne 根据主键删除单条记录
func DeleteOne(table string, pkColumn string, pkValue interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
query := fmt.Sprintf("DELETE FROM %s WHERE %s=$1", table, pkColumn)
res, err := tx.Exec(query, pkValue)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// DeleteBatch 根据主键批量删除记录
func DeleteBatch(table string, pkColumn string, pkValues []interface{}) (int64, error) {
if len(pkValues) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, pk := range pkValues {
query := fmt.Sprintf("DELETE FROM %s WHERE %s=$1", table, pkColumn)
res, err := tx.Exec(query, pk)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
@@ -0,0 +1,146 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 内部辅助函数 ----------------
// buildInsertSQL 构建插入 SQL 和参数
func buildInsertSQL(table string, data map[string]interface{}, returning string) (string, []interface{}) {
columns := make([]string, 0, len(data))
placeholders := make([]string, 0, len(data))
values := make([]interface{}, 0, len(data))
i := 1
for k, v := range data {
columns = append(columns, k)
placeholders = append(placeholders, fmt.Sprintf("$%d", i))
values = append(values, v)
i++
}
sql := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", table,
strings.Join(columns, ","), strings.Join(placeholders, ","))
if returning != "" {
sql += " RETURNING " + returning
}
return sql, values
}
// ---------------- 公共方法 ----------------
// InsertOne 插入单条记录,返回受影响行数
func InsertOne(table string, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildInsertSQL(table, data, "")
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// InsertBatch 批量插入,返回总受影响行数
func InsertBatch(table string, dataList []map[string]interface{}) (int64, error) {
if len(dataList) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, data := range dataList {
sql, values := buildInsertSQL(table, data, "")
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
// InsertOneReturnPK 插入单条记录,返回主键值
func InsertOneReturnPK(table string, pkColumn string, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildInsertSQL(table, data, pkColumn)
var pk int64
err = tx.Get(&pk, sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return pk, nil
}
// InsertBatchReturnPK 批量插入多条记录,返回主键数组
func InsertBatchReturnPK(table string, pkColumn string, dataList []map[string]interface{}) ([]int64, error) {
if len(dataList) == 0 {
return nil, nil
}
tx, err := DB.Beginx()
if err != nil {
return nil, err
}
var pkList []int64
for _, data := range dataList {
sql, values := buildInsertSQL(table, data, pkColumn)
var pk int64
err := tx.Get(&pk, sql, values...)
if err != nil {
tx.Rollback()
return nil, err
}
pkList = append(pkList, pk)
}
if err := tx.Commit(); err != nil {
return nil, err
}
return pkList, nil
}
@@ -0,0 +1,96 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 通用查询方法 ----------------
// GetOne 根据主键查询单条记录,返回 map[string]interface{}
func GetOne(table string, pkColumn string, pkValue interface{}) (map[string]interface{}, error) {
query := fmt.Sprintf("SELECT * FROM %s WHERE %s=$1", table, pkColumn)
row := make(map[string]interface{})
err := DB.Get(&row, query, pkValue)
if err != nil {
return nil, err
}
return row, nil
}
// GetBatch 根据主键批量查询,返回 []map[string]interface{}
func GetBatch(table string, pkColumn string, pkValues []interface{}) ([]map[string]interface{}, error) {
if len(pkValues) == 0 {
return nil, nil
}
var rows []map[string]interface{}
// 构建 IN 占位符
placeholders := make([]string, len(pkValues))
for i := range pkValues {
placeholders[i] = fmt.Sprintf("$%d", i+1)
}
query := fmt.Sprintf("SELECT * FROM %s WHERE %s IN (%s)", table, pkColumn, strings.Join(placeholders, ","))
err := DB.Select(&rows, query, pkValues...)
if err != nil {
return nil, err
}
return rows, nil
}
// Find 根据条件查询多条记录,可选排序
// conditions: map[column]value, 将以 AND 拼接
// orderBy: 可选排序字段,如 "created_at ASC",为空默认 "b_id DESC"
func Find(table string, conditions map[string]interface{}, orderBy ...string) ([]map[string]interface{}, error) {
if len(conditions) == 0 {
return nil, fmt.Errorf("查询条件不能为空")
}
var whereParts []string
var values []interface{}
i := 1
for k, v := range conditions {
whereParts = append(whereParts, fmt.Sprintf("%s=$%d", k, i))
values = append(values, v)
i++
}
query := fmt.Sprintf("SELECT * FROM %s WHERE %s", table, strings.Join(whereParts, " AND "))
order := "b_id DESC"
if len(orderBy) > 0 && orderBy[0] != "" {
order = orderBy[0]
}
query += " ORDER BY " + order
var rows []map[string]interface{}
err := DB.Select(&rows, query, values...)
if err != nil {
return nil, err
}
return rows, nil
}
// FindAll 查询整个表,可选排序
func FindAll(table string, orderBy ...string) ([]map[string]interface{}, error) {
query := fmt.Sprintf("SELECT * FROM %s", table)
order := "b_id DESC"
if len(orderBy) > 0 && orderBy[0] != "" {
order = orderBy[0]
}
query += " ORDER BY " + order
var rows []map[string]interface{}
err := DB.Select(&rows, query)
if err != nil {
return nil, err
}
return rows, nil
}
@@ -0,0 +1,103 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 内部辅助函数 ----------------
// buildUpdateSQL 构建 UPDATE SQL 和参数
// idColumn: 主键列名
func buildUpdateSQL(table string, data map[string]interface{}, idColumn string) (string, []interface{}) {
var setParts []string
var values []interface{}
i := 1
for k, v := range data {
setParts = append(setParts, fmt.Sprintf("%s=$%d", k, i))
values = append(values, v)
i++
}
// WHERE id = $n
sql := fmt.Sprintf("UPDATE %s SET %s WHERE %s=$%d",
table,
strings.Join(setParts, ", "),
idColumn,
i,
)
return sql, values
}
// ---------------- 公共方法 ----------------
// UpdateOne 更新单条记录,按主键 idColumn
func UpdateOne(table string, idColumn string, id interface{}, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildUpdateSQL(table, data, idColumn)
values = append(values, id) // 最后一个参数是 id
res, err := tx.Exec(sql, values...)
if err != nil {
err := tx.Rollback()
if err != nil {
return 0, err
}
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// UpdateBatch 批量更新,dataList 中每个 map 必须包含主键 idColumn
func UpdateBatch(table string, idColumn string, dataList []map[string]interface{}) (int64, error) {
if len(dataList) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, data := range dataList {
idValue, ok := data[idColumn]
if !ok {
tx.Rollback()
return 0, fmt.Errorf("缺少主键列 %s", idColumn)
}
// 移除主键列,否则会重复在 SET 中出现
delete(data, idColumn)
sql, values := buildUpdateSQL(table, data, idColumn)
values = append(values, idValue)
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
+40
View File
@@ -816,6 +816,46 @@ import 'react-native-gesture-handler'
## 集成[react-native-iconfont-cli](https://github.com/iconfont-cli/react-native-iconfont-cli)
安装:
```bash
pnpm add react-native-iconfont-cli -D
```
BUG位置:https://github.com/iconfont-cli/react-native-iconfont-cli/issues/42
解决fang'an修改模板 `node_modules/react-native-iconfont-cli/templates/SingleIcon.tsx.template`:
```tsx
/* eslint-disable */
/* tslint:disable */
import React from 'react';
import type { FunctionComponent } from 'react';
import type { ViewProps } from 'react-native';
#svgComponents#
#helper#
interface Props extends Omit<GProps, 'color'>, ViewProps {
size?: number;
color?: string | string[];
}
const #componentName#: FunctionComponent<Props> = ({
size = #size#,
color,
...rest
}) => {
return (
#iconContent#
);
};
export default React.memo(#componentName#);
```
## 配置深度链接