Files
cz-web/src/views/login/cpns/SmsLoginForm.vue
wangzzpeng 7bc84bbe5e first
2026-09-24 10:10:43 +08:00

146 lines
3.0 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">
<input
v-model="localPhone"
class="sms-login__input"
type="text"
placeholder="请输入手机号"
maxlength="11"
autocomplete="tel"
>
</div>
<div class="sms-login__field">
<SmsCodeInput v-model:code="localCode" @get-code="onGetCode" />
</div>
<label class="sms-login__agree">
<input v-model="localAgree" type="checkbox">
<span>已阅读并同意《用户协议》和《隐私政策》</span>
</label>
<button class="sms-login__submit" type="submit">
登 录
</button>
</form>
</template>
<style lang="less" scoped>
.sms-login {
.flex(column, flex-start);
gap: @spacing-base;
&__field {
width: 100%;
}
&__input {
width: 100%;
height: 44px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
}
&::placeholder {
color: @text-color-secondary;
}
}
&__agree {
.flex(row, flex-start);
gap: @spacing-xs;
font-size: @font-size-sm;
color: @text-color-secondary;
cursor: pointer;
input {
margin-top: 2px;
accent-color: @primary-color;
}
}
&__submit {
width: 100%;
height: 44px;
border: none;
border-radius: @radius-base;
background: @primary-color;
color: @white;
font-size: @font-size-lg;
letter-spacing: 2px;
cursor: pointer;
transition: background 0.2s;
&:hover {
background: @primary-hover;
}
}
}
</style>