Files
frontend-app/pages/login_package/login/login.vue
T
2026-08-17 17:13:40 +08:00

746 lines
21 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="login_warp">
<u-icon size="30rpx" name="arrow-left" color="#333" @click="onBack"></u-icon>
<view class="login_logo_warp">
<view style="text-align: center">
<up-image src="/static/logo.png" width="90" height="118" bgColor="#f1f6ff00" radius="10"></up-image>
</view>
<!-- <view style="margin-top: 20rpx;">
<up-image src="/static/logo_z.png" width="100" height="40" bgColor="#f1f6ff00"></up-image>
</view> -->
</view>
<view class="login_info">
<view class="login_info_item">
<up-input placeholder="请输入手机号/账户名称" border="surround" v-model="form.name" :customStyle="inputCss"
:adjust-position="false" @change="checkNameParam"></up-input>
<qiaobao-assistant page-key="pages/login_package/login/login" title="账户登录" />
</view>
<!-- 密码登录 -->
<view class="login_info_item" v-if="loginWay === 'password'">
<up-input placeholder="请输入密码" border="surround" v-model="form.password" :customStyle="inputCss"
:type="isShow ? 'text' : 'password'" :adjust-position="false" @change="checkParam">
<template #suffix style="margin-right: 10rpx">
<up-image v-if="isShow" src="/pages/login_package/static/login/show.png" width="20" height="20"
bgColor="#f1f6ff00" @click="isShow = false"></up-image>
<up-image v-else src="/pages/login_package/static/login/hidden.png" width="20" height="20"
bgColor="#f1f6ff00" @click="isShow = true"></up-image>
</template>
</up-input>
</view>
<!-- 验证码登录 -->
<view class="login_info_item" v-else>
<up-input placeholder="请输入验证码" border="surround" v-model="form.code" :customStyle="inputCss"
:adjust-position="false">
<template #suffix style="margin-right: 10rpx">
<view v-if="countdown" class="code-warp">
<up-count-down :time="60 * 1000" format="ss" @finish="countdown = false"></up-count-down>
<text style="margin-left: 10rpx">s</text>
</view>
<view v-else @click="getMobileCode" class="code_msg">
获取验证码
</view>
</template>
</up-input>
</view>
<view class="login_comm_but login_comm_but_yes" @click="loginFun">
<text style="margin-left: 10rpx">登录</text>
</view>
<view class="cut_way_warp">
<view v-if="loginWay === 'password'" @click="loginWay = 'code'">验证码登录</view>
<view v-if="loginWay === 'code'" @click="loginWay = 'password'">密码登录登录</view>
<view @click="jumpForgot">忘记密码</view>
<view @click="jumpRegister">注册</view>
</view>
</view>
<view>
<!-- #ifdef APP-PLUS -->
<view class="other_login">其他登录方式</view>
<view class="login_other_icon">
<view class="login_other_item" @click="wechatOneLogin(2)">
<up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44"
bgColor="#f1f6ff00"></up-image>
微信登录
</view>
<!-- <view class="login_other_item" @click="aa"> -->
<view v-if="!isIOS" class="login_other_item" @click="alipayOneLogin">
<up-image src="/pages/login_package/static/login/ZFB.png" width="44" height="44"
bgColor="#f1f6ff00"></up-image>
支付宝登录
</view>
<view v-if="isIOS" class="login_other_item" @click="appleOneLogin">
<up-icon name="apple-fill" size="44" color="#000000"></up-icon>
Apple登录
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view class="other_login">其他登录方式</view>
<view class="login_other_icon">
<view class="login_other_item" @click="wechatOneLogin(1)">
<up-image src="/pages/login_package/static/login/WXICON.png" width="44" height="44"
bgColor="#f1f6ff00"></up-image>
微信登录
</view>
</view>
<view class="login_other_icon">
<view class="login_other_item_you" @click="jumpHome">
游客模式
</view>
</view>
<!-- #endif -->
</view>
<view class="policy_warp">
<up-checkbox name="isCheck" usedAlone v-model:checked="isPolicy" shape="circle" activeColor="#7934F6" size="19"
iconSize="18">
<template #label>
<text>已阅读并同意</text>
<text class="policy_a_warp" @click="jumpUserAgreement">《服务协议》</text>
<text>、</text>
<text class="policy_a_warp" @click="jumpPrivacyAgreement">《隐私政策》</text>
<text>、</text>
<text class="policy_a_warp" @click="jumpProductAgreement">《售后保障协议》</text>
</template>
</up-checkbox>
</view>
<up-toast ref="uToastRef"></up-toast>
<!-- 自定义协议弹窗 -->
<view v-if="showPolicyModal" class="modal-overlay" @click="showPolicyModal = false">
<view class="modal-content" @click.stop>
<view class="modal-title">温馨提示</view>
<view class="modal-message">请您阅读并同意《服务协议》与《隐私政策》</view>
<view class="modal-buttons">
<view class="modal-btn modal-btn-cancel" @click="showPolicyModal = false">取消</view>
<view class="modal-btn modal-btn-confirm" @click="handlePolicyConfirm">同意并登录</view>
</view>
</view>
</view>
</view>
</template>
<script>
import InputCodeComm from "@/pages/login_package/components/code-comm/code-comm.vue";
import {
SMS_TYPE
} from "@/utils/enumUtils.js";
import {
getUserList
} from "@/api/common.js";
import {
loginbysms,
loginbypw,
wechatLogin,
alipayLogin,
appleLogin
} from "@/api/auth.js";
import {
setStorageFun,
TOKEN_NAME,
USER_KEY,
USER_DATA,
USER_LOGIN_TIME,
} from "@/utils/auth.js";
import CryptoJS from "crypto-js";
// #ifdef APP-PLUS
const hyyAlipay = uni.requireNativePlugin("Hyy-Alipay");
// #endif
export default {
onLaunch: function () {
console.log("App Launch");
const res = uni.getSystemInfoSync();
uni.setStorageSync("platform", res.platform);
// #ifdef APP-PLUS
// 获取应用版本信息
plus.runtime.getProperty(plus.runtime.appid, function (inf) {
console.log("版本信息", inf.versionCode);
uni.setStorageSync("version-1", inf.version); // 大版本号
uni.setStorageSync("versionCode", inf.versionCode); // 小版本号
});
let uuid = plus.device.uuid;
// #endif
},
components: {
InputCodeComm,
},
data() {
return {
form: {
name: null,
password: null,
code: null,
},
inputCss: {
height: "80rpx",
background: "#F3F3F3FF",
"border-radius": "30rpx",
border: "0rpx",
"padding-left": "16px",
},
loginWay: "password",
isShow: false, // 是否显示
isPolicy: false, // 是否同意
countdown: false, // 清空倒计时
loading: false,
showPolicyModal: false,
};
},
methods: {
onBack() {
console.log('onBack',)
uni.switchTab({
url: '/pages/home/home'
})
},
aa() {
const nativiPlugin = uni.requireNativePlugin('WITTestUniPlugin');
console.log("隐藏原生tabbar", nativiPlugin)
nativiPlugin.testAsyncFunc({},
(ret) => {
uni.showToast({
title: '调用异步方法 ' + ret,
icon: "none"
})
console.log(ret);
});
},
jumpHome() {
// const sysPlatform = getCurrentSysPlatform();
// if(sysPlatform === "android"){
// uni.switchTab({
// url: '/pages/message/message',
// })
// }else{
uni.switchTab({
url: "/pages/home/home",
});
// }
},
async loginFun(val = {}) {
const then = this;
const form = this.form;
const params = {};
if (!this.isPolicy) {
this.showPolicyModal = true;
return;
}
let response = val;
if (this.loginWay === "password") {
params.mobile = form.name;
params.password = CryptoJS.MD5(form.password).toString();
response = await loginbypw(params);
}
if (this.loginWay === "code") {
params.mobile = form.name;
params.smsCode = form.code;
response = await loginbysms(params);
}
const data = response.data;
setStorageFun(TOKEN_NAME, data.token);
// 用于无感登录
setStorageFun(USER_KEY, "");
const userInfo = {
avatar: data.avatarUrl,
name: data.name,
userId: data.userId,
grade: data.grade,
inviteCode: data.inviteCode,
};
setStorageFun(USER_DATA, userInfo);
// 当前登录得时间戳
let currentTimeStamp = new Date().getTime();
setStorageFun(USER_LOGIN_TIME, currentTimeStamp);
const res = uni.getSystemInfoSync();
uni.setStorageSync('platform', res.platform);
// #ifdef APP-PLUS         
// 获取应用版本信息
plus.runtime.getProperty(plus.runtime.appid, function (inf) {
console.log("版本信息", inf.versionCode)
uni.setStorageSync('version-1', inf.version); // 大版本号
uni.setStorageSync('versionCode', inf.versionCode); // 小版本号
});
let uuid = plus.device.uuid;
// #endif
this.$refs.uToastRef.show({
type: "success",
message: response.msg,
});
setTimeout(() => {
then.jumpHome();
}, 2000);
},
checkNameParam(val) {
// console.log("val",val);
},
checkParam(val) {
// console.log("val",val);
},
/**
* 获取手机验证码
*/
async getMobileCode() {
const form = this.form;
if (!form.name) {
this.$refs.uToastRef.show({
type: "error",
message: "请输入账号",
});
return;
}
this.countdown = true;
const params = {
mobile: form.name,
type: SMS_TYPE.LOGIN,
};
const response = await getUserList(params);
console.log("responseresponseresponse", response);
if (response && response.bizcode === 100) {
this.$refs.uToastRef.show({
type: "success",
message: response.msg,
});
} else {
this.countdown = false;
}
},
jumpForgot() {
uni.navigateTo({
url: "/pages/rwa_package/setting/forgot-pass?type=3",
});
},
jumpRegister() {
uni.navigateTo({
url: "/pages/login_package/register/register",
});
},
// 用户协议
jumpUserAgreement() {
uni.navigateTo({
url: "/pages/mine_package/mine_user_agreement/mine_user_agreement?backPath=login",
});
},
// 隐私协议
jumpPrivacyAgreement() {
uni.navigateTo({
url: "/pages/mine_package/mine_privacy_agreement/mine_privacy_agreement?backPath=login",
});
},
// 售后保障协议
jumpProductAgreement() {
uni.navigateTo({
url: "/pages/mine_package/mine_product_agreement/mine_product_agreement?backPath=login",
});
},
// 微信登录
async wechatOneLogin(type) {
const then = this;
this.loading = true;
console.log("微信登录--1", this.isPolicy)
// 检查是否同意协议
if (!this.isPolicy) {
uni.showModal({
title: '温馨提示',
content: '请您阅读并同意《服务协议》与《隐私政策》',
confirmText: "同意登录",
success: (res) => {
if (res.confirm) {
this.isPolicy = true;
this.wechatOneLogin(type);
} else {
this.loading = false;
}
},
fail: (err) => {
this.loading = false;
console.log('showModal error:', err);
}
});
return;
}
try {
// 1. 调用微信登录API
uni.login({
provider: "weixin",
onlyAuthorize: true,
success: async (loginRes) => {
console.log("微信登录成功:", loginRes);
// 2. 发送code到后端换取token
const params = {
isValid: false,
token: loginRes.code,
type
// 可以根据需要添加其他参数
};
console.log("微信登录接口返回-1:", params);
const response = await wechatLogin(params);
console.log(
"微信登录接口返回-2:",
response,
response.data,
response.data.token
);
if (response && response.bizcode === 100) {
if (response.data.userId) {
// 登录
this.loginWay = "wechat";
this.loginFun(response);
} else {
// 去微信注册
uni.navigateTo({
url: `/pages/login_package/bind-phone/bind-phone?token=${response.data.token}&type=1`,
});
}
} else {
this.$refs.uToastRef.show({
type: "error",
message: response.msg || "微信登录失败",
});
}
},
fail: (err) => {
this.loading = false;
console.error("微信登录失败:", err);
this.$refs.uToastRef.show({
type: "error",
message: "微信登录失败,请重试",
});
},
});
} catch (error) {
this.loading = false;
console.error("微信登录异常:", error);
this.$refs.uToastRef.show({
type: "error",
message: "微信登录异常,请重试",
});
}
},
// 支付宝一键登录
async alipayOneLogin() {
const then = this;
this.loading = true;
console.log("支付宝登录", hyyAlipay);
// 检查是否同意协议
if (!this.isPolicy) {
uni.showModal({
title: '温馨提示',
content: '请您阅读并同意《服务协议》与《隐私政策》',
confirmText: "同意登录",
success: (res) => {
if (res.confirm) {
this.isPolicy = true;
this.alipayOneLogin();
} else {
this.loading = false;
}
},
fail: (err) => {
this.loading = false;
console.log('showModal error:', err);
}
});
return;
}
hyyAlipay.openAuthScheme({
appId: "2021005183625053", // 支付宝分配给开发者的应用 ID
scheme: "trustbridgeapp", // manifest.json -> "App常用其他设置" -> "UrlSchemes"里设置
},
(res) => {
console.log("支付宝回调", res);
alipayLogin({
isValid: false,
token: res.auth_code,
}).then((response) => {
console.log("支付宝登录接口返回:", response, !response.data.userId);
if (response && response.bizcode === 100) {
if (response.data.userId) {
// 登录
this.loginWay = "alipay";
this.loginFun(response);
} else {
// 去微信注册
uni.navigateTo({
url: `/pages/login_package/bind-phone/bind-phone?token=${response.data.token}&type=2`,
});
}
} else {
this.$refs.uToastRef.show({
type: "error",
message: response.msg || "微信登录失败",
});
}
});
}
);
},
handlePolicyConfirm() {
this.showPolicyModal = false;
this.isPolicy = true;
this.loginFun();
},
// Apple 登录 (仅 App iOS 端)
async appleOneLogin() {
this.loading = true;
// 检查是否同意协议
if (!this.isPolicy) {
uni.showModal({
title: '温馨提示',
content: '请您阅读并同意《服务协议》与《隐私政策》',
confirmText: "同意登录",
success: (res) => {
if (res.confirm) {
this.isPolicy = true;
this.appleOneLogin();
} else {
this.loading = false;
}
},
fail: (err) => {
this.loading = false;
console.log('showModal error:', err);
}
});
return;
}
// #ifdef APP-PLUS
uni.getProvider({
service: 'oauth',
success: (provRes) => {
if (!provRes.provider || !provRes.provider.includes('apple')) {
this.loading = false;
this.$refs.uToastRef.show({
type: "error",
message: "当前运行环境或自定义基座未支持 Apple 登录",
});
return;
}
uni.login({
provider: 'apple',
success: async (loginRes) => {
console.log('Apple 登录成功:', loginRes);
const authResult = loginRes.appleInfo || {};
const params = {
identityToken: authResult.identityToken,
// openId: authResult.user,
// fullName: authResult.fullName ? `${authResult.fullName.familyName || ''}${authResult.fullName.givenName || ''}` : '',
// authorizationCode: authResult.authorizationCode
};
console.log("Apple 登录成功-0:", params)
try {
const response = await appleLogin(params);
console.log("Apple 登录成功-1:", response)
if (response && response.bizcode === 100) {
if (response.data && response.data.userId) {
this.loginWay = "apple";
this.loginFun(response);
} else {
uni.navigateTo({
url: `/pages/login_package/bind-phone/bind-phone?token=${response.data.token}&type=3`,
});
}
} else {
console.log("Apple 登录成功-2:", response)
this.$refs.uToastRef.show({
type: "error",
message: response?.msg || "Apple登录失败",
});
}
} catch (error) {
console.error("Apple登录异常:", error);
this.$refs.uToastRef.show({
type: "error",
message: "Apple登录异常,请重试",
});
} finally {
this.loading = false;
}
},
fail: (err) => {
this.loading = false;
console.error('Apple登录授权失败:', err);
this.$refs.uToastRef.show({
type: "error",
message: "Apple登录授权失败",
});
}
});
// #endif
},
})
}
},
computed: {
isIOS() {
// #ifdef APP-PLUS
return uni.getSystemInfoSync().platform === "ios";
// #endif
return false;
},
},
};
</script>
<style lang="scss" scoped>
.login_warp {
height: calc(100vh - 400rpx);
padding: 150rpx 50rpx 0;
}
.login_logo_warp {
display: grid;
justify-content: center;
}
.login_info {
margin-top: 60rpx;
.login_info_item {
margin-bottom: 40rpx;
}
.code_msg {
font-size: 36rpx;
color: $app-bt-bj;
}
}
.login_comm_but {
background: #cccccc;
border-radius: 20rpx;
width: 100%;
text-align: center;
font-weight: 500;
font-size: 32rpx;
color: #999999;
padding: 28rpx 0;
display: flex;
justify-content: center;
}
.login_comm_but_yes {
background: $app-bt-bj;
color: #ffffff;
}
.cut_way_warp {
display: flex;
justify-content: space-between;
font-weight: 500;
font-size: 28rpx;
color: #999999;
margin-top: 20rpx;
}
.other_login {
font-size: 28rpx;
text-align: center;
margin-top: 80rpx;
margin-bottom: 32rpx;
color: #999999;
}
.login_other_icon {
display: flex;
padding: 0 100rpx;
justify-content: center;
.login_other_item {
display: flex;
flex: 50%;
font-size: 28rpx;
flex-direction: column;
align-items: center;
margin-bottom: 80rpx;
}
.login_other_item_you {
width: 500rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #7934F6;
color: #7934F6;
border-radius: 10rpx;
}
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
width: 500rpx;
background: #fff;
border-radius: 20rpx;
padding: 24rpx;
text-align: center;
}
.modal-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
}
.modal-message {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 40rpx;
}
.modal-buttons {
display: flex;
}
.modal-btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
}
.modal-btn-cancel {
color: #999;
border-right: 1rpx solid #eee;
}
.modal-btn-confirm {
color: #7934F6;
}
</style>