283 lines
6.3 KiB
Vue
283 lines
6.3 KiB
Vue
<template>
|
|
<!-- <view class="title_bar">
|
|
<Title-bar :titleCenter="true" :canBack="false" title="登录" />
|
|
</view> -->
|
|
<mj-page class="login_page">
|
|
<view class="title"> 欢迎使用学小乐 </view>
|
|
<view class="login_form">
|
|
<view class="login_form_item">
|
|
<view class="left">
|
|
<image
|
|
:src="`${OSS_URL}/iconfont/phone_icon.png`"
|
|
mode=""
|
|
class="login_form_item_icon"
|
|
></image>
|
|
<input
|
|
v-model="formatPhone"
|
|
class="input_box"
|
|
type="text"
|
|
placeholder="请输入手机号"
|
|
placeholder-style="color:rgba(169, 170, 181, 1);text-align: left;font-size:30rpx;"
|
|
@input="phoneDivision"
|
|
/>
|
|
</view>
|
|
</view>
|
|
<view class="login_form_item">
|
|
<view class="left">
|
|
<image
|
|
:src="`${OSS_URL}/iconfont/code_icon.png`"
|
|
mode=""
|
|
class="login_form_item_icon"
|
|
></image>
|
|
<input
|
|
v-model="verifyCode"
|
|
class="input_box"
|
|
type="number"
|
|
placeholder="请输入验证码"
|
|
placeholder-style="color:rgba(169, 170, 181, 1);text-align: left;font-size:30rpx;"
|
|
/>
|
|
</view>
|
|
<view class="code_btn">
|
|
<template v-if="codeTime > 0">
|
|
<text class="time_tip">{{ codeTimeContet }} 秒后重新发送</text>
|
|
</template>
|
|
<template v-else>
|
|
<text class="time_tip" @click="getCode">获取验证码</text>
|
|
</template>
|
|
</view>
|
|
</view>
|
|
<button class="phone_btn" @click="handleLogin">登录</button>
|
|
</view>
|
|
</mj-page>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, nextTick, onMounted } from 'vue'
|
|
|
|
import { sendCodeMessageApi, smsLoginApi, wxLoginApi } from '@/api'
|
|
import { useUserStore } from '@/store'
|
|
import router from '@/router/router'
|
|
import db from '@/utils/db'
|
|
import hud from '@/utils/hud'
|
|
|
|
const emits = defineEmits(['reloadFun'])
|
|
const OSS_URL = import.meta.env.VITE_OSS_HOST
|
|
const { getUserInfo, setToken } = useUserStore()
|
|
|
|
const formatPhone = ref('')
|
|
const verifyCode = ref('')
|
|
const codeTime = ref(0)
|
|
const codeTimeContet = computed(() => {
|
|
return codeTime.value
|
|
})
|
|
|
|
function validatePhone() {
|
|
let reg = /^[1][0,1,2,3, 4, 5, 6, 7, 8, 9][0-9]{9}$/
|
|
return reg.test(formatPhone.value.replace(/\s+/g, ''))
|
|
}
|
|
// 手机344分割
|
|
function phoneDivision() {
|
|
nextTick(() => {
|
|
let value = formatPhone.value.replace(/\D/g, '').substr(0, 11)
|
|
let len = value.length // 获取长度判断
|
|
if (len > 3 && len < 8) {
|
|
value = value.replace(/^(\d{3})/g, '$1 ')
|
|
} else if (len >= 8) {
|
|
value = value.replace(/^(\d{3})(\d{4})/g, '$1 $2 ')
|
|
}
|
|
formatPhone.value = value
|
|
})
|
|
}
|
|
|
|
// 获取验证码
|
|
async function getCode() {
|
|
if (!validatePhone()) {
|
|
hud.error('请输入正确的手机号')
|
|
return
|
|
}
|
|
try {
|
|
await sendCodeMessageApi(formatPhone.value.replace(/\s+/g, ''))
|
|
hud.success('发送成功!')
|
|
codeTime.value = 60
|
|
let timer = setInterval(() => {
|
|
codeTime.value--
|
|
if (codeTime.value < 1) {
|
|
clearInterval(timer)
|
|
codeTime.value = 0
|
|
}
|
|
}, 1000)
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
// 登录
|
|
async function handleLogin() {
|
|
if (!validatePhone() || !verifyCode.value) {
|
|
hud.error('账号或验证码不正确')
|
|
return
|
|
}
|
|
await smsLogin()
|
|
}
|
|
|
|
let wxUser: any
|
|
async function smsLogin() {
|
|
hud.load({
|
|
task: async () => {
|
|
const token = await smsLoginApi({
|
|
adminType: 16,
|
|
clientType: 'PARENT',
|
|
phone: formatPhone.value.replace(/\s+/g, ''),
|
|
verifyCode: verifyCode.value,
|
|
wxUser,
|
|
})
|
|
await loginSuccess(token)
|
|
},
|
|
option: '登录',
|
|
})
|
|
}
|
|
|
|
async function wxLogin() {
|
|
const code = db.get('code')
|
|
if (!code) {
|
|
return
|
|
}
|
|
// 移除code
|
|
db.pop('code')
|
|
|
|
hud.load({
|
|
task: async () => {
|
|
// 登录逻辑
|
|
const data = await wxLoginApi({
|
|
code,
|
|
})
|
|
// 存储openid
|
|
if (data.wxUser.openid) {
|
|
db.set('openid', data.wxUser.openid)
|
|
}
|
|
if (data.accessToken) {
|
|
// 说明已经有绑定过账号
|
|
await loginSuccess(data.accessToken)
|
|
} else {
|
|
// 说明没有绑定过账号
|
|
wxUser = data.wxUser
|
|
}
|
|
},
|
|
option: '登录',
|
|
})
|
|
}
|
|
|
|
async function loginSuccess(accessToken: any) {
|
|
setToken(accessToken)
|
|
await getUserInfo()
|
|
router.toHome()
|
|
}
|
|
|
|
onMounted(async () => {
|
|
// 清空token
|
|
db.pop('token')
|
|
|
|
// 尝试微信登录
|
|
wxLogin()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.title_bar {
|
|
z-index: 99;
|
|
}
|
|
|
|
.login_page {
|
|
margin-top: 120rpx;
|
|
|
|
.title {
|
|
margin-bottom: 87rpx;
|
|
line-height: 56rpx;
|
|
font-size: 40rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
text-align: center;
|
|
}
|
|
|
|
.login_form {
|
|
padding: 0 30rpx;
|
|
|
|
&_item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 24rpx 30rpx;
|
|
margin-bottom: 40rpx;
|
|
background-color: #fff;
|
|
border-radius: 20rpx;
|
|
|
|
.left {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.input_box {
|
|
text-align: left;
|
|
color: rgba(51, 51, 51, 1);
|
|
font-size: 30rpx;
|
|
line-height: 42rpx;
|
|
}
|
|
}
|
|
|
|
&_icon {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.code_btn {
|
|
color: rgba(97, 93, 255, 1);
|
|
font-size: 30rpx;
|
|
line-height: 42rpx;
|
|
.time_tip {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
}
|
|
}
|
|
|
|
.phone_btn {
|
|
margin: 60rpx 0 0 0;
|
|
height: 90rpx;
|
|
width: 100%;
|
|
line-height: 90rpx;
|
|
background-color: #615dff;
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
border-radius: 20rpx;
|
|
}
|
|
}
|
|
|
|
.popup_box {
|
|
background-color: #fff;
|
|
border-radius: 20rpx 20rpx 0 0;
|
|
overflow: hidden;
|
|
|
|
.header_title {
|
|
margin: 30rpx 0 0 30rpx;
|
|
color: rgba(51, 51, 51, 1);
|
|
font-size: 32rpx;
|
|
font-weight: 500;
|
|
text-align: left;
|
|
}
|
|
|
|
.method_list {
|
|
text-align: center;
|
|
padding: 0 54rpx;
|
|
|
|
.item {
|
|
padding: 30rpx 0;
|
|
border-bottom: 1rpx solid rgba(235, 235, 235, 1);
|
|
font-weight: 400;
|
|
height: 45rpx;
|
|
color: rgba(51, 51, 51, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|