|
|
- <template>
- <view class="login-container">
- <!-- 背景图 -->
- <!-- <image class="bg-image" src="@/subPages/static/登录_背景图.png" mode="aspectFill"></image> -->
-
- <!-- 主要内容 -->
- <view class="content">
- <!-- Logo和标题区域 -->
- <view class="logo-section">
- <image class="logo" :src="configParamContent('login_logo')" mode="aspectFit"></image>
- <text class="title-text">{{ configParamContent('app_name') }}</text>
- </view>
-
- <!-- 登录按钮区域 -->
- <view class="login-section">
- <button class="login-btn" @click="handleLogin">
- 登录
- </button>
-
- <button class="guest-btn" @click="handleGuestLogin">
- 取消登录
- </button>
-
- <!-- 协议文本 -->
- <view class="agreement-text">
- <view class="agreement-content">
- <view class="checkbox-container" @click="toggleAgreement">
- <view class="checkbox" :class="{ 'checked': isAgreed }">
- <view class="checkbox-inner" v-if="isAgreed"></view>
- </view>
- </view>
- <text >我已阅读并同意
- <text class="link-text" @click="showServiceAgreement">《服务协议》</text>
- <text>和</text>
- <text class="link-text" @click="showPrivacyPolicy">《隐私政策》</text>
- </text>
- </view>
- </view>
- </view>
- </view>
-
- <!-- 用户协议和隐私政策弹窗 -->
- <uv-modal ref="serviceModal" title="《服务协议与隐私条款》" confirm-text="我知道了" confirm-color="#06DADC" @confirm="isAgreed = true">
- <view class="privacy-content">
- <scroll-view scroll-y style="height: 600rpx;">
- <!-- 如果是富文本 -->
- <uv-parse :content="configParamContent('privacy_policy')"></uv-parse>
- </scroll-view>
- </view>
- </uv-modal>
-
- <!-- 用户协议和隐私政策弹窗 -->
- <uv-modal ref="guideModal" title="《个人信息保护指引》" confirm-text="我知道了" confirm-color="#06DADC" @confirm="isAgreed = true">
- <view class="privacy-content">
- <scroll-view scroll-y style="height: 600rpx;">
- <!-- 如果是富文本 -->
- <uv-parse :content="configParamContent('user_agreement')"></uv-parse>
- </scroll-view>
- </view>
- </uv-modal>
- </view>
- </template>
-
- <script>
-
- // #ifdef H5
- import share from '@/utils/share.js'
- // #endif
-
- import uvParse from '../../uni_modules/uv-parse/components/uv-parse/uv-parse.vue';
- export default {
- components: { uvParse },
- name: 'Login',
- data() {
- return {
- isAgreed: false
- }
- },
- mounted() {
- // #ifdef H5
- // H5环境下检查URL参数,处理微信授权回调
- this.checkWechatAuthCallback();
- // #endif
- },
- methods: {
- // 微信登录统一入口
- handleLogin() {
- if (!this.isAgreed) {
- this.$refs.serviceModal.open();
- this.$refs.guideModal.open();
- return
- }
-
- // #ifdef MP-WEIXIN
- // 小程序环境
- this.miniProgramLogin();
- // #endif
-
- // #ifdef H5
- // H5环境 - 微信公众号授权
- this.wechatOfficialLogin();
- // #endif
- },
-
- // 小程序登录
- miniProgramLogin() {
- uni.login({
- provider: 'weixin',
- success: async (res) => {
- console.log('小程序登录成功', res);
- await this.processLogin(res.code);
- },
- fail: (err) => {
- console.log('小程序登录失败', err);
- uni.showToast({
- title: '登录失败',
- icon: 'none'
- });
- }
- })
- },
-
- // 微信公众号授权登录
- wechatOfficialLogin() {
- console.log('开始微信公众号授权登录');
-
- // 构建微信授权URL
- const appId = this.configParamContent('official_appid') || 'your_wechat_appid'; // 从配置中获取AppID
- const redirectUri = encodeURIComponent(window.location.origin + window.location.pathname + '#/subPages/login/login');
-
- console.log('redirectUri:', window.location.origin + window.location.pathname + '#/subPages/login/login');
-
- const state = Date.now().toString();
-
- // 保存当前邀请人信息
- if (uni.getStorageSync('inviter')) {
- sessionStorage.setItem('temp_inviter', uni.getStorageSync('inviter'));
- }
-
- const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect`;
-
- console.log('跳转到微信授权页面:', authUrl);
- window.location.href = authUrl;
- },
-
- // 检查微信授权回调
- checkWechatAuthCallback() {
- const code = this.getUrlParameter('code');
- const state = this.getUrlParameter('state');
-
- if (code && state) {
- console.log('检测到微信授权回调, code:', code, 'state:', state);
- // 恢复邀请人信息
- const tempInviter = sessionStorage.getItem('temp_inviter');
- if (tempInviter) {
- uni.setStorageSync('inviter', tempInviter);
- sessionStorage.removeItem('temp_inviter');
- }
-
- // 处理登录
- this.processLogin(code, 'official');
- }
- },
-
- // 统一登录处理
- async processLogin(code, type = 'miniprogram') {
- try {
- const loginParams = {
- code: code
- };
-
- // 添加邀请人信息
- if (uni.getStorageSync('inviter')) {
- loginParams.inviter = uni.getStorageSync('inviter');
- }
-
- // 添加登录类型参数
- if (type === 'official') {
- loginParams.type = 'official';
- }
-
- console.log('登录参数:', loginParams);
-
- const { result: loginRes } = await this.$api.login.login(loginParams);
-
- uni.setStorageSync('token', loginRes.token);
-
- const userInfo = loginRes.userInfo;
-
- // 存储用户信息到store
- this.$store.dispatch('updateUserInfo', userInfo);
-
- // #ifdef H5
- share()
- // #endif
-
- if (!userInfo.avatar || !userInfo.name || !userInfo.phone) {
- uni.navigateTo({
- url: '/subPages/login/userInfo'
- });
- return;
- } else {
- uni.showToast({
- title: '登录成功',
- icon: 'success'
- });
- uni.switchTab({
- url: '/pages/index/home'
- });
- }
- } catch (error) {
- console.error('登录失败:', error);
- uni.showToast({
- title: '登录失败,请重试',
- icon: 'none'
- });
-
- // #ifdef H5
- // H5环境下如果登录失败,清除URL参数并重新加载页面
- if (this.getUrlParameter('code')) {
- const cleanUrl = window.location.origin + window.location.pathname + window.location.hash.split('?')[0];
- window.history.replaceState({}, document.title, cleanUrl);
- }
- // #endif
- }
- },
-
- // 获取URL参数
- getUrlParameter(name) {
- // #ifdef H5
- const url = window.location.href;
- try {
- const urlParams = new URLSearchParams(window.location.search);
- return urlParams.get(name) || '';
- } catch (e) {
- // 兼容性处理
- const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
- const results = regex.exec(url);
- if (!results) return '';
- if (!results[2]) return '';
- return decodeURIComponent(results[2].replace(/\+/g, ' '));
- }
- // #endif
-
- // #ifndef H5
- return '';
- // #endif
- },
-
- // 游客登录
- handleGuestLogin() {
- console.log('暂不登录');
- // 跳转到主页
- uni.switchTab({
- url: '/pages/index/home'
- });
- },
-
- // 显示服务协议
- showServiceAgreement() {
- this.$refs.serviceModal.open();
- console.log('查看服务协议');
- // 这里可以跳转到协议页面或显示弹窗
- },
-
- // 显示隐私政策
- showPrivacyPolicy() {
- this.$refs.guideModal.open();
- console.log('查看隐私条款');
- // 这里可以跳转到隐私政策页面或显示弹窗
- },
-
- // 切换协议同意状态
- toggleAgreement() {
- this.isAgreed = !this.isAgreed;
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .login-container {
- position: relative;
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- background: #E8FBFB;
- .bg-image {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 1;
- }
-
- .content {
- position: relative;
- z-index: 2;
- height: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 0 60rpx;
-
- .logo-section {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-bottom: 120rpx;
-
- .logo {
- width: 120rpx;
- height: 120rpx;
- margin-bottom: 40rpx;
- }
-
- .title-text {
- font-size: 36rpx;
- font-weight: 600;
- color: $primary-text-color;
- text-align: center;
- }
- }
-
- .login-section {
- width: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
-
- .login-btn {
- width: 630rpx;
- height: 88rpx;
- margin-bottom: 30rpx;
- background-color: $primary-color;
- border: none;
- border-radius: 44rpx;
- color: white;
- font-size: 32rpx;
- font-weight: 500;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .guest-btn {
- width: 630rpx;
- height: 88rpx;
- margin-bottom: 60rpx;
- border: 2rpx solid $primary-color;
- border-radius: 44rpx;
- color: $primary-color;
- font-size: 32rpx;
- font-weight: 400;
- background-color: transparent;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .agreement-text {
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 24rpx;
- color: $secondary-text-color;
- line-height: 1.5;
-
- .checkbox-container {
- margin-right: 12rpx;
- cursor: pointer;
-
- .checkbox {
- width: 29rpx;
- height: 29rpx;
- border: 1rpx solid $secondary-text-color;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: all 0.3s ease;
-
- &.checked {
- border-color: $primary-color;
- background-color: $primary-color;
- }
-
- .checkbox-inner {
- width: 16rpx;
- height: 16rpx;
- background-color: white;
- border-radius: 50%;
- }
- }
- }
-
- .agreement-content {
- flex: 1;
- text-align: left;
- display: flex;
- .link-text {
- color: $primary-color;
- // text-decoration: underline;
- }
- }
- }
- }
- }
-
- .privacy-content{
- max-height: 600rpx;
- }
- }
- </style>
|