mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-27 08:25:07 +00:00
feat: 手机验证码作为用户凭证
This commit is contained in:
@@ -11,6 +11,9 @@
|
|||||||
"format": "prettier --config \"./.prettierrc.js\" --write \"./src/**/*.{ts,tsx,scss}\""
|
"format": "prettier --config \"./.prettierrc.js\" --write \"./src/**/*.{ts,tsx,scss}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@alicloud/dysmsapi20170525": "^2.0.23",
|
||||||
|
"@alicloud/openapi-client": "^0.4.5",
|
||||||
|
"@alicloud/tea-util": "^1.4.5",
|
||||||
"@chakra-ui/icons": "^2.0.17",
|
"@chakra-ui/icons": "^2.0.17",
|
||||||
"@chakra-ui/react": "^2.5.1",
|
"@chakra-ui/react": "^2.5.1",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.6",
|
||||||
|
179
pnpm-lock.yaml
generated
179
pnpm-lock.yaml
generated
@@ -1,6 +1,9 @@
|
|||||||
lockfileVersion: 5.4
|
lockfileVersion: 5.4
|
||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
|
'@alicloud/dysmsapi20170525': ^2.0.23
|
||||||
|
'@alicloud/openapi-client': ^0.4.5
|
||||||
|
'@alicloud/tea-util': ^1.4.5
|
||||||
'@chakra-ui/icons': ^2.0.17
|
'@chakra-ui/icons': ^2.0.17
|
||||||
'@chakra-ui/react': ^2.5.1
|
'@chakra-ui/react': ^2.5.1
|
||||||
'@emotion/react': ^11.10.6
|
'@emotion/react': ^11.10.6
|
||||||
@@ -61,6 +64,9 @@ specifiers:
|
|||||||
zustand: ^4.3.5
|
zustand: ^4.3.5
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@alicloud/dysmsapi20170525': registry.npmmirror.com/@alicloud/dysmsapi20170525/2.0.23
|
||||||
|
'@alicloud/openapi-client': registry.npmmirror.com/@alicloud/openapi-client/0.4.5
|
||||||
|
'@alicloud/tea-util': registry.npmmirror.com/@alicloud/tea-util/1.4.5
|
||||||
'@chakra-ui/icons': registry.npmmirror.com/@chakra-ui/icons/2.0.17_react@18.2.0
|
'@chakra-ui/icons': registry.npmmirror.com/@chakra-ui/icons/2.0.17_react@18.2.0
|
||||||
'@chakra-ui/react': registry.npmmirror.com/@chakra-ui/react/2.5.1_e6pzu3hsaqmql4fl7jx73ckiym
|
'@chakra-ui/react': registry.npmmirror.com/@chakra-ui/react/2.5.1_e6pzu3hsaqmql4fl7jx73ckiym
|
||||||
'@emotion/react': registry.npmmirror.com/@emotion/react/11.10.6_pmekkgnqduwlme35zpnqhenc34
|
'@emotion/react': registry.npmmirror.com/@emotion/react/11.10.6_pmekkgnqduwlme35zpnqhenc34
|
||||||
@@ -124,6 +130,117 @@ devDependencies:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/credentials/2.2.6:
|
||||||
|
resolution: {integrity: sha512-jG+msY77dHmAF3x+8VTy7fEgORyXLHmDci8t92HeipBdCHsPptDegA++GEwKgR7f6G4wvafYt+aqMZ1iligdrQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/credentials/-/credentials-2.2.6.tgz}
|
||||||
|
name: '@alicloud/credentials'
|
||||||
|
version: 2.2.6
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
httpx: registry.npmmirror.com/httpx/2.2.7
|
||||||
|
ini: registry.npmmirror.com/ini/1.3.8
|
||||||
|
kitx: registry.npmmirror.com/kitx/2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/dysmsapi20170525/2.0.23:
|
||||||
|
resolution: {integrity: sha512-C02xj9S2ZPL13SciChlIY3s5+PiOM13jEGZSn+L92aiWYCBqTlpx9UMwNKBNWImMSOlG71IOSYfsQggaoIY+4Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/dysmsapi20170525/-/dysmsapi20170525-2.0.23.tgz}
|
||||||
|
name: '@alicloud/dysmsapi20170525'
|
||||||
|
version: 2.0.23
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/endpoint-util': registry.npmmirror.com/@alicloud/endpoint-util/0.0.1
|
||||||
|
'@alicloud/openapi-client': registry.npmmirror.com/@alicloud/openapi-client/0.4.5
|
||||||
|
'@alicloud/openapi-util': registry.npmmirror.com/@alicloud/openapi-util/0.3.1
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
'@alicloud/tea-util': registry.npmmirror.com/@alicloud/tea-util/1.4.5
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/endpoint-util/0.0.1:
|
||||||
|
resolution: {integrity: sha512-+pH7/KEXup84cHzIL6UJAaPqETvln4yXlD9JzlrqioyCSaWxbug5FUobsiI6fuUOpw5WwoB3fWAtGbFnJ1K3Yg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/endpoint-util/-/endpoint-util-0.0.1.tgz}
|
||||||
|
name: '@alicloud/endpoint-util'
|
||||||
|
version: 0.0.1
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
kitx: registry.npmmirror.com/kitx/2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/gateway-spi/0.0.8:
|
||||||
|
resolution: {integrity: sha512-KM7fu5asjxZPmrz9sJGHJeSU+cNQNOxW+SFmgmAIrITui5hXL2LB+KNRuzWmlwPjnuA2X3/keq9h6++S9jcV5g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/gateway-spi/-/gateway-spi-0.0.8.tgz}
|
||||||
|
name: '@alicloud/gateway-spi'
|
||||||
|
version: 0.0.8
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/credentials': registry.npmmirror.com/@alicloud/credentials/2.2.6
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/openapi-client/0.4.5:
|
||||||
|
resolution: {integrity: sha512-x1blwhfPOVkH/JCLWFssFRWDL0C75RToun9AwhNV+84gqJB2/GUipm3quHGLon8JiQ0DQ9YBUho2rukSoAvhJQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/openapi-client/-/openapi-client-0.4.5.tgz}
|
||||||
|
name: '@alicloud/openapi-client'
|
||||||
|
version: 0.4.5
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/credentials': registry.npmmirror.com/@alicloud/credentials/2.2.6
|
||||||
|
'@alicloud/gateway-spi': registry.npmmirror.com/@alicloud/gateway-spi/0.0.8
|
||||||
|
'@alicloud/openapi-util': registry.npmmirror.com/@alicloud/openapi-util/0.3.1
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
'@alicloud/tea-util': registry.npmmirror.com/@alicloud/tea-util/1.4.5
|
||||||
|
'@alicloud/tea-xml': registry.npmmirror.com/@alicloud/tea-xml/0.0.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/openapi-util/0.3.1:
|
||||||
|
resolution: {integrity: sha512-6mGT+hs+SXismZi/CEkjPhhbn2U3qTT/Qv/RXAYFA1DC3Jk4/YaX3N7RtpgdzOhdD7uI8XtNkaULKHZY3BrtxQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/openapi-util/-/openapi-util-0.3.1.tgz}
|
||||||
|
name: '@alicloud/openapi-util'
|
||||||
|
version: 0.3.1
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
'@alicloud/tea-util': registry.npmmirror.com/@alicloud/tea-util/1.4.5
|
||||||
|
kitx: registry.npmmirror.com/kitx/2.1.0
|
||||||
|
sm3: registry.npmmirror.com/sm3/1.0.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/tea-typescript/1.8.0:
|
||||||
|
resolution: {integrity: sha512-CWXWaquauJf0sW30mgJRVu9aaXyBth5uMBCUc+5vKTK1zlgf3hIqRUjJZbjlwHwQ5y9anwcu18r48nOZb7l2QQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/tea-typescript/-/tea-typescript-1.8.0.tgz}
|
||||||
|
name: '@alicloud/tea-typescript'
|
||||||
|
version: 1.8.0
|
||||||
|
dependencies:
|
||||||
|
'@types/node': registry.npmmirror.com/@types/node/12.20.55
|
||||||
|
httpx: registry.npmmirror.com/httpx/2.2.7
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/tea-util/1.4.5:
|
||||||
|
resolution: {integrity: sha512-7NuThYUi90/ivT/ORKusm0NVKlc1khPTtlzTR77xEqSBt7d24Ee/Lo70hx9PWP28nHpIZ1gM0NKYBtpq7HUDlg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/tea-util/-/tea-util-1.4.5.tgz}
|
||||||
|
name: '@alicloud/tea-util'
|
||||||
|
version: 1.4.5
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
kitx: registry.npmmirror.com/kitx/2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@alicloud/tea-xml/0.0.2:
|
||||||
|
resolution: {integrity: sha512-Xs7v5y7YSNSDDYmiDWAC0/013VWPjS3dQU4KezSLva9VGiTVPaL3S7Nk4NrTmAYCG6MKcrRj/nGEDIWL5KRoPg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@alicloud/tea-xml/-/tea-xml-0.0.2.tgz}
|
||||||
|
name: '@alicloud/tea-xml'
|
||||||
|
version: 0.0.2
|
||||||
|
dependencies:
|
||||||
|
'@alicloud/tea-typescript': registry.npmmirror.com/@alicloud/tea-typescript/1.8.0
|
||||||
|
'@types/xml2js': registry.npmmirror.com/@types/xml2js/0.4.11
|
||||||
|
xml2js: registry.npmmirror.com/xml2js/0.4.23
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/@ampproject/remapping/2.2.0:
|
registry.npmmirror.com/@ampproject/remapping/2.2.0:
|
||||||
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.0.tgz}
|
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.0.tgz}
|
||||||
name: '@ampproject/remapping'
|
name: '@ampproject/remapping'
|
||||||
@@ -5031,6 +5148,18 @@ packages:
|
|||||||
version: 0.7.31
|
version: 0.7.31
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@types/node/12.20.55:
|
||||||
|
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/node/-/node-12.20.55.tgz}
|
||||||
|
name: '@types/node'
|
||||||
|
version: 12.20.55
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@types/node/14.18.42:
|
||||||
|
resolution: {integrity: sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/node/-/node-14.18.42.tgz}
|
||||||
|
name: '@types/node'
|
||||||
|
version: 14.18.42
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/@types/node/18.14.0:
|
registry.npmmirror.com/@types/node/18.14.0:
|
||||||
resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/node/-/node-18.14.0.tgz}
|
resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/node/-/node-18.14.0.tgz}
|
||||||
name: '@types/node'
|
name: '@types/node'
|
||||||
@@ -5133,6 +5262,14 @@ packages:
|
|||||||
'@types/webidl-conversions': registry.npmmirror.com/@types/webidl-conversions/7.0.0
|
'@types/webidl-conversions': registry.npmmirror.com/@types/webidl-conversions/7.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/@types/xml2js/0.4.11:
|
||||||
|
resolution: {integrity: sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/xml2js/-/xml2js-0.4.11.tgz}
|
||||||
|
name: '@types/xml2js'
|
||||||
|
version: 0.4.11
|
||||||
|
dependencies:
|
||||||
|
'@types/node': registry.npmmirror.com/@types/node/18.14.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/@typescript-eslint/parser/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm:
|
registry.npmmirror.com/@typescript-eslint/parser/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm:
|
||||||
resolution: {integrity: sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.52.0.tgz}
|
resolution: {integrity: sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.52.0.tgz}
|
||||||
id: registry.npmmirror.com/@typescript-eslint/parser/5.52.0
|
id: registry.npmmirror.com/@typescript-eslint/parser/5.52.0
|
||||||
@@ -7650,6 +7787,17 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/httpx/2.2.7:
|
||||||
|
resolution: {integrity: sha512-Wjh2JOAah0pdczfqL8NC5378G7jMt0Zcpn8U+yyxAiejjlagzSTQgJHuVvka2VNPQlKfoGehYRc79WKq9E4gDw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/httpx/-/httpx-2.2.7.tgz}
|
||||||
|
name: httpx
|
||||||
|
version: 2.2.7
|
||||||
|
dependencies:
|
||||||
|
'@types/node': registry.npmmirror.com/@types/node/14.18.42
|
||||||
|
debug: registry.npmmirror.com/debug/4.3.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/human-signals/3.0.1:
|
registry.npmmirror.com/human-signals/3.0.1:
|
||||||
resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz}
|
resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz}
|
||||||
name: human-signals
|
name: human-signals
|
||||||
@@ -8284,6 +8432,14 @@ packages:
|
|||||||
commander: registry.npmmirror.com/commander/8.3.0
|
commander: registry.npmmirror.com/commander/8.3.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/kitx/2.1.0:
|
||||||
|
resolution: {integrity: sha512-C/5v9MtIX7aHGOjwn5BmrrbNkJSf7i0R5mRzmh13GSAdRqQ7bYQo/Su2pTYNylFicqKNTVX3HML9k1u8k51+pQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/kitx/-/kitx-2.1.0.tgz}
|
||||||
|
name: kitx
|
||||||
|
version: 2.1.0
|
||||||
|
dependencies:
|
||||||
|
'@types/node': registry.npmmirror.com/@types/node/12.20.55
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/kleur/4.1.5:
|
registry.npmmirror.com/kleur/4.1.5:
|
||||||
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/kleur/-/kleur-4.1.5.tgz}
|
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/kleur/-/kleur-4.1.5.tgz}
|
||||||
name: kleur
|
name: kleur
|
||||||
@@ -10598,6 +10754,12 @@ packages:
|
|||||||
is-fullwidth-code-point: registry.npmmirror.com/is-fullwidth-code-point/4.0.0
|
is-fullwidth-code-point: registry.npmmirror.com/is-fullwidth-code-point/4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
registry.npmmirror.com/sm3/1.0.3:
|
||||||
|
resolution: {integrity: sha512-KyFkIfr8QBlFG3uc3NaljaXdYcsbRy1KrSfc4tsQV8jW68jAktGeOcifu530Vx/5LC+PULHT0Rv8LiI8Gw+c1g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/sm3/-/sm3-1.0.3.tgz}
|
||||||
|
name: sm3
|
||||||
|
version: 1.0.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/smart-buffer/4.2.0:
|
registry.npmmirror.com/smart-buffer/4.2.0:
|
||||||
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz}
|
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz}
|
||||||
name: smart-buffer
|
name: smart-buffer
|
||||||
@@ -11618,6 +11780,16 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/xml2js/0.4.23:
|
||||||
|
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xml2js/-/xml2js-0.4.23.tgz}
|
||||||
|
name: xml2js
|
||||||
|
version: 0.4.23
|
||||||
|
engines: {node: '>=4.0.0'}
|
||||||
|
dependencies:
|
||||||
|
sax: registry.npmmirror.com/sax/1.1.6
|
||||||
|
xmlbuilder: registry.npmmirror.com/xmlbuilder/11.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/xmlbuilder/10.1.1:
|
registry.npmmirror.com/xmlbuilder/10.1.1:
|
||||||
resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz}
|
resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz}
|
||||||
name: xmlbuilder
|
name: xmlbuilder
|
||||||
@@ -11625,6 +11797,13 @@ packages:
|
|||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
registry.npmmirror.com/xmlbuilder/11.0.1:
|
||||||
|
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz}
|
||||||
|
name: xmlbuilder
|
||||||
|
version: 11.0.1
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/xregexp/2.0.0:
|
registry.npmmirror.com/xregexp/2.0.0:
|
||||||
resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xregexp/-/xregexp-2.0.0.tgz}
|
resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xregexp/-/xregexp-2.0.0.tgz}
|
||||||
name: xregexp
|
name: xregexp
|
||||||
|
@@ -9,7 +9,7 @@ wx号: fastgpt123
|
|||||||
|
|
||||||
|
|
||||||
### 快速开始
|
### 快速开始
|
||||||
1. 使用邮箱注册账号。
|
1. 使用手机号注册账号。
|
||||||
2. 进入账号页面,添加关联账号,目前只有 openai 的账号可以添加,直接去 openai 官网,把 API Key 粘贴过来。
|
2. 进入账号页面,添加关联账号,目前只有 openai 的账号可以添加,直接去 openai 官网,把 API Key 粘贴过来。
|
||||||
3. 如果填写了自己的 openai 账号,使用时会直接用你的账号。如果没有填写,需要付费使用平台的账号。
|
3. 如果填写了自己的 openai 账号,使用时会直接用你的账号。如果没有填写,需要付费使用平台的账号。
|
||||||
4. 进入模型页,创建一个模型,建议直接用 ChatGPT。
|
4. 进入模型页,创建一个模型,建议直接用 ChatGPT。
|
||||||
|
@@ -1,50 +1,55 @@
|
|||||||
import { GET, POST, PUT } from './request';
|
import { GET, POST, PUT } from './request';
|
||||||
import { createHashPassword, Obj2Query } from '@/utils/tools';
|
import { createHashPassword, Obj2Query } from '@/utils/tools';
|
||||||
import { ResLogin } from './response/user';
|
import { ResLogin } from './response/user';
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
import { UserType, UserUpdateParams } from '@/types/user';
|
import { UserType, UserUpdateParams } from '@/types/user';
|
||||||
import type { PagingData, RequestPaging } from '@/types';
|
import type { PagingData, RequestPaging } from '@/types';
|
||||||
import { BillSchema, PaySchema } from '@/types/mongoSchema';
|
import { BillSchema, PaySchema } from '@/types/mongoSchema';
|
||||||
import { adaptBill } from '@/utils/adapt';
|
import { adaptBill } from '@/utils/adapt';
|
||||||
|
|
||||||
export const sendCodeToEmail = ({ email, type }: { email: string; type: `${EmailTypeEnum}` }) =>
|
export const sendAuthCode = ({
|
||||||
GET('/user/sendEmail', { email, type });
|
username,
|
||||||
|
type
|
||||||
|
}: {
|
||||||
|
username: string;
|
||||||
|
type: `${UserAuthTypeEnum}`;
|
||||||
|
}) => GET('/user/sendAuthCode', { username, type });
|
||||||
|
|
||||||
export const getTokenLogin = () => GET<UserType>('/user/tokenLogin');
|
export const getTokenLogin = () => GET<UserType>('/user/tokenLogin');
|
||||||
|
|
||||||
export const postRegister = ({
|
export const postRegister = ({
|
||||||
email,
|
phone,
|
||||||
password,
|
password,
|
||||||
code
|
code
|
||||||
}: {
|
}: {
|
||||||
email: string;
|
phone: string;
|
||||||
code: string;
|
code: string;
|
||||||
password: string;
|
password: string;
|
||||||
}) =>
|
}) =>
|
||||||
POST<ResLogin>('/user/register', {
|
POST<ResLogin>('/user/register', {
|
||||||
email,
|
phone,
|
||||||
code,
|
code,
|
||||||
password: createHashPassword(password)
|
password: createHashPassword(password)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const postFindPassword = ({
|
export const postFindPassword = ({
|
||||||
email,
|
username,
|
||||||
code,
|
code,
|
||||||
password
|
password
|
||||||
}: {
|
}: {
|
||||||
email: string;
|
username: string;
|
||||||
code: string;
|
code: string;
|
||||||
password: string;
|
password: string;
|
||||||
}) =>
|
}) =>
|
||||||
POST<ResLogin>('/user/updatePasswordByCode', {
|
POST<ResLogin>('/user/updatePasswordByCode', {
|
||||||
email,
|
username,
|
||||||
code,
|
code,
|
||||||
password: createHashPassword(password)
|
password: createHashPassword(password)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const postLogin = ({ email, password }: { email: string; password: string }) =>
|
export const postLogin = ({ username, password }: { username: string; password: string }) =>
|
||||||
POST<ResLogin>('/user/loginByPassword', {
|
POST<ResLogin>('/user/loginByPassword', {
|
||||||
email,
|
username,
|
||||||
password: createHashPassword(password)
|
password: createHashPassword(password)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
export enum EmailTypeEnum {
|
export enum UserAuthTypeEnum {
|
||||||
register = 'register',
|
register = 'register',
|
||||||
findPassword = 'findPassword'
|
findPassword = 'findPassword'
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useMemo, useCallback } from 'react';
|
import { useState, useMemo, useCallback } from 'react';
|
||||||
import { sendCodeToEmail } from '@/api/user';
|
import { sendAuthCode } from '@/api/user';
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
let timer: any;
|
let timer: any;
|
||||||
import { useToast } from './useToast';
|
import { useToast } from './useToast';
|
||||||
|
|
||||||
@@ -19,11 +19,11 @@ export const useSendCode = () => {
|
|||||||
}, [codeCountDown]);
|
}, [codeCountDown]);
|
||||||
|
|
||||||
const sendCode = useCallback(
|
const sendCode = useCallback(
|
||||||
async ({ email, type }: { email: string; type: `${EmailTypeEnum}` }) => {
|
async ({ username, type }: { username: string; type: `${UserAuthTypeEnum}` }) => {
|
||||||
setCodeSending(true);
|
setCodeSending(true);
|
||||||
try {
|
try {
|
||||||
await sendCodeToEmail({
|
await sendAuthCode({
|
||||||
email,
|
username,
|
||||||
type
|
type
|
||||||
});
|
});
|
||||||
setCodeCountDown(60);
|
setCodeCountDown(60);
|
||||||
|
@@ -7,24 +7,24 @@ import { generateToken } from '@/service/utils/tools';
|
|||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
try {
|
try {
|
||||||
const { email, password } = req.body;
|
const { username, password } = req.body;
|
||||||
|
|
||||||
if (!email || !password) {
|
if (!username || !password) {
|
||||||
throw new Error('缺少参数');
|
throw new Error('缺少参数');
|
||||||
}
|
}
|
||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
// 检测邮箱是否存在
|
// 检测用户是否存在
|
||||||
const authEmail = await User.findOne({
|
const authUser = await User.findOne({
|
||||||
email
|
username
|
||||||
});
|
});
|
||||||
if (!authEmail) {
|
if (!authUser) {
|
||||||
throw new Error('邮箱未注册');
|
throw new Error('用户未注册');
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email,
|
username,
|
||||||
password
|
password
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -5,23 +5,29 @@ import { User } from '@/service/models/user';
|
|||||||
import { AuthCode } from '@/service/models/authCode';
|
import { AuthCode } from '@/service/models/authCode';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { generateToken } from '@/service/utils/tools';
|
import { generateToken } from '@/service/utils/tools';
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
const { email, code, password } = req.body;
|
const { phone, code, password } = req.body;
|
||||||
|
|
||||||
if (!email || !code || !password) {
|
if (!phone || !code || !password) {
|
||||||
throw new Error('缺少参数');
|
throw new Error('缺少参数');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reg = /^1[3456789]\d{9}$/;
|
||||||
|
|
||||||
|
if (!reg.test(phone)) {
|
||||||
|
throw new Error('手机号格式错误');
|
||||||
|
}
|
||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
// 验证码校验
|
// 验证码校验. 注册只接收手机号
|
||||||
const authCode = await AuthCode.findOne({
|
const authCode = await AuthCode.findOne({
|
||||||
email,
|
username: phone,
|
||||||
code,
|
code,
|
||||||
type: EmailTypeEnum.register,
|
type: UserAuthTypeEnum.register,
|
||||||
expiredTime: { $gte: Date.now() }
|
expiredTime: { $gte: Date.now() }
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -31,15 +37,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
// 重名校验
|
// 重名校验
|
||||||
const authRepeat = await User.findOne({
|
const authRepeat = await User.findOne({
|
||||||
email
|
username: phone
|
||||||
});
|
});
|
||||||
|
|
||||||
if (authRepeat) {
|
if (authRepeat) {
|
||||||
throw new Error('邮箱已被注册');
|
throw new Error('手机号已被注册');
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await User.create({
|
const response = await User.create({
|
||||||
email,
|
username: phone,
|
||||||
password
|
password
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -50,6 +56,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
throw new Error('获取用户信息异常');
|
throw new Error('获取用户信息异常');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除验证码记录
|
||||||
|
await AuthCode.deleteMany({
|
||||||
|
username: phone
|
||||||
|
});
|
||||||
|
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
data: {
|
data: {
|
||||||
token: generateToken(user._id),
|
token: generateToken(user._id),
|
||||||
|
@@ -2,28 +2,27 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { AuthCode } from '@/service/models/authCode';
|
import { AuthCode } from '@/service/models/authCode';
|
||||||
import { connectToDatabase, User } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { sendCode } from '@/service/utils/sendEmail';
|
import { sendPhoneCode, sendEmailCode } from '@/service/utils/sendNote';
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
|
import { customAlphabet } from 'nanoid';
|
||||||
|
const nanoid = customAlphabet('1234567890', 6);
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
try {
|
try {
|
||||||
const { email, type } = req.query as { email: string; type: `${EmailTypeEnum}` };
|
const { username, type } = req.query as { username: string; type: `${UserAuthTypeEnum}` };
|
||||||
|
|
||||||
if (!email || !type) {
|
if (!username || !type) {
|
||||||
throw new Error('缺少参数');
|
throw new Error('缺少参数');
|
||||||
}
|
}
|
||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
let code = '';
|
let code = nanoid();
|
||||||
for (let i = 0; i < 6; i++) {
|
|
||||||
code += Math.floor(Math.random() * 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断 1 分钟内是否有重复数据
|
// 判断 1 分钟内是否有重复数据
|
||||||
const authCode = await AuthCode.findOne({
|
const authCode = await AuthCode.findOne({
|
||||||
email,
|
username,
|
||||||
type,
|
type,
|
||||||
expiredTime: { $gte: Date.now() + 4 * 60 * 1000 } // 如果有一个记录的过期时间,大于当前+4分钟,说明距离上次发送还没到1分钟。(因为默认创建时,过期时间是未来5分钟)
|
expiredTime: { $gte: Date.now() + 4 * 60 * 1000 } // 如果有一个记录的过期时间,大于当前+4分钟,说明距离上次发送还没到1分钟。(因为默认创建时,过期时间是未来5分钟)
|
||||||
});
|
});
|
||||||
@@ -34,13 +33,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
// 创建 auth 记录
|
// 创建 auth 记录
|
||||||
await AuthCode.create({
|
await AuthCode.create({
|
||||||
email,
|
username,
|
||||||
type,
|
type,
|
||||||
code
|
code
|
||||||
});
|
});
|
||||||
|
|
||||||
// 发送验证码
|
if (username.includes('@')) {
|
||||||
await sendCode(email as string, code, type as `${EmailTypeEnum}`);
|
await sendEmailCode(username, code, type);
|
||||||
|
} else {
|
||||||
|
// 发送验证码
|
||||||
|
await sendPhoneCode(username, code);
|
||||||
|
}
|
||||||
|
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
message: '发送验证码成功'
|
message: '发送验证码成功'
|
@@ -5,13 +5,13 @@ import { User } from '@/service/models/user';
|
|||||||
import { AuthCode } from '@/service/models/authCode';
|
import { AuthCode } from '@/service/models/authCode';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { generateToken } from '@/service/utils/tools';
|
import { generateToken } from '@/service/utils/tools';
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
const { email, code, password } = req.body;
|
const { username, code, password } = req.body;
|
||||||
|
|
||||||
if (!email || !code || !password) {
|
if (!username || !code || !password) {
|
||||||
throw new Error('缺少参数');
|
throw new Error('缺少参数');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
// 验证码校验
|
// 验证码校验
|
||||||
const authCode = await AuthCode.findOne({
|
const authCode = await AuthCode.findOne({
|
||||||
email,
|
username,
|
||||||
code,
|
code,
|
||||||
type: EmailTypeEnum.findPassword,
|
type: UserAuthTypeEnum.findPassword,
|
||||||
expiredTime: { $gte: Date.now() }
|
expiredTime: { $gte: Date.now() }
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,16 +32,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
// 更新对应的记录
|
// 更新对应的记录
|
||||||
await User.updateOne(
|
await User.updateOne(
|
||||||
{
|
{
|
||||||
email
|
username
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
password
|
password
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 根据 email 获取用户信息
|
// 根据 username 获取用户信息
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email
|
username
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@@ -14,7 +14,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RegisterType {
|
interface RegisterType {
|
||||||
email: string;
|
username: string;
|
||||||
code: string;
|
code: string;
|
||||||
password: string;
|
password: string;
|
||||||
password2: string;
|
password2: string;
|
||||||
@@ -36,10 +36,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
|
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
|
||||||
|
|
||||||
const onclickSendCode = useCallback(async () => {
|
const onclickSendCode = useCallback(async () => {
|
||||||
const check = await trigger('email');
|
const check = await trigger('username');
|
||||||
if (!check) return;
|
if (!check) return;
|
||||||
sendCode({
|
sendCode({
|
||||||
email: getValues('email'),
|
username: getValues('username'),
|
||||||
type: 'findPassword'
|
type: 'findPassword'
|
||||||
});
|
});
|
||||||
}, [getValues, sendCode, trigger]);
|
}, [getValues, sendCode, trigger]);
|
||||||
@@ -47,12 +47,12 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
const [requesting, setRequesting] = useState(false);
|
const [requesting, setRequesting] = useState(false);
|
||||||
|
|
||||||
const onclickFindPassword = useCallback(
|
const onclickFindPassword = useCallback(
|
||||||
async ({ email, code, password }: RegisterType) => {
|
async ({ username, code, password }: RegisterType) => {
|
||||||
setRequesting(true);
|
setRequesting(true);
|
||||||
try {
|
try {
|
||||||
loginSuccess(
|
loginSuccess(
|
||||||
await postFindPassword({
|
await postFindPassword({
|
||||||
email,
|
username,
|
||||||
code,
|
code,
|
||||||
password
|
password
|
||||||
})
|
})
|
||||||
@@ -78,23 +78,24 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
找回 FastGPT 账号
|
找回 FastGPT 账号
|
||||||
</Box>
|
</Box>
|
||||||
<form onSubmit={handleSubmit(onclickFindPassword)}>
|
<form onSubmit={handleSubmit(onclickFindPassword)}>
|
||||||
<FormControl mt={8} isInvalid={!!errors.email}>
|
<FormControl mt={8} isInvalid={!!errors.username}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="邮箱"
|
placeholder="邮箱/手机号"
|
||||||
size={mediaLgMd}
|
size={mediaLgMd}
|
||||||
{...register('email', {
|
{...register('username', {
|
||||||
required: '邮箱不能为空',
|
required: '邮箱/手机号不能为空',
|
||||||
pattern: {
|
pattern: {
|
||||||
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
|
value:
|
||||||
message: '邮箱错误'
|
/(^1[3456789]\d{9}$)|(^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$)/,
|
||||||
|
message: '邮箱/手机号格式错误'
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
></Input>
|
></Input>
|
||||||
<FormErrorMessage position={'absolute'} fontSize="xs">
|
<FormErrorMessage position={'absolute'} fontSize="xs">
|
||||||
{!!errors.email && errors.email.message}
|
{!!errors.username && errors.username.message}
|
||||||
</FormErrorMessage>
|
</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={8} isInvalid={!!errors.email}>
|
<FormControl mt={8} isInvalid={!!errors.username}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Input
|
<Input
|
||||||
flex={1}
|
flex={1}
|
||||||
|
@@ -13,7 +13,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface LoginFormType {
|
interface LoginFormType {
|
||||||
email: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
const [requesting, setRequesting] = useState(false);
|
const [requesting, setRequesting] = useState(false);
|
||||||
|
|
||||||
const onclickLogin = useCallback(
|
const onclickLogin = useCallback(
|
||||||
async ({ email, password }: LoginFormType) => {
|
async ({ username, password }: LoginFormType) => {
|
||||||
setRequesting(true);
|
setRequesting(true);
|
||||||
try {
|
try {
|
||||||
loginSuccess(
|
loginSuccess(
|
||||||
await postLogin({
|
await postLogin({
|
||||||
email,
|
username,
|
||||||
password
|
password
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -59,20 +59,21 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
登录 FastGPT
|
登录 FastGPT
|
||||||
</Box>
|
</Box>
|
||||||
<form onSubmit={handleSubmit(onclickLogin)}>
|
<form onSubmit={handleSubmit(onclickLogin)}>
|
||||||
<FormControl mt={8} isInvalid={!!errors.email}>
|
<FormControl mt={8} isInvalid={!!errors.username}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="邮箱"
|
placeholder="邮箱/手机号"
|
||||||
size={mediaLgMd}
|
size={mediaLgMd}
|
||||||
{...register('email', {
|
{...register('username', {
|
||||||
required: '邮箱不能为空',
|
required: '邮箱/手机号不能为空',
|
||||||
pattern: {
|
pattern: {
|
||||||
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
|
value:
|
||||||
message: '邮箱错误'
|
/(^1[3456789]\d{9}$)|(^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$)/,
|
||||||
|
message: '邮箱/手机号格式错误'
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
></Input>
|
></Input>
|
||||||
<FormErrorMessage position={'absolute'} fontSize="xs">
|
<FormErrorMessage position={'absolute'} fontSize="xs">
|
||||||
{!!errors.email && errors.email.message}
|
{!!errors.username && errors.username.message}
|
||||||
</FormErrorMessage>
|
</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={8} isInvalid={!!errors.password}>
|
<FormControl mt={8} isInvalid={!!errors.password}>
|
||||||
|
@@ -14,7 +14,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RegisterType {
|
interface RegisterType {
|
||||||
email: string;
|
phone: string;
|
||||||
password: string;
|
password: string;
|
||||||
password2: string;
|
password2: string;
|
||||||
code: string;
|
code: string;
|
||||||
@@ -36,10 +36,10 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
|
const { codeSending, sendCodeText, sendCode, codeCountDown } = useSendCode();
|
||||||
|
|
||||||
const onclickSendCode = useCallback(async () => {
|
const onclickSendCode = useCallback(async () => {
|
||||||
const check = await trigger('email');
|
const check = await trigger('phone');
|
||||||
if (!check) return;
|
if (!check) return;
|
||||||
sendCode({
|
sendCode({
|
||||||
email: getValues('email'),
|
username: getValues('phone'),
|
||||||
type: 'register'
|
type: 'register'
|
||||||
});
|
});
|
||||||
}, [getValues, sendCode, trigger]);
|
}, [getValues, sendCode, trigger]);
|
||||||
@@ -47,12 +47,12 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
const [requesting, setRequesting] = useState(false);
|
const [requesting, setRequesting] = useState(false);
|
||||||
|
|
||||||
const onclickRegister = useCallback(
|
const onclickRegister = useCallback(
|
||||||
async ({ email, password, code }: RegisterType) => {
|
async ({ phone, password, code }: RegisterType) => {
|
||||||
setRequesting(true);
|
setRequesting(true);
|
||||||
try {
|
try {
|
||||||
loginSuccess(
|
loginSuccess(
|
||||||
await postRegister({
|
await postRegister({
|
||||||
email,
|
phone,
|
||||||
code,
|
code,
|
||||||
password
|
password
|
||||||
})
|
})
|
||||||
@@ -78,23 +78,23 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
注册 FastGPT 账号
|
注册 FastGPT 账号
|
||||||
</Box>
|
</Box>
|
||||||
<form onSubmit={handleSubmit(onclickRegister)}>
|
<form onSubmit={handleSubmit(onclickRegister)}>
|
||||||
<FormControl mt={8} isInvalid={!!errors.email}>
|
<FormControl mt={8} isInvalid={!!errors.phone}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="邮箱"
|
placeholder="手机号"
|
||||||
size={mediaLgMd}
|
size={mediaLgMd}
|
||||||
{...register('email', {
|
{...register('phone', {
|
||||||
required: '邮箱不能为空',
|
required: '手机号不能为空',
|
||||||
pattern: {
|
pattern: {
|
||||||
value: /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/,
|
value: /^1[3456789]\d{9}$/,
|
||||||
message: '邮箱错误'
|
message: '手机号格式错误'
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
></Input>
|
></Input>
|
||||||
<FormErrorMessage position={'absolute'} fontSize="xs">
|
<FormErrorMessage position={'absolute'} fontSize="xs">
|
||||||
{!!errors.email && errors.email.message}
|
{!!errors.phone && errors.phone.message}
|
||||||
</FormErrorMessage>
|
</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={8} isInvalid={!!errors.email}>
|
<FormControl mt={8} isInvalid={!!errors.phone}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Input
|
<Input
|
||||||
flex={1}
|
flex={1}
|
||||||
|
@@ -51,8 +51,8 @@ const NumberSetting = () => {
|
|||||||
账号信息
|
账号信息
|
||||||
</Box>
|
</Box>
|
||||||
<Flex mt={6} alignItems={'center'}>
|
<Flex mt={6} alignItems={'center'}>
|
||||||
<Box flex={'0 0 60px'}>邮箱:</Box>
|
<Box flex={'0 0 60px'}>用户账号:</Box>
|
||||||
<Box>{userInfo?.email}</Box>
|
<Box>{userInfo?.username}</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box mt={6}>
|
<Box mt={6}>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
|
@@ -2,7 +2,7 @@ import { Schema, model, models, Model } from 'mongoose';
|
|||||||
import { AuthCodeSchema as AuthCodeType } from '@/types/mongoSchema';
|
import { AuthCodeSchema as AuthCodeType } from '@/types/mongoSchema';
|
||||||
|
|
||||||
const AuthCodeSchema = new Schema({
|
const AuthCodeSchema = new Schema({
|
||||||
email: {
|
username: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
@@ -3,7 +3,8 @@ import { hashPassword } from '@/service/utils/tools';
|
|||||||
import { PRICE_SCALE } from '@/constants/common';
|
import { PRICE_SCALE } from '@/constants/common';
|
||||||
import { UserModelSchema } from '@/types/mongoSchema';
|
import { UserModelSchema } from '@/types/mongoSchema';
|
||||||
const UserSchema = new Schema({
|
const UserSchema = new Schema({
|
||||||
email: {
|
username: {
|
||||||
|
// 可以是手机/邮箱,新的验证都只用手机
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
unique: true // 唯一
|
unique: true // 唯一
|
||||||
|
@@ -1,63 +0,0 @@
|
|||||||
import * as nodemailer from 'nodemailer';
|
|
||||||
import { EmailTypeEnum } from '@/constants/common';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
const myEmail = process.env.MY_MAIL;
|
|
||||||
let mailTransport = nodemailer.createTransport({
|
|
||||||
// host: 'smtp.qq.email',
|
|
||||||
service: 'qq',
|
|
||||||
secure: true, //安全方式发送,建议都加上
|
|
||||||
auth: {
|
|
||||||
user: myEmail,
|
|
||||||
pass: process.env.MAILE_CODE
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emailMap: { [key: string]: any } = {
|
|
||||||
[EmailTypeEnum.register]: {
|
|
||||||
subject: '注册 FastGPT 账号',
|
|
||||||
html: (code: string) => `<div>您正在注册 FastGPT 账号,验证码为:${code}</div>`
|
|
||||||
},
|
|
||||||
[EmailTypeEnum.findPassword]: {
|
|
||||||
subject: '修改 FastGPT 密码',
|
|
||||||
html: (code: string) => `<div>您正在修改 FastGPT 账号密码,验证码为:${code}</div>`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const sendCode = (email: string, code: string, type: `${EmailTypeEnum}`) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const options = {
|
|
||||||
from: `"FastGPT" ${myEmail}`,
|
|
||||||
to: email,
|
|
||||||
subject: emailMap[type]?.subject,
|
|
||||||
html: emailMap[type]?.html(code)
|
|
||||||
};
|
|
||||||
mailTransport.sendMail(options, function (err, msg) {
|
|
||||||
if (err) {
|
|
||||||
console.log('send email error->', err);
|
|
||||||
reject('邮箱异常');
|
|
||||||
} else {
|
|
||||||
resolve('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const sendTrainSucceed = (email: string, modelName: string) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const options = {
|
|
||||||
from: `"FastGPT" ${myEmail}`,
|
|
||||||
to: email,
|
|
||||||
subject: '模型训练完成通知',
|
|
||||||
html: `你的模型 ${modelName} 已于 ${dayjs().format('YYYY-MM-DD HH:mm')} 训练完成!`
|
|
||||||
};
|
|
||||||
mailTransport.sendMail(options, function (err, msg) {
|
|
||||||
if (err) {
|
|
||||||
console.log('send email error->', err);
|
|
||||||
reject('邮箱异常');
|
|
||||||
} else {
|
|
||||||
resolve('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
72
src/service/utils/sendNote.ts
Normal file
72
src/service/utils/sendNote.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import * as nodemailer from 'nodemailer';
|
||||||
|
import { UserAuthTypeEnum } from '@/constants/common';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import Dysmsapi, * as dysmsapi from '@alicloud/dysmsapi20170525';
|
||||||
|
// @ts-ignore
|
||||||
|
import * as OpenApi from '@alicloud/openapi-client';
|
||||||
|
// @ts-ignore
|
||||||
|
import * as Util from '@alicloud/tea-util';
|
||||||
|
|
||||||
|
const myEmail = process.env.MY_MAIL;
|
||||||
|
const mailTransport = nodemailer.createTransport({
|
||||||
|
// host: 'smtp.qq.phone',
|
||||||
|
service: 'qq',
|
||||||
|
secure: true, //安全方式发送,建议都加上
|
||||||
|
auth: {
|
||||||
|
user: myEmail,
|
||||||
|
pass: process.env.MAILE_CODE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emailMap: { [key: string]: any } = {
|
||||||
|
[UserAuthTypeEnum.register]: {
|
||||||
|
subject: '注册 FastGPT 账号',
|
||||||
|
html: (code: string) => `<div>您正在注册 FastGPT 账号,验证码为:${code}</div>`
|
||||||
|
},
|
||||||
|
[UserAuthTypeEnum.findPassword]: {
|
||||||
|
subject: '修改 FastGPT 密码',
|
||||||
|
html: (code: string) => `<div>您正在修改 FastGPT 账号密码,验证码为:${code}</div>`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sendEmailCode = (email: string, code: string, type: `${UserAuthTypeEnum}`) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const options = {
|
||||||
|
from: `"FastGPT" ${myEmail}`,
|
||||||
|
to: email,
|
||||||
|
subject: emailMap[type]?.subject,
|
||||||
|
html: emailMap[type]?.html(code)
|
||||||
|
};
|
||||||
|
mailTransport.sendMail(options, function (err, msg) {
|
||||||
|
if (err) {
|
||||||
|
console.log('send email error->', err);
|
||||||
|
reject('发生邮件异常');
|
||||||
|
} else {
|
||||||
|
resolve('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sendPhoneCode = async (phone: string, code: string) => {
|
||||||
|
const accessKeyId = process.env.aliAccessKeyId;
|
||||||
|
const accessKeySecret = process.env.aliAccessKeySecret;
|
||||||
|
const signName = process.env.aliSignName;
|
||||||
|
const templateCode = process.env.aliTemplateCode;
|
||||||
|
const endpoint = 'dysmsapi.aliyuncs.com';
|
||||||
|
|
||||||
|
const sendSmsRequest = new dysmsapi.SendSmsRequest({
|
||||||
|
phoneNumbers: phone,
|
||||||
|
signName,
|
||||||
|
templateCode,
|
||||||
|
templateParam: `{"code":${code}}`
|
||||||
|
});
|
||||||
|
|
||||||
|
const config = new OpenApi.Config({ accessKeyId, accessKeySecret, endpoint });
|
||||||
|
const client = new Dysmsapi(config);
|
||||||
|
const runtime = new Util.RuntimeOptions({});
|
||||||
|
const res = await client.sendSmsWithOptions(sendSmsRequest, runtime);
|
||||||
|
if (res.body.code !== 'OK') {
|
||||||
|
return Promise.reject(res.body.message || '发送短信失败');
|
||||||
|
}
|
||||||
|
};
|
4
src/types/mongoSchema.d.ts
vendored
4
src/types/mongoSchema.d.ts
vendored
@@ -11,7 +11,7 @@ export type ServiceName = 'openai';
|
|||||||
|
|
||||||
export interface UserModelSchema {
|
export interface UserModelSchema {
|
||||||
_id: string;
|
_id: string;
|
||||||
email: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
balance: number;
|
balance: number;
|
||||||
openaiKey: string;
|
openaiKey: string;
|
||||||
@@ -20,7 +20,7 @@ export interface UserModelSchema {
|
|||||||
|
|
||||||
export interface AuthCodeSchema {
|
export interface AuthCodeSchema {
|
||||||
_id: string;
|
_id: string;
|
||||||
email: string;
|
username: string;
|
||||||
code: string;
|
code: string;
|
||||||
type: 'register' | 'findPassword';
|
type: 'register' | 'findPassword';
|
||||||
expiredTime: number;
|
expiredTime: number;
|
||||||
|
7
src/types/user.d.ts
vendored
7
src/types/user.d.ts
vendored
@@ -1,11 +1,6 @@
|
|||||||
export enum UserNumberEnum {
|
|
||||||
phone = 'phone',
|
|
||||||
wx = 'wx'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserType {
|
export interface UserType {
|
||||||
_id: string;
|
_id: string;
|
||||||
email: string;
|
username: string;
|
||||||
openaiKey: string;
|
openaiKey: string;
|
||||||
balance: number;
|
balance: number;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user