app/pages/passport/login.vue

791 lines
21 KiB
Vue
Raw Normal View History

2025-03-14 16:27:50 +08:00
<template>
2025-04-21 17:39:41 +08:00
<div class="wrapper">
<div v-if="!wechatLogin">
<!-- <u-navbar :is-back="true" :border-bottom="false" :custom-back="customback"></u-navbar> -->
<div class="imgage">
<div>便捷生活畅玩无终街</div>
<!-- <div class="title">{{ loginTitleWay[current].title }}</div>
2025-03-14 16:27:50 +08:00
<div :class="current == 1 ? 'desc-light' : 'desc'">
{{ loginTitleWay[current].desc
}}<span v-if="current == 1">{{ mobile | secrecyMobile }}</span>
2025-04-21 17:39:41 +08:00
</div> -->
</div>
<!-- 手机号 -->
<div v-show="current == 0" style="padding: 0px 40px">
<u-input
:custom-style="inputStyle"
:placeholder-style="placeholderStyle"
placeholder="请输入手机号 (11位)"
class="mobile"
focus
v-model="mobile"
type="number"
maxlength="11"
/>
<div
:class="!enabuleFetchCode ? 'disable' : 'fetch'"
@click="fetchCode"
class="btn"
>
获取验证码
</div>
<div class="flex">
<u-checkbox-group :icon-size="24" width="45rpx">
<u-checkbox
shape="circle"
v-model="enabulePrivacy"
active-color="#FF5E00"
></u-checkbox>
</u-checkbox-group>
<div class="tips">
未注册的手机号验证后将自动创建用户账号登录即代表您已同意<span
@click="navigateToPrivacy('privacy')"
>使用条款及隐私协议</span
>
</div>
</div>
</div>
<!-- 输入验证码 -->
<div v-show="current == 1" class="box-code">
<verifyCode
type="bottom"
@confirm="submit"
boxActiveColor="#D8D8D8"
v-model="code"
isFocus
boxNormalColor="#D8D8D8"
cursorColor="#D8D8D8"
/>
<div class="fetch-btn">
<u-verification-code
change-text="验证码已发送x"
end-text="重新获取验证码"
unique-key="page-login"
:seconds="seconds"
@end="end"
@start="start"
ref="uCode"
@change="codeChange"
></u-verification-code>
<span @tap="fetchCode" :style="{ color: codeColor }">
{{ tips }}</span
>
</div>
</div>
<!-- 循环出当前可使用的第三方登录模式 -->
2025-04-25 18:20:19 +08:00
<!-- <div class="flex login-list">
2025-04-21 17:39:41 +08:00
<div
v-if="item.code"
:style="{ background: item.color }"
class="login-item"
v-for="(item, index) in loginList"
:key="index"
>
<u-icon
v-if="item.title != 'APPLE'"
color="#fff"
size="42"
:name="item.icon"
@click="navigateLogin(item)"
>
</u-icon>
<u-image
v-else
src="/static/appleidButton@2x.png"
:lazy-load="false"
@click="navigateLogin(item)"
width="80"
height="80"
/>
</div>
2025-04-25 18:20:19 +08:00
</div> -->
2025-04-21 17:39:41 +08:00
<myVerification
v-if="codeFlag"
@send="verification"
class="verification"
ref="verification"
business="LOGIN"
/>
</div>
<view v-else>
<wechatH5Login />
</view>
</div>
2025-03-14 16:27:50 +08:00
</template>
<script>
2025-04-21 17:39:41 +08:00
import { openIdLogin, loginCallback } from "@/api/connect.js";
import api from "@/config/api.js";
import { sendMobile, smsLogin } from "@/api/login";
import myVerification from "@/components/verification/verification.vue"; //验证码模块
import uuid from "@/utils/uuid.modified.js"; // uuid
import verifyCode from "@/components/verify-code/verify-code";
import { getUserInfo } from "@/api/members";
import { whetherNavigate } from "@/utils/Foundation"; //登录跳转
import storage from "@/utils/storage.js"; //缓存
import wechatH5Login from "./wechatH5Login.vue";
import { webConnect } from "@/api/connect.js";
export default {
components: {
myVerification,
verifyCode,
wechatH5Login,
},
data() {
return {
uuid,
wechatLogin: false, //是否加载微信公众号登录
flage: false, //是否验证码验证
codeFlag: true, //验证开关,用于是否展示验证码
tips: "",
current: 0,
codeColor: "#999", //按钮验证码颜色
lightColor: this.$lightColor,
seconds: 60, //默认验证码等待时间
loginTitleWay: [
{
title: "欢迎登录",
desc: "登录后更精彩,美好生活即将开始",
},
{
title: "请输入验证码",
desc: "已经发送验证码至",
},
],
showBack: false,
enabuleFetchCode: false,
enabulePrivacy: false, //隐私政策
mobile: "", //手机号
code: "", //验证码
inputStyle: {
height: "104rpx",
"border-bottom": "1rpx solid #D8D8D8",
"letter-spacing": "1rpx",
"font-size": "40rpx",
"line-height": "40rpx",
color: "#333",
},
placeholderStyle: "font-size: 32rpx;line-height: 32rpx;color: #999999;",
loginList: [
//第三方登录集合
{
icon: "weixin-fill",
color: "#00a327",
title: "微信",
code: "WECHAT",
},
{
icon: "qq-fill",
color: "#38ace9",
title: "QQ",
code: "QQ",
},
{
icon: "apple-fill",
color: "#000000",
title: "Apple",
code: "APPLE",
},
],
initurl: false,
};
},
onShow() {
//#ifdef H5
let isWXBrowser = /micromessenger/i.test(navigator.userAgent);
if (isWXBrowser) {
webConnect("WECHAT").then((res) => {
let data = res.data;
if (data.success) {
window.location = data.result;
}
});
}
//#endif
},
mounted() {
// #ifndef APP-PLUS
//判断是否微信浏览器
var ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
this.wechatLogin = true;
return;
}
// #endif
/**
* 条件编译判断当前客户端类型
*/
//#ifdef H5
this.clientType = "H5";
//#endif
//#ifdef APP-PLUS
this.clientType = "APP";
/**如果是app 加载支持的登录方式*/
let _this = this;
uni.getProvider({
service: "oauth",
success: (result) => {
_this.loginList = result.provider.map((value) => {
//展示title
let title = "";
//系统code
let code = "";
//颜色
let color = "#8b8b8b";
//图标
let icon = "";
//uni 联合登录 code
let appcode = "";
switch (value) {
case "weixin":
icon = "weixin-circle-fill";
color = "#00a327";
title = "微信";
code = "WECHAT";
break;
case "qq":
icon = "qq-circle-fill";
color = "#38ace9";
title = "QQ";
code = "QQ";
break;
case "apple":
icon = "apple-fill";
color = "#000000";
title = "Apple";
code = "APPLE";
break;
}
return {
title: title,
code: code,
color: color,
icon: icon,
appcode: value,
};
});
},
fail: (error) => {
uni.showToast({
title: "获取登录通道失败" + error,
duration: 2000,
icon: "none",
});
},
});
//#endif
//特殊平台,登录方式需要过滤
// #ifdef H5
this.methodFilter(["QQ"]);
// #endif
//微信小程序,只支持微信登录
// #ifdef MP-WEIXIN
this.methodFilter(["WECHAT"]);
// #endif
},
watch: {
current(val) {
val ? (this.showBack = true) : (this.showBack = false);
},
mobile: {
handler(val) {
if (val.length == 11) {
this.enabuleFetchCode = true;
}
},
},
async flage(val) {
if (val) {
if (this.$refs.uCode.canGetCode) {
// 向后端请求验证码
uni.showLoading({});
let res = await sendMobile(this.mobile);
uni.hideLoading();
// 这里此提示会被this.start()方法中的提示覆盖
if (res.data.success) {
this.current = 1;
this.$refs.uCode.start();
} else {
uni.showToast({
title: res.data.message,
duration: 2000,
icon: "none",
});
this.flage = false;
}
} else {
this.$u.toast("请倒计时结束后再发送");
}
} else {
this.$refs.verification.hide();
}
},
},
onLoad(options) {
if (options.init == "index") {
this.initurl = true;
}
if (options && options.state) {
this.stateLogin(options.state);
}
},
methods: {
customback() {
if (this.initurl) {
uni.switchTab({
url: "/pages/tabbar/vlog/index?init=ok",
});
} else {
uni.navigateBack();
}
},
//联合信息返回登录
stateLogin(state) {
loginCallback(state).then((res) => {
console.log(res);
let data = res.data;
if (data.success) {
storage.setAccessToken(data.result.accessToken);
storage.setRefreshToken(data.result.refreshToken);
// 登录成功
uni.showToast({
title: "登录成功!",
icon: "none",
});
getUserInfo().then((user) => {
storage.setUserInfo(user.data.result);
storage.setHasLogin(true);
});
getCurrentPages().length > 1
? uni.navigateBack({
delta: getCurrentPages().length - 2,
})
: uni.switchTab({
url: "/pages/tabbar/home/index",
});
}
});
},
/** 根据参数显示登录模块 */
methodFilter(code) {
let way = [];
this.loginList.forEach((item) => {
if (code.length != 0) {
code.forEach((val) => {
if (item.code == val) {
way.push(item);
}
});
} else {
uni.showToast({
title: "配置有误请联系管理员",
duration: 2000,
icon: "none",
});
}
});
this.loginList = way;
},
//非h5 获取openid
async nonH5OpenId(item) {
let _this = this;
//获取各个openid
await uni.login({
provider: item.appcode,
// #ifdef MP-ALIPAY
scopes: "auth_user", //支付宝小程序需设置授权类型
// #endif
success: function (res) {
uni.setStorageSync("type", item.code);
//微信小程序意外的其它方式直接在storage中写入openid
// #ifndef MP-WEIXIN
uni.setStorageSync("openid", res.authResult.openid);
// #endif
},
fail(e) {
uni.showToast({
title: "第三方登录暂不可用!",
icon: "none",
duration: 3000,
});
},
complete(e) {
//获取用户信息
uni.getUserInfo({
provider: item.appcode,
success: function (infoRes) {
//写入用户信息
uni.setStorageSync("nickname", infoRes.userInfo.nickName);
uni.setStorageSync("avatar", infoRes.userInfo.avatarUrl);
// #ifdef MP-WEIXIN
//微信小程序获取openid 需要特殊处理 如需获取openid请参考uni-id: https://uniapp.dcloud.net.cn/uniCloud/uni-id
_this.weixinMPOpenID(res).then((res) => {
//这里需要先行获得openid再使用openid登录小程序登录需要两步所以这里特殊编译
_this.goOpenidLogin("WECHAT_MP");
});
// #endif
// #ifndef MP-WEIXIN
_this.goOpenidLogin("APP");
//#endif
},
});
},
});
},
//openid 登录
goOpenidLogin(clientType) {
// 获取准备好的参数,进行登录系统
let params = {
uuid: uni.getStorageSync("openid"), //联合登陆id
source: uni.getStorageSync("type"), //联合登陆类型
nickname: uni.getStorageSync("nickname"), // 昵称
avatar: uni.getStorageSync("avatar"), // 头像
uniAccessToken: uni.getStorageSync("uni_access_token"), //第三方token
};
openIdLogin(params, clientType).then((res) => {
if (!res.data.success) {
let errormessage = "第三方登录暂不可用";
uni.showToast({
// title: '未绑定第三方账号',
title: errormessage,
icon: "none",
duration: 3000,
});
return;
} else {
2025-04-21 18:04:01 +08:00
var infoData = res.data.result;
storage.setAccessToken(infoData.accessToken);
storage.setRefreshToken(infoData.refreshToken);
const vlogInfo = JSON.parse(infoData.tikUser);
// 将vlog的token和vlog用户信息放入缓存
storage.setVlogToken(vlogInfo.userToken);
storage.setVlogUserInfo(vlogInfo);
2025-04-21 17:39:41 +08:00
// 登录成功
uni.showToast({
title: "第三方登录成功!",
icon: "none",
});
// 执行登录
getUserInfo().then((user) => {
if (user.data.success) {
/**
* 个人信息存储到缓存userInfo中
*/
storage.setUserInfo(user.data.result);
storage.setHasLogin(true);
/**
* 计算出当前router路径
* 1.如果跳转的链接为登录页面或跳转的链接为空页面则会重新跳转到首页
* 2.都不满足返回跳转页面
*/
whetherNavigate();
} else {
uni.switchTab({
url: "/pages/tabbar/home/index",
});
}
});
}
});
},
//微信小程序获取openid
async weixinMPOpenID(res) {
await miniProgramLogin(res.code).then((res) => {
uni.setStorageSync("openid", res.data);
});
},
/**跳转到登录页面 */
navigateLogin(connectLogin) {
// #ifdef H5
let code = connectLogin.code;
let buyer = api.buyer;
window.open(
buyer + `/passport/connect/connect/login/web/` + code,
"_self"
);
// #endif
// #ifdef APP-PLUS
this.nonH5OpenId(connectLogin);
// #endif
},
// 提交
submit() {
/**
* 清空当前账号信息
*/
storage.setHasLogin(false);
storage.setAccessToken("");
storage.setRefreshToken("");
storage.setUserInfo({});
// 清理vlog信息
storage.setVlogToken("");
storage.setVlogUserInfo({});
/**
* 执行登录
*/
smsLogin(
{
mobile: this.mobile,
code: this.code,
},
this.clientType
).then((res) => {
// console.log(res)
if (res.data.success) {
const infoData = res.data.result;
const vlogInfo = JSON.parse(infoData.tikUser);
storage.setAccessToken(infoData.accessToken);
storage.setRefreshToken(infoData.refreshToken);
// 将vlog的token和vlog用户信息放入缓存
storage.setVlogToken(vlogInfo.userToken);
storage.setVlogUserInfo(vlogInfo);
/**
* 登录成功后获取个人信息
*/
getUserInfo().then((user) => {
// console.log(user)
if (user.data.success) {
/**
* 个人信息存储到缓存userInfo中
*/
storage.setUserInfo(user.data.result);
storage.setHasLogin(true);
// 登录成功
uni.showToast({
title: "登录成功!",
icon: "none",
});
/**
* 计算出当前router路径
* 1.如果跳转的链接为登录页面或跳转的链接为空页面则会重新跳转到首页
* 2.都不满足返回跳转页面
*/
whetherNavigate();
} else {
uni.switchTab({
url: "/pages/tabbar/home/index",
});
}
});
}
});
},
// 验证码验证
verification(val) {
// console.log(val)
this.flage = val == this.$store.state.verificationKey ? true : false;
// console.log(this.flage)
},
// 跳转
navigateToPrivacy(val) {
uni.navigateTo({
url: "/pages/mine/help/tips?type=" + val,
});
},
// 点击获取验证码
start() {
this.codeColor = "#999";
this.$u.toast("验证码已发送");
this.flage = false;
this.codeFlag = false;
this.$refs.verification.hide();
},
/**点击验证码*/
codeChange(text) {
this.tips = text;
},
/** 结束验证码后执行 */
end() {
this.codeColor = this.lightColor;
this.codeFlag = true;
console.log(this.codeColor);
},
// 发送验证码
fetchCode() {
if (!this.enabulePrivacy) {
uni.showToast({
title: "请同意用户隐私",
duration: 2000,
icon: "none",
});
return false;
}
if (!this.$u.test.mobile(this.mobile)) {
uni.showToast({
title: "请填写正确手机号",
duration: 2000,
icon: "none",
});
return false;
}
if (this.tips == "重新获取验证码") {
uni.showLoading({
title: "加载中",
});
if (!this.codeFlag) {
let timer = setInterval(() => {
if (this.$refs.verification) {
this.$refs.verification.error(); //发送
}
clearInterval(timer);
}, 100);
}
uni.hideLoading();
}
if (!this.flage) {
this.$refs.verification.error(); //发送
return false;
}
},
},
};
2025-03-14 16:27:50 +08:00
</script>
<style>
2025-04-21 17:39:41 +08:00
page {
background: #fff;
}
2025-03-14 16:27:50 +08:00
</style>
<style lang="scss" scoped>
2025-04-21 17:39:41 +08:00
.wrapper {
// padding: 0 80rpx;
}
.title {
padding-top: calc(104rpx);
font-style: normal;
line-height: 1;
font-weight: 500;
font-size: 56rpx;
color: #333;
}
.box-code {
margin-top: 78rpx;
}
.desc,
.desc-light {
font-size: 32rpx;
line-height: 32rpx;
color: #333333;
margin-top: 40rpx;
}
.desc {
color: #333;
}
.desc-light {
color: #999999;
> span {
color: #333;
margin-left: 8rpx;
}
}
.mobile {
margin-top: 80rpx;
}
.disable {
// background: linear-gradient(90deg, #ffdcba 2.21%, #ffcfb2 99.86%);
background: #FE3C3C;
}
.fetch {
background: #FE3C3C;
}
.btn {
border-radius: 100px;
width: 590rpx;
margin-top: 97rpx;
height: 80rpx;
font-size: 30rpx;
line-height: 80rpx;
text-align: center;
color: #ffffff;
}
.tips {
font-size: 12px;
line-height: 20px;
margin-top: 32rpx;
width: 546rpx;
> span {
color: $light-color;
}
}
.fetch-btn {
width: 370rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background: #f2f2f2;
border-radius: 100rpx;
font-size: 28rpx;
color: #999;
margin: 71rpx auto 0 auto;
}
.login-list {
display: flex;
width: 80%;
margin: 0 auto;
margin-top: 25vh;
// position: absolute;
// bottom: 20px;
align-items: center;
justify-content: center;
}
.login-item {
width: 80rpx;
border-radius: 10rpx;
height: 80rpx;
display: flex;
justify-content: center;
align-items: center;
margin: 0 20rpx;
}
.imgage {
width: 100%;
height: 37.5vh;
background: url("./static/logn.png");
background-size: 100% 100%;
& > div {
width: 100%;
height: 80%;
display: flex;
justify-content: center;
align-items: end;
color: #fff;
font-size: 14px;
}
}
</style>