You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

273 lines
6.1 KiB

<template>
<view class="login-page">
<!-- 顶部装饰元素 -->
<view class="top-decoration">
<view class="circle circle-1"></view>
<view class="circle circle-2"></view>
<view class="circle circle-3"></view>
</view>
<!-- Logo区域 -->
<view class="logo-section">
<image class="logo" src="/static/logo.png" mode="aspectFit"></image>
<text class="app-title">劳务地图</text>
</view>
<!-- 登录按钮区域 -->
<view class="login-section">
<button class="wechat-login-btn" open-type="getPhoneNumber" @getphonenumber="onWechatLogin">
<image class="wechat-icon" src="/static/wechat-icon.png" mode="aspectFit"></image>
<text class="btn-text">微信一键登录</text>
</button>
{{ loginRes }}
<view class="agreement-section">
<label class="checkbox-wrapper">
<checkbox :checked="agreeChecked" @tap="toggleAgreement" color="#07c160" />
<text class="agreement-text">我已阅读并同意</text>
</label>
<text class="agreement-link" @tap="showAgreement">用户协议</text>
<text class="agreement-text"></text>
<text class="agreement-link" @tap="showPrivacyPolicy">隐私政策</text>
</view>
</view>
<!-- 底部装饰 -->
<view class="bottom-decoration"></view>
</view>
</template>
<script setup>
import { computed, ref } from 'vue';
import { appUserQuery, userLogin } from '../../api';
import { useUserStore } from '../../stores/user.js';
// 用户协议勾选状态
const agreeChecked = ref(false);
// 获取用户 store 实例
const userStore = useUserStore();
const loginRes = computed(() => userStore.loginRes);
// 微信登录处理
const onWechatLogin = (e) => {
// 检查用户是否同意协议
if (!agreeChecked.value) {
uni.showToast({
title: '请先同意用户协议和隐私政策',
icon: 'none'
});
return;
}
// 显示加载提示
uni.showLoading({
title: '登录中...'
});
// 获取微信登录凭证
uni.login({
provider: 'weixin',
success: async (wxLoginRes) => {
try {
const code = wxLoginRes.code;
const loginRes = await userLogin({ code });
// 隐藏加载提示
uni.hideLoading();
// 使用 Pinia 存储 loginRes 数据
userStore.setLoginRes(loginRes.data);
// 登录成功提示
uni.showToast({
title: '登录成功',
icon: 'success'
});
const userProfileRes = await appUserQuery()
userStore.setUserInfo(userProfileRes.data);
// 跳转到首页
setTimeout(() => {
uni.switchTab({
url: '/pages/index/index'
});
}, 1000);
} catch (error) {
// 隐藏加载提示
uni.hideLoading();
console.error('登录过程出错', error);
uni.showToast({
title: '登录过程出错,请重试',
icon: 'none'
});
}
},
fail: (err) => {
// 隐藏加载提示
uni.hideLoading();
console.error('微信登录失败', err);
uni.showToast({
title: '微信登录失败,请重试',
icon: 'none'
});
}
});
};
// 切换用户协议勾选状态
const toggleAgreement = () => {
agreeChecked.value = !agreeChecked.value;
};
// 显示用户协议
const showAgreement = () => {
uni.showToast({
title: '用户协议',
icon: 'none'
});
};
// 显示隐私政策
const showPrivacyPolicy = () => {
uni.showToast({
title: '隐私政策',
icon: 'none'
});
};
</script>
<style lang="scss">
.login-page {
display: flex;
flex-direction: column;
min-height: 100vh;
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf9 100%);
padding: 20px;
// 顶部装饰
.top-decoration {
position: relative;
height: 120px;
margin-bottom: 40px;
.circle {
position: absolute;
border-radius: 50%;
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
opacity: 0.1;
&.circle-1 {
width: 80px;
height: 80px;
top: 0;
right: 10%;
}
&.circle-2 {
width: 120px;
height: 120px;
top: -20px;
left: 5%;
}
&.circle-3 {
width: 60px;
height: 60px;
bottom: 0;
right: 25%;
}
}
}
// Logo区域
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 60px;
.logo {
width: 100px;
height: 100px;
margin-bottom: 20px;
}
.app-title {
font-size: 24px;
font-weight: bold;
color: #333;
}
}
// 登录区域
.login-section {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
.wechat-login-btn {
width: 80%;
height: 50px;
background: #07c160;
border-radius: 25px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30px;
box-shadow: 0 4px 10px rgba(7, 193, 96, 0.3);
.wechat-icon {
width: 24px;
height: 24px;
margin-right: 10px;
}
.btn-text {
color: white;
font-size: 16px;
font-weight: 500;
}
&::after {
border: none;
}
}
// 协议区域
.agreement-section {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: center;
padding: 0 20px;
.checkbox-wrapper {
display: flex;
align-items: center;
margin-right: 5px;
.agreement-text {
margin-left: 5px;
}
}
.agreement-text {
font-size: 12px;
color: #999;
margin: 0 2px;
}
.agreement-link {
font-size: 12px;
color: #07c160;
text-decoration: underline;
}
}
}
// 底部装饰
.bottom-decoration {
height: 60px;
}
}
</style>