石广澎
2025-11-30 55ee7bd313c7d8030ce8c547b18ad5f19507afd2
pages/pay/bindCard/bindCard.vue
New file
@@ -0,0 +1,392 @@
<template>
   <view>
      <view class="u-font-42 font-bold u-text-center u-m-t-30">添加银行卡</view>
      <view class="u-font-28 u-text-center u-m-t-10 u-m-b-60">填写以下信息进行绑卡</view>
      <u--form class="" labelWidth="80" :model="form" :rules="rules" ref="uForm">
         <u-form-item class="form-item u-m-b-24" label="持卡人" prop="acctName">
            <u--input v-model="form.acctName" inputAlign="right" border="none" :readonly="userInfo.tlAuthName" placeholder="请输入持卡人姓名"></u--input>
         </u-form-item>
         <u-form-item class="form-item u-m-b-24" label="身份证号" prop="idNo">
            <u--input v-model="form.idNo" inputAlign="right" border="none" :readonly="userInfo.tlAuthIdentityNo" placeholder="请输入持卡人身份证号"></u--input>
         </u-form-item>
         <u-form-item class="form-item u-m-b-24" label="手机号" prop="mobile">
            <u--input v-model="form.mobile" inputAlign="right" border="none" placeholder="请输入手机号"></u--input>
         </u-form-item>
         <view class="u-font-30 color-333 u-m-t-60 u-m-b-24">银行卡类别</view>
         <view class="u-flex u-row-between u-m-b-24">
            <view @click="chooseType('DC')" :class="['type-btn',{'type-act':cardType=='DC'}]">储蓄卡
            </view>
            <view @click="chooseType('CC')" :class="['type-btn',{'type-act':cardType=='CC'}]">信用卡
            </view>
         </view>
         <u-form-item class="form-item u-m-b-24" label="卡号" prop="cardNo">
            <u--input v-model="form.cardNo" inputAlign="right" border="none" placeholder="请输入持卡人本人银行卡号"></u--input>
         </u-form-item>
         <block v-if="cardType=='CC'">
            <u-form-item class="form-item u-m-b-24" label="有效期" prop="validdate">
               <u--input v-model="form.validdate" inputAlign="right" border="none" placeholder="请输入信用卡有效期">
               </u--input>
            </u-form-item>
            <u-form-item class="form-item u-m-b-24" label="安全码" prop="cvv2">
               <u--input v-model="form.cvv2" inputAlign="right" border="none" placeholder="请输入信用卡安全码"></u--input>
            </u-form-item>
         </block>
         <view class="u-flex u-m-b-24">
            <u-form-item class="form-item" label="验证码" prop="code">
               <u--input v-model="form.code" maxlength="6" inputAlign="right" border="none" placeholder="请输入验证码">
               </u--input>
            </u-form-item>
            <view @click="getCode" class="code-btn" :class="codeAct?'code-act':''">{{tips}}</view>
         </view>
      </u--form>
      <label @click="checked=!checked" class="u-flex u-font-24 color-999 u-m-t-30">
         <radio style="transform: scale(0.7);" color="#e93b3d" @change="radioChange" :checked="checked" />我已阅读并同意
         <view @click.stop="showAgreement=true" class="" style="color: #e93b3d;">《用户协议》</view>
      </label>
      <view class="u-m-b-60" style="opacity: 0;">
         <button class="bind-btn">立即绑卡</button>
      </view>
      <view class="btn-box">
         <button @click="doBind" :loading="loading" :disabled="loading" class="bind-btn">立即绑卡</button>
      </view>
      <!-- 用户协议 -->
      <u-popup @close="showAgreement=false" :show="showAgreement" mode="center" :round="30" closeable
         :safeAreaInsetBottom="false">
         <card-agreement @confirm="checked=true;showAgreement=false;doBind()"></card-agreement>
      </u-popup>
      <!-- 首绑有礼活动 -->
      <u-popup bgColor="transparent" @close="showAct=false" :show="showAct" mode="center" :round="30"
         :safeAreaInsetBottom="false">
         <bind-card-activity :couponList="couponList" @close="showAct = false"></bind-card-activity>
      </u-popup>
      <u-toast ref="uToast"></u-toast>
      <u-code :seconds="seconds" @end="end" @start="start" ref="uCode" keepRunning changeText="已发送(x)"
         @change="codeChange"></u-code>
   </view>
