Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
有来技术
vue3-element-admin
提交
9a297d19
V
vue3-element-admin
项目概览
有来技术
/
vue3-element-admin
通知
2
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue3-element-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
9a297d19
编写于
3月 24, 2023
作者:
H
haoxr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 新增登录验证码
上级
40c40fa9
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
114 addition
and
54 deletion
+114
-54
src/api/auth/index.ts
src/api/auth/index.ts
+13
-1
src/api/auth/types.ts
src/api/auth/types.ts
+27
-2
src/assets/icons/verify_code.svg
src/assets/icons/verify_code.svg
+9
-0
src/lang/en.ts
src/lang/en.ts
+1
-4
src/lang/zh-cn.ts
src/lang/zh-cn.ts
+1
-4
src/views/login/index.vue
src/views/login/index.vue
+63
-43
未找到文件。
src/api/auth/index.ts
浏览文件 @
9a297d19
import
request
from
'
@/utils/request
'
;
import
{
AxiosPromise
}
from
'
axios
'
;
import
{
LoginData
,
LoginResult
}
from
'
./types
'
;
import
{
CaptchaResult
,
LoginData
,
LoginResult
}
from
'
./types
'
;
/**
* 登录API
...
...
@@ -25,3 +25,15 @@ export function logoutApi() {
method
:
'
delete
'
});
}
/**
* 获取验证码
*/
export
function
getCaptchaApi
():
AxiosPromise
<
CaptchaResult
>
{
return
request
({
url
:
'
/api/v1/auth/captcha
'
,
method
:
'
get
'
});
}
src/api/auth/types.ts
浏览文件 @
9a297d19
...
...
@@ -5,11 +5,21 @@ export interface LoginData {
/**
* 用户名
*/
username
:
string
;
username
?
:
string
;
/**
* 密码
*/
password
:
string
;
password
?:
string
;
/**
* 验证码缓存key
*/
verifyCodeKey
?:
string
;
/**
* 验证码
*/
verifyCode
?:
string
;
}
/**
...
...
@@ -33,3 +43,18 @@ export interface LoginResult {
*/
tokenType
?:
string
;
}
/**
* 验证码响应
*/
export
interface
CaptchaResult
{
/**
* 验证码缓存key
*/
verifyCodeKey
:
string
;
/**
* 验证码图片Base64字符串
*/
verifyCodeBase64
:
string
;
}
src/assets/icons/verify_code.svg
0 → 100644
浏览文件 @
9a297d19
<svg
t=
"1655050462467"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"2131"
width=
"200"
height=
"200"
>
<path
d=
"M917.6 267.2c-36.1-2.5-72.4-9.3-103.6-19.3-10.1-3-20.2-6.4-30.3-10-21.4-6.3-50.5-18.8-83.6-36.6-0.4-0.2-0.7-0.4-1.1-0.6-7.8-4.2-15.7-8.7-23.8-13.4-10.9-6.3-21.7-12.9-32.5-19.9-0.4-0.3-0.8-0.5-1.2-0.8-7.7-5-15.5-10.2-23.1-15.5-5-3.4-10-7.1-15-10.7-3.8-2.8-7.5-5.3-11.3-8.2-27.4-20.5-54.5-43.5-79.9-68.3-25.4 24.8-52.5 47.8-79.9 68.3-3.7 2.8-7.5 5.4-11.3 8.2-5 3.6-10 7.3-15 10.7-7.7 5.4-15.4 10.5-23.1 15.5-0.4 0.3-0.8 0.5-1.2 0.8-10.8 6.9-21.6 13.6-32.5 19.9-8.1 4.7-16 9.2-23.8 13.4-0.3 0.2-0.7 0.4-1 0.6-33 17.8-62.2 30.3-83.6 36.6-10.1 3.6-20.2 7-30.3 10-31.1 10-67.4 16.8-103.6 19.3h0.1c1.1 16.2 2.1 37.7 3.4 60.9h0.7c6.1 86.8 23.5 210.2 49.7 282.8 1.2 3.2 2.2 6.5 3.3 9.6 0.6 1.5 1.2 2.8 1.8 4.3 62.8 162.1 171.9 280.1 303 323.4v0.4c17.3 5.7 31.9 9.3 43.5 11.5 11.5-2.2 26.1-5.8 43.5-11.5v-0.4C687 905 796.1 787 858.9 624.8c0.6-1.5 1.2-2.8 1.8-4.3 1.2-3.1 2.2-6.4 3.3-9.6 26.2-72.5 43.6-196 49.7-282.8h0.7c1.1-23.3 2.2-44.7 3.2-60.9z m-47.4 41.9l-0.5 9.5c-0.5 2.2-0.9 4.4-1 6.6C863 406 847 525.7 821.3 596.7c-0.7 1.9-1.4 3.9-2 5.8-0.4 1.2-0.8 2.5-1.4 4.1-0.5 1.2-1 2.5-1.4 3.4C758.1 760.8 657.7 869.3 541 907.8c-1.9 0.6-3.7 1.4-5.5 2.2-7.9 2.5-15.7 4.6-23.2 6.3-7.5-1.7-15.2-3.8-23.1-6.3-1.8-0.9-3.6-1.6-5.5-2.2-116.7-38.5-217.1-147-275.4-297.5-0.5-1.2-0.9-2.4-1.7-4.1-0.4-1.2-0.8-2.4-1.3-3.6-0.7-2-1.3-3.9-1.9-5.6-25.8-71.2-41.7-191-47.4-271.7-0.2-2.3-0.5-4.5-1-6.6l-0.5-9.3c-0.1-1.5-0.2-3-0.2-4.5 24.6-3.8 48.4-9.3 70-16.2 10.1-3 20.4-6.4 31.4-10.4 25.2-7.6 56.5-21.2 90.5-39.6 0.6-0.3 1.2-0.6 1.7-0.9 8.2-4.4 16.7-9.2 24.8-14 10.7-6.1 22-13 34.5-21.1 0.4-0.2 1-0.6 1.3-0.8 8.2-5.3 16.4-10.8 24.1-16.2 4.5-3.1 9.1-6.4 13.7-9.7l2.4-1.8 4-2.9c2.6-1.9 5.2-3.7 7.5-5.5 17.9-13.4 35.3-27.5 52-42.1 16.7 14.7 34 28.7 51.8 42 2.6 1.9 5.1 3.8 7.7 5.6l4.3 3.1 1.5 1.1c4.8 3.5 9.6 6.9 14 9.9 8.1 5.7 16.3 11.2 23.7 16l2.1 1.3c12.4 8 23.7 14.9 34.1 20.8 8.6 5 17 9.8 25 14.1 0.4 0.2 1 0.5 1.5 0.8 34.2 18.4 65.6 32.1 90.9 39.7 11 3.9 21.3 7.3 30.6 10.1 22.1 7.1 46.1 12.6 70.8 16.5 0.1 1.5 0.1 3 0 4.4z"
p-id=
"2132"
></path>
<path
d=
"M710.6 411.2L476.1 651.6l-120-123c-8.3-8.5-21.8-8.5-30.1 0s-8.3 22.3 0 30.9L461.1 698c4.2 4.3 9.6 6.4 15.1 6.4 5.4 0 10.9-2.1 15-6.4l249.5-255.7c8.3-8.5 8.3-22.3 0-30.9-8.3-8.7-21.8-8.7-30.1-0.2z"
p-id=
"2133"
></path>
</svg>
src/lang/en.ts
浏览文件 @
9a297d19
...
...
@@ -10,10 +10,7 @@ export default {
username
:
'
Username
'
,
password
:
'
Password
'
,
login
:
'
Login
'
,
code
:
'
Verification Code
'
,
copyright
:
''
,
icp
:
''
,
thirdPartyLogin
:
'
third-party login
'
verifyCode
:
'
Verify Code
'
,
},
// 导航栏国际化
navbar
:
{
...
...
src/lang/zh-cn.ts
浏览文件 @
9a297d19
...
...
@@ -10,10 +10,7 @@ export default {
username
:
'
用户名
'
,
password
:
'
密码
'
,
login
:
'
登 录
'
,
code
:
'
请输入验证码
'
,
copyright
:
''
,
icp
:
''
,
thirdPartyLogin
:
'
第三方登录
'
verifyCode
:
'
验证码
'
},
navbar
:
{
dashboard
:
'
首页
'
,
...
...
src/views/login/index.vue
浏览文件 @
9a297d19
<
template
>
<div
class=
"login-container"
>
<el-form
ref=
"loginFormRef"
:model=
"loginData"
:rules=
"loginRules"
class=
"login-form"
>
<el-form
ref=
"loginFormRef"
:model=
"loginData"
:rules=
"loginRules"
class=
"login-form"
>
<div
class=
"flex text-white items-center py-4"
>
<span
class=
"text-2xl flex-1 text-center"
>
{{
$t
(
'
login.title
'
)
}}
</span>
<lang-select
style=
"color: #fff"
/>
...
...
@@ -15,51 +10,40 @@
<div
class=
"p-2 text-white"
>
<svg-icon
icon-class=
"user"
/>
</div>
<el-input
class=
"flex-1"
ref=
"username"
size=
"large"
v-model=
"loginData.username"
:placeholder=
"$t('login.username')"
name=
"username"
/>
<el-input
class=
"flex-1"
ref=
"username"
size=
"large"
v-model=
"loginData.username"
:placeholder=
"$t('login.username')"
name=
"username"
/>
</el-form-item>
<el-tooltip
:disabled=
"isCapslock === false"
content=
"Caps lock is On"
placement=
"right"
>
<el-tooltip
:disabled=
"isCapslock === false"
content=
"Caps lock is On"
placement=
"right"
>
<el-form-item
prop=
"password"
>
<span
class=
"p-2 text-white"
>
<svg-icon
icon-class=
"password"
/>
</span>
<el-input
class=
"flex-1"
v-model=
"loginData.password"
placeholder=
"密码"
:type=
"passwordVisible === false ? 'password' : 'input'"
size=
"large"
name=
"password"
@
keyup=
"checkCapslock"
@
keyup.enter=
"handleLogin"
/>
<el-input
class=
"flex-1"
v-model=
"loginData.password"
placeholder=
"密码"
:type=
"passwordVisible === false ? 'password' : 'input'"
size=
"large"
name=
"password"
@
keyup=
"checkCapslock"
@
keyup.enter=
"handleLogin"
/>
<span
class=
"mr-2"
@
click=
"passwordVisible = !passwordVisible"
>
<svg-icon
:icon-class=
"passwordVisible === false ? 'eye' : 'eye-open'"
class=
"text-white cursor-pointer"
/>
<svg-icon
:icon-class=
"passwordVisible === false ? 'eye' : 'eye-open'"
class=
"text-white cursor-pointer"
/>
</span>
</el-form-item>
</el-tooltip>
<el-button
size=
"default"
:loading=
"loading"
type=
"primary"
class=
"w-full"
@
click.prevent=
"handleLogin"
>
{{
$t
(
'
login.login
'
)
}}
<!-- 验证码 -->
<el-form-item
prop=
"verifyCode"
>
<span
class=
"p-2 text-white"
>
<svg-icon
icon-class=
"verify_code"
/>
</span>
<el-input
v-model=
"loginData.verifyCode"
auto-complete=
"off"
:placeholder=
"$t('login.verifyCode')"
class=
"w-[60%]"
@
keyup.enter=
"handleLogin"
/>
<div
class=
"captcha"
>
<img
:src=
"captchaBase64"
@
click=
"getCaptcha"
/>
</div>
</el-form-item>
<el-button
size=
"default"
:loading=
"loading"
type=
"primary"
class=
"w-full"
@
click.prevent=
"handleLogin"
>
{{
$t
(
'
login.login
'
)
}}
</el-button>
<!-- 账号密码提示 -->
...
...
@@ -81,6 +65,7 @@ import { useUserStore } from '@/store/modules/user';
// API依赖
import
{
LocationQuery
,
LocationQueryValue
,
useRoute
}
from
'
vue-router
'
;
import
{
getCaptchaApi
}
from
'
@/api/auth
'
;
import
{
LoginData
}
from
'
@/api/auth/types
'
;
const
userStore
=
useUserStore
();
...
...
@@ -90,15 +75,17 @@ const loginFormRef = ref(ElForm);
const
loginData
=
ref
<
LoginData
>
({
username
:
'
admin
'
,
password
:
'
123456
'
password
:
'
123456
'
,
});
const
loginRules
=
{
username
:
[{
required
:
true
,
trigger
:
'
blur
'
}],
password
:
[{
required
:
true
,
trigger
:
'
blur
'
,
validator
:
validatePassword
}]
password
:
[{
required
:
true
,
trigger
:
'
blur
'
,
validator
:
validatePassword
}],
// verifyCode: [{ required: true, trigger: 'blur' }],
};
const
passwordVisible
=
ref
(
false
);
const
captchaBase64
=
ref
()
const
loading
=
ref
(
false
);
...
...
@@ -119,7 +106,18 @@ function checkCapslock(e: any) {
}
/**
* 登录
* 验证码
*/
function
getCaptcha
()
{
getCaptchaApi
().
then
(({
data
})
=>
{
const
{
verifyCodeBase64
,
verifyCodeKey
}
=
data
;
loginData
.
value
.
verifyCodeKey
=
verifyCodeKey
;
captchaBase64
.
value
=
verifyCodeBase64
;
});
}
/**
* 登录
*/
function
handleLogin
()
{
loginFormRef
.
value
.
validate
((
valid
:
boolean
)
=>
{
...
...
@@ -150,9 +148,26 @@ function handleLogin() {
}
});
}
onMounted
(()
=>
{
getCaptcha
();
});
</
script
>
<
style
lang=
"scss"
scoped
>
.captcha
{
position
:
absolute
;
right
:
0
;
top
:
0
;
img
{
height
:
48px
;
width
:
120px
;
cursor
:
pointer
;
}
}
.login-container
{
min-height
:
100%
;
width
:
100%
;
...
...
@@ -167,6 +182,7 @@ function handleLogin() {
overflow
:
hidden
;
}
}
.el-form-item
{
border
:
1px
solid
rgba
(
255
,
255
,
255
,
0
.1
);
background
:
rgba
(
0
,
0
,
0
,
0
.1
);
...
...
@@ -175,17 +191,20 @@ function handleLogin() {
.el-input
{
background
:
transparent
;
// 子组件 scoped 无效,使用 :deep
:deep
(
.el-input__wrapper
)
{
padding
:
0
;
background
:
transparent
;
box-shadow
:
none
;
.el-input__inner
{
background
:
transparent
;
border
:
0px
;
border-radius
:
0px
;
color
:
#fff
;
caret-color
:
#fff
;
&
:-webkit-autofill
{
box-shadow
:
0
0
0
1000px
transparent
inset
!
important
;
-webkit-text-fill-color
:
#fff
!
important
;
...
...
@@ -202,5 +221,6 @@ function handleLogin() {
}
}
}
}
</
style
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录