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

<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>