You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.6 KiB
164 lines
4.6 KiB
<template>
|
|
<div class="phone-code-input">
|
|
<!-- 手机号输入框 + 发送按钮 -->
|
|
<GuipFormItem column="column" addClass="w388">
|
|
<div slot="formLeft" class="form-top-icon">
|
|
<img src="../assets/franchise1/storeNum.svg" alt="">
|
|
<span>手机号码</span>
|
|
</div>
|
|
<el-form-item slot="formDom" :prop="phoneProp" :rules="phoneRules" style="display: flex;justify-content: space-between;">
|
|
<el-input v-model="phone" @input="validateInput"
|
|
placeholder="请输入手机号" style="width: 277px;" clearable @blur="validatePhone">
|
|
</el-input>
|
|
<GuipButton type="reverseMild" :btnstyle="{width:'99px',height:'38px'}" :disabled="!canSendCode" @click="sendCode" class="send-btn">
|
|
{{ countdown > 0 ? `${countdown}s后重试` : '获取验证码' }}</GuipButton>
|
|
</el-form-item>
|
|
</GuipFormItem>
|
|
<!-- 验证码输入框 -->
|
|
<GuipFormItem column="column" addClass="w388">
|
|
<div slot="formLeft" class="form-top-icon">
|
|
<img src="../assets/franchise1/codeNumber.svg" alt="">
|
|
<span>验证码</span>
|
|
</div>
|
|
<el-form-item slot="formDom" :prop="codeProp" :rules="codeRules">
|
|
<div class="code-input-wrapper">
|
|
<el-input v-model="code" placeholder="请输入验证码" clearable @blur="validateCode"></el-input>
|
|
</div>
|
|
</el-form-item>
|
|
</GuipFormItem>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import GuipFormItem from '@/components/GuipFormItem.vue';
|
|
import GuipButton from '@/components/GuipButton.vue';
|
|
|
|
export default {
|
|
name: "PhoneCodeInput",
|
|
components:{
|
|
GuipButton,
|
|
GuipFormItem,
|
|
},
|
|
props: {
|
|
// 用于 Form 校验的 prop(如 'phone' 和 'code')
|
|
phoneProp: {
|
|
type: String,
|
|
default: "phone",
|
|
},
|
|
codeProp: {
|
|
type: String,
|
|
default: "code",
|
|
},
|
|
// 初始值(v-model)
|
|
value: {
|
|
type: Object,
|
|
default: () => ({
|
|
phone: "",
|
|
code: "",
|
|
}),
|
|
},
|
|
// 自定义校验规则(可选)
|
|
phoneRules: {
|
|
type: Array,
|
|
default: () => [
|
|
{ required: true, message: "请输入手机号", trigger: "blur" },
|
|
{ pattern: /^1[3-9]\d{9}$/, message: "手机号格式错误", trigger: "blur" },
|
|
],
|
|
},
|
|
codeRules: {
|
|
type: Array,
|
|
default: () => [
|
|
{ required: true, message: "请输入验证码", trigger: "blur" },
|
|
{ pattern: /^\d{6}$/, message: "验证码必须是6位数字", trigger: "blur" },
|
|
],
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
phone: this.value.phone,
|
|
code: this.value.code,
|
|
countdown: 0, // 倒计时
|
|
timer: null, // 定时器
|
|
};
|
|
},
|
|
computed: {
|
|
// 是否可以发送验证码(手机号格式正确且未在倒计时)
|
|
canSendCode() {
|
|
return /^1[3-9]\d{9}$/.test(this.phone) && this.countdown === 0;
|
|
},
|
|
},
|
|
watch: {
|
|
// 监听内部数据变化,同步到父组件
|
|
phone(newVal) {
|
|
this.$emit("input", { ...this.value, phone: newVal });
|
|
},
|
|
code(newVal) {
|
|
this.$emit("input", { ...this.value, code: newVal });
|
|
},
|
|
// 监听外部 v-model 变化,更新内部数据
|
|
value: {
|
|
deep: true,
|
|
handler(newVal) {
|
|
this.phone = newVal.phone;
|
|
this.code = newVal.code;
|
|
},
|
|
},
|
|
},
|
|
methods: {
|
|
// 校验手机号
|
|
validatePhone() {
|
|
console.log('ooooo');
|
|
// formRef 固定名称
|
|
this.$refs.formRef?.validateField(this.phoneProp);
|
|
},
|
|
validateInput() {
|
|
// formRef 固定名称
|
|
// this.$refs.formRef?.validateField(this.phoneProp);
|
|
if (/^1[3-9]\d{9}$/.test(this.phone)) {
|
|
this.$refs.formRef?.validateField(this.phoneProp, (errorMsg) => {
|
|
if (!errorMsg) {
|
|
console.log('-----00000');
|
|
// 校验通过,错误提示会自动消失
|
|
}else{
|
|
console.log('776767676');
|
|
}
|
|
});
|
|
}
|
|
},
|
|
// 校验验证码
|
|
validateCode() {
|
|
this.$refs.formRef?.validateField(this.codeProp);
|
|
},
|
|
// 发送验证码
|
|
sendCode() {
|
|
if (!this.canSendCode) return;
|
|
|
|
// 模拟发送验证码(实际调用 API)
|
|
|
|
this.startCountdown()
|
|
|
|
this.$emit("send-code", this.phone);
|
|
},
|
|
startCountdown() {
|
|
this.countdown = 60;
|
|
this.timer = setInterval(() => {
|
|
this.countdown--;
|
|
if (this.countdown <= 0) {
|
|
clearInterval(this.timer);
|
|
}
|
|
}, 1000);
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
if (this.timer) clearInterval(this.timer);
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.code-input-wrapper {
|
|
display: flex;
|
|
gap: 10px;
|
|
flex: 1;
|
|
}
|
|
</style>
|