182 lines
3.9 KiB
Vue
182 lines
3.9 KiB
Vue
<script setup lang="ts">
|
||
import { computed } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import { SmsCodeInput } from '@/components'
|
||
import { isPhone } from '@/utils/validate'
|
||
|
||
interface Props {
|
||
phone: string
|
||
code: string
|
||
agree: boolean
|
||
}
|
||
|
||
const props = defineProps<Props>()
|
||
|
||
const emit = defineEmits<{
|
||
'update:phone': [value: string]
|
||
'update:code': [value: string]
|
||
'update:agree': [value: boolean]
|
||
getCode: [phone: string]
|
||
submit: []
|
||
}>()
|
||
|
||
const localPhone = computed({
|
||
get: () => props.phone,
|
||
set: (value: string) => emit('update:phone', value),
|
||
})
|
||
|
||
const localCode = computed({
|
||
get: () => props.code,
|
||
set: (value: string) => emit('update:code', value),
|
||
})
|
||
|
||
const localAgree = computed({
|
||
get: () => props.agree,
|
||
set: (value: boolean) => emit('update:agree', value),
|
||
})
|
||
|
||
function onGetCode(): void {
|
||
if (!isPhone(props.phone)) {
|
||
ElMessage.warning('手机号格式不正确')
|
||
return
|
||
}
|
||
emit('getCode', props.phone)
|
||
}
|
||
|
||
function onSubmit(): void {
|
||
if (!isPhone(props.phone)) {
|
||
ElMessage.warning('手机号格式不正确')
|
||
return
|
||
}
|
||
if (!props.code) {
|
||
ElMessage.warning('请输入验证码')
|
||
return
|
||
}
|
||
emit('submit')
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<form class="sms-login" @submit.prevent="onSubmit">
|
||
<div class="sms-login__field">
|
||
<label class="sms-login__label" for="sms-phone">手机号</label>
|
||
<input
|
||
id="sms-phone"
|
||
v-model="localPhone"
|
||
class="sms-login__input"
|
||
type="text"
|
||
placeholder="请输入手机号"
|
||
maxlength="11"
|
||
autocomplete="tel"
|
||
>
|
||
</div>
|
||
<div class="sms-login__field">
|
||
<label class="sms-login__label" for="sms-code">验证码</label>
|
||
<SmsCodeInput v-model:code="localCode" @get-code="onGetCode" />
|
||
</div>
|
||
<label class="sms-login__agree">
|
||
<input v-model="localAgree" type="checkbox">
|
||
<span>已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
|
||
</label>
|
||
<button class="sms-login__submit" type="submit">
|
||
登录
|
||
</button>
|
||
</form>
|
||
</template>
|
||
|
||
<style lang="less" scoped>
|
||
// 设计稿 #38(手机验证码登录)纵向坐标:
|
||
// 手机号标签 438 → 验证码标签 520(差 82)
|
||
// 验证码输入框底 ~588 → 勾选行 622 → 登录按钮文字 669
|
||
.sms-login {
|
||
.flex(column, flex-start, stretch);
|
||
margin: 26px 0 0;
|
||
width: 100%;
|
||
|
||
&__field {
|
||
.flex(column, flex-start, stretch);
|
||
gap: 6px;
|
||
width: 100%;
|
||
}
|
||
|
||
// 第一个字段底(457+40=497... 按标签 438+17+6+40=501)→ 第二标签 520,间距 19px
|
||
&__field + &__field {
|
||
margin-top: 19px;
|
||
}
|
||
|
||
&__label {
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
line-height: 17px;
|
||
color: #1f2937;
|
||
text-align: center;
|
||
}
|
||
|
||
&__input {
|
||
width: 100%;
|
||
height: 40px;
|
||
padding: 0 12px;
|
||
border: 1px solid @border-color;
|
||
border-radius: @radius-sm;
|
||
background: @white;
|
||
font-size: 13px;
|
||
color: #1f2937;
|
||
outline: none;
|
||
transition: border-color 0.2s;
|
||
box-sizing: border-box;
|
||
|
||
&:focus {
|
||
border-color: @primary-strong;
|
||
}
|
||
|
||
&::placeholder {
|
||
color: #1f2937;
|
||
}
|
||
}
|
||
|
||
// 设计稿 #38:勾选框 (992.2,623) 7.5×14,勾选文字 622
|
||
&__agree {
|
||
.flex(row, flex-start, center);
|
||
gap: 8px;
|
||
margin-top: 14px;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 16px;
|
||
color: #6b7280;
|
||
cursor: pointer;
|
||
|
||
input {
|
||
flex-shrink: 0;
|
||
width: 14px;
|
||
height: 14px;
|
||
margin: 0;
|
||
accent-color: @primary-strong;
|
||
}
|
||
|
||
em {
|
||
font-style: normal;
|
||
color: @primary-strong;
|
||
}
|
||
}
|
||
|
||
// 设计稿 #38:按钮文字 (1302,669) 54×20
|
||
&__submit {
|
||
width: 100%;
|
||
height: 46px;
|
||
margin-top: 17px;
|
||
border: none;
|
||
border-radius: @radius-sm;
|
||
background: @primary-strong;
|
||
color: @white;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
|
||
&:hover {
|
||
background: @primary-hover;
|
||
}
|
||
}
|
||
}
|
||
</style>
|