|
|
@@ -4,53 +4,35 @@
|
|
|
<view class="nav-bar">
|
|
|
<text class="nav-title">登录</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- Logo 区域 -->
|
|
|
<view class="logo-section">
|
|
|
- <view class="logo-icon">
|
|
|
- <!-- 蓝色圆角正方形 logo -->
|
|
|
- </view>
|
|
|
+ <image class="logo-icon" src="/static/image/public/logo.png" mode="aspectFill"></image>
|
|
|
<text class="app-name">布尔销销乐</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 表单区域 -->
|
|
|
<view class="form-section">
|
|
|
<!-- 手机号输入 -->
|
|
|
<view class="input-item">
|
|
|
- <uni-easyinput
|
|
|
- v-model="phoneNumber"
|
|
|
- placeholder="请输入手机号"
|
|
|
- type="number"
|
|
|
- maxlength="11"
|
|
|
- :clearable="false"
|
|
|
- class="phone-input"
|
|
|
- />
|
|
|
+ <uni-easyinput v-model="phoneNumber" placeholder="请输入手机号" type="number" maxlength="11"
|
|
|
+ :clearable="false" class="phone-input" />
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 验证码输入 -->
|
|
|
<view class="input-item verify-code-row">
|
|
|
- <uni-easyinput
|
|
|
- v-model="verifyCode"
|
|
|
- placeholder="验证码"
|
|
|
- type="number"
|
|
|
- maxlength="6"
|
|
|
- :clearable="false"
|
|
|
- class="code-input"
|
|
|
- />
|
|
|
- <text
|
|
|
- class="get-code-btn"
|
|
|
- :class="{ disabled: countdown > 0 }"
|
|
|
- @click="getVerifyCode"
|
|
|
- >
|
|
|
+ <uni-easyinput v-model="verifyCode" placeholder="验证码" type="number" maxlength="6" :clearable="false"
|
|
|
+ class="code-input" />
|
|
|
+ <text class="get-code-btn" :class="{ disabled: countdown > 0 }" @click="getVerifyCode">
|
|
|
{{ countdown > 0 ? `${countdown}s` : '获取验证码' }}
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 登录按钮 -->
|
|
|
<view class="login-btn-wrapper">
|
|
|
<button class="login-btn" @click="handleLogin" :loading="isLoading">登录</button>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 协议说明 -->
|
|
|
<view class="agreement-text">
|
|
|
<text class="gray-text">登录即代表您已同意</text>
|
|
|
@@ -59,7 +41,7 @@
|
|
|
<text class="link-text" @click="showPrivacyPolicy">《隐私政策》</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 其他登录方式 -->
|
|
|
<view class="other-method-section">
|
|
|
<view class="divider">
|
|
|
@@ -67,7 +49,7 @@
|
|
|
<text class="divider-text">其他方式</text>
|
|
|
<view class="divider-line"></view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 微信一键登录 -->
|
|
|
<view class="wechat-login-wrapper">
|
|
|
<button class="wechat-login-btn" @click="wechatLogin">
|
|
|
@@ -76,7 +58,7 @@
|
|
|
</button>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 用户协议弹窗 -->
|
|
|
<view class="agreement-popup" v-if="showUserAgreementPopup" @click="closeUserAgreement">
|
|
|
<view class="popup-mask"></view>
|
|
|
@@ -89,7 +71,7 @@
|
|
|
<view class="agreement-content">
|
|
|
<text class="agreement-title">用户协议</text>
|
|
|
<text class="update-time">最后更新时间:2026 年 4 月 24 日</text>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">一、协议的接受与修改</text>
|
|
|
<text class="section-content">
|
|
|
@@ -98,7 +80,7 @@
|
|
|
1.3 我们有权根据需要不时修改本协议条款,修改后的协议一旦公布即有效代替原来的协议。您可随时查阅最新协议。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">二、服务内容</text>
|
|
|
<text class="section-content">
|
|
|
@@ -106,7 +88,7 @@
|
|
|
2.2 我们有权对服务内容进行变更、中断或终止,变更、中断或终止服务前将尽可能提前通知用户。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">三、用户账号</text>
|
|
|
<text class="section-content">
|
|
|
@@ -115,7 +97,7 @@
|
|
|
3.3 您应妥善保管您的账号信息,因您保管不善导致账号被盗、密码失密或遭受其他损失的,您应自行承担相应责任。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">四、用户行为规范</text>
|
|
|
<text class="section-content">
|
|
|
@@ -129,7 +111,7 @@
|
|
|
(6) 散布谣言、淫秽色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">五、知识产权</text>
|
|
|
<text class="section-content">
|
|
|
@@ -137,7 +119,7 @@
|
|
|
5.2 未经我们书面许可,您不得以任何形式复制、传播、展示、修改本服务的内容。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">六、免责声明</text>
|
|
|
<text class="section-content">
|
|
|
@@ -145,7 +127,7 @@
|
|
|
6.2 因网络状况、通讯线路、黑客攻击、计算机病毒、政府管制等任何非我们原因导致的服务中断或数据丢失,我们不承担责任。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">七、协议终止</text>
|
|
|
<text class="section-content">
|
|
|
@@ -153,7 +135,7 @@
|
|
|
7.2 如您违反本协议,我们有权终止向您提供服务,并保留追究法律责任的权利。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">八、法律适用与争议解决</text>
|
|
|
<text class="section-content">
|
|
|
@@ -161,7 +143,7 @@
|
|
|
8.2 如双方就本协议内容或其执行发生任何争议,应友好协商解决;协商不成的,任何一方均可向我们所在地有管辖权的人民法院提起诉讼。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">九、联系我们</text>
|
|
|
<text class="section-content">
|
|
|
@@ -177,7 +159,7 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 隐私政策弹窗 -->
|
|
|
<view class="agreement-popup" v-if="showPrivacyPolicyPopup" @click="closePrivacyPolicy">
|
|
|
<view class="popup-mask"></view>
|
|
|
@@ -190,7 +172,7 @@
|
|
|
<view class="agreement-content">
|
|
|
<text class="agreement-title">隐私政策</text>
|
|
|
<text class="update-time">最后更新时间:2026 年 4 月 24 日</text>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">一、我们如何收集和使用您的个人信息</text>
|
|
|
<text class="section-content">
|
|
|
@@ -201,7 +183,7 @@
|
|
|
1.2 我们收集的信息仅用于提供服务、改进产品质量和保障账号安全,不会用于其他用途。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">二、我们如何共享、转让、公开披露您的个人信息</text>
|
|
|
<text class="section-content">
|
|
|
@@ -212,7 +194,7 @@
|
|
|
2.3 我们不会公开披露您的个人信息,除非获得您的明确同意或基于法律规定。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">三、我们如何保护您的个人信息</text>
|
|
|
<text class="section-content">
|
|
|
@@ -221,7 +203,7 @@
|
|
|
3.3 我们仅允许有必要知晓这些信息的员工访问您的个人信息,并为此设置了严格的访问权限控制。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">四、您的权利</text>
|
|
|
<text class="section-content">
|
|
|
@@ -230,7 +212,7 @@
|
|
|
4.3 您有权注销您的账号。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">五、我们如何处理未成年人的个人信息</text>
|
|
|
<text class="section-content">
|
|
|
@@ -238,7 +220,7 @@
|
|
|
5.2 若您是 18 周岁以下的未成年人,在使用本服务前,应事先取得您家长或法定监护人的书面同意。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">六、隐私政策的更新</text>
|
|
|
<text class="section-content">
|
|
|
@@ -246,7 +228,7 @@
|
|
|
6.2 当本政策的条款发生变更时,我们会在版本更新时以适当的方式向您提示变更后的内容。
|
|
|
</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view class="section">
|
|
|
<text class="section-title">七、联系我们</text>
|
|
|
<text class="section-content">
|
|
|
@@ -266,472 +248,485 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref } from 'vue'
|
|
|
-import { sendVerifyCode, loginByPhone } from '@/api/user.js'
|
|
|
-import { saveUserInfo } from '@/utils/userCache.js'
|
|
|
-
|
|
|
-// 表单数据
|
|
|
-const phoneNumber = ref('')
|
|
|
-const verifyCode = ref('')
|
|
|
-const countdown = ref(0)
|
|
|
-const isLoading = ref(false)
|
|
|
-let timer = null
|
|
|
-
|
|
|
-// 弹窗控制
|
|
|
-const showUserAgreementPopup = ref(false)
|
|
|
-const showPrivacyPolicyPopup = ref(false)
|
|
|
-
|
|
|
-// 获取验证码
|
|
|
-const getVerifyCode = async () => {
|
|
|
- if (countdown.value > 0) return
|
|
|
-
|
|
|
- if (!phoneNumber.value || phoneNumber.value.length !== 11) {
|
|
|
- uni.showToast({
|
|
|
- title: '请输入正确的手机号',
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- const res = await sendVerifyCode(phoneNumber.value)
|
|
|
- console.log('验证码发送成功:', res)
|
|
|
-
|
|
|
- // 开始倒计时
|
|
|
- countdown.value = 60
|
|
|
- timer = setInterval(() => {
|
|
|
- countdown.value--
|
|
|
- if (countdown.value <= 0) {
|
|
|
- clearInterval(timer)
|
|
|
- }
|
|
|
- }, 1000)
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- title: '验证码已发送',
|
|
|
- icon: 'success'
|
|
|
- })
|
|
|
- } catch (error) {
|
|
|
- console.error('发送验证码失败:', error)
|
|
|
- }
|
|
|
-}
|
|
|
+ import {
|
|
|
+ ref
|
|
|
+ } from 'vue'
|
|
|
+ import {
|
|
|
+ sendVerifyCode,
|
|
|
+ loginByPhone
|
|
|
+ } from '@/api/user.js'
|
|
|
+ import {
|
|
|
+ saveUserInfo
|
|
|
+ } from '@/utils/userCache.js'
|
|
|
+
|
|
|
+ // 表单数据
|
|
|
+ const phoneNumber = ref('')
|
|
|
+ const verifyCode = ref('')
|
|
|
+ const countdown = ref(0)
|
|
|
+ const isLoading = ref(false)
|
|
|
+ let timer = null
|
|
|
+
|
|
|
+ // 弹窗控制
|
|
|
+ const showUserAgreementPopup = ref(false)
|
|
|
+ const showPrivacyPolicyPopup = ref(false)
|
|
|
+
|
|
|
+ // 获取验证码
|
|
|
+ const getVerifyCode = async () => {
|
|
|
+ if (countdown.value > 0) return
|
|
|
+
|
|
|
+ if (!phoneNumber.value || phoneNumber.value.length !== 11) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请输入正确的手机号',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await sendVerifyCode(phoneNumber.value)
|
|
|
+ console.log('验证码发送成功:', res)
|
|
|
+
|
|
|
+ // 开始倒计时
|
|
|
+ countdown.value = 60
|
|
|
+ timer = setInterval(() => {
|
|
|
+ countdown.value--
|
|
|
+ if (countdown.value <= 0) {
|
|
|
+ clearInterval(timer)
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
|
|
|
-// 处理登录
|
|
|
-const handleLogin = async () => {
|
|
|
- if (isLoading.value) return
|
|
|
-
|
|
|
- if (!phoneNumber.value || phoneNumber.value.length !== 11) {
|
|
|
- uni.showToast({
|
|
|
- title: '请输入正确的手机号',
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if (!verifyCode.value || verifyCode.value.length !== 6) {
|
|
|
- uni.showToast({
|
|
|
- title: '请输入验证码',
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- isLoading.value = true
|
|
|
-
|
|
|
- try {
|
|
|
- const res = await loginByPhone(phoneNumber.value, verifyCode.value)
|
|
|
- console.log('登录成功:', res)
|
|
|
-
|
|
|
- // 保存用户信息和 token
|
|
|
- const { userInfo, token } = res.data || res
|
|
|
- const saveSuccess = saveUserInfo(userInfo, token)
|
|
|
-
|
|
|
- if (saveSuccess) {
|
|
|
uni.showToast({
|
|
|
- title: '登录成功',
|
|
|
+ title: '验证码已发送',
|
|
|
icon: 'success'
|
|
|
})
|
|
|
-
|
|
|
- // 延迟跳转
|
|
|
- setTimeout(() => {
|
|
|
- uni.reLaunch({
|
|
|
- url: '/pages/index/index'
|
|
|
- })
|
|
|
- }, 1500)
|
|
|
- } else {
|
|
|
+ } catch (error) {
|
|
|
+ console.error('发送验证码失败:', error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理登录
|
|
|
+ const handleLogin = async () => {
|
|
|
+ if (isLoading.value) return
|
|
|
+
|
|
|
+ if (!phoneNumber.value || phoneNumber.value.length !== 11) {
|
|
|
uni.showToast({
|
|
|
- title: '保存登录信息失败',
|
|
|
+ title: '请输入正确的手机号',
|
|
|
icon: 'none'
|
|
|
})
|
|
|
+ return
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('登录失败:', error)
|
|
|
- } finally {
|
|
|
- isLoading.value = false
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 微信登录
|
|
|
-const wechatLogin = () => {
|
|
|
- // #ifdef MP-WEIXIN
|
|
|
- uni.getUserProfile({
|
|
|
- desc: '用于完善用户资料',
|
|
|
- success: (res) => {
|
|
|
- console.log('微信授权成功:', res.userInfo)
|
|
|
- // TODO: 调用微信登录接口
|
|
|
+
|
|
|
+ if (!verifyCode.value || verifyCode.value.length !== 6) {
|
|
|
uni.showToast({
|
|
|
- title: '微信授权成功',
|
|
|
- icon: 'success'
|
|
|
+ title: '请输入验证码',
|
|
|
+ icon: 'none'
|
|
|
})
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.log('微信授权失败:', err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ isLoading.value = true
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await loginByPhone(phoneNumber.value, verifyCode.value)
|
|
|
+ console.log('登录成功:', res)
|
|
|
+
|
|
|
+ // 保存用户信息和 token
|
|
|
+ const {
|
|
|
+ userInfo,
|
|
|
+ token
|
|
|
+ } = res.data || res
|
|
|
+ const saveSuccess = saveUserInfo(userInfo, token)
|
|
|
+
|
|
|
+ if (saveSuccess) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '登录成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 延迟跳转
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.reLaunch({
|
|
|
+ url: '/pages/index/index'
|
|
|
+ })
|
|
|
+ }, 1500)
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: '保存登录信息失败',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('登录失败:', error)
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false
|
|
|
}
|
|
|
- })
|
|
|
- // #endif
|
|
|
-
|
|
|
- // #ifndef MP-WEIXIN
|
|
|
- uni.showToast({
|
|
|
- title: '请在微信小程序中使用',
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- // #endif
|
|
|
-}
|
|
|
-
|
|
|
-// 显示用户协议
|
|
|
-const showUserAgreement = () => {
|
|
|
- showUserAgreementPopup.value = true
|
|
|
-}
|
|
|
-
|
|
|
-// 关闭用户协议
|
|
|
-const closeUserAgreement = () => {
|
|
|
- showUserAgreementPopup.value = false
|
|
|
-}
|
|
|
-
|
|
|
-// 显示隐私政策
|
|
|
-const showPrivacyPolicy = () => {
|
|
|
- showPrivacyPolicyPopup.value = true
|
|
|
-}
|
|
|
-
|
|
|
-// 关闭隐私政策
|
|
|
-const closePrivacyPolicy = () => {
|
|
|
- showPrivacyPolicyPopup.value = false
|
|
|
-}
|
|
|
-
|
|
|
-// 页面卸载时清除定时器
|
|
|
-import { onUnmounted } from 'vue'
|
|
|
-onUnmounted(() => {
|
|
|
- if (timer) {
|
|
|
- clearInterval(timer)
|
|
|
}
|
|
|
-})
|
|
|
-</script>
|
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
-.login-container {
|
|
|
- min-height: 100vh;
|
|
|
- background-color: #ffffff;
|
|
|
- padding: 0 40rpx;
|
|
|
- position: relative;
|
|
|
-}
|
|
|
-
|
|
|
-// 导航栏
|
|
|
-.nav-bar {
|
|
|
- height: 88rpx;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- .nav-title {
|
|
|
- font-size: 34rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #000000;
|
|
|
+ // 微信登录
|
|
|
+ const wechatLogin = () => {
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ uni.getUserProfile({
|
|
|
+ desc: '用于完善用户资料',
|
|
|
+ success: (res) => {
|
|
|
+ console.log('微信授权成功:', res.userInfo)
|
|
|
+ // TODO: 调用微信登录接口
|
|
|
+ uni.showToast({
|
|
|
+ title: '微信授权成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.log('微信授权失败:', err)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // #ifndef MP-WEIXIN
|
|
|
+ uni.showToast({
|
|
|
+ title: '请在微信小程序中使用',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ // #endif
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// Logo 区域
|
|
|
-.logo-section {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- margin-top: 60rpx;
|
|
|
- margin-bottom: 80rpx;
|
|
|
-
|
|
|
- .logo-icon {
|
|
|
- width: 160rpx;
|
|
|
- height: 160rpx;
|
|
|
- background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
|
|
|
- border-radius: 32rpx;
|
|
|
- box-shadow: 0 8rpx 24rpx rgba(24, 144, 255, 0.3);
|
|
|
+
|
|
|
+ // 显示用户协议
|
|
|
+ const showUserAgreement = () => {
|
|
|
+ showUserAgreementPopup.value = true
|
|
|
}
|
|
|
-
|
|
|
- .app-name {
|
|
|
- font-size: 40rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #000000;
|
|
|
- margin-top: 32rpx;
|
|
|
+
|
|
|
+ // 关闭用户协议
|
|
|
+ const closeUserAgreement = () => {
|
|
|
+ showUserAgreementPopup.value = false
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 表单区域
|
|
|
-.form-section {
|
|
|
- .input-item {
|
|
|
- margin-bottom: 24rpx;
|
|
|
-
|
|
|
- .phone-input, .code-input {
|
|
|
- background-color: #f5f7fa;
|
|
|
- border-radius: 16rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- }
|
|
|
+
|
|
|
+ // 显示隐私政策
|
|
|
+ const showPrivacyPolicy = () => {
|
|
|
+ showPrivacyPolicyPopup.value = true
|
|
|
}
|
|
|
-
|
|
|
- .verify-code-row {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- .code-input {
|
|
|
- flex: 1;
|
|
|
- margin-right: 20rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .get-code-btn {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #1890ff;
|
|
|
- white-space: nowrap;
|
|
|
-
|
|
|
- &.disabled {
|
|
|
- color: #999999;
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
+ // 关闭隐私政策
|
|
|
+ const closePrivacyPolicy = () => {
|
|
|
+ showPrivacyPolicyPopup.value = false
|
|
|
}
|
|
|
-
|
|
|
- .login-btn-wrapper {
|
|
|
- margin-top: 48rpx;
|
|
|
- margin-bottom: 24rpx;
|
|
|
-
|
|
|
- .login-btn {
|
|
|
- width: 100%;
|
|
|
- height: 88rpx;
|
|
|
- background: linear-gradient(90deg, #1890ff 0%, #096dd9 100%);
|
|
|
- border-radius: 16rpx;
|
|
|
- border: none;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- color: #ffffff;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- &::after {
|
|
|
- border: none;
|
|
|
- }
|
|
|
+
|
|
|
+ // 页面卸载时清除定时器
|
|
|
+ import {
|
|
|
+ onUnmounted
|
|
|
+ } from 'vue'
|
|
|
+ onUnmounted(() => {
|
|
|
+ if (timer) {
|
|
|
+ clearInterval(timer)
|
|
|
}
|
|
|
+ })
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .login-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background-color: #ffffff;
|
|
|
+ padding: 0 40rpx;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
-
|
|
|
- .agreement-text {
|
|
|
+
|
|
|
+ // 导航栏
|
|
|
+ .nav-bar {
|
|
|
+ height: 88rpx;
|
|
|
display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
+ align-items: center;
|
|
|
justify-content: center;
|
|
|
- font-size: 22rpx;
|
|
|
-
|
|
|
- .gray-text {
|
|
|
- color: #999999;
|
|
|
- margin: 0 4rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .link-text {
|
|
|
- color: #1890ff;
|
|
|
- margin: 0 4rpx;
|
|
|
+
|
|
|
+ .nav-title {
|
|
|
+ font-size: 34rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #000000;
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-// 其他登录方式
|
|
|
-.other-method-section {
|
|
|
- margin-top: 120rpx;
|
|
|
-
|
|
|
- .divider {
|
|
|
+ // Logo 区域
|
|
|
+ .logo-section {
|
|
|
display: flex;
|
|
|
+ flex-direction: column;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-bottom: 40rpx;
|
|
|
-
|
|
|
- .divider-line {
|
|
|
- width: 120rpx;
|
|
|
- height: 1rpx;
|
|
|
- background-color: #e5e5e5;
|
|
|
+ margin-top: 60rpx;
|
|
|
+ margin-bottom: 80rpx;
|
|
|
+
|
|
|
+ .logo-icon {
|
|
|
+ width: 160rpx;
|
|
|
+ height: 160rpx;
|
|
|
+ background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
|
|
|
+ border-radius: 32rpx;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(24, 144, 255, 0.3);
|
|
|
}
|
|
|
-
|
|
|
- .divider-text {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #999999;
|
|
|
- margin: 0 24rpx;
|
|
|
+
|
|
|
+ .app-name {
|
|
|
+ font-size: 40rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #000000;
|
|
|
+ margin-top: 32rpx;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .wechat-login-wrapper {
|
|
|
- .wechat-login-btn {
|
|
|
- width: 100%;
|
|
|
- height: 88rpx;
|
|
|
- background: linear-gradient(90deg, #07c160 0%, #06ad56 100%);
|
|
|
- border-radius: 16rpx;
|
|
|
- border: none;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- color: #ffffff;
|
|
|
+
|
|
|
+ // 表单区域
|
|
|
+ .form-section {
|
|
|
+ .input-item {
|
|
|
+ margin-bottom: 24rpx;
|
|
|
+
|
|
|
+ .phone-input,
|
|
|
+ .code-input {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .verify-code-row {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- &::after {
|
|
|
- border: none;
|
|
|
+
|
|
|
+ .code-input {
|
|
|
+ flex: 1;
|
|
|
+ margin-right: 20rpx;
|
|
|
}
|
|
|
-
|
|
|
- .wechat-icon {
|
|
|
- margin-right: 12rpx;
|
|
|
- font-size: 36rpx;
|
|
|
+
|
|
|
+ .get-code-btn {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #1890ff;
|
|
|
+ white-space: nowrap;
|
|
|
+
|
|
|
+ &.disabled {
|
|
|
+ color: #999999;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- .wechat-text {
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-btn-wrapper {
|
|
|
+ margin-top: 48rpx;
|
|
|
+ margin-bottom: 24rpx;
|
|
|
+
|
|
|
+ .login-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 88rpx;
|
|
|
+ background: linear-gradient(90deg, #1890ff 0%, #096dd9 100%);
|
|
|
+ border-radius: 16rpx;
|
|
|
+ border: none;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .agreement-text {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 22rpx;
|
|
|
+
|
|
|
+ .gray-text {
|
|
|
+ color: #999999;
|
|
|
+ margin: 0 4rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .link-text {
|
|
|
+ color: #1890ff;
|
|
|
+ margin: 0 4rpx;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 协议弹窗
|
|
|
-.agreement-popup {
|
|
|
- position: fixed;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- z-index: 1000;
|
|
|
-
|
|
|
- .popup-mask {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- background-color: rgba(0, 0, 0, 0.5);
|
|
|
- }
|
|
|
-
|
|
|
- .popup-content {
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- background-color: #ffffff;
|
|
|
- border-radius: 32rpx 32rpx 0 0;
|
|
|
- max-height: 80vh;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- animation: slideUp 0.3s ease-out;
|
|
|
-
|
|
|
- .popup-header {
|
|
|
+
|
|
|
+ // 其他登录方式
|
|
|
+ .other-method-section {
|
|
|
+ margin-top: 120rpx;
|
|
|
+
|
|
|
+ .divider {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 32rpx;
|
|
|
- border-bottom: 1rpx solid #f0f0f0;
|
|
|
-
|
|
|
- .popup-title {
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #000000;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+
|
|
|
+ .divider-line {
|
|
|
+ width: 120rpx;
|
|
|
+ height: 1rpx;
|
|
|
+ background-color: #e5e5e5;
|
|
|
}
|
|
|
-
|
|
|
- .popup-close {
|
|
|
- font-size: 40rpx;
|
|
|
+
|
|
|
+ .divider-text {
|
|
|
+ font-size: 24rpx;
|
|
|
color: #999999;
|
|
|
- width: 60rpx;
|
|
|
- height: 60rpx;
|
|
|
+ margin: 0 24rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .wechat-login-wrapper {
|
|
|
+ .wechat-login-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 88rpx;
|
|
|
+ background: linear-gradient(90deg, #07c160 0%, #06ad56 100%);
|
|
|
+ border-radius: 16rpx;
|
|
|
+ border: none;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .wechat-icon {
|
|
|
+ margin-right: 12rpx;
|
|
|
+ font-size: 36rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .wechat-text {
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .popup-body {
|
|
|
- flex: 1;
|
|
|
- overflow-y: auto;
|
|
|
- padding: 32rpx;
|
|
|
-
|
|
|
- .agreement-content {
|
|
|
+ }
|
|
|
+
|
|
|
+ // 协议弹窗
|
|
|
+ .agreement-popup {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 1000;
|
|
|
+
|
|
|
+ .popup-mask {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-content {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border-radius: 32rpx 32rpx 0 0;
|
|
|
+ max-height: 80vh;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ animation: slideUp 0.3s ease-out;
|
|
|
+
|
|
|
+ .popup-header {
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
-
|
|
|
- .agreement-title {
|
|
|
- font-size: 36rpx;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 32rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+
|
|
|
+ .popup-title {
|
|
|
+ font-size: 32rpx;
|
|
|
font-weight: 600;
|
|
|
color: #000000;
|
|
|
- display: block;
|
|
|
- text-align: center;
|
|
|
- margin-bottom: 20rpx;
|
|
|
}
|
|
|
-
|
|
|
- .update-time {
|
|
|
- font-size: 24rpx;
|
|
|
+
|
|
|
+ .popup-close {
|
|
|
+ font-size: 40rpx;
|
|
|
color: #999999;
|
|
|
- display: block;
|
|
|
- text-align: center;
|
|
|
- margin-bottom: 40rpx;
|
|
|
+ width: 60rpx;
|
|
|
+ height: 60rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
}
|
|
|
-
|
|
|
- .section {
|
|
|
- margin-bottom: 32rpx;
|
|
|
-
|
|
|
- .section-title {
|
|
|
- font-size: 28rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .popup-body {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 32rpx;
|
|
|
+
|
|
|
+ .agreement-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ .agreement-title {
|
|
|
+ font-size: 36rpx;
|
|
|
font-weight: 600;
|
|
|
color: #000000;
|
|
|
display: block;
|
|
|
- margin-bottom: 16rpx;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
}
|
|
|
-
|
|
|
- .section-content {
|
|
|
+
|
|
|
+ .update-time {
|
|
|
font-size: 24rpx;
|
|
|
- color: #333333;
|
|
|
- line-height: 1.8;
|
|
|
+ color: #999999;
|
|
|
display: block;
|
|
|
- white-space: pre-wrap;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section {
|
|
|
+ margin-bottom: 32rpx;
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ font-size: 28rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #000000;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-content {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #333333;
|
|
|
+ line-height: 1.8;
|
|
|
+ display: block;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- .popup-footer {
|
|
|
- padding: 24rpx 32rpx 40rpx;
|
|
|
- border-top: 1rpx solid #f0f0f0;
|
|
|
-
|
|
|
- .agree-btn {
|
|
|
- width: 100%;
|
|
|
- height: 80rpx;
|
|
|
- background: linear-gradient(90deg, #1890ff 0%, #096dd9 100%);
|
|
|
- border-radius: 16rpx;
|
|
|
- border: none;
|
|
|
- font-size: 30rpx;
|
|
|
- font-weight: 500;
|
|
|
- color: #ffffff;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- &::after {
|
|
|
+
|
|
|
+ .popup-footer {
|
|
|
+ padding: 24rpx 32rpx 40rpx;
|
|
|
+ border-top: 1rpx solid #f0f0f0;
|
|
|
+
|
|
|
+ .agree-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ background: linear-gradient(90deg, #1890ff 0%, #096dd9 100%);
|
|
|
+ border-radius: 16rpx;
|
|
|
border: none;
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-@keyframes slideUp {
|
|
|
- from {
|
|
|
- transform: translateY(100%);
|
|
|
- }
|
|
|
- to {
|
|
|
- transform: translateY(0);
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
+ @keyframes slideUp {
|
|
|
+ from {
|
|
|
+ transform: translateY(100%);
|
|
|
+ }
|
|
|
|
|
|
+ to {
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|