<template>
  <!-- 两步验证 -->
  <a-modal
    centered
    v-model="visible"
    @cancel="handleCancel"
    :maskClosable="false"
  >
    <div slot="title" :style="{ textAlign: 'center' }">两步验证</div>
    <template slot="footer">
      <div :style="{ textAlign: 'center' }">
        <a-button key="back" @click="handleCancel">返回</a-button>
        <a-button key="submit" type="primary" :loading="stepLoading" @click="handleStepOk">
          继续
        </a-button>
      </div>
    </template>

    <a-spin :spinning="stepLoading">
      <a-form layout="vertical" :auto-form-create="(form)=>{this.form = form}">
        <div class="step-form-wrapper">
          <p style="text-align: center" v-if="!stepLoading">请在手机中打开 Google Authenticator 或两步验证 APP<br />输入 6 位动态码</p>
          <p style="text-align: center" v-else>正在验证..<br/>请稍后</p>
          <a-form-item
            :style="{ textAlign: 'center' }"
            hasFeedback
            fieldDecoratorId="stepCode"
            :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入 6 位动态码!', pattern: /^\d{6}$/, len: 6 }]}"
          >
            <a-input :style="{ textAlign: 'center' }" @keyup.enter.native="handleStepOk" placeholder="000000" />
          </a-form-item>
          <p style="text-align: center">
            <a @click="onForgeStepCode">遗失手机?</a>
          </p>
        </div>
      </a-form>
    </a-spin>
  </a-modal>
</template>

<script>
export default {
  props: {
    // 定义 visible 属性，类型为布尔值，用于接收外部传入的模态框显示隐藏状态，默认值为 false，表示默认情况下模态框是隐藏的，外部可以通过传入 true 来显示模态框，实现了从外部控制模态框显示与否的功能，通过 v-model 双向绑定与模板中的 a-modal 组件关联起来。
    visible: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      // 定义 stepLoading 属性，用于控制表单提交验证等操作过程中的加载状态显示，初始值为 false，表示初始状态下没有正在进行的加载操作，当执行验证相关操作时会将其设置为 true 来显示加载动画（通过模板中相关组件的绑定来实现视觉效果），验证完成后再根据结果设置回 false。
      stepLoading: false,
      // 定义 form 属性，初始值为 null，通过模板中 a-form 组件的 :auto-form-create 绑定的函数，会将实际的表单实例赋值给这个属性，方便后续在组件内部对表单进行验证等操作，比如调用表单的验证方法来检查用户输入是否符合要求。
      form: null
    }
  },
  methods: {
    handleStepOk () {
      const vm = this;
      // 当点击 "继续" 按钮（通过模板中按钮绑定的事件触发该方法），先将 stepLoading 属性设置为 true，使得按钮显示加载状态（如显示旋转的加载动画等），同时告知用户正在进行验证操作。
      this.stepLoading = true;
      // 调用表单实例（this.form）的 validateFields 方法来验证表单输入内容是否符合之前设置的验证规则（比如输入的是否是 6 位数字等），该方法接收一个回调函数，回调函数有两个参数，err 表示验证是否出错（如果为 null 则表示验证通过，否则表示有验证错误），values 表示表单输入的各个字段的值组成的对象。
      this.form.validateFields((err, values) => {
        if (!err) {
          // 如果验证通过（err 为 null），在控制台打印出 values 对象（包含用户输入的表单数据），方便调试查看输入内容，然后通过 setTimeout 设置一个 2 秒的定时器，模拟一个异步验证操作完成后的后续处理（比如向服务器发送验证请求并等待响应等场景），在定时器回调函数中，将 stepLoading 属性设置回 false，表示验证完成，停止加载动画显示，并且通过 $emit 触发 'success' 事件，将包含验证通过的表单值（values）的对象传递出去，以便父组件可以监听这个事件并进行相应的业务逻辑处理，比如跳转到下一步操作页面等。
          console.log('values', values);
          setTimeout(() => {
            vm.stepLoading = false;
            vm.$emit('success', { values });
          }, 2000);
          return;
        }
        // 如果验证出错（err 不为 null），将 stepLoading 属性设置回 false，停止加载动画显示，然后通过 $emit 触发 'error' 事件，将包含验证错误信息（err）的对象传递出去，以便父组件可以监听这个事件并进行相应的提示用户重新输入等业务逻辑处理。
        this.stepLoading = false;
        this.$emit('error', { err });
      });
    },
    handleCancel () {
      // 当点击 "返回" 按钮或者模态框的取消操作按钮（通过模板中按钮和模态框事件绑定触发该方法），将 visible 属性设置为 false，隐藏模态框，同时通过 $emit 触发 'cancel' 事件，通知父组件模态框已被取消关闭，父组件可以根据这个事件进行相应的逻辑处理，比如恢复之前的页面状态等。
      this.visible = false;
      this.$emit('cancel');
    },
    onForgeStepCode () {
      // 该方法目前函数体为空，从模板中绑定的事件来看，可能后续用于处理用户点击 "遗失手机?" 链接时的相关逻辑，比如显示提示信息引导用户如何找回验证方式、联系客服等操作相关的逻辑，具体功能需要根据业务需求来完善。
    }
  }
}
</script>
<style lang="less" scoped>
// 对类名为 "step-form-wrapper" 的元素设置样式规则，以下是具体的样式属性说明。
.step-form-wrapper {
  // 设置元素在水平方向上自动居中，通过设置左右外边距为 auto，使得该元素在父元素中能水平居中显示，常用于将内容块在页面中放置在较为居中的位置，视觉上更加美观和平衡。
  margin: 0 auto;
  // 设置元素的宽度为父元素宽度的 80%，但同时限制最大宽度不超过 400px，这样既可以保证在较宽的页面中元素能有合适的宽度占比，又能防止在大屏幕等情况下元素过宽影响视觉效果，使表单内容在不同屏幕尺寸下都能保持较好的展示效果。
  width: 80%;
  max-width: 400px;
}
</style>