</template>
<script>
   import {
      isContain,
      signUpToApply,
      bindCard,
      getMyCoupUseDetail,
      getUserInfo
   } from '@/common/api/index'
   export default {
      data() {
         return {
            showAct: false,
            couponList: [],
            bankName: '',
            cardType: 'DC',
            tips: '',
            seconds: 60,
            codeAct: true,
            showAgreement: false,
            checked: true,
            loading: false,
            userInfo: {
               tlAuthIdentityNo: '',
               tlAuthName: ''
            },
            form: {
               acctName: '',
               idNo: '',
               cardNo: '',
               validdate: '',
               cvv2: '',
               mobile: '',
               code: ''
            },
            rules: {
               acctName: [{
                  required: true,
                  message: '持卡人姓名不能为空',
                  trigger: 'blur'
               }, {
                  // 自定义验证函数,见上说明
                  validator: (rule, value, callback) => {
                     // 上面有说,返回true表示校验通过,返回false表示不通过
                     // uni.$u.test.mobile()就是返回true或者false的
                     return uni.$u.test.rangeLength(value, [2, 6]) && uni.$u.test.chinese(value);
                  },
                  message: '持卡人姓名不正确',
                  trigger: 'change'
               }],
               idNo: [{
                  required: true,
                  message: '身份证号不能为空',
                  trigger: 'blur'
               }, {
                  // 自定义验证函数,见上说明
                  validator: (rule, value, callback) => {
                     // 上面有说,返回true表示校验通过,返回false表示不通过
                     // uni.$u.test.mobile()就是返回true或者false的
                     return uni.$u.test.idCard(value);
                  },
                  message: '身份证号不正确',
                  trigger: 'blur'
               }],
               mobile: [{
                  required: true,
                  message: '手机号不能为空',
                  trigger: 'blur'
               }, {
                  // 自定义验证函数,见上说明
                  validator: (rule, value, callback) => {
                     // 上面有说,返回true表示校验通过,返回false表示不通过
                     // uni.$u.test.mobile()就是返回true或者false的
                     return uni.$u.test.mobile(value);
                  },
                  message: '手机号不正确',
                  trigger: 'blur'
               }],
               cardNo: [{
                  required: true,
                  message: '卡号不能为空',
                  trigger: 'blur'
               }, {
                  // 自定义验证函数,见上说明
                  validator: (rule, value, callback) => {
                     // 上面有说,返回true表示校验通过,返回false表示不通过
                     // uni.$u.test.mobile()就是返回true或者false的
                     return this.$utils.verifyBankCard(value);
                  },
                  message: '卡号不正确',
                  trigger: 'blur'
               }, {
                  // 自定义验证函数,见上说明
                  asyncValidator: (rule, value, callback) => {
                     isContain({
                        params: {
                           cardNum: value
                        }
                     }).then(res => {
                        if (res) {
                           callback();
                        } else {
                           callback(new Error('卡号不在卡段内'));
                        }
                     }).catch(() => {
                        callback(new Error('卡号不在卡段内'));
                     })
                  },
                  trigger: 'blur'
               }],
               validdate: [{
                  required: true,
                  message: '有效期不能为空',
                  trigger: 'blur'
               }, {
                  len: 4,
                  message: '有效期不正确',
                  trigger: 'blur'
               }],
               cvv2: [{
                  required: true,
                  message: '安全码不能为空',
                  trigger: ['blur']
               }, {
                  min: 3,
                  max: 4,
                  message: '安全码长度为3-4',
                  trigger: 'blur'
               }]
            }
         };
      },
      onLoad() {
         const IS_NEW = uni.getStorageSync('IS_NEW')
         if(!IS_NEW){
            getUserInfo().then(res=>{
               if(res){
                  this.userInfo = res
                  this.form.mobile = res.mobile
                  this.form.acctName = res.tlAuthName||res.memberName
                  this.form.idNo = res.tlAuthIdentityNo||res.idcard
               }
            })
         }
      },
      onReady() {
         //如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则。
         this.$refs.uForm.setRules(this.rules)
      },
      methods: {
         codeChange(text) {
            this.tips = text;
         },
         end() {
            this.codeAct = true
         },
         start() {
            this.codeAct = false
         },
         // 发送验证码
         getCode() {
            if (this.$refs.uCode.canGetCode) {
               delete this.rules.code
               this.$refs.uForm.clearValidate();
               this.$refs.uForm.setRules(this.rules);
               this.$nextTick(() => {
                  this.$refs.uForm.validate().then(() => {
                     uni.showLoading({
                        title: '正在获取验证码'
                     })
                     const params = uni.$u.deepClone(this.form);
                     delete params.thpinfo
                     delete params.code
                     signUpToApply(params).then(res => {
                        this.form.thpinfo = JSON.stringify(res.thpinfo)
                        uni.hideLoading();
                        uni.$u.toast('验证码已发送');
                        // 通知验证码组件内部开始倒计时
                        this.$refs.uCode.start();
                     }).catch(() => {
                        uni.hideLoading();
                     })
                  })
               })
            } else {
               uni.$u.toast('倒计时结束后再发送');
            }
         },
         //选择银行卡类型
         chooseType(type) {
            this.cardType = type
         },
         //绑定银行卡
         doBind() {
            if (!this.checked) {
               this.showAgreement = true
               return
            }
            this.rules.code = [{
               required: true,
               message: '验证码不能为空',
               trigger: 'blur'
            }, {
               // 自定义验证函数,见上说明
               validator: (rule, value, callback) => {
                  // 上面有说,返回true表示校验通过,返回false表示不通过
                  // uni.$u.test.mobile()就是返回true或者false的
                  return uni.$u.test.code(value, 6);
               },
               message: '验证码格式不正确',
               trigger: 'blur'
            }]
            this.$refs.uForm.setRules(this.rules)
            this.$nextTick(() => {
               this.$refs.uForm.validate().then(() => {
                  this.loading = true
                  const params = uni.$u.deepClone(this.form);
                  if (this.cardType == 'DC') {
                     delete params.validdate
                     delete params.cvv2
                  }
                  bindCard(params).then(res => {
                     getMyCoupUseDetail().then(res => {
                        this.loading = false
                        if (res && res.length > 0) {
                           this.showAct = true
                           this.couponList = res
                        } else {
                           uni.showToast({
                              icon: 'success',
                              title: '绑卡成功',
                              mask: true
                           })
                           setTimeout(() => {
                              uni.navigateBack()
                           }, 1000)
                        }
                     }).catch(() => {
                        this.loading = false
                     })
                  }).catch(() => {
                     this.loading = false
                  })
               }).catch(errors => {
               })
            })
         }
      },
   }
</script>
<style>
   page {
      background-color: #fff;
      padding: 32rpx;
      color: #333;
   }
</style>
<style lang="scss" scoped>
   .form-item {
      border: 1px solid #D9D9D9;
      border-radius: 10rpx;
      padding: 4rpx 32rpx;
   }
   ::v-deep .u-form-item__body__right__message {
      text-align: right;
   }
   .btn-box {
      width: 686rpx;
      position: fixed;
      bottom: 30rpx;
   }
   .bind-btn {
      width: 686rpx;
      height: 98rpx;
      border-radius: 10rpx;
      background: #d31f28;
      color: #fff;
      font-size: 34rpx;
   }
   .code-btn {
      background-color: #F2F2F2;
      border-radius: 10rpx;
      color: #999;
      width: 290rpx;
      height: 88rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-left: 20rpx;
   }
   .code-act {
      background-color: #D31F28;
      color: #fff;
   }
   .type-btn {
      width: 333rpx;
      height: 88rpx;
      border-radius: 10rpx;
      border: 1px solid #d9d9d9;
      background-color: #ffffff;
      font-size: 30rpx;
      color: #333;
      text-align: center;
      line-height: 88rpx;
   }
   .type-act {
      font-weight: bold;
      border-color: #D31F28;
      color: #D31F28;
      background-image: url('~@/static/check-type.png');
      background-position: right bottom;
      background-repeat: no-repeat;
      background-size: 42rpx 38rpx;
   }
</style>