|
@@ -1,10 +1,17 @@
|
|
|
<template>
|
|
<template>
|
|
|
<view class="login-container">
|
|
<view class="login-container">
|
|
|
<!-- 返回按钮 -->
|
|
<!-- 返回按钮 -->
|
|
|
|
|
+ <!-- #ifdef H5 -->
|
|
|
|
|
+ <view class="back-btn" @click="handleBack">
|
|
|
|
|
+ <text class="back-icon">←</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
<view class="back-button" @click="handleBack">
|
|
<view class="back-button" @click="handleBack">
|
|
|
<text class="back-icon">←</text>
|
|
<text class="back-icon">←</text>
|
|
|
<text class="back-text">返回</text>
|
|
<text class="back-text">返回</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
|
|
|
<!-- 背景装饰 -->
|
|
<!-- 背景装饰 -->
|
|
|
<view class="bg-decoration">
|
|
<view class="bg-decoration">
|
|
@@ -14,15 +21,58 @@
|
|
|
|
|
|
|
|
<!-- Logo和标题 -->
|
|
<!-- Logo和标题 -->
|
|
|
<view class="header">
|
|
<view class="header">
|
|
|
|
|
+ <!-- #ifdef H5 -->
|
|
|
|
|
+ <image class="logo" src="/static/images/logo.png" mode="aspectFit"></image>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
<image class="logo" :src="getImageUrl('/static/images/logo.png')" mode="aspectFit"></image>
|
|
<image class="logo" :src="getImageUrl('/static/images/logo.png')" mode="aspectFit"></image>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
<text class="title">量化交易大师</text>
|
|
<text class="title">量化交易大师</text>
|
|
|
<text class="subtitle">专业的市场量化分析工具</text>
|
|
<text class="subtitle">专业的市场量化分析工具</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 登录按钮区域 -->
|
|
<!-- 登录按钮区域 -->
|
|
|
<view class="login-actions">
|
|
<view class="login-actions">
|
|
|
|
|
+ <!-- #ifdef H5 -->
|
|
|
|
|
+ <!-- 初始状态:显示登录和注册按钮 -->
|
|
|
|
|
+ <view v-if="currentStep === 'initial'" class="button-group">
|
|
|
|
|
+ <button class="login-btn primary-btn" @click="handleLoginClick">
|
|
|
|
|
+ <text class="btn-text">登录</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="login-btn secondary-btn" @click="handleRegisterClick">
|
|
|
|
|
+ <text class="btn-text">注册</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 输入手机号密码表单 -->
|
|
|
|
|
+ <view v-else-if="currentStep === 'input'" class="form-container">
|
|
|
|
|
+ <view class="form-title">{{ isLogin ? '登录账号' : '注册账号' }}</view>
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="phoneNumber"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ placeholder="请输入手机号"
|
|
|
|
|
+ maxlength="11"
|
|
|
|
|
+ class="form-input"
|
|
|
|
|
+ />
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="password"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ :password="true"
|
|
|
|
|
+ placeholder="请输入密码"
|
|
|
|
|
+ class="form-input"
|
|
|
|
|
+ />
|
|
|
|
|
+ <button class="login-btn primary-btn" @click="handleSubmit">
|
|
|
|
|
+ <text class="btn-text">{{ isLogin ? '登录' : '注册' }}</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="login-btn cancel-btn" @click="handleCancel">
|
|
|
|
|
+ <text class="btn-text">取消</text>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
+
|
|
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
<!-- 老用户:微信一键登录 -->
|
|
<!-- 老用户:微信一键登录 -->
|
|
|
- <button
|
|
|
|
|
|
|
+ <button
|
|
|
v-if="showOneClickLogin"
|
|
v-if="showOneClickLogin"
|
|
|
class="login-btn primary-btn"
|
|
class="login-btn primary-btn"
|
|
|
@click="handleWxLogin"
|
|
@click="handleWxLogin"
|
|
@@ -31,7 +81,7 @@
|
|
|
</button>
|
|
</button>
|
|
|
|
|
|
|
|
<!-- 新用户第二步:授权手机号登录(已完成头像昵称授权后显示) -->
|
|
<!-- 新用户第二步:授权手机号登录(已完成头像昵称授权后显示) -->
|
|
|
- <button
|
|
|
|
|
|
|
+ <button
|
|
|
v-else-if="showPhoneAuth"
|
|
v-else-if="showPhoneAuth"
|
|
|
class="login-btn primary-btn"
|
|
class="login-btn primary-btn"
|
|
|
open-type="getPhoneNumber"
|
|
open-type="getPhoneNumber"
|
|
@@ -42,7 +92,7 @@
|
|
|
</button>
|
|
</button>
|
|
|
|
|
|
|
|
<!-- 新用户第一步:获取头像昵称 -->
|
|
<!-- 新用户第一步:获取头像昵称 -->
|
|
|
- <button
|
|
|
|
|
|
|
+ <button
|
|
|
v-else
|
|
v-else
|
|
|
class="login-btn primary-btn"
|
|
class="login-btn primary-btn"
|
|
|
@click="handleGetUserProfile"
|
|
@click="handleGetUserProfile"
|
|
@@ -50,8 +100,25 @@
|
|
|
<text class="btn-icon">👤</text>
|
|
<text class="btn-icon">👤</text>
|
|
|
<text class="btn-text">授权登录</text>
|
|
<text class="btn-text">授权登录</text>
|
|
|
</button>
|
|
</button>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
|
|
|
<!-- 用户协议 -->
|
|
<!-- 用户协议 -->
|
|
|
|
|
+ <!-- #ifdef H5 -->
|
|
|
|
|
+ <view v-if="currentStep === 'initial'" class="agreement">
|
|
|
|
|
+ <checkbox-group @change="handleAgreementChange">
|
|
|
|
|
+ <label class="agreement-label">
|
|
|
|
|
+ <checkbox :checked="agreedToTerms" color="#5d55e8" />
|
|
|
|
|
+ <text class="agreement-text">
|
|
|
|
|
+ 我已阅读并同意
|
|
|
|
|
+ <text class="link" @click.stop="showAgreement('user')">《用户协议》</text>
|
|
|
|
|
+ 和
|
|
|
|
|
+ <text class="link" @click.stop="showAgreement('privacy')">《隐私政策》</text>
|
|
|
|
|
+ </text>
|
|
|
|
|
+ </label>
|
|
|
|
|
+ </checkbox-group>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
<view class="agreement">
|
|
<view class="agreement">
|
|
|
<checkbox-group @change="handleAgreementChange">
|
|
<checkbox-group @change="handleAgreementChange">
|
|
|
<label class="agreement-label">
|
|
<label class="agreement-label">
|
|
@@ -65,44 +132,110 @@
|
|
|
</label>
|
|
</label>
|
|
|
</checkbox-group>
|
|
</checkbox-group>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
|
|
+ <!-- #ifdef MP-WEIXIN -->
|
|
|
<!-- 用户信息完善弹窗 -->
|
|
<!-- 用户信息完善弹窗 -->
|
|
|
- <user-info-popup
|
|
|
|
|
|
|
+ <user-info-popup
|
|
|
ref="userInfoPopup"
|
|
ref="userInfoPopup"
|
|
|
@confirm="handleUserInfoConfirm"
|
|
@confirm="handleUserInfoConfirm"
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <!-- #endif -->
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
|
|
+// #ifdef H5
|
|
|
|
|
+import { startH5Auth, handleH5AuthCallback, setToken } from '@/utils/auth.js'
|
|
|
|
|
+import { checkUserStatus, h5PhoneLogin } from '@/utils/api.js'
|
|
|
|
|
+// #endif
|
|
|
|
|
+
|
|
|
|
|
+// #ifdef MP-WEIXIN
|
|
|
import { wxSilentLogin, wxPhoneLogin, wxCompleteUserInfo } from '@/utils/auth.js'
|
|
import { wxSilentLogin, wxPhoneLogin, wxCompleteUserInfo } from '@/utils/auth.js'
|
|
|
import { uploadFile, updateUserProfile, getImageUrl } from '@/utils/api.js'
|
|
import { uploadFile, updateUserProfile, getImageUrl } from '@/utils/api.js'
|
|
|
import UserInfoPopup from '@/components/UserInfoPopup.vue'
|
|
import UserInfoPopup from '@/components/UserInfoPopup.vue'
|
|
|
|
|
+// #endif
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
components: {
|
|
components: {
|
|
|
UserInfoPopup
|
|
UserInfoPopup
|
|
|
},
|
|
},
|
|
|
-
|
|
|
|
|
|
|
+ // #endif
|
|
|
|
|
+
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
|
|
+ // #ifdef H5
|
|
|
|
|
+ currentStep: 'initial', // 'initial' | 'input'
|
|
|
|
|
+ isLogin: true, // true=登录, false=注册
|
|
|
|
|
+ phoneNumber: '',
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ tempWxData: null, // 临时存储微信授权数据
|
|
|
|
|
+ // #endif
|
|
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
showOneClickLogin: true, // 是否显示一键登录按钮
|
|
showOneClickLogin: true, // 是否显示一键登录按钮
|
|
|
showPhoneAuth: false, // 是否显示手机号授权按钮(新用户第二步)
|
|
showPhoneAuth: false, // 是否显示手机号授权按钮(新用户第二步)
|
|
|
- agreedToTerms: false, // 是否同意协议
|
|
|
|
|
loginCode: '', // 微信登录code
|
|
loginCode: '', // 微信登录code
|
|
|
tempUserData: null, // 临时存储的用户数据(openid, unionid等)
|
|
tempUserData: null, // 临时存储的用户数据(openid, unionid等)
|
|
|
- tempUserProfile: null // 临时存储的用户头像昵称信息
|
|
|
|
|
|
|
+ tempUserProfile: null, // 临时存储的用户头像昵称信息
|
|
|
|
|
+ // #endif
|
|
|
|
|
+ agreedToTerms: false // 是否同意协议
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ onLoad(options) {
|
|
|
|
|
+ // #ifdef H5
|
|
|
|
|
+ // 恢复登录/注册状态
|
|
|
|
|
+ const savedIsLogin = uni.getStorageSync('temp_isLogin')
|
|
|
|
|
+ if (savedIsLogin !== null && savedIsLogin !== undefined && savedIsLogin !== '') {
|
|
|
|
|
+ this.isLogin = savedIsLogin === 'true'
|
|
|
|
|
+ uni.removeStorageSync('temp_isLogin')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查URL中是否有微信授权回调的code参数
|
|
|
|
|
+ let code = options && options.code
|
|
|
|
|
+
|
|
|
|
|
+ // H5首屏加载时 getCurrentPages/options 可能不稳定,做兜底解析
|
|
|
|
|
+ if (!code && typeof window !== 'undefined') {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const urlParams = new URLSearchParams(window.location.search)
|
|
|
|
|
+ code = urlParams.get('code') || code
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ // ignore
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!code && window.location.hash) {
|
|
|
|
|
+ const hash = window.location.hash
|
|
|
|
|
+ const queryIndex = hash.indexOf('?')
|
|
|
|
|
+ if (queryIndex >= 0) {
|
|
|
|
|
+ const query = hash.substring(queryIndex + 1)
|
|
|
|
|
+ try {
|
|
|
|
|
+ const hashParams = new URLSearchParams(query)
|
|
|
|
|
+ code = hashParams.get('code') || code
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ // ignore
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (code) {
|
|
|
|
|
+ console.log('[登录] 检测到授权回调code:', code)
|
|
|
|
|
+ this.handleAuthCallback(code)
|
|
|
}
|
|
}
|
|
|
|
|
+ // #endif
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
/**
|
|
/**
|
|
|
* 获取图片URL
|
|
* 获取图片URL
|
|
|
*/
|
|
*/
|
|
|
getImageUrl(url) {
|
|
getImageUrl(url) {
|
|
|
return getImageUrl(url)
|
|
return getImageUrl(url)
|
|
|
},
|
|
},
|
|
|
|
|
+ // #endif
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 返回上一页
|
|
* 返回上一页
|
|
@@ -110,21 +243,198 @@ export default {
|
|
|
handleBack() {
|
|
handleBack() {
|
|
|
const pages = getCurrentPages()
|
|
const pages = getCurrentPages()
|
|
|
if (pages.length > 1) {
|
|
if (pages.length > 1) {
|
|
|
- // 有上一页,返回
|
|
|
|
|
uni.navigateBack()
|
|
uni.navigateBack()
|
|
|
} else {
|
|
} else {
|
|
|
- // 没有上一页,跳转到首页
|
|
|
|
|
uni.switchTab({
|
|
uni.switchTab({
|
|
|
url: '/pages/index/index'
|
|
url: '/pages/index/index'
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 第一步:微信一键登录(老用户静默登录)
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ // #ifdef H5
|
|
|
|
|
+ async handleLoginClick() {
|
|
|
|
|
+ if (!this.agreedToTerms) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '请先阅读并同意用户协议',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.isLogin = true
|
|
|
|
|
+ uni.setStorageSync('temp_isLogin', 'true')
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ uni.showLoading({ title: '授权中...' })
|
|
|
|
|
+ await startH5Auth()
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ console.error('[登录] 微信授权失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: error.message || '授权失败,请重试',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ async handleRegisterClick() {
|
|
|
|
|
+ if (!this.agreedToTerms) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '请先阅读并同意用户协议',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.isLogin = false
|
|
|
|
|
+ uni.setStorageSync('temp_isLogin', 'false')
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ uni.showLoading({ title: '授权中...' })
|
|
|
|
|
+ await startH5Auth()
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ console.error('[注册] 微信授权失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: error.message || '授权失败,请重试',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ async handleAuthCallback(code) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ uni.showLoading({ title: '处理中...' })
|
|
|
|
|
+
|
|
|
|
|
+ const result = await handleH5AuthCallback(code)
|
|
|
|
|
+ const statusResult = await checkUserStatus(result.openid)
|
|
|
|
|
+ const isRegistered = statusResult.data
|
|
|
|
|
+
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+
|
|
|
|
|
+ this.tempWxData = {
|
|
|
|
|
+ openid: result.openid,
|
|
|
|
|
+ unionid: result.unionid,
|
|
|
|
|
+ nickname: result.nickname,
|
|
|
|
|
+ avatarUrl: result.avatarUrl
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isLogin) {
|
|
|
|
|
+ if (isRegistered) {
|
|
|
|
|
+ this.currentStep = 'input'
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '该微信未注册,请先注册',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ this.currentStep = 'initial'
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (!isRegistered) {
|
|
|
|
|
+ this.currentStep = 'input'
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '该微信已注册,请直接登录',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ this.currentStep = 'initial'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ console.error('[授权] 处理失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: error.message || '处理失败,请重试',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ this.currentStep = 'initial'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ async handleSubmit() {
|
|
|
|
|
+ if (!this.phoneNumber) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '请输入手机号',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!/^1[3-9]\d{9}$/.test(this.phoneNumber)) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '手机号格式不正确',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.password) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '请输入密码',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ uni.showLoading({ title: this.isLogin ? '登录中...' : '注册中...' })
|
|
|
|
|
+
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ openid: this.tempWxData.openid,
|
|
|
|
|
+ unionid: this.tempWxData.unionid,
|
|
|
|
|
+ phone: this.phoneNumber,
|
|
|
|
|
+ password: this.password
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.isLogin) {
|
|
|
|
|
+ params.nickname = this.tempWxData.nickname
|
|
|
|
|
+ params.avatarUrl = this.tempWxData.avatarUrl
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const result = await h5PhoneLogin(params)
|
|
|
|
|
+
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+
|
|
|
|
|
+ if (result.code === 200 && result.data.token) {
|
|
|
|
|
+ setToken(result.data.token)
|
|
|
|
|
+ console.log('[登录] 成功')
|
|
|
|
|
+ this.handleLoginSuccess()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new Error(result.message || (this.isLogin ? '登录失败' : '注册失败'))
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ console.error('[提交] 失败:', error)
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: error.message || (this.isLogin ? '登录失败,请重试' : '注册失败,请重试'),
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ handleCancel() {
|
|
|
|
|
+ this.currentStep = 'initial'
|
|
|
|
|
+ this.phoneNumber = ''
|
|
|
|
|
+ this.password = ''
|
|
|
|
|
+ this.tempWxData = null
|
|
|
|
|
+ },
|
|
|
|
|
+ // #endif
|
|
|
|
|
+
|
|
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
async handleWxLogin() {
|
|
async handleWxLogin() {
|
|
|
- // 检查是否同意协议
|
|
|
|
|
if (!this.agreedToTerms) {
|
|
if (!this.agreedToTerms) {
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
title: '请先阅读并同意用户协议',
|
|
title: '请先阅读并同意用户协议',
|
|
@@ -136,36 +446,30 @@ export default {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
uni.showLoading({ title: '登录中...' })
|
|
uni.showLoading({ title: '登录中...' })
|
|
|
-
|
|
|
|
|
- // 调用 wx.login 获取 code
|
|
|
|
|
|
|
+
|
|
|
const loginRes = await this.wxLoginAsync()
|
|
const loginRes = await this.wxLoginAsync()
|
|
|
this.loginCode = loginRes.code
|
|
this.loginCode = loginRes.code
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
console.log('[登录] 获取到微信code:', this.loginCode)
|
|
console.log('[登录] 获取到微信code:', this.loginCode)
|
|
|
-
|
|
|
|
|
- // 调用后端接口检查是否为老用户
|
|
|
|
|
|
|
+
|
|
|
const result = await wxSilentLogin(this.loginCode)
|
|
const result = await wxSilentLogin(this.loginCode)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
uni.hideLoading()
|
|
uni.hideLoading()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (result && result.isSign === 'true') {
|
|
if (result && result.isSign === 'true') {
|
|
|
- // 老用户,直接登录成功
|
|
|
|
|
console.log('[登录] 老用户登录成功')
|
|
console.log('[登录] 老用户登录成功')
|
|
|
this.handleLoginSuccess()
|
|
this.handleLoginSuccess()
|
|
|
} else if (result && result.isSign === 'false') {
|
|
} else if (result && result.isSign === 'false') {
|
|
|
- // 新用户,需要先获取头像昵称
|
|
|
|
|
console.log('[登录] 新用户,需要先获取头像昵称')
|
|
console.log('[登录] 新用户,需要先获取头像昵称')
|
|
|
this.showOneClickLogin = false
|
|
this.showOneClickLogin = false
|
|
|
this.showPhoneAuth = false
|
|
this.showPhoneAuth = false
|
|
|
} else if (result && result.code === 103) {
|
|
} else if (result && result.code === 103) {
|
|
|
- // 账号被禁用
|
|
|
|
|
uni.showModal({
|
|
uni.showModal({
|
|
|
title: '账号异常',
|
|
title: '账号异常',
|
|
|
content: '您的账号已被禁用,如有疑问请联系客服',
|
|
content: '您的账号已被禁用,如有疑问请联系客服',
|
|
|
showCancel: false
|
|
showCancel: false
|
|
|
})
|
|
})
|
|
|
} else {
|
|
} else {
|
|
|
- // 后端返回异常
|
|
|
|
|
throw new Error('登录接口返回数据异常')
|
|
throw new Error('登录接口返回数据异常')
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -179,11 +483,7 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 第二步:获取用户头像昵称(新用户)
|
|
|
|
|
- */
|
|
|
|
|
handleGetUserProfile() {
|
|
handleGetUserProfile() {
|
|
|
- // 检查是否同意协议
|
|
|
|
|
if (!this.agreedToTerms) {
|
|
if (!this.agreedToTerms) {
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
title: '请先阅读并同意用户协议',
|
|
title: '请先阅读并同意用户协议',
|
|
@@ -192,27 +492,22 @@ export default {
|
|
|
})
|
|
})
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
console.log('[登录] 打开用户信息弹窗')
|
|
console.log('[登录] 打开用户信息弹窗')
|
|
|
this.$refs.userInfoPopup.open()
|
|
this.$refs.userInfoPopup.open()
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 用户信息弹窗确认回调(新用户第二步完成后)
|
|
|
|
|
- */
|
|
|
|
|
handleUserInfoConfirm(userInfo) {
|
|
handleUserInfoConfirm(userInfo) {
|
|
|
console.log('[登录] 用户信息已获取:', userInfo)
|
|
console.log('[登录] 用户信息已获取:', userInfo)
|
|
|
-
|
|
|
|
|
- // 保存用户头像昵称信息
|
|
|
|
|
|
|
+
|
|
|
this.tempUserProfile = {
|
|
this.tempUserProfile = {
|
|
|
nickname: userInfo.nickname,
|
|
nickname: userInfo.nickname,
|
|
|
avatarUrl: userInfo.avatarUrl,
|
|
avatarUrl: userInfo.avatarUrl,
|
|
|
tempAvatarPath: userInfo.tempAvatarPath
|
|
tempAvatarPath: userInfo.tempAvatarPath
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 显示手机号授权按钮
|
|
|
|
|
|
|
+
|
|
|
this.showPhoneAuth = true
|
|
this.showPhoneAuth = true
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
title: '请继续授权手机号',
|
|
title: '请继续授权手机号',
|
|
|
icon: 'none',
|
|
icon: 'none',
|
|
@@ -220,18 +515,14 @@ export default {
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 第三步:获取手机号授权(新用户)
|
|
|
|
|
- */
|
|
|
|
|
async handleGetPhoneNumber(e) {
|
|
async handleGetPhoneNumber(e) {
|
|
|
console.log('[登录] 手机号授权回调:', e)
|
|
console.log('[登录] 手机号授权回调:', e)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
|
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
|
|
- // 检查是否是权限问题
|
|
|
|
|
if (e.detail.errMsg.includes('no permission')) {
|
|
if (e.detail.errMsg.includes('no permission')) {
|
|
|
uni.showModal({
|
|
uni.showModal({
|
|
|
title: '权限不足',
|
|
title: '权限不足',
|
|
|
- content: '获取手机号功能需要:\n1. 小程序企业认证"权限 \n2. 在真机上测试',
|
|
|
|
|
|
|
+ content: '获取手机号功能需要:\n1. 小程序企业认证权限 \n2. 在真机上测试',
|
|
|
showCancel: false
|
|
showCancel: false
|
|
|
})
|
|
})
|
|
|
} else {
|
|
} else {
|
|
@@ -245,55 +536,45 @@ export default {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
uni.showLoading({ title: '验证中...' })
|
|
uni.showLoading({ title: '验证中...' })
|
|
|
-
|
|
|
|
|
- // 重新获取 code(微信要求)
|
|
|
|
|
|
|
+
|
|
|
const loginRes = await this.wxLoginAsync()
|
|
const loginRes = await this.wxLoginAsync()
|
|
|
const newLoginCode = loginRes.code
|
|
const newLoginCode = loginRes.code
|
|
|
-
|
|
|
|
|
- // 构建请求参数
|
|
|
|
|
|
|
+
|
|
|
const params = {
|
|
const params = {
|
|
|
loginCode: newLoginCode,
|
|
loginCode: newLoginCode,
|
|
|
phoneCode: e.detail.code,
|
|
phoneCode: e.detail.code,
|
|
|
encryptedData: e.detail.encryptedData,
|
|
encryptedData: e.detail.encryptedData,
|
|
|
iv: e.detail.iv
|
|
iv: e.detail.iv
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
console.log('[登录] 发送手机号验证请求')
|
|
console.log('[登录] 发送手机号验证请求')
|
|
|
-
|
|
|
|
|
- // 调用后端接口验证手机号
|
|
|
|
|
|
|
+
|
|
|
const result = await wxPhoneLogin(params)
|
|
const result = await wxPhoneLogin(params)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
uni.hideLoading()
|
|
uni.hideLoading()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (result && result.isSign === 'false') {
|
|
if (result && result.isSign === 'false') {
|
|
|
- // 需要完成注册(已有头像昵称,现在有手机号)
|
|
|
|
|
console.log('[登录] 需要完成注册')
|
|
console.log('[登录] 需要完成注册')
|
|
|
- // 保存手机号相关信息
|
|
|
|
|
this.tempUserData = {
|
|
this.tempUserData = {
|
|
|
openid: result.openid,
|
|
openid: result.openid,
|
|
|
unionid: result.unionid,
|
|
unionid: result.unionid,
|
|
|
phoneNumber: result.phoneNumber
|
|
phoneNumber: result.phoneNumber
|
|
|
}
|
|
}
|
|
|
- // 直接提交注册
|
|
|
|
|
await this.submitRegistration()
|
|
await this.submitRegistration()
|
|
|
} else if (result && result.isSign === 'true') {
|
|
} else if (result && result.isSign === 'true') {
|
|
|
- // 已注册,直接登录成功
|
|
|
|
|
console.log('[登录] 已注册用户,登录成功')
|
|
console.log('[登录] 已注册用户,登录成功')
|
|
|
this.handleLoginSuccess()
|
|
this.handleLoginSuccess()
|
|
|
} else {
|
|
} else {
|
|
|
- // 后端返回异常
|
|
|
|
|
throw new Error('验证接口返回数据异常')
|
|
throw new Error('验证接口返回数据异常')
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
uni.hideLoading()
|
|
uni.hideLoading()
|
|
|
console.error('[登录] 手机号验证失败:', error)
|
|
console.error('[登录] 手机号验证失败:', error)
|
|
|
-
|
|
|
|
|
- // 根据错误信息提供友好提示
|
|
|
|
|
|
|
+
|
|
|
let errorMsg = '验证失败,请重试'
|
|
let errorMsg = '验证失败,请重试'
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (error.message) {
|
|
if (error.message) {
|
|
|
if (error.message.includes('48001') || error.message.includes('未开通手机号快速验证组件')) {
|
|
if (error.message.includes('48001') || error.message.includes('未开通手机号快速验证组件')) {
|
|
|
- // 未开通权限
|
|
|
|
|
uni.showModal({
|
|
uni.showModal({
|
|
|
title: '权限未开通',
|
|
title: '权限未开通',
|
|
|
content: '小程序未开通"手机号快速验证组件"权限\n\n请前往微信公众平台:\n开发 → 开发管理 → 接口设置\n开通"手机号快速验证组件"',
|
|
content: '小程序未开通"手机号快速验证组件"权限\n\n请前往微信公众平台:\n开发 → 开发管理 → 接口设置\n开通"手机号快速验证组件"',
|
|
@@ -310,7 +591,7 @@ export default {
|
|
|
errorMsg = error.message
|
|
errorMsg = error.message
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
title: errorMsg,
|
|
title: errorMsg,
|
|
|
icon: 'none',
|
|
icon: 'none',
|
|
@@ -319,14 +600,10 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 第四步:提交注册(新用户完成所有授权后)
|
|
|
|
|
- */
|
|
|
|
|
async submitRegistration() {
|
|
async submitRegistration() {
|
|
|
try {
|
|
try {
|
|
|
uni.showLoading({ title: '注册中...' })
|
|
uni.showLoading({ title: '注册中...' })
|
|
|
-
|
|
|
|
|
- // 构建用户信息
|
|
|
|
|
|
|
+
|
|
|
const completeInfo = {
|
|
const completeInfo = {
|
|
|
openid: this.tempUserData.openid,
|
|
openid: this.tempUserData.openid,
|
|
|
unionid: this.tempUserData.unionid,
|
|
unionid: this.tempUserData.unionid,
|
|
@@ -334,24 +611,20 @@ export default {
|
|
|
nickname: this.tempUserProfile.nickname,
|
|
nickname: this.tempUserProfile.nickname,
|
|
|
avatarUrl: this.tempUserProfile.avatarUrl
|
|
avatarUrl: this.tempUserProfile.avatarUrl
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
console.log('[登录] 提交用户信息')
|
|
console.log('[登录] 提交用户信息')
|
|
|
-
|
|
|
|
|
- // 调用后端接口完成注册
|
|
|
|
|
|
|
+
|
|
|
await wxCompleteUserInfo(completeInfo)
|
|
await wxCompleteUserInfo(completeInfo)
|
|
|
-
|
|
|
|
|
- // 注册成功后,上传头像到服务器
|
|
|
|
|
|
|
+
|
|
|
if (this.tempUserProfile.tempAvatarPath) {
|
|
if (this.tempUserProfile.tempAvatarPath) {
|
|
|
console.log('[登录] 开始上传头像到服务器')
|
|
console.log('[登录] 开始上传头像到服务器')
|
|
|
try {
|
|
try {
|
|
|
const uploadedUrl = await this.uploadAvatarWithToken(this.tempUserProfile.tempAvatarPath)
|
|
const uploadedUrl = await this.uploadAvatarWithToken(this.tempUserProfile.tempAvatarPath)
|
|
|
console.log('[登录] 头像上传成功:', uploadedUrl)
|
|
console.log('[登录] 头像上传成功:', uploadedUrl)
|
|
|
if (uploadedUrl) {
|
|
if (uploadedUrl) {
|
|
|
- // 更新用户头像为服务器URL
|
|
|
|
|
const updateResult = await updateUserProfile({ avatar: uploadedUrl })
|
|
const updateResult = await updateUserProfile({ avatar: uploadedUrl })
|
|
|
console.log('[登录] updateUserProfile返回:', updateResult)
|
|
console.log('[登录] updateUserProfile返回:', updateResult)
|
|
|
|
|
|
|
|
- // 更新本地存储的用户信息(使用后端返回的最新数据)
|
|
|
|
|
if (updateResult && updateResult.code === 200 && updateResult.data) {
|
|
if (updateResult && updateResult.code === 200 && updateResult.data) {
|
|
|
uni.setStorageSync('user_info', JSON.stringify(updateResult.data))
|
|
uni.setStorageSync('user_info', JSON.stringify(updateResult.data))
|
|
|
console.log('[登录] 本地用户信息已更新')
|
|
console.log('[登录] 本地用户信息已更新')
|
|
@@ -361,7 +634,7 @@ export default {
|
|
|
console.warn('[登录] 头像上传失败:', uploadErr)
|
|
console.warn('[登录] 头像上传失败:', uploadErr)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
uni.hideLoading()
|
|
uni.hideLoading()
|
|
|
console.log('[登录] 注册成功')
|
|
console.log('[登录] 注册成功')
|
|
|
this.handleLoginSuccess()
|
|
this.handleLoginSuccess()
|
|
@@ -376,9 +649,6 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 带token上传头像
|
|
|
|
|
- */
|
|
|
|
|
uploadAvatarWithToken(filePath) {
|
|
uploadAvatarWithToken(filePath) {
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
uni.uploadFile({
|
|
uni.uploadFile({
|
|
@@ -403,19 +673,29 @@ export default {
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 登录成功后的处理
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ wxLoginAsync() {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ uni.login({
|
|
|
|
|
+ provider: 'weixin',
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ resolve(res)
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ reject(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // #endif
|
|
|
|
|
+
|
|
|
handleLoginSuccess() {
|
|
handleLoginSuccess() {
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
title: '登录成功',
|
|
title: '登录成功',
|
|
|
icon: 'success',
|
|
icon: 'success',
|
|
|
duration: 1500
|
|
duration: 1500
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
- // 延迟跳转,让用户看到成功提示
|
|
|
|
|
|
|
+
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
- // 跳转到首页或返回上一页
|
|
|
|
|
const pages = getCurrentPages()
|
|
const pages = getCurrentPages()
|
|
|
if (pages.length > 1) {
|
|
if (pages.length > 1) {
|
|
|
uni.navigateBack()
|
|
uni.navigateBack()
|
|
@@ -427,44 +707,89 @@ export default {
|
|
|
}, 1500)
|
|
}, 1500)
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 协议勾选变化
|
|
|
|
|
- */
|
|
|
|
|
handleAgreementChange(e) {
|
|
handleAgreementChange(e) {
|
|
|
this.agreedToTerms = e.detail.value.length > 0
|
|
this.agreedToTerms = e.detail.value.length > 0
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 显示协议内容
|
|
|
|
|
- */
|
|
|
|
|
showAgreement(type) {
|
|
showAgreement(type) {
|
|
|
uni.navigateTo({
|
|
uni.navigateTo({
|
|
|
url: `/pages/agreement/agreement?type=${type}`
|
|
url: `/pages/agreement/agreement?type=${type}`
|
|
|
})
|
|
})
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 封装 wx.login 为 Promise
|
|
|
|
|
- */
|
|
|
|
|
- wxLoginAsync() {
|
|
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
|
|
- uni.login({
|
|
|
|
|
- provider: 'weixin',
|
|
|
|
|
- success: (res) => {
|
|
|
|
|
- resolve(res)
|
|
|
|
|
- },
|
|
|
|
|
- fail: (err) => {
|
|
|
|
|
- reject(err)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
-/* 返回按钮 */
|
|
|
|
|
|
|
+/* #ifdef H5 */
|
|
|
|
|
+.back-btn {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: env(safe-area-inset-top, 20rpx);
|
|
|
|
|
+ left: 40rpx;
|
|
|
|
|
+ width: 80rpx;
|
|
|
|
|
+ height: 80rpx;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 9999;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
+ margin-top: 20rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.back-btn:active {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.3);
|
|
|
|
|
+ transform: scale(0.95);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.back-icon {
|
|
|
|
|
+ font-size: 40rpx;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.button-group {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.secondary-btn {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ border: 2rpx solid #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.cancel-btn {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-container {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-title {
|
|
|
|
|
+ font-size: 36rpx;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ margin-bottom: 40rpx;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-input {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 96rpx;
|
|
|
|
|
+ border-radius: 48rpx;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ padding: 0 40rpx;
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ margin-bottom: 24rpx;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+}
|
|
|
|
|
+/* #endif */
|
|
|
|
|
+
|
|
|
|
|
+/* #ifdef MP-WEIXIN */
|
|
|
.back-button {
|
|
.back-button {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
top: 80rpx;
|
|
top: 80rpx;
|
|
@@ -490,6 +815,12 @@ export default {
|
|
|
color: #fff;
|
|
color: #fff;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.btn-icon {
|
|
|
|
|
+ font-size: 40rpx;
|
|
|
|
|
+ margin-right: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+/* #endif */
|
|
|
|
|
+
|
|
|
.login-container {
|
|
.login-container {
|
|
|
min-height: 100vh;
|
|
min-height: 100vh;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
@@ -502,7 +833,6 @@ export default {
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 背景装饰 */
|
|
|
|
|
.bg-decoration {
|
|
.bg-decoration {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
top: 0;
|
|
top: 0;
|
|
@@ -532,7 +862,6 @@ export default {
|
|
|
left: -50rpx;
|
|
left: -50rpx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 头部 */
|
|
|
|
|
.header {
|
|
.header {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
@@ -562,7 +891,6 @@ export default {
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 登录按钮区域 */
|
|
|
|
|
.login-actions {
|
|
.login-actions {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
z-index: 1;
|
|
z-index: 1;
|
|
@@ -577,7 +905,7 @@ export default {
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
font-size: 32rpx;
|
|
font-size: 32rpx;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
- margin-bottom: 40rpx;
|
|
|
|
|
|
|
+ margin-bottom: 24rpx;
|
|
|
border: none;
|
|
border: none;
|
|
|
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
|
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
|
|
}
|
|
}
|
|
@@ -587,16 +915,10 @@ export default {
|
|
|
color: #667eea;
|
|
color: #667eea;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.btn-icon {
|
|
|
|
|
- font-size: 40rpx;
|
|
|
|
|
- margin-right: 16rpx;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.btn-text {
|
|
.btn-text {
|
|
|
font-size: 32rpx;
|
|
font-size: 32rpx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 用户协议 */
|
|
|
|
|
.agreement {
|
|
.agreement {
|
|
|
margin-top: 60rpx;
|
|
margin-top: 60rpx;
|
|
|
}
|
|
}
|