mahjong_group/pages/me/login.vue
2025-09-06 20:17:36 +08:00

466 lines
8.7 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="bg-decoration">
<!-- 云朵装饰 -->
<view class="cloud cloud-1"></view>
<view class="cloud cloud-2"></view>
<view class="cloud cloud-3"></view>
<!-- 小鸟装饰 -->
<view class="bird bird-1"></view>
<view class="bird bird-2"></view>
</view>
<!-- 头部区域 -->
<view class="header">
<image src="@@:app/static/Logo.jpg" class="logo" mode="aspectFit"></image>
<text class="welcome-text">欢迎登录</text>
</view>
<!-- 登录表单 -->
<view class="login-form">
<!-- 一键登录按钮 -->
<view class="one-click-login">
<view class="quick-login-btn" @click="handleOneClickLogin" :class="{ disabled: loading }">
<text>{{ loading ? '登录中...' : '一键登录' }}</text>
</view>
</view>
<!-- 用户协议同意 -->
<view class="agreement-section">
<view class="agreement-checkbox" @click="toggleAgreement">
<checkbox :value="agreedToTerms" :checked="agreedToTerms" style="transform:scale(0.5);margin-top: -8rpx;" />
<text class="agreement-text">
我已阅读并同意
<text class="agreement-link" @click.stop="showUserAgreement">用户协议</text>
<text class="agreement-link" @click.stop="showPrivacyPolicy">隐私政策</text>
</text>
</view>
</view>
<!-- 暂不登录按钮 -->
<view class="skip-login-btn" @click="skipLogin">
<text>暂不登录</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
// 响应式数据
const loading = ref(false)
const agreedToTerms = ref(false)
// 方法
const toggleAgreement = () => {
agreedToTerms.value = !agreedToTerms.value
}
const handleOneClickLogin = async () => {
if (loading.value) return
if (!agreedToTerms.value) {
uni.showToast({
title: '请先同意用户协议和隐私政策',
icon: 'none'
})
return
}
loading.value = true
try {
// 这里调用一键登录API如运营商一键登录
// const response = await oneClickLoginApi()
// 模拟一键登录成功
await new Promise(resolve => setTimeout(resolve, 2000))
// 生成随机手机号用于演示
const randomPhone = '138' + Math.floor(Math.random() * 100000000).toString().padStart(8, '0')
// 保存登录状态
uni.setStorageSync('userInfo', {
phone: randomPhone,
nickname: '用户' + randomPhone.slice(-4),
uid: 'U' + Date.now(),
avatar: '@@:app/nouser.png',
rating: 4.6,
reputation: 5.0,
cardQuality: 4.5,
cardSkill: 4.5,
pigeonCount: 0
})
uni.showToast({
title: '登录成功',
icon: 'success'
})
// 延迟跳转
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
console.error('一键登录失败:', error)
uni.showToast({
title: '登录失败,请重试',
icon: 'error'
})
} finally {
loading.value = false
}
}
const skipLogin = () => {
uni.navigateBack()
}
const showUserAgreement = () => {
uni.showModal({
title: '用户协议',
content: '这里是用户协议的内容...\n\n1. 用户权利和义务\n2. 服务条款\n3. 免责声明\n4. 其他条款',
showCancel: false,
confirmText: '我知道了'
})
}
const showPrivacyPolicy = () => {
uni.showModal({
title: '隐私政策',
content: '这里是隐私政策的内容...\n\n1. 信息收集\n2. 信息使用\n3. 信息保护\n4. 信息共享',
showCancel: false,
confirmText: '我知道了'
})
}
</script>
<style lang="scss" scoped>
.login-container {
min-height: 100vh;
background: linear-gradient(180deg, #87CEEB 0%, #98FB98 50%, #F0E68C 100%);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-decoration {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
// 云朵样式
.cloud {
position: absolute;
background: rgba(255, 255, 255, 0.8);
border-radius: 50rpx;
&::before,
&::after {
content: '';
position: absolute;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
}
&.cloud-1 {
width: 120rpx;
height: 40rpx;
top: 15%;
left: 10%;
&::before {
width: 50rpx;
height: 50rpx;
top: -25rpx;
left: 10rpx;
}
&::after {
width: 60rpx;
height: 60rpx;
top: -30rpx;
right: 10rpx;
}
}
&.cloud-2 {
width: 100rpx;
height: 35rpx;
top: 25%;
right: 15%;
&::before {
width: 40rpx;
height: 40rpx;
top: -20rpx;
left: 8rpx;
}
&::after {
width: 50rpx;
height: 50rpx;
top: -25rpx;
right: 8rpx;
}
}
&.cloud-3 {
width: 80rpx;
height: 30rpx;
top: 70%;
left: 20%;
&::before {
width: 35rpx;
height: 35rpx;
top: -17rpx;
left: 6rpx;
}
&::after {
width: 40rpx;
height: 40rpx;
top: -20rpx;
right: 6rpx;
}
}
}
// 小鸟样式
.bird {
position: absolute;
width: 20rpx;
height: 15rpx;
background: #8B4513;
border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
&::before {
content: '';
position: absolute;
width: 8rpx;
height: 6rpx;
background: #8B4513;
border-radius: 50%;
top: 2rpx;
left: -5rpx;
transform: rotate(-20deg);
}
&.bird-1 {
top: 20%;
right: 25%;
animation: fly 3s ease-in-out infinite;
}
&.bird-2 {
top: 60%;
left: 15%;
animation: fly 4s ease-in-out infinite reverse;
}
}
// 花朵样式
.flower {
position: absolute;
width: 30rpx;
height: 30rpx;
&::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(circle, #FFB6C1 30%, #FF69B4 70%);
border-radius: 50%;
}
&::after {
content: '';
position: absolute;
width: 6rpx;
height: 20rpx;
background: #228B22;
border-radius: 3rpx;
bottom: -20rpx;
left: 50%;
transform: translateX(-50%);
}
&.flower-1 {
top: 40%;
left: 8%;
animation: sway 2s ease-in-out infinite;
}
&.flower-2 {
top: 80%;
right: 10%;
animation: sway 2.5s ease-in-out infinite reverse;
}
&.flower-3 {
top: 50%;
right: 30%;
animation: sway 3s ease-in-out infinite;
}
}
// 动画效果
@keyframes fly {
0%, 100% { transform: translateX(0) translateY(0); }
25% { transform: translateX(10rpx) translateY(-5rpx); }
50% { transform: translateX(20rpx) translateY(0); }
75% { transform: translateX(10rpx) translateY(5rpx); }
}
@keyframes sway {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(2deg); }
50% { transform: rotate(0deg); }
75% { transform: rotate(-2deg); }
}
@keyframes shine {
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
}
.header {
text-align: center;
margin-bottom: 80rpx;
.logo {
width: 200rpx;
height: 200rpx;
border-radius: 50%;
margin-bottom: 30rpx;
border: 8rpx solid #FFE4B5;
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1);
}
.app-name {
display: block;
font-size: 48rpx;
font-weight: bold;
color: #8B4513;
margin-bottom: 20rpx;
text-shadow: 2rpx 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
.welcome-text {
display: block;
font-size: 28rpx;
color: #228B22;
font-weight: 500;
}
}
.login-form {
padding: 0 60rpx;
width: 100%;
max-width: 600rpx;
}
.one-click-login {
margin: 40rpx 0;
.quick-login-btn {
background: linear-gradient(135deg, #F36903 0%, #E55A00 100%);
color: white;
height: 100rpx;
border-radius: 50rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: bold;
box-shadow: 0 8rpx 20rpx rgba(243, 105, 3, 0.3);
border: 4rpx solid #FFE4B5;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transform: rotate(45deg);
transition: all 0.5s;
}
&:active::before {
animation: shine 0.6s ease-in-out;
}
&.disabled {
background: linear-gradient(135deg, #D3D3D3 0%, #A9A9A9 100%);
color: #666;
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.1);
}
.quick-login-icon {
width: 40rpx;
height: 40rpx;
margin-right: 15rpx;
}
}
}
.agreement-section {
margin: 30rpx 0;
.agreement-checkbox {
display: flex;
align-items: flex-start;
.checkbox {
width: 30rpx;
height: 30rpx;
margin-right: 15rpx;
margin-top: 5rpx;
flex-shrink: 0;
}
.agreement-text {
font-size: 24rpx;
color: #8B4513;
line-height: 1.5;
.agreement-link {
color: #FF69B4;
text-decoration: underline;
font-weight: 500;
}
}
}
}
.skip-login-btn {
text-align: center;
margin: 40rpx 0;
text {
font-size: 28rpx;
color: #8B4513;
text-decoration: underline;
font-weight: 500;
}
}
</style>