|
|
@@ -1,7 +1,5 @@
|
|
|
<template>
|
|
|
- <!-- 手机登录界面+微信快捷登录 -->
|
|
|
<view class="login-page">
|
|
|
-
|
|
|
<!-- 状态栏占位 -->
|
|
|
<view class="status-bar"></view>
|
|
|
|
|
|
@@ -21,198 +19,193 @@
|
|
|
|
|
|
<!-- Logo和标题 -->
|
|
|
<view class="header">
|
|
|
- <view class="logo-circle">
|
|
|
- <image class="logo" src="/static/images/logo.png" mode="aspectFill"></image>
|
|
|
+ <view class="logo-container">
|
|
|
+ <view class="logo-circle">
|
|
|
+ <image class="logo" src="/static/images/logo.png" mode="aspectFit"></image>
|
|
|
+ </view>
|
|
|
+ <view class="logo-shadow"></view>
|
|
|
</view>
|
|
|
-
|
|
|
-
|
|
|
- <view class="logo-shadow"></view>
|
|
|
- </view>
|
|
|
- <view class="title-section">
|
|
|
- <text class="title">知己</text>
|
|
|
- <view class="title-underline"></view>
|
|
|
+ <view class="title-section">
|
|
|
+ <text class="title">知己</text>
|
|
|
+ <view class="title-underline"></view>
|
|
|
+ </view>
|
|
|
+ <text class="subtitle">访客记录软件</text>
|
|
|
</view>
|
|
|
- <text class="subtitle">访客记录软件</text>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 登录按钮 -->
|
|
|
- <view class="login-section">
|
|
|
- <view class="btn-container">
|
|
|
- <button class="wechat-btn" @tap="handleWxLogin" :class="{ 'btn-loading': isLoading }">
|
|
|
- <u-icon name="weixin-fill" size="20" color="#fff" style="margin-right: 12rpx;"></u-icon>
|
|
|
- <text>授权快捷登录</text>
|
|
|
- </button>
|
|
|
- </view>
|
|
|
+ <!-- 登录按钮 -->
|
|
|
+ <view class="login-section">
|
|
|
+ <view class="btn-container">
|
|
|
+ <button class="wechat-btn" @tap="handleWxLogin" :class="{ 'btn-loading': isLoading }">
|
|
|
+ <u-icon name="weixin-fill" size="20" color="#fff" style="margin-right: 12rpx;"></u-icon>
|
|
|
+ <text>授权快捷登录</text>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
|
|
|
- <view class="divider">
|
|
|
- <view class="divider-line"></view>
|
|
|
- <text class="divider-text">或</text>
|
|
|
- <view class="divider-line"></view>
|
|
|
- </view>
|
|
|
+ <view class="divider">
|
|
|
+ <view class="divider-line"></view>
|
|
|
+ <text class="divider-text">或</text>
|
|
|
+ <view class="divider-line"></view>
|
|
|
+ </view>
|
|
|
|
|
|
- <view class="btn-container">
|
|
|
- <button class="phone-btn" @tap="handlePhoneLogin">
|
|
|
- <u-icon name="phone" size="20" color="#e28669" style="margin-right: 12rpx;"></u-icon>
|
|
|
- <text>手机号登录</text>
|
|
|
+ <view class="btn-container">
|
|
|
+ <button class="phone-btn" @tap="handlePhoneLogin">
|
|
|
+ <u-icon name="phone" size="20" color="#e28669" style="margin-right: 12rpx;"></u-icon>
|
|
|
+ <text>手机号登录</text>
|
|
|
|
|
|
- </button>
|
|
|
- </view>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
|
|
|
- <view class="btn-container">
|
|
|
- <button class="browse-btn" @tap="handleBrowse">
|
|
|
- <text>暂不登录,先去看看</text>
|
|
|
- </button>
|
|
|
- </view>
|
|
|
+ <view class="btn-container">
|
|
|
+ <button class="browse-btn" @tap="handleBrowse">
|
|
|
+ <text>暂不登录,先去看看</text>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
|
|
|
- <view class="agreement">
|
|
|
- <view class="checkbox-wrapper" @tap="toggleAgreement">
|
|
|
- <view class="zen-checkbox" :class="{ 'checked': isAgree }">
|
|
|
- <view class="zen-circle-inner" v-if="isAgree"></view>
|
|
|
+ <view class="agreement">
|
|
|
+ <view class="checkbox-wrapper" @tap="toggleAgreement">
|
|
|
+ <view class="zen-checkbox" :class="{ 'checked': isAgree }">
|
|
|
+ <view class="zen-circle-inner" v-if="isAgree"></view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
+ <text class="agreement-text">
|
|
|
+ 登录即代表您已同意
|
|
|
+ <text class="link" @tap="goToPrivacy">《隐私政策》</text>
|
|
|
+ 和
|
|
|
+ <text class="link" @tap="goToService">《服务协议》</text>
|
|
|
+ </text>
|
|
|
</view>
|
|
|
- <text class="agreement-text">
|
|
|
- 登录即代表您已同意
|
|
|
- <text class="link" @tap="goToPrivacy">《隐私政策》</text>
|
|
|
- 和
|
|
|
- <text class="link" @tap="goToService">《服务协议》</text>
|
|
|
- </text>
|
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 底部装饰 -->
|
|
|
- <view class="bottom-decoration">
|
|
|
- <view class="company-info">
|
|
|
- <text class="company-name">知己访客记录系统</text>
|
|
|
- <text class="version">v1.0.0</text>
|
|
|
+ <!-- 底部装饰 -->
|
|
|
+ <view class="bottom-decoration">
|
|
|
+ <view class="company-info">
|
|
|
+ <text class="company-name">知己访客记录系统</text>
|
|
|
+ <text class="version">v1.0.0</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
- <!-- 首次登录设置弹框 -->
|
|
|
- <u-popup :show="showProfileModal">
|
|
|
- <view class="profile-modal">
|
|
|
- <view class="modal-header">
|
|
|
- <text class="modal-title">完善个人信息</text>
|
|
|
- <text class="modal-subtitle">请设置您的账号和头像</text>
|
|
|
- </view>
|
|
|
+ <!-- 首次登录设置弹框 -->
|
|
|
+ <u-popup :show="showProfileModal">
|
|
|
+ <view class="profile-modal">
|
|
|
+ <view class="modal-header">
|
|
|
+ <text class="modal-title">完善个人信息</text>
|
|
|
+ <text class="modal-subtitle">请设置您的账号和头像</text>
|
|
|
+ </view>
|
|
|
|
|
|
- <view class="modal-content">
|
|
|
- <!-- 头像选择 -->
|
|
|
- <view class="avatar-section">
|
|
|
- <text class="section-label">头像</text>
|
|
|
- <button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"
|
|
|
- :disabled="isUploadingAvatar">
|
|
|
- <view class="avatar-container">
|
|
|
- <image class="avatar-preview" :src="tempAvatar || '/static/images/avatar.png'"
|
|
|
- mode="aspectFill"></image>
|
|
|
- <view class="avatar-overlay">
|
|
|
- <u-icon v-if="!isUploadingAvatar" name="camera" size="24" color="#fff"></u-icon>
|
|
|
- <u-loading-icon v-else mode="spinner" size="24" color="#fff"></u-loading-icon>
|
|
|
+ <view class="modal-content">
|
|
|
+ <!-- 头像选择 -->
|
|
|
+ <view class="avatar-section">
|
|
|
+ <text class="section-label">头像</text>
|
|
|
+ <button class="avatar-button" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"
|
|
|
+ :disabled="isUploadingAvatar">
|
|
|
+ <view class="avatar-container">
|
|
|
+ <image class="avatar-preview" :src="tempAvatar || '/static/images/avatar.png'"
|
|
|
+ mode="aspectFill"></image>
|
|
|
+ <view class="avatar-overlay">
|
|
|
+ <u-icon v-if="!isUploadingAvatar" name="camera" size="24" color="#fff"></u-icon>
|
|
|
+ <u-loading-icon v-else mode="spinner" size="24" color="#fff"></u-loading-icon>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- </button>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 账号输入 -->
|
|
|
+ <view class="account-section">
|
|
|
+ <text class="section-label">用户名</text>
|
|
|
+ <u-input v-model="tempAccount" placeholder="请输入用户名" :maxlength="20" :clearable="true"
|
|
|
+ border="surround"></u-input>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 账号输入 -->
|
|
|
- <view class="account-section">
|
|
|
- <text class="section-label">用户名</text>
|
|
|
- <u-input v-model="tempAccount" placeholder="请输入用户名" :maxlength="20" :clearable="true"
|
|
|
- border="surround"></u-input>
|
|
|
+ <view class="modal-actions">
|
|
|
+ <button class="confirm-btn" @tap="confirmProfile"
|
|
|
+ :disabled="!tempAccount.trim() || isUploadingAvatar">
|
|
|
+ <text v-if="!isUploadingAvatar">确认</text>
|
|
|
+ <text v-else>头像上传中...</text>
|
|
|
+ </button>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
- <view class="modal-actions">
|
|
|
- <button class="confirm-btn" @tap="confirmProfile" :disabled="!tempAccount.trim() || isUploadingAvatar">
|
|
|
- <text v-if="!isUploadingAvatar">确认</text>
|
|
|
- <text v-else>头像上传中...</text>
|
|
|
- </button>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </u-popup>
|
|
|
-
|
|
|
-
|
|
|
+ </u-popup>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import {
|
|
|
- wxLogin,
|
|
|
- updateProfile
|
|
|
-} from '@/config/api.js';
|
|
|
-import {
|
|
|
- UPLOAD_URL
|
|
|
-} from '@/common/config.js';
|
|
|
-
|
|
|
-export default {
|
|
|
- data() {
|
|
|
- return {
|
|
|
- isAgree: false,
|
|
|
- isLoading: false,
|
|
|
- redirectUrl: '', // 登录成功后的重定向地址
|
|
|
- showProfileModal: false, // 显示个人信息设置弹框
|
|
|
- tempAccount: '', // 临时账号
|
|
|
- tempAvatar: '', // 临时头像
|
|
|
- loginData: null, // 临时保存登录数据
|
|
|
- isUploadingAvatar: false // 头像上传状态
|
|
|
- }
|
|
|
- },
|
|
|
- onLoad(options) {
|
|
|
- // 获取重定向地址
|
|
|
- if (options.redirect) {
|
|
|
- this.redirectUrl = decodeURIComponent(options.redirect);
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- // 处理微信登录
|
|
|
- async handleWxLogin() {
|
|
|
- if (!this.isAgree) {
|
|
|
- let that = this
|
|
|
- // 弹出确认弹框询问用户是否同意协议
|
|
|
- uni.showModal({
|
|
|
- title: '提示',
|
|
|
- content: '登录需要您同意《隐私政策》和《服务协议》,是否同意?',
|
|
|
- success: function (res) {
|
|
|
- if (res.confirm) {
|
|
|
- // 用户点击同意,自动勾选协议并执行登录
|
|
|
- that.isAgree = true;
|
|
|
- that.executeLogin();
|
|
|
- } else if (res.cancel) {
|
|
|
- console.log('用户点击取消');
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- return;
|
|
|
+ import {
|
|
|
+ wxLogin,
|
|
|
+ updateProfile
|
|
|
+ } from '@/config/api.js';
|
|
|
+ import {
|
|
|
+ UPLOAD_URL
|
|
|
+ } from '@/common/config.js';
|
|
|
+
|
|
|
+ export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isAgree: false,
|
|
|
+ isLoading: false,
|
|
|
+ redirectUrl: '', // 登录成功后的重定向地址
|
|
|
+ showProfileModal: false, // 显示个人信息设置弹框
|
|
|
+ tempAccount: '', // 临时账号
|
|
|
+ tempAvatar: '', // 临时头像
|
|
|
+ loginData: null, // 临时保存登录数据
|
|
|
+ isUploadingAvatar: false // 头像上传状态
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad(options) {
|
|
|
+ // 获取重定向地址
|
|
|
+ if (options.redirect) {
|
|
|
+ this.redirectUrl = decodeURIComponent(options.redirect);
|
|
|
}
|
|
|
-
|
|
|
- this.executeLogin();
|
|
|
},
|
|
|
+ methods: {
|
|
|
+ // 处理微信登录
|
|
|
+ async handleWxLogin() {
|
|
|
+ if (!this.isAgree) {
|
|
|
+ let that = this
|
|
|
+ // 弹出确认弹框询问用户是否同意协议
|
|
|
+ uni.showModal({
|
|
|
+ title: '提示',
|
|
|
+ content: '登录需要您同意《隐私政策》和《服务协议》,是否同意?',
|
|
|
+ success: function(res) {
|
|
|
+ if (res.confirm) {
|
|
|
+ // 用户点击同意,自动勾选协议并执行登录
|
|
|
+ that.isAgree = true;
|
|
|
+ that.executeLogin();
|
|
|
+ } else if (res.cancel) {
|
|
|
+ console.log('用户点击取消');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // 执行登录逻辑
|
|
|
- async executeLogin() {
|
|
|
- uni.showLoading({
|
|
|
- mask: true
|
|
|
- })
|
|
|
- this.isLoading = true;
|
|
|
-
|
|
|
- uni.getUserProfile({
|
|
|
- desc: '用于完善会员资料',
|
|
|
- success: (profileRes) => {
|
|
|
- uni.login({
|
|
|
- provider: 'weixin',
|
|
|
- success: async (loginRes) => {
|
|
|
- console.log('loginRes:', loginRes.code);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
- const loginData = await wxLogin({
|
|
|
- code: loginRes.code,
|
|
|
- account: profileRes.userInfo.nickName,
|
|
|
- avatarUrl: profileRes.userInfo.avatarUrl,
|
|
|
- grant_type: 'wechat'
|
|
|
- });
|
|
|
-
|
|
|
- if (loginData.code === 200) {
|
|
|
- // 检查是否为首次登录
|
|
|
- if (loginData.isFirstLogin) {
|
|
|
- // 首次登录,显示个人信息设置弹框
|
|
|
+ this.executeLogin();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 执行登录逻辑
|
|
|
+ async executeLogin() {
|
|
|
+ uni.showLoading({
|
|
|
+ mask: true
|
|
|
+ })
|
|
|
+ this.isLoading = true;
|
|
|
+
|
|
|
+ uni.getUserProfile({
|
|
|
+ desc: '用于完善会员资料',
|
|
|
+ success: (profileRes) => {
|
|
|
+ uni.login({
|
|
|
+ provider: 'weixin',
|
|
|
+ success: async (loginRes) => {
|
|
|
+ console.log(loginRes.code, "code")
|
|
|
+ try {
|
|
|
+ const loginData = await wxLogin({
|
|
|
+ code: loginRes.code,
|
|
|
+ account: profileRes.userInfo.nickName,
|
|
|
+ avatarUrl: profileRes.userInfo.avatarUrl,
|
|
|
+ grant_type: 'wechat'
|
|
|
+ });
|
|
|
+
|
|
|
+ if (loginData.code === 200) {
|
|
|
this.loginData = loginData;
|
|
|
this.tempAccount = loginData.account || '';
|
|
|
this.tempAvatar = loginData.avatar || '';
|
|
|
@@ -228,704 +221,686 @@ export default {
|
|
|
this.$store.commit('refresh_token', loginData
|
|
|
.refresh_token);
|
|
|
uni.hideLoading();
|
|
|
- } else {
|
|
|
- // 非首次登录,直接保存并跳转
|
|
|
this.saveLoginDataAndRedirect(loginData);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: loginData.msg || '登录失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
}
|
|
|
- } else {
|
|
|
+ } catch (e) {
|
|
|
+ console.error('登录错误:', e);
|
|
|
uni.showToast({
|
|
|
- title: loginData.msg || '登录失败',
|
|
|
+ title: '登录失败,请重试',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
+ } finally {
|
|
|
+ this.isLoading = false;
|
|
|
}
|
|
|
- } catch (e) {
|
|
|
- console.error('登录错误:', e);
|
|
|
- uni.showToast({
|
|
|
- title: '登录失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- } finally {
|
|
|
+ },
|
|
|
+ fail: () => {
|
|
|
this.isLoading = false;
|
|
|
}
|
|
|
- },
|
|
|
- fail: () => {
|
|
|
- this.isLoading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ this.isLoading = false;
|
|
|
+ if (err.errMsg.includes('cancel')) {
|
|
|
+ return; // 用户取消,不显示提示
|
|
|
}
|
|
|
- });
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- this.isLoading = false;
|
|
|
- if (err.errMsg.includes('cancel')) {
|
|
|
- return; // 用户取消,不显示提示
|
|
|
+ uni.showToast({
|
|
|
+ title: '获取用户信息失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
}
|
|
|
- uni.showToast({
|
|
|
- title: '获取用户信息失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 切换协议同意状态
|
|
|
+ toggleAgreement() {
|
|
|
+ this.isAgree = !this.isAgree;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 返回上一页
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 跳转到隐私政策
|
|
|
+ goToPrivacy() {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pagesA/public/richtext'
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- // 切换协议同意状态
|
|
|
- toggleAgreement() {
|
|
|
- this.isAgree = !this.isAgree;
|
|
|
- },
|
|
|
+ // 跳转到服务协议
|
|
|
+ goToService() {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pagesA/public/richtext'
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- // 返回上一页
|
|
|
- goBack() {
|
|
|
- uni.navigateBack();
|
|
|
- },
|
|
|
+ handleBrowse() {
|
|
|
+ // 直接返回首页
|
|
|
+ uni.switchTab({
|
|
|
+ url: '/pages/index/index'
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- // 跳转到隐私政策
|
|
|
- goToPrivacy() {
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pagesA/public/richtext'
|
|
|
- });
|
|
|
- },
|
|
|
+ // 跳转到手机登录页面
|
|
|
+ handlePhoneLogin() {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pagesA/public/phone-login'
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- // 跳转到服务协议
|
|
|
- goToService() {
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pagesA/public/richtext'
|
|
|
- });
|
|
|
- },
|
|
|
+ // 保存登录数据并跳转
|
|
|
+ saveLoginDataAndRedirect(loginData) {
|
|
|
+ uni.setStorageSync('access_token', loginData.access_token);
|
|
|
+ uni.setStorageSync('refresh_token', loginData.refresh_token);
|
|
|
+ uni.setStorageSync('user', loginData);
|
|
|
|
|
|
- handleBrowse() {
|
|
|
- // 直接返回首页
|
|
|
- uni.switchTab({
|
|
|
- url: '/pages/index/index'
|
|
|
- });
|
|
|
- },
|
|
|
+ this.$store.commit('isLogin', true);
|
|
|
+ this.$store.commit('refresh_token', loginData.refresh_token);
|
|
|
|
|
|
- // 跳转到手机登录页面
|
|
|
- handlePhoneLogin() {
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pagesA/public/phone-login'
|
|
|
- });
|
|
|
- },
|
|
|
+ uni.showToast({
|
|
|
+ title: '登录成功',
|
|
|
+ icon: 'success',
|
|
|
+ duration: 1000
|
|
|
+ });
|
|
|
|
|
|
- // 保存登录数据并跳转
|
|
|
- saveLoginDataAndRedirect(loginData) {
|
|
|
- uni.setStorageSync('access_token', loginData.access_token);
|
|
|
- uni.setStorageSync('refresh_token', loginData.refresh_token);
|
|
|
- uni.setStorageSync('user', loginData);
|
|
|
-
|
|
|
- this.$store.commit('isLogin', true);
|
|
|
- this.$store.commit('refresh_token', loginData.refresh_token);
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- title: '登录成功',
|
|
|
- icon: 'success',
|
|
|
- duration: 1000
|
|
|
- });
|
|
|
-
|
|
|
- // 登录成功后的跳转
|
|
|
- setTimeout(() => {
|
|
|
- if (this.redirectUrl) {
|
|
|
- uni.redirectTo({
|
|
|
- url: this.redirectUrl
|
|
|
+ // 登录成功后的跳转
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.switchTab({
|
|
|
+ url: '/pages/index/index'
|
|
|
});
|
|
|
- } else {
|
|
|
- // 检查是否有待处理的邀请,如果有则跳转到首页触发邀请弹框
|
|
|
- const pendingInvitation = uni.getStorageSync('pendingInvitation');
|
|
|
- if (pendingInvitation && pendingInvitation.inviterId) {
|
|
|
- console.log('登录成功,发现待处理邀请,跳转到首页');
|
|
|
- // 使用 reLaunch 确保首页能重新加载并检查邀请
|
|
|
- uni.reLaunch({
|
|
|
- url: '/pages/index/index'
|
|
|
+ }, 1000);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 微信小程序头像选择回调
|
|
|
+ async onChooseAvatar(e) {
|
|
|
+ console.log('选择头像:', e.detail.avatarUrl);
|
|
|
+
|
|
|
+ // 显示上传状态
|
|
|
+ this.isUploadingAvatar = true;
|
|
|
+ uni.showLoading({
|
|
|
+ title: '上传头像中...',
|
|
|
+ mask: true
|
|
|
+ });
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 上传头像到服务器
|
|
|
+ const uploadResult = await this.uploadFilePromise(e.detail.avatarUrl);
|
|
|
+ if (uploadResult && uploadResult.data && uploadResult.data.link) {
|
|
|
+ this.tempAvatar = uploadResult.data.link;
|
|
|
+ uni.showToast({
|
|
|
+ title: '头像上传成功',
|
|
|
+ icon: 'success'
|
|
|
});
|
|
|
} else {
|
|
|
- uni.switchTab({
|
|
|
- url: '/pages/index/index'
|
|
|
- });
|
|
|
+ throw new Error('上传失败');
|
|
|
}
|
|
|
- }
|
|
|
- }, 1000);
|
|
|
- },
|
|
|
-
|
|
|
- // 微信小程序头像选择回调
|
|
|
- async onChooseAvatar(e) {
|
|
|
- console.log('选择头像:', e.detail.avatarUrl);
|
|
|
-
|
|
|
- // 显示上传状态
|
|
|
- this.isUploadingAvatar = true;
|
|
|
- uni.showLoading({
|
|
|
- title: '上传头像中...',
|
|
|
- mask: true
|
|
|
- });
|
|
|
-
|
|
|
- try {
|
|
|
- // 上传头像到服务器
|
|
|
- const uploadResult = await this.uploadFilePromise(e.detail.avatarUrl);
|
|
|
- if (uploadResult && uploadResult.data && uploadResult.data.link) {
|
|
|
- this.tempAvatar = uploadResult.data.link;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('头像上传失败:', error);
|
|
|
uni.showToast({
|
|
|
- title: '头像上传成功',
|
|
|
- icon: 'success'
|
|
|
+ title: '头像上传失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
});
|
|
|
- } else {
|
|
|
- throw new Error('上传失败');
|
|
|
+ } finally {
|
|
|
+ this.isUploadingAvatar = false;
|
|
|
+ uni.hideLoading();
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('头像上传失败:', error);
|
|
|
- uni.showToast({
|
|
|
- title: '头像上传失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- } finally {
|
|
|
- this.isUploadingAvatar = false;
|
|
|
- uni.hideLoading();
|
|
|
- }
|
|
|
- },
|
|
|
+ },
|
|
|
+
|
|
|
+ // 上传文件到服务器
|
|
|
+ uploadFilePromise(filePath) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ // 优先使用登录数据中的token,如果没有则使用本地存储的token
|
|
|
+ const token = (this.loginData && this.loginData.access_token) || uni.getStorageSync(
|
|
|
+ 'access_token');
|
|
|
+
|
|
|
+ if (!token) {
|
|
|
+ reject(new Error('未找到访问令牌'));
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 上传文件到服务器
|
|
|
- uploadFilePromise(filePath) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // 优先使用登录数据中的token,如果没有则使用本地存储的token
|
|
|
- const token = (this.loginData && this.loginData.access_token) || uni.getStorageSync(
|
|
|
- 'access_token');
|
|
|
+ uni.uploadFile({
|
|
|
+ url: UPLOAD_URL,
|
|
|
+ filePath: filePath,
|
|
|
+ header: {
|
|
|
+ "Blade-Auth": token
|
|
|
+ },
|
|
|
+ name: 'file',
|
|
|
+ formData: {
|
|
|
+ user: 'avatar'
|
|
|
+ },
|
|
|
+ success: (res) => {
|
|
|
+ try {
|
|
|
+ const result = JSON.parse(res.data);
|
|
|
+ if (result.success || result.code === 200) {
|
|
|
+ resolve(result);
|
|
|
+ } else {
|
|
|
+ reject(new Error(result.msg || '上传失败'));
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ reject(new Error('解析响应失败'));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: (error) => {
|
|
|
+ reject(error);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
|
|
|
- if (!token) {
|
|
|
- reject(new Error('未找到访问令牌'));
|
|
|
+ // 确认个人信息设置
|
|
|
+ async confirmProfile() {
|
|
|
+ if (!this.tempAccount.trim()) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请输入账号',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- uni.uploadFile({
|
|
|
- url: UPLOAD_URL,
|
|
|
- filePath: filePath,
|
|
|
- header: {
|
|
|
- "Blade-Auth": token
|
|
|
- },
|
|
|
- name: 'file',
|
|
|
- formData: {
|
|
|
- user: 'avatar'
|
|
|
- },
|
|
|
- success: (res) => {
|
|
|
- try {
|
|
|
- const result = JSON.parse(res.data);
|
|
|
- if (result.success || result.code === 200) {
|
|
|
- resolve(result);
|
|
|
- } else {
|
|
|
- reject(new Error(result.msg || '上传失败'));
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- reject(new Error('解析响应失败'));
|
|
|
- }
|
|
|
- },
|
|
|
- fail: (error) => {
|
|
|
- reject(error);
|
|
|
- }
|
|
|
+ uni.showLoading({
|
|
|
+ title: '保存中...',
|
|
|
+ mask: true
|
|
|
});
|
|
|
- });
|
|
|
- },
|
|
|
|
|
|
- // 确认个人信息设置
|
|
|
- async confirmProfile() {
|
|
|
- if (!this.tempAccount.trim()) {
|
|
|
- uni.showToast({
|
|
|
- title: '请输入账号',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
+ try {
|
|
|
+ // 调用更新用户信息接口
|
|
|
+ const updateRes = await updateProfile({
|
|
|
+ account: this.tempAccount.trim(),
|
|
|
+ avatar: this.tempAvatar
|
|
|
+ });
|
|
|
|
|
|
- uni.showLoading({
|
|
|
- title: '保存中...',
|
|
|
- mask: true
|
|
|
- });
|
|
|
+ if (updateRes.code == 200) {
|
|
|
+ // 更新登录数据中的用户信息
|
|
|
+ this.loginData.account = this.tempAccount.trim();
|
|
|
+ if (this.tempAvatar) {
|
|
|
+ this.loginData.avatar = this.tempAvatar;
|
|
|
+ this.loginData.avatarUrl = this.tempAvatar; // 同时更新 avatarUrl 字段
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
- // 调用更新用户信息接口
|
|
|
- const updateRes = await updateProfile({
|
|
|
- account: this.tempAccount.trim(),
|
|
|
- avatar: this.tempAvatar
|
|
|
- });
|
|
|
+ // 更新本地存储的用户信息
|
|
|
+ uni.setStorageSync('user', this.loginData);
|
|
|
|
|
|
- if (updateRes.code == 200) {
|
|
|
- // 更新登录数据中的用户信息
|
|
|
- this.loginData.account = this.tempAccount.trim();
|
|
|
- if (this.tempAvatar) {
|
|
|
- this.loginData.avatar = this.tempAvatar;
|
|
|
- this.loginData.avatarUrl = this.tempAvatar; // 同时更新 avatarUrl 字段
|
|
|
+ // 保存登录数据并跳转
|
|
|
+ this.saveLoginDataAndRedirect(this.loginData);
|
|
|
+ this.showProfileModal = false;
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ title: updateRes.msg || '保存失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
- // 更新本地存储的用户信息
|
|
|
- uni.setStorageSync('user', this.loginData);
|
|
|
-
|
|
|
- // 保存登录数据并跳转
|
|
|
- this.saveLoginDataAndRedirect(this.loginData);
|
|
|
- this.showProfileModal = false;
|
|
|
- } else {
|
|
|
+ } catch (error) {
|
|
|
+ console.error('更新用户信息错误:', error);
|
|
|
uni.showToast({
|
|
|
- title: updateRes.msg || '保存失败,请重试',
|
|
|
+ title: '保存失败,请重试',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
+ } finally {
|
|
|
+ uni.hideLoading();
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('更新用户信息错误:', error);
|
|
|
- uni.showToast({
|
|
|
- title: '保存失败,请重试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- } finally {
|
|
|
- uni.hideLoading();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.login-page {
|
|
|
- min-height: 100vh;
|
|
|
- background: #F5F5F5;
|
|
|
- position: relative;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
-
|
|
|
-.status-bar {
|
|
|
- height: var(--status-bar-height);
|
|
|
- width: 100%;
|
|
|
-}
|
|
|
-
|
|
|
-// 现代化背景
|
|
|
-.modern-bg {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- pointer-events: none;
|
|
|
- z-index: 1;
|
|
|
-
|
|
|
- .bg-shape {
|
|
|
+ .login-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #F5F5F5;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-bar {
|
|
|
+ height: var(--status-bar-height);
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 现代化背景
|
|
|
+ .modern-bg {
|
|
|
position: absolute;
|
|
|
- border-radius: 50%;
|
|
|
-
|
|
|
- &.shape-1 {
|
|
|
- width: 300rpx;
|
|
|
- height: 300rpx;
|
|
|
- top: 15%;
|
|
|
- right: -80rpx;
|
|
|
- background: linear-gradient(135deg, rgba(255, 91, 5, 0.1) 0%, transparent 70%);
|
|
|
- }
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ pointer-events: none;
|
|
|
+ z-index: 1;
|
|
|
|
|
|
- &.shape-2 {
|
|
|
- width: 200rpx;
|
|
|
- height: 200rpx;
|
|
|
- top: 50%;
|
|
|
- left: -60rpx;
|
|
|
- background: linear-gradient(135deg, rgba(41, 44, 53, 0.08) 0%, transparent 70%);
|
|
|
- }
|
|
|
+ .bg-shape {
|
|
|
+ position: absolute;
|
|
|
+ border-radius: 50%;
|
|
|
+
|
|
|
+ &.shape-1 {
|
|
|
+ width: 300rpx;
|
|
|
+ height: 300rpx;
|
|
|
+ top: 15%;
|
|
|
+ right: -80rpx;
|
|
|
+ background: linear-gradient(135deg, rgba(255, 91, 5, 0.1) 0%, transparent 70%);
|
|
|
+ }
|
|
|
|
|
|
- &.shape-3 {
|
|
|
- width: 150rpx;
|
|
|
- height: 150rpx;
|
|
|
- bottom: 25%;
|
|
|
- right: 15%;
|
|
|
- background: linear-gradient(135deg, rgba(255, 91, 5, 0.06) 0%, transparent 70%);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.nav-back {
|
|
|
- position: fixed;
|
|
|
- left: 30rpx;
|
|
|
- top: calc(var(--status-bar-height) + 20rpx);
|
|
|
- z-index: 100;
|
|
|
-
|
|
|
- .back-btn {
|
|
|
- width: 80rpx;
|
|
|
- height: 80rpx;
|
|
|
- background: #FFFFFF;
|
|
|
- border: 1rpx solid rgba(255, 91, 5, 0.2);
|
|
|
- border-radius: 50%;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- transition: all 0.3s ease;
|
|
|
- box-shadow: 0 4rpx 16rpx rgba(41, 44, 53, 0.1);
|
|
|
+ &.shape-2 {
|
|
|
+ width: 200rpx;
|
|
|
+ height: 200rpx;
|
|
|
+ top: 50%;
|
|
|
+ left: -60rpx;
|
|
|
+ background: linear-gradient(135deg, rgba(41, 44, 53, 0.08) 0%, transparent 70%);
|
|
|
+ }
|
|
|
|
|
|
- &:active {
|
|
|
- transform: scale(0.95);
|
|
|
- background: rgba(255, 91, 5, 0.1);
|
|
|
+ &.shape-3 {
|
|
|
+ width: 150rpx;
|
|
|
+ height: 150rpx;
|
|
|
+ bottom: 25%;
|
|
|
+ right: 15%;
|
|
|
+ background: linear-gradient(135deg, rgba(255, 91, 5, 0.06) 0%, transparent 70%);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .back-icon {
|
|
|
- font-family: "iconfont";
|
|
|
- font-size: 36rpx;
|
|
|
- color: #292C35;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.header {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- padding-top: 120rpx;
|
|
|
- position: relative;
|
|
|
- z-index: 2;
|
|
|
-
|
|
|
- .logo-container {
|
|
|
- position: relative; // 设置为相对定位,作为子元素的定位参考
|
|
|
- margin-bottom: 60rpx; // 底部外边距60rpx,与标题保持间距
|
|
|
-
|
|
|
- .logo-circle {
|
|
|
- width: 100rpx; // Logo容器宽度100rpx
|
|
|
- height: 100rpx; // Logo容器高度100rpx
|
|
|
- border-radius: 20rpx; // 圆角20rpx,让容器呈圆角矩形
|
|
|
- background: #FFFFFF; // 背景色为白色
|
|
|
- display: flex; // 使用弹性布局
|
|
|
- align-items: center; // 垂直居中对齐
|
|
|
- justify-content: center; // 水平居中对齐
|
|
|
- box-shadow: 0 8rpx 24rpx rgba(41, 44, 53, 0.1); // 添加阴影效果,让容器有浮起感
|
|
|
- border: 2rpx solid rgba(255, 91, 5, 0.2); // 边框2rpx,橙色半透明
|
|
|
-
|
|
|
- .logo {
|
|
|
- width: 40rpx; // Logo图片宽度40rpx
|
|
|
- height: 40rpx; // Logo图片高度40rpx
|
|
|
- border-radius: 16rpx; // Logo图片圆角16rpx
|
|
|
+ .nav-back {
|
|
|
+ position: fixed;
|
|
|
+ left: 30rpx;
|
|
|
+ top: calc(var(--status-bar-height) + 20rpx);
|
|
|
+ z-index: 100;
|
|
|
+
|
|
|
+ .back-btn {
|
|
|
+ width: 80rpx;
|
|
|
+ height: 80rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border: 1rpx solid rgba(255, 91, 5, 0.2);
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(41, 44, 53, 0.1);
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ transform: scale(0.95);
|
|
|
+ background: rgba(255, 91, 5, 0.1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .logo-shadow {
|
|
|
- position: absolute; // 绝对定位,相对于logo-container定位
|
|
|
- bottom: -20rpx; // 距离底部-20rpx,创建阴影向下延伸效果
|
|
|
- left: 50%; // 距离左边50%
|
|
|
- transform: translateX(-50%); // 水平居中,通过左移自身宽度的一半来实现
|
|
|
- width: 160rpx; // 阴影宽度160rpx
|
|
|
- height: 20rpx; // 阴影高度20rpx
|
|
|
- background: radial-gradient(ellipse, rgba(255, 91, 5, 0.1) 0%, transparent 70%); // 径向渐变,从中心向外逐渐透明
|
|
|
- border-radius: 50%; // 完全圆形
|
|
|
+ .back-icon {
|
|
|
+ font-family: "iconfont";
|
|
|
+ font-size: 36rpx;
|
|
|
+ color: #292C35;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .title-section {
|
|
|
- text-align: center;
|
|
|
- margin-bottom: 20rpx;
|
|
|
+ .header {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ padding-top: 120rpx;
|
|
|
position: relative;
|
|
|
+ z-index: 2;
|
|
|
+
|
|
|
+ .logo-container {
|
|
|
+ position: relative;
|
|
|
+ margin-bottom: 60rpx;
|
|
|
+
|
|
|
+ .logo-circle {
|
|
|
+ width: 200rpx;
|
|
|
+ height: 200rpx;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(41, 44, 53, 0.1);
|
|
|
+ border: 2rpx solid rgba(255, 91, 5, 0.2);
|
|
|
+
|
|
|
+ .logo {
|
|
|
+ width: 160rpx;
|
|
|
+ height: 160rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .title {
|
|
|
- font-size: 64rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #292C35;
|
|
|
- letter-spacing: 8rpx;
|
|
|
- font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
|
|
|
- text-shadow: 0 2rpx 8rpx rgba(41, 44, 53, 0.1);
|
|
|
- }
|
|
|
-
|
|
|
- .title-underline {
|
|
|
- position: absolute;
|
|
|
- bottom: -10rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- width: 80rpx;
|
|
|
- height: 4rpx;
|
|
|
- background: linear-gradient(90deg, transparent, #FF5B05, transparent);
|
|
|
- border-radius: 2rpx;
|
|
|
+ .logo-shadow {
|
|
|
+ position: absolute;
|
|
|
+ bottom: -20rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 160rpx;
|
|
|
+ height: 20rpx;
|
|
|
+ background: radial-gradient(ellipse, rgba(255, 91, 5, 0.1) 0%, transparent 70%);
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .subtitle {
|
|
|
- font-size: 28rpx;
|
|
|
- color: rgba(41, 44, 53, 0.7);
|
|
|
- font-weight: 300;
|
|
|
- letter-spacing: 4rpx;
|
|
|
- font-family: inherit;
|
|
|
- }
|
|
|
-}
|
|
|
+ .title-section {
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-size: 64rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #292C35;
|
|
|
+ letter-spacing: 8rpx;
|
|
|
+ font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
|
|
|
+ text-shadow: 0 2rpx 8rpx rgba(41, 44, 53, 0.1);
|
|
|
+ }
|
|
|
|
|
|
-.login-section {
|
|
|
- padding: 80rpx 60rpx;
|
|
|
- position: relative;
|
|
|
- z-index: 2;
|
|
|
+ .title-underline {
|
|
|
+ position: absolute;
|
|
|
+ bottom: -10rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 80rpx;
|
|
|
+ height: 4rpx;
|
|
|
+ background: linear-gradient(90deg, transparent, #FF5B05, transparent);
|
|
|
+ border-radius: 2rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .btn-container {
|
|
|
- margin-bottom: 40rpx;
|
|
|
+ .subtitle {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: rgba(41, 44, 53, 0.7);
|
|
|
+ font-weight: 300;
|
|
|
+ letter-spacing: 4rpx;
|
|
|
+ font-family: inherit;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .wechat-btn {
|
|
|
+ .login-section {
|
|
|
+ padding: 80rpx 60rpx;
|
|
|
position: relative;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 100%;
|
|
|
- height: 96rpx;
|
|
|
- background: linear-gradient(135deg, #FF5B05 0%, #FF8E3C 100%);
|
|
|
- border: none;
|
|
|
- border-radius: 48rpx;
|
|
|
- color: #fff;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- transition: all 0.3s ease;
|
|
|
- box-shadow: 0 4rpx 16rpx rgba(255, 91, 5, 0.3);
|
|
|
-
|
|
|
- &:active {
|
|
|
- transform: translateY(2rpx);
|
|
|
- box-shadow: 0 2rpx 8rpx rgba(255, 91, 5, 0.4);
|
|
|
- }
|
|
|
+ z-index: 2;
|
|
|
|
|
|
- &.btn-loading {
|
|
|
- background: linear-gradient(135deg, #FFB088 0%, #FFA573 100%);
|
|
|
- color: rgba(255, 255, 255, 0.8);
|
|
|
+ .btn-container {
|
|
|
+ margin-bottom: 40rpx;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .phone-btn {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 100%;
|
|
|
- height: 96rpx;
|
|
|
- background: #FFFFFF;
|
|
|
- border: 2rpx solid #FF5B05;
|
|
|
- border-radius: 48rpx;
|
|
|
- color: #FF5B05;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- transition: all 0.3s ease;
|
|
|
- box-shadow: 0 4rpx 16rpx rgba(41, 44, 53, 0.1);
|
|
|
-
|
|
|
- &:active {
|
|
|
- transform: translateY(2rpx);
|
|
|
- background: rgba(255, 91, 5, 0.05);
|
|
|
- }
|
|
|
- }
|
|
|
+ .wechat-btn {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 96rpx;
|
|
|
+ background: linear-gradient(135deg, #FF5B05 0%, #FF8E3C 100%);
|
|
|
+ border: none;
|
|
|
+ border-radius: 48rpx;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(255, 91, 5, 0.3);
|
|
|
|
|
|
- .divider {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin: 40rpx 0;
|
|
|
+ &:active {
|
|
|
+ transform: translateY(2rpx);
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(255, 91, 5, 0.4);
|
|
|
+ }
|
|
|
|
|
|
- .divider-line {
|
|
|
- flex: 1;
|
|
|
- height: 1rpx;
|
|
|
- background: linear-gradient(90deg, transparent, rgba(41, 44, 53, 0.1), transparent);
|
|
|
+ &.btn-loading {
|
|
|
+ background: linear-gradient(135deg, #FFB088 0%, #FFA573 100%);
|
|
|
+ color: rgba(255, 255, 255, 0.8);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .divider-text {
|
|
|
- margin: 0 30rpx;
|
|
|
- font-size: 26rpx;
|
|
|
- color: rgba(41, 44, 53, 0.5);
|
|
|
- }
|
|
|
- }
|
|
|
+ .phone-btn {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 96rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border: 2rpx solid #FF5B05;
|
|
|
+ border-radius: 48rpx;
|
|
|
+ color: #FF5B05;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ box-shadow: 0 4rpx 16rpx rgba(41, 44, 53, 0.1);
|
|
|
|
|
|
- .browse-btn {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 100%;
|
|
|
- height: 88rpx;
|
|
|
- background: transparent;
|
|
|
- border: 1rpx solid rgba(41, 44, 53, 0.2);
|
|
|
- border-radius: 44rpx;
|
|
|
- color: #292C35;
|
|
|
- font-size: 28rpx;
|
|
|
- transition: all 0.3s ease;
|
|
|
-
|
|
|
- &:active {
|
|
|
- background: rgba(41, 44, 53, 0.05);
|
|
|
- transform: translateY(1rpx);
|
|
|
+ &:active {
|
|
|
+ transform: translateY(2rpx);
|
|
|
+ background: rgba(255, 91, 5, 0.05);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .agreement {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- margin-top: 60rpx;
|
|
|
+ .divider {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin: 40rpx 0;
|
|
|
|
|
|
- .checkbox-wrapper {
|
|
|
- margin-right: 16rpx;
|
|
|
+ .divider-line {
|
|
|
+ flex: 1;
|
|
|
+ height: 1rpx;
|
|
|
+ background: linear-gradient(90deg, transparent, rgba(41, 44, 53, 0.1), transparent);
|
|
|
+ }
|
|
|
+
|
|
|
+ .divider-text {
|
|
|
+ margin: 0 30rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: rgba(41, 44, 53, 0.5);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .zen-checkbox {
|
|
|
- width: 36rpx;
|
|
|
- height: 36rpx;
|
|
|
- border: 2rpx solid rgba(255, 91, 5, 0.4);
|
|
|
- border-radius: 18rpx;
|
|
|
+ .browse-btn {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 88rpx;
|
|
|
+ background: transparent;
|
|
|
+ border: 1rpx solid rgba(41, 44, 53, 0.2);
|
|
|
+ border-radius: 44rpx;
|
|
|
+ color: #292C35;
|
|
|
+ font-size: 28rpx;
|
|
|
transition: all 0.3s ease;
|
|
|
- background: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
- &.checked {
|
|
|
- background: #FF5B05;
|
|
|
- border-color: #FF5B05;
|
|
|
+ &:active {
|
|
|
+ background: rgba(41, 44, 53, 0.05);
|
|
|
+ transform: translateY(1rpx);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- .zen-circle-inner {
|
|
|
- width: 16rpx;
|
|
|
- height: 16rpx;
|
|
|
- border-radius: 50%;
|
|
|
- background: #fff;
|
|
|
+ .agreement {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-top: 60rpx;
|
|
|
+
|
|
|
+ .checkbox-wrapper {
|
|
|
+ margin-right: 16rpx;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .agreement-text {
|
|
|
- font-size: 24rpx;
|
|
|
- color: rgba(41, 44, 53, 0.6);
|
|
|
- line-height: 1.5;
|
|
|
+ .zen-checkbox {
|
|
|
+ width: 36rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ border: 2rpx solid rgba(255, 91, 5, 0.4);
|
|
|
+ border-radius: 18rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ background: rgba(255, 255, 255, 0.9);
|
|
|
+
|
|
|
+ &.checked {
|
|
|
+ background: #FF5B05;
|
|
|
+ border-color: #FF5B05;
|
|
|
+ }
|
|
|
|
|
|
- .link {
|
|
|
- color: #FF5B05;
|
|
|
- text-decoration: none;
|
|
|
+ .zen-circle-inner {
|
|
|
+ width: 16rpx;
|
|
|
+ height: 16rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 底部装饰
|
|
|
-.bottom-decoration {
|
|
|
- position: absolute;
|
|
|
- bottom: 40rpx;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- z-index: 1;
|
|
|
-
|
|
|
- .company-info {
|
|
|
- text-align: center;
|
|
|
-
|
|
|
- .company-name {
|
|
|
- display: block;
|
|
|
- font-size: 24rpx;
|
|
|
- color: rgba(41, 44, 53, 0.6);
|
|
|
- margin-bottom: 8rpx;
|
|
|
- font-weight: 400;
|
|
|
- }
|
|
|
|
|
|
- .version {
|
|
|
- font-size: 20rpx;
|
|
|
- color: rgba(41, 44, 53, 0.4);
|
|
|
- font-weight: 300;
|
|
|
+ .agreement-text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: rgba(41, 44, 53, 0.6);
|
|
|
+ line-height: 1.5;
|
|
|
+
|
|
|
+ .link {
|
|
|
+ color: #FF5B05;
|
|
|
+ text-decoration: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 个人信息设置弹框样式
|
|
|
-.profile-modal {
|
|
|
- width: 750rpx;
|
|
|
- background: #fff;
|
|
|
- border-radius: 20rpx;
|
|
|
- overflow: hidden;
|
|
|
-
|
|
|
- .modal-header {
|
|
|
- text-align: center;
|
|
|
- padding: 60rpx 40rpx 40rpx;
|
|
|
- background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
|
-
|
|
|
- .modal-title {
|
|
|
- display: block;
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: 600;
|
|
|
- color: #2c3e50;
|
|
|
- margin-bottom: 12rpx;
|
|
|
- }
|
|
|
|
|
|
- .modal-subtitle {
|
|
|
- font-size: 26rpx;
|
|
|
- color: rgba(44, 62, 80, 0.7);
|
|
|
+ // 底部装饰
|
|
|
+ .bottom-decoration {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 40rpx;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ z-index: 1;
|
|
|
+
|
|
|
+ .company-info {
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .company-name {
|
|
|
+ display: block;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: rgba(41, 44, 53, 0.6);
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+
|
|
|
+ .version {
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: rgba(41, 44, 53, 0.4);
|
|
|
+ font-weight: 300;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .modal-content {
|
|
|
- padding: 40rpx;
|
|
|
+ // 个人信息设置弹框样式
|
|
|
+ .profile-modal {
|
|
|
+ width: 750rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ overflow: hidden;
|
|
|
|
|
|
- .avatar-section {
|
|
|
- margin-bottom: 40rpx;
|
|
|
+ .modal-header {
|
|
|
text-align: center;
|
|
|
+ padding: 60rpx 40rpx 40rpx;
|
|
|
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
|
|
|
|
- .section-label {
|
|
|
+ .modal-title {
|
|
|
display: block;
|
|
|
- font-size: 28rpx;
|
|
|
+ font-size: 36rpx;
|
|
|
+ font-weight: 600;
|
|
|
color: #2c3e50;
|
|
|
- margin-bottom: 20rpx;
|
|
|
- font-weight: 500;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
}
|
|
|
|
|
|
- .avatar-button {
|
|
|
- background: none;
|
|
|
- border: none;
|
|
|
- padding: 0;
|
|
|
- margin: 0 auto;
|
|
|
- display: block;
|
|
|
- width: 160rpx;
|
|
|
- height: 160rpx;
|
|
|
+ .modal-subtitle {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: rgba(44, 62, 80, 0.7);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- &::after {
|
|
|
- border: none;
|
|
|
- }
|
|
|
+ .modal-content {
|
|
|
+ padding: 40rpx;
|
|
|
|
|
|
- &:disabled {
|
|
|
- opacity: 0.7;
|
|
|
+ .avatar-section {
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .section-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ font-weight: 500;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .avatar-container {
|
|
|
- position: relative;
|
|
|
- width: 160rpx;
|
|
|
- height: 160rpx;
|
|
|
- border-radius: 50%;
|
|
|
- overflow: hidden;
|
|
|
- border: 3rpx solid #4A90E2;
|
|
|
+ .avatar-button {
|
|
|
+ background: none;
|
|
|
+ border: none;
|
|
|
+ padding: 0;
|
|
|
+ margin: 0 auto;
|
|
|
+ display: block;
|
|
|
+ width: 160rpx;
|
|
|
+ height: 160rpx;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
|
|
|
- .avatar-preview {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
+ &:disabled {
|
|
|
+ opacity: 0.7;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .avatar-overlay {
|
|
|
- position: absolute;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- height: 50rpx;
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
+ .avatar-container {
|
|
|
+ position: relative;
|
|
|
+ width: 160rpx;
|
|
|
+ height: 160rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 3rpx solid #4A90E2;
|
|
|
+
|
|
|
+ .avatar-preview {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .avatar-overlay {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ height: 50rpx;
|
|
|
+ background: rgba(0, 0, 0, 0.5);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .account-section {
|
|
|
- .section-label {
|
|
|
- display: block;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #2c3e50;
|
|
|
- margin-bottom: 20rpx;
|
|
|
- font-weight: 500;
|
|
|
+ .account-section {
|
|
|
+ .section-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .modal-actions {
|
|
|
- padding: 0 40rpx 40rpx;
|
|
|
+ .modal-actions {
|
|
|
+ padding: 0 40rpx 40rpx;
|
|
|
|
|
|
- .confirm-btn {
|
|
|
- width: 100%;
|
|
|
- height: 80rpx;
|
|
|
- background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
|
|
- color: #fff;
|
|
|
- border-radius: 12rpx;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: 500;
|
|
|
- border: none;
|
|
|
- transition: all 0.3s ease;
|
|
|
+ .confirm-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ border: none;
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
|
- &:disabled {
|
|
|
- background: #bdc3c7;
|
|
|
- color: rgba(255, 255, 255, 0.7);
|
|
|
- }
|
|
|
+ &:disabled {
|
|
|
+ background: #bdc3c7;
|
|
|
+ color: rgba(255, 255, 255, 0.7);
|
|
|
+ }
|
|
|
|
|
|
- &:not(:disabled):active {
|
|
|
- transform: translateY(2rpx);
|
|
|
- box-shadow: 0 2rpx 8rpx rgba(74, 144, 226, 0.3);
|
|
|
+ &:not(:disabled):active {
|
|
|
+ transform: translateY(2rpx);
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(74, 144, 226, 0.3);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
</style>
|