|
@@ -0,0 +1,141 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <v-form @submit.prevent ref="phoneForm">
|
|
|
+ <v-text-field v-model="loginData.phone" placeholder="请输入手机号" color="#00897B" variant="outlined" density="compact" :rules="phoneRules" validate-on="input">
|
|
|
+ <template v-slot:prepend-inner>
|
|
|
+ <span class="d-flex">
|
|
|
+ <v-icon icon="mdi-cellphone" size="20"></v-icon>
|
|
|
+ <span class="d-flex" id="menu-activator">
|
|
|
+ <span class="phone-number">{{ currentArea }}</span>
|
|
|
+ <v-icon size="20">mdi-chevron-down</v-icon>
|
|
|
+ </span>
|
|
|
+ <v-menu activator="#menu-activator">
|
|
|
+ <v-list>
|
|
|
+ <v-list-item v-for="(item, index) in items" :key="index" :value="index" @click="handleChangeCurrentArea(item)">
|
|
|
+ <v-list-item-title>{{ item.label }}</v-list-item-title>
|
|
|
+ </v-list-item>
|
|
|
+ </v-list>
|
|
|
+ </v-menu>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </v-text-field>
|
|
|
+ <v-text-field v-model="loginData.code" placeholder="请输入验证码" color="#00897B" variant="outlined" density="compact" prepend-inner-icon="mdi-security" :rules="[v=> !!v || '请填写验证码']">
|
|
|
+ <template #append-inner>
|
|
|
+ <span v-if="showCode" class="login-code" @click="handleCode">获取验证码</span>
|
|
|
+ <span v-else class="disable">重新获取{{ count }}s</span>
|
|
|
+ </template>
|
|
|
+ </v-text-field>
|
|
|
+ </v-form>
|
|
|
+ <v-snackbar v-model="tips.show" :color="tips.color" :timeout="1500" location="top">{{ tips.text }}</v-snackbar>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+defineOptions({ name: 'verification-code' })
|
|
|
+import { ref, reactive, defineExpose } from 'vue'
|
|
|
+import { setCodeTime } from '@/utils/code'
|
|
|
+import { sendSmsCode } from '@/api/common/index'
|
|
|
+
|
|
|
+const phoneRules = ref([
|
|
|
+ value => {
|
|
|
+ if (value) return true
|
|
|
+ return '请输入手机号'
|
|
|
+ },
|
|
|
+ value => {
|
|
|
+ if (value?.length <= 11 && /^1[3456789]\d{9}$/.test(value)) return true
|
|
|
+ return '请输入正确的手机号码'
|
|
|
+ }
|
|
|
+])
|
|
|
+
|
|
|
+const tips = reactive({
|
|
|
+ show: false,
|
|
|
+ color: '',
|
|
|
+ text: ''
|
|
|
+})
|
|
|
+
|
|
|
+// 手机号区域
|
|
|
+const currentArea = ref('0086')
|
|
|
+const items = [
|
|
|
+ { label: '中国大陆-0086', value: '0086' }
|
|
|
+]
|
|
|
+const handleChangeCurrentArea = (e) => {
|
|
|
+ currentArea.value = e.value
|
|
|
+}
|
|
|
+
|
|
|
+// 获取验证码
|
|
|
+const showCode = ref(true)
|
|
|
+const count = ref(0)
|
|
|
+const timer = ref(null)
|
|
|
+const handleCode = () => {
|
|
|
+ if (!loginData.phone) {
|
|
|
+ tips.text = '请输入手机号码'
|
|
|
+ tips.color = 'warning'
|
|
|
+ tips.show = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ count.value = 60
|
|
|
+ setTime()
|
|
|
+ getSmsCode()
|
|
|
+}
|
|
|
+const getSmsCode = async () => {
|
|
|
+ const query = {
|
|
|
+ phone: loginData.phone,
|
|
|
+ scene: 30
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ await sendSmsCode(query)
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error, 'error')
|
|
|
+ }
|
|
|
+}
|
|
|
+const setTime = () => {
|
|
|
+ showCode.value = false
|
|
|
+ timer.value = setInterval(() => {
|
|
|
+ let number = count.value
|
|
|
+ if (number > 0 && number <= 60) {
|
|
|
+ count.value--
|
|
|
+ setCodeTime(number - 1)
|
|
|
+ } else {
|
|
|
+ showCode.value = true
|
|
|
+ clearInterval(timer.value)
|
|
|
+ timer.value = null
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
+}
|
|
|
+const autoTimer = () => {
|
|
|
+ count.value = 0
|
|
|
+ if(!count.value) return
|
|
|
+ setTime()
|
|
|
+}
|
|
|
+autoTimer()
|
|
|
+
|
|
|
+const loginData = reactive({
|
|
|
+ phone: '13229740091',
|
|
|
+ code: ''
|
|
|
+})
|
|
|
+
|
|
|
+const phoneForm = ref()
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ loginData,
|
|
|
+ phoneForm
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.login-code {
|
|
|
+ width: 62px;
|
|
|
+ color: var(--default-color);
|
|
|
+ font-size: 12px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+.disable {
|
|
|
+ width: 72px;
|
|
|
+ color: grey;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+.phone-number {
|
|
|
+ width: 34px;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+</style>
|