From 65290af1ead6b8a344e951a31f3448b3c8c1714f Mon Sep 17 00:00:00 2001 From: renhaoting <370797079@qq.com> Date: Thu, 27 Nov 2025 16:47:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=B4=E8=A5=BF=E5=90=88=E6=B3=95=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7binding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vididin/features/withdraw/BankUtil.kt | 51 +++++++++++++++++++ .../withdraw/WithdrawBindBankDialog.kt | 51 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 app/src/main/java/com/gamedog/vididin/features/withdraw/BankUtil.kt diff --git a/app/src/main/java/com/gamedog/vididin/features/withdraw/BankUtil.kt b/app/src/main/java/com/gamedog/vididin/features/withdraw/BankUtil.kt new file mode 100644 index 0000000..eeb50c1 --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/features/withdraw/BankUtil.kt @@ -0,0 +1,51 @@ +package com.gamedog.vididin.features.withdraw + +object BankUtil { + + /** + * 验证输入的巴西CPF号码是否合法。 + * + * @param cpf 待验证的CPF字符串,可以包含分隔符(如 XXX.XXX.XXX-XX)或仅为纯数字。 + * @return 如果CPF格式正确且校验码有效则返回true,否则返回false。 + */ + fun isValidCpf(cpf: String?): Boolean { + if (cpf.isNullOrBlank()) { + return false + } + + // 1. 提取纯数字 + val cleanCpf = cpf.replace("[^\\d]".toRegex(), "") + + // 2. 初步格式验证:必须是11位数字,且不能所有数字相同(如111.111.111-11) + if (cleanCpf.length != 11 || cleanCpf.all { it == cleanCpf[0] }) { + return false + } + + // 3. 计算并验证第一个校验位 + val firstCheckDigit = calculateCheckDigit(cleanCpf, 9, 10) + if (firstCheckDigit != cleanCpf[9].toString().toInt()) { + return false + } + + // 4. 计算并验证第二个校验位 + val secondCheckDigit = calculateCheckDigit(cleanCpf, 10, 11) + return secondCheckDigit == cleanCpf[10].toString().toInt() + } + + /** + * 计算CPF的校验位。 + * + * @param digits 纯数字的CPF字符串。 + * @param length 参与计算的前几位数字的长度。 + * @param weight 起始权重。 + * @return 计算出的校验位数字。 + */ + private fun calculateCheckDigit(digits: String, length: Int, weight: Int): Int { + var sum = 0 + for (i in 0 until length) { + sum += digits[i].toString().toInt() * (weight - i) + } + val remainder = sum % 11 + return if (remainder < 2) 0 else 11 - remainder + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawBindBankDialog.kt b/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawBindBankDialog.kt index 9b2544d..e8342d0 100644 --- a/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawBindBankDialog.kt +++ b/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawBindBankDialog.kt @@ -2,8 +2,12 @@ package com.gamedog.vididin.features.withdraw import android.content.Context +import android.text.Editable +import android.text.TextWatcher +import androidx.core.view.isVisible import com.ama.core.architecture.util.setOnClickBatch import com.ama.core.architecture.widget.BindingDialog +import com.gamedog.vididin.R import com.gamedog.vididin.databinding.DialogWithdrawBindingBankBinding as ViewBinding import com.gamedog.vididin.router.Router @@ -29,6 +33,50 @@ class WithdrawBindBankDialog(context: Context) : BindingDialog(cont } } } + + + + tvCpfEdit.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + checkBankAccountValidation(s.toString()) + } + + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) { + } + + override fun onTextChanged( + s: CharSequence?, + start: Int, + before: Int, + count: Int + ) { + } + + }) + + + } + + checkBankAccountValidation("") + } + + private fun checkBankAccountValidation(bankAccount: String) { + // TODO - forTesting- contain "B" + if (BankUtil.isValidCpf(bankAccount) || bankAccount.contains("B")) { + mBinding.ivState.isVisible = true + mBinding.ivState.setImageResource(R.mipmap.icon_success) + mBinding.tvConfirm.alpha = 1F + mBinding.tvConfirm.isClickable = true + } else { + mBinding.ivState.isVisible = !bankAccount.isEmpty() + mBinding.ivState.setImageResource(R.mipmap.icon_fail) + mBinding.tvConfirm.alpha = 0.3F + mBinding.tvConfirm.isClickable = false } } @@ -36,6 +84,9 @@ class WithdrawBindBankDialog(context: Context) : BindingDialog(cont ownerActivity?.let { Router.Withdraw.startActivity(it) } } + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + } }