HomeLease/pages/login/login.vue

549 lines
13 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 :style="{ top: getNavBarHeight() + 'rpx' }" class="goback" @click="goback">
<uni-icons :size="getTitleBarHeight()" type="left"></uni-icons>
</view>
<view class="logo-section">
<image :src="CommonEnum.LOGIN_SRC" class="logo-image"></image>
</view>
<view class="main-content">
<!-- 登录按钮 -->
<button :disabled="loginLoading" class="login-btn" @click="throttle()(goToLogin, 3000)">
<text class="btn-text">{{ loginLoading ? '登录中...' : '微信用户一键登录' }}</text>
</button>
</view>
<!-- 底部协议 -->
<view class="agreement-section">
<view class="agreement-checkbox" @click="toggleAgreement">
<view :class="{ checked: hasAgreed }" class="checkbox">
<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
:scroll-top="scrollTop"
class="popup-body"
scroll-y="true"
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
:scroll-top="scrollTop"
class="popup-body"
scroll-y="true"
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 { 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'
import { getNavBarHeight, getTitleBarHeight } from '../../utils/system'
import throttle from 'uview-ui/libs/function/throttle'
export default {
data() {
return {
loginLoading: false,
hasAgreed: false,
hasReadServiceTerms: false,
hasReadPrivacyPolicy: false,
showServiceTermsPopup: false,
showPrivacyPolicyPopup: false,
serviceTermsContent: '',
privacyPolicyContent: '',
scrollTop: 0,
agentId: '', // 添加agentId字段
}
},
computed: {
CommonEnum() {
return commonEnum
},
},
onLoad: async function (options) {
if (options && options.q) {
const q = decodeURIComponent(options.q) // 解码二维码链接
console.log('解析后的链接:', q) // 示例: https://wx.ccttiot.com/cf/i/?agentId=63
// 提取agentId参数
const agentId = this.getUrlParam('agentId', q)
if (agentId) {
this.agentId = agentId // 存入实例属性
console.log('成功存入agentId:', this.agentId)
} else {
console.log('获取id失败')
}
}
},
onUnload() {
forceHideLoading()
if (this.pageLoading) {
this.pageLoading.destroy()
}
},
methods: {
throttle() {
return throttle
},
getTitleBarHeight,
getNavBarHeight,
goback() {
uni.navigateBack()
},
getUrlParam(key, url) {
const regex = new RegExp(`[?&]${key}=([^&#]*)`)
const match = url.match(regex)
return match ? decodeURIComponent(match[1]) : null
},
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()
}
},
goToLogin() {
console.log('开始登录流程')
// 显示加载状态
this.pageLoading?.show('登录中...')
uni.showModal({
title: '确认登录',
content: '我已阅读并同意服务协议和隐私政策',
confirmText: '确定登录',
cancelText: '取消',
success: async modalRes => {
if (modalRes.confirm) {
this.hasAgreed = true
try {
// 1. 获取微信登录code
const loginRes = await new Promise((resolve, reject) => {
uni.login({
success: resolve,
fail: reject,
})
})
if (!loginRes.code) {
throw new Error('获取登录code失败')
}
console.log('获取到登录code:', loginRes.code)
console.log('携带的agentId:', this.agentId)
// 2. 调用登录接口
const loginData = {
loginCode: loginRes.code,
agentId: this.agentId,
}
const res = await wxLogin(loginData)
if (res.code === 200) {
console.log('登录成功:', res)
uni.setStorageSync('token', res.token)
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500,
complete: () => {
uni.switchTab({
url: '/pages/index/index',
})
},
})
} else {
throw new Error(res.msg || '登录失败')
}
} catch (error) {
console.error('登录流程出错:', error)
uni.showToast({
title: error.message || '登录失败',
icon: 'none',
})
} finally {
this.pageLoading?.hide()
forceHideLoading()
}
}
},
fail: err => {
console.error('弹窗操作失败:', err)
this.pageLoading?.hide()
},
})
},
},
}
</script>
<style lang="scss" scoped>
page {
position: relative;
background: #ffffff;
}
.goback {
color: #e80a0a;
position: absolute;
left: 20rpx;
}
.login-container {
padding-bottom: 40rpx;
max-width: 750rpx;
background: #ffffff;
}
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 80rpx;
width: 100%;
margin-top: 330rpx;
//border:green 1px solid;
}
.logo-image {
width: 276rpx;
height: 276rpx;
}
.main-content {
padding: 0 53rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 654rpx;
//border: red 1px solid;
}
.login-btn {
width: 100%;
height: 98rpx;
background: #f15a04;
border-radius: 10rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
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;
overflow: hidden;
position: relative;
height: 0;
}
.terms-content {
padding: 20rpx;
line-height: 1.8;
font-size: 28rpx;
color: #333;
word-wrap: break-word;
word-break: break-all;
}
.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: #f15a04;
border-radius: 35rpx;
font-size: 28rpx;
color: #ffffff;
border: none;
}
</style>