mirror of
http://36.133.248.69:3088/admin/RentWeAppFront.git
synced 2026-06-07 06:22:27 +08:00
239 lines
5.1 KiB
Vue
239 lines
5.1 KiB
Vue
<template>
|
||
<view class="login-container">
|
||
<customNavbar opacity="0" :show-home="true" :show-back="false" :is-transparent="true" />
|
||
|
||
<view class="content">
|
||
<view class="title">登录</view>
|
||
|
||
<view class="illustration">
|
||
<image :src="staticHost + '/public/static/login/bg.png'" mode="aspectFit" />
|
||
</view>
|
||
|
||
<button class="login-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhone">
|
||
手机号快捷登录
|
||
</button>
|
||
|
||
<view class="user-type">
|
||
<u-radio-group v-model="loginType" active-color="#EA414A" shape="square">
|
||
<u-radio name="0">个人</u-radio>
|
||
<u-radio name="1">企业</u-radio>
|
||
</u-radio-group>
|
||
</view>
|
||
|
||
<view class="agreement">
|
||
<u-checkbox v-model="agreeProtocol" shape="square" active-color="#EA414A">
|
||
<text class="agreement-text">
|
||
我已阅读并同意
|
||
<text class="link" @tap.stop="goPrivacy('user')">《用户协议》</text>
|
||
和
|
||
<text class="link" @tap.stop="goPrivacy('privacy')">《隐私政策》</text>
|
||
</text>
|
||
</u-checkbox>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
loginType: "0",
|
||
agreeProtocol: false
|
||
};
|
||
},
|
||
computed: {
|
||
staticHost() {
|
||
return this.$config.staticUrl;
|
||
}
|
||
},
|
||
methods: {
|
||
// 微信获取手机号(修复版)
|
||
async onGetPhone(e) {
|
||
// 用户拒绝
|
||
if (e.detail.errMsg !== "getPhoneNumber:ok") {
|
||
this.$mytip.toast("已取消授权");
|
||
return;
|
||
}
|
||
|
||
// 必须勾选协议
|
||
if (!this.agreeProtocol) {
|
||
this.$mytip.toast("请先同意用户协议与隐私政策");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 1. 先拿微信登录 code
|
||
const loginRes = await new Promise((resolve, reject) => {
|
||
uni.login({
|
||
provider: "weixin",
|
||
success: resolve,
|
||
fail: reject
|
||
});
|
||
});
|
||
|
||
// 2. 传给后端登录
|
||
await this.doLogin({
|
||
loginCode: loginRes.code,
|
||
encryptedData: e.detail.encryptedData,
|
||
iv: e.detail.iv,
|
||
loginType: this.loginType
|
||
});
|
||
|
||
} catch (err) {
|
||
this.$mytip.toast("授权失败,请重试");
|
||
}
|
||
},
|
||
|
||
// 登录接口(修复:用户信息 + 全局刷新)
|
||
async doLogin(data) {
|
||
uni.showLoading({ title: "登录中...", mask: true });
|
||
|
||
try {
|
||
// 1. 登录拿 token
|
||
const authRes = await this.$u.post("/login/weChatLogin", data);
|
||
const token = authRes.data;
|
||
|
||
if (!token) {
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录失败");
|
||
return;
|
||
}
|
||
|
||
// 2. 保存 token(全局)
|
||
this.$u.vuex("vuex_token", token);
|
||
|
||
// 3. 获取并保存用户信息(修复:必须 await 等它完成)
|
||
await this.getUserOtherInfo(this.loginType, token);
|
||
|
||
// 4. 登录成功 → 强制刷新全局状态 + 跳首页
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录成功");
|
||
|
||
// 🔥 关键:强制刷新页面,解决用户信息不显示
|
||
setTimeout(() => {
|
||
uni.switchTab({
|
||
url: "/pages/index/index",
|
||
success() {
|
||
const page = getCurrentPages().pop();
|
||
if (page) page.onLoad();
|
||
}
|
||
});
|
||
}, 500);
|
||
|
||
} catch (err) {
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录失败,请稍后重试");
|
||
}
|
||
},
|
||
|
||
// 获取用户信息(修复:必须返回 Promise)
|
||
getUserOtherInfo(loginType, token) {
|
||
return new Promise((resolve, reject) => {
|
||
this.$u.get("/login/userInfo", {}, {
|
||
"WT": token,
|
||
"USERTYPE": loginType
|
||
}).then(obj => {
|
||
if (obj?.flag) {
|
||
// 🔥 保存用户信息到缓存
|
||
uni.setStorageSync('userInfo', obj.data);
|
||
|
||
// 🔥 同时存入 vuex 全局状态(首页就能实时刷新)
|
||
this.$u.vuex('vuex_userInfo', obj.data);
|
||
}
|
||
resolve();
|
||
}).catch(() => {
|
||
resolve();
|
||
});
|
||
});
|
||
},
|
||
|
||
// 返回
|
||
goBack() {
|
||
uni.navigateBack({ delta: 1 });
|
||
},
|
||
|
||
// 协议
|
||
goPrivacy(type) {
|
||
const url = type === "user"
|
||
? "/pages-biz/privacy/userAgreement"
|
||
: "/pages-biz/privacy/privacyPolicy";
|
||
uni.navigateTo({ url });
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.login-container {
|
||
height: 100vh;
|
||
background: #fff;
|
||
padding-top: var(--status-bar-height);
|
||
}
|
||
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 0 40rpx;
|
||
margin-top: 200rpx;
|
||
}
|
||
|
||
.title {
|
||
font-size: 48rpx;
|
||
font-weight: 500;
|
||
color: #222;
|
||
margin-bottom: 60rpx;
|
||
}
|
||
|
||
.illustration {
|
||
width: 100%;
|
||
height: 400rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 60rpx;
|
||
|
||
image {
|
||
width: 80%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.login-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: linear-gradient(90deg, #FF2F31 0%, #FF9379 100%);
|
||
border-radius: 49rpx;
|
||
font-size: 36rpx;
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 40rpx;
|
||
border: none;
|
||
}
|
||
|
||
.user-type {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 40rpx;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.agreement {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.agreement-text {
|
||
font-size: 26rpx;
|
||
color: #cecece;
|
||
}
|
||
|
||
.link {
|
||
color: #334254;
|
||
}
|
||
</style> |