feat: 手机验证码作为用户凭证

This commit is contained in:
archer
2023-04-16 19:53:50 +08:00
parent 36dad6df33
commit faf722fa15
20 changed files with 375 additions and 167 deletions

View File

@@ -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
View File

@@ -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

View File

@@ -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。

View File

@@ -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)
}); });

View File

@@ -1,4 +1,4 @@
export enum EmailTypeEnum { export enum UserAuthTypeEnum {
register = 'register', register = 'register',
findPassword = 'findPassword' findPassword = 'findPassword'
} }

View File

@@ -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);

View File

@@ -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
}); });

View File

@@ -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),

View File

@@ -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: '发送验证码成功'

View File

@@ -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) {

View File

@@ -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}

View File

@@ -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}>

View File

@@ -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}

View File

@@ -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'}>

View File

@@ -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
}, },

View File

@@ -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 // 唯一

View File

@@ -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('');
}
});
});
};

View 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 || '发送短信失败');
}
};

View File

@@ -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
View File

@@ -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;
} }