login.vue 6.01 KB
<template>
  <van-image width="100%" height="100%" :src="logo_image" />
  <div class="login-header">
    <van-row align="center">
      <van-col span="8">
      </van-col>
      <van-col span="8" class="title">
        <p>登&nbsp;录</p>
      </van-col>
      <van-col span="8">
      </van-col>
    </van-row>
  </div>
  <div class="login-section">
    <van-config-provider :theme-vars="themeVars">
      <van-form ref="form" @submit="onSubmit">
        <van-cell-group inset style="border: 1px solid #EAEAEA;">
          <van-field v-if="use_widget" v-model="phone" name="phone" label="手机号" placeholder="手机号" readonly clickable
            @touchstart.stop="showKeyboard" />
          <van-field v-else v-model="phone" name="phone" label="手机号" placeholder="手机号"
            :rules="[{ validator, message: '请输入正确手机号' }]" />
          <van-field v-model="code" center clearable name="code" label="短信验证码" placeholder="请输入短信验证码"
            :formatter="formatter" :rules="[{ required: true, message: '请填写验证码' }]">
            <template #button>
              <van-button @click="sendCode" v-if="countDown.current.value.total === limit" size="small" type="primary" :disabled="disabled">
                <span>发送验证码</span>
              </van-button>
              <van-button v-else size="small" type="primary" :disabled="disabled">
                <span>{{ countDown.current.value.seconds }} 秒重新发送</span>
              </van-button>
            </template>
          </van-field>
        </van-cell-group>
        <div class="btn" @click="submit">
          登&nbsp;录
        </div>
      </van-form>
    </van-config-provider>
  </div>

  <van-number-keyboard v-model="phone" :show="keyboard_show" :maxlength="11" @blur="onBlur" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { Toast } from 'vant'
import { useRoute, useRouter } from 'vue-router'
import axios from '@/utils/axios'
import logo_image from '@images/zhengshu-banner@2x.png'
import { wxInfo } from '@/utils/tools';

import { useCountDown } from '@vant/use';

const $route = useRoute();
const $router = useRouter();

// 判断是否显示控件
let use_widget = ref(true);
/**
 * 手机号码校验
 * 函数返回 true 表示校验通过,false 表示不通过
 * @param {*} val 
 */
const validator = (val) => {
  let flag = false;
  // 简单判断手机号位数
  if (/1\d{10}/.test(val) && phone.value.length === 11) {
    disabled.value = false;
    flag = true;
  } else {
    disabled.value = true;
    flag = false;
  }
  return flag
};


const phone = ref('');
const code = ref('');
// TAG: 开发环境测试数据
if (import.meta.env.DEV) {
  phone.value = import.meta.env.VITE_ID
  code.value = import.meta.env.VITE_PIN
}

onMounted(() => {
  /**
   * 判断微信环境看是否弹出控件框
   * 桌面微信直接输入
   * 其他环境弹出输入框
   */
  if (wxInfo().isiOS || wxInfo().isAndroid) {
    use_widget.value = true;
  } else {
    use_widget.value = false;
  }
})

// 手机号输入控件控制
const keyboard_show = ref(false);
const showKeyboard = () => { // 弹出数字弹框
  keyboard_show.value = true;
};
const onBlur = () => { // 数字键盘失焦回调
  keyboard_show.value = false;
  if (phone.value.length === 11) {
    disabled.value = false;
  }
};

// 设置发送短信倒计时
// const countDown = ref(60);
// const countDownHandle = () => {
//   // 倒计时
//   if (countDown.value === 0) {
//     countDown.value = 60;
//   } else {
//     countDown.value--;
//     setTimeout(() => {
//       countDownHandle()
//     }, 1000)
//   }
// }

// 设置发送短信倒计时
// TAG: vant 自带倒计时函数
const limit = ref(60000); // 配置倒计时秒数
const countDown = useCountDown({
  // 倒计时 24 小时
  time: limit.value,
  onFinish: () => {
    countDown.reset();
  }
});

const sendCode = () => { // 发送验证码
  countDown.start();
  // TODO: 验证码接口
  axios.post('/srv/?a=bind_phone&t=get_code', {
    phone: phone.value
  })
    .then(res => {
      if (res.data.code === 1) {
        Toast.success('发送成功');
      } else {
        console.warn(res.data);
        Toast({
          message: res.data.msg,
          icon: 'close',
        });
      }
    })
    .catch(err => {
      console.error(err);
    })
};

const disabled = ref(true);
// 过滤输入的数字 只能四位
const formatter = (value) => value.substring(0, 4);

/**
 * 用户登录
 * @param {*} values 
 */

const onSubmit = (values) => {
  axios.post('/srv/?a=b_login', {
    phone: values.phone,
    pin: values.code,
  })
    .then(res => {
      if (res.data.code === 1) {
        $router.push({
          path: '/business/index'
        });
      } else {
        console.warn(res.data);
        Toast({
          message: res.data.msg,
          icon: 'close',
        });
      }
    })
    .catch(err => {
      console.error(err);
    })
};

const themeVars = {
  buttonPrimaryBackground: '#F9D95C',
  buttonPrimaryBorderColor: '#F9D95C',
  buttonPrimaryColor: '#713610',
};
</script>

<script>
// FIXME: VUE2写法
import mixin from 'common/mixin';

export default {
  mixins: [mixin.init],
  data() {
    return {

    }
  },
  mounted() {

  },
  methods: {
    submit() {
      let valid = this.$refs.form.validate();
      valid
        .then(() => {
          this.$refs.form.submit();
        })
        .catch(error => {
          console.error(error);
          this.$toast({
            message: '请检查后再次提交',
            icon: 'cross',
          });
        })
    }
  },
}
</script>

<style lang="less" scoped>
body {
  --van-button-primary-background: white;
}

.login-header {
  margin-bottom: 1rem;

  .title {
    text-align: center;
    margin-top: 2vh;

    p {
      font-size: 2.5vh;
      margin: 1vh;
    }
  }
}

.login-section {

  // background-color: #FAFAFA;
  .btn {
    margin: 16px;
    background-color: #F9D95C;
    text-align: center;
    color: #713610;
    font-size: 2vh;
    padding: 1vh;
    border-radius: 5px;
  }
}
</style>