HomeLease/pages/login/login.vue
2025-08-12 15:38:25 +08:00

686 lines
15 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="logo-section">
<image :src="CommonEnum.LOGIN_SRC" class="logo-image"></image>
</view>
<view class="main-content">
<!-- 登录按钮 -->
<button
class="login-btn"
@click="getPhoneNumber"
:disabled="loginLoading"
>
<text class="btn-text">{{ loginLoading ? '登录中...' : '微信用户一键登录' }}</text>
</button>
</view>
<!-- 底部协议 -->
<view class="agreement-section">
<view class="agreement-checkbox" @click="toggleAgreement">
<view class="checkbox" :class="{ 'checked': hasAgreed }">
<text v-if="hasAgreed" class="checkmark">✓</text>
</view>
</view>
<text class="agreement-text">我已阅读并同意</text>
<text class="agreement-link" @click="showServiceTerms">《服务协议》</text>
<text class="agreement-text">与</text>
<text class="agreement-link" @click="showPrivacyPolicy">《隐私政策》</text>
</view>
<!-- 服务条款弹窗 -->
<view v-if="showServiceTermsPopup" class="popup-overlay" @click="closeServiceTermsPopup">
<view class="popup-content" @click.stop>
<view class="popup-header">
<text class="popup-title">服务条款</text>
<text class="popup-close" @click="closeServiceTermsPopup">×</text>
</view>
<scroll-view class="popup-body" scroll-y="true" :scroll-top="scrollTop" show-scrollbar="true">
<view class="terms-content">
<rich-text :nodes="serviceTermsContent"></rich-text>
</view>
</scroll-view>
<view class="popup-footer">
<text class="popup-tip">请仔细阅读服务条款,阅读完毕后点击同意</text>
<button class="popup-btn" @click="agreeServiceTerms">同意</button>
</view>
</view>
</view>
<!-- 隐私政策弹窗 -->
<view v-if="showPrivacyPolicyPopup" class="popup-overlay" @click="closePrivacyPolicyPopup">
<view class="popup-content" @click.stop>
<view class="popup-header">
<text class="popup-title">隐私政策</text>
<text class="popup-close" @click="closePrivacyPolicyPopup">×</text>
</view>
<scroll-view class="popup-body" scroll-y="true" :scroll-top="scrollTop" show-scrollbar="true">
<view class="terms-content">
<rich-text :nodes="privacyPolicyContent"></rich-text>
</view>
</scroll-view>
<view class="popup-footer">
<text class="popup-tip">请仔细阅读隐私政策阅读完毕后点击同意</text>
<button class="popup-btn" @click="agreePrivacyPolicy">同意</button>
</view>
</view>
</view>
</view>
</template>
<script>
import { navigateToPage } from "@/utils/router.js";
import { wxLogin } from "@/api/auth/auth.js";
import { forceHideLoading, AutoLoadingManager } from "@/utils/request.js";
import { getServiceTerms, getPrivacyPolicy } from "@/api/article/article.js";
import { commonEnum } from "../../enum/commonEnum";
export default {
data() {
return {
currentTime: '',
loginLoading: false,
hasAgreed: false,
hasReadServiceTerms: false,
hasReadPrivacyPolicy: false,
showServiceTermsPopup: false,
showPrivacyPolicyPopup: false,
serviceTermsContent: '',
privacyPolicyContent: '',
scrollTop: 0,
statusBarHeight: 0,
}
},
computed: {
CommonEnum() {
return commonEnum
},
canLogin() {
return this.hasAgreed;
}
},
onLoad() {
// 获取状态栏高度
const systemInfo = uni.getSystemInfoSync();
this.statusBarHeight = systemInfo.statusBarHeight || 0;
// 初始化页面loading管理器
this.pageLoading = new AutoLoadingManager();
// 更新时间
this.updateTime();
setInterval(this.updateTime, 1000);
},
onUnload() {
// 页面卸载时清除loading
forceHideLoading();
if (this.pageLoading) {
this.pageLoading.destroy()
}
},
methods: {
updateTime() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
this.currentTime = `${hours}:${minutes}`;
},
// 切换同意状态
toggleAgreement() {
if (this.hasReadServiceTerms && this.hasReadPrivacyPolicy) {
this.hasAgreed = !this.hasAgreed;
} else {
uni.showToast({
title: '请先阅读服务条款和隐私政策',
icon: 'none'
});
}
},
// 显示服务条款
async showServiceTerms() {
try {
const res = await getServiceTerms();
if (res.code === 200 && res.data) {
let content = res.data.content || '暂无服务条款内容';
content = content.replace(/\n/g, '<br/>');
content = `<div style="word-wrap: break-word; word-break: break-all; line-height: 1.8; font-size: 28rpx; color: #333; padding: 0; margin: 0;">${content}</div>`;
this.serviceTermsContent = content;
this.showServiceTermsPopup = true;
this.scrollTop = 0;
} else {
uni.showToast({
title: '获取服务条款失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取服务条款失败:', error);
uni.showToast({
title: '获取服务条款失败',
icon: 'none'
});
}
},
// 显示隐私政策
async showPrivacyPolicy() {
try {
const res = await getPrivacyPolicy();
if (res.code === 200 && res.data) {
let content = res.data.content || '暂无隐私政策内容';
content = content.replace(/\n/g, '<br/>');
content = `<div style="word-wrap: break-word; word-break: break-all; line-height: 1.8; font-size: 28rpx; color: #333; padding: 0; margin: 0;">${content}</div>`;
this.privacyPolicyContent = content;
this.showPrivacyPolicyPopup = true;
this.scrollTop = 0;
} else {
uni.showToast({
title: '获取隐私政策失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取隐私政策失败:', error);
uni.showToast({
title: '获取隐私政策失败',
icon: 'none'
});
}
},
// 关闭服务条款弹窗
closeServiceTermsPopup() {
this.showServiceTermsPopup = false;
},
// 关闭隐私政策弹窗
closePrivacyPolicyPopup() {
this.showPrivacyPolicyPopup = false;
},
// 同意服务条款
async agreeServiceTerms() {
this.hasReadServiceTerms = true;
this.closeServiceTermsPopup();
this.checkAgreementStatus();
if (!this.hasReadPrivacyPolicy) {
setTimeout(() => {
this.showPrivacyPolicy();
}, 500);
}
},
// 同意隐私政策
async agreePrivacyPolicy() {
this.hasReadPrivacyPolicy = true;
this.closePrivacyPolicyPopup();
this.checkAgreementStatus();
if (!this.hasReadServiceTerms) {
setTimeout(() => {
this.showServiceTerms();
}, 500);
}
},
// 检查同意状态
checkAgreementStatus() {
if (this.hasReadServiceTerms && this.hasReadPrivacyPolicy) {
this.hasAgreed = true;
}
},
// 显示未阅读的条款
async showUnreadTerms() {
if (!this.hasReadServiceTerms) {
await this.showServiceTerms();
return;
}
if (!this.hasReadPrivacyPolicy) {
await this.showPrivacyPolicy();
return;
}
},
getPhoneNumber() {
if (!this.hasReadServiceTerms || !this.hasReadPrivacyPolicy) {
uni.showToast({
title: '请先阅读服务条款和隐私政策',
icon: 'none',
duration: 2000
});
this.showUnreadTerms();
return;
}
let that = this;
uni.login({
success(res) {
if (res.code) {
console.log('登录!', res);
let data = {
loginCode: res.code,
appId: 1,
};
if (that.pageLoading) {
that.pageLoading.show('登录中...')
}
wxLogin(data).then((res) => {
if (that.pageLoading) {
that.pageLoading.hide()
}
forceHideLoading();
if (res.code == 200) {
console.log(res, 'resres');
uni.setStorageSync('token', res.token);
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500
});
setTimeout(() => {
that.ceshi()
}, 1500);
} else {
uni.showToast({
title: res.msg || '登录失败',
icon: 'none'
});
}
}).catch((error) => {
if (that.pageLoading) {
that.pageLoading.hide()
}
forceHideLoading();
console.error('登录失败:', error);
uni.showToast({
title: '登录失败',
icon: 'none'
});
});
}
},
fail(err) {
console.error('微信登录失败:', err);
uni.showToast({
title: '微信登录失败',
icon: 'none'
});
}
});
},
async ceshi() {
if (this.pageLoading) {
this.pageLoading.hide()
}
forceHideLoading();
navigateToPage('index');
},
}
}
</script>
<style lang="scss">
page {
background: #ffffff;
}
.login-container {
padding-bottom: 40rpx;
max-width: 750rpx;
background: #ffffff;
}
.status-icons {
display: flex;
gap: 8rpx;
}
.status-icon {
font-size: 20rpx;
}
/* 头部区域 */
.header-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
margin-bottom: 40rpx;
}
.header-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.header-actions {
display: flex;
gap: 20rpx;
}
.action-btn {
font-size: 32rpx;
padding: 10rpx;
color: #666;
}
/* 主要内容区域 */
.main-content {
padding: 0 30rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 40vh;
}
/* Logo区域 */
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 80rpx;
width: 100%;
margin-top: 330rpx;
}
.logo-image {
width: 276rpx;
height: 276rpx;
border-radius: 28rpx;
}
.form-group {
margin-bottom: 30rpx;
}
.input-container {
position: relative;
display: flex;
align-items: center;
background: #f8f9fa;
border-radius: 25rpx;
padding: 0 20rpx;
border: 2rpx solid transparent;
transition: all 0.3s ease;
}
.input-container:focus-within {
border-color: #ff9a9e;
background: #fff;
box-shadow: 0 0 0 6rpx rgba(255, 154, 158, 0.1);
}
.input-icon {
font-size: 32rpx;
margin-right: 20rpx;
color: #999;
}
.form-input {
flex: 1;
height: 80rpx;
font-size: 28rpx;
color: #333;
background: transparent;
border: none;
outline: none;
}
.form-input::placeholder {
color: #999;
}
.password-toggle {
font-size: 32rpx;
padding: 10rpx;
color: #999;
}
/* 表单选项 */
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
}
.remember-password {
display: flex;
align-items: center;
gap: 10rpx;
}
.checkbox {
width: 28rpx;
height: 28rpx;
border: 2rpx solid #ddd;
border-radius: 6rpx;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
transition: all 0.3s ease;
}
.checkbox.checked {
background: #ff9a9e;
border-color: #ff9a9e;
}
.checkmark {
color: #fff;
font-size: 18rpx;
font-weight: bold;
}
.option-text {
font-size: 26rpx;
color: #666;
}
.forgot-password {
font-size: 26rpx;
color: #ff9a9e;
text-decoration: underline;
}
/* 登录按钮 */
.login-btn {
width: 100%;
height: 90rpx;
background: #ff6b35;
border-radius: 45rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40rpx;
transition: all 0.3s ease;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.3);
}
.login-btn:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 8rpx rgba(255, 107, 53, 0.3);
}
.login-btn:disabled {
background: #ccc;
box-shadow: none;
}
.btn-text {
font-size: 32rpx;
font-weight: 600;
color: #fff;
}
/* 底部协议 */
.agreement-section {
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
padding: 30rpx;
margin-top: 40rpx;
flex-wrap: wrap;
}
.agreement-checkbox {
display: flex;
align-items: center;
}
.checkbox {
width: 28rpx;
height: 28rpx;
border: 2rpx solid #ff6b35;
border-radius: 6rpx;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
transition: all 0.3s ease;
}
.checkbox.checked {
background: #ff6b35;
border-color: #ff6b35;
}
.checkmark {
color: #fff;
font-size: 18rpx;
font-weight: bold;
}
.agreement-text {
font-size: 24rpx;
color: #666;
}
.agreement-link {
font-size: 24rpx;
color: #ff6b35;
text-decoration: underline;
}
/* 弹窗样式 */
.popup-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx;
box-sizing: border-box;
}
.popup-content {
background: #fff;
border-radius: 20rpx;
overflow: hidden;
display: flex;
flex-direction: column;
width: 100%;
max-width: 680rpx;
height: 85vh;
max-height: 900rpx;
min-height: 600rpx;
margin: 0;
}
.popup-header {
padding: 30rpx;
border-bottom: 1rpx solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
}
.popup-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
.popup-close {
font-size: 40rpx;
color: #999;
cursor: pointer;
padding: 10rpx;
}
.popup-body {
flex: 1;
padding: 30rpx;
overflow: hidden;
position: relative;
height: 0;
}
.terms-content {
line-height: 1.8;
font-size: 28rpx;
color: #333;
word-wrap: break-word;
word-break: break-all;
padding-bottom: 20rpx;
}
.popup-footer {
padding: 30rpx;
border-top: 1rpx solid #eee;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
}
.popup-tip {
font-size: 24rpx;
color: #999;
margin-bottom: 20rpx;
text-align: center;
}
.popup-btn {
width: 200rpx;
height: 70rpx;
background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
border-radius: 35rpx;
font-size: 28rpx;
color: #FFFFFF;
border: none;
}
</style>