249 lines
5.6 KiB
Vue
249 lines
5.6 KiB
Vue
<!-- pages/login/login.vue -->
|
|
<template>
|
|
<view class="container">
|
|
<!-- 微信登录 -->
|
|
<template v-if="loginType === 'wxLogin'">
|
|
<view class="login-title">手机号快捷登录</view>
|
|
<view class="wx-login-container">
|
|
<template>
|
|
<view class="login-status">
|
|
<text>请授权您的手机号码完成登录</text>
|
|
</view>
|
|
<button
|
|
v-if="autoWxLoginFlag"
|
|
class="wx-login-btn"
|
|
open-type="getPhoneNumber"
|
|
@getphonenumber="getPhoneNumber"
|
|
:disabled="!isAgree"
|
|
:class="{'btn-disabled': !isAgree}"
|
|
>
|
|
<text class="btn-text">授权手机号</text>
|
|
</button>
|
|
|
|
<!-- 用户协议 -->
|
|
<view class="agreement-container">
|
|
<checkbox-group @change="handleAgreeChange">
|
|
<label class="agreement-item">
|
|
<checkbox :checked="isAgree" color="#07c160" style="transform:scale(0.7)" />
|
|
<text class="agreement-text">我已阅读并同意</text>
|
|
<text class="agreement-link" @tap.stop="openUserAgreement">《用户协议》</text>
|
|
<text class="agreement-text">和</text>
|
|
<text class="agreement-link" @tap.stop="openPrivacyPolicy">《隐私政策》</text>
|
|
</label>
|
|
</checkbox-group>
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</template>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { getWeChatOpenId } from '@/api/user/user.ts'
|
|
import useUserStore from "@/stores/user/useUserStore"
|
|
import { doWxLogin } from "./hooks/login.ts"
|
|
|
|
const userStore = useUserStore();
|
|
const isRegister = ref(false);
|
|
const inviteCode = ref("");
|
|
const userInfo = ref({});
|
|
const isAgree = ref(false);
|
|
const phoneParams = ref({});
|
|
const loginType = ref("wxLogin");
|
|
const autoWxLoginFlag = ref(false);
|
|
|
|
|
|
// 生命周期
|
|
onLoad((options) => {
|
|
isRegister.value = options.isRegister == 0;
|
|
loginType.value = options.loginType || "wxLogin";
|
|
if (options.inviteCode) {
|
|
inviteCode.value = options.inviteCode;
|
|
}
|
|
autoWxLogin();
|
|
});
|
|
|
|
const getAppId = () => {
|
|
const appId = uni.getAccountInfoSync().miniProgram.appId;
|
|
return appId;
|
|
};
|
|
|
|
const autoWxLogin = () => {
|
|
uni.login({
|
|
provider: 'weixin',
|
|
success: function (loginRes) {
|
|
// 登录成功后显示提示用户需要点击授权
|
|
uni.showModal({
|
|
title: '登录提示',
|
|
content: '请点击下方按钮授权手机号来完成登录',
|
|
showCancel: false,
|
|
success: () => {
|
|
autoWxLoginFlag.value = true;
|
|
}
|
|
});
|
|
},
|
|
fail: (err) => {
|
|
console.error('微信登录失败:', err)
|
|
uni.showToast({
|
|
title: '微信登录失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const getOpenID = async (code) => {
|
|
try {
|
|
const { data } = await getWeChatOpenId({ code });
|
|
phoneParams.value = {
|
|
sessionKey: data.session_key,
|
|
openid: data.openid,
|
|
unionid: data?.unionid ?? "",
|
|
};
|
|
uni.showToast({ title: "请授权手机号", icon: "none" });
|
|
} catch (error) {
|
|
console.error("获取OpenID失败:", error);
|
|
}
|
|
};
|
|
|
|
const getPhoneNumber = async (e) => {
|
|
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
|
uni.showToast({ title: "需要授权手机号才能登录", icon: "none" });
|
|
return
|
|
}
|
|
|
|
if (!isAgree.value) {
|
|
uni.showToast({ title: "请先同意用户协议和隐私政策", icon: "none" });
|
|
return
|
|
}
|
|
|
|
uni.login({
|
|
provider: 'weixin',
|
|
success: function (loginRes) {
|
|
const params = {
|
|
openIdCode: loginRes.code,
|
|
phoneCode: e.detail.code,
|
|
appId: getAppId()
|
|
}
|
|
uni.showLoading({
|
|
title: '登录中...',
|
|
mask: true
|
|
})
|
|
doWxLogin(params).then((res) => {
|
|
uni.hideLoading()
|
|
/* uni.reLaunch({
|
|
url: '/pages/index/index'
|
|
}) */
|
|
}).catch(err => {
|
|
uni.hideLoading()
|
|
uni.showToast({
|
|
title: err.msg || '登录失败,请重试',
|
|
icon: 'none'
|
|
})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// 同意协议变更
|
|
const handleAgreeChange = (e) => {
|
|
isAgree.value = e.detail.value.length > 0;
|
|
}
|
|
|
|
// 打开用户协议
|
|
const openUserAgreement = () => {
|
|
uni.navigateTo({
|
|
url: '/pages/agreement/user-agreement'
|
|
})
|
|
}
|
|
|
|
// 打开隐私政策
|
|
const openPrivacyPolicy = () => {
|
|
uni.navigateTo({
|
|
url: '/pages/agreement/privacy-policy'
|
|
})
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import "./login.scss";
|
|
|
|
.login-status {
|
|
margin: 80rpx 0 40rpx;
|
|
color: #333;
|
|
font-size: 30rpx;
|
|
text-align: center;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.agreement-container {
|
|
margin-top: 40rpx;
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.agreement-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.agreement-text {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.agreement-link {
|
|
font-size: 26rpx;
|
|
color: #07c160;
|
|
}
|
|
|
|
.wx-login-btn {
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: -50%;
|
|
left: -50%;
|
|
width: 200%;
|
|
height: 200%;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
transform: rotate(45deg);
|
|
opacity: 0;
|
|
}
|
|
|
|
&:active::after {
|
|
animation: btnRipple 0.6s ease-out;
|
|
}
|
|
|
|
.btn-text {
|
|
font-weight: 500;
|
|
letter-spacing: 4rpx;
|
|
}
|
|
}
|
|
|
|
.btn-disabled {
|
|
opacity: 0.6;
|
|
background: linear-gradient(135deg, #cccccc, #aaaaaa) !important;
|
|
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1) !important;
|
|
}
|
|
|
|
@keyframes btnRipple {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translate(-50%, -50%) rotate(45deg) scale(0);
|
|
}
|
|
50% {
|
|
opacity: 0.5;
|
|
}
|
|
100% {
|
|
opacity: 0;
|
|
transform: translate(-50%, -50%) rotate(45deg) scale(2);
|
|
}
|
|
}
|
|
</style>
|