Files
client-qgdzs/pages/login/login.vue

271 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="login-container">
<view class="login-box">
<view class="logo-section">
<image class="logo" src="/static/logo.png" mode="aspectFit"></image>
<view class="app-name">趣味答题</view>
<view class="app-desc">海量题库轻松学习</view>
</view>
<button
class="wx-login-btn"
:class="{ 'disabled': isLoading }"
:disabled="isLoading"
open-type="getUserInfo"
@getuserinfo="handleWxLogin"
>
<text class="wx-icon">👤</text>
<text>{{ isLoading ? '登录中...' : '微信一键登录' }}</text>
</button>
<view class="skip-btn" @click="handleSkip">
<text>暂不登录</text>
</view>
<view class="tips">
登录即表示同意用户协议隐私政策
</view>
</view>
</view>
</template>
<script>
import api from '../../utils/api.js'
import storage from '../../utils/storage.js'
export default {
data() {
return {
isLoading: false,
redirectUrl: ''
}
},
onLoad(options) {
if (options.redirect) {
this.redirectUrl = decodeURIComponent(options.redirect)
}
},
methods: {
async handleWxLogin(e) {
if (this.isLoading) {
return
}
this.isLoading = true
try {
uni.showLoading({
title: '登录中...',
mask: true
})
uni.login({
provider: 'weixin',
success: async (loginRes) => {
console.log('uni.login 成功:', loginRes)
if (!loginRes.code) {
throw new Error('获取微信登录凭证失败')
}
try {
const res = await api.wxLogin(loginRes.code)
console.log('后端登录返回:', res)
if (res.data && res.data.accessToken) {
storage.setToken(res.data.accessToken)
const userInfo = {
...res.data,
nickName: res.data.nickName || '微信用户',
avatarUrl: res.data.avatarUrl || ''
}
storage.setUserInfo(userInfo)
try {
const questionRes = await api.getQuestion()
if (questionRes.data) {
storage.setQuestion(questionRes.data)
}
} catch (questionError) {
console.error('获取题目失败:', questionError)
}
uni.hideLoading()
uni.showToast({
title: '登录成功',
icon: 'success'
})
setTimeout(() => {
this.navigateAfterLogin()
}, 1500)
} else {
throw new Error(res.message || '登录失败')
}
} catch (apiError) {
console.error('登录接口调用失败:', apiError)
uni.hideLoading()
uni.showToast({
title: apiError.message || '登录失败,请重试',
icon: 'none',
duration: 2000
})
}
},
fail: (err) => {
console.error('uni.login 失败:', err)
uni.hideLoading()
uni.showToast({
title: '微信登录失败',
icon: 'none'
})
}
})
} catch (error) {
console.error('登录异常:', error)
uni.hideLoading()
uni.showToast({
title: '登录失败,请重试',
icon: 'none'
})
} finally {
this.isLoading = false
}
},
handleSkip() {
if (this.redirectUrl) {
if (this.isTabBarPage(this.redirectUrl)) {
uni.switchTab({
url: this.redirectUrl
})
} else {
uni.redirectTo({
url: this.redirectUrl
})
}
} else {
uni.switchTab({
url: '/pages/index/index'
})
}
},
navigateAfterLogin() {
if (this.redirectUrl) {
if (this.isTabBarPage(this.redirectUrl)) {
uni.switchTab({
url: this.redirectUrl
})
} else {
uni.redirectTo({
url: this.redirectUrl
})
}
} else {
uni.switchTab({
url: '/pages/index/index'
})
}
},
isTabBarPage(url) {
const tabBarPages = [
'/pages/index/index',
'/pages/gameplay/gameplay',
'/pages/mine/mine'
]
return tabBarPages.some(page => url.includes(page))
}
}
}
</script>
<style scoped>
.login-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 40rpx;
}
.login-box {
width: 100%;
max-width: 600rpx;
background: #ffffff;
border-radius: 20rpx;
padding: 80rpx 40rpx;
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.1);
}
.logo-section {
text-align: center;
margin-bottom: 80rpx;
}
.logo {
width: 160rpx;
height: 160rpx;
margin-bottom: 30rpx;
}
.app-name {
font-size: 48rpx;
font-weight: bold;
color: #333;
margin-bottom: 16rpx;
}
.app-desc {
font-size: 28rpx;
color: #999;
}
.wx-login-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #07c160 0%, #06ae56 100%);
color: #ffffff;
font-size: 32rpx;
border-radius: 48rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30rpx;
box-shadow: 0 8rpx 24rpx rgba(7, 193, 96, 0.3);
}
.wx-login-btn.disabled {
opacity: 0.6;
}
.wx-icon {
font-size: 36rpx;
margin-right: 12rpx;
}
.skip-btn {
text-align: center;
padding: 20rpx 0;
margin-bottom: 40rpx;
}
.skip-btn text {
font-size: 28rpx;
color: #999;
}
.tips {
font-size: 24rpx;
color: #999;
text-align: center;
line-height: 1.6;
}
</style>