Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
boyueCEnd
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
游洁
boyueCEnd
Commits
d4462fc9
Commit
d4462fc9
authored
Nov 20, 2025
by
youjie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
no message
parent
73fdf525
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
125 additions
and
1259 deletions
+125
-1259
zh-CN.ts
src/i18n/locales/zh-CN.ts
+1
-1
Login.vue
src/views/auth/Login.vue
+124
-81
bindingForm.vue
src/views/auth/components/bindingForm.vue
+0
-304
loginForm.vue
src/views/auth/components/loginForm.vue
+0
-336
registerForm.vue
src/views/auth/components/registerForm.vue
+0
-537
No files found.
src/i18n/locales/zh-CN.ts
View file @
d4462fc9
...
@@ -58,7 +58,7 @@ export default {
...
@@ -58,7 +58,7 @@ export default {
bindingRecommendCodeRequired
:
'请输入推荐码'
,
bindingRecommendCodeRequired
:
'请输入推荐码'
,
backStep
:
'上一步'
,
backStep
:
'上一步'
,
registerSuccess
:
'注册成功'
,
registerSuccess
:
'注册成功'
,
registerSuccessText
:
'
一起奔赴阳光、沙滩与烟火气吧~
'
,
registerSuccessText
:
'
恭喜注册成功!
'
,
agreementText
:
'「我同意使用条款与隐私政策」'
,
agreementText
:
'「我同意使用条款与隐私政策」'
,
forgetPassword
:
'忘记密码'
,
forgetPassword
:
'忘记密码'
,
newPassword
:
'新密码'
,
newPassword
:
'新密码'
,
...
...
src/views/auth/Login.vue
View file @
d4462fc9
...
@@ -68,6 +68,46 @@
...
@@ -68,6 +68,46 @@
</a-form>
</a-form>
</a-space>
</a-space>
<!-- 谷歌登录 -->
<!-- <div v-else-if="loginMsg.reType === 1" class="login-form-content google-content">
<div class="google-auth-container">
<div
id="g_id_onload"
data-client_id="13534363185-3utcasahjr950mf6uumq8upefl0fu2rl.apps.googleusercontent.com"
data-context="signin"
data-ux_mode="popup"
data-callback="googleCallback"
data-auto_select="false"
data-itp_support="true"
></div>
<div
class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-locale="en-US"
data-logo_alignment="center"
data-width="360"
></div>
</div>
</div> -->
<!-- Line登录 -->
<!-- <div v-else-if="loginMsg.reType === 3" class="login-form-content scan-content">
<div class="qr-container">
<div class="qr-box line-qr-box">
<div class="qr-code-placeholder">
<i class="ki-outline ki-message-text"></i>
</div>
</div>
<p class="scan-instruction">{{ t('login.scanTip') }}</p>
<p class="scan-status">{{ t('login.scanWaiting') }}</p>
</div>
</div> -->
<div
class=
"mt-[40px] flex items-center justify-center"
>
<div
class=
"mt-[40px] flex items-center justify-center"
>
<a-divider
orientation=
"center"
class=
"text-[16px] text-[#EEEFEB]"
></a-divider>
<a-divider
orientation=
"center"
class=
"text-[16px] text-[#EEEFEB]"
></a-divider>
<span
class=
"text-nowrap primary1-3 px-[14px]"
>
{{ t('login.othenLogin') }}
</span>
<span
class=
"text-nowrap primary1-3 px-[14px]"
>
{{ t('login.othenLogin') }}
</span>
...
@@ -78,9 +118,9 @@
...
@@ -78,9 +118,9 @@
<div
class=
"w-[42px] h-[42px]
<div
class=
"w-[42px] h-[42px]
rounded-full bg-[#FFF]
rounded-full bg-[#FFF]
flex items-center justify-center cursor-pointer loginForm-item"
flex items-center justify-center cursor-pointer loginForm-item"
v-for=
"(item,index) in loginType
s"
:key=
"index"
v-for=
"(method,index) in loginMethod
s"
:key=
"index"
@
click=
"toggleLoginType(item.value
)"
>
@
click=
"toggleLoginType(method.key
)"
>
<img
:src=
"item
.url"
alt=
""
class=
"w-[14px] h-[14px]"
/>
<img
:src=
"method
.url"
alt=
""
class=
"w-[14px] h-[14px]"
/>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -104,7 +144,6 @@ import { useSystemConfigStore } from '@/stores/index'
...
@@ -104,7 +144,6 @@ import { useSystemConfigStore } from '@/stores/index'
import
ErpUserService
from
'@/services/ErpUserService'
import
ErpUserService
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
loginHeader
from
"./components/header.vue"
;
import
loginHeader
from
"./components/header.vue"
;
import
loginForm
from
"./components/loginForm.vue"
;
import
f
from
'@/assets/images/login_f.png'
import
f
from
'@/assets/images/login_f.png'
import
G
from
'@/assets/images/login_G.png'
import
G
from
'@/assets/images/login_G.png'
import
tel
from
'@/assets/images/login_tel.png'
import
tel
from
'@/assets/images/login_tel.png'
...
@@ -132,25 +171,29 @@ const loginMsg = reactive({
...
@@ -132,25 +171,29 @@ const loginMsg = reactive({
password
:
''
,
//123456
password
:
''
,
//123456
})
})
const
loginTypes
=
ref
([
const
loginMethods
=
ref
([
// { key: 'account', label: 'login.accountLogin', icon: 'ki-user' },
// { key: 'wechat', label: 'login.wechatLogin', icon: 'ki-whatsapp' },
// { key: 'google', label: 'login.googleLogin', icon: 'ki-google' },
// { key: 'line', label: 'login.lineLogin', icon: 'ki-message-text' },
{
{
label
:
'f'
,
label
:
'f'
,
value
:
7
,
key
:
7
,
url
:
f
,
url
:
f
,
},
},
{
{
label
:
'G'
,
label
:
'G'
,
value
:
1
,
key
:
1
,
url
:
G
,
url
:
G
,
},
},
{
{
label
:
'tel'
,
label
:
'tel'
,
value
:
0
,
key
:
0
,
url
:
tel
,
url
:
tel
,
},
},
{
{
label
:
'inline'
,
label
:
'inline'
,
value
:
3
,
key
:
3
,
url
:
line
,
url
:
line
,
},
},
])
])
...
...
src/views/auth/components/bindingForm.vue
deleted
100644 → 0
View file @
73fdf525
<
template
>
<div
class=
"w-full flex flex-col loginForm"
>
<div
class=
"flex justify-center"
>
<div
class=
"w-[463px] h-[635px] "
>
<!--
<div
class=
"loginForm-bg w-full h-[620px] rounded-[18px] absolute top-0 left-0 bottom-0 z-[2]"
></div>
-->
<!-- absolute top-0 left-0 bottom-0 -->
<div
class=
"loginForm-bg w-full h-full rounded-[18px] flex flex-col"
>
<a-space
direction=
"vertical"
class=
"px-[72px]"
>
<a-form
:model=
"loginMsg"
:rules=
"rules"
@
submit=
"loginHandler"
layout=
"vertical"
class=
"mt-[42px]"
>
<a-form-item
field=
""
:label=
"t('login.bindingName')"
>
<a-input
class=
"loginMsg-input"
v-model=
"loginMsg.account"
:placeholder=
"t('login.bindingNameRequired')"
:maxLength=
"16"
size=
"large"
>
<!--
<template
#
prefix
>
<icon-user
size=
"16"
strokeLinejoin=
"miter"
/>
</
template
>
-->
</a-input>
</a-form-item>
<a-form-item
field=
""
:label=
"t('login.bindingPhone')"
class=
""
>
<a-input
class=
"loginMsg-input"
v-model=
"loginMsg.account"
:placeholder=
"t('login.bindingPhoneRequired')"
:maxLength=
"16"
size=
"large"
>
<
template
#
prefix
>
<a-dropdown
position=
"br"
trigger
.
stop=
"click"
>
<div
class=
"flex items-center"
>
<span
class=
"text-[16px] font-bold mr-[22px]"
>
+86
</span>
<icon-down
size=
"16"
strokeLinejoin=
"miter"
/>
</div>
<template
#
content
>
<a-doption
v-for=
"option in AreaCodeList"
:key=
"option.value"
@
click
.
stop=
"handleAreaCodeChange(option.value)"
:class=
"
{ 'bg-blue-50': currentAreaCode === option.value }"
>
<div
class=
"flex items-center space-x-3 px-2 py-1"
>
<!--
<span
class=
"text-lg"
>
{{
option
.
flag
}}
</span>
-->
<span
class=
"font-medium"
>
{{
option
.
label
}}
</span>
</div>
</a-doption>
</
template
>
</a-dropdown>
</template>
</a-input>
</a-form-item>
<a-form-item
field=
""
:label=
"t('login.bindingWechat')"
class=
""
>
<a-input
class=
"loginMsg-input"
v-model=
"loginMsg.password"
size=
"large"
:placeholder=
"t('login.bindingWechatRequired')"
:defaultVisibility=
"false"
:maxLength=
"50"
:invisible-button=
"false"
>
<!-- <template #prefix>
<icon-key size="16" strokeLinejoin="miter" />
</template> -->
</a-input>
</a-form-item>
<a-form-item
field=
""
:label=
"t('login.bindingRecommendCode')"
class=
""
>
<a-input
class=
"loginMsg-input"
v-model=
"loginMsg.password"
size=
"large"
:placeholder=
"t('login.bindingRecommendCodeRequired')"
:defaultVisibility=
"false"
:maxLength=
"50"
:invisible-button=
"false"
>
<!-- <template #prefix>
<icon-key size="16" strokeLinejoin="miter" />
</template> -->
</a-input>
</a-form-item>
<div
class=
"flex items-center justify-center mb-[15px] cursor-pointer"
@
click=
"search.msg.privacy = !search.msg.privacy"
>
<div
class=
"mr-[12px]"
>
<div
v-if=
"!search.msg.privacy"
class=
"w-[17px] h-[17px] rounded-[6px] bg-[#008AFF] border-[1px] border-[#C0CEB3] bg-white"
></div>
<img
v-else
src=
"@/assets/images/login-agr.png"
alt=
""
class=
"w-[17px] h-[17px]"
>
</div>
<span
class=
"text-[#008AFF] text-sm"
>
{{ t('login.agreementText') }}
</span>
</div>
<div
class=
"mt-[10px] flex flex-row items-center"
>
<a-button
type=
"primary"
size=
"large"
:loading=
"loading"
html-type=
"submit"
class=
"microsoft-font flex-1 font-medium !h-[46px] !rounded-[13px] !text-[16px]"
@
click=
"loginHandler"
>
{{ t('login.register') }}
</a-button>
</div>
<div
class=
"flex flex-row items-center"
>
<a-button
type=
"text"
size=
"large"
html-type=
"submit"
class=
"microsoft-font flex-1 font-medium !h-[46px] !rounded-[13px] !text-[#0C150D] !text-[16px]"
@
click=
"backStep"
>
{{ t('login.backStep') }}
</a-button>
</div>
</a-form>
</a-space>
</div>
</div>
</div>
<div
class=
"flex justify-center text-white pb-[117px] text-[16px]"
>
<div
class=
"px-[17px] py-[30px] cursor-pointer"
@
click=
"handleClick('/login')"
>
{{ t('login.backToHome') }}
</div>
</div>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
type
Ref
,
computed
,
inject
}
from
'vue'
import
{
useUserStore
}
from
'@/stores/index'
import
UserServices
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
{
onMounted
}
from
'vue'
import
VueHcaptcha
from
'@hcaptcha/vue3-hcaptcha'
import
{
useRouter
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
f
from
'@/assets/images/login_f.png'
import
G
from
'@/assets/images/login_G.png'
import
tel
from
'@/assets/images/login_tel.png'
import
line
from
'@/assets/images/login_line.png'
const
{
t
}
=
useI18n
();
const
userStore
=
useUserStore
()
const
loading
=
ref
(
false
)
const
currentTenantId
=
ref
(
0
)
const
needVerify
=
ref
(
false
)
const
validateToken
=
ref
(
''
)
const
router
=
useRouter
()
const
invisibleHcaptcha
=
ref
()
const
loginMsg
=
reactive
({
account
:
'17308037817'
,
password
:
'123456'
,
tenantId
:
null
as
string
|
null
,
read
:
true
,
})
const
search
=
inject
(
'search'
)
as
any
;
// console.log(search.msg,'---------')
const
AreaCodeList
=
ref
([
{
value
:
'+86'
,
label
:
'中国'
,
},
{
value
:
'+1'
,
label
:
'美国'
,
},
])
// 验证规则调整
const
rules
=
computed
(()
=>
({
account
:
[
{
required
:
true
,
message
:
t
(
'login.accountRequired'
),
},
],
password
:
[
{
required
:
true
,
message
:
t
(
'login.passwordRequired'
),
},
],
}))
const
currentAreaCode
=
ref
(
'+86'
)
const
verifyHandler
=
(
token
:
string
,
ekey
:
string
)
=>
{
validateToken
.
value
=
token
}
const
verifyCheckHandler
=
async
()
=>
{
const
response
=
await
UserServices
.
NeedVerifyStatusAsync
()
if
(
response
.
data
.
resultCode
==
ApiResult
.
SUCCESS
)
{
needVerify
.
value
=
response
.
data
.
data
==
1
}
else
needVerify
.
value
=
true
}
const
handleAreaCodeChange
=
(
value
:
string
)
=>
{
loginMsg
.
account
=
value
+
loginMsg
.
account
.
slice
(
2
)
}
const
handleClick
=
(
path
:
string
)
=>
{
router
.
push
(
path
)
}
const
backStep
=
()
=>
{
search
.
loginType
=
2
}
const
loginHandler
=
async
({
values
,
errors
}:
any
)
=>
{
if
(
errors
||
loading
.
value
)
return
loading
.
value
=
true
const
result
=
await
userStore
.
setUserPasswordLoginAsync
(
loginMsg
.
account
,
loginMsg
.
password
,
validateToken
.
value
,
loginMsg
.
tenantId
?.
toString
()
||
''
,
)
loading
.
value
=
false
currentTenantId
.
value
=
0
if
(
result
.
status
==
'SUCCESS'
)
{
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
})
}
else
{
if
(
!
needVerify
.
value
)
needVerify
.
value
=
result
.
verify
if
(
invisibleHcaptcha
.
value
&&
needVerify
.
value
)
invisibleHcaptcha
.
value
.
reset
()
}
}
const
initGoogleLogin
=
()
=>
{
const
cb
=
(
data
:
any
)
=>
{
loading
.
value
=
true
;
//that.onGoogleCredential(data.credential);
userStore
.
setUserGoogleLoginAsync
(
data
.
credential
)
};
window
.
googleCallback
=
cb
;
const
s
=
document
.
createElement
(
'script'
);
s
.
src
=
'https://accounts.google.com/gsi/client'
;
document
.
body
.
appendChild
(
s
);
}
onMounted
(
async
()
=>
{
//await verifyCheckHandler()
//initGoogleLogin()
})
</
script
>
<
style
scoped
lang=
"scss"
>
:deep
(
.arco-form-item-content
)
{
min-height
:
46px
;
border-radius
:
12px
;
}
:deep
(
.arco-input-wrapper
)
{
height
:
46px
;
border-radius
:
12px
!
important
;
background-color
:
#EEEFEB
;
}
:deep
(
.arco-input-focus
)
{
border-radius
:
12px
;
box-shadow
:
rgba
(
60
,
85
,
62
,
0
.18
)
0px
5px
15px
;
border
:
2px
solid
var
(
--
primary-2
);
background-color
:
#FFFFFF
;
}
:deep
(
.arco-form-item-label
)
{
font-size
:
16px
;
padding-left
:
17px
;
}
:deep
(
.arco-input-wrapper
.arco-input.arco-input-size-large
)
{
font-size
:
16px
;
}
:deep
(
.arco-btn-primary
)
{
box-shadow
:
rgba
(
74
,
102
,
77
,
0
.15
)
0px
5px
15px
;
}
:deep
(
.arco-divider-text
)
{
/*background: #fff;*/
font-size
:
16px
;
color
:
#C2C3C0
;
font-weight
:
400
;
}
:deep
(
.arco-divider-horizontal
)
{
width
:
93px
;
min-width
:
93px
;
border-bottom
:
1px
solid
#EEF0E8
;
}
:deep
(
.arco-input
)
{
text-indent
:
4px
;
}
:deep
(
.arco-btn-primary
)
{
background-color
:
var
(
--
primary1-7
);
}
:deep
(
.arco-btn-primary
:hover
)
{
background-color
:
var
(
--
primary1-5
);
}
:deep
(
.arco-btn-text
:hover
)
{
background-color
:
rgba
(
0
,
0
,
0
,
0
.0
);
}
:deep
(
.arco-divider-vertical
)
{
border-left
:
1px
solid
var
(
--
primary1-4
);
}
.loginForm-bg
{
background
:
url('../../../assets/images/login_formbg.png')
no-repeat
white
;
background-size
:
100%
100%
;
}
.loginForm-item
{
border
:
1px
solid
var
(
--
primary1-4
);
}
.loginForm-itemActive
{
border
:
2px
solid
var
(
--
primary1-1
);
}
</
style
>
src/views/auth/components/loginForm.vue
deleted
100644 → 0
View file @
73fdf525
<
template
>
<div
class=
"w-full flex flex-col loginForm pt-[97px]"
>
<div
class=
"flex justify-center"
>
<div
class=
"w-[463px] h-[620px] "
>
<!--
<div
class=
"loginForm-bg w-full h-[620px] rounded-[18px] absolute top-0 left-0 bottom-0 z-[2]"
></div>
-->
<!-- absolute top-0 left-0 bottom-0 -->
<div
class=
"loginForm-bg w-full h-full rounded-[18px] flex flex-col"
>
<div
class=
"text-center pt-[46px] primary-6"
>
<div
class=
"text-[32px] font-bold"
>
{{
t
(
'login.loginTo'
)
}}
</div>
<!--
<div
class=
"text-[17px] mt-[18px]"
>
{{
t
(
'login.loginToSubImm'
)
}}
</div>
-->
<div
class=
"flex justify-center items-center mt-[18px]"
>
<img
src=
"@/assets/images/welcome-login.png"
alt=
""
class=
"h-[26px]"
>
</div>
</div>
<a-space
direction=
"vertical"
class=
"px-[72px]"
>
<a-form
:model=
"loginMsg"
:rules=
"rules"
@
submit=
"loginHandler"
layout=
"vertical"
class=
"mt-[42px]"
>
<a-form-item
field=
"email"
:label=
"loginMsg.reType==0?t('login.account'):t('login.emailLogin')"
>
<a-input
class=
"loginMsg-input"
v-model=
"loginMsg.email"
:placeholder=
"loginMsg.reType==0?t('login.accountPlaceholder'):t('login.emailPasswordPlaceholder')"
:maxLength=
"16"
size=
"large"
>
<!--
<template
#
prefix
>
<icon-user
size=
"16"
strokeLinejoin=
"miter"
/>
</
template
>
-->
</a-input>
</a-form-item>
<a-form-item
field=
"password"
:label=
"t('login.password')"
class=
""
>
<!-- :invisible-button="true" -->
<!-- :defaultVisibility="true" -->
<a-input-password
class=
"loginMsg-input"
v-model=
"loginMsg.password"
size=
"large"
:placeholder=
"t('login.passwordPlaceholder')"
:maxLength=
"50"
:invisible-button=
"false"
>
<!-- <template #prefix>
<icon-key size="16" strokeLinejoin="miter" />
</template> -->
</a-input-password>
</a-form-item>
<div
class=
"mt-[34px] flex flex-row items-center"
>
<a-button
type=
"primary"
size=
"large"
:loading=
"loading"
html-type=
"submit"
class=
"microsoft-font flex-1 font-bold text-gray-200 !h-[46px] !rounded-[13px] !text-base"
>
{{ t('login.loginButton') }}
</a-button>
</div>
</a-form>
</a-space>
<div
class=
"mt-[40px] flex items-center justify-center"
>
<a-divider
orientation=
"center"
class=
"text-[16px] text-[#EEEFEB]"
></a-divider>
<span
class=
"text-nowrap primary1-3 px-[14px]"
>
{{ t('login.othenLogin') }}
</span>
<a-divider
orientation=
"center"
class=
"text-[16px] text-[#EEEFEB]"
></a-divider>
</div>
<div
class=
"flex items-center justify-between px-[100px] mt-[20px]"
>
<!-- loginForm-itemActive loginForm-item-->
<div
class=
"w-[42px] h-[42px]
rounded-full bg-[#FFF]
flex items-center justify-center cursor-pointer loginForm-item"
v-for=
"(item,index) in loginTypes"
:key=
"index"
@
click=
"toggleLoginType(item.value)"
>
<img
:src=
"item.url"
alt=
""
class=
"w-[14px] h-[14px]"
/>
</div>
</div>
</div>
</div>
</div>
<div
class=
"flex justify-center text-white pb-[117px] text-[16px]"
>
<div
class=
"px-[17px] py-[30px] cursor-pointer"
@
click=
"handleClick('/forgePassword')"
>
{{ t('login.forgotPassword') }}
</div>
<div
class=
"px-[17px] py-[30px] cursor-pointer"
@
click=
"handleClick('/register')"
>
{{ t('login.registerNow') }}
</div>
</div>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
computed
,
inject
}
from
'vue'
import
{
useUserStore
}
from
'@/stores/index'
import
UserServices
from
'@/services/ErpUserService'
import
ErpUserService
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
{
onMounted
}
from
'vue'
import
VueHcaptcha
from
'@hcaptcha/vue3-hcaptcha'
import
{
useRouter
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
{
useSystemConfigStore
}
from
'@/stores/index'
import
f
from
'@/assets/images/login_f.png'
import
G
from
'@/assets/images/login_G.png'
import
tel
from
'@/assets/images/login_tel.png'
import
line
from
'@/assets/images/login_line.png'
const
{
t
}
=
useI18n
();
const
userStore
=
useUserStore
()
const
systemConfigStore
=
useSystemConfigStore
()
const
loading
=
ref
(
false
)
const
currentTenantId
=
ref
(
0
)
const
needVerify
=
ref
(
false
)
const
validateToken
=
ref
(
''
)
const
router
=
useRouter
()
const
invisibleHcaptcha
=
ref
()
const
loginMsg
=
reactive
({
tenantId
:
systemConfigStore
.
tenantId
||
null
,
reType
:
0
,
//登录方式 0账号密码 1谷歌授权 3LINE授权 7FaceBook授权
openId
:
""
,
email
:
"2310721242@qq.com"
,
password
:
'123456'
,
})
const
loginTypes
=
ref
([
{
label
:
'f'
,
value
:
7
,
url
:
f
,
},
{
label
:
'G'
,
value
:
1
,
url
:
G
,
},
{
label
:
'tel'
,
value
:
0
,
url
:
tel
,
},
{
label
:
'inline'
,
value
:
3
,
url
:
line
,
},
])
// const search = inject('search') as any;
// 验证规则调整
const
rules
=
computed
(()
=>
({
email
:
[
{
required
:
true
,
message
:
t
(
'login.accountRequired'
),
},
],
password
:
[
{
required
:
true
,
message
:
t
(
'login.passwordRequired'
),
},
],
}))
const
verifyHandler
=
(
token
:
string
,
ekey
:
string
)
=>
{
validateToken
.
value
=
token
}
const
verifyCheckHandler
=
async
()
=>
{
const
response
=
await
ErpUserService
.
NeedVerifyStatusAsync
()
if
(
response
.
data
.
resultCode
==
ApiResult
.
SUCCESS
)
{
needVerify
.
value
=
response
.
data
.
data
==
1
}
else
needVerify
.
value
=
true
}
const
handleClick
=
(
path
:
string
)
=>
{
router
.
push
(
path
)
}
const
toggleLoginType
=
(
type
:
number
)
=>
{
loginMsg
.
reType
=
type
if
(
type
==
1
)
{
initGoogleLogin
()
}
}
const
loginHandler
=
async
({
values
,
errors
}:
any
)
=>
{
if
(
errors
||
loading
.
value
)
return
loading
.
value
=
true
try
{
const
result
=
await
userStore
.
setUserPasswordLoginAsync
(
loginMsg
.
email
,
loginMsg
.
password
,
loginMsg
.
tenantId
?.
toString
()
||
''
,
loginMsg
.
reType
,
loginMsg
.
openId
?.
toString
()
||
''
,
)
loading
.
value
=
false
currentTenantId
.
value
=
0
if
(
result
.
status
==
'SUCCESS'
)
{
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
})
}
else
{
if
(
!
needVerify
.
value
)
needVerify
.
value
=
result
.
verify
if
(
invisibleHcaptcha
.
value
&&
needVerify
.
value
)
invisibleHcaptcha
.
value
.
reset
()
}
}
finally
{
loading
.
value
=
false
}
}
// 初始化谷歌登录
const
initGoogleLogin
=
()
=>
{
const
cb
=
async
(
data
:
any
)
=>
{
loading
.
value
=
true
try
{
const
result
=
await
userStore
.
setUserGoogleLoginAsync
(
data
.
credential
)
if
(
result
.
status
===
'SUCCESS'
)
{
// 登录成功,跳转到Dashboard
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
||
'/dashboard'
,
})
}
}
finally
{
loading
.
value
=
false
}
}
;(
window
as
any
).
googleCallback
=
cb
const
script
=
document
.
createElement
(
'script'
)
script
.
src
=
'https://accounts.google.com/gsi/client'
document
.
body
.
appendChild
(
script
)
}
// 检查是否需要验证
const
checkNeedVerify
=
async
()
=>
{
try
{
const
response
=
await
ErpUserService
.
NeedVerifyStatusAsync
()
if
(
response
.
data
.
resultCode
===
ApiResult
.
SUCCESS
)
{
needVerify
.
value
=
response
.
data
.
data
===
1
}
else
{
needVerify
.
value
=
true
}
}
catch
(
error
)
{
needVerify
.
value
=
true
}
}
// 初始化
const
init
=
async
()
=>
{
// 如果已经登录且是正常代理商,直接跳转到仪表盘
if
(
userStore
.
getUserToken
&&
userStore
.
getUser
)
{
const
userStatus
=
userStore
.
getUser
.
status
const
disableStatus
=
userStore
.
getUser
.
disableStatus
// 只有状态正常的代理商才跳转到仪表盘
// 申请中(PendingReview)和被拒绝(Rejected)状态不跳转,允许继续登录
if
(
userStatus
!==
'PendingReview'
&&
userStatus
!==
'Rejected'
&&
disableStatus
!==
'Disable'
)
{
router
.
replace
(
'/dashboard'
)
return
}
}
await
checkNeedVerify
()
initGoogleLogin
()
}
init
()
</
script
>
<
style
scoped
lang=
"scss"
>
:deep
(
.arco-form-item-content
)
{
min-height
:
46px
;
border-radius
:
12px
;
}
:deep
(
.arco-input-wrapper
)
{
height
:
46px
;
border-radius
:
12px
!
important
;
background-color
:
#EEEFEB
;
}
:deep
(
.arco-input-focus
)
{
border-radius
:
12px
;
box-shadow
:
rgba
(
60
,
85
,
62
,
0
.18
)
0px
5px
15px
;
border
:
2px
solid
#8AAA8A
;
background-color
:
#FFFFFF
;
}
:deep
(
.arco-form-item-label
)
{
font-size
:
16px
;
padding-left
:
17px
;
}
:deep
(
.arco-input-wrapper
.arco-input.arco-input-size-large
)
{
font-size
:
16px
;
}
:deep
(
.arco-btn-primary
)
{
box-shadow
:
rgba
(
74
,
102
,
77
,
0
.15
)
0px
5px
15px
;
}
:deep
(
.arco-divider-text
)
{
/*background: #fff;*/
font-size
:
16px
;
color
:
#C2C3C0
;
font-weight
:
400
;
}
:deep
(
.arco-divider-horizontal
)
{
width
:
93px
;
min-width
:
93px
;
border-bottom
:
1px
solid
#EEF0E8
;
}
:deep
(
.arco-input
)
{
text-indent
:
4px
;
}
:deep
(
.arco-form-item-label-required-symbol
)
{
display
:
none
;
}
:deep
(
.arco-form-item-message
)
{
color
:
rgba
(
255
,
0
,
0
,
0
);
}
.loginForm-bg
{
background
:
url('../../../assets/images/login_formbg.png')
no-repeat
white
;
background-size
:
100%
100%
;
}
/*.loginForm-bg:deep(.arco-btn-primary){
background-color: var(--primary1-6) !important;
}*/
.loginForm-item
{
border
:
1px
solid
var
(
--
primary1-3
);
}
.loginForm-item
:hover
{
border
:
2px
solid
var
(
--
primary1-5
);
}
.loginForm-itemActive
{
border
:
2px
solid
var
(
--
primary1-5
);
}
</
style
>
src/views/auth/components/registerForm.vue
deleted
100644 → 0
View file @
73fdf525
<
template
>
<div
class=
"w-full flex flex-col loginForm"
>
<div
class=
"flex justify-center"
>
<div
class=
"w-[463px] h-[580px] "
>
<!--
<div
class=
"loginForm-bg w-full h-[620px] rounded-[18px] absolute top-0 left-0 bottom-0 z-[2]"
></div>
-->
<!-- absolute top-0 left-0 bottom-0 -->
<div
class=
"loginForm-bg w-full h-full rounded-[18px] flex flex-col"
>
<a-space
direction=
"vertical"
class=
"px-[72px]"
>
<a-form
:model=
"formData"
:rules=
"rules"
@
submit=
"handleSendCode"
layout=
"vertical"
class=
"mt-[42px]"
>
<!--
<div
class=
"flex items-end"
>
<div
class=
"flex-1"
>
<a-form-item
field=
"emailNum"
:label=
"t('login.email')"
>
<a-input
class=
"formData-input"
v-model=
"formData.emailNum"
placeholder=
""
:maxLength=
"16"
size=
"large"
>
</a-input>
</a-form-item>
</div>
<a-form-item
class=
"text-[16px] text-1 px-[6px] font-medium !w-[31px]"
>
<div>
@
</div>
</a-form-item>
<a-form-item
field=
"emailSuffix"
label=
""
class=
"!w-[107px]"
>
<a-input
class=
"formData-input"
v-model=
"formData.emailSuffix"
placeholder=
""
:maxLength=
"16"
size=
"large"
>
</a-input>
</a-form-item>
</div>
-->
<a-form-item
field=
"email"
:label=
"t('login.email')"
>
<a-input
class=
"formData-input"
v-model=
"formData.email"
placeholder=
""
:maxLength=
"16"
size=
"large"
>
</a-input>
</a-form-item>
<a-form-item
field=
"verificationCode"
:label=
"t('login.verifyCode')"
class=
""
>
<a-input
class=
"formData-input"
v-model=
"formData.verificationCode"
size=
"large"
:placeholder=
"t('login.verifyCodeRequired')"
:defaultVisibility=
"false"
:maxLength=
"50"
:invisible-button=
"false"
@
input=
"handleCodeInput"
>
<template
#
suffix
>
<a-divider
direction=
"vertical"
class=
"text-[16px] text-[#EEEFEB]"
></a-divider>
<div
class=
"cursor-pointer primary1 font-medium text-[16px]"
>
<!--
<div
v-if=
"search.countdown > 0"
>
{{
t
(
'login.resendCode'
,
{
seconds
:
search
.
countdown
}
)
}}
<
/div
>
<
div
v
-
else
@
click
=
"handleSendCode"
>
{{
t
(
'login.getVerifyCode'
)
}}
<
/div> --
>
<
icon
-
check
-
circle
-
fill
v
-
if
=
"codeValidateStatus === 'success'"
class
=
"text-green-700"
/>
<
icon
-
close
-
circle
-
fill
v
-
else
-
if
=
"codeValidateStatus === 'error'"
class
=
"text-red-500"
/>
<
a
-
button
@
click
=
"handleSendCode"
:
disabled
=
"!canSendCode || sendCodeCountdown > 0"
:
loading
=
"sendingCode"
size
=
"large"
type
=
"text"
class
=
"w-full"
>
<
span
class
=
"primary1-5"
>
{{
sendCodeCountdown
>
0
?
`${sendCodeCountdown
}
s ${t('register.resend')
}
`
:
t
(
'login.getVerifyCode'
)
}}
<
/span
>
<
/a-button
>
<
/div
>
<
/template
>
<
/a-input
>
<
/a-form-item
>
<
a
-
form
-
item
field
=
"password"
:
label
=
"t('login.setPassword')"
class
=
""
>
<
a
-
input
-
password
class
=
"formData-input"
v
-
model
=
"formData.password"
size
=
"large"
:
placeholder
=
"t('login.setPasswordRequired')"
:
defaultVisibility
=
"false"
:
maxLength
=
"50"
:
invisible
-
button
=
"false"
>
<!--
<
template
#
prefix
>
<
icon
-
key
size
=
"16"
strokeLinejoin
=
"miter"
/>
<
/template> --
>
<
/a-input-password
>
<
/a-form-item
>
<
a
-
form
-
item
field
=
"confirmPassword"
:
label
=
"t('login.repeatedpassword')"
class
=
""
>
<
a
-
input
-
password
class
=
"formData-input"
v
-
model
=
"formData.confirmPassword"
size
=
"large"
:
placeholder
=
"t('login.confirmPasswordRequired')"
:
defaultVisibility
=
"false"
:
maxLength
=
"50"
:
invisible
-
button
=
"false"
>
<
/a-input-password
>
<
/a-form-item
>
<
div
class
=
"mt-[27px] flex flex-row items-center"
>
<
a
-
button
type
=
"primary"
size
=
"large"
:
loading
=
"loading"
html
-
type
=
"submit"
class
=
"microsoft-font flex-1 font-bold text-gray-200 !h-[46px] !rounded-[13px] !text-base"
@
click
=
"loginHandler"
>
{{
t
(
'login.nextStep'
)
}}
<
/a-button
>
<
/div
>
<
/a-form
>
<
/a-space
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"flex justify-center text-white pb-[117px] text-[16px]"
>
<
div
class
=
"px-[17px] py-[30px] cursor-pointer"
@
click
=
"handleClick('/login')"
>
{{
t
(
'login.backToHome'
)
}}
<
/div
>
<
/div
>
<
/div
>
<
/template
>
<
script
setup
lang
=
"ts"
>
import
{
ref
,
reactive
,
type
Ref
,
computed
,
inject
}
from
'vue'
import
{
useUserStore
}
from
'@/stores/index'
import
ErpUserService
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
{
onMounted
}
from
'vue'
import
VueHcaptcha
from
'@hcaptcha/vue3-hcaptcha'
import
{
useRouter
}
from
'vue-router'
import
{
useI18n
}
from
'vue-i18n'
import
{
Message
}
from
'@arco-design/web-vue'
import
UserService
from
'@/services/UserService'
const
{
t
}
=
useI18n
();
const
userStore
=
useUserStore
()
const
loading
=
ref
(
false
)
const
currentTenantId
=
ref
(
0
)
const
needVerify
=
ref
(
false
)
const
validateToken
=
ref
(
''
)
const
router
=
useRouter
()
const
invisibleHcaptcha
=
ref
()
const
search
=
inject
(
'search'
)
as
any
;
const
formData
=
reactive
(
search
.
msg
)
// formData = search.msg
// 邮箱验证状态
const
emailChecking
=
ref
(
false
)
const
emailValidateStatus
=
ref
<
''
|
'success'
|
'error'
|
'warning'
>
(
''
)
const
emailValidateMessage
=
ref
(
''
)
// 验证码相关状态
const
sendingCode
=
ref
(
false
)
const
sendCodeCountdown
=
ref
(
0
)
const
codeValidateStatus
=
ref
<
''
|
'success'
|
'error'
>
(
''
)
const
codeValidateMessage
=
ref
(
''
)
const
emailVerified
=
ref
(
false
)
const
verificationToken
=
ref
(
''
)
const
lastVerifiedEmail
=
ref
(
''
)
console
.
log
(
search
.
msg
,
'---------'
)
// 验证规则调整
const
rules
=
computed
(()
=>
({
email
:
[
{
required
:
true
,
message
:
t
(
'login.emailRequired'
)
}
,
{
type
:
'email'
,
message
:
t
(
'login.emailInvalid'
)
}
],
emailNum
:
[
{
required
:
true
,
message
:
t
(
'login.emailFormat'
),
}
,
],
emailSuffix
:
[
{
required
:
true
,
message
:
t
(
'login.emailFormat'
),
}
,
],
verificationCode
:
[
{
required
:
true
,
message
:
t
(
'login.verifyCodeRequired'
),
}
,
],
password
:
[
{
required
:
true
,
message
:
t
(
'login.passwordRequired'
),
}
,
{
validator
:
(
value
:
any
,
cb
:
any
)
=>
{
if
(
!
/^
(?=
.*
[
A-Za-z
])(?=
.*
\d)
.{8,
}
$/
.
test
(
value
))
{
cb
(
t
(
'login.passwordFormat'
))
}
else
if
(
value
!==
formData
.
confirmPassword
)
{
cb
(
t
(
'login.passwordMismatch'
))
}
else
{
cb
()
}
}
}
],
confirmPassword
:
[
{
required
:
true
,
message
:
t
(
'login.confirmPasswordRequired'
)
}
,
{
validator
:
(
value
:
any
,
cb
:
any
)
=>
{
if
(
!
/^
(?=
.*
[
A-Za-z
])(?=
.*
\d)
.{8,
}
$/
.
test
(
value
))
{
cb
(
t
(
'login.passwordFormat'
))
}
else
if
(
value
!==
formData
.
password
)
{
cb
(
t
(
'login.passwordMismatch'
))
}
else
{
cb
()
}
}
}
],
}
))
const
verifyHandler
=
(
token
:
string
,
ekey
:
string
)
=>
{
validateToken
.
value
=
token
}
const
verifyCheckHandler
=
async
()
=>
{
const
response
=
await
ErpUserService
.
NeedVerifyStatusAsync
()
if
(
response
.
data
.
resultCode
==
ApiResult
.
SUCCESS
)
{
needVerify
.
value
=
response
.
data
.
data
==
1
}
else
needVerify
.
value
=
true
}
const
handleClick
=
(
path
:
string
)
=>
{
router
.
push
(
path
)
}
// 判断是否可以发送验证码
const
canSendCode
=
computed
(()
=>
{
return
formData
.
email
&&
emailValidateStatus
.
value
===
'success'
}
)
// 邮箱验证延时器
let
emailCheckTimer
:
number
|
null
=
null
// 处理邮箱失焦验证
const
handleEmailBlur
=
async
()
=>
{
const
email
=
formData
.
email
.
trim
()
// 清除之前的定时器
if
(
emailCheckTimer
)
{
clearTimeout
(
emailCheckTimer
)
}
// 如果邮箱为空或格式不正确,不验证
if
(
!
email
)
{
emailValidateStatus
.
value
=
''
emailValidateMessage
.
value
=
''
return
}
// 简单的邮箱格式验证
const
emailRegex
=
/^
[^\s
@
]
+@
[^\s
@
]
+
\.[^\s
@
]
+$/
if
(
!
emailRegex
.
test
(
email
))
{
emailValidateStatus
.
value
=
'error'
emailValidateMessage
.
value
=
t
(
'register.emailInvalid'
)
return
}
// 延迟 500ms 验证,避免频繁请求
emailCheckTimer
=
setTimeout
(
async
()
=>
{
await
validateEmail
(
email
)
}
,
500
)
}
// 验证邮箱是否可用
const
validateEmail
=
async
(
email
:
string
)
=>
{
emailChecking
.
value
=
true
emailValidateStatus
.
value
=
''
emailValidateMessage
.
value
=
''
try
{
const
result
=
await
UserService
.
validateEmailAsync
(
email
,
formData
.
tenantId
||
'default'
)
if
(
result
.
isValid
)
{
// 邮箱可用
emailValidateStatus
.
value
=
'success'
emailValidateMessage
.
value
=
t
(
'emailValidation.available'
)
}
else
if
(
result
.
isExist
)
{
// 邮箱已存在
emailValidateStatus
.
value
=
'error'
emailValidateMessage
.
value
=
t
(
'emailValidation.exists'
)
}
else
if
(
!
result
.
isValidFormat
)
{
// 格式不正确
emailValidateStatus
.
value
=
'error'
emailValidateMessage
.
value
=
t
(
'emailValidation.invalidFormat'
)
}
else
{
// 其他错误
emailValidateStatus
.
value
=
'error'
emailValidateMessage
.
value
=
result
.
message
||
t
(
'emailValidation.checkFailed'
)
}
}
catch
(
error
:
any
)
{
console
.
error
(
'邮箱验证失败:'
,
error
)
emailValidateStatus
.
value
=
'warning'
emailValidateMessage
.
value
=
t
(
'emailValidation.checkFailed'
)
}
finally
{
emailChecking
.
value
=
false
}
}
// 处理邮箱输入变化
const
handleEmailChange
=
()
=>
{
// 如果邮箱已验证,且当前邮箱与已验证邮箱不同,则重置验证状态
if
(
emailVerified
.
value
&&
formData
.
email
!==
lastVerifiedEmail
.
value
)
{
emailVerified
.
value
=
false
verificationToken
.
value
=
''
codeValidateStatus
.
value
=
''
codeValidateMessage
.
value
=
''
formData
.
verificationCode
=
''
Message
.
warning
(
t
(
'register.emailChangedNeedVerify'
))
}
}
// 发送验证码
const
handleSendCode
=
async
()
=>
{
if
(
!
formData
.
email
||
emailValidateStatus
.
value
!==
'success'
)
{
Message
.
warning
(
t
(
'register.pleaseInputValidEmail'
))
return
}
sendingCode
.
value
=
true
try
{
const
result
=
await
UserService
.
sendVerificationCodeAsync
(
formData
.
email
,
formData
.
tenantId
||
'default'
)
if
(
result
.
success
)
{
Message
.
success
(
result
.
message
||
t
(
'register.codeSent'
))
// 开始倒计时
sendCodeCountdown
.
value
=
result
.
expiresIn
||
60
const
timer
=
setInterval
(()
=>
{
sendCodeCountdown
.
value
--
if
(
sendCodeCountdown
.
value
<=
0
)
{
clearInterval
(
timer
)
}
}
,
1000
)
}
else
{
Message
.
error
(
result
.
message
||
t
(
'register.codeSendFailed'
))
}
}
catch
(
error
:
any
)
{
console
.
error
(
'发送验证码失败:'
,
error
)
Message
.
error
(
error
.
message
||
t
(
'register.codeSendFailed'
))
}
finally
{
sendingCode
.
value
=
false
}
}
// 处理验证码输入
const
handleCodeInput
=
()
=>
{
// 重置验证状态
codeValidateStatus
.
value
=
''
codeValidateMessage
.
value
=
''
// 当输入6位时自动验证
if
(
formData
.
verificationCode
.
length
===
6
)
{
verifyCode
()
}
}
// 验证验证码(在用户输入完6位后自动验证)
const
verifyCode
=
async
()
=>
{
if
(
!
formData
.
verificationCode
||
formData
.
verificationCode
.
length
!==
6
)
{
return
}
try
{
const
result
=
await
UserService
.
verifyEmailCodeAsync
(
formData
.
email
,
formData
.
verificationCode
,
formData
.
tenantId
||
'default'
)
if
(
result
.
isValid
)
{
codeValidateStatus
.
value
=
'success'
codeValidateMessage
.
value
=
t
(
'register.codeVerified'
)
emailVerified
.
value
=
true
verificationToken
.
value
=
result
.
verificationToken
||
''
lastVerifiedEmail
.
value
=
formData
.
email
Message
.
success
(
t
(
'register.codeVerified'
))
}
else
{
codeValidateStatus
.
value
=
'error'
codeValidateMessage
.
value
=
result
.
message
||
t
(
'register.codeInvalid'
)
emailVerified
.
value
=
false
verificationToken
.
value
=
''
}
}
catch
(
error
:
any
)
{
console
.
error
(
'验证码验证失败:'
,
error
)
codeValidateStatus
.
value
=
'error'
codeValidateMessage
.
value
=
error
.
message
||
t
(
'register.codeVerifyFailed'
)
emailVerified
.
value
=
false
verificationToken
.
value
=
''
}
}
// 处理 OTA 授权验证
const
handleOtaAuth
=
async
(
token
:
string
)
=>
{
const
loading
=
Message
.
loading
(
t
(
'otaAuth.verifying'
))
try
{
const
result
=
await
OtaAuthService
.
validateOtaToken
(
token
)
if
(
result
.
success
)
{
// 保存临时令牌和用户信息到 sessionStorage
sessionStorage
.
setItem
(
'tempToken'
,
result
.
temporaryAccessToken
)
sessionStorage
.
setItem
(
'otaUserInfo'
,
JSON
.
stringify
(
result
.
userInfo
))
// 根据建议路由跳转
const
suggestedRoute
=
result
.
distributorStatus
.
suggestedRoute
router
.
replace
({
path
:
suggestedRoute
}
)
}
else
{
Message
.
error
(
t
(
'otaAuth.authFailed'
))
router
.
replace
(
'/login'
)
}
}
catch
(
error
:
any
)
{
console
.
error
(
'OTA 授权验证失败:'
,
error
)
Message
.
error
(
error
.
message
||
t
(
'otaAuth.authFailed'
))
router
.
replace
(
'/login'
)
}
finally
{
loading
.
close
()
}
}
const
handleFileUpload
=
(
options
:
any
)
=>
{
const
{
fileItem
,
onSuccess
,
onError
}
=
options
// TODO: 实现真实的文件上传到服务器
// 现在先模拟上传成功
setTimeout
(()
=>
{
formData
.
documentFilePath
=
`/uploads/${fileItem.file.name
}
`
onSuccess
()
Message
.
success
(
t
(
'register.uploadSuccess'
))
}
,
1000
)
}
const
handlePrevious
=
()
=>
{
currentStep
.
value
--
}
const
handleNext
=
()
=>
{
// 简单验证必填字段
if
(
currentStep
.
value
===
1
)
{
// 未登录用户需要验证邮箱和密码
if
(
!
isLoggedIn
.
value
&&
!
isFromOta
.
value
)
{
if
(
!
formData
.
email
||
!
formData
.
password
||
!
formData
.
confirmPassword
)
{
Message
.
warning
(
t
(
'register.pleaseComplete'
))
return
}
if
(
formData
.
password
!==
formData
.
confirmPassword
)
{
Message
.
warning
(
t
(
'register.passwordMismatch'
))
return
}
// 检查邮箱是否已验证
if
(
!
emailVerified
.
value
)
{
Message
.
warning
(
t
(
'register.pleaseVerifyEmail'
))
return
}
// 检查验证码
if
(
!
formData
.
verificationCode
||
codeValidateStatus
.
value
!==
'success'
)
{
Message
.
warning
(
t
(
'register.pleaseVerifyCode'
))
return
}
}
}
else
if
(
currentStep
.
value
===
2
)
{
if
(
!
formData
.
companyOrBrandName
||
!
formData
.
contactPerson
||
!
formData
.
contactPhone
||
!
formData
.
documentFilePath
)
{
Message
.
warning
(
t
(
'register.pleaseComplete'
))
return
}
}
currentStep
.
value
++
}
<
/script
>
<
style
scoped
lang
=
"scss"
>
:
deep
(.
arco
-
form
-
item
-
content
){
min
-
height
:
46
px
;
border
-
radius
:
12
px
;
}
:
deep
(.
arco
-
input
-
wrapper
){
height
:
46
px
;
border
-
radius
:
12
px
!
important
;
background
-
color
:
#
EEEFEB
;
}
:
deep
(.
arco
-
input
-
focus
){
border
-
radius
:
12
px
;
box
-
shadow
:
rgba
(
60
,
85
,
62
,
0.18
)
0
px
5
px
15
px
;
border
:
2
px
solid
var
(
--
primary
-
2
);
background
-
color
:
#
FFFFFF
;
}
:
deep
(.
arco
-
form
-
item
-
label
){
font
-
size
:
16
px
;
padding
-
left
:
17
px
;
}
:
deep
(.
arco
-
input
-
wrapper
.
arco
-
input
.
arco
-
input
-
size
-
large
){
font
-
size
:
16
px
;
}
:
deep
(.
arco
-
btn
-
primary
){
box
-
shadow
:
rgba
(
74
,
102
,
77
,
0.15
)
0
px
5
px
15
px
;
}
:
deep
(.
arco
-
divider
-
text
){
/*background: #fff;*/
font
-
size
:
16
px
;
color
:
#
C2C3C0
;
font
-
weight
:
400
;
}
:
deep
(.
arco
-
divider
-
horizontal
){
width
:
93
px
;
min
-
width
:
93
px
;
border
-
bottom
:
1
px
solid
#
EEF0E8
;
}
:
deep
(.
arco
-
input
){
text
-
indent
:
4
px
;
}
.
loginForm
-
bg
{
background
:
url
(
'../../../assets/images/login_formbg.png'
)
no
-
repeat
white
;
background
-
size
:
100
%
100
%
;
}
:
deep
(.
arco
-
btn
-
primary
){
background
-
color
:
var
(
--
primary1
-
7
);
}
:
deep
(.
arco
-
btn
-
primary
:
hover
){
background
-
color
:
var
(
--
primary1
-
5
);
}
:
deep
(.
arco
-
form
-
item
-
label
-
required
-
symbol
){
display
:
none
;
}
:
deep
(.
arco
-
form
-
item
-
message
){
// color: rgba(255,0,0,0);
}
:
deep
(.
arco
-
divider
-
vertical
){
border
-
left
:
1
px
solid
var
(
--
primary1
-
4
);
}
<
/style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment