edu/uniapp/src/pages/login/login.vue

495 lines
16 KiB
Vue
Raw Normal View History

2022-09-07 08:10:28 +00:00
<template>
2024-10-10 06:10:49 +00:00
<page-meta :page-style="$theme.pageStyle">
<!-- #ifndef H5 -->
<navigation-bar :front-color="$theme.navColor" :background-color="$theme.navBgColor" />
<!-- #endif -->
</page-meta>
2022-09-07 13:00:03 +00:00
<view
2024-10-10 06:10:49 +00:00
class="bg-white login min-h-full flex flex-col items-center px-[40rpx] pt-[120rpx] box-border"
2022-09-07 13:00:03 +00:00
>
2022-09-07 08:10:28 +00:00
<view>
2024-10-10 06:10:49 +00:00
<image
:src="appStore.getWebsiteConfig.shop_logo"
mode="widthFix"
class="w-[160rpx] h-[160rpx] rounded-full"
/>
2022-09-07 08:10:28 +00:00
</view>
2024-10-10 06:10:49 +00:00
<view class="w-full mt-[140rpx] pb-[60rpx]">
<block v-if="!phoneLogin">
<!-- #ifdef MP-WEIXIN || H5 -->
<view v-if="isOpenOtherAuth && isWeixin && inWxAuth">
<u-button
type="primary"
@click="wxLogin"
:customStyle="{ height: '100rpx' }"
hover-class="none"
>
用户一键登录
</u-button>
</view>
<!-- #endif -->
<view class="mt-[40rpx]">
<u-button
@click="phoneLogin = !phoneLogin"
:customStyle="{ height: '100rpx' }"
hover-class="none"
>
手机号登录
</u-button>
</view>
</block>
<block v-if="phoneLogin">
<!-- 密码登录 -->
2022-09-13 09:41:24 +00:00
<template
2024-10-10 06:10:49 +00:00
v-if="
formData.scene == LoginWayEnum.ACCOUNT &&
includeLoginWay(LoginWayEnum.ACCOUNT)
"
2022-09-13 09:41:24 +00:00
>
2024-10-10 06:10:49 +00:00
<view
class="px-[18rpx] border border-solid border-lightc border-light rounded-[10rpx] h-[100rpx] items-center flex"
>
2022-09-07 12:58:01 +00:00
<u-input
class="flex-1"
2024-10-10 06:10:49 +00:00
v-model="formData.account"
2022-09-07 12:58:01 +00:00
:border="false"
2024-10-10 06:10:49 +00:00
placeholder="输入账号"
2022-09-08 08:28:56 +00:00
/>
2024-10-10 06:10:49 +00:00
</view>
<view
class="px-[18rpx] py-[10rpx] border border-solid border-light rounded-[10rpx] flex h-[100rpx] items-center mt-[40rpx]"
>
2022-09-07 12:58:01 +00:00
<u-input
class="flex-1"
v-model="formData.password"
type="password"
2024-10-10 06:10:49 +00:00
placeholder="输入密码"
2022-09-07 12:58:01 +00:00
:border="false"
/>
2022-09-09 01:50:39 +00:00
<navigator url="/pages/forget_pwd/forget_pwd" hover-class="none">
<view
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4 ml-3"
>
忘记密码
</view>
</navigator>
2024-10-10 06:10:49 +00:00
</view>
2022-09-07 12:58:01 +00:00
</template>
2024-10-10 06:10:49 +00:00
<!-- 验证码登录 -->
2022-09-13 09:41:24 +00:00
<template
2024-10-10 06:10:49 +00:00
v-if="
formData.scene == LoginWayEnum.MOBILE &&
includeLoginWay(LoginWayEnum.MOBILE)
"
2022-09-13 09:41:24 +00:00
>
2024-10-10 06:10:49 +00:00
<view
class="px-[18rpx] border border-solid border-lightc border-light rounded-[10rpx] h-[100rpx] items-center flex"
>
2022-09-07 12:58:01 +00:00
<u-input
class="flex-1"
2024-10-10 06:10:49 +00:00
v-model="formData.account"
2022-09-07 12:58:01 +00:00
:border="false"
placeholder="请输入手机号码"
/>
2024-10-10 06:10:49 +00:00
</view>
<view
class="px-[18rpx] border border-solid border-lightc border-light rounded-[10rpx] h-[100rpx] items-center flex mt-[40rpx]"
>
2022-09-07 12:58:01 +00:00
<u-input
class="flex-1"
v-model="formData.code"
placeholder="请输入验证码"
:border="false"
/>
2024-10-10 06:10:49 +00:00
2022-09-07 12:58:01 +00:00
<view
2022-09-20 04:15:08 +00:00
class="border-l border-solid border-0 border-light pl-3 leading-4 ml-3 w-[180rpx]"
2022-09-07 12:58:01 +00:00
@click="sendSms"
>
<u-verification-code
ref="uCodeRef"
:seconds="60"
@change="codeChange"
change-text="x秒"
/>
2024-10-10 06:10:49 +00:00
<text :class="formData.account ? 'text-primary' : 'text-muted'">
2022-09-20 04:15:08 +00:00
{{ codeTips }}
</text>
2022-09-07 12:58:01 +00:00
</view>
2024-10-10 06:10:49 +00:00
</view>
2022-09-07 12:58:01 +00:00
</template>
2024-10-10 06:10:49 +00:00
</block>
2022-09-13 09:41:24 +00:00
<view class="mt-[40rpx]" v-if="isOpenAgreement">
2022-09-07 12:58:01 +00:00
<u-checkbox v-model="isCheckAgreement" shape="circle">
<view class="text-xs flex">
已阅读并同意
2022-10-13 07:03:11 +00:00
<view @click.stop>
<navigator
class="text-primary"
hover-class="none"
url="/pages/agreement/agreement?type=service"
>
服务协议
</navigator>
</view>
<view @click.stop>
<navigator
class="text-primary"
hover-class="none"
url="/pages/agreement/agreement?type=privacy"
>
隐私协议
</navigator>
</view>
2022-09-07 12:58:01 +00:00
</view>
</u-checkbox>
</view>
2024-10-10 06:10:49 +00:00
<block v-if="phoneLogin">
<view class="mt-[60rpx]">
<u-button
type="primary"
@click="handleLogin(formData.scene)"
:customStyle="{
height: '100rpx',
opacity: DisableStyle ? '1' : '0.5'
}"
hover-class="none"
2022-09-13 09:41:24 +00:00
>
2024-10-10 06:10:49 +00:00
登录
</u-button>
</view>
<view class="flex justify-between mt-[40rpx]">
2022-09-13 09:41:24 +00:00
<view
v-if="
formData.scene == LoginWayEnum.MOBILE &&
includeLoginWay(LoginWayEnum.ACCOUNT)
"
2024-10-10 06:10:49 +00:00
>已有账号使用
<span class="text-primary" @click="changeLoginWay(LoginWayEnum.ACCOUNT)"
2024-10-10 06:10:49 +00:00
>密码登录</span
>
</view>
<view
v-if="
formData.scene == LoginWayEnum.ACCOUNT &&
includeLoginWay(LoginWayEnum.MOBILE)
"
>已有账号使用
2024-10-10 06:10:49 +00:00
<span
class="text-primary"
@click="changeLoginWay(LoginWayEnum.MOBILE)"
v-if="
formData.scene == LoginWayEnum.ACCOUNT &&
includeLoginWay(LoginWayEnum.MOBILE)
"
>验证码登录</span
>
2022-09-13 09:41:24 +00:00
</view>
2024-10-10 06:10:49 +00:00
<navigator url="/pages/register/register" hover-class="none"
>注册账号</navigator
2022-09-13 09:41:24 +00:00
>
2024-10-10 06:10:49 +00:00
</view>
</block>
2022-09-07 08:10:28 +00:00
</view>
2024-10-10 06:10:49 +00:00
<!-- 协议弹框 -->
<u-modal
v-model="showModel"
show-cancel-button
:show-title="false"
confirm-color="var(--color-primary)"
@confirm=";(isCheckAgreement = true), (showModel = false)"
@cancel="showModel = false"
>
<view class="text-center px-[70rpx] py-[60rpx]">
<view> 请先阅读并同意 </view>
<view class="flex justify-center">
<navigator data-theme="" url="/pages/agreement/agreement?type=service">
<view class="text-primary">服务协议</view>
</navigator>
<navigator url="/pages/agreement/agreement?type=privacy">
<view class="text-primary">隐私协议</view>
</navigator>
</view>
</view>
</u-modal>
<!-- #ifdef MP-WEIXIN -->
2023-03-29 07:52:38 +00:00
<mplogin-popup
v-model:show="showLoginPopup"
2024-10-10 06:10:49 +00:00
:logo="websiteConfig.shop_logo"
:title="websiteConfig.shop_name"
2023-03-29 07:52:38 +00:00
@update="handleUpdateUser"
/>
2024-10-10 06:10:49 +00:00
<!-- #endif -->
2022-09-07 08:10:28 +00:00
</view>
</template>
<script setup lang="ts">
2024-10-10 06:10:49 +00:00
import { login, mnpLogin, updateUser, OALogin } from '@/api/account'
2022-09-07 12:58:01 +00:00
import { smsSend } from '@/api/app'
import { SMSEnum } from '@/enums/appEnums'
2024-10-10 06:10:49 +00:00
import { BACK_URL } from '@/enums/constantEnums'
2022-09-08 08:28:56 +00:00
import { useLockFn } from '@/hooks/useLockFn'
2022-09-08 11:09:53 +00:00
import { useAppStore } from '@/stores/app'
2022-09-08 08:28:56 +00:00
import { useUserStore } from '@/stores/user'
2024-10-10 06:10:49 +00:00
import { useRouter, useRoute } from 'uniapp-router-next'
2022-09-15 07:03:12 +00:00
import cache from '@/utils/cache'
2022-09-15 02:53:31 +00:00
import { isWeixinClient } from '@/utils/client'
// #ifdef H5
2024-10-10 06:10:49 +00:00
import wechatOa, { UrlScene } from '@/utils/wechat'
2022-09-15 02:53:31 +00:00
// #endif
import { onLoad, onShow } from '@dcloudio/uni-app'
2022-09-13 09:41:24 +00:00
import { computed, reactive, ref, shallowRef, watch } from 'vue'
import { storeToRefs } from 'pinia'
2022-09-13 09:41:24 +00:00
enum LoginWayEnum {
ACCOUNT = 1,
MOBILE = 2
}
2022-09-15 02:53:31 +00:00
const isWeixin = ref(true)
// #ifdef H5
2022-09-15 07:03:12 +00:00
isWeixin.value = isWeixinClient()
2022-09-15 02:53:31 +00:00
// #endif
2022-09-13 09:41:24 +00:00
2024-10-10 06:10:49 +00:00
const route = useRoute()
const router = useRouter()
const userStore = useUserStore()
const { userInfo, isLogin } = storeToRefs(userStore)
2022-09-13 09:41:24 +00:00
const appStore = useAppStore()
2024-10-10 06:10:49 +00:00
const showModel = ref(false)
2022-09-07 12:58:01 +00:00
const uCodeRef = shallowRef()
const codeTips = ref('')
2024-10-10 06:10:49 +00:00
const showLoginPopup = ref(false)
2022-09-07 12:58:01 +00:00
const isCheckAgreement = ref(false)
2024-10-10 06:10:49 +00:00
2022-09-07 08:10:28 +00:00
const formData = reactive({
2024-10-10 06:10:49 +00:00
scene: 1,
account: '',
2022-09-07 12:58:01 +00:00
password: '',
2024-10-10 06:10:49 +00:00
code: ''
2022-09-07 08:10:28 +00:00
})
2024-10-10 06:10:49 +00:00
const phoneLogin = ref(false)
const loginData = ref()
2022-09-07 12:58:01 +00:00
const codeChange = (text: string) => {
codeTips.value = text
}
2024-10-10 06:10:49 +00:00
const websiteConfig = computed(() => appStore.getWebsiteConfig)
2022-09-07 12:58:01 +00:00
const sendSms = async () => {
2024-10-10 06:10:49 +00:00
if (!formData.account) return
2022-09-07 12:58:01 +00:00
if (uCodeRef.value?.canGetCode) {
await smsSend({
scene: SMSEnum.LOGIN,
2024-10-10 06:10:49 +00:00
mobile: formData.account
2022-09-07 12:58:01 +00:00
})
uni.$u.toast('发送成功')
uCodeRef.value?.start()
}
}
2022-09-08 08:28:56 +00:00
2024-10-10 06:10:49 +00:00
const changeLoginWay = (way: LoginWayEnum) => {
formData.scene = way
2022-09-13 09:41:24 +00:00
}
const includeLoginWay = (way: LoginWayEnum) => {
2024-10-10 06:10:49 +00:00
return appStore.getLoginConfig.login_way?.includes(String(way))
2022-09-13 09:41:24 +00:00
}
2024-10-10 06:10:49 +00:00
const inWxAuth = computed(() => {
return appStore.getLoginConfig.wechat_auth
})
2022-09-13 09:41:24 +00:00
2024-10-10 06:10:49 +00:00
const isOpenAgreement = computed(() => appStore.getLoginConfig.login_agreement == 1)
2022-09-13 09:41:24 +00:00
2024-10-10 06:10:49 +00:00
const isOpenOtherAuth = computed(() => appStore.getLoginConfig.third_auth == 1)
const isForceBindMobile = computed(() => appStore.getLoginConfig.coerce_mobile == 1)
2022-09-13 09:41:24 +00:00
2024-10-10 06:10:49 +00:00
const loginFun = async () => {
if (!isCheckAgreement.value && isOpenAgreement.value) return (showModel.value = true)
if (formData.scene == LoginWayEnum.ACCOUNT) {
if (!formData.account) return uni.$u.toast('请输入账号/手机号码')
if (!formData.password) return uni.$u.toast('请输入密码')
}
if (formData.scene == LoginWayEnum.MOBILE) {
if (!formData.account) return uni.$u.toast('请输入手机号码')
if (!formData.code) return uni.$u.toast('请输入验证码')
}
uni.showLoading({
title: '请稍后...'
})
2022-09-08 08:28:56 +00:00
try {
2024-10-10 06:10:49 +00:00
const data = await login(formData)
loginHandle(data)
2022-09-08 08:28:56 +00:00
} catch (error: any) {
uni.hideLoading()
uni.$u.toast(error)
2022-09-08 08:28:56 +00:00
}
}
2022-09-07 12:58:01 +00:00
2022-09-15 02:53:31 +00:00
const loginHandle = async (data: any) => {
2024-10-10 06:10:49 +00:00
const { token, mobile } = data
if (!mobile && isForceBindMobile.value) {
2022-09-15 02:53:31 +00:00
userStore.temToken = token
2024-10-10 06:10:49 +00:00
router.navigateTo('/pages/bind_mobile/bind_mobile')
2022-09-15 02:53:31 +00:00
uni.hideLoading()
return
}
userStore.login(data.token)
await userStore.getUser()
uni.$u.toast('登录成功')
uni.hideLoading()
2023-01-17 07:46:07 +00:00
const pages = getCurrentPages()
if (pages.length > 1) {
const prevPage = pages[pages.length - 2]
2024-10-10 06:10:49 +00:00
await router.navigateBack()
// @ts-ignore
const { onLoad, options } = prevPage
// 刷新上一个页面
onLoad && onLoad(options)
2022-09-15 07:03:12 +00:00
} else if (cache.get(BACK_URL)) {
2024-10-10 06:10:49 +00:00
try {
router.redirectTo(cache.get(BACK_URL))
} catch (error) {
router.switchTab(cache.get(BACK_URL))
}
} else {
try {
router.reLaunch('/pages/index/index')
} catch (error) {
router.switchTab('/pages/index/index')
}
2022-09-15 07:03:12 +00:00
}
cache.remove(BACK_URL)
2022-09-15 02:53:31 +00:00
}
2022-09-13 09:41:24 +00:00
const { lockFn: handleLogin } = useLockFn(loginFun)
2022-09-08 08:28:56 +00:00
2024-10-10 06:10:49 +00:00
const oaLogin = async (options: any = { getUrl: true }) => {
const { code, getUrl } = options
if (getUrl) {
await wechatOa.getUrl(UrlScene.LOGIN)
} else {
const data = await OALogin({
code
})
return data
}
return Promise.reject()
2022-09-07 12:58:01 +00:00
}
2024-10-10 06:10:49 +00:00
const wxLogin = async () => {
if (!isCheckAgreement.value && isOpenAgreement.value) {
showModel.value = true
console.log(showModel.value)
return
}
// #ifdef MP-WEIXIN
uni.showLoading({
title: '请稍后...'
})
try {
const { code }: any = await uni.login({
provider: 'weixin'
})
const data = await mnpLogin({
2024-10-10 06:10:49 +00:00
code: code
})
2023-03-29 07:52:38 +00:00
loginData.value = data
2024-10-10 06:10:49 +00:00
if (data.is_new_user) {
2023-03-29 07:52:38 +00:00
uni.hideLoading()
userStore.temToken = data.token
showLoginPopup.value = true
return
}
loginHandle(data)
2024-10-10 06:10:49 +00:00
} catch (error: any) {
uni.hideLoading()
uni.$u.toast(error)
}
2024-10-10 06:10:49 +00:00
// #endif
// #ifdef H5
if (isWeixin.value) {
oaLogin()
}
// #endif
}
2023-03-29 07:52:38 +00:00
const handleUpdateUser = async (value: any) => {
await updateUser(value, { token: userStore.temToken })
showLoginPopup.value = false
loginHandle(loginData.value)
}
2022-09-13 09:41:24 +00:00
watch(
() => appStore.getLoginConfig,
(value) => {
2024-10-10 06:10:49 +00:00
if (value.login_way) {
formData.scene = value.login_way[0]
2022-09-13 09:41:24 +00:00
}
},
{
immediate: true
}
)
2024-10-10 06:10:49 +00:00
const DisableStyle = computed(() => {
if (formData.scene == 1 && formData.account && formData.password) {
return true
} else if (formData.scene == 2 && formData.account && formData.code) {
return true
} else {
return false
}
})
2022-09-13 09:41:24 +00:00
2024-10-10 06:10:49 +00:00
const removeWxQuery = () => {
const options = route.query
if (options.code && options.state) {
delete options.code
delete options.state
router.redirectTo({ path: route.path, query: options })
}
}
onLoad(async () => {
//#ifdef H5
const options = wechatOa.getAuthData()
2022-09-13 09:41:24 +00:00
try {
2024-10-10 06:10:49 +00:00
if (options.code && options.scene === UrlScene.LOGIN) {
2022-09-13 09:41:24 +00:00
uni.showLoading({
title: '请稍后...'
})
2024-10-10 06:10:49 +00:00
const data = await oaLogin(options)
if (data) {
loginData.value = data
loginHandle(loginData.value)
}
2022-09-15 02:53:31 +00:00
}
2024-10-10 06:10:49 +00:00
} catch (error) {
removeWxQuery()
} finally {
uni.hideLoading()
//清除保存的授权数据
wechatOa.setAuthData()
2022-09-15 02:53:31 +00:00
}
2024-10-10 06:10:49 +00:00
//#endif
})
if (isLogin.value == true) {
window.location.href = '/mobile/pages/user/user'
}
2022-09-07 08:10:28 +00:00
</script>
<style lang="scss">
page {
height: 100%;
}
</style>