message-verify 1.0.1-beta.5 → 1.0.1-beta.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "message-verify",
3
- "version": "1.0.1-beta.5",
3
+ "version": "1.0.1-beta.50",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "dependencies": {
@@ -29,6 +29,7 @@
29
29
  "build": "tsc -b",
30
30
  "analyze": "vite build",
31
31
  "lint": "eslint .",
32
- "preview": "vite preview"
32
+ "preview": "vite preview",
33
+ "release:beta": "pnpm version prerelease --preid=beta && pnpm run build && pnpm publish"
33
34
  }
34
35
  }
package/src/index.tsx CHANGED
@@ -1,55 +1,85 @@
1
1
  import ReactDOM from 'react-dom/client'
2
- import VerifyModal from './verify-modal.js'
2
+ import VerifyModal from './modal/verify-modal.js'
3
3
  import Fingerprint2 from 'fingerprintjs2';
4
- import { ModalConfig } from './utils/type.js';
4
+ import ReLoginModal from './modal/relogin-modal.js';
5
+ import { VerifyModalConfig, LoginModalConfig } from './utils/type.js';
5
6
 
6
- let cachedFingerprint: string | null = null;
7
+ let fingerprintPromise: Promise<string> | null = null; // 用 Promise 本身作为缓存
8
+ let modalRoot: ReactDOM.Root | null = null
7
9
  export const initFingerprint = async (): Promise<string> => {
8
- if (cachedFingerprint) {
9
- // 已有缓存,直接返回 Promise
10
- return Promise.resolve(cachedFingerprint);
11
- }
12
- // 首次异步获取并缓存
13
- return new Promise((resolve) => {
14
- Fingerprint2.get(function (components) {
15
- console.log('components', components);
16
- const includeKeys = ['userAgent', 'deviceMemory', 'cpuClass', 'hardwareConcurrency', 'platform'];
17
- const values = components
18
- .filter(component => includeKeys.includes(component.key))
19
- .map(component => component.value)
20
- .join('###');
21
- const fingerprint = Fingerprint2.x64hash128(values, 31);
22
- cachedFingerprint = fingerprint;
23
- resolve(fingerprint);
10
+ console.log('fingerprintPromise:', fingerprintPromise);
11
+ if (!fingerprintPromise) {
12
+ fingerprintPromise = new Promise((resolve) => {
13
+ Fingerprint2.get(components => {
14
+ const includeKeys = ['userAgent', 'cpuClass', 'hardwareConcurrency', 'platform'];
15
+ console.log('components:', components);
16
+ const values = components
17
+ .filter(c => includeKeys.includes(c.key))
18
+ .map(c => c.value)
19
+ .join('###');
20
+ console.log('values:', values);
21
+ const fingerprint = Fingerprint2.x64hash128(values, 31);
22
+ console.log('fingerprint:', fingerprint);
23
+ resolve(fingerprint);
24
+ });
24
25
  });
25
- });
26
+ }
27
+ return fingerprintPromise;
26
28
  };
27
29
 
28
- let modalRoot: ReactDOM.Root | null = null
30
+ const destroyModal = (modalId: string) => {
31
+ if (modalRoot) {
32
+ modalRoot.unmount()
33
+ document.getElementById(modalId)?.remove()
34
+ modalRoot = null
35
+ }
36
+ }
29
37
 
30
- export const createMessageVerifyModal = (modalProps: ModalConfig) => {
31
- const container = document.createElement('div')
32
- container.id = 'antd-modal-container'
33
- document.body.appendChild(container)
38
+ const creatModal = (modalProps: VerifyModalConfig | LoginModalConfig, modalId: string, ModalDom:any) => {
39
+ destroyModal(modalId);
40
+ const container = document.createElement('div')
41
+ container.id = modalId
42
+ document.body.appendChild(container)
34
43
 
35
- modalRoot = ReactDOM.createRoot(container)
36
- modalRoot.render(
37
- <VerifyModal
38
- props={{
39
- ...modalProps,
40
- onClose: () => {
41
- modalProps.onClose?.()
42
- destroyModal()
43
- }
44
- }}
45
- />
46
- )
44
+ modalRoot = ReactDOM.createRoot(container)
45
+ modalRoot.render(
46
+ <ModalDom
47
+ props={{
48
+ ...modalProps,
49
+ onClose: () => {
50
+ destroyModal(modalId);
51
+ }
52
+ }}
53
+ />
54
+ )
47
55
  }
48
56
 
49
- const destroyModal = () => {
50
- if (modalRoot) {
51
- modalRoot.unmount()
52
- document.getElementById('antd-modal-container')?.remove()
53
- modalRoot = null
54
- }
55
- }
57
+ const createMessageVerifyModal = (modalProps: VerifyModalConfig) => {
58
+ const verifyModalId = 'verify-modal-container';
59
+ creatModal(modalProps, verifyModalId, VerifyModal);
60
+ }
61
+ // 新增 relogin 弹窗创建方法
62
+ export const createReLoginModal = (modalProps: LoginModalConfig) => {
63
+ const reLoginModalId = 'relogin-modal-container';
64
+ creatModal(modalProps, reLoginModalId, ReLoginModal);
65
+ }
66
+
67
+ export const VerifyHandler = ({data, config, http, verifyPromise, sendApi}: VerifyModalConfig): Promise<any> => {
68
+ const toEmpty = () => {
69
+ verifyPromise.current = null;
70
+ };
71
+ if (!verifyPromise.current) {
72
+ verifyPromise.current = new Promise((resolve, reject) => {
73
+ createMessageVerifyModal({
74
+ data,
75
+ config,
76
+ http,
77
+ apiResolve: resolve,
78
+ apiReject: reject,
79
+ apiPromiseToEmpty: toEmpty,
80
+ sendApi
81
+ } as VerifyModalConfig);
82
+ }).finally(toEmpty);
83
+ }
84
+ return verifyPromise.current;
85
+ };
package/src/locales/en.ts CHANGED
@@ -6,5 +6,9 @@ export default {
6
6
  sendSuccess: 'Successfully sent',
7
7
  sendFailed: 'Send failed',
8
8
  reSend: 'Resend',
9
- countDownSecound: '{countdown} seconds'
9
+ countDownSecound: '{countdown} seconds',
10
+ accountAlert: 'Account Security Alert',
11
+ alertContent: 'Changes have been detected in your login environment or network information.To ensure account security, please log in again to verify your identity.',
12
+ ok: 'OK',
13
+ chidoriOpenPro: 'Chidori has activated security protection for you'
10
14
  };
package/src/locales/id.ts CHANGED
@@ -6,5 +6,9 @@ export default {
6
6
  sendSuccess: 'Berhasil dikirim',
7
7
  sendFailed: 'Gagal mengirim',
8
8
  reSend: 'Kirim Ulang',
9
- countDownSecound: '{countdown} detik'
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'
10
14
  };
package/src/locales/zh.ts CHANGED
@@ -6,5 +6,9 @@ export default {
6
6
  sendSuccess: '发送成功',
7
7
  sendFailed: '发送失败',
8
8
  reSend: '重新发送',
9
- countDownSecound: '{countdown}秒'
9
+ countDownSecound: '{countdown}秒',
10
+ accountAlert: '账号安全提醒',
11
+ alertContent: '检测到您的登录环境或网络信息有变动,为保障账户安全,请重新登录验证身份',
12
+ ok: '好的',
13
+ chidoriOpenPro: 'chidori已为您开启安全防护'
10
14
  };
package/src/main.tsx CHANGED
@@ -1,11 +1,12 @@
1
1
  import { createRoot } from 'react-dom/client';
2
- import { createMessageVerifyModal, initFingerprint } from './index.js'; // 或 './index'
2
+ import { initFingerprint, createReLoginModal, VerifyHandler } 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
- console.log(fp);
8
+ const fp2 = await initFingerprint();
9
+ console.log(fp, fp2);
9
10
 
10
11
  const config = {
11
12
  "transitional": {
@@ -13,12 +14,6 @@ const config = {
13
14
  "forcedJSONParsing": true,
14
15
  "clarifyTimeoutError": false
15
16
  },
16
- "transformRequest": [
17
- null
18
- ],
19
- "transformResponse": [
20
- null
21
- ],
22
17
  "timeout": 0,
23
18
  "xsrfCookieName": "XSRF-TOKEN",
24
19
  "xsrfHeaderName": "X-XSRF-TOKEN",
@@ -26,10 +21,8 @@ const config = {
26
21
  "maxBodyLength": -1,
27
22
  "headers": {
28
23
  "Accept": "application/json, text/plain, */*",
29
- "X-Device-Fingerprint": "185fcce88c629725321adf29daa5e444",
30
- "Content-Type": "application/json",
31
- "sms-code": "121212",
32
- "sms-code-key": "212190c7-2f5e-4cc1-82ec-a242c2ab5425"
24
+ "X-Device-Fingerprint": "531f14c7176b16ebeb18e2b23d6bd124",
25
+ "Content-Type": "application/json"
33
26
  },
34
27
  "url": "/classification/admin/level/edit",
35
28
  "method": "post",
@@ -44,18 +37,22 @@ const config = {
44
37
  "formInstance": {},
45
38
  "data": "{\"id\":1,\"classificationName\":\"个人基本概况信息\",\"classificationLevel\":2}",
46
39
  "baseURL": "http://localhost:62888"
47
- };
40
+ }
41
+
42
+ const promise = {current: null};
48
43
  createRoot(document.getElementById('root')!).render(
49
44
  <>
50
- <button onClick={() => createMessageVerifyModal({
51
- data,
52
- config,
53
- response: {
54
- config
45
+ <button onClick={() => {
46
+ return VerifyHandler({data, config, http: axios, verifyPromise: promise});
47
+ }}>
48
+ Show verify Modal
49
+ </button>
50
+ <button onClick={() => createReLoginModal({
51
+ goLogin: () => {
52
+ console.log('goLogin');
55
53
  },
56
- lang: 'en',
57
- http: axios,
54
+ lang: 'zh',
58
55
  })}>
59
- Show verify Modal
56
+ Show login Modal
60
57
  </button>
61
58
  </>);
@@ -1,20 +1,23 @@
1
1
  import { useState } from 'react'
2
- import { Modal, Button } from './compoments/index.js'
3
- import { ModalConfig } from './utils/type.js';
2
+ import { Modal, Button } from '../compoments/index.js'
3
+ import { LoginModalConfig } from '../utils/type.js';
4
+ import t from '../utils/i18n.js'
4
5
 
5
- const ReLoginModal = ({ props }: { props: ModalConfig }) => {
6
- console.log('props', props);
6
+ const ReLoginModal = ({ props }: { props: LoginModalConfig }) => {
7
+ const { goLogin, lang, onClose: destroyModal } = props || {};
7
8
  const [visible, setVisible] = useState(true);
8
9
  const onClose = () => {
9
10
  setVisible(false);
11
+ goLogin();
12
+ destroyModal?.();
10
13
  };
11
14
  return (
12
15
  <Modal visible={visible} onClose={onClose} width={420}>
13
16
  <div style={{ fontWeight: 500, fontSize: 20, marginBottom: 24 }}>
14
- 账号安全提醒
17
+ {t('accountAlert', lang)}
15
18
  </div>
16
19
  <div style={{ color: '#222', fontSize: 16, marginBottom: 40, lineHeight: '24px' }}>
17
- 检测到您的登录环境或网络信息有变动,为保障账户安全,请重新登录验证身份
20
+ {t('alertContent', lang)}
18
21
  </div>
19
22
  <div style={{ display: 'flex', justifyContent: 'center' }}>
20
23
  <Button
@@ -22,16 +25,15 @@ const ReLoginModal = ({ props }: { props: ModalConfig }) => {
22
25
  background: '#1677ff',
23
26
  color: '#fff',
24
27
  border: 'none',
25
- width: 160,
26
- height: 44,
27
- fontSize: 18,
28
- fontWeight: 500,
28
+ width: 80,
29
+ height: 36,
30
+ fontSize: 14,
29
31
  borderRadius: 8,
30
32
  boxShadow: '0 2px 8px rgba(22,119,255,0.08)',
31
33
  }}
32
34
  onClick={onClose}
33
35
  >
34
- 好的
36
+ {t('ok', lang)}
35
37
  </Button>
36
38
  </div>
37
39
  </Modal>
@@ -0,0 +1,183 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { Modal, Input, Button, message } from '../compoments/index.js'
3
+ import Api from '../utils/resource.js'
4
+ import t from '../utils/i18n.js'
5
+ import { VerifyModalConfig } from '../utils/type.js';
6
+ import { axios } from '@yqg/resource';
7
+
8
+ const CreateMessageVerifyModal = ({ props }: { props: VerifyModalConfig }) => {
9
+ const [visible, setVisible] = useState(true);
10
+ const [countdown, setCountdown] = useState(60);
11
+ const [otp, setOtp] = useState('');
12
+ const [captchaImage, setCaptchaImage] = useState<string>('');
13
+ const [captchCode, setCaptchCode] = useState<string>('');
14
+ const [captchaKey, setCaptchaKey] = useState<string>('');
15
+ const { data, http, lang, sendApi = '/admin/sms/send', config, apiResolve, apiPromiseToEmpty, onClose } = props || {};
16
+ const dataObj = JSON.parse(data || '{}');
17
+ const { mobile, verifyCodeKey } = dataObj || {};
18
+
19
+ const getKey = async () => {
20
+ try {
21
+ const res = await Api.getCaptchaKey();
22
+ const { body: key } = res.data || {};
23
+ setCaptchaKey(key);
24
+ if (key) {
25
+ const image = Api.getCaptchaImgUrl(key) as unknown;
26
+ setCaptchaImage(image as string);
27
+ }
28
+ } catch (err) {
29
+ const msg =
30
+ typeof err === 'object' && err !== null && 'message' in err
31
+ ? (err as { message: string }).message
32
+ : String(err);
33
+ message.error(msg as React.ReactNode);
34
+ }
35
+ }
36
+
37
+ useEffect(() => {
38
+ let timer: number | null = null;
39
+ if (visible && countdown > 0) {
40
+ timer = setInterval(() => {
41
+ setCountdown((prev) => prev - 1);
42
+ }, 1000);
43
+ }
44
+ if (countdown === 0) {
45
+ getKey();
46
+ }
47
+ return () => {
48
+ if (timer) clearInterval(timer);
49
+ };
50
+ }, [visible, countdown]);
51
+
52
+ const handleResend = async () => {
53
+ const formData = new FormData();
54
+ formData.append('captchaKey', captchaKey);
55
+ formData.append('captcha', captchCode);
56
+ // 重新发送验证码
57
+ const res = await axios.post(sendApi, formData);
58
+ const { code, detail } = res.data?.status || {};
59
+ if (code !== 0) {
60
+ message.error(detail || t('sendFailed', lang));
61
+ return;
62
+ }
63
+ message.success(t('sendSuccess', lang));
64
+ // 重置倒计时、验证码
65
+ setCountdown(60);
66
+ setOtp('');
67
+ }
68
+
69
+ return (
70
+ <Modal
71
+ width={420}
72
+ visible={visible}
73
+ onClose={() => {
74
+ setVisible(false);
75
+ apiPromiseToEmpty?.();
76
+ onClose?.();
77
+ }}
78
+ >
79
+ <div style={{ fontSize: 14, color: '#666' }}>{t('alreadySend', lang, { phone: mobile })}</div>
80
+
81
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12 }}>
82
+ <Input.OTP
83
+ length={6}
84
+ value={otp}
85
+ onChange={async (val) => {
86
+ setOtp(val);
87
+ if (val.length === 6) {
88
+ // try {
89
+ // const res = await Promise.race([
90
+ // new Promise((resolve, reject) => {
91
+ // setTimeout(() => {
92
+ // reject(new Error('Timeout'));
93
+ // }, 1000);
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
+ // ]) as any;
110
+ // if (res?.data?.status?.code === 0) {
111
+ // apiResolve(res);
112
+ // setVisible(false);
113
+ // } else {
114
+ // message.error('验证失败');
115
+ // setOtp('');
116
+ // }
117
+ // } catch (error) {
118
+ // console.warn('catch', error);
119
+ // message.error('验证失败');
120
+ // setOtp('');
121
+ // }
122
+ try {
123
+ new Promise((resolve, reject) => {
124
+ http({
125
+ ...config,
126
+ headers: {
127
+ ...http.defaults.headers.common,
128
+ 'sms-code': val,
129
+ 'sms-code-key': verifyCodeKey,
130
+ 'Content-Type': config.headers['Content-Type'],
131
+ }
132
+ }).then((res: any) => {
133
+ console.log('res', res);
134
+ console.log('res?.data?.status?.code', res?.data?.status?.code)
135
+ if (res?.data?.status?.code === 0) {
136
+ console.log('res?.data?.status?.code2', res?.data?.status?.code)
137
+ apiResolve(res);
138
+ setVisible(false);
139
+ } else {
140
+ console.log('res?.data?.status?.code3', res?.data?.status?.code)
141
+ message.error('验证失败');
142
+ setOtp('');
143
+ }
144
+ resolve(res);
145
+ }).catch(err => {
146
+ console.log('err', err)
147
+ reject(err);
148
+ })
149
+ });
150
+ } catch (error) {
151
+ console.warn('catch=>error', error);
152
+ message.error('验证失败');
153
+ setOtp('');
154
+ }
155
+ }
156
+ }} />
157
+ <Button
158
+ disabled={countdown > 0 || !captchCode}
159
+ onClick={handleResend}
160
+ style={{ padding: '8px' }}
161
+ >
162
+ {countdown > 0 ? t('countDownSecound', lang, { countdown }) : t('reSend', lang)}
163
+ </Button>
164
+ </div>
165
+ {countdown > 0 ? null :
166
+ <div style={{ marginTop: 12, display: 'flex', alignItems: 'center' }}>
167
+ <Input
168
+ placeholder={t('pleaseEnterPicVerifyCode', lang)}
169
+ onChange={(e) => {
170
+ setCaptchCode(e as string)
171
+ }}
172
+ style={{ width: 300 }}
173
+ />
174
+
175
+ {captchaImage && <img src={captchaImage} alt={t('verifyCode', lang)} style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
176
+ </div>}
177
+ {(countdown > 0 || captchCode) ? null : <div style={{ fontSize: 14, color: 'red' }}>{t('pleaseEnterAndSend', lang)}</div>}
178
+ <div style={{ fontSize: 14, color: '#666', marginTop: 12 }}>{t('chidoriOpenPro', lang)}</div>
179
+ </Modal>
180
+ );
181
+ };
182
+
183
+ export default CreateMessageVerifyModal;
package/src/utils/type.ts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- export type ModalConfig = {
2
+ export type VerifyModalConfig = {
3
3
  data: string;
4
4
  onClose?: () => void
5
5
  config: {
@@ -8,7 +8,7 @@ export type ModalConfig = {
8
8
  };
9
9
  [key: string]: unknown;
10
10
  };
11
- lang: 'zh' | 'en' | 'id';
11
+ lang?: 'zh' | 'en' | 'id';
12
12
  http: {
13
13
  (params: object): Promise<unknown>;
14
14
  defaults: {
@@ -19,6 +19,15 @@ export type ModalConfig = {
19
19
  }
20
20
  }
21
21
  };
22
- api?: string;
23
- response: any;
22
+ sendApi?: string;
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';
24
33
  }
@@ -1,129 +0,0 @@
1
- import { useEffect, useState } from 'react'
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
- import { axios } from '@yqg/resource';
7
-
8
- const CreateMessageVerifyModal = ({ props }: { props: ModalConfig }) => {
9
- const [visible, setVisible] = useState(true);
10
- const [countdown, setCountdown] = useState(60);
11
- const [otp, setOtp] = useState('');
12
- const [captchaImage, setCaptchaImage] = useState<string>('');
13
- const [captchCode, setCaptchCode] = useState<string>('');
14
- const [captchaKey, setCaptchaKey] = useState<string>('');
15
- const { data, config, http, lang, api='/admin/sms/send', response } = props || {};
16
- const dataObj = JSON.parse(data || '{}');
17
- const { mobile, verifyCodeKey } = dataObj || {};
18
-
19
- const getKey = async () => {
20
- try {
21
- const res = await Api.getCaptchaKey();
22
- const { body: key } = res.data || {};
23
- setCaptchaKey(key);
24
- if (key) {
25
- const image = Api.getCaptchaImgUrl(key) as unknown;
26
- setCaptchaImage(image as string);
27
- }
28
- } catch (err) {const msg =
29
- typeof err === 'object' && err !== null && 'message' in err
30
- ? (err as {message: string}).message
31
- : String(err);
32
- message.error(msg as React.ReactNode);
33
- }
34
- }
35
-
36
- useEffect(() => {
37
- let timer: number | null = null;
38
- if (visible && countdown > 0) {
39
- timer = setInterval(() => {
40
- setCountdown((prev) => prev - 1);
41
- }, 1000);
42
- }
43
- if (countdown === 0) {
44
- getKey();
45
- }
46
- return () => {
47
- if (timer) clearInterval(timer);
48
- };
49
- }, [visible, countdown]);
50
-
51
- const handleResend = async () => {
52
- const formData = new FormData();
53
- formData.append('captchaKey', captchaKey);
54
- formData.append('captcha', captchCode);
55
- // 重新发送验证码
56
- const res = await axios.post(api, formData);
57
- const { code, detail } = res.data?.status || {};
58
- if (code !== 0) {
59
- message.error(detail || t('sendFailed', lang));
60
- return;
61
- }
62
- message.success(t('sendSuccess', lang));
63
- setCountdown(60);
64
- }
65
-
66
- return (
67
- <Modal
68
- width={420}
69
- visible={visible}
70
- onClose={() => {
71
- setVisible(false);
72
- props.onClose?.();
73
- }}
74
- >
75
- <div style={{ fontSize: 14, color: '#666' }}>{t('alreadySend', lang, { phone: mobile })}</div>
76
-
77
- <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 12 }}>
78
- <Input.OTP
79
- length={6}
80
- value={otp}
81
- onChange={async (val) => {
82
- setOtp(val);
83
- if (val.length === 6) {
84
- const {data: {status: {code, detail} = {}}} = response || {};
85
- http({
86
- ...config,
87
- headers: {
88
- ...http.defaults.headers.common,
89
- 'sms-code': val,
90
- 'sms-code-key': verifyCodeKey,
91
- 'Content-Type': config.headers['Content-Type'],
92
- }
93
- }) as any;
94
- console.log(response, code, 'config');
95
- if(code !== 0) {
96
- message.error(detail || t('verifyFailed', lang));
97
- return;
98
- } else {
99
- message.success(t('verifySuccess', lang));
100
- setVisible(false);
101
- }
102
- }
103
- }} />
104
- <Button
105
- disabled={countdown > 0 || !captchCode}
106
- onClick={handleResend}
107
- style={{ padding: '8px' }}
108
- >
109
- {countdown > 0 ? t('countDownSecound', lang, { countdown }) : t('reSend', lang)}
110
- </Button>
111
- </div>
112
- {countdown > 0 ? null :
113
- <div style={{ marginTop: 12, display: 'flex', alignItems: 'center' }}>
114
- <Input
115
- placeholder={t('pleaseEnterPicVerifyCode', lang)}
116
- onChange={(e) => {
117
- setCaptchCode(e as string)
118
- }}
119
- style={{ width: 300 }}
120
- />
121
-
122
- {captchaImage && <img src={captchaImage} alt={t('verifyCode', lang)} style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
123
- </div>}
124
- {(countdown > 0 || captchCode) ? null : <div style={{ fontSize: 14, color: 'red' }}>{t('pleaseEnterAndSend', lang)}</div>}
125
- </Modal>
126
- );
127
- };
128
-
129
- export default CreateMessageVerifyModal;
File without changes