message-verify 0.0.42-beta.0 → 0.0.44-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/input.d.ts +10 -1
- package/dist/compoments/input.js +40 -3
- package/dist/index.d.ts +10 -1
- package/dist/main.js +7 -1
- package/dist/verify-modal.d.ts +10 -1
- package/dist/verify-modal.js +7 -3
- package/package.json +1 -1
- package/src/compoments/input.tsx +70 -7
- package/src/index.tsx +10 -1
- package/src/main.tsx +10 -1
- package/src/verify-modal.tsx +23 -11
@@ -6,5 +6,14 @@ interface CustomInputProps {
|
|
6
6
|
type?: string;
|
7
7
|
style?: React.CSSProperties;
|
8
8
|
}
|
9
|
-
|
9
|
+
interface OTPInputProps {
|
10
|
+
length: number;
|
11
|
+
value?: string;
|
12
|
+
onChange?: (val: string) => void;
|
13
|
+
style?: React.CSSProperties;
|
14
|
+
}
|
15
|
+
declare const OTPInput: React.FC<OTPInputProps>;
|
16
|
+
declare const Input: React.FC<CustomInputProps> & {
|
17
|
+
OTP: typeof OTPInput;
|
18
|
+
};
|
10
19
|
export default Input;
|
package/dist/compoments/input.js
CHANGED
@@ -1,6 +1,42 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
|
3
|
-
|
2
|
+
import { useRef } from 'react';
|
3
|
+
const OTPInput = ({ length, value = '', onChange, style }) => {
|
4
|
+
const inputsRef = useRef([]);
|
5
|
+
// 拆分 value
|
6
|
+
const chars = [];
|
7
|
+
for (let i = 0; i < length; i++) {
|
8
|
+
chars.push(value[i] || '');
|
9
|
+
}
|
10
|
+
const handleChange = (idx, char) => {
|
11
|
+
if (!/^[0-9a-zA-Z]?$/.test(char))
|
12
|
+
return; // 只允许单字符
|
13
|
+
const arr = chars.slice();
|
14
|
+
arr[idx] = char;
|
15
|
+
const newVal = arr.join('');
|
16
|
+
onChange?.(newVal);
|
17
|
+
// 自动聚焦下一个
|
18
|
+
if (char && idx < length - 1) {
|
19
|
+
inputsRef.current[idx + 1]?.focus();
|
20
|
+
}
|
21
|
+
};
|
22
|
+
const handleKeyDown = (idx, e) => {
|
23
|
+
if (e.key === 'Backspace' && !chars[idx] && idx > 0) {
|
24
|
+
// 删除时自动聚焦上一个
|
25
|
+
inputsRef.current[idx - 1]?.focus();
|
26
|
+
}
|
27
|
+
};
|
28
|
+
return (_jsx("div", { style: { display: 'flex', gap: 8, ...style }, children: Array.from({ length }).map((_, idx) => (_jsx("input", { ref: el => { inputsRef.current[idx] = el; }, type: "text", maxLength: 1, value: chars[idx], onChange: e => handleChange(idx, e.target.value), onKeyDown: e => handleKeyDown(idx, e), style: {
|
29
|
+
width: 32,
|
30
|
+
height: 36,
|
31
|
+
textAlign: 'center',
|
32
|
+
fontSize: 18,
|
33
|
+
border: '1px solid #d9d9d9',
|
34
|
+
borderRadius: 8,
|
35
|
+
outline: 'none',
|
36
|
+
} }, idx))) }));
|
37
|
+
};
|
38
|
+
const Input = (props) => {
|
39
|
+
return (_jsx("input", { type: props.type || 'text', value: props.value, placeholder: props.placeholder, onChange: e => props.onChange?.(e.target.value), style: {
|
4
40
|
padding: '6px 12px',
|
5
41
|
border: '1px solid #d9d9d9',
|
6
42
|
borderRadius: 4,
|
@@ -9,7 +45,8 @@ const Input = ({ value, onChange, placeholder, type = 'text', style }) => {
|
|
9
45
|
width: '100%',
|
10
46
|
boxSizing: 'border-box',
|
11
47
|
height: 36,
|
12
|
-
...style,
|
48
|
+
...props.style,
|
13
49
|
} }));
|
14
50
|
};
|
51
|
+
Input.OTP = OTPInput;
|
15
52
|
export default Input;
|
package/dist/index.d.ts
CHANGED
@@ -2,6 +2,15 @@ export type ModalConfig = {
|
|
2
2
|
data: string;
|
3
3
|
onClose?: () => void;
|
4
4
|
config: object;
|
5
|
-
http:
|
5
|
+
http: {
|
6
|
+
(params: object): Promise<unknown>;
|
7
|
+
defaults: {
|
8
|
+
headers: {
|
9
|
+
common: {
|
10
|
+
[key: string]: unknown;
|
11
|
+
};
|
12
|
+
};
|
13
|
+
};
|
14
|
+
};
|
6
15
|
};
|
7
16
|
export declare const createMessageVerifyModal: (modalProps: ModalConfig) => void;
|
package/dist/main.js
CHANGED
@@ -5,5 +5,11 @@ const data = "{\"mobile\":\"188****4035\",\"verifyCodeKey\":\"3f025b33-988e-47c0
|
|
5
5
|
createRoot(document.getElementById('root')).render(_jsx("button", { onClick: () => createMessageVerifyModal({
|
6
6
|
data,
|
7
7
|
config: {},
|
8
|
-
http: () => Promise.resolve({}),
|
8
|
+
http: Object.assign(() => Promise.resolve({}), {
|
9
|
+
defaults: {
|
10
|
+
headers: {
|
11
|
+
common: {}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}),
|
9
15
|
}), children: "Show Modal" }));
|
package/dist/verify-modal.d.ts
CHANGED
@@ -2,7 +2,16 @@ type ModalConfig = {
|
|
2
2
|
data: string;
|
3
3
|
onClose?: () => void;
|
4
4
|
config: object;
|
5
|
-
http:
|
5
|
+
http: {
|
6
|
+
(params: object): Promise<unknown>;
|
7
|
+
defaults: {
|
8
|
+
headers: {
|
9
|
+
common: {
|
10
|
+
[key: string]: unknown;
|
11
|
+
};
|
12
|
+
};
|
13
|
+
};
|
14
|
+
};
|
6
15
|
};
|
7
16
|
declare const ModalDom: ({ props }: {
|
8
17
|
props: ModalConfig;
|
package/dist/verify-modal.js
CHANGED
@@ -5,12 +5,13 @@ import Api from './resource.js';
|
|
5
5
|
const ModalDom = ({ props }) => {
|
6
6
|
const [visible, setVisible] = useState(true);
|
7
7
|
const [countdown, setCountdown] = useState(3);
|
8
|
+
const [otp, setOtp] = useState('');
|
8
9
|
const [captchaImage, setCaptchaImage] = useState('');
|
9
10
|
const [captchCode, setCaptchCode] = useState('');
|
10
11
|
const [captchaKey, setCaptchaKey] = useState('');
|
11
12
|
const { data, config, http } = props || {};
|
12
13
|
const dataObj = JSON.parse(data || '{}');
|
13
|
-
const { mobile } = dataObj || {};
|
14
|
+
const { mobile, verifyCodeKey } = dataObj || {};
|
14
15
|
const getKey = async () => {
|
15
16
|
const res = await Api.getCaptchaKey();
|
16
17
|
const { body: key } = res.data || {};
|
@@ -51,10 +52,13 @@ const ModalDom = ({ props }) => {
|
|
51
52
|
props.onClose?.();
|
52
53
|
}, 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) => {
|
53
54
|
setCaptchCode(e);
|
54
|
-
} }), 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, {
|
55
|
+
} }), 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.OTP, { length: 6, value: otp, onChange: (val) => {
|
56
|
+
setOtp(val);
|
55
57
|
if (val.length === 6) {
|
56
|
-
|
58
|
+
http.defaults.headers.common['sms-code'] = val;
|
59
|
+
http.defaults.headers.common['sms-code-key'] = verifyCodeKey;
|
57
60
|
http(config);
|
61
|
+
setVisible(false);
|
58
62
|
}
|
59
63
|
} }), _jsx(Button, { disabled: countdown > 0 || !captchCode, onClick: handleResend, children: countdown > 0 ? `${countdown}秒` : '重新发送' })] })] }));
|
60
64
|
};
|
package/package.json
CHANGED
package/src/compoments/input.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useRef } from 'react';
|
2
2
|
|
3
3
|
interface CustomInputProps {
|
4
4
|
value?: string;
|
@@ -8,13 +8,74 @@ interface CustomInputProps {
|
|
8
8
|
style?: React.CSSProperties;
|
9
9
|
}
|
10
10
|
|
11
|
-
|
11
|
+
interface OTPInputProps {
|
12
|
+
length: number;
|
13
|
+
value?: string;
|
14
|
+
onChange?: (val: string) => void;
|
15
|
+
style?: React.CSSProperties;
|
16
|
+
}
|
17
|
+
|
18
|
+
const OTPInput: React.FC<OTPInputProps> = ({ length, value = '', onChange, style }) => {
|
19
|
+
const inputsRef = useRef<Array<HTMLInputElement | null>>([]);
|
20
|
+
|
21
|
+
// 拆分 value
|
22
|
+
const chars: string[] = [];
|
23
|
+
for (let i = 0; i < length; i++) {
|
24
|
+
chars.push(value[i] || '');
|
25
|
+
}
|
26
|
+
|
27
|
+
const handleChange = (idx: number, char: string) => {
|
28
|
+
if (!/^[0-9a-zA-Z]?$/.test(char)) return; // 只允许单字符
|
29
|
+
const arr = chars.slice();
|
30
|
+
arr[idx] = char;
|
31
|
+
const newVal = arr.join('');
|
32
|
+
onChange?.(newVal);
|
33
|
+
// 自动聚焦下一个
|
34
|
+
if (char && idx < length - 1) {
|
35
|
+
inputsRef.current[idx + 1]?.focus();
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
const handleKeyDown = (idx: number, e: React.KeyboardEvent<HTMLInputElement>) => {
|
40
|
+
if (e.key === 'Backspace' && !chars[idx] && idx > 0) {
|
41
|
+
// 删除时自动聚焦上一个
|
42
|
+
inputsRef.current[idx - 1]?.focus();
|
43
|
+
}
|
44
|
+
};
|
45
|
+
|
46
|
+
return (
|
47
|
+
<div style={{ display: 'flex', gap: 8, ...style }}>
|
48
|
+
{Array.from({ length }).map((_, idx) => (
|
49
|
+
<input
|
50
|
+
key={idx}
|
51
|
+
ref={el => { inputsRef.current[idx] = el; }}
|
52
|
+
type="text"
|
53
|
+
maxLength={1}
|
54
|
+
value={chars[idx]}
|
55
|
+
onChange={e => handleChange(idx, e.target.value)}
|
56
|
+
onKeyDown={e => handleKeyDown(idx, e)}
|
57
|
+
style={{
|
58
|
+
width: 32,
|
59
|
+
height: 36,
|
60
|
+
textAlign: 'center',
|
61
|
+
fontSize: 18,
|
62
|
+
border: '1px solid #d9d9d9',
|
63
|
+
borderRadius: 8,
|
64
|
+
outline: 'none',
|
65
|
+
}}
|
66
|
+
/>
|
67
|
+
))}
|
68
|
+
</div>
|
69
|
+
);
|
70
|
+
};
|
71
|
+
|
72
|
+
const Input: React.FC<CustomInputProps> & { OTP: typeof OTPInput } = (props) => {
|
12
73
|
return (
|
13
74
|
<input
|
14
|
-
type={type}
|
15
|
-
value={value}
|
16
|
-
placeholder={placeholder}
|
17
|
-
onChange={e => onChange?.(e.target.value)}
|
75
|
+
type={props.type || 'text'}
|
76
|
+
value={props.value}
|
77
|
+
placeholder={props.placeholder}
|
78
|
+
onChange={e => props.onChange?.(e.target.value)}
|
18
79
|
style={{
|
19
80
|
padding: '6px 12px',
|
20
81
|
border: '1px solid #d9d9d9',
|
@@ -24,10 +85,12 @@ const Input: React.FC<CustomInputProps> = ({ value, onChange, placeholder, type
|
|
24
85
|
width: '100%',
|
25
86
|
boxSizing: 'border-box',
|
26
87
|
height: 36,
|
27
|
-
...style,
|
88
|
+
...props.style,
|
28
89
|
}}
|
29
90
|
/>
|
30
91
|
);
|
31
92
|
};
|
32
93
|
|
94
|
+
Input.OTP = OTPInput;
|
95
|
+
|
33
96
|
export default Input;
|
package/src/index.tsx
CHANGED
@@ -5,7 +5,16 @@ export type ModalConfig = {
|
|
5
5
|
data: string;
|
6
6
|
onClose?: () => void
|
7
7
|
config: object;
|
8
|
-
http:
|
8
|
+
http: {
|
9
|
+
(params: object): Promise<unknown>;
|
10
|
+
defaults: {
|
11
|
+
headers: {
|
12
|
+
common: {
|
13
|
+
[key: string]: unknown;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
};
|
9
18
|
}
|
10
19
|
|
11
20
|
let modalRoot: ReactDOM.Root | null = null
|
package/src/main.tsx
CHANGED
@@ -7,7 +7,16 @@ createRoot(document.getElementById('root')!).render(
|
|
7
7
|
<button onClick={() => createMessageVerifyModal({
|
8
8
|
data,
|
9
9
|
config: {},
|
10
|
-
http:
|
10
|
+
http: Object.assign(
|
11
|
+
() => Promise.resolve({}),
|
12
|
+
{
|
13
|
+
defaults: {
|
14
|
+
headers: {
|
15
|
+
common: {}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
),
|
11
20
|
})}>
|
12
21
|
Show Modal
|
13
22
|
</button>);
|
package/src/verify-modal.tsx
CHANGED
@@ -6,17 +6,27 @@ type ModalConfig = {
|
|
6
6
|
data: string;
|
7
7
|
onClose?: () => void;
|
8
8
|
config: object;
|
9
|
-
http:
|
9
|
+
http: {
|
10
|
+
(params: object): Promise<unknown>;
|
11
|
+
defaults: {
|
12
|
+
headers: {
|
13
|
+
common: {
|
14
|
+
[key: string]: unknown;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
};
|
10
19
|
}
|
11
20
|
const ModalDom = ({ props }: { props: ModalConfig }) => {
|
12
21
|
const [visible, setVisible] = useState(true);
|
13
22
|
const [countdown, setCountdown] = useState(3);
|
23
|
+
const [otp, setOtp] = useState('');
|
14
24
|
const [captchaImage, setCaptchaImage] = useState<string>('');
|
15
25
|
const [captchCode, setCaptchCode] = useState<string>('');
|
16
26
|
const [captchaKey, setCaptchaKey] = useState<string>('');
|
17
27
|
const { data, config, http } = props || {};
|
18
28
|
const dataObj = JSON.parse(data || '{}');
|
19
|
-
const { mobile } = dataObj || {};
|
29
|
+
const { mobile, verifyCodeKey } = dataObj || {};
|
20
30
|
|
21
31
|
|
22
32
|
const getKey = async () => {
|
@@ -78,15 +88,17 @@ const ModalDom = ({ props }: { props: ModalConfig }) => {
|
|
78
88
|
</div>}
|
79
89
|
{(countdown > 0 || captchCode) ? null : <div style={{ fontSize: 14, color: 'red' }}>请输入图形验证码后,重新发送验证码</div>}
|
80
90
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 8 }}>
|
81
|
-
<Input
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
91
|
+
<Input.OTP length={6}
|
92
|
+
value={otp}
|
93
|
+
onChange={(val) => {
|
94
|
+
setOtp(val);
|
95
|
+
if(val.length === 6) {
|
96
|
+
http.defaults.headers.common['sms-code'] = val as string;
|
97
|
+
http.defaults.headers.common['sms-code-key'] = verifyCodeKey as string;
|
98
|
+
http(config);
|
99
|
+
setVisible(false);
|
100
|
+
}
|
101
|
+
}} />
|
90
102
|
<Button
|
91
103
|
disabled={countdown > 0 || !captchCode}
|
92
104
|
onClick={handleResend}
|