Lufaneng 11 months ago
parent 1f735c5c53
commit d9b50796c1

@ -1,3 +1,8 @@
<!-- #ifdef H5 -->
<!-- 可选引入微信JS-SDK用于更高级的微信功能 -->
<!-- <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> -->
<!-- #endif -->
<template> <template>
<view class="container"> <view class="container">
<view class="header"> <view class="header">
@ -6,129 +11,559 @@
</view> </view>
<div class="main"> <div class="main">
<view class="form"> <view class="form">
<uv-form labelAlign="right" labelWidth="50" labelPosition="top" :model="userInfo" :rules="rules" <uv-form
ref="form"> labelAlign="right"
labelWidth="50"
labelPosition="top"
:model="userInfo"
:rules="rules"
ref="form"
>
<uv-form-item prop="phone"> <uv-form-item prop="phone">
<div class="formLabel"> <div class="formLabel">
<img class="img" src="/static/imgs/phone.png" alt=""> <img class="img" src="/static/imgs/phone.png" alt="" />
手机号 手机号
</div> </div>
<uv-input v-model="userInfo.phone" color="#000" border="bottom" <uv-input
:placeholderStyle="{color:'#666778'}" placeholder="请输入用户名"> v-model="userInfo.phone"
</uv-input> color="#000"
border="bottom"
:placeholderStyle="{ color: '#666778' }"
placeholder="请输入用户名"
></uv-input>
</uv-form-item> </uv-form-item>
<uv-form-item prop="password"> <uv-form-item prop="password">
<div class="formLabel"> <div class="formLabel">
<img class="img" src="/static/imgs/code.png" alt=""> <img class="img" src="/static/imgs/code.png" alt="" />
验证码 验证码
</div> </div>
<uv-input v-model="userInfo.password" color="#000" border="bottom" <uv-input
:placeholderStyle="{color:'#666778'}" placeholder="请输入验证码"> v-model="userInfo.password"
color="#000"
border="bottom"
:placeholderStyle="{ color: '#666778' }"
placeholder="请输入验证码"
>
<template v-slot:suffix> <template v-slot:suffix>
<uv-code ref="codeRef" @change="codeChange" seconds="20" changeText="X秒重新获取"></uv-code> <uv-code
<text style="color:#4D82FD" @click="getCode">{{tips}}</text> ref="codeRef"
@change="codeChange"
seconds="20"
changeText="X秒重新获取"
></uv-code>
<text style="color: #4d82fd" @click="getCode">{{ tips }}</text>
</template> </template>
</uv-input> </uv-input>
</uv-form-item> </uv-form-item>
</uv-form> </uv-form>
</view> </view>
<uv-button @click="login" customStyle="margin-top:30px" text="登录" color="#3F70FF"></uv-button> <uv-button
<div class="wechatBox"> @click="login"
customStyle="margin-top:30px"
text="登录"
color="#3F70FF"
></uv-button>
<div class="wechatBox" v-if="showWechatLogin">
<uv-divider text="第三方登录"></uv-divider> <uv-divider text="第三方登录"></uv-divider>
<uv-icon name="weixin-circle-fill" color="#5fc157" size="50"></uv-icon> <uv-icon
name="weixin-circle-fill"
color="#5fc157"
size="50"
@click="wechatLogin"
></uv-icon>
</div> </div>
</div> </div>
<!-- 微信登录绑定手机号弹窗 -->
<uv-popup
ref="popup"
mode="center"
:closeOnClickOverlay="false"
:round="10"
>
<view class="bind-phone-modal">
<view class="modal-header">
<view class="modal-title">绑定手机号</view>
<view class="modal-subtitle">为了您的账户安全请绑定手机号</view>
</view>
<view class="modal-form">
<uv-form
:model="bindPhoneInfo"
:rules="bindPhoneRules"
ref="bindPhoneForm"
>
<uv-form-item prop="phone">
<uv-input
v-model="bindPhoneInfo.phone"
placeholder="请输入手机号"
type="number"
maxlength="11"
border="surround"
></uv-input>
</uv-form-item>
<uv-form-item prop="code">
<uv-input
v-model="bindPhoneInfo.code"
placeholder="请输入验证码"
border="surround"
>
<template v-slot:suffix>
<uv-code
ref="bindCodeRef"
@change="bindCodeChange"
seconds="60"
changeText="X秒重新获取"
></uv-code>
<text
style="color: #4d82fd; font-size: 12px"
@click="getBindCode"
>
{{ bindCodeTips }}
</text>
</template>
</uv-input>
</uv-form-item>
</uv-form>
</view>
<view class="modal-actions">
<!-- <uv-button
type="default"
@click="closeBindPhoneModal"
customStyle="margin-right: 12px;"
>
取消
</uv-button> -->
<uv-button
type="primary"
@click="confirmBindPhone"
:loading="bindingPhone"
>
确认绑定
</uv-button>
</view>
</view>
</uv-popup>
</view> </view>
</template> </template>
<script setup> <script setup>
import { import { ref, onMounted } from "vue";
ref
} from "vue";
import { import {
HOME_PATH, HOME_PATH,
LOGIN_PATH, LOGIN_PATH,
isTabBarPath, isTabBarPath,
removeQueryString, removeQueryString,
} from "@/router"; } from "@/router";
import { import { useAuthStore, useUserStore } from "@/store";
useAuthStore, import { onLoad } from "@dcloudio/uni-app";
useUserStore
} from "@/store"; import RPC from "@/utils/request";
import {
onLoad
} from "@dcloudio/uni-app";
import RPC from "@/utils/request" const authStore = useAuthStore();
const userStore = useUserStore();
const authStore = useAuthStore() //
const userStore = useUserStore() const showWechatLogin = ref(false);
const tips = ref('获取验证码') //
// const showBindPhoneModal = ref(false);
const popup = ref(null);
const bindingPhone = ref(false);
const bindCodeTips = ref("获取验证码");
const bindCodeRef = ref(null);
const bindPhoneForm = ref(null);
const bindPhoneInfo = ref({
phone: "",
code: "",
});
const bindPhoneRules = ref({
phone: [
{
required: true,
message: "请输入手机号",
trigger: ["blur", "change"],
},
{
pattern: /^1[3-9]\d{9}$/,
message: "请输入正确的手机号",
trigger: ["blur", "change"],
},
],
code: {
required: true,
message: "请输入验证码",
trigger: ["blur", "change"],
},
});
const tips = ref("获取验证码");
const codeChange = (text) => { const codeChange = (text) => {
tips.value = text tips.value = text;
} };
const codeRef = ref(null) const codeRef = ref(null);
const getCode = () => { const getCode = () => {
if (!userInfo.phone) { if (!userInfo.phone) {
uni.showToast({ uni.showToast({
title:'请填写手机号', title: "请填写手机号",
icon:'none' icon: "none",
}); });
return return;
} }
if (codeRef.value.canGetCode) { if (codeRef.value.canGetCode) {
// //
uni.showLoading({ uni.showLoading({
title: '正在获取验证码' title: "正在获取验证码",
}) });
setTimeout(() => { setTimeout(() => {
uni.hideLoading(); uni.hideLoading();
// this.start() // this.start()
uni.showToast({ uni.showToast({
title:'验证码已发送', title: "验证码已发送",
icon:'none' icon: "none",
}); });
// //
codeRef.value.start(); codeRef.value.start();
}, 2000); }, 2000);
} else { } else {
uni.showToast({ uni.showToast({
title:'倒计时结束后再发送', title: "倒计时结束后再发送",
icon:'none' icon: "none",
}) });
}
} }
};
const form = ref(null);
const form = ref(null)
const userInfo = ref({ const userInfo = ref({
phone: '', phone: "",
password: '', password: "",
}) });
const rules = ref({ const rules = ref({
'phone': { phone: [
{
required: true, required: true,
message: '请填写手机号', message: "请输入手机号",
trigger: ['blur', 'change'] trigger: ["blur", "change"],
}, },
'password': { {
pattern: /^1[3-9]\d{9}$/,
message: "请输入正确的手机号",
trigger: ["blur", "change"],
},
],
password: {
required: true, required: true,
message: '请填写验证码', message: "请填写验证码",
trigger: ['blur', 'change'] trigger: ["blur", "change"],
} },
}) });
let redirect = HOME_PATH; let redirect = HOME_PATH;
onLoad((options) => { onLoad((options) => {
if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) { if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) {
redirect = decodeURIComponent(options.redirect) redirect = decodeURIComponent(options.redirect);
}
});
//
const checkEnvironment = () => {
// #ifdef MP-WEIXIN
//
showWechatLogin.value = true;
// #endif
// #ifdef H5
// H5
const ua = navigator.userAgent.toLowerCase();
const isWechat = ua.indexOf("micromessenger") !== -1;
showWechatLogin.value = isWechat;
// #endif
// #ifdef APP-PLUS
// App
showWechatLogin.value = false;
// #endif
};
//
const wechatLogin = () => {
// #ifdef MP-WEIXIN
//
// uni.login({
// provider: "weixin",
// success: (loginRes) => {
// console.log(":", loginRes);
// //
// uni.getUserProfile({
// desc: "",
// success: (userRes) => {
// console.log(":", userRes);
// //
// showBindPhoneModal.value = true;
// },
// fail: (err) => {
// console.error(":", err);
// uni.showToast({
// title: "",
// icon: "none",
// });
// },
// });
// },
// fail: (err) => {
// console.error(":", err);
// uni.showToast({
// title: "",
// icon: "none",
// });
// },
// });
popup.value.open();
// #endif
// #ifdef H5
// H5
if (typeof WeixinJSBridge !== "undefined") {
// 使JS-SDK
wechatH5Login();
} else {
uni.showToast({
title: "请在微信中打开",
icon: "none",
});
}
// #endif
};
//
const getBindCode = () => {
if (!bindPhoneInfo.value.phone) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return;
}
if (!/^1[3-9]\d{9}$/.test(bindPhoneInfo.value.phone)) {
uni.showToast({
title: "请输入正确的手机号",
icon: "none",
});
return;
}
if (bindCodeRef.value.canGetCode) {
uni.showLoading({
title: "正在获取验证码",
});
// API
// RPC.post('/api/sms/send', {
// phone: bindPhoneInfo.value.phone,
// type: 'bind'
// }).then(() => {
// uni.hideLoading()
// uni.showToast({
// title: '',
// icon: 'success'
// })
// bindCodeRef.value.start()
// }).catch(() => {
// uni.hideLoading()
// uni.showToast({
// title: '',
// icon: 'none'
// })
// })
//
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: "验证码已发送",
icon: "success",
});
bindCodeRef.value.start();
}, 1500);
} else {
uni.showToast({
title: "倒计时结束后再发送",
icon: "none",
});
}
};
//
const bindCodeChange = (text) => {
bindCodeTips.value = text;
};
// H5
const wechatH5Login = () => {
// #ifdef H5
// URL
const appId = "YOUR_WECHAT_APP_ID"; // AppID
const redirectUri = encodeURIComponent(
window.location.origin + "/pages/login/login"
); //
const scope = "snsapi_userinfo"; //
const state = "STATE" + Date.now(); // CSRF
//
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
if (code) {
//
handleWechatH5Callback(code);
} else {
//
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`;
uni.showLoading({
title: "正在跳转微信授权...",
});
//
window.location.href = authUrl;
} }
// #endif
};
// H5
const handleWechatH5Callback = async (code) => {
// #ifdef H5
try {
uni.showLoading({
title: "正在获取用户信息...",
});
// code
// const result = await RPC.post('/api/wechat/h5-login', {
// code: code
// });
//
setTimeout(() => {
uni.hideLoading();
//
const userInfo = {
openid: "mock_openid_" + Date.now(),
nickname: "微信用户",
headimgurl: "/static/imgs/avatar.png",
};
console.log("微信H5登录成功用户信息:", userInfo);
//
popup.value.open();
// URLcode
const url = new URL(window.location);
url.searchParams.delete("code");
url.searchParams.delete("state");
window.history.replaceState(
{},
document.title,
url.pathname + url.search
);
}, 1500);
} catch (error) {
uni.hideLoading();
console.error("微信H5登录失败:", error);
uni.showToast({
title: "微信登录失败,请重试",
icon: "none",
});
}
// #endif
};
// JS-SDK
const initWechatJSSDK = () => {
// #ifdef H5
// 使JS-SDK
// JS-SDKhttps://res.wx.qq.com/open/js/jweixin-1.6.0.js
//
// if (typeof wx !== 'undefined') {
// wx.config({
// debug: false,
// appId: 'YOUR_WECHAT_APP_ID',
// timestamp: timestamp,
// nonceStr: nonceStr,
// signature: signature,
// jsApiList: ['chooseImage', 'uploadImage', 'getLocation'] // 使JS
// });
//
// wx.ready(() => {
// console.log('JS-SDK');
// });
//
// wx.error((res) => {
// console.error('JS-SDK:', res);
// });
// }
// #endif
};
//
const confirmBindPhone = async () => {
try {
await bindPhoneForm.value.validate();
bindingPhone.value = true;
// API
// const result = await RPC.post('/api/wechat/bind-phone', {
// phone: bindPhoneInfo.value.phone,
// code: bindPhoneInfo.value.code,
// wechatCode: wechatLoginCode // code
// })
//
setTimeout(() => {
bindingPhone.value = false;
uni.showToast({
title: "绑定成功",
icon: "success",
});
//
authStore.setAccessToken("wechat_access_token");
// userStore.setUserInfo(result.userInfo)
closeBindPhoneModal();
//
setTimeout(() => {
uni.$uv.route({
type: isTabBarPath(redirect) ? "switchTab" : "redirectTo",
url: redirect,
}); });
}, 1000);
}, 2000);
} catch (error) {
console.error("绑定手机号失败:", error);
bindingPhone.value = false;
}
};
//
const closeBindPhoneModal = () => {
popup.value.close();
bindPhoneInfo.value = {
phone: "",
code: "",
};
bindCodeTips.value = "获取验证码";
};
const login = async () => { const login = async () => {
await form.value.validate() await form.value.validate();
console.log(userInfo.value) console.log(userInfo.value);
// RPC.post('/account/login', { // RPC.post('/account/login', {
// username: userInfo.value.name, // username: userInfo.value.name,
// password: userInfo.value.password, // password: userInfo.value.password,
@ -145,14 +580,30 @@
// url: redirect, // url: redirect,
// }); // });
// }) // })
authStore.setAccessToken('accessToken') authStore.setAccessToken("accessToken");
setTimeout(() => { setTimeout(() => {
uni.$uv.route({ uni.$uv.route({
type: isTabBarPath(redirect) ? "switchTab" : "redirectTo", type: isTabBarPath(redirect) ? "switchTab" : "redirectTo",
url: redirect, url: redirect,
}); });
}, 800); }, 800);
};
onMounted(() => {
checkEnvironment();
// #ifdef H5
//
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
if (code && showWechatLogin.value) {
handleWechatH5Callback(code);
} }
// JS-SDK
// initWechatJSSDK();
// #endif
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -160,7 +611,11 @@
height: 100vh; height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: linear-gradient(124.92deg, rgba(77, 130, 253, 1) 7.66%, rgba(85, 184, 254, 1) 89.55%); background: linear-gradient(
124.92deg,
rgba(77, 130, 253, 1) 7.66%,
rgba(85, 184, 254, 1) 89.55%
);
.header { .header {
height: 15vh; height: 15vh;
@ -199,6 +654,54 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
.uv-icon {
cursor: pointer;
transition: transform 0.2s;
&:active {
transform: scale(0.95);
}
}
}
}
}
.bind-phone-modal {
width: 320px;
padding: 24px;
.modal-header {
text-align: center;
margin-bottom: 24px;
.modal-title {
font-size: 18px;
font-weight: bold;
color: #333;
margin-bottom: 8px;
}
.modal-subtitle {
font-size: 14px;
color: #666;
}
}
.modal-form {
margin-bottom: 24px;
.uv-form-item {
margin-bottom: 16px;
}
}
.modal-actions {
display: flex;
gap: 12px;
.uv-button {
flex: 1;
} }
} }
} }

Loading…
Cancel
Save