web-base-pc/src/components/walletBindBank.vue

532 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
title="绑定银行卡"
:visible.sync="dialogVisible"
width="40%"
:close-on-click-modal="false"
:before-close="handleCloseDialog"
>
<div class="bind-bank-form-container">
<el-form
ref="bankForm"
:rules="rules"
:model="form"
label-position="right"
label-width="100px"
>
<el-form-item label="银行卡号:" prop="cardNumber">
<el-input
v-model="form.cardNumber"
placeholder="请输入银行卡号"
></el-input>
</el-form-item>
<el-form-item label="银行选择:" prop="pkBank">
<el-select v-model="form.pkBank" placeholder="请选择银行名称">
<el-option
v-for="(item, index) in bankCardChioceList"
:key="index"
:label="item.bankName"
:value="item.pkId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="开户支行:" prop="subBankName">
<el-input
v-model="form.subBankName"
placeholder="请输入开户支行"
></el-input>
</el-form-item>
<el-form-item label="姓名:" prop="accountName">
<el-input
v-model="form.accountName"
placeholder="请输入姓名"
></el-input>
</el-form-item>
<el-form-item label="证件类型:" prop="idType">
<el-select v-model="form.idType" placeholder="请选择证件类型">
<el-option
v-for="(item, index) in cardTypeList"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="证件号码:" prop="idCard">
<el-input
v-model="form.idCard"
placeholder="请输入证件号码"
></el-input>
</el-form-item>
<el-form-item v-if="isMainlandChinaUser" label="手机号:" prop="phone">
<el-input
v-model="form.phone"
placeholder="银行卡预留手机号"
></el-input>
</el-form-item>
<el-form-item
v-if="isMainlandChinaUser && needsVerificationCode"
label="验证码:"
prop="verificationCode"
>
<el-input
v-model="form.verificationCode"
placeholder="请输入验证码"
></el-input>
<el-button
style="margin-left: 10px"
:class="{ 'is-disabled': isSendingCode }"
:disabled="isSendingCode"
type="primary"
@click="sendVerificationCode"
>
{{ verificationCodeButtonText }}
</el-button>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<!-- <div class="btn cancel-btn" @click="handleCloseDialog">取消</div> -->
<el-button @click="handleCloseDialog">取消</el-button>
<el-button type="primary" @click="submitBankForm('bankForm')"
>确定
</el-button>
</div>
</el-dialog>
</template>
<script>
import * as walletApi from "@/api/wallet.js";
import { mapGetters } from "vuex";
export default {
data() {
// 自定义验证码校验逻辑
const validateVerificationCode = (rule, value, callback) => {
if (this.isMainlandChinaUser && this.needsVerificationCode && !value) {
callback(new Error("请输入验证码"));
} else {
callback();
}
};
// 自定义手机号校验逻辑
const validatePhoneNumber = (rule, value, callback) => {
if (this.isMainlandChinaUser && !value) {
callback(new Error("请输入正确的手机号"));
} else if (this.isMainlandChinaUser && value && value.length < 11) {
callback(new Error("请输入正确的手机号"));
} else {
callback();
}
};
return {
cardTypeList: [], // 证件类型列表
dialogVisible: false, // 控制对话框显示
form: {
cardNumber: "", // 银行卡号
accountName: "", // 姓名
idCard: "", // 证件号码
phone: "", // 手机号
pkBank: "", // 银行ID (原 pkBank)
verificationCode: "", // 验证码
subBankName: "", // 开户支行
idType: "", // 证件类型
},
isSendingCode: false, // 是否正在发送验证码
countdownSeconds: 60, // 倒计时秒数
verificationCodeButtonText: "获取验证码", // 验证码按钮文字
countdownTimer: null, // 倒计时定时器
rules: {
cardNumber: [
{ required: true, message: "请输入银行卡号", trigger: "blur" },
],
verificationCode: [
{ required: true, message: "请输入验证码", trigger: "blur" },
{ validator: validateVerificationCode, trigger: "blur" },
],
idType: [
{ required: true, message: "请选择证件类型", trigger: "change" },
],
accountName: [
{ required: true, message: "请输入姓名", trigger: "blur" },
],
subBankName: [
{ required: true, message: "请输入开户支行", trigger: "blur" },
],
// bankNo 验证似乎是重复的,已移除
// name 验证似乎是重复的,已移除
idCard: [
{ required: true, message: "请输入证件号码", trigger: "blur" },
],
// smsCode 似乎未使用,已移除
phone: [
{
required: true,
message: "请输入银行卡预留手机号",
trigger: "blur",
},
// { min: 11, message: '请输入正确的手机号', trigger: "blur" }, // 合并到 validator
{ validator: validatePhoneNumber, trigger: "blur" },
],
pkBank: [
// 原 pkBank
{ required: true, message: "请选择银行卡", trigger: "change" },
],
},
isBankCardVerified: false, // 银行卡是否已验证通过 (原 ifpass)
bankCardChioceList: [], // 可选银行列表
// pkCountry: "", // 由 isMainlandChinaUser 计算属性替代
needsVerificationCode: false, // 是否需要验证码 (原 cancode)
};
},
props: {
// isAdd 更名为 visible更符合对话框的常用属性名
visible: {
type: Boolean,
default: false,
},
},
computed: {
...mapGetters(["userInfo"]),
// 计算用户是否为中国大陆用户
isMainlandChinaUser() {
return this.userInfo?.pkCountry === 1;
},
},
watch: {
// 监听 prop 变化来控制对话框显示
visible(newVal) {
this.dialogVisible = newVal;
if (newVal) {
// 对话框打开时重置状态(如果需要)
this.resetFormState();
}
},
// 监听对话框内部状态变化,并通知父组件
dialogVisible(newVal) {
if (!newVal) {
this.$emit("update:visible", false); // 使用 .sync 修饰符更新父组件状态
this.$emit("closeBind", this.isBankCardVerified ? 1 : 0); // 保留原有逻辑,根据验证状态发送不同值
this.resetFormAndValidation(); // 关闭时重置表单和状态
}
},
},
created() {
this.fetchBankCardChoices();
this.checkVerificationRequirement();
// this.pkCountry = this.userInfo.pkCountry; // 不再需要单独存储,使用计算属性
},
beforeDestroy() {
// 组件销毁前清除定时器
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
}
},
methods: {
// 检查是否需要验证码
checkVerificationRequirement() {
walletApi
.checkIfWhite()
.then((res) => {
// 后端接口 flag 为 'Y' 表示在白名单,不需要验证码
this.needsVerificationCode = !(res.code == 200 && res.flag === "Y");
})
.catch((_err) => {
// 处理获取白名单状态失败的情况,可以设置默认值或提示用户
console.error("获取白名单状态失败:", _err);
this.needsVerificationCode = true; // 默认为需要验证码
});
},
// 获取银行卡选项和证件类型
fetchBankCardChoices() {
walletApi
.getBankCardChoiceList()
.then((res) => {
this.bankCardChioceList = res.data || [];
})
.catch((_err) => {
console.error("获取银行列表失败:", _err);
});
walletApi
.getCardType()
.then((res) => {
this.cardTypeList = res.data || [];
})
.catch((_err) => {
console.error("获取证件类型失败:", _err);
});
},
// 关闭对话框处理
handleCloseDialog() {
this.dialogVisible = false;
// 关闭时已在 watch 中处理了 resetFields 和 emit 事件
},
// 重置表单和相关状态
resetFormAndValidation() {
this.$refs.bankForm?.resetFields();
this.isBankCardVerified = false;
this.clearCountdown(); // 清除倒计时状态
},
// 清除倒计时状态
clearCountdown() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
this.isSendingCode = false;
this.verificationCodeButtonText = "获取验证码";
this.countdownSeconds = 60;
},
// 重置表单外的状态(如果需要)
resetFormState() {
this.isBankCardVerified = false;
this.clearCountdown();
},
// 实际执行绑卡操作
performBindBank() {
// 对于非中国大陆用户,或不需要验证码的情况,直接标记为已验证
// if (!this.isMainlandChinaUser || !this.needsVerificationCode) {
// this.isBankCardVerified = true;
// }
// if (!this.isBankCardVerified) {
// this.$message({
// message: "请先完成银行卡验证", // 或 '银行卡验证不一致'
// type: "warning",
// });
// return;
// }
// let that = this; // 不再需要
walletApi
.bindWalletBankAdd(this.form)
.then(() => {
this.$message({
message: "银行卡绑定成功",
type: "success",
});
// 成功后关闭对话框,并触发成功回调
setTimeout(() => {
// this.resetFormAndValidation(); // 已移至 watch 中处理关闭
// this.$emit("closeBind", 1); // 已移至 watch 中处理关闭
this.dialogVisible = false; // 关闭对话框
}, 1500);
})
.catch((_err) => {
// 添加错误处理
console.error("绑定银行卡失败:", _err);
this.$message({
message: "银行卡绑定失败,请稍后重试",
type: "error",
});
});
},
// 提交表单(验证 + 绑卡)
submitBankForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
// 如果是中国大陆用户且需要验证码
// if (this.isMainlandChinaUser && this.needsVerificationCode) {
// walletApi
// .verifyBankCard(this.form)
// .then(() => {
// // 验证成功,标记状态并执行绑卡
// this.isBankCardVerified = true;
// this.performBindBank();
// })
// .catch((_err) => {
// // 使用 _err 表示未使用
// // 验证失败
// this.isBankCardVerified = false;
// // 提示后端返回的错误信息,或通用错误信息
// this.$message({
// message: _err?.msg || "银行卡验证失败", // 优先使用后端消息
// type: "warning",
// });
// // this.countdownSeconds = 0; // 不应在此重置倒计时,应在 clearCountdown 中处理
// this.clearCountdown(); // 验证失败时也应该能重新获取验证码
// });
// } else {
// // 非中国大陆用户或不需要验证码,直接尝试绑卡
// // isBankCardVerified 在 performBindBank 开始时会设置为 true
// this.performBindBank();
// }
this.performBindBank();
} else {
console.log("表单验证失败!");
return false;
}
});
},
// 发送验证码并启动倒计时
sendVerificationCode() {
if (!this.form.phone) {
this.$message({
message: "请先输入手机号",
type: "warning",
});
return;
}
if (this.isSendingCode) return; // 防止重复点击
this.isSendingCode = true;
this.verificationCodeButtonText = `${this.countdownSeconds}s后重新发送`;
this.countdownTimer = setInterval(() => {
this.countdownSeconds--;
if (this.countdownSeconds <= 0) {
this.clearCountdown(); // 使用统一的清理函数
} else {
this.verificationCodeButtonText = `${this.countdownSeconds}s后重新发送`;
}
}, 1000);
// 调用发送验证码接口
walletApi
.getVerification({ phone: this.form.phone })
.then(() => {
this.$message({
message: "验证码已发送",
type: "success",
});
})
.catch((_err) => {
// 添加错误处理
console.error("发送验证码失败:", _err);
// this.$message({
// message: "验证码发送失败,请稍后重试",
// type: "error",
// });
this.clearCountdown(); // 发送失败时重置按钮状态
});
},
},
};
</script>
<style lang="scss" scoped>
// 统一管理表单容器样式
.bind-bank-form-container {
padding: 20px 30px; // 调整内边距
// 使用深度选择器影响 Element UI 内部元素
::v-deep .el-form-item {
margin-bottom: 22px; // 统一表单项间距
padding-bottom: 8px; // 增加底部内边距
display: flex; // 确保 label 和 content 在一行
align-items: center; // 垂直居中对齐
.el-form-item__label {
padding-right: 12px; // 标签右侧留空
color: #333; // 标签颜色
}
.el-form-item__content {
flex: 1; // 内容区域占据剩余空间
margin-left: 0 !important; // 覆盖 Element UI 默认的 margin
display: flex; // 使 input 和按钮等可以在一行显示
align-items: center; // 垂直居中对齐内部元素
}
.el-input,
.el-select {
flex: 1; // 输入框/选择框占据主要空间
width: auto; // 覆盖固定宽度
}
// .el-input__inner, .el-select .el-input__inner {
// border: none; // 移除内部输入框边框
// padding-left: 0; // 移除左侧内边距
// &:focus {
// box-shadow: none; // 移除聚焦时的阴影
// }
// }
// // 移除选择框外层边框(如果需要完全无边框)
// .el-select .el-input.is-focus .el-input__inner {
// border: none !important;
// }
// .el-select .el-input__inner:focus {
// border-color: transparent !important; // Element UI 可能有特定样式,尝试覆盖
// }
}
// 最后一个表单项移除下边框
::v-deep .el-form-item:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
}
// 验证码按钮样式
.verification-code-button {
background-color: #d5251d; // 主题色
color: #ffffff;
border-radius: 4px; // 圆角调整
padding: 6px 12px; // 内边距调整
font-size: 12px; // 字体大小调整
cursor: pointer;
white-space: nowrap; // 防止文字换行
margin-left: 10px; // 与输入框的间距
transition: background-color 0.3s, opacity 0.3s; // 过渡效果
&:hover {
background-color: #c02018; // Hover 颜色加深
}
// 禁用状态样式
&.is-disabled {
opacity: 0.6;
cursor: not-allowed;
background-color: #fab6b6; // 禁用时颜色变浅
&:hover {
background-color: #fab6b6; // 禁用时 Hover 颜色不变
}
}
}
// 对话框底部按钮区域样式
.dialog-footer {
display: flex;
justify-content: space-around; // 按钮均匀分布
padding: 20px 30px 30px; // 底部区域内边距
border-top: 1px solid #f0f0f0; // 添加顶部边框分隔
.btn {
width: 160px; // 按钮宽度调整
height: 45px; // 按钮高度调整
border-radius: 6px;
display: flex; // 使用 flex 居中文字
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s; // 添加过渡效果
}
.confirm-btn {
background-color: #d5251d; // 主题色
color: #ffffff;
&:hover {
background-color: #c02018;
}
}
.cancel-btn {
background-color: #f5f5f5; // 取消按钮背景色
color: #666; // 取消按钮文字颜色
border: 1px solid #e0e0e0; // 添加边框
&:hover {
background-color: #eeeeee;
}
}
}
// 对话框标题加粗Element UI 默认可能已处理)
::v-deep .el-dialog__title {
font-weight: 500;
}
</style>