u
This commit is contained in:
1 parent
c7a1f83c67
commit
6849579652
19 files changed
+600
-249
No files matched your search
@@ -10,12 +10,14 @@
|
||||
"web": "expo start --web"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alova/adapter-axios": "^2.0.16",
|
||||
"@gluestack-ui/core": "^3.0.12",
|
||||
"@gluestack-ui/utils": "^3.0.11",
|
||||
"@gluestack/ui-next-adapter": "^3.0.3",
|
||||
"@legendapp/motion": "^2.4.0",
|
||||
"@react-native-async-storage/async-storage": "2.2.0",
|
||||
"alova": "^3.3.4",
|
||||
"axios": "^1.13.2",
|
||||
"expo": "~54.0.20",
|
||||
"expo-constants": "~18.0.10",
|
||||
"expo-font": "~14.0.9",
|
||||
|
||||
+178
-8
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@alova/adapter-axios':
|
||||
specifier: ^2.0.16
|
||||
version: 2.0.16(alova@3.3.4)(axios@1.13.2)
|
||||
'@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.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)
|
||||
@@ -26,6 +29,9 @@ importers:
|
||||
alova:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4
|
||||
axios:
|
||||
specifier: ^1.13.2
|
||||
version: 1.13.2
|
||||
expo:
|
||||
specifier: ~54.0.20
|
||||
version: 54.0.21(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
@@ -111,6 +117,12 @@ packages:
|
||||
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@alova/adapter-axios@2.0.16':
|
||||
resolution: {integrity: sha512-O9iskfllA8Yd5QV7w/c2aBduf1ocpD5goXp3aJbBXovZanKbsgMyvuFycXmTeqPyLdjURo5fYicEmWHwURpkbQ==}
|
||||
peerDependencies:
|
||||
alova: ^3.0.20
|
||||
axios: '>=0.4.0'
|
||||
|
||||
'@alova/shared@1.3.1':
|
||||
resolution: {integrity: sha512-ijSOaFLUFcVzMKSY3avoEE5C03/p9atjMDPBwvNkwnzaCrhv6/m4A121NdadF8YlHCRuifyYfz90IyEdMXTsJg==}
|
||||
|
||||
@@ -2215,10 +2227,16 @@ packages:
|
||||
async-limiter@1.0.1:
|
||||
resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
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
|
||||
|
||||
axios@1.13.2:
|
||||
resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==}
|
||||
|
||||
babel-jest@29.7.0:
|
||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
@@ -2355,6 +2373,10 @@ packages:
|
||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -2469,6 +2491,10 @@ packages:
|
||||
resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==}
|
||||
engines: {node: '>=0.1.90'}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
commander@12.1.0:
|
||||
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2616,6 +2642,10 @@ packages:
|
||||
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
depd@2.0.0:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -2677,6 +2707,10 @@ packages:
|
||||
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
@@ -2719,6 +2753,22 @@ packages:
|
||||
error-stack-parser@2.1.4:
|
||||
resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==}
|
||||
|
||||
es-define-property@1.0.1:
|
||||
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-errors@1.3.0:
|
||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3153,6 +3203,15 @@ packages:
|
||||
flow-enums-runtime@0.0.6:
|
||||
resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==}
|
||||
|
||||
follow-redirects@1.15.11:
|
||||
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
|
||||
follow-redirects@1.5.10:
|
||||
resolution: {integrity: sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
@@ -3164,6 +3223,10 @@ packages:
|
||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
form-data@4.0.4:
|
||||
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
format@0.2.2:
|
||||
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
|
||||
engines: {node: '>=0.4.x'}
|
||||
@@ -3199,6 +3262,10 @@ packages:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-nonce@1.0.1:
|
||||
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3207,6 +3274,10 @@ packages:
|
||||
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
get-proto@1.0.1:
|
||||
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-tsconfig@4.13.0:
|
||||
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
|
||||
|
||||
@@ -3252,6 +3323,10 @@ packages:
|
||||
globrex@0.1.2:
|
||||
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
|
||||
|
||||
gopd@1.2.0:
|
||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
@@ -3266,6 +3341,14 @@ packages:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
has-symbols@1.1.0:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3587,56 +3670,48 @@ 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==}
|
||||
@@ -3737,6 +3812,10 @@ packages:
|
||||
marky@1.3.0:
|
||||
resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==}
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
||||
|
||||
@@ -4371,6 +4450,9 @@ packages:
|
||||
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -5319,6 +5401,12 @@ snapshots:
|
||||
|
||||
'@alloc/quick-lru@5.2.0': {}
|
||||
|
||||
'@alova/adapter-axios@2.0.16(alova@3.3.4)(axios@1.13.2)':
|
||||
dependencies:
|
||||
'@alova/shared': 1.3.1
|
||||
alova: 3.3.4
|
||||
axios: 1.13.2
|
||||
|
||||
'@alova/shared@1.3.1': {}
|
||||
|
||||
'@antfu/eslint-config@6.2.0(@vue/compiler-sfc@3.5.22)(eslint@9.39.0(jiti@1.21.7))(typescript@5.9.3)':
|
||||
@@ -8285,12 +8373,22 @@ snapshots:
|
||||
|
||||
async-limiter@1.0.1: {}
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
axios@0.19.2:
|
||||
dependencies:
|
||||
follow-redirects: 1.5.10
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
axios@1.13.2:
|
||||
dependencies:
|
||||
follow-redirects: 1.15.11
|
||||
form-data: 4.0.4
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
babel-jest@29.7.0(@babel/core@7.28.5):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
@@ -8484,6 +8582,11 @@ snapshots:
|
||||
|
||||
cac@6.7.14: {}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase-css@2.0.1: {}
|
||||
@@ -8597,6 +8700,10 @@ snapshots:
|
||||
|
||||
colors@1.4.0: {}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
commander@12.1.0: {}
|
||||
|
||||
commander@2.20.3: {}
|
||||
@@ -8725,6 +8832,8 @@ snapshots:
|
||||
|
||||
define-lazy-prop@2.0.0: {}
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
@@ -8776,6 +8885,12 @@ snapshots:
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
ee-first@1.1.1: {}
|
||||
@@ -8805,6 +8920,21 @@ snapshots:
|
||||
dependencies:
|
||||
stackframe: 1.3.4
|
||||
|
||||
es-define-property@1.0.1: {}
|
||||
|
||||
es-errors@1.3.0: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
es-set-tostringtag@2.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
@@ -9356,6 +9486,8 @@ snapshots:
|
||||
|
||||
flow-enums-runtime@0.0.6: {}
|
||||
|
||||
follow-redirects@1.15.11: {}
|
||||
|
||||
follow-redirects@1.5.10:
|
||||
dependencies:
|
||||
debug: 3.1.0
|
||||
@@ -9369,6 +9501,14 @@ snapshots:
|
||||
cross-spawn: 7.0.6
|
||||
signal-exit: 4.1.0
|
||||
|
||||
form-data@4.0.4:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
es-set-tostringtag: 2.1.0
|
||||
hasown: 2.0.2
|
||||
mime-types: 2.1.35
|
||||
|
||||
format@0.2.2: {}
|
||||
|
||||
freeport-async@2.0.0: {}
|
||||
@@ -9392,10 +9532,28 @@ snapshots:
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.1.1
|
||||
function-bind: 1.1.2
|
||||
get-proto: 1.0.1
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
get-nonce@1.0.1: {}
|
||||
|
||||
get-package-type@0.1.0: {}
|
||||
|
||||
get-proto@1.0.1:
|
||||
dependencies:
|
||||
dunder-proto: 1.0.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
get-tsconfig@4.13.0:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
@@ -9442,6 +9600,8 @@ snapshots:
|
||||
|
||||
globrex@0.1.2: {}
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
@@ -9450,6 +9610,12 @@ snapshots:
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
dependencies:
|
||||
has-symbols: 1.1.0
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
@@ -9891,6 +10057,8 @@ snapshots:
|
||||
|
||||
marky@1.3.0: {}
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@@ -10898,6 +11066,8 @@ snapshots:
|
||||
kleur: 3.0.3
|
||||
sisteransi: 1.0.5
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
qrcode-terminal@0.11.0: {}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Lock, UserRound } from 'lucide-react-native'
|
||||
import { useState } from 'react'
|
||||
import { Image, Text, View } from 'react-native'
|
||||
import { AForm, AFormItem, AInput } from '@/components/common/ao'
|
||||
import { IconQq, IconWeixin, IconZhiwen } from '@/components/iconfont'
|
||||
import { Button, ButtonText } from '@/components/ui/button'
|
||||
import {
|
||||
@@ -10,13 +11,9 @@ import {
|
||||
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 { CheckIcon } from '@/components/ui/icon'
|
||||
|
||||
import alovaInstance from '@/request'
|
||||
import { useToast } from '@/utils/toast'
|
||||
|
||||
@@ -30,13 +27,14 @@ interface LoginForm {
|
||||
export default function AuthLogin() {
|
||||
const toast = useToast()
|
||||
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
const [form, setForm] = useState<LoginForm>({
|
||||
username: '',
|
||||
password: '',
|
||||
rememberMe: true,
|
||||
})
|
||||
|
||||
const handleInputChange = (field: keyof LoginForm, value: string) => {
|
||||
setForm(prev => ({ ...prev, [field]: value }))
|
||||
}
|
||||
const defaultLogin = () => {
|
||||
alovaInstance.Post('/auth/login/default', {
|
||||
title: 'foo',
|
||||
@@ -56,39 +54,21 @@ export default function AuthLogin() {
|
||||
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 }))}
|
||||
<AForm form={form}>
|
||||
<AFormItem label="账号">
|
||||
<AInput
|
||||
value={form.username}
|
||||
onChange={text => handleInputChange('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 }))}
|
||||
</AFormItem>
|
||||
<AFormItem label="密码">
|
||||
<AInput
|
||||
isPassword
|
||||
value={form.password}
|
||||
onChange={text => handleInputChange('password', text)}
|
||||
/>
|
||||
<InputSlot className="pr-3" onPress={() => setShowPassword(prev => !prev)}>
|
||||
<InputIcon as={showPassword ? EyeIcon : EyeOffIcon} />
|
||||
</InputSlot>
|
||||
</Input>
|
||||
</FormControl>
|
||||
</AFormItem>
|
||||
</AForm>
|
||||
|
||||
<View className="w-full flex-row justify-between items-center mb-6">
|
||||
<Checkbox
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface FormRef {
|
||||
interface FormProps {
|
||||
children: React.ReactNode
|
||||
form: Record<string, any>
|
||||
scrollRef: React.RefObject<ScrollView | null>
|
||||
scrollRef?: React.RefObject<ScrollView | null>
|
||||
}
|
||||
|
||||
interface FormContextType {
|
||||
@@ -57,7 +57,7 @@ const Form = forwardRef<FormRef, FormProps>(({ children, form, scrollRef }, ref)
|
||||
|
||||
const scrollToField = (name: string) => {
|
||||
const y = fieldPositions.current.get(name)
|
||||
if (y !== undefined && scrollRef.current) {
|
||||
if (y !== undefined && scrollRef?.current) {
|
||||
scrollRef.current.scrollTo({ y, animated: true })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ interface RuleType {
|
||||
}
|
||||
|
||||
interface FormItemProps<T> {
|
||||
name: keyof T
|
||||
name?: keyof T
|
||||
label?: string
|
||||
rules?: RuleType[]
|
||||
children: React.ReactNode
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import { axiosRequestAdapter } from '@alova/adapter-axios'
|
||||
import { createAlova } from 'alova'
|
||||
import { createServerTokenAuthentication } from 'alova/client'
|
||||
import adapterFetch from 'alova/fetch'
|
||||
import { useToast } from '@/utils/toast'
|
||||
|
||||
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication({
|
||||
// ...
|
||||
})
|
||||
|
||||
const alovaInstance = createAlova({
|
||||
baseURL: 'http://192.168.1.136:8085/app',
|
||||
requestAdapter: adapterFetch(),
|
||||
// ...
|
||||
beforeRequest: onAuthRequired((method) => {
|
||||
// ...原请求前拦截器
|
||||
}),
|
||||
responded: onResponseRefreshToken((response, method) => {
|
||||
// ...原响应成功拦截器
|
||||
return response.json()
|
||||
}),
|
||||
// baseURL: 'http://192.168.1.136:8085/app',
|
||||
baseURL: 'http://192.168.5.6:8085/app',
|
||||
requestAdapter: axiosRequestAdapter(),
|
||||
responded(response) {
|
||||
// response自动被推断为AxiosResponse类型
|
||||
|
||||
return response.data
|
||||
},
|
||||
})
|
||||
|
||||
export default alovaInstance
|
||||
@@ -15,7 +15,8 @@ db:
|
||||
|
||||
jwt:
|
||||
secret: 3Bde3BGEbYqtqyEUzW3ry8jKFcaPH17fRmTmqE7MDr05Lwj95uruRKrrkb44TJ4s
|
||||
expiry: -1
|
||||
accessExpiry: 30m
|
||||
refreshExpiry: 720h
|
||||
|
||||
log:
|
||||
dir: "logs" # 日志根目录
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"base-go-v2/internal/db"
|
||||
response "base-go-v2/internal/reponse"
|
||||
"base-go-v2/internal/router"
|
||||
"base-go-v2/internal/utils/jwtx"
|
||||
"base-go-v2/internal/utils/mapx"
|
||||
"base-go-v2/internal/utils/uid"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func InitAuthRouter(r *router.Router) {
|
||||
@@ -15,20 +15,71 @@ func InitAuthRouter(r *router.Router) {
|
||||
group.POST("/register/default", registerDefault)
|
||||
}
|
||||
|
||||
func RefreshToken(c *router.Context) error {
|
||||
bodyData, err := c.GetBodyWithRequired("accessToken", "refreshToken")
|
||||
//func RefreshToken(c *router.Context) error {
|
||||
// _, err := c.GetBodyWithRequired("accessToken", "refreshToken")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// //accessToken := bodyData.GetString("accessToken")
|
||||
// //refreshToken := bodyData.GetString("refreshToken")
|
||||
//}
|
||||
|
||||
// 默认登录
|
||||
// 默认登录
|
||||
func loginDefault(c *router.Context) error {
|
||||
// 获取请求体并校验必填字段
|
||||
bodyData, err := c.GetBodyWithRequired("account", "password")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accessToken := bodyData.GetString("accessToken")
|
||||
refreshToken := bodyData.GetString("refreshToken")
|
||||
}
|
||||
|
||||
// 默认登录
|
||||
func loginDefault(c *router.Context) error {
|
||||
fmt.Println("loginDefault 被调用")
|
||||
account := bodyData.GetString("account")
|
||||
password := bodyData.GetString("password")
|
||||
|
||||
return response.Success(c).Send()
|
||||
// 查询用户
|
||||
userQuery := mapx.New().SetKV(
|
||||
"account", account,
|
||||
"password", password,
|
||||
)
|
||||
user, err := db.FindOne("user_info", userQuery)
|
||||
if err != nil {
|
||||
return response.Success(c).Message("查询用户失败,请稍后重试").IsSuccess(false).Send()
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
// 账号或密码错误
|
||||
return response.Success(c).
|
||||
IsSuccess(false).
|
||||
Message("账号或密码错误").
|
||||
Send()
|
||||
}
|
||||
|
||||
userId := user.GetInt("id")
|
||||
|
||||
// 创建 Access Token 和 Refresh Token
|
||||
accessToken, err := jwtx.CreateAccessToken(userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
refreshToken, err := jwtx.CreateRefreshToken(userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 返回数据
|
||||
respData := mapx.New().
|
||||
SetIntToString("userId", userId).
|
||||
SetKV(
|
||||
"username", user.GetString("username"),
|
||||
"seqNo", user.GetInt("seq_no"),
|
||||
"gender", user.GetInt("gender"),
|
||||
"accessToken", accessToken,
|
||||
"refreshToken", refreshToken,
|
||||
)
|
||||
|
||||
return response.Success(c).
|
||||
Data(respData).
|
||||
Send()
|
||||
}
|
||||
|
||||
func registerDefault(c *router.Context) error {
|
||||
@@ -48,7 +99,7 @@ func registerDefault(c *router.Context) error {
|
||||
}
|
||||
|
||||
if len(existingUsers) > 0 {
|
||||
return response.Error(c).Message("该账号已被注册").Send()
|
||||
return response.Error(c).IsSuccess(false).Message("该账号已被注册").Send()
|
||||
}
|
||||
|
||||
// 构造新用户数据
|
||||
@@ -64,7 +115,7 @@ func registerDefault(c *router.Context) error {
|
||||
return err
|
||||
}
|
||||
if insertedRows != 1 {
|
||||
return response.Error(c).Message("注册失败").Send()
|
||||
return response.Success(c).IsSuccess(false).Message("注册失败").Send()
|
||||
}
|
||||
|
||||
return response.Success(c).Message("注册成功").Send()
|
||||
|
||||
@@ -18,8 +18,9 @@ func init() {
|
||||
Port: 8080,
|
||||
},
|
||||
JWT: types.JWTConfig{
|
||||
Secret: "default_secret",
|
||||
Expiry: time.Hour,
|
||||
Secret: "default_secret",
|
||||
RefreshExpiry: time.Hour,
|
||||
AccessExpiry: time.Hour,
|
||||
},
|
||||
Db: types.DbConfig{
|
||||
MaxOpenConns: 10,
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"base-go-v2/internal/utils/mapx"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ---------------- 通用查询方法 ----------------
|
||||
|
||||
// GetOne 根据主键查询单条记录,返回 map[string]interface{}
|
||||
func GetOne(table string, pkColumn string, pkValue interface{}) (map[string]interface{}, error) {
|
||||
// GetOne 根据主键查询单条记录,返回 mapx.M
|
||||
func GetOne(table string, pkColumn string, pkValue interface{}) (mapx.M, error) {
|
||||
query := fmt.Sprintf("SELECT * FROM %s WHERE %s=$1", table, pkColumn)
|
||||
|
||||
row := make(map[string]interface{})
|
||||
row := mapx.New()
|
||||
err := DB.Get(&row, query, pkValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -19,13 +20,13 @@ func GetOne(table string, pkColumn string, pkValue interface{}) (map[string]inte
|
||||
return row, nil
|
||||
}
|
||||
|
||||
// GetBatch 根据主键批量查询,返回 []map[string]interface{}
|
||||
func GetBatch(table string, pkColumn string, pkValues []interface{}) ([]map[string]interface{}, error) {
|
||||
// GetBatch 根据主键批量查询,返回 []mapx.M
|
||||
func GetBatch(table string, pkColumn string, pkValues []interface{}) ([]mapx.M, error) {
|
||||
if len(pkValues) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var rows []map[string]interface{}
|
||||
var rows []mapx.M
|
||||
|
||||
// 构建 IN 占位符
|
||||
placeholders := make([]string, len(pkValues))
|
||||
@@ -42,10 +43,8 @@ func GetBatch(table string, pkColumn string, pkValues []interface{}) ([]map[stri
|
||||
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) {
|
||||
// Find 根据条件查询多条记录,可选排序,返回 []mapx.M
|
||||
func Find(table string, conditions map[string]interface{}, orderBy ...string) ([]mapx.M, error) {
|
||||
if len(conditions) == 0 {
|
||||
return nil, fmt.Errorf("查询条件不能为空")
|
||||
}
|
||||
@@ -67,7 +66,7 @@ func Find(table string, conditions map[string]interface{}, orderBy ...string) ([
|
||||
}
|
||||
query += " ORDER BY " + order
|
||||
|
||||
var rows []map[string]interface{}
|
||||
var rows []mapx.M
|
||||
err := DB.Select(&rows, query, values...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -76,8 +75,8 @@ func Find(table string, conditions map[string]interface{}, orderBy ...string) ([
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// FindAll 查询整个表,可选排序
|
||||
func FindAll(table string, orderBy ...string) ([]map[string]interface{}, error) {
|
||||
// FindAll 查询整个表,可选排序,返回 []mapx.M
|
||||
func FindAll(table string, orderBy ...string) ([]mapx.M, error) {
|
||||
query := fmt.Sprintf("SELECT * FROM %s", table)
|
||||
|
||||
order := "b_id DESC"
|
||||
@@ -86,7 +85,7 @@ func FindAll(table string, orderBy ...string) ([]map[string]interface{}, error)
|
||||
}
|
||||
query += " ORDER BY " + order
|
||||
|
||||
var rows []map[string]interface{}
|
||||
var rows []mapx.M
|
||||
err := DB.Select(&rows, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -94,3 +93,35 @@ func FindAll(table string, orderBy ...string) ([]map[string]interface{}, error)
|
||||
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// FindOne 根据条件查询单条记录,返回 mapx.M
|
||||
func FindOne(table string, conditions map[string]interface{}, orderBy ...string) (mapx.M, 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 + " LIMIT 1" // 只取一条记录
|
||||
|
||||
row := mapx.New()
|
||||
err := DB.Get(&row, query, values...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return row, nil
|
||||
}
|
||||
@@ -1,19 +1,34 @@
|
||||
package errs
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ValidationError 用于收集多个字段错误,同时实现 error 接口
|
||||
type ValidationError struct {
|
||||
field string
|
||||
message string
|
||||
Errors map[string]string // key: 字段名, value: 错误信息
|
||||
}
|
||||
|
||||
func (e *ValidationError) Error() string {
|
||||
return fmt.Sprintf("字段 %s: %s", e.field, e.message)
|
||||
// Error 实现 error 接口
|
||||
func (v *ValidationError) Error() string {
|
||||
if len(v.Errors) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
msgs := make([]string, 0, len(v.Errors))
|
||||
for field, msg := range v.Errors {
|
||||
msgs = append(msgs, fmt.Sprintf("%s: %s", field, msg))
|
||||
}
|
||||
return strings.Join(msgs, "; ")
|
||||
}
|
||||
|
||||
func NewValidationError(field, message string) error {
|
||||
// NewValidationError 创建多字段的 ValidationError
|
||||
func NewValidationError(errors map[string]string) error {
|
||||
if len(errors) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &ValidationError{
|
||||
field: field,
|
||||
message: message,
|
||||
Errors: errors,
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,22 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Result 是最终响应结构体
|
||||
type Result struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
TrackId string `json:"trackId"`
|
||||
IsSuccess bool `json:"isSuccess"` // 是否成功
|
||||
Code string `json:"code"` // 状态码
|
||||
Message string `json:"message"` // 提示信息
|
||||
Data interface{} `json:"data,omitempty"` // 数据
|
||||
TrackId string `json:"trackId,omitempty"` // 请求追踪ID
|
||||
}
|
||||
|
||||
// Code 定义状态码
|
||||
type Code struct {
|
||||
Value string
|
||||
Message string
|
||||
}
|
||||
|
||||
// 常用状态码
|
||||
var (
|
||||
CodeSuccess = Code{"0000", "请求成功"}
|
||||
CodeFail = Code{"0001", "请求失败"}
|
||||
@@ -31,53 +35,75 @@ var (
|
||||
|
||||
const defaultMessage = "未知错误"
|
||||
|
||||
// Builder 用于构建响应
|
||||
type Builder struct {
|
||||
c *router.Context
|
||||
result Result
|
||||
}
|
||||
|
||||
// ---------------- 构造函数 ----------------
|
||||
|
||||
// Success 创建成功响应
|
||||
func Success(c *router.Context) *Builder {
|
||||
return &Builder{
|
||||
c: c,
|
||||
result: Result{
|
||||
Code: CodeSuccess.Value,
|
||||
Message: CodeSuccess.Message,
|
||||
IsSuccess: true,
|
||||
Code: CodeSuccess.Value,
|
||||
Message: CodeSuccess.Message,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Error 创建失败响应
|
||||
func Error(c *router.Context) *Builder {
|
||||
return &Builder{
|
||||
c: c,
|
||||
result: Result{
|
||||
Code: CodeFail.Value,
|
||||
Message: CodeFail.Message,
|
||||
IsSuccess: false,
|
||||
Code: CodeFail.Value,
|
||||
Message: CodeFail.Message,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- 链式方法 ----------------
|
||||
|
||||
// 设置 IsSuccess 字段
|
||||
func (b *Builder) IsSuccess(IsSuccess bool) *Builder {
|
||||
b.result.IsSuccess = IsSuccess
|
||||
return b
|
||||
}
|
||||
|
||||
// 设置 Code,并根据 Code 自动设置 IsSuccess
|
||||
func (b *Builder) Code(code string) *Builder {
|
||||
b.result.Code = code
|
||||
b.result.Message = GetMessage(code)
|
||||
b.result.IsSuccess = code == CodeSuccess.Value
|
||||
return b
|
||||
}
|
||||
|
||||
// 设置 Code 对象,并自动设置 IsSuccess
|
||||
func (b *Builder) CodeObj(code Code) *Builder {
|
||||
b.result.Code = code.Value
|
||||
b.result.Message = code.Message
|
||||
b.result.IsSuccess = code.Value == CodeSuccess.Value
|
||||
return b
|
||||
}
|
||||
|
||||
// 自定义提示信息
|
||||
func (b *Builder) Message(msg string) *Builder {
|
||||
b.result.Message = msg
|
||||
return b
|
||||
}
|
||||
|
||||
// 设置返回数据
|
||||
func (b *Builder) Data(data interface{}) *Builder {
|
||||
b.result.Data = data
|
||||
return b
|
||||
}
|
||||
|
||||
// 发送响应
|
||||
func (b *Builder) Send() error {
|
||||
// 默认 Data 为空
|
||||
if b.result.Data == nil {
|
||||
@@ -90,10 +116,12 @@ func (b *Builder) Send() error {
|
||||
b.result.TrackId = strutil.ToString(trackId)
|
||||
}
|
||||
|
||||
// 发送响应
|
||||
return b.c.JSON(http.StatusOK, b.result)
|
||||
}
|
||||
|
||||
// ---------------- 辅助函数 ----------------
|
||||
|
||||
// 根据 Code 获取默认提示信息
|
||||
func GetMessage(value string) string {
|
||||
for _, c := range []Code{
|
||||
CodeSuccess, CodeFail, CodeNoLogin,
|
||||
|
||||
@@ -97,7 +97,7 @@ func (c *Context) GetBodyWithRequired(keys ...string) (mapx.M, error) {
|
||||
}
|
||||
|
||||
// 校验必填字段
|
||||
if err := validate.ValidateNotEmpty(req, keys...); err != nil {
|
||||
if err := validate.NotEmpty(req, keys...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ type ServerConfig struct {
|
||||
}
|
||||
|
||||
type JWTConfig struct {
|
||||
Secret string
|
||||
Expiry time.Duration
|
||||
Secret string
|
||||
AccessExpiry time.Duration
|
||||
RefreshExpiry time.Duration
|
||||
}
|
||||
|
||||
type DbConfig struct {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"base-go-v2/internal/config"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTokenExpired = errors.New("token expired")
|
||||
ErrTokenInvalid = errors.New("token invalid")
|
||||
)
|
||||
|
||||
// CustomClaims 定义自己的 payload 结构
|
||||
type CustomClaims struct {
|
||||
UserID string `json:"user_id"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// CreateToken 创建一个 JWT token
|
||||
// 支持 config.App.JWT.Expiry == -1 永不过期
|
||||
func CreateToken(orgID, userID string) (string, error) {
|
||||
claims := CustomClaims{
|
||||
UserID: userID,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
expiry := config.App.JWT.Expiry
|
||||
|
||||
switch {
|
||||
case expiry > 0:
|
||||
expireAt := time.Now().Add(expiry)
|
||||
claims.ExpiresAt = jwt.NewNumericDate(expireAt)
|
||||
case expiry == -1:
|
||||
// 永不过期,ExpiresAt 设置为 nil
|
||||
claims.ExpiresAt = nil
|
||||
default:
|
||||
// 默认过期时间,例如 1 小时
|
||||
expireAt := time.Now().Add(time.Hour)
|
||||
claims.ExpiresAt = jwt.NewNumericDate(expireAt)
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(config.App.JWT.Secret))
|
||||
}
|
||||
|
||||
// VerifyToken 验证并解析 JWT token
|
||||
func VerifyToken(tokenString string) (*CustomClaims, error) {
|
||||
signKey := []byte(config.App.JWT.Secret)
|
||||
|
||||
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
// 校验签名算法
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, ErrTokenInvalid
|
||||
}
|
||||
return signKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, ErrTokenInvalid
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(*CustomClaims)
|
||||
if !ok || !token.Valid {
|
||||
return nil, ErrTokenInvalid
|
||||
}
|
||||
|
||||
// 检查过期:ExpiresAt 为 nil 时永不过期
|
||||
if claims.ExpiresAt != nil && time.Now().After(claims.ExpiresAt.Time) {
|
||||
return nil, ErrTokenExpired
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package jwtx
|
||||
|
||||
import (
|
||||
"base-go-v2/internal/config"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// CustomClaims 自定义 payload,可扩展其他信息
|
||||
type CustomClaims struct {
|
||||
UserID int `json:"user_id"` // 改为 int
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// TokenResult 用于返回验证结果
|
||||
type TokenResult struct {
|
||||
Claims *CustomClaims
|
||||
Valid bool
|
||||
Expired bool
|
||||
}
|
||||
|
||||
// CreateAccessToken 创建 Access Token,只返回 token 和 error
|
||||
func CreateAccessToken(userID int) (string, error) {
|
||||
return createToken(userID, config.App.JWT.AccessExpiry)
|
||||
}
|
||||
|
||||
// CreateRefreshToken 创建 Refresh Token,只返回 token 和 error
|
||||
func CreateRefreshToken(userID int) (string, error) {
|
||||
return createToken(userID, config.App.JWT.RefreshExpiry)
|
||||
}
|
||||
|
||||
// 内部方法,根据过期时间生成 token
|
||||
func createToken(userID int, expiry time.Duration) (string, error) {
|
||||
claims := &CustomClaims{
|
||||
UserID: userID,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
switch {
|
||||
case expiry > 0:
|
||||
expireAt := time.Now().Add(expiry)
|
||||
claims.ExpiresAt = jwt.NewNumericDate(expireAt)
|
||||
case expiry == -1:
|
||||
claims.ExpiresAt = nil // 永不过期
|
||||
default:
|
||||
expireAt := time.Now().Add(time.Hour)
|
||||
claims.ExpiresAt = jwt.NewNumericDate(expireAt)
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
signed, err := token.SignedString([]byte(config.App.JWT.Secret))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return signed, nil
|
||||
}
|
||||
|
||||
// VerifyToken 验证 token 并返回结构化结果
|
||||
func VerifyToken(tokenString string) TokenResult {
|
||||
result := TokenResult{Valid: false}
|
||||
|
||||
token, _ := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.App.JWT.Secret), nil
|
||||
})
|
||||
|
||||
claims, ok := token.Claims.(*CustomClaims)
|
||||
if !ok || !token.Valid {
|
||||
return result // token 无效
|
||||
}
|
||||
|
||||
result.Claims = claims
|
||||
result.Valid = true
|
||||
if claims.ExpiresAt != nil && time.Now().After(claims.ExpiresAt.Time) {
|
||||
result.Expired = true
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
package mapx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// M 是 map[string]interface{} 的别名
|
||||
type M map[string]interface{}
|
||||
|
||||
@@ -29,6 +34,35 @@ func (m M) SetKV(kvs ...interface{}) M {
|
||||
return m
|
||||
}
|
||||
|
||||
// ---------------- 新增方法 ----------------
|
||||
|
||||
// SetIntToString 将 int 或 int64 直接转为 string 存储,用于前端安全传输
|
||||
func (m M) SetIntToString(key string, val interface{}) M {
|
||||
var s string
|
||||
switch v := val.(type) {
|
||||
case int:
|
||||
s = strconv.Itoa(v) // 直接转为 string
|
||||
case int64:
|
||||
s = strconv.FormatInt(v, 10)
|
||||
default:
|
||||
panic("SetIntToString: unsupported type")
|
||||
}
|
||||
m[key] = s
|
||||
return m
|
||||
}
|
||||
|
||||
// GetIntFromString 将前端传来的字符串解析为 int64
|
||||
func (m M) GetIntFromString(key string) int64 {
|
||||
if v, ok := m[key]; ok {
|
||||
if s, ok := v.(string); ok {
|
||||
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Get 获取值
|
||||
func (m M) Get(key string) interface{} {
|
||||
return m[key]
|
||||
@@ -62,44 +96,15 @@ func (m M) GetInt(key string) int {
|
||||
return int(val)
|
||||
case float64:
|
||||
return int(val)
|
||||
case string:
|
||||
if i, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||||
return int(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetFloat 获取浮点数类型
|
||||
func (m M) GetFloat(key string) float64 {
|
||||
if v, ok := m[key]; ok {
|
||||
switch val := v.(type) {
|
||||
case float32:
|
||||
return float64(val)
|
||||
case float64:
|
||||
return val
|
||||
case int:
|
||||
return float64(val)
|
||||
case int8:
|
||||
return float64(val)
|
||||
case int16:
|
||||
return float64(val)
|
||||
case int32:
|
||||
return float64(val)
|
||||
case int64:
|
||||
return float64(val)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetBool 获取布尔类型
|
||||
func (m M) GetBool(key string) bool {
|
||||
if v, ok := m[key]; ok {
|
||||
if b, ok := v.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Merge 合并另一个 M,后者会覆盖前者同名字段
|
||||
func (m M) Merge(other M) M {
|
||||
for k, v := range other {
|
||||
@@ -107,3 +112,8 @@ func (m M) Merge(other M) M {
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// MarshalJSON 支持 M 自定义 JSON 序列化
|
||||
func (m M) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]interface{}(m))
|
||||
}
|
||||
@@ -1,42 +1,65 @@
|
||||
package validate
|
||||
|
||||
import (
|
||||
"base-go-v2/internal/errs"
|
||||
"errors"
|
||||
"reflect"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ValidateNotEmpty 校验结构体中指定字段不能为空
|
||||
func ValidateNotEmpty(s interface{}, fields ...string) error {
|
||||
v := reflect.ValueOf(s)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
// ValidationError 用于收集多个字段错误,同时实现 error 接口
|
||||
type ValidationError struct {
|
||||
Errors map[string]string
|
||||
}
|
||||
|
||||
// Error 实现 error 接口
|
||||
func (v *ValidationError) Error() string {
|
||||
msgs := make([]string, 0, len(v.Errors))
|
||||
for field, err := range v.Errors {
|
||||
msgs = append(msgs, fmt.Sprintf("%s: %s", field, err))
|
||||
}
|
||||
return strings.Join(msgs, "; ")
|
||||
}
|
||||
|
||||
// NotEmpty 校验 map[string]interface{} 中指定字段不能为空
|
||||
func NotEmpty(data map[string]interface{}, fields ...string) error {
|
||||
errs := make(map[string]string)
|
||||
|
||||
for _, field := range fields {
|
||||
f := v.FieldByName(field)
|
||||
if !f.IsValid() {
|
||||
return errors.New("field " + field + " does not exist")
|
||||
}
|
||||
|
||||
switch f.Kind() {
|
||||
case reflect.String:
|
||||
if strings.TrimSpace(f.String()) == "" {
|
||||
return errs.NewValidationError(field, "不能为空")
|
||||
}
|
||||
case reflect.Slice, reflect.Array, reflect.Map:
|
||||
if f.Len() == 0 {
|
||||
return errs.NewValidationError(field, "不能为空")
|
||||
}
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
if f.IsNil() {
|
||||
return errs.NewValidationError(field, "不能为空")
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
collectErrors(data[field], field, errs)
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return &ValidationError{Errors: errs}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// collectErrors 递归收集字段错误
|
||||
func collectErrors(v interface{}, path string, errs map[string]string) {
|
||||
if v == nil {
|
||||
errs[path] = fmt.Sprintf("字段 %s 不能为空", path)
|
||||
return
|
||||
}
|
||||
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
if strings.TrimSpace(val) == "" {
|
||||
errs[path] = fmt.Sprintf("字段 %s 不能为空", path)
|
||||
}
|
||||
case []interface{}:
|
||||
if len(val) == 0 {
|
||||
errs[path] = fmt.Sprintf("字段 %s 不能为空", path)
|
||||
}
|
||||
for i, elem := range val {
|
||||
collectErrors(elem, fmt.Sprintf("%s[%d]", path, i), errs)
|
||||
}
|
||||
case map[string]interface{}:
|
||||
if len(val) == 0 {
|
||||
errs[path] = fmt.Sprintf("字段 %s 不能为空", path)
|
||||
}
|
||||
for k, elem := range val {
|
||||
collectErrors(elem, fmt.Sprintf("%s.%s", path, k), errs)
|
||||
}
|
||||
default:
|
||||
// 其他类型暂不校验
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,35 @@
|
||||
{"level":"INFO","ts":"2025-11-05 16:59:43.475","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.1.136","elapsed":0.0009773,"trackId":"376656818492932096"}
|
||||
{"level":"INFO","ts":"2025-11-05 17:00:17.955","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.1.136","elapsed":0.0009184,"trackId":"376656963112534016"}
|
||||
{"level":"INFO","ts":"2025-11-05 17:00:21.027","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.1.136","elapsed":0,"trackId":"376656976001630208"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:35:40.062","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0005206,"trackId":"376726261852012544"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:35:47.481","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0008274,"trackId":"376726292969553920"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:35:48.665","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726297939804160"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:35:48.907","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726298954825728"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:35:49.171","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0009767,"trackId":"376726300057927680"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:37:38.008","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0005298,"trackId":"376726756557586432"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:18.445","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726926162657280"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:20.520","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0004533,"trackId":"376726934865838080"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:21.140","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726937466306560"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:21.288","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0004953,"trackId":"376726938082869248"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:21.609","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726939433435136"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:21.828","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726940351987712"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:22.088","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.000925,"trackId":"376726941438312448"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:22.281","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0002126,"trackId":"376726942252007424"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:22.476","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0002409,"trackId":"376726943069896704"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:22.663","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726943854231552"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:22.883","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726944776978432"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:23.100","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0007084,"trackId":"376726945682948096"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:23.324","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726946626666496"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:23.548","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726947566190592"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:23.796","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0007185,"trackId":"376726948606377984"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:23.992","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0002713,"trackId":"376726949424267264"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:24.230","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0006165,"trackId":"376726950422511616"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:24.432","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726951273955328"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:24.628","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726952096038912"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:25.076","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726953975087104"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:25.276","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0000358,"trackId":"376726954813947904"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:25.459","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726955581505536"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:25.664","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0004416,"trackId":"376726956437143552"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:25.864","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0005154,"trackId":"376726957276004352"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:26.084","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0.0002596,"trackId":"376726958202945536"}
|
||||
{"level":"INFO","ts":"2025-11-05 21:38:26.319","caller":"middleware/logger.go:34","msg":"接口请求","path":"/app/auth/login/default","method":"POST","ip":"192.168.5.3","elapsed":0,"trackId":"376726959188606976"}
|
||||
Reference in new issue
Block a user