Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
查尔斯-BUG万象集
Continew Admin
提交
a5a4cd49
Continew Admin
项目概览
查尔斯-BUG万象集
/
Continew Admin
7 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
分析
仓库
DevOps
项目成员
Pages
Continew Admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
a5a4cd49
编写于
9月 28, 2023
作者:
查尔斯-BUG万象集
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: 登录页面 UI 新增邮箱登录模式
上级
3f92660e
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
237 addition
and
35 deletion
+237
-35
continew-admin-ui/src/api/auth/login.ts
continew-admin-ui/src/api/auth/login.ts
+4
-3
continew-admin-ui/src/views/login/components/email-login.vue
continew-admin-ui/src/views/login/components/email-login.vue
+156
-0
continew-admin-ui/src/views/login/components/phone-login.vue
continew-admin-ui/src/views/login/components/phone-login.vue
+10
-6
continew-admin-ui/src/views/login/index.vue
continew-admin-ui/src/views/login/index.vue
+52
-20
continew-admin-ui/src/views/login/locale/en-US.ts
continew-admin-ui/src/views/login/locale/en-US.ts
+8
-3
continew-admin-ui/src/views/login/locale/zh-CN.ts
continew-admin-ui/src/views/login/locale/zh-CN.ts
+7
-3
未找到文件。
continew-admin-ui/src/api/auth/login.ts
浏览文件 @
a5a4cd49
...
...
@@ -6,10 +6,11 @@ const BASE_URL = '/auth';
export
interface
LoginReq
{
phone
?:
string
;
username
:
string
;
password
:
string
;
email
?:
string
;
username
?:
string
;
password
?:
string
;
captcha
:
string
;
uuid
:
string
;
uuid
?
:
string
;
}
export
interface
LoginRes
{
...
...
continew-admin-ui/src/views/login/components/email-login.vue
0 → 100644
浏览文件 @
a5a4cd49
<
template
>
<a-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
layout=
"vertical"
size=
"large"
class=
"login-form"
>
<a-form-item
field=
"email"
hide-label
>
<a-input
v-model=
"form.email"
:placeholder=
"$t('login.email.placeholder.email')"
allow-clear
/>
</a-form-item>
<a-form-item
field=
"captcha"
hide-label
>
<a-input
v-model=
"form.captcha"
:placeholder=
"$t('login.email.placeholder.captcha')"
:max-length=
"6"
allow-clear
style=
"flex: 1 1"
/>
<a-button
class=
"captcha-btn"
:loading=
"captchaLoading"
:disabled=
"captchaDisable"
@
click=
"handleSendCaptcha"
>
{{
captchaBtnName
}}
</a-button>
</a-form-item>
<a-button
class=
"btn"
:loading=
"loading"
type=
"primary"
html-type=
"submit"
>
{{
$t
(
'
login.button
'
)
}}
(即将开放)
</a-button>
</a-form>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
getCurrentInstance
,
ref
,
toRefs
,
reactive
,
computed
}
from
'
vue
'
;
import
{
useI18n
}
from
'
vue-i18n
'
;
import
{
useLoginStore
}
from
'
@/store
'
;
import
{
LoginReq
}
from
'
@/api/auth/login
'
;
const
{
proxy
}
=
getCurrentInstance
()
as
any
;
const
{
t
}
=
useI18n
();
const
loginStore
=
useLoginStore
();
const
loading
=
ref
(
false
);
const
captchaLoading
=
ref
(
false
);
const
captchaDisable
=
ref
(
false
);
const
captchaTime
=
ref
(
60
);
const
captchaTimer
=
ref
();
const
captchaBtnNameKey
=
ref
(
'
login.captcha.get
'
);
const
captchaBtnName
=
computed
(()
=>
t
(
captchaBtnNameKey
.
value
));
const
data
=
reactive
({
form
:
{}
as
LoginReq
,
rules
:
{
email
:
[
{
required
:
true
,
message
:
t
(
'
login.email.error.required.email
'
)
},
],
captcha
:
[
{
required
:
true
,
message
:
t
(
'
login.email.error.required.captcha
'
)
},
],
},
});
const
{
form
,
rules
}
=
toRefs
(
data
);
/**
* 重置验证码
*/
const
resetCaptcha
=
()
=>
{
window
.
clearInterval
(
captchaTimer
.
value
);
captchaTime
.
value
=
60
;
captchaBtnNameKey
.
value
=
'
login.captcha.get
'
;
captchaDisable
.
value
=
false
;
};
/**
* 发送验证码
*/
const
handleSendCaptcha
=
()
=>
{
if
(
captchaLoading
.
value
)
return
;
proxy
.
$refs
.
formRef
.
validateField
(
'
email
'
,
(
valid
:
any
)
=>
{
if
(
!
valid
)
{
captchaLoading
.
value
=
true
;
captchaBtnNameKey
.
value
=
'
login.captcha.ing
'
;
captchaLoading
.
value
=
false
;
captchaDisable
.
value
=
true
;
captchaBtnNameKey
.
value
=
`
${
t
(
'
login.captcha.get
'
)}
(
${(
captchaTime
.
value
-=
1
)}
s)`
;
captchaTimer
.
value
=
window
.
setInterval
(()
=>
{
captchaTime
.
value
-=
1
;
captchaBtnNameKey
.
value
=
`
${
t
(
'
login.captcha.get
'
)}
(
${
captchaTime
.
value
}
s)`
;
if
(
captchaTime
.
value
<
0
)
{
window
.
clearInterval
(
captchaTimer
.
value
);
captchaTime
.
value
=
60
;
captchaBtnNameKey
.
value
=
t
(
'
login.captcha.get
'
);
captchaDisable
.
value
=
false
;
}
},
1000
);
}
});
};
</
script
>
<
style
lang=
"less"
scoped
>
.login-form {
box-sizing: border-box;
padding: 32px 5px 0;
margin-top: 16px;
.arco-input-wrapper,
:deep(.arco-select-view-single) {
background-color: var(--color-bg-white);
border: 1px solid var(--color-border-3);
height: 40px;
border-radius: 4px;
font-size: 13px;
}
.arco-input-wrapper.arco-input-error {
background-color: var(--color-danger-light-1);
border-color: var(--color-danger-light-4);
}
.captcha-btn {
height: 40px;
margin-left: 12px;
min-width: 98px;
border-radius: 4px;
}
.arco-btn-secondary:not(.arco-btn-disabled) {
background-color: #f6f8fa;
border: 1px solid #dde2e9;
color: #41464f;
}
.arco-btn-secondary:not(.arco-btn-disabled):hover {
background-color: transparent;
border: 1px solid rgb(var(--primary-6));
}
.btn {
border-radius: 4px;
box-shadow: 0 0 0 1px #05f, 0 2px 1px rgba(0, 0, 0, 0.15);
font-size: 14px;
font-weight: 500;
height: 40px;
line-height: 22px;
margin: 20px 0 12px;
width: 100%;
}
}
</
style
>
continew-admin-ui/src/views/login/components/phone-login.vue
浏览文件 @
a5a4cd49
...
...
@@ -53,13 +53,17 @@
const
captchaDisable
=
ref
(
false
);
const
captchaTime
=
ref
(
60
);
const
captchaTimer
=
ref
();
const
captchaBtnNameKey
=
ref
(
'
login.
phone.captcha
'
);
const
captchaBtnNameKey
=
ref
(
'
login.
captcha.get
'
);
const
captchaBtnName
=
computed
(()
=>
t
(
captchaBtnNameKey
.
value
));
const
data
=
reactive
({
form
:
{}
as
LoginReq
,
rules
:
{
phone
:
[
{
required
:
true
,
message
:
t
(
'
login.phone.error.required.phone
'
)
},
{
match
:
/^1
[
3-9
]\d{9}
$/
,
message
:
t
(
'
login.phone.error.match.phone
'
),
},
],
captcha
:
[
{
required
:
true
,
message
:
t
(
'
login.phone.error.required.captcha
'
)
},
...
...
@@ -74,7 +78,7 @@
const
resetCaptcha
=
()
=>
{
window
.
clearInterval
(
captchaTimer
.
value
);
captchaTime
.
value
=
60
;
captchaBtnNameKey
.
value
=
'
login.
phone.captcha
'
;
captchaBtnNameKey
.
value
=
'
login.
captcha.get
'
;
captchaDisable
.
value
=
false
;
};
...
...
@@ -86,21 +90,21 @@
proxy
.
$refs
.
formRef
.
validateField
(
'
phone
'
,
(
valid
:
any
)
=>
{
if
(
!
valid
)
{
captchaLoading
.
value
=
true
;
captchaBtnNameKey
.
value
=
'
login.
phone.
captcha.ing
'
;
captchaBtnNameKey
.
value
=
'
login.captcha.ing
'
;
captchaLoading
.
value
=
false
;
captchaDisable
.
value
=
true
;
captchaBtnNameKey
.
value
=
`
${
t
(
'
login.
phone.reCaptcha
'
'
login.
captcha.get
'
)}
(
${(
captchaTime
.
value
-=
1
)}
s)`
;
captchaTimer
.
value
=
window
.
setInterval
(()
=>
{
captchaTime
.
value
-=
1
;
captchaBtnNameKey
.
value
=
`
${
t
(
'
login.
phone.reCaptcha
'
)}
(
${
captchaBtnNameKey
.
value
=
`
${
t
(
'
login.
captcha.get
'
)}
(
${
captchaTime
.
value
}
s)`
;
if
(
captchaTime
.
value
<
0
)
{
window
.
clearInterval
(
captchaTimer
.
value
);
captchaTime
.
value
=
60
;
captchaBtnNameKey
.
value
=
t
(
'
login.
phone.reCaptcha
'
);
captchaBtnNameKey
.
value
=
t
(
'
login.
captcha.get
'
);
captchaDisable
.
value
=
false
;
}
},
1000
);
...
...
continew-admin-ui/src/views/login/index.vue
浏览文件 @
a5a4cd49
...
...
@@ -12,26 +12,34 @@
<div
class=
"left-banner"
></div>
<div
class=
"login-card"
>
<div
class=
"title"
>
{{
$t
(
'
login.welcome
'
)
}}
{{
appStore
.
getTitle
}}
</div
>
{{
$t
(
'
login.welcome
'
)
}}
{{
appStore
.
getTitle
}}
</div
>
<a-tabs
class=
"account-tab"
default-active-key=
"1"
>
<a-tab-pane
key=
"1"
:title=
"$t('login.account')"
><AccountLogin
/></a-tab-pane>
<a-tab-pane
key=
"2"
:title=
"$t('login.phone')"
><PhoneLogin
/></a-tab-pane>
<EmailLogin
v-if=
"isEmailLogin"
/>
<a-tabs
v-else
class=
"account-tab"
default-active-key=
"1"
>
<a-tab-pane
key=
"1"
:title=
"$t('login.account')"
>
<AccountLogin
/>
</a-tab-pane>
<a-tab-pane
key=
"2"
:title=
"$t('login.phone')"
>
<PhoneLogin
/>
</a-tab-pane>
</a-tabs>
<div
class=
"oauth"
>
<a-divider
class=
"text"
orientation=
"center"
>
{{
$t
(
'
login.other
'
)
}}
</a-divider>
<div
class=
"idps"
>
<a-tooltip
content=
"邮箱登录(即将开放)"
mini
>
<div
class=
"mail app"
>
<icon-email
/>
{{
$t
(
'
login.email.txt
'
)
}}
</div>
</a-tooltip>
<div
v-if=
"!isEmailLogin"
class=
"mail app"
@
click=
"toggleLoginMode"
>
<icon-email
/>
{{
$t
(
'
login.email.txt
'
)
}}
</div>
<div
v-else
class=
"account app"
@
click=
"toggleLoginMode"
>
<icon-user
/>
{{
$t
(
'
login.account.txt
'
)
}}
</div>
<a-tooltip
content=
"Gitee(即将开放)"
mini
>
<a
href=
"javascript: void(0);"
class=
"app"
>
<svg
...
...
@@ -65,7 +73,7 @@
</div>
</div>
</div>
<div
class=
"footer"
>
<div
v-if=
"appStore.device === 'desktop'"
class=
"footer"
>
<div
class=
"beian"
>
<div
class=
"below text"
v-html=
"appStore.getCopyright"
></div>
</div>
...
...
@@ -74,14 +82,23 @@
</
template
>
<
script
lang=
"ts"
setup
>
import
{
ref
}
from
'
vue
'
;
import
{
useI18n
}
from
'
vue-i18n
'
;
import
{
useAppStore
}
from
'
@/store
'
;
import
getFile
from
'
@/utils/file
'
;
import
useResponsive
from
'
@/hooks/responsive
'
;
import
AccountLogin
from
'
./components/account-login.vue
'
;
import
PhoneLogin
from
'
./components/phone-login.vue
'
;
import
EmailLogin
from
'
./components/email-login.vue
'
;
const
{
t
}
=
useI18n
();
const
appStore
=
useAppStore
();
useResponsive
(
true
);
const
isEmailLogin
=
ref
(
false
);
const
toggleLoginMode
=
()
=>
{
isEmailLogin
.
value
=
!
isEmailLogin
.
value
;
};
</
script
>
<
style
lang=
"less"
scoped
>
...
...
@@ -137,7 +154,7 @@
max-width: 500px;
object-fit: contain;
position: absolute;
top: 5%;
top:
4.
5%;
width: 100%;
}
}
...
...
@@ -225,16 +242,31 @@
.mail {
min-width: 81px;
width: 81px;
}
.account {
min-width: 147px;
width: 147px;
}
.mail,
.account {
color: #41464f;
font-size: 12px;
font-weight: 400;
line-height: 20px;
padding: 6px 10px;
svg {
color: #000;
font-size: 16px;
margin-right: 10px;
}
}
.mail svg,
.account svg {
font-size: 16px;
margin-right: 10px;
}
.mail:hover,
.account:hover {
color: rgb(var(--primary-6));
}
.mail svg:hover,
.account svg:hover {
color: rgb(var(--primary-6));
}
}
}
...
...
continew-admin-ui/src/views/login/locale/en-US.ts
浏览文件 @
a5a4cd49
...
...
@@ -10,15 +10,20 @@ export default {
'
login.account.placeholder.captcha
'
:
'
Please enter captcha
'
,
'
login.phone.placeholder.phone
'
:
'
Please enter phone
'
,
'
login.phone.placeholder.captcha
'
:
'
Please enter captcha
'
,
'
login.phone.captcha
'
:
'
Get captcha
'
,
'
login.phone.captcha.ing
'
:
'
Sending...
'
,
'
login.phone.reCaptcha
'
:
'
Resend captcha
'
,
'
login.email.placeholder.email
'
:
'
Please enter email
'
,
'
login.email.placeholder.captcha
'
:
'
Please enter captcha
'
,
'
login.captcha.get
'
:
'
Get captcha
'
,
'
login.captcha.ing
'
:
'
Sending...
'
,
'
login.account.error.required.username
'
:
'
Please enter username
'
,
'
login.account.error.required.password
'
:
'
Please enter password
'
,
'
login.account.error.required.captcha
'
:
'
Please enter captcha
'
,
'
login.phone.error.required.phone
'
:
'
Please enter phone
'
,
'
login.phone.error.match.phone
'
:
'
Please enter the correct mobile phone number
'
,
'
login.phone.error.required.captcha
'
:
'
Please enter captcha
'
,
'
login.email.error.required.email
'
:
'
Please enter email
'
,
'
login.email.error.required.captcha
'
:
'
Please enter captcha
'
,
'
login.captcha
'
:
'
Captcha
'
,
'
login.rememberMe
'
:
'
Remember me
'
,
...
...
continew-admin-ui/src/views/login/locale/zh-CN.ts
浏览文件 @
a5a4cd49
...
...
@@ -10,15 +10,19 @@ export default {
'
login.account.placeholder.captcha
'
:
'
请输入验证码
'
,
'
login.phone.placeholder.phone
'
:
'
请输入手机号
'
,
'
login.phone.placeholder.captcha
'
:
'
请输入验证码
'
,
'
login.phone.captcha
'
:
'
获取验证码
'
,
'
login.phone.captcha.ing
'
:
'
发送中...
'
,
'
login.phone.reCaptcha
'
:
'
重新发送
'
,
'
login.email.placeholder.email
'
:
'
请输入邮箱
'
,
'
login.email.placeholder.captcha
'
:
'
请输入验证码
'
,
'
login.captcha.get
'
:
'
获取验证码
'
,
'
login.captcha.ing
'
:
'
发送中...
'
,
'
login.account.error.required.username
'
:
'
请输入用户名
'
,
'
login.account.error.required.password
'
:
'
请输入密码
'
,
'
login.account.error.required.captcha
'
:
'
请输入验证码
'
,
'
login.phone.error.required.phone
'
:
'
请输入手机号
'
,
'
login.phone.error.match.phone
'
:
'
请输入正确的手机号
'
,
'
login.phone.error.required.captcha
'
:
'
请输入验证码
'
,
'
login.email.error.required.email
'
:
'
请输入邮箱
'
,
'
login.email.error.required.captcha
'
:
'
请输入验证码
'
,
'
login.captcha
'
:
'
验证码
'
,
'
login.rememberMe
'
:
'
记住我
'
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录