liveh5-nuxt/app/pages/collectCode/login/index.vue

245 lines
8.6 KiB
Vue
Raw Normal View History

2025-01-23 06:11:41 +00:00
<script setup>
2025-02-24 06:54:10 +00:00
import {useRouter, useRoute} from 'vue-router';
import {useI18n} from 'vue-i18n'
import {senCode, userLogin} from "@/api/auth/index.js";
import {codeAuthStore} from "@/stores-collect-code/auth/index.js";
import {message} from '@/components/x-message/useMessage.js'
2025-01-23 06:11:41 +00:00
// ... 现有导入 ...
import FingerprintJS from '@fingerprintjs/fingerprintjs'
import {checkPhone, mobileLogin, userSend} from "@/api-collect-code/auth/index.js";
2025-02-24 06:54:10 +00:00
const {userInfo, codeToken, fingerprint} = codeAuthStore()
2025-01-23 06:11:41 +00:00
const router = useRouter();
const route = useRoute();
2025-02-24 06:54:10 +00:00
const {locale} = useI18n()
2025-01-23 06:11:41 +00:00
const loadingRef = ref({
loading1: false,
loading2: false,
})
const password = ref('')
const loginType = ref(0)
const interval = ref(null)
const startCountdown = () => {
if (interval.value) {
clearInterval(interval.value);
}
countdown.value = 60;
interval.value = setInterval(() => {
if (countdown.value > 0) {
countdown.value--;
} else {
clearInterval(interval.value);
}
}, 1000);
}
const countdown = ref(0);
const phoneNum = ref('')
const code = ref('')
2025-01-23 06:11:41 +00:00
const pane = ref(0)
const getFingerprint = async () => {
const fp = await FingerprintJS.load()
const result = await fp.get()
return result.visitorId // 稳定的指纹哈希值
}
// 如果指纹存在,且指纹和指纹库中的指纹一致,则直接登录
const checkFingerprint = async () => {
const tempFingerprint = await getFingerprint()
if (fingerprint && fingerprint === tempFingerprint) {
await router.push('/collectCode/mine')
}
}
const codeInput = ref(null)
const isFocused = ref(false)
2025-01-23 06:11:41 +00:00
checkFingerprint()
const vanSwipeRef = ref(null)
const getCode = async () => {
loadingRef.value.loading1 = true
try {
const res = await checkPhone({
tel: phoneNum.value,
})
2025-02-24 06:54:10 +00:00
if (res.status === 0) {
const sendRes = await userSend({telNum: phoneNum.value, zone: '+86'})
startCountdown()
pane.value = 1
await nextTick()
vanSwipeRef.value?.swipeTo(pane.value)
2025-03-02 09:21:17 +00:00
}
} catch (error) {
console.error('获取验证码失败:', error)
} finally {
loadingRef.value.loading1 = false
}
2025-01-23 06:11:41 +00:00
}
const changeToPwd = async () => {
loginType.value = loginType.value === 0 ? 1 : 0
}
const goBack = () => {
code.value = ''
pane.value = 0
vanSwipeRef.value?.swipeTo(pane.value)
}
const goLogin = async () => {
loadingRef.value.loading2 = true
const res = await mobileLogin({
TelNum: phoneNum.value,
2025-02-24 06:54:10 +00:00
Password: loginType.value === 1 ? password.value : '',
Code: loginType.value === 0 ? code.value : ''
2025-01-23 06:11:41 +00:00
})
if (res.status === 0) {
userInfo.value = res.data.accountInfo
codeToken.value = res.data.token
2025-01-23 06:11:41 +00:00
fingerprint.value = await getFingerprint()
await router.push('/collectCode/mine');
2025-02-24 06:54:10 +00:00
2025-01-23 06:11:41 +00:00
}
loadingRef.value.loading2 = false
}
2025-02-24 06:54:10 +00:00
const showPassword = ref(false)
2025-01-23 06:11:41 +00:00
2025-02-24 06:54:10 +00:00
const togglePasswordVisibility = () => {
showPassword.value = !showPassword.value
}
2025-01-23 06:11:41 +00:00
</script>
<template>
<div class="grow-1 w-[100vw] bg-[url('@/static/images/asdfsdd.png')] bg-bottom bg-cover px-[31px] pt-[86px]">
2025-01-23 06:11:41 +00:00
<div class="w-full flex justify-center mb-[100px] flex-col items-center">
<img class="h-[105px] w-[189px]" src="@/static/images/ghfggff.png" alt="">
<img class="h-[29px] w-[108px]" src="@/static/images/qrcodetext.png" alt="">
</div>
<van-swipe ref="vanSwipeRef" :show-indicators="false" :touchable="false" :lazy-render="true" :loop="false">
<van-swipe-item>
<div v-if="pane === 0">
<div>
<div class="">
<div class="border-b-[1.7px] mt-[8px]">
<van-field v-model="phoneNum" clearable :placeholder="$t('collectCode.login.phoneNumberPlaceholder')">
<template #label>
<div class="text-[16px] text-[#1A1A1A] flex align-center justify-start">
{{ $t('collectCode.login.phoneNumber') }}
</div>
</template>
</van-field>
</div>
<div class="border-b-[1.7px] mt-[8px]" v-if="loginType === 1">
<van-field
v-model="password"
:type="showPassword ? 'text' : 'password'"
clearable
:placeholder="$t('collectCode.login.passwordPlaceholder')"
>
<template #label>
<div class="text-[16px] text-[#1A1A1A] flex align-center justify-start">
{{ $t('collectCode.login.password') }}
</div>
</template>
<template #button>
<div class="flex justify-center items-center">
<van-icon
size="20"
:name="showPassword ? 'eye-o' : 'closed-eye'"
@click="togglePasswordVisibility"
/>
</div>
</template>
</van-field>
</div>
<div class="flex justify-end mt-[10px]">
<div class="text-[14px] text-[#2B53AC]" @click="changeToPwd">
{{ loginType === 0 ? $t('collectCode.login.passwordLogin') : $t('collectCode.login.codeLogin') }}
</div>
2025-01-23 06:11:41 +00:00
</div>
</div>
<div class="mt-[55px]">
<div v-if="loginType === 0">
<van-button :loading="loadingRef.loading1" v-if="phoneNum" :loading-text="$t('collectCode.login.getCode')"
type="primary" block style="height: 48px" @click="getCode">{{
$t('collectCode.login.getCode')
}}
</van-button>
<van-button v-else type="primary" color="#D3D3D3" block style="height: 48px">
{{ $t('collectCode.login.getCode') }}
</van-button>
</div>
<div v-else>
<van-button type="primary" v-if="password" block :loading="loadingRef.loading2"
:loading-text="$t('collectCode.login.login')"
style="height: 48px;margin-top:10px" @click="goLogin">{{ $t('collectCode.login.login') }}
</van-button>
<van-button v-else type="primary" color="#D3D3D3" block style="height: 48px">
{{ $t('collectCode.login.login') }}
</van-button>
</div>
2025-01-23 06:11:41 +00:00
</div>
</div>
</div>
</van-swipe-item>
<van-swipe-item>
<div v-if="pane == 1">
<div>
<div class="flex mb-[16px]">
<div class="text-[16px] text-[#BDBDBD] mr-[10px]">{{ $t('collectCode.login.hasSendTo') }}</div>
<div class="text-[16px] text-[#000]">+86 {{ phoneNum }}</div>
</div>
<div class="relative">
<van-password-input
:value="code"
:gutter="10"
:mask="false"
:focused="isFocused"
/>
<input
v-model="code"
type="tel"
maxlength="6"
ref="codeInput"
2025-03-02 09:21:17 +00:00
class="opacity-0 absolute top-0 left-0 h-full w-full z-999"
@input="code = $event.target.value.replace(/\D/g, '').slice(0, 6)"
@focus="isFocused = true"
@blur="isFocused = false"
/>
</div>
<div class="flex justify-between">
<div :class="`${countdown>0?'text-#BDBDBD':'text-#2B53AC'} text-14px`">
{{ $t('collectCode.login.reSend') }}<span v-if="countdown>0">({{ countdown }})</span>
</div>
<div @click="goBack" class="text-#2B53AC text-14px">
{{ $t('collectCode.login.back') }}
</div>
</div>
<div class="mt-[17px]">
<van-button v-if="code.length === 6" type="primary" block :loading="loadingRef.loading2"
:loading-text="$t('collectCode.login.login')" style="height: 48px" @click="goLogin">
{{ $t('collectCode.login.login') }}
</van-button>
<van-button v-else type="primary" color="#D3D3D3" block style="height: 48px">
{{ $t('collectCode.login.login') }}
</van-button>
</div>
2025-01-23 06:11:41 +00:00
</div>
</div>
</van-swipe-item>
</van-swipe>
</div>
</template>
<style scoped lang="scss">
:deep(.van-cell.van-field) {
padding-left: 0;
}
:deep(.van-password-input) {
margin: 0;
}
:deep(.van-password-input__item) {
border: 1px solid #E5E5E5;
width: 41px;
height: 41px;
}
</style>