message-verify 0.0.37-beta.0 → 0.0.39-beta.0
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/dist/compoments/button.js +5 -4
- package/dist/compoments/index.d.ts +2 -1
- package/dist/compoments/index.js +2 -1
- package/dist/compoments/input.d.ts +1 -0
- package/dist/compoments/input.js +4 -2
- package/dist/compoments/message.d.ts +6 -0
- package/dist/compoments/message.js +53 -0
- package/dist/index.js +3 -56
- package/dist/resource.js +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/verify-modal.d.ts +12 -0
- package/dist/verify-modal.js +55 -0
- package/package.json +1 -2
- package/src/compoments/button.tsx +5 -4
- package/src/compoments/index.ts +2 -1
- package/src/compoments/input.tsx +5 -2
- package/src/compoments/message.tsx +60 -0
- package/src/index.tsx +2 -85
- package/src/resource.ts +4 -4
- package/src/verify-modal.tsx +97 -0
- package/src/app.tsx +0 -107
@@ -8,12 +8,13 @@ const Button = ({ disabled, onClick, children, style }) => {
|
|
8
8
|
}
|
9
9
|
};
|
10
10
|
return (_jsx("button", { disabled: disabled, onClick: handleClick, style: {
|
11
|
-
padding: '6px
|
12
|
-
borderRadius:
|
11
|
+
padding: '6px 6px',
|
12
|
+
borderRadius: 5,
|
13
13
|
border: '1px solid #d9d9d9',
|
14
|
-
background: disabled ? '#f5f5f5' : '#
|
15
|
-
color: disabled ? '#aaa' : '#
|
14
|
+
background: disabled ? '#f5f5f5' : '#fff',
|
15
|
+
color: disabled ? '#aaa' : '#333',
|
16
16
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
17
|
+
whiteSpace: 'nowrap',
|
17
18
|
...style,
|
18
19
|
}, children: children }));
|
19
20
|
};
|
package/dist/compoments/index.js
CHANGED
package/dist/compoments/input.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
const Input = ({ value, onChange, placeholder, type = 'text' }) => {
|
2
|
+
const Input = ({ value, onChange, placeholder, type = 'text', style }) => {
|
3
3
|
return (_jsx("input", { type: type, value: value, placeholder: placeholder, onChange: e => onChange?.(e.target.value), style: {
|
4
4
|
padding: '6px 12px',
|
5
5
|
border: '1px solid #d9d9d9',
|
@@ -7,7 +7,9 @@ const Input = ({ value, onChange, placeholder, type = 'text' }) => {
|
|
7
7
|
outline: 'none',
|
8
8
|
fontSize: 14,
|
9
9
|
width: '100%',
|
10
|
-
boxSizing: 'border-box'
|
10
|
+
boxSizing: 'border-box',
|
11
|
+
height: 36,
|
12
|
+
...style,
|
11
13
|
} }));
|
12
14
|
};
|
13
15
|
export default Input;
|
@@ -0,0 +1,53 @@
|
|
1
|
+
let messageContainer = null;
|
2
|
+
function createContainer() {
|
3
|
+
if (!messageContainer) {
|
4
|
+
messageContainer = document.createElement('div');
|
5
|
+
messageContainer.style.position = 'fixed';
|
6
|
+
messageContainer.style.top = '24px';
|
7
|
+
messageContainer.style.left = '50%';
|
8
|
+
messageContainer.style.transform = 'translateX(-50%)';
|
9
|
+
messageContainer.style.zIndex = '9999';
|
10
|
+
document.body.appendChild(messageContainer);
|
11
|
+
}
|
12
|
+
}
|
13
|
+
function showMessage(content, type) {
|
14
|
+
createContainer();
|
15
|
+
const msgDiv = document.createElement('div');
|
16
|
+
msgDiv.style.marginTop = '8px';
|
17
|
+
msgDiv.style.padding = '10px 24px';
|
18
|
+
msgDiv.style.borderRadius = '4px';
|
19
|
+
msgDiv.style.boxShadow = '0 2px 8px rgba(0,0,0,0.08)';
|
20
|
+
msgDiv.style.fontSize = '16px';
|
21
|
+
if (type === 'success') {
|
22
|
+
msgDiv.style.background = '#f6ffed';
|
23
|
+
msgDiv.style.color = '#52c41a';
|
24
|
+
}
|
25
|
+
else if (type === 'error') {
|
26
|
+
msgDiv.style.background = '#fff2f0';
|
27
|
+
msgDiv.style.color = '#ff4d4f';
|
28
|
+
}
|
29
|
+
else if (type === 'info') {
|
30
|
+
msgDiv.style.background = '#e6f4ff';
|
31
|
+
msgDiv.style.color = '#1677ff';
|
32
|
+
}
|
33
|
+
msgDiv.innerText = String(content);
|
34
|
+
messageContainer.appendChild(msgDiv);
|
35
|
+
setTimeout(() => {
|
36
|
+
msgDiv.remove();
|
37
|
+
if (messageContainer && messageContainer.childElementCount === 0) {
|
38
|
+
messageContainer.remove();
|
39
|
+
messageContainer = null;
|
40
|
+
}
|
41
|
+
}, 2000);
|
42
|
+
}
|
43
|
+
export const message = {
|
44
|
+
success(content) {
|
45
|
+
showMessage(content, 'success');
|
46
|
+
},
|
47
|
+
error(content) {
|
48
|
+
showMessage(content, 'error');
|
49
|
+
},
|
50
|
+
info(content) {
|
51
|
+
showMessage(content, 'info');
|
52
|
+
}
|
53
|
+
};
|
package/dist/index.js
CHANGED
@@ -1,66 +1,13 @@
|
|
1
|
-
import {
|
2
|
-
import { Modal, Input, Button } from './compoments/index.js';
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
3
2
|
import ReactDOM from 'react-dom/client';
|
4
|
-
import
|
5
|
-
import Api from './resource.js';
|
3
|
+
import VerifyModal from './verify-modal.js';
|
6
4
|
let modalRoot = null;
|
7
|
-
const ModalDom = ({ config }) => {
|
8
|
-
const [visible, setVisible] = useState(true);
|
9
|
-
const [countdown, setCountdown] = useState(60);
|
10
|
-
const [captchaImage, setCaptchaImage] = useState('');
|
11
|
-
const [captchCode, setCaptchCode] = useState('');
|
12
|
-
const [captchaKey, setCaptchaKey] = useState('');
|
13
|
-
const { data } = config || {};
|
14
|
-
const { mobile } = data || {};
|
15
|
-
const getKey = async () => {
|
16
|
-
const res = await Api.getCaptchaKey();
|
17
|
-
const { body: key } = res.data || {};
|
18
|
-
setCaptchaKey(key);
|
19
|
-
if (key) {
|
20
|
-
console.log('res=>key', key);
|
21
|
-
const image = Api.getCaptchaImgUrl(key);
|
22
|
-
console.log('image', image);
|
23
|
-
setCaptchaImage(image);
|
24
|
-
}
|
25
|
-
};
|
26
|
-
useEffect(() => {
|
27
|
-
let timer = null;
|
28
|
-
if (visible && countdown > 0) {
|
29
|
-
timer = setInterval(() => {
|
30
|
-
setCountdown((prev) => prev - 1);
|
31
|
-
}, 1000);
|
32
|
-
}
|
33
|
-
if (countdown === 0) {
|
34
|
-
getKey();
|
35
|
-
}
|
36
|
-
return () => {
|
37
|
-
if (timer)
|
38
|
-
clearInterval(timer);
|
39
|
-
};
|
40
|
-
}, [visible, countdown]);
|
41
|
-
useEffect(() => {
|
42
|
-
console.log('mobile', mobile);
|
43
|
-
}, []);
|
44
|
-
const handleResend = async () => {
|
45
|
-
setCountdown(60);
|
46
|
-
const res = await Api.reSendCode({ captchaKey, captcha: captchCode });
|
47
|
-
console.log('handleResend=>res', res);
|
48
|
-
// message.success('发送成功');
|
49
|
-
};
|
50
|
-
return (_jsxs(Modal, { visible: visible, onClose: () => {
|
51
|
-
setVisible(false);
|
52
|
-
config.onClose?.();
|
53
|
-
}, children: [_jsxs("div", { children: ["\u5DF2\u53D1\u9001\u77ED\u4FE1\u81F3\u60A8\u7684\u624B\u673A\uFF1A", mobile] }), countdown > 0 ? null : _jsxs("div", { style: { marginTop: 8, display: 'flex', alignItems: 'center', width: 300 }, children: [_jsx(Input, { onChange: (e) => {
|
54
|
-
setCaptchCode(e);
|
55
|
-
} }), captchaImage && _jsx("img", { src: captchaImage, alt: "\u9A8C\u8BC1\u7801", style: { width: 100, height: 30, marginLeft: 8 }, onClick: getKey })] }), countdown > 0 ? null : _jsx("div", { children: "\u8BF7\u8F93\u5165\u56FE\u5F62\u9A8C\u8BC1\u7801\u540E\uFF0C\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u7801" }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }, children: [_jsx(Input, { onChange: (val) => { console.log('change', val); } }), _jsx(Button, { disabled: countdown > 0 || !captchCode, onClick: handleResend, children: countdown > 0 ? `${countdown}秒` : '重新发送' })] })] }));
|
56
|
-
};
|
57
|
-
// ... existing code ...
|
58
5
|
export const createMessageVerifyModal = (config) => {
|
59
6
|
const container = document.createElement('div');
|
60
7
|
container.id = 'antd-modal-container';
|
61
8
|
document.body.appendChild(container);
|
62
9
|
modalRoot = ReactDOM.createRoot(container);
|
63
|
-
modalRoot.render(_jsx(
|
10
|
+
modalRoot.render(_jsx(VerifyModal, { config: {
|
64
11
|
...config,
|
65
12
|
onClose: () => {
|
66
13
|
config.onClose?.();
|
package/dist/resource.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { assign, axios as instance, customPost } from '@yqg/resource';
|
2
|
-
|
2
|
+
import { message } from './compoments/index.js';
|
3
3
|
import { YQG_SUCCESS } from './utils/status.js';
|
4
4
|
const urlPrefix = '/admin/';
|
5
5
|
// axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
|
@@ -14,7 +14,7 @@ instance.interceptors.response.use((res) => {
|
|
14
14
|
reader.readAsText(res.data, 'utf-8');
|
15
15
|
reader.onload = () => {
|
16
16
|
const parsedObj = JSON.parse(reader.result);
|
17
|
-
|
17
|
+
message.info(parsedObj?.status?.detail);
|
18
18
|
};
|
19
19
|
return Promise.reject();
|
20
20
|
}
|
@@ -29,13 +29,13 @@ instance.interceptors.response.use((res) => {
|
|
29
29
|
case YQG_SUCCESS:
|
30
30
|
return Promise.resolve(res);
|
31
31
|
default: {
|
32
|
-
|
32
|
+
message.error(detail);
|
33
33
|
return Promise.reject(res);
|
34
34
|
}
|
35
35
|
}
|
36
36
|
}, (err) => {
|
37
37
|
const detail = err?.data?.status?.detail || 'Unknown error';
|
38
|
-
|
38
|
+
message.error(detail);
|
39
39
|
return Promise.reject(err);
|
40
40
|
});
|
41
41
|
const api = {
|
@@ -1 +1 @@
|
|
1
|
-
{"root":["../src/
|
1
|
+
{"root":["../src/index.tsx","../src/main.tsx","../src/resource.ts","../src/verify-modal.tsx","../src/vite-env.d.ts","../src/compoments/button.tsx","../src/compoments/index.ts","../src/compoments/input.tsx","../src/compoments/message.tsx","../src/compoments/modal.tsx","../src/utils/getfingerprint.ts","../src/utils/index.ts","../src/utils/status.ts"],"version":"5.7.3"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
type ModalConfig = {
|
2
|
+
data: {
|
3
|
+
mobile: string;
|
4
|
+
verifyCodeKey: string;
|
5
|
+
sendSuccess: boolean;
|
6
|
+
};
|
7
|
+
onClose?: () => void;
|
8
|
+
};
|
9
|
+
declare const ModalDom: ({ config }: {
|
10
|
+
config: ModalConfig;
|
11
|
+
}) => import("react/jsx-runtime.js").JSX.Element;
|
12
|
+
export default ModalDom;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import { useEffect, useState } from 'react';
|
3
|
+
import { Modal, Input, Button, message } from './compoments/index.js';
|
4
|
+
import Api from './resource.js';
|
5
|
+
const ModalDom = ({ config }) => {
|
6
|
+
const [visible, setVisible] = useState(true);
|
7
|
+
const [countdown, setCountdown] = useState(3);
|
8
|
+
const [captchaImage, setCaptchaImage] = useState('');
|
9
|
+
const [captchCode, setCaptchCode] = useState('');
|
10
|
+
const [captchaKey, setCaptchaKey] = useState('');
|
11
|
+
const { data } = config || {};
|
12
|
+
const { mobile } = data || {};
|
13
|
+
const getKey = async () => {
|
14
|
+
const res = await Api.getCaptchaKey();
|
15
|
+
const { body: key } = res.data || {};
|
16
|
+
setCaptchaKey(key);
|
17
|
+
if (key) {
|
18
|
+
console.log('res=>key', key);
|
19
|
+
const image = Api.getCaptchaImgUrl(key);
|
20
|
+
console.log('image', image);
|
21
|
+
setCaptchaImage(image);
|
22
|
+
}
|
23
|
+
};
|
24
|
+
useEffect(() => {
|
25
|
+
let timer = null;
|
26
|
+
if (visible && countdown > 0) {
|
27
|
+
timer = setInterval(() => {
|
28
|
+
setCountdown((prev) => prev - 1);
|
29
|
+
}, 1000);
|
30
|
+
}
|
31
|
+
if (countdown === 0) {
|
32
|
+
getKey();
|
33
|
+
}
|
34
|
+
return () => {
|
35
|
+
if (timer)
|
36
|
+
clearInterval(timer);
|
37
|
+
};
|
38
|
+
}, [visible, countdown]);
|
39
|
+
useEffect(() => {
|
40
|
+
console.log('mobile', mobile);
|
41
|
+
}, [mobile]);
|
42
|
+
const handleResend = async () => {
|
43
|
+
setCountdown(60);
|
44
|
+
const res = await Api.reSendCode({ captchaKey, captcha: captchCode });
|
45
|
+
console.log('handleResend=>res', res);
|
46
|
+
message.success('发送成功');
|
47
|
+
};
|
48
|
+
return (_jsxs(Modal, { visible: visible, onClose: () => {
|
49
|
+
setVisible(false);
|
50
|
+
config.onClose?.();
|
51
|
+
}, children: [_jsxs("div", { style: { fontSize: 14, color: '#666' }, children: ["\u5DF2\u53D1\u9001\u77ED\u4FE1\u81F3\u60A8\u7684\u624B\u673A\uFF1A", mobile] }), countdown > 0 ? null : _jsxs("div", { style: { marginBlock: 8, display: 'flex', alignItems: 'center', width: 300 }, children: [_jsx(Input, { placeholder: "\u8BF7\u8F93\u5165\u56FE\u5F62\u9A8C\u8BC1\u7801", onChange: (e) => {
|
52
|
+
setCaptchCode(e);
|
53
|
+
} }), captchaImage && _jsx("img", { src: captchaImage, alt: "\u9A8C\u8BC1\u7801", style: { width: 100, height: 30, marginLeft: 8 }, onClick: getKey })] }), (countdown > 0 || captchCode) ? null : _jsx("div", { style: { fontSize: 14, color: 'red' }, children: "\u8BF7\u8F93\u5165\u56FE\u5F62\u9A8C\u8BC1\u7801\u540E\uFF0C\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u7801" }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }, children: [_jsx(Input, { placeholder: "\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801", onChange: (val) => { console.log('change', val); } }), _jsx(Button, { disabled: countdown > 0 || !captchCode, onClick: handleResend, children: countdown > 0 ? `${countdown}秒` : '重新发送' })] })] }));
|
54
|
+
};
|
55
|
+
export default ModalDom;
|
package/package.json
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
{
|
2
2
|
"name": "message-verify",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.39-beta.0",
|
4
4
|
"type": "module",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"dependencies": {
|
7
|
-
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
8
7
|
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
9
8
|
"@yqg/resource": "^1.3.8",
|
10
9
|
"react": "^19.0.0",
|
@@ -21,12 +21,13 @@ const Button: React.FC<CustomButtonProps> = ({ disabled, onClick, children, styl
|
|
21
21
|
disabled={disabled}
|
22
22
|
onClick={handleClick}
|
23
23
|
style={{
|
24
|
-
padding: '6px
|
25
|
-
borderRadius:
|
24
|
+
padding: '6px 6px',
|
25
|
+
borderRadius: 5,
|
26
26
|
border: '1px solid #d9d9d9',
|
27
|
-
background: disabled ? '#f5f5f5' : '#
|
28
|
-
color: disabled ? '#aaa' : '#
|
27
|
+
background: disabled ? '#f5f5f5' : '#fff',
|
28
|
+
color: disabled ? '#aaa' : '#333',
|
29
29
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
30
|
+
whiteSpace: 'nowrap',
|
30
31
|
...style,
|
31
32
|
}}
|
32
33
|
>
|
package/src/compoments/index.ts
CHANGED
package/src/compoments/input.tsx
CHANGED
@@ -5,9 +5,10 @@ interface CustomInputProps {
|
|
5
5
|
onChange?: (val: string) => void;
|
6
6
|
placeholder?: string;
|
7
7
|
type?: string;
|
8
|
+
style?: React.CSSProperties;
|
8
9
|
}
|
9
10
|
|
10
|
-
const Input: React.FC<CustomInputProps> = ({ value, onChange, placeholder, type = 'text' }) => {
|
11
|
+
const Input: React.FC<CustomInputProps> = ({ value, onChange, placeholder, type = 'text', style }) => {
|
11
12
|
return (
|
12
13
|
<input
|
13
14
|
type={type}
|
@@ -21,7 +22,9 @@ const Input: React.FC<CustomInputProps> = ({ value, onChange, placeholder, type
|
|
21
22
|
outline: 'none',
|
22
23
|
fontSize: 14,
|
23
24
|
width: '100%',
|
24
|
-
boxSizing: 'border-box'
|
25
|
+
boxSizing: 'border-box',
|
26
|
+
height: 36,
|
27
|
+
...style,
|
25
28
|
}}
|
26
29
|
/>
|
27
30
|
);
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { ReactNode } from 'react';
|
2
|
+
|
3
|
+
let messageContainer: HTMLDivElement | null = null;
|
4
|
+
|
5
|
+
function createContainer() {
|
6
|
+
if (!messageContainer) {
|
7
|
+
messageContainer = document.createElement('div');
|
8
|
+
messageContainer.style.position = 'fixed';
|
9
|
+
messageContainer.style.top = '24px';
|
10
|
+
messageContainer.style.left = '50%';
|
11
|
+
messageContainer.style.transform = 'translateX(-50%)';
|
12
|
+
messageContainer.style.zIndex = '9999';
|
13
|
+
document.body.appendChild(messageContainer);
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
function showMessage(content: ReactNode, type: 'success' | 'error' | 'info') {
|
18
|
+
createContainer();
|
19
|
+
const msgDiv = document.createElement('div');
|
20
|
+
msgDiv.style.marginTop = '8px';
|
21
|
+
msgDiv.style.padding = '10px 24px';
|
22
|
+
msgDiv.style.borderRadius = '4px';
|
23
|
+
msgDiv.style.boxShadow = '0 2px 8px rgba(0,0,0,0.08)';
|
24
|
+
msgDiv.style.fontSize = '16px';
|
25
|
+
|
26
|
+
if (type === 'success') {
|
27
|
+
msgDiv.style.background = '#f6ffed';
|
28
|
+
msgDiv.style.color = '#52c41a';
|
29
|
+
} else if (type === 'error') {
|
30
|
+
msgDiv.style.background = '#fff2f0';
|
31
|
+
msgDiv.style.color = '#ff4d4f';
|
32
|
+
} else if (type === 'info') {
|
33
|
+
msgDiv.style.background = '#e6f4ff';
|
34
|
+
msgDiv.style.color = '#1677ff';
|
35
|
+
}
|
36
|
+
|
37
|
+
msgDiv.innerText = String(content);
|
38
|
+
|
39
|
+
messageContainer!.appendChild(msgDiv);
|
40
|
+
|
41
|
+
setTimeout(() => {
|
42
|
+
msgDiv.remove();
|
43
|
+
if (messageContainer && messageContainer.childElementCount === 0) {
|
44
|
+
messageContainer.remove();
|
45
|
+
messageContainer = null;
|
46
|
+
}
|
47
|
+
}, 2000);
|
48
|
+
}
|
49
|
+
|
50
|
+
export const message = {
|
51
|
+
success(content: ReactNode) {
|
52
|
+
showMessage(content, 'success');
|
53
|
+
},
|
54
|
+
error(content: ReactNode) {
|
55
|
+
showMessage(content, 'error');
|
56
|
+
},
|
57
|
+
info(content: ReactNode) {
|
58
|
+
showMessage(content, 'info');
|
59
|
+
}
|
60
|
+
};
|
package/src/index.tsx
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
import { Modal, Input, Button } from './compoments/index.js'
|
2
1
|
import ReactDOM from 'react-dom/client'
|
3
|
-
import
|
4
|
-
import Api from './resource.js'
|
2
|
+
import VerifyModal from './verify-modal.js'
|
5
3
|
|
6
4
|
export type ModalConfig = {
|
7
5
|
data: {
|
@@ -14,87 +12,6 @@ export type ModalConfig = {
|
|
14
12
|
|
15
13
|
let modalRoot: ReactDOM.Root | null = null
|
16
14
|
|
17
|
-
const ModalDom = ({ config }: { config: ModalConfig }) => {
|
18
|
-
const [visible, setVisible] = useState(true);
|
19
|
-
const [countdown, setCountdown] = useState(60);
|
20
|
-
const [captchaImage, setCaptchaImage] = useState<string>('');
|
21
|
-
const [captchCode, setCaptchCode] = useState<string>('');
|
22
|
-
const [captchaKey, setCaptchaKey] = useState<string>('');
|
23
|
-
const { data } = config || {};
|
24
|
-
const { mobile } = data || {};
|
25
|
-
|
26
|
-
|
27
|
-
const getKey = async () => {
|
28
|
-
const res = await Api.getCaptchaKey();
|
29
|
-
const { body: key } = res.data || {};
|
30
|
-
setCaptchaKey(key);
|
31
|
-
if(key) {
|
32
|
-
console.log('res=>key', key);
|
33
|
-
const image = Api.getCaptchaImgUrl(key) as unknown;
|
34
|
-
console.log('image', image);
|
35
|
-
setCaptchaImage(image as string);
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
useEffect(() => {
|
40
|
-
let timer: number | null = null;
|
41
|
-
if (visible && countdown > 0) {
|
42
|
-
timer = setInterval(() => {
|
43
|
-
setCountdown((prev) => prev - 1);
|
44
|
-
}, 1000);
|
45
|
-
}
|
46
|
-
if (countdown === 0) {
|
47
|
-
getKey();
|
48
|
-
}
|
49
|
-
return () => {
|
50
|
-
if (timer) clearInterval(timer);
|
51
|
-
};
|
52
|
-
}, [visible, countdown]);
|
53
|
-
|
54
|
-
useEffect(() => {
|
55
|
-
console.log('mobile', mobile);
|
56
|
-
}, [])
|
57
|
-
|
58
|
-
const handleResend = async() => {
|
59
|
-
setCountdown(60);
|
60
|
-
const res = await Api.reSendCode({captchaKey, captcha: captchCode});
|
61
|
-
console.log('handleResend=>res', res);
|
62
|
-
// message.success('发送成功');
|
63
|
-
}
|
64
|
-
|
65
|
-
return (
|
66
|
-
<Modal
|
67
|
-
visible={visible}
|
68
|
-
onClose={() => {
|
69
|
-
setVisible(false);
|
70
|
-
config.onClose?.();
|
71
|
-
}}
|
72
|
-
>
|
73
|
-
<div>已发送短信至您的手机:{mobile}</div>
|
74
|
-
{countdown > 0 ? null : <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', width: 300 }}>
|
75
|
-
<Input onChange={(e) => {
|
76
|
-
setCaptchCode(e as string)
|
77
|
-
}} />
|
78
|
-
|
79
|
-
{captchaImage && <img src={captchaImage} alt="验证码" style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
|
80
|
-
</div>}
|
81
|
-
{countdown > 0 ? null : <div>请输入图形验证码后,重新发送验证码</div>}
|
82
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
|
83
|
-
<Input
|
84
|
-
onChange={(val) => {console.log('change', val)}}
|
85
|
-
/>
|
86
|
-
<Button
|
87
|
-
disabled={countdown > 0 || !captchCode}
|
88
|
-
onClick={handleResend}
|
89
|
-
>
|
90
|
-
{countdown > 0 ? `${countdown}秒` : '重新发送'}
|
91
|
-
</Button>
|
92
|
-
</div>
|
93
|
-
</Modal>
|
94
|
-
);
|
95
|
-
};
|
96
|
-
// ... existing code ...
|
97
|
-
|
98
15
|
export const createMessageVerifyModal = (config: ModalConfig) => {
|
99
16
|
const container = document.createElement('div')
|
100
17
|
container.id = 'antd-modal-container'
|
@@ -102,7 +19,7 @@ export const createMessageVerifyModal = (config: ModalConfig) => {
|
|
102
19
|
|
103
20
|
modalRoot = ReactDOM.createRoot(container)
|
104
21
|
modalRoot.render(
|
105
|
-
<
|
22
|
+
<VerifyModal
|
106
23
|
config={{
|
107
24
|
...config,
|
108
25
|
onClose: () => {
|
package/src/resource.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { assign, axios as instance, customPost } from '@yqg/resource';
|
2
|
-
|
2
|
+
import { message } from './compoments/index.js';
|
3
3
|
import { YQG_SUCCESS } from './utils/status.js';
|
4
4
|
|
5
5
|
const urlPrefix = '/admin/';
|
@@ -16,7 +16,7 @@ instance.interceptors.response.use(
|
|
16
16
|
reader.readAsText(res.data, 'utf-8');
|
17
17
|
reader.onload = () => {
|
18
18
|
const parsedObj = JSON.parse(reader.result as string);
|
19
|
-
|
19
|
+
message.info(parsedObj?.status?.detail);
|
20
20
|
};
|
21
21
|
|
22
22
|
return Promise.reject();
|
@@ -33,14 +33,14 @@ instance.interceptors.response.use(
|
|
33
33
|
case YQG_SUCCESS:
|
34
34
|
return Promise.resolve(res);
|
35
35
|
default: {
|
36
|
-
|
36
|
+
message.error(detail);
|
37
37
|
return Promise.reject(res);
|
38
38
|
}
|
39
39
|
}
|
40
40
|
},
|
41
41
|
(err: {data: {status: {detail: string}}}) => {
|
42
42
|
const detail = err?.data?.status?.detail || 'Unknown error';
|
43
|
-
|
43
|
+
message.error(detail);
|
44
44
|
|
45
45
|
return Promise.reject(err);
|
46
46
|
},
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { useEffect, useState } from 'react'
|
2
|
+
import { Modal, Input, Button, message } from './compoments/index.js'
|
3
|
+
import Api from './resource.js'
|
4
|
+
|
5
|
+
type ModalConfig = {
|
6
|
+
data: {
|
7
|
+
mobile: string;
|
8
|
+
verifyCodeKey: string;
|
9
|
+
sendSuccess: boolean;
|
10
|
+
};
|
11
|
+
onClose?: () => void
|
12
|
+
}
|
13
|
+
const ModalDom = ({ config }: { config: ModalConfig }) => {
|
14
|
+
const [visible, setVisible] = useState(true);
|
15
|
+
const [countdown, setCountdown] = useState(3);
|
16
|
+
const [captchaImage, setCaptchaImage] = useState<string>('');
|
17
|
+
const [captchCode, setCaptchCode] = useState<string>('');
|
18
|
+
const [captchaKey, setCaptchaKey] = useState<string>('');
|
19
|
+
const { data } = config || {};
|
20
|
+
const { mobile } = data || {};
|
21
|
+
|
22
|
+
|
23
|
+
const getKey = async () => {
|
24
|
+
const res = await Api.getCaptchaKey();
|
25
|
+
const { body: key } = res.data || {};
|
26
|
+
setCaptchaKey(key);
|
27
|
+
if(key) {
|
28
|
+
console.log('res=>key', key);
|
29
|
+
const image = Api.getCaptchaImgUrl(key) as unknown;
|
30
|
+
console.log('image', image);
|
31
|
+
setCaptchaImage(image as string);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
useEffect(() => {
|
36
|
+
let timer: number | null = null;
|
37
|
+
if (visible && countdown > 0) {
|
38
|
+
timer = setInterval(() => {
|
39
|
+
setCountdown((prev) => prev - 1);
|
40
|
+
}, 1000);
|
41
|
+
}
|
42
|
+
if (countdown === 0) {
|
43
|
+
getKey();
|
44
|
+
}
|
45
|
+
return () => {
|
46
|
+
if (timer) clearInterval(timer);
|
47
|
+
};
|
48
|
+
}, [visible, countdown]);
|
49
|
+
|
50
|
+
useEffect(() => {
|
51
|
+
console.log('mobile', mobile);
|
52
|
+
}, [mobile])
|
53
|
+
|
54
|
+
const handleResend = async() => {
|
55
|
+
setCountdown(60);
|
56
|
+
const res = await Api.reSendCode({captchaKey, captcha: captchCode});
|
57
|
+
console.log('handleResend=>res', res);
|
58
|
+
message.success('发送成功');
|
59
|
+
}
|
60
|
+
|
61
|
+
return (
|
62
|
+
<Modal
|
63
|
+
visible={visible}
|
64
|
+
onClose={() => {
|
65
|
+
setVisible(false);
|
66
|
+
config.onClose?.();
|
67
|
+
}}
|
68
|
+
>
|
69
|
+
<div style={{ fontSize: 14, color: '#666' }}>已发送短信至您的手机:{mobile}</div>
|
70
|
+
{countdown > 0 ? null : <div style={{ marginBlock: 8, display: 'flex', alignItems: 'center', width: 300 }}>
|
71
|
+
<Input
|
72
|
+
placeholder="请输入图形验证码"
|
73
|
+
onChange={(e) => {
|
74
|
+
setCaptchCode(e as string)
|
75
|
+
}}
|
76
|
+
/>
|
77
|
+
|
78
|
+
{captchaImage && <img src={captchaImage} alt="验证码" style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
|
79
|
+
</div>}
|
80
|
+
{(countdown > 0 || captchCode) ? null : <div style={{ fontSize: 14, color: 'red' }}>请输入图形验证码后,重新发送验证码</div>}
|
81
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
|
82
|
+
<Input
|
83
|
+
placeholder="请输入验证码"
|
84
|
+
onChange={(val) => {console.log('change', val)}}
|
85
|
+
/>
|
86
|
+
<Button
|
87
|
+
disabled={countdown > 0 || !captchCode}
|
88
|
+
onClick={handleResend}
|
89
|
+
>
|
90
|
+
{countdown > 0 ? `${countdown}秒` : '重新发送'}
|
91
|
+
</Button>
|
92
|
+
</div>
|
93
|
+
</Modal>
|
94
|
+
);
|
95
|
+
};
|
96
|
+
|
97
|
+
export default ModalDom;
|
package/src/app.tsx
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
// import { useEffect, useState } from 'react'
|
2
|
-
// import { createPortal } from 'react-dom';
|
3
|
-
// import { Input, Button, Modal, message } from 'antd';
|
4
|
-
// import Api from './resource.js'
|
5
|
-
import '@ant-design/v5-patch-for-react-19';
|
6
|
-
|
7
|
-
interface Props {
|
8
|
-
data: {
|
9
|
-
mobile: string;
|
10
|
-
verifyCodeKey: string;
|
11
|
-
sendSuccess: boolean;
|
12
|
-
};
|
13
|
-
refresh: () => void;
|
14
|
-
isShow: boolean;
|
15
|
-
}
|
16
|
-
const App: React.FC<Props> = () => {
|
17
|
-
// const { mobile } = data || {};
|
18
|
-
// const [countdown, setCountdown] = useState(3);
|
19
|
-
// const [visible, setVisible] = useState(isShow || false);
|
20
|
-
// const [captchaImage, setCaptchaImage] = useState<string>('');
|
21
|
-
// const [captchCode, setCaptchCode] = useState<string>('');
|
22
|
-
// const [captchaKey, setCaptchaKey] = useState<string>('');
|
23
|
-
|
24
|
-
// const getKey = async () => {
|
25
|
-
// const res = await Api.getCaptchaKey();
|
26
|
-
// const { body: key } = res.data || {};
|
27
|
-
// setCaptchaKey(key);
|
28
|
-
// if(key) {
|
29
|
-
// console.log('res=>key', key);
|
30
|
-
// const image = Api.getCaptchaImgUrl(key) as unknown;
|
31
|
-
// console.log('image', image);
|
32
|
-
// setCaptchaImage(image as string);
|
33
|
-
// }
|
34
|
-
// }
|
35
|
-
|
36
|
-
// useEffect(() => {
|
37
|
-
// setVisible(true);
|
38
|
-
// }, [])
|
39
|
-
|
40
|
-
// useEffect(() => {
|
41
|
-
// let timer: number | null = null;
|
42
|
-
// if (visible && countdown > 0) {
|
43
|
-
// timer = setInterval(() => {
|
44
|
-
// setCountdown((prev) => prev - 1);
|
45
|
-
// }, 1000);
|
46
|
-
// }
|
47
|
-
// if (countdown === 0) {
|
48
|
-
// getKey();
|
49
|
-
// }
|
50
|
-
// return () => {
|
51
|
-
// if (timer) clearInterval(timer);
|
52
|
-
// };
|
53
|
-
// }, [visible, countdown]);
|
54
|
-
|
55
|
-
// const handleResend = async() => {
|
56
|
-
// setCountdown(60);
|
57
|
-
// const res = await Api.reSendCode({captchaKey, captcha: captchCode});
|
58
|
-
// console.log('handleResend=>res', res);
|
59
|
-
// // message.success('发送成功');
|
60
|
-
// }
|
61
|
-
|
62
|
-
// const renderModal = (
|
63
|
-
// <Modal
|
64
|
-
// open={visible}
|
65
|
-
// onClose={() => setVisible(false)}
|
66
|
-
// width={400}
|
67
|
-
// footer={
|
68
|
-
// <Button onClick={() => {/* 提交逻辑 */}}>
|
69
|
-
// 提交
|
70
|
-
// </Button>
|
71
|
-
// }
|
72
|
-
// >
|
73
|
-
// <div>已发送短信至您的手机:{mobile}</div>
|
74
|
-
// {countdown > 0 ? null : <div style={{ marginTop: 8, display: 'flex', alignItems: 'center', width: 300 }}>
|
75
|
-
// <Input onChange={(e) => {
|
76
|
-
// setCaptchCode(e.target.value as string)
|
77
|
-
// }} />
|
78
|
-
|
79
|
-
// {captchaImage && <img src={captchaImage} alt="验证码" style={{ width: 100, height: 30, marginLeft: 8 }} onClick={getKey} />}
|
80
|
-
// </div>}
|
81
|
-
// {countdown > 0 ? null : <div>请输入图形验证码后,重新发送验证码</div>}
|
82
|
-
// <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
|
83
|
-
// <Input.OTP
|
84
|
-
// disabled={!captchCode}
|
85
|
-
// length={6}
|
86
|
-
// onChange={(val) => {console.log('change', val)}}
|
87
|
-
// />
|
88
|
-
// <Button
|
89
|
-
// disabled={countdown > 0 || !captchCode}
|
90
|
-
// onClick={handleResend}
|
91
|
-
// >
|
92
|
-
// {countdown > 0 ? `${countdown}秒` : '重新发送'}
|
93
|
-
// </Button>
|
94
|
-
// </div>
|
95
|
-
// </Modal>
|
96
|
-
|
97
|
-
// )
|
98
|
-
|
99
|
-
// console.log('captchCode', captchCode);
|
100
|
-
// if(isShow) {
|
101
|
-
// return createPortal(renderModal, document.body);
|
102
|
-
// }
|
103
|
-
// return null;
|
104
|
-
return <div>111</div>
|
105
|
-
}
|
106
|
-
|
107
|
-
export default App;
|