@pubinfo/module-captcha 2.1.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/LICENSE +21 -0
- package/dist/api/modules/auth/index.d.ts +1 -0
- package/dist/api/modules/auth/renzhengfuwu.d.ts +78 -0
- package/dist/api/request.d.ts +1 -0
- package/dist/components/VerifyInput/PubinfoVerifyInput.vue.d.ts +17 -0
- package/dist/components/VerifyInput/authService.d.ts +9 -0
- package/dist/components/VerifyInput/captchaUtils.d.ts +6 -0
- package/dist/components/VerifyPoints/PubinfoFixedPoint.vue.d.ts +11 -0
- package/dist/components/VerifyPoints/PubinfoPopPoint.vue.d.ts +17 -0
- package/dist/components/VerifyPoints/PubinfoTouchPoint.vue.d.ts +30 -0
- package/dist/components/VerifyPoints/common/checkEvent.d.ts +5 -0
- package/dist/components/VerifyPoints/common/initFuns.d.ts +2 -0
- package/dist/components/VerifyPoints/common/touchService.d.ts +10 -0
- package/dist/components/VerifyPoints/common/variable.d.ts +39 -0
- package/dist/components/VerifyPoints/pubinfoPopPoint.d.ts +1 -0
- package/dist/components/VerifySlide/PubinfoFixedSlide.vue.d.ts +14 -0
- package/dist/components/VerifySlide/PubinfoPopSlide.vue.d.ts +17 -0
- package/dist/components/VerifySlide/PubinfoTouchSlide.vue.d.ts +35 -0
- package/dist/components/VerifySlide/common/init.d.ts +2 -0
- package/dist/components/VerifySlide/common/mouse.d.ts +9 -0
- package/dist/components/VerifySlide/common/touchService.d.ts +10 -0
- package/dist/components/VerifySlide/common/variable.d.ts +59 -0
- package/dist/components/VerifySlide/pubinfoPopSlide.d.ts +1 -0
- package/dist/components/aes.d.ts +1 -0
- package/dist/context.d.ts +2 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6165 -0
- package/dist/interface.d.ts +15 -0
- package/package.json +44 -0
- package/src/api/modules/auth/index.ts +1 -0
- package/src/api/modules/auth/renzhengfuwu.ts +223 -0
- package/src/api/modules/auth/typings.d.ts +140 -0
- package/src/api/request.ts +4 -0
- package/src/components/VerifyInput/PubinfoVerifyInput.vue +91 -0
- package/src/components/VerifyInput/authService.ts +22 -0
- package/src/components/VerifyInput/captchaUtils.ts +15 -0
- package/src/components/VerifyPoints/PubinfoFixedPoint.vue +224 -0
- package/src/components/VerifyPoints/PubinfoPopPoint.vue +55 -0
- package/src/components/VerifyPoints/PubinfoTouchPoint.vue +73 -0
- package/src/components/VerifyPoints/common/checkEvent.ts +72 -0
- package/src/components/VerifyPoints/common/initFuns.ts +44 -0
- package/src/components/VerifyPoints/common/touchService.ts +53 -0
- package/src/components/VerifyPoints/common/variable.ts +76 -0
- package/src/components/VerifyPoints/pubinfoPopPoint.ts +34 -0
- package/src/components/VerifySlide/PubinfoFixedSlide.vue +285 -0
- package/src/components/VerifySlide/PubinfoPopSlide.vue +53 -0
- package/src/components/VerifySlide/PubinfoTouchSlide.vue +51 -0
- package/src/components/VerifySlide/common/init.ts +41 -0
- package/src/components/VerifySlide/common/mouse.ts +124 -0
- package/src/components/VerifySlide/common/touchService.ts +52 -0
- package/src/components/VerifySlide/common/variable.ts +90 -0
- package/src/components/VerifySlide/pubinfoPopSlide.ts +34 -0
- package/src/components/aes.ts +13 -0
- package/src/context.ts +4 -0
- package/src/images/click.png +0 -0
- package/src/index.ts +37 -0
- package/src/interface.ts +19 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RequestInstance } from 'pubinfo';
|
|
2
|
+
export interface CaptchaOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 接口请求实例
|
|
5
|
+
*/
|
|
6
|
+
request: InternalContext['request'];
|
|
7
|
+
}
|
|
8
|
+
export interface InternalContext {
|
|
9
|
+
request: RequestInstance;
|
|
10
|
+
}
|
|
11
|
+
export { RequestInstance };
|
|
12
|
+
export interface CaptchaResult {
|
|
13
|
+
captchaVerification: string;
|
|
14
|
+
captchaType: string;
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pubinfo/module-captcha",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "2.1.1",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"default": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./style.css": "./dist/index.css"
|
|
11
|
+
},
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@ant-design/icons-vue": "^7.0.1",
|
|
24
|
+
"ant-design-vue": "^4.2.6",
|
|
25
|
+
"pubinfo": "2.1.1"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@vueuse/core": "^13.7.0",
|
|
29
|
+
"crypto-js": "^4.2.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@ant-design/icons-vue": "^7.0.1",
|
|
33
|
+
"@types/crypto-js": "^4.2.2",
|
|
34
|
+
"ant-design-vue": "^4.2.6",
|
|
35
|
+
"pubinfo": "2.1.1"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "pubinfo build -w --sourcemap",
|
|
39
|
+
"build": "pubinfo build",
|
|
40
|
+
"openapi": "pnpx @pubinfo/openapi generate",
|
|
41
|
+
"test": "vitest",
|
|
42
|
+
"coverage": "vitest --coverage"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './renzhengfuwu';
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { auth as request } from '@/api/request';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description 验证码-前端校验 需要校验的验证码类型:blockPuzzle、clickWord
|
|
5
|
+
* @url /auth/captcha/check
|
|
6
|
+
* @method POST
|
|
7
|
+
* @author @pubinfo/openapi
|
|
8
|
+
*/
|
|
9
|
+
export function postAuthCaptchaCheck<
|
|
10
|
+
R = API.ResponseDataValidCodeVo,
|
|
11
|
+
T = API.ResponseDataValidCodeVo,
|
|
12
|
+
>(
|
|
13
|
+
body: API.CaptchaCheckDto,
|
|
14
|
+
options?: Parameters<typeof request.Post<R, T>>[2],
|
|
15
|
+
) {
|
|
16
|
+
return request.Post<R, T>('/auth/captcha/check', body, {
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
...(options || {}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @description 验证码-获取验证码图片
|
|
26
|
+
* @url /auth/captcha/get
|
|
27
|
+
* @method POST
|
|
28
|
+
* @author @pubinfo/openapi
|
|
29
|
+
*/
|
|
30
|
+
export function postAuthCaptchaGet<
|
|
31
|
+
R = API.ResponseDataValidCodeVo,
|
|
32
|
+
T = API.ResponseDataValidCodeVo,
|
|
33
|
+
>(body: API.CaptchaGetDto, options?: Parameters<typeof request.Post<R, T>>[2]) {
|
|
34
|
+
return request.Post<R, T>('/auth/captcha/get', body, {
|
|
35
|
+
headers: {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
},
|
|
38
|
+
...(options || {}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @description 切换登录组织
|
|
44
|
+
* @url /auth/changeLoginOrg
|
|
45
|
+
* @method POST
|
|
46
|
+
* @author @pubinfo/openapi
|
|
47
|
+
*/
|
|
48
|
+
export function postAuthChangeLoginOrg<
|
|
49
|
+
R = API.ResponseDataLoginTokenVo,
|
|
50
|
+
T = API.ResponseDataLoginTokenVo,
|
|
51
|
+
>(
|
|
52
|
+
params: API.postAuthChangeLoginOrgParams,
|
|
53
|
+
options?: Parameters<typeof request.Post<R, T>>[2],
|
|
54
|
+
) {
|
|
55
|
+
return request.Post<R, T>(
|
|
56
|
+
'/auth/changeLoginOrg',
|
|
57
|
+
{},
|
|
58
|
+
{
|
|
59
|
+
params: {
|
|
60
|
+
...params,
|
|
61
|
+
},
|
|
62
|
+
...(options || {}),
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @description 判断缓存的token是否有效
|
|
69
|
+
* @url /auth/checkCacheToken
|
|
70
|
+
* @method GET
|
|
71
|
+
* @author @pubinfo/openapi
|
|
72
|
+
*/
|
|
73
|
+
export function getAuthCheckCacheToken<
|
|
74
|
+
R = API.ResponseDataBoolean,
|
|
75
|
+
T = API.ResponseDataBoolean,
|
|
76
|
+
>(
|
|
77
|
+
params: API.getAuthCheckCacheTokenParams,
|
|
78
|
+
options?: Parameters<typeof request.Get<R, T>>[1],
|
|
79
|
+
) {
|
|
80
|
+
return request.Get<R, T>('/auth/checkCacheToken', {
|
|
81
|
+
params: {
|
|
82
|
+
...params,
|
|
83
|
+
},
|
|
84
|
+
...(options || {}),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description 密码登录
|
|
90
|
+
* @url /auth/login
|
|
91
|
+
* @method POST
|
|
92
|
+
* @author @pubinfo/openapi
|
|
93
|
+
*/
|
|
94
|
+
export function postAuthLogin<
|
|
95
|
+
R = API.ResponseDataLoginTokenVo,
|
|
96
|
+
T = API.ResponseDataLoginTokenVo,
|
|
97
|
+
>(body: API.LoginByPwdDto, options?: Parameters<typeof request.Post<R, T>>[2]) {
|
|
98
|
+
return request.Post<R, T>('/auth/login', body, {
|
|
99
|
+
headers: {
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
...(options || {}),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @description 获取登录公钥
|
|
108
|
+
* @url /auth/login/key
|
|
109
|
+
* @method GET
|
|
110
|
+
* @author @pubinfo/openapi
|
|
111
|
+
*/
|
|
112
|
+
export function getAuthLoginKey<
|
|
113
|
+
R = API.ResponseDataString,
|
|
114
|
+
T = API.ResponseDataString,
|
|
115
|
+
>(options?: Parameters<typeof request.Get<R, T>>[1]) {
|
|
116
|
+
return request.Get<R, T>('/auth/login/key', {
|
|
117
|
+
...(options || {}),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @description 获取图片验证码
|
|
123
|
+
* @url /auth/login/validCode
|
|
124
|
+
* @method GET
|
|
125
|
+
* @author @pubinfo/openapi
|
|
126
|
+
*/
|
|
127
|
+
export function getAuthLoginValidCode<
|
|
128
|
+
R = API.ResponseDataValidCodeVo,
|
|
129
|
+
T = API.ResponseDataValidCodeVo,
|
|
130
|
+
>(
|
|
131
|
+
params: API.getAuthLoginValidCodeParams,
|
|
132
|
+
options?: Parameters<typeof request.Get<R, T>>[1],
|
|
133
|
+
) {
|
|
134
|
+
return request.Get<R, T>('/auth/login/validCode', {
|
|
135
|
+
params: {
|
|
136
|
+
...params,
|
|
137
|
+
},
|
|
138
|
+
...(options || {}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @description 验证码-密码登录
|
|
144
|
+
* @url /auth/loginNew
|
|
145
|
+
* @method POST
|
|
146
|
+
* @author @pubinfo/openapi
|
|
147
|
+
*/
|
|
148
|
+
export function postAuthLoginNew<
|
|
149
|
+
R = API.ResponseDataLoginTokenVo,
|
|
150
|
+
T = API.ResponseDataLoginTokenVo,
|
|
151
|
+
>(
|
|
152
|
+
body: API.LoginByPwdCaptchaDto,
|
|
153
|
+
options?: Parameters<typeof request.Post<R, T>>[2],
|
|
154
|
+
) {
|
|
155
|
+
return request.Post<R, T>('/auth/loginNew', body, {
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
},
|
|
159
|
+
...(options || {}),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @description 登出
|
|
165
|
+
* @url /auth/loginOut
|
|
166
|
+
* @method POST
|
|
167
|
+
* @author @pubinfo/openapi
|
|
168
|
+
*/
|
|
169
|
+
export function postAuthLoginOut<
|
|
170
|
+
R = API.ResponseDataVoid,
|
|
171
|
+
T = API.ResponseDataVoid,
|
|
172
|
+
>(options?: Parameters<typeof request.Post<R, T>>[2]) {
|
|
173
|
+
return request.Post<R, T>(
|
|
174
|
+
'/auth/loginOut',
|
|
175
|
+
{},
|
|
176
|
+
{
|
|
177
|
+
...(options || {}),
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @description 单点免密登录接口
|
|
184
|
+
* @url /auth/ssoLogin
|
|
185
|
+
* @method POST
|
|
186
|
+
* @author @pubinfo/openapi
|
|
187
|
+
*/
|
|
188
|
+
export function postAuthSsoLogin<
|
|
189
|
+
R = API.ResponseDataLoginTokenVo,
|
|
190
|
+
T = API.ResponseDataLoginTokenVo,
|
|
191
|
+
>(body: API.SsoLoginDto, options?: Parameters<typeof request.Post<R, T>>[2]) {
|
|
192
|
+
return request.Post<R, T>('/auth/ssoLogin', body, {
|
|
193
|
+
headers: {
|
|
194
|
+
'Content-Type': 'application/json',
|
|
195
|
+
},
|
|
196
|
+
...(options || {}),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @description 刷新访问令牌
|
|
202
|
+
* @url /auth/token/refresh
|
|
203
|
+
* @method POST
|
|
204
|
+
* @author @pubinfo/openapi
|
|
205
|
+
*/
|
|
206
|
+
export function postAuthTokenRefresh<
|
|
207
|
+
R = API.ResponseDataLoginTokenVo,
|
|
208
|
+
T = API.ResponseDataLoginTokenVo,
|
|
209
|
+
>(
|
|
210
|
+
params: API.postAuthTokenRefreshParams,
|
|
211
|
+
options?: Parameters<typeof request.Post<R, T>>[2],
|
|
212
|
+
) {
|
|
213
|
+
return request.Post<R, T>(
|
|
214
|
+
'/auth/token/refresh',
|
|
215
|
+
{},
|
|
216
|
+
{
|
|
217
|
+
params: {
|
|
218
|
+
...params,
|
|
219
|
+
},
|
|
220
|
+
...(options || {}),
|
|
221
|
+
},
|
|
222
|
+
);
|
|
223
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
declare namespace API {
|
|
4
|
+
type CaptchaCheckDto = {
|
|
5
|
+
/** 类型 clickWord:文字、blockPuzzle:滑块 */
|
|
6
|
+
captchaType: string;
|
|
7
|
+
/** 加密坐标 */
|
|
8
|
+
pointJson: string;
|
|
9
|
+
/** token */
|
|
10
|
+
token: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type CaptchaGetDto = {
|
|
14
|
+
/** 类型 clickWord:文字、blockPuzzle:滑块、imageCode:图片 */
|
|
15
|
+
captchaType?: string;
|
|
16
|
+
/** 客户端UI组件id */
|
|
17
|
+
clientUid?: string;
|
|
18
|
+
/** 时间戳 1751542686180 */
|
|
19
|
+
ts?: string;
|
|
20
|
+
/** 尺寸(长x宽),例:150x50表示长为150宽为50,不填默认150x50,最大尺寸:长500,宽200 */
|
|
21
|
+
size?: string;
|
|
22
|
+
/** 验证码长度,不填默认4位 */
|
|
23
|
+
length?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type getAuthCheckCacheTokenParams = {
|
|
27
|
+
accessToken: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type getAuthLoginValidCodeParams = {
|
|
32
|
+
/** 尺寸(长x宽),例:150x50表示长为150宽为50,不填默认150x50,最大尺寸:长500,宽200 */
|
|
33
|
+
size?: string;
|
|
34
|
+
/** 验证码长度,不填默认4位 */
|
|
35
|
+
length?: number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type IResponseCode = {
|
|
39
|
+
code?: number;
|
|
40
|
+
msg?: string;
|
|
41
|
+
hint?: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type LoginByPwdCaptchaDto = {
|
|
45
|
+
/** 登录类型 */
|
|
46
|
+
loginType: string;
|
|
47
|
+
/** 登录名 */
|
|
48
|
+
loginName: string;
|
|
49
|
+
/** 密码 */
|
|
50
|
+
loginPwd: string;
|
|
51
|
+
/** imageCode:验证码hash/其他:加密后的token,AES.encode(token+"---"+pointListStr, key) */
|
|
52
|
+
codeHash: string;
|
|
53
|
+
/** 验证码 imageCode类型必填 */
|
|
54
|
+
code?: string;
|
|
55
|
+
/** 验证码类型,clickWord:文字、blockPuzzle:滑块、imageCode(默认):图片 */
|
|
56
|
+
captchaType?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
type LoginByPwdDto = {
|
|
60
|
+
/** 登录类型 */
|
|
61
|
+
loginType: string;
|
|
62
|
+
/** 登录名 */
|
|
63
|
+
loginName: string;
|
|
64
|
+
/** 密码 */
|
|
65
|
+
loginPwd: string;
|
|
66
|
+
/** 验证码hash */
|
|
67
|
+
codeHash: string;
|
|
68
|
+
/** 验证码 */
|
|
69
|
+
code: string;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type LoginTokenVo = {
|
|
73
|
+
/** 刷新令牌 */
|
|
74
|
+
refreshToken?: string;
|
|
75
|
+
/** 访问令牌 */
|
|
76
|
+
accessToken?: string;
|
|
77
|
+
loginResponse?: IResponseCode;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
type postAuthChangeLoginOrgParams = {
|
|
81
|
+
/** 新组织id */
|
|
82
|
+
orgId: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
type postAuthTokenRefreshParams = {
|
|
86
|
+
/** 刷新令牌 */
|
|
87
|
+
refreshToken: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
type ResponseDataBoolean = {
|
|
91
|
+
code?: number;
|
|
92
|
+
msg?: string;
|
|
93
|
+
hint?: string;
|
|
94
|
+
data?: boolean;
|
|
95
|
+
success?: boolean;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
type ResponseDataLoginTokenVo = {
|
|
99
|
+
code?: number;
|
|
100
|
+
msg?: string;
|
|
101
|
+
hint?: string;
|
|
102
|
+
data?: LoginTokenVo;
|
|
103
|
+
success?: boolean;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
type ResponseDataString = {
|
|
107
|
+
code?: number;
|
|
108
|
+
msg?: string;
|
|
109
|
+
hint?: string;
|
|
110
|
+
data?: string;
|
|
111
|
+
success?: boolean;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
type ResponseDataValidCodeVo = {
|
|
115
|
+
code?: number;
|
|
116
|
+
msg?: string;
|
|
117
|
+
hint?: string;
|
|
118
|
+
data?: ValidCodeVo;
|
|
119
|
+
success?: boolean;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
type ResponseDataVoid = {
|
|
123
|
+
code?: number;
|
|
124
|
+
msg?: string;
|
|
125
|
+
hint?: string;
|
|
126
|
+
data?: Record<string, any>;
|
|
127
|
+
success?: boolean;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
type SsoLoginDto = {
|
|
131
|
+
/** 登录类型 */
|
|
132
|
+
loginType: string;
|
|
133
|
+
code?: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
type ValidCodeVo = {
|
|
137
|
+
key?: string;
|
|
138
|
+
plaintext?: string;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useActiveElement } from '@vueuse/core';
|
|
3
|
+
import { computed, onMounted, ref } from 'vue';
|
|
4
|
+
import { fetchCaptcha } from './authService.ts';
|
|
5
|
+
import { getAddonAfterHeight } from './captchaUtils';
|
|
6
|
+
|
|
7
|
+
// 定义组件属性和事件
|
|
8
|
+
const props = withDefaults(
|
|
9
|
+
defineProps<{
|
|
10
|
+
size?: 'large' | 'middle' | 'small'
|
|
11
|
+
modelValue: string
|
|
12
|
+
}>(),
|
|
13
|
+
{
|
|
14
|
+
size: 'large',
|
|
15
|
+
},
|
|
16
|
+
);
|
|
17
|
+
const emit = defineEmits(['update:modelValue', 'getCaptchaHash']);
|
|
18
|
+
|
|
19
|
+
// 初始化状态
|
|
20
|
+
const captchaHash = ref<string>('');
|
|
21
|
+
const captchaImgUrl = ref<string>('');
|
|
22
|
+
|
|
23
|
+
// 计算属性
|
|
24
|
+
const addonAfterHeight = computed(() =>
|
|
25
|
+
getAddonAfterHeight(props.size),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const activeElement = useActiveElement();
|
|
29
|
+
const focusElementDataId = computed(() =>
|
|
30
|
+
activeElement.value?.dataset?.id || 'null',
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
function changeInput(e: Event) {
|
|
34
|
+
const target = e.target as HTMLInputElement;
|
|
35
|
+
emit('update:modelValue', target.value);
|
|
36
|
+
}
|
|
37
|
+
// 验证码相关方法
|
|
38
|
+
async function send() {
|
|
39
|
+
try {
|
|
40
|
+
const { imgUrl, hash } = await fetchCaptcha('100x40');
|
|
41
|
+
captchaImgUrl.value = imgUrl;
|
|
42
|
+
captchaHash.value = hash!;
|
|
43
|
+
emit('getCaptchaHash', captchaHash.value);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('获取验证码失败:', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 组件挂载时获取验证码
|
|
51
|
+
onMounted(() => {
|
|
52
|
+
send();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
defineExpose({
|
|
56
|
+
refresh: send,
|
|
57
|
+
});
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<a-input
|
|
62
|
+
:size="props.size"
|
|
63
|
+
allow-clear
|
|
64
|
+
placeholder="请输入验证码"
|
|
65
|
+
data-id="captchas"
|
|
66
|
+
@change="changeInput"
|
|
67
|
+
>
|
|
68
|
+
<template #prefix>
|
|
69
|
+
<PubinfoIcon v-if="focusElementDataId === 'captchas'" name="i-solar-shield-check-bold" color="#1578FF" />
|
|
70
|
+
<PubinfoIcon v-else name="i-solar-shield-check-broken" color="#AFB0B2" />
|
|
71
|
+
</template>
|
|
72
|
+
<template #addonAfter>
|
|
73
|
+
<div
|
|
74
|
+
:style="{ height: `${addonAfterHeight}px` }"
|
|
75
|
+
w-100px
|
|
76
|
+
cursor-pointer
|
|
77
|
+
p-2px
|
|
78
|
+
@click="send"
|
|
79
|
+
>
|
|
80
|
+
<img size-full :src="captchaImgUrl">
|
|
81
|
+
</div>
|
|
82
|
+
</template>
|
|
83
|
+
</a-input>
|
|
84
|
+
</template>
|
|
85
|
+
|
|
86
|
+
<style scoped>
|
|
87
|
+
:deep(.ant-input-group-addon) {
|
|
88
|
+
padding: 0 !important;
|
|
89
|
+
overflow: hidden;
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getAuthLoginValidCode } from '@/api/modules/auth';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 获取验证码图片
|
|
5
|
+
* @param size 验证码尺寸
|
|
6
|
+
* @returns 包含验证码图片URL和hash的对象
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchCaptcha(size: string = '100x40') {
|
|
9
|
+
const res = await getAuthLoginValidCode({ size });
|
|
10
|
+
|
|
11
|
+
if (!res.success || !res.data) {
|
|
12
|
+
throw new Error('获取验证码失败');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { key, plaintext } = res.data;
|
|
16
|
+
const imgUrl = `data:image/png;base64,${plaintext}`;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
imgUrl,
|
|
20
|
+
hash: key,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 根据尺寸计算高度
|
|
3
|
+
* @param size 尺寸大小
|
|
4
|
+
* @returns 对应的高度值
|
|
5
|
+
*/
|
|
6
|
+
export function getAddonAfterHeight(size: 'large' | 'middle' | 'small') {
|
|
7
|
+
switch (size) {
|
|
8
|
+
case 'large':
|
|
9
|
+
return 36;
|
|
10
|
+
case 'small':
|
|
11
|
+
return 20;
|
|
12
|
+
default:
|
|
13
|
+
return 28;
|
|
14
|
+
}
|
|
15
|
+
}
|