message-verify 1.0.0 → 1.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.arcconfig +0 -4
- package/dist/index.d.ts +2 -3
- package/dist/index.js +30 -55
- package/dist/locales/en.d.ts +0 -5
- package/dist/locales/en.js +1 -6
- package/dist/locales/id.d.ts +0 -5
- package/dist/locales/id.js +1 -6
- package/dist/locales/zh.d.ts +0 -5
- package/dist/locales/zh.js +1 -6
- package/dist/main.js +37 -42
- package/dist/relogin-modal.d.ts +2 -2
- package/dist/relogin-modal.js +7 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/type.d.ts +3 -14
- package/dist/verify-modal.d.ts +2 -2
- package/dist/verify-modal.js +19 -40
- package/eslint.config.js +1 -2
- package/package.json +2 -3
- package/src/index.tsx +44 -70
- package/src/locales/en.ts +1 -6
- package/src/locales/id.ts +1 -6
- package/src/locales/zh.ts +1 -6
- package/src/main.tsx +39 -48
- package/src/{modal/relogin-modal.tsx → relogin-modal.tsx} +11 -13
- package/src/utils/type.ts +3 -13
- package/src/{modal/verify-modal.tsx → verify-modal.tsx} +28 -50
- package/arcanist/.phutil_module_cache +0 -1
- package/arcanist/__phutil_library_init__.php +0 -3
- package/arcanist/__phutil_library_map__.php +0 -18
- package/arcanist/lint/engine/YqgWebDiffLintEngine.php +0 -68
- package/dist/modal/relogin-modal.d.ts +0 -5
- package/dist/modal/relogin-modal.js +0 -24
- package/dist/modal/verify-modal.d.ts +0 -5
- package/dist/modal/verify-modal.js +0 -115
- package/dist/utils/resource.d.ts +0 -2
- package/dist/utils/resource.js +0 -7
- /package/src/{utils/resource.ts → resource.ts} +0 -0
package/src/locales/id.ts
CHANGED
@@ -6,10 +6,5 @@ export default {
|
|
6
6
|
sendSuccess: 'Berhasil dikirim',
|
7
7
|
sendFailed: 'Gagal mengirim',
|
8
8
|
reSend: 'Kirim Ulang',
|
9
|
-
countDownSecound: '{countdown} detik'
|
10
|
-
accountAlert: 'Peringatan Keamanan Akun',
|
11
|
-
alertContent: 'Terdeteksi perubahan pada lingkungan login atau informasi jaringan Anda.Untuk menjaga keamanan akun, silakan login kembali untuk memverifikasi identitas Anda.',
|
12
|
-
ok: 'Baiklah',
|
13
|
-
chidoriOpenPro: 'chidori telah mengaktifkan keamanan untuk Anda',
|
14
|
-
verifyFail: 'Autentikasi gagal'
|
9
|
+
countDownSecound: '{countdown} detik'
|
15
10
|
};
|
package/src/locales/zh.ts
CHANGED
@@ -6,10 +6,5 @@ export default {
|
|
6
6
|
sendSuccess: '发送成功',
|
7
7
|
sendFailed: '发送失败',
|
8
8
|
reSend: '重新发送',
|
9
|
-
countDownSecound: '{countdown}秒'
|
10
|
-
accountAlert: '账号安全提醒',
|
11
|
-
alertContent: '检测到您的登录环境或网络信息有变动,为保障账户安全,请重新登录验证身份',
|
12
|
-
ok: '好的',
|
13
|
-
chidoriOpenPro: 'chidori已为您开启安全防护',
|
14
|
-
verifyFail: '验证失败'
|
9
|
+
countDownSecound: '{countdown}秒'
|
15
10
|
};
|
package/src/main.tsx
CHANGED
@@ -1,58 +1,49 @@
|
|
1
1
|
import { createRoot } from 'react-dom/client';
|
2
|
-
import {
|
2
|
+
import { createMessageVerifyModal, initFingerprint } from './index.js'; // 或 './index'
|
3
3
|
import { axios } from '@yqg/resource';
|
4
4
|
|
5
5
|
const data = "{\"mobile\":\"188****4035\",\"verifyCodeKey\":\"3f025b33-988e-47c0-950d-6beb776d043f\",\"needValid\":true,\"step\":2,\"message\":\"需要填写验证码\"}";
|
6
6
|
|
7
7
|
const fp = await initFingerprint();
|
8
|
-
|
9
|
-
console.log(fp, fp2);
|
8
|
+
console.log(fp);
|
10
9
|
|
11
|
-
const config = {
|
12
|
-
"transitional": {
|
13
|
-
"silentJSONParsing": true,
|
14
|
-
"forcedJSONParsing": true,
|
15
|
-
"clarifyTimeoutError": false
|
16
|
-
},
|
17
|
-
"timeout": 0,
|
18
|
-
"xsrfCookieName": "XSRF-TOKEN",
|
19
|
-
"xsrfHeaderName": "X-XSRF-TOKEN",
|
20
|
-
"maxContentLength": -1,
|
21
|
-
"maxBodyLength": -1,
|
22
|
-
"headers": {
|
23
|
-
"Accept": "application/json, text/plain, */*",
|
24
|
-
"X-Device-Fingerprint": "531f14c7176b16ebeb18e2b23d6bd124",
|
25
|
-
"Content-Type": "application/json"
|
26
|
-
},
|
27
|
-
"url": "/classification/admin/level/edit",
|
28
|
-
"method": "post",
|
29
|
-
"dataFormat": "JSON",
|
30
|
-
"showRequestData": true,
|
31
|
-
"showResponseData": false,
|
32
|
-
"showGeneralResponseData": true,
|
33
|
-
"headersList": [],
|
34
|
-
"requestDataFunc": "\nfunction(formFilterData){\n // 这里写你的处理逻辑\n return {\n ...formFilterData,\n 'classificationLevel': 2 //等级\n }\n}\n",
|
35
|
-
"responseDataFunc": "",
|
36
|
-
"responseGeneralDataFunc": "function(req, { data, util, window }) {\n return req\n .then((response) => {\n return Promise.resolve({\n status: {\n code: 0,\n }\n })\n })\n .catch((error) => {\n // 检查是否有响应数据\n if (error.response && error.response.data) {\n const responseData = error.response.data;\n const detail = responseData.body?.status?.detail || responseData.status?.detail;\n if (detail) {\n util.message.error(detail);\n } else {\n util.message.error('编辑失败,请重试');\n }\n } else {\n util.message.error('编辑失败,请重试');\n }\n console.error('Error during deletion:', error);\n });\n}",
|
37
|
-
"formInstance": {},
|
38
|
-
"data": "{\"id\":1,\"classificationName\":\"个人基本概况信息\",\"classificationLevel\":2}",
|
39
|
-
"baseURL": "http://localhost:62888"
|
40
|
-
}
|
41
|
-
|
42
|
-
const promise = {current: null};
|
43
10
|
createRoot(document.getElementById('root')!).render(
|
44
11
|
<>
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
12
|
+
<button onClick={() => createMessageVerifyModal({
|
13
|
+
data,
|
14
|
+
config: {
|
15
|
+
"transitional": {
|
16
|
+
"silentJSONParsing": true,
|
17
|
+
"forcedJSONParsing": true,
|
18
|
+
"clarifyTimeoutError": false
|
19
|
+
},
|
20
|
+
"timeout": 0,
|
21
|
+
"xsrfCookieName": "XSRF-TOKEN",
|
22
|
+
"xsrfHeaderName": "X-XSRF-TOKEN",
|
23
|
+
"maxContentLength": -1,
|
24
|
+
"maxBodyLength": -1,
|
25
|
+
"headers": {
|
26
|
+
"Accept": "application/json, text/plain, */*",
|
27
|
+
"X-Device-Fingerprint": "185fcce88c629725321adf29daa5e444",
|
28
|
+
"Content-Type": "application/json"
|
29
|
+
},
|
30
|
+
"url": "/classification/admin/level/edit",
|
31
|
+
"method": "post",
|
32
|
+
"dataFormat": "JSON",
|
33
|
+
"showRequestData": true,
|
34
|
+
"showResponseData": false,
|
35
|
+
"showGeneralResponseData": true,
|
36
|
+
"headersList": [],
|
37
|
+
"requestDataFunc": "\nfunction(formFilterData){\n // 这里写你的处理逻辑\n return {\n ...formFilterData,\n 'classificationLevel': 2 //等级\n }\n}\n",
|
38
|
+
"responseDataFunc": "",
|
39
|
+
"responseGeneralDataFunc": "function(req, { data, util, window }) {\n return req\n .then((response) => {\n return Promise.resolve({\n status: {\n code: 0,\n }\n })\n })\n .catch((error) => {\n // 检查是否有响应数据\n if (error.response && error.response.data) {\n const responseData = error.response.data;\n const detail = responseData.body?.status?.detail || responseData.status?.detail;\n if (detail) {\n util.message.error(detail);\n } else {\n util.message.error('编辑失败,请重试');\n }\n } else {\n util.message.error('编辑失败,请重试');\n }\n console.error('Error during deletion:', error);\n });\n}",
|
40
|
+
"formInstance": {},
|
41
|
+
"data": "{\"id\":1,\"classificationName\":\"个人基本概况信息\",\"classificationLevel\":2}",
|
42
|
+
"baseURL": "http://localhost:62888"
|
43
|
+
},
|
44
|
+
lang: 'en',
|
45
|
+
http: axios,
|
46
|
+
})}>
|
47
|
+
Show verify Modal
|
48
|
+
</button>
|
58
49
|
</>);
|
@@ -1,23 +1,20 @@
|
|
1
1
|
import { useState } from 'react'
|
2
|
-
import { Modal, Button } from '
|
3
|
-
import {
|
4
|
-
import t from '../utils/i18n.js'
|
2
|
+
import { Modal, Button } from './compoments/index.js'
|
3
|
+
import { ModalConfig } from './utils/type.js';
|
5
4
|
|
6
|
-
const ReLoginModal = ({ props }: { props:
|
7
|
-
|
5
|
+
const ReLoginModal = ({ props }: { props: ModalConfig }) => {
|
6
|
+
console.log('props', props);
|
8
7
|
const [visible, setVisible] = useState(true);
|
9
8
|
const onClose = () => {
|
10
9
|
setVisible(false);
|
11
|
-
goLogin();
|
12
|
-
destroyModal?.();
|
13
10
|
};
|
14
11
|
return (
|
15
12
|
<Modal visible={visible} onClose={onClose} width={420}>
|
16
13
|
<div style={{ fontWeight: 500, fontSize: 20, marginBottom: 24 }}>
|
17
|
-
|
14
|
+
账号安全提醒
|
18
15
|
</div>
|
19
16
|
<div style={{ color: '#222', fontSize: 16, marginBottom: 40, lineHeight: '24px' }}>
|
20
|
-
|
17
|
+
检测到您的登录环境或网络信息有变动,为保障账户安全,请重新登录验证身份
|
21
18
|
</div>
|
22
19
|
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
23
20
|
<Button
|
@@ -25,15 +22,16 @@ const ReLoginModal = ({ props }: { props: LoginModalConfig }) => {
|
|
25
22
|
background: '#1677ff',
|
26
23
|
color: '#fff',
|
27
24
|
border: 'none',
|
28
|
-
width:
|
29
|
-
height:
|
30
|
-
fontSize:
|
25
|
+
width: 160,
|
26
|
+
height: 44,
|
27
|
+
fontSize: 18,
|
28
|
+
fontWeight: 500,
|
31
29
|
borderRadius: 8,
|
32
30
|
boxShadow: '0 2px 8px rgba(22,119,255,0.08)',
|
33
31
|
}}
|
34
32
|
onClick={onClose}
|
35
33
|
>
|
36
|
-
|
34
|
+
好的
|
37
35
|
</Button>
|
38
36
|
</div>
|
39
37
|
</Modal>
|
package/src/utils/type.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
export type
|
2
|
+
export type ModalConfig = {
|
3
3
|
data: string;
|
4
4
|
onClose?: () => void
|
5
5
|
config: {
|
@@ -8,7 +8,7 @@ export type VerifyModalConfig = {
|
|
8
8
|
};
|
9
9
|
[key: string]: unknown;
|
10
10
|
};
|
11
|
-
lang
|
11
|
+
lang: 'zh' | 'en' | 'id';
|
12
12
|
http: {
|
13
13
|
(params: object): Promise<unknown>;
|
14
14
|
defaults: {
|
@@ -19,15 +19,5 @@ export type VerifyModalConfig = {
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
};
|
22
|
-
|
23
|
-
apiReject?: any;
|
24
|
-
apiResolve?: any;
|
25
|
-
apiPromiseToEmpty?: () => void;
|
26
|
-
verifyPromise: {current: Promise<any> | null}
|
27
|
-
}
|
28
|
-
|
29
|
-
export type LoginModalConfig = {
|
30
|
-
goLogin: () => void;
|
31
|
-
onClose?: () => void
|
32
|
-
lang?: 'zh' | 'en' | 'id';
|
22
|
+
api?: string;
|
33
23
|
}
|
@@ -1,18 +1,18 @@
|
|
1
1
|
import { useEffect, useState } from 'react'
|
2
|
-
import { Modal, Input, Button, message } from '
|
3
|
-
import Api from '
|
4
|
-
import t from '
|
5
|
-
import {
|
2
|
+
import { Modal, Input, Button, message } from './compoments/index.js'
|
3
|
+
import Api from './resource.js'
|
4
|
+
import t from './utils/i18n.js'
|
5
|
+
import { ModalConfig } from './utils/type.js';
|
6
6
|
import { axios } from '@yqg/resource';
|
7
7
|
|
8
|
-
const CreateMessageVerifyModal = ({ props }: { props:
|
8
|
+
const CreateMessageVerifyModal = ({ props }: { props: ModalConfig }) => {
|
9
9
|
const [visible, setVisible] = useState(true);
|
10
10
|
const [countdown, setCountdown] = useState(60);
|
11
11
|
const [otp, setOtp] = useState('');
|
12
12
|
const [captchaImage, setCaptchaImage] = useState<string>('');
|
13
13
|
const [captchCode, setCaptchCode] = useState<string>('');
|
14
14
|
const [captchaKey, setCaptchaKey] = useState<string>('');
|
15
|
-
const { data, http, lang,
|
15
|
+
const { data, config, http, lang, api='/admin/sms/send' } = props || {};
|
16
16
|
const dataObj = JSON.parse(data || '{}');
|
17
17
|
const { mobile, verifyCodeKey } = dataObj || {};
|
18
18
|
|
@@ -25,11 +25,10 @@ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
|
|
25
25
|
const image = Api.getCaptchaImgUrl(key) as unknown;
|
26
26
|
setCaptchaImage(image as string);
|
27
27
|
}
|
28
|
-
} catch (err) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
: String(err);
|
28
|
+
} catch (err) {const msg =
|
29
|
+
typeof err === 'object' && err !== null && 'message' in err
|
30
|
+
? (err as {message: string}).message
|
31
|
+
: String(err);
|
33
32
|
message.error(msg as React.ReactNode);
|
34
33
|
}
|
35
34
|
}
|
@@ -54,16 +53,14 @@ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
|
|
54
53
|
formData.append('captchaKey', captchaKey);
|
55
54
|
formData.append('captcha', captchCode);
|
56
55
|
// 重新发送验证码
|
57
|
-
const res = await axios.post(
|
56
|
+
const res = await axios.post(api, formData);
|
58
57
|
const { code, detail } = res.data?.status || {};
|
59
58
|
if (code !== 0) {
|
60
59
|
message.error(detail || t('sendFailed', lang));
|
61
60
|
return;
|
62
61
|
}
|
63
62
|
message.success(t('sendSuccess', lang));
|
64
|
-
// 重置倒计时、验证码
|
65
63
|
setCountdown(60);
|
66
|
-
setOtp('');
|
67
64
|
}
|
68
65
|
|
69
66
|
return (
|
@@ -72,8 +69,7 @@ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
|
|
72
69
|
visible={visible}
|
73
70
|
onClose={() => {
|
74
71
|
setVisible(false);
|
75
|
-
|
76
|
-
onClose?.();
|
72
|
+
props.onClose?.();
|
77
73
|
}}
|
78
74
|
>
|
79
75
|
<div style={{ fontSize: 14, color: '#666' }}>{t('alreadySend', lang, { phone: mobile })}</div>
|
@@ -85,40 +81,23 @@ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
|
|
85
81
|
onChange={async (val) => {
|
86
82
|
setOtp(val);
|
87
83
|
if (val.length === 6) {
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
new Promise((resolve, reject) => {
|
96
|
-
http({
|
97
|
-
...config,
|
98
|
-
headers: {
|
99
|
-
...http.defaults.headers.common,
|
100
|
-
'sms-code': val,
|
101
|
-
'sms-code-key': verifyCodeKey,
|
102
|
-
'Content-Type': config.headers['Content-Type'],
|
103
|
-
}
|
104
|
-
}).then(res => {
|
105
|
-
resolve(res);
|
106
|
-
}).catch(err => {
|
107
|
-
reject(err);
|
108
|
-
})
|
109
|
-
})
|
110
|
-
]) as any;
|
111
|
-
if (res?.data?.status?.code === 0) {
|
112
|
-
apiResolve(res);
|
113
|
-
setVisible(false);
|
114
|
-
} else {
|
115
|
-
message.error(t('verifyFail', lang));
|
116
|
-
setOtp('');
|
84
|
+
const res = await http({
|
85
|
+
...config,
|
86
|
+
headers: {
|
87
|
+
...http.defaults.headers.common,
|
88
|
+
'sms-code': val,
|
89
|
+
'sms-code-key': verifyCodeKey,
|
90
|
+
'Content-Type': config.headers['Content-Type'],
|
117
91
|
}
|
118
|
-
}
|
119
|
-
|
120
|
-
|
121
|
-
|
92
|
+
}) as any;
|
93
|
+
console.log(res, 'res');
|
94
|
+
const {data: {status: {code, detail} = {}}} = res;
|
95
|
+
if(code !== 0) {
|
96
|
+
message.error(detail || t('verifyFailed', lang));
|
97
|
+
return;
|
98
|
+
} else {
|
99
|
+
message.success(t('verifySuccess', lang));
|
100
|
+
setVisible(false);
|
122
101
|
}
|
123
102
|
}
|
124
103
|
}} />
|
@@ -143,7 +122,6 @@ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
|
|
143
122
|
{captchaImage && <img src={captchaImage} alt={t('verifyCode', lang)} style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
|
144
123
|
</div>}
|
145
124
|
{(countdown > 0 || captchCode) ? null : <div style={{ fontSize: 14, color: 'red' }}>{t('pleaseEnterAndSend', lang)}</div>}
|
146
|
-
<div style={{ fontSize: 14, color: '#666', marginTop: 12 }}>{t('chidoriOpenPro', lang)}</div>
|
147
125
|
</Modal>
|
148
126
|
);
|
149
127
|
};
|
@@ -1 +0,0 @@
|
|
1
|
-
{"__symbol_cache_version__":11,"0861795cb7fca1601b342f4e44fe1aed":{"have":{"class":{"YqgWebDiffLintEngine":13}},"need":{"class":{"ArcanistLintEngine":42,"ExecFuture":1832,"PhutilConsole":1780}},"xmap":{"YqgWebDiffLintEngine":["ArcanistLintEngine"]}}}
|
@@ -1,18 +0,0 @@
|
|
1
|
-
<?php
|
2
|
-
|
3
|
-
/**
|
4
|
-
* This file is automatically generated. Use 'arc liberate' to rebuild it.
|
5
|
-
*
|
6
|
-
* @generated
|
7
|
-
* @phutil-library-version 2
|
8
|
-
*/
|
9
|
-
phutil_register_library_map(array(
|
10
|
-
'__library_version__' => 2,
|
11
|
-
'class' => array(
|
12
|
-
'YqgWebDiffLintEngine' => 'lint/engine/YqgWebDiffLintEngine.php',
|
13
|
-
),
|
14
|
-
'function' => array(),
|
15
|
-
'xmap' => array(
|
16
|
-
'YqgWebDiffLintEngine' => 'ArcanistLintEngine',
|
17
|
-
),
|
18
|
-
));
|
@@ -1,68 +0,0 @@
|
|
1
|
-
<?php
|
2
|
-
|
3
|
-
class YqgWebDiffLintEngine extends ArcanistLintEngine
|
4
|
-
{
|
5
|
-
/** @Override */
|
6
|
-
public function buildLinters()
|
7
|
-
{
|
8
|
-
// Filter the affected paths.
|
9
|
-
$paths = $this->getPaths();
|
10
|
-
foreach ($paths as $key => $path) {
|
11
|
-
if (!$this->pathExists($path)) {
|
12
|
-
// Don't lint removed files. In more complex linters it is sometimes
|
13
|
-
// appropriate to lint removed files so you can raise a warning like
|
14
|
-
// "you deleted X, but forgot to delete Y!", but most linters do not
|
15
|
-
// operate correctly on removed files.
|
16
|
-
unset($paths[$key]);
|
17
|
-
continue;
|
18
|
-
}
|
19
|
-
|
20
|
-
$disk = $this->getFilePathOnDisk($path);
|
21
|
-
if (is_dir($disk)) {
|
22
|
-
// Don't lint directories. (In SVN, they can be directly modified by
|
23
|
-
// changing properties on them, and may appear as modified paths.)
|
24
|
-
unset($paths[$key]);
|
25
|
-
continue;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
|
29
|
-
$command = '';
|
30
|
-
$patterns = array(
|
31
|
-
'/\.(jsx?|tsx?|vue?|ts?)$/' => 'pnpm eslint',
|
32
|
-
// '/\.(less|s?css)$/' => 'npx stylelint --fix' // 理论上暂时不用 style lint
|
33
|
-
);
|
34
|
-
|
35
|
-
foreach ($patterns as $pattern => $lintCommand) {
|
36
|
-
$matchedPaths = preg_grep($pattern, $paths);
|
37
|
-
if (count($matchedPaths) > 0) {
|
38
|
-
if (strlen($command)) {
|
39
|
-
$command .= ' && \\';
|
40
|
-
}
|
41
|
-
|
42
|
-
$command .= $lintCommand . ' ' . join(' ', $matchedPaths);
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
$root = $this->getWorkingCopy()->getProjectRoot();
|
47
|
-
$console = PhutilConsole::getConsole();
|
48
|
-
|
49
|
-
$future = new ExecFuture($command);
|
50
|
-
$future->setCWD($root . "/");
|
51
|
-
list($exitcode, $stdout, $stderr) = $future->resolve();
|
52
|
-
$console->writeOut($stdout);
|
53
|
-
$console->writeOut($stderr);
|
54
|
-
$console->writeOut("\n");
|
55
|
-
|
56
|
-
if ($exitcode != 0) {
|
57
|
-
$console->writeOut("All code in any code-base should look like a single person typed it, no matter how many people contributed. --idiomatic.js\n");
|
58
|
-
$console->writeOut("无论有多少人在维护,所有在代码仓库中的代码理应看起来像同一个人写的。 --idiomatic.js\n");
|
59
|
-
$console->writeOut("https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_CN\n");
|
60
|
-
throw new Exception("Keep it in mind!");
|
61
|
-
} else {
|
62
|
-
$console->writeOut("All code are clean, you did a great job!\n");
|
63
|
-
}
|
64
|
-
|
65
|
-
return;
|
66
|
-
}
|
67
|
-
|
68
|
-
}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { useState } from 'react';
|
3
|
-
import { Modal, Button } from '../compoments/index.js';
|
4
|
-
import t from '../utils/i18n.js';
|
5
|
-
const ReLoginModal = ({ props }) => {
|
6
|
-
const { goLogin, lang, onClose: destroyModal } = props || {};
|
7
|
-
const [visible, setVisible] = useState(true);
|
8
|
-
const onClose = () => {
|
9
|
-
setVisible(false);
|
10
|
-
goLogin();
|
11
|
-
destroyModal?.();
|
12
|
-
};
|
13
|
-
return (_jsxs(Modal, { visible: visible, onClose: onClose, width: 420, children: [_jsx("div", { style: { fontWeight: 500, fontSize: 20, marginBottom: 24 }, children: t('accountAlert', lang) }), _jsx("div", { style: { color: '#222', fontSize: 16, marginBottom: 40, lineHeight: '24px' }, children: t('alertContent', lang) }), _jsx("div", { style: { display: 'flex', justifyContent: 'center' }, children: _jsx(Button, { style: {
|
14
|
-
background: '#1677ff',
|
15
|
-
color: '#fff',
|
16
|
-
border: 'none',
|
17
|
-
width: 80,
|
18
|
-
height: 36,
|
19
|
-
fontSize: 14,
|
20
|
-
borderRadius: 8,
|
21
|
-
boxShadow: '0 2px 8px rgba(22,119,255,0.08)',
|
22
|
-
}, onClick: onClose, children: t('ok', lang) }) })] }));
|
23
|
-
};
|
24
|
-
export default ReLoginModal;
|
@@ -1,115 +0,0 @@
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { useEffect, useState } from 'react';
|
3
|
-
import { Modal, Input, Button, message } from '../compoments/index.js';
|
4
|
-
import Api from '../utils/resource.js';
|
5
|
-
import t from '../utils/i18n.js';
|
6
|
-
import { axios } from '@yqg/resource';
|
7
|
-
const CreateMessageVerifyModal = ({ props }) => {
|
8
|
-
const [visible, setVisible] = useState(true);
|
9
|
-
const [countdown, setCountdown] = useState(60);
|
10
|
-
const [otp, setOtp] = useState('');
|
11
|
-
const [captchaImage, setCaptchaImage] = useState('');
|
12
|
-
const [captchCode, setCaptchCode] = useState('');
|
13
|
-
const [captchaKey, setCaptchaKey] = useState('');
|
14
|
-
const { data, http, lang, sendApi = '/admin/sms/send', config, apiResolve, apiPromiseToEmpty, onClose } = props || {};
|
15
|
-
const dataObj = JSON.parse(data || '{}');
|
16
|
-
const { mobile, verifyCodeKey } = dataObj || {};
|
17
|
-
const getKey = async () => {
|
18
|
-
try {
|
19
|
-
const res = await Api.getCaptchaKey();
|
20
|
-
const { body: key } = res.data || {};
|
21
|
-
setCaptchaKey(key);
|
22
|
-
if (key) {
|
23
|
-
const image = Api.getCaptchaImgUrl(key);
|
24
|
-
setCaptchaImage(image);
|
25
|
-
}
|
26
|
-
}
|
27
|
-
catch (err) {
|
28
|
-
const msg = typeof err === 'object' && err !== null && 'message' in err
|
29
|
-
? err.message
|
30
|
-
: String(err);
|
31
|
-
message.error(msg);
|
32
|
-
}
|
33
|
-
};
|
34
|
-
useEffect(() => {
|
35
|
-
let timer = null;
|
36
|
-
if (visible && countdown > 0) {
|
37
|
-
timer = setInterval(() => {
|
38
|
-
setCountdown((prev) => prev - 1);
|
39
|
-
}, 1000);
|
40
|
-
}
|
41
|
-
if (countdown === 0) {
|
42
|
-
getKey();
|
43
|
-
}
|
44
|
-
return () => {
|
45
|
-
if (timer)
|
46
|
-
clearInterval(timer);
|
47
|
-
};
|
48
|
-
}, [visible, countdown]);
|
49
|
-
const handleResend = async () => {
|
50
|
-
const formData = new FormData();
|
51
|
-
formData.append('captchaKey', captchaKey);
|
52
|
-
formData.append('captcha', captchCode);
|
53
|
-
// 重新发送验证码
|
54
|
-
const res = await axios.post(sendApi, formData);
|
55
|
-
const { code, detail } = res.data?.status || {};
|
56
|
-
if (code !== 0) {
|
57
|
-
message.error(detail || t('sendFailed', lang));
|
58
|
-
return;
|
59
|
-
}
|
60
|
-
message.success(t('sendSuccess', lang));
|
61
|
-
// 重置倒计时、验证码
|
62
|
-
setCountdown(60);
|
63
|
-
setOtp('');
|
64
|
-
};
|
65
|
-
return (_jsxs(Modal, { width: 420, visible: visible, onClose: () => {
|
66
|
-
setVisible(false);
|
67
|
-
apiPromiseToEmpty?.();
|
68
|
-
onClose?.();
|
69
|
-
}, children: [_jsx("div", { style: { fontSize: 14, color: '#666' }, children: t('alreadySend', lang, { phone: mobile }) }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 12 }, children: [_jsx(Input.OTP, { length: 6, value: otp, onChange: async (val) => {
|
70
|
-
setOtp(val);
|
71
|
-
if (val.length === 6) {
|
72
|
-
try {
|
73
|
-
const res = await Promise.race([
|
74
|
-
new Promise((resolve, reject) => {
|
75
|
-
setTimeout(() => {
|
76
|
-
reject(new Error('Timeout'));
|
77
|
-
}, 1000);
|
78
|
-
}),
|
79
|
-
new Promise((resolve, reject) => {
|
80
|
-
http({
|
81
|
-
...config,
|
82
|
-
headers: {
|
83
|
-
...http.defaults.headers.common,
|
84
|
-
'sms-code': val,
|
85
|
-
'sms-code-key': verifyCodeKey,
|
86
|
-
'Content-Type': config.headers['Content-Type'],
|
87
|
-
}
|
88
|
-
}).then(res => {
|
89
|
-
resolve(res);
|
90
|
-
}).catch(err => {
|
91
|
-
reject(err);
|
92
|
-
});
|
93
|
-
})
|
94
|
-
]);
|
95
|
-
if (res?.data?.status?.code === 0) {
|
96
|
-
apiResolve(res);
|
97
|
-
setVisible(false);
|
98
|
-
}
|
99
|
-
else {
|
100
|
-
message.error(t('verifyFail', lang));
|
101
|
-
setOtp('');
|
102
|
-
}
|
103
|
-
}
|
104
|
-
catch (error) {
|
105
|
-
console.warn('catch=>error', error);
|
106
|
-
message.error(t('verifyFail', lang));
|
107
|
-
setOtp('');
|
108
|
-
}
|
109
|
-
}
|
110
|
-
} }), _jsx(Button, { disabled: countdown > 0 || !captchCode, onClick: handleResend, style: { padding: '8px' }, children: countdown > 0 ? t('countDownSecound', lang, { countdown }) : t('reSend', lang) })] }), countdown > 0 ? null :
|
111
|
-
_jsxs("div", { style: { marginTop: 12, display: 'flex', alignItems: 'center' }, children: [_jsx(Input, { placeholder: t('pleaseEnterPicVerifyCode', lang), onChange: (e) => {
|
112
|
-
setCaptchCode(e);
|
113
|
-
}, style: { width: 300 } }), captchaImage && _jsx("img", { src: captchaImage, alt: t('verifyCode', lang), style: { width: 100, height: 30, marginLeft: 8 }, onClick: getKey })] }), (countdown > 0 || captchCode) ? null : _jsx("div", { style: { fontSize: 14, color: 'red' }, children: t('pleaseEnterAndSend', lang) }), _jsx("div", { style: { fontSize: 14, color: '#666', marginTop: 12 }, children: t('chidoriOpenPro', lang) })] }));
|
114
|
-
};
|
115
|
-
export default CreateMessageVerifyModal;
|
package/dist/utils/resource.d.ts
DELETED
package/dist/utils/resource.js
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
import { assign, customPost } from '@yqg/resource';
|
2
|
-
const api = {
|
3
|
-
getCaptchaKey: customPost('/messageVerify/admin/captcha/key'),
|
4
|
-
reSendCode: customPost('/admin/sms/send'),
|
5
|
-
getCaptchaImgUrl: (captchaKey) => { return `/messageVerify/admin/captcha/image/${captchaKey}`; },
|
6
|
-
};
|
7
|
-
export default assign(api);
|
File without changes
|