|
@@ -4,11 +4,12 @@
|
|
|
<image class="avatar" :src="userInfo.avatar || '/static/avatar.png'"></image>
|
|
|
<view class="user-details">
|
|
|
<text class="username">{{ userInfo.username }}</text>
|
|
|
- <text class="user-id">ID: {{ userInfo.userId }}</text>
|
|
|
+ <!-- <text class="user-id">ID: {{ userInfo.userId }}</text> -->
|
|
|
+ <text class="user-phone" v-if="userInfo.phone">手机: {{ formatPhone(userInfo.phone) }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <view class="user-info" v-else @click="goLogin">
|
|
|
+ <view class="user-info" v-else @click="wxLogin">
|
|
|
<image class="avatar" src="/static/avatar.png"></image>
|
|
|
<view class="user-details">
|
|
|
<text class="username">点击登录</text>
|
|
@@ -29,269 +30,640 @@
|
|
|
<view class="logout-btn" @click="handleLogout" v-if="isLogin">
|
|
|
<text>退出登录</text>
|
|
|
</view>
|
|
|
+
|
|
|
+ <!-- 添加一个隐藏的授权按钮,在需要时显示 -->
|
|
|
+ <view class="auth-modal" v-if="showAuthModal">
|
|
|
+ <view class="auth-content">
|
|
|
+ <text class="auth-title">微信授权登录</text>
|
|
|
+ <text class="auth-desc">请授权获取您的微信头像和昵称</text>
|
|
|
+ <button class="auth-btn" @tap="getUserProfile">确认授权</button>
|
|
|
+ <button class="auth-cancel" @tap="cancelAuth">取消</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 添加获取手机号按钮 -->
|
|
|
+ <button
|
|
|
+ v-if="isLogin && !userInfo.phone"
|
|
|
+ open-type="getPhoneNumber"
|
|
|
+ @getphonenumber="getPhoneNumber"
|
|
|
+ class="get-phone-btn">
|
|
|
+ 绑定手机号
|
|
|
+ </button>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
- export default {
|
|
|
- data() {
|
|
|
- return {
|
|
|
- isLogin: false,
|
|
|
- userInfo: {
|
|
|
- username: '',
|
|
|
- userId: '',
|
|
|
- avatar: ''
|
|
|
- },
|
|
|
- menuItems: [
|
|
|
- { title: '个人资料', icon: 'icon-user', action: 'profile' },
|
|
|
- // { title: '我的订单', icon: 'icon-order', action: 'orders' },
|
|
|
- // { title: '我的收藏', icon: 'icon-star', action: 'favorites' },
|
|
|
- { title: '设置', icon: 'icon-settings', action: 'settings' },
|
|
|
- { title: '帮助中心', icon: 'icon-help', action: 'help' }
|
|
|
- ]
|
|
|
- }
|
|
|
- },
|
|
|
- onShow() {
|
|
|
- // 每次显示页面时检查登录状态
|
|
|
- this.checkLoginStatus();
|
|
|
- },
|
|
|
- methods: {
|
|
|
- // 检查登录状态
|
|
|
- checkLoginStatus() {
|
|
|
- try {
|
|
|
- const token = uni.getStorageSync('token');
|
|
|
- const userInfo = uni.getStorageSync('userInfo');
|
|
|
+// 直接导入所有需要的 API 函数
|
|
|
+import { log } from 'util';
|
|
|
+import { wxLogin, getUserInfo, getUserPhoneNumber, logout } from '../../api/user.js';
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isLogin: false,
|
|
|
+ userInfo: {
|
|
|
+ username: '',
|
|
|
+ userId: '',
|
|
|
+ avatar: ''
|
|
|
+ },
|
|
|
+ menuItems: [
|
|
|
+ { title: '个人资料', icon: 'icon-user', action: 'profile' },
|
|
|
+ // { title: '我的订单', icon: 'icon-order', action: 'orders' },
|
|
|
+ // { title: '我的收藏', icon: 'icon-star', action: 'favorites' },
|
|
|
+ { title: '设置', icon: 'icon-settings', action: 'settings' },
|
|
|
+ { title: '帮助中心', icon: 'icon-help', action: 'help' }
|
|
|
+ ],
|
|
|
+ showAuthModal: false,
|
|
|
+ wxLoginCode: '' // 存储微信登录code
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onShow() {
|
|
|
+ // 每次显示页面时检查登录状态
|
|
|
+ this.checkLoginStatus();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 检查登录状态
|
|
|
+ checkLoginStatus() {
|
|
|
+ try {
|
|
|
+ const token = uni.getStorageSync('token');
|
|
|
+ const userInfoStr = uni.getStorageSync('userInfo');
|
|
|
+
|
|
|
+ if (token && userInfoStr) {
|
|
|
+ const userInfo = JSON.parse(userInfoStr);
|
|
|
|
|
|
- if (token && userInfo) {
|
|
|
- this.isLogin = true;
|
|
|
- this.userInfo = JSON.parse(userInfo);
|
|
|
- } else {
|
|
|
- this.isLogin = false;
|
|
|
- this.userInfo = {
|
|
|
- username: '',
|
|
|
- userId: '',
|
|
|
- avatar: ''
|
|
|
- };
|
|
|
+ // 检查登录是否过期(可选:如果需要登录有效期)
|
|
|
+ const loginTime = userInfo.loginTime || 0;
|
|
|
+ const currentTime = new Date().getTime();
|
|
|
+ const loginExpireTime = 7 * 24 * 60 * 60 * 1000; // 例如7天过期
|
|
|
+
|
|
|
+ if (currentTime - loginTime > loginExpireTime) {
|
|
|
+ console.log('登录已过期,需要重新登录');
|
|
|
+ this.handleLogout(false); // 静默登出,不显示提示
|
|
|
+ return;
|
|
|
}
|
|
|
- } catch (e) {
|
|
|
- console.error('获取登录状态失败', e);
|
|
|
+
|
|
|
+ // 设置登录状态
|
|
|
+ this.isLogin = true;
|
|
|
+ this.userInfo = userInfo;
|
|
|
+
|
|
|
+ // 可选:每次打开页面时刷新用户信息
|
|
|
+ this.fetchUserDetail();
|
|
|
+ } else {
|
|
|
+ // 未登录状态
|
|
|
this.isLogin = false;
|
|
|
+ this.userInfo = {
|
|
|
+ username: '',
|
|
|
+ userId: '',
|
|
|
+ avatar: '',
|
|
|
+ phone: ''
|
|
|
+ };
|
|
|
}
|
|
|
- },
|
|
|
+ } catch (e) {
|
|
|
+ console.error('获取登录状态失败', e);
|
|
|
+ this.isLogin = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 前往登录页
|
|
|
+ goLogin() {
|
|
|
+ // 显示登录方式选择
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: ['账号密码登录', '微信登录'],
|
|
|
+ success: (res) => {
|
|
|
+ if (res.tapIndex === 0) {
|
|
|
+ // 账号密码登录
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/login/login'
|
|
|
+ });
|
|
|
+ } else if (res.tapIndex === 1) {
|
|
|
+ // 微信登录
|
|
|
+ this.wxLogin();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 微信登录
|
|
|
+ wxLogin() {
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ this.getWxLoginCode();
|
|
|
+ // #endif
|
|
|
|
|
|
- // 前往登录页
|
|
|
- goLogin() {
|
|
|
- // 显示登录方式选择
|
|
|
- uni.showActionSheet({
|
|
|
- itemList: ['账号密码登录', '微信登录'],
|
|
|
- success: (res) => {
|
|
|
- if (res.tapIndex === 0) {
|
|
|
- // 账号密码登录
|
|
|
- uni.navigateTo({
|
|
|
- url: '/pages/login/login'
|
|
|
- });
|
|
|
- } else if (res.tapIndex === 1) {
|
|
|
- // 微信登录
|
|
|
- this.wxLogin();
|
|
|
+ // #ifndef MP-WEIXIN
|
|
|
+ uni.showToast({
|
|
|
+ title: '请在微信环境中使用微信登录',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ // #endif
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取微信登录 code
|
|
|
+ getWxLoginCode() {
|
|
|
+ uni.showLoading({ title: '登录中...' });
|
|
|
+
|
|
|
+ // 每次都重新获取 code
|
|
|
+ uni.login({
|
|
|
+ provider: 'weixin',
|
|
|
+ success: (loginRes) => {
|
|
|
+ console.log('获取微信登录code成功:', loginRes.code);
|
|
|
+ // 保存code,并显示授权弹窗
|
|
|
+ this.wxLoginCode = loginRes.code;
|
|
|
+ uni.hideLoading();
|
|
|
+ this.showAuthModal = true;
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ uni.hideLoading();
|
|
|
+ console.error('获取微信登录code失败:', err);
|
|
|
+ uni.showToast({
|
|
|
+ title: '微信登录失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 用户点击授权按钮时调用
|
|
|
+ getUserProfile() {
|
|
|
+ // 这个方法直接绑定到按钮的点击事件
|
|
|
+ wx.getUserProfile({
|
|
|
+ desc: '用于完善用户资料',
|
|
|
+ success: (profileRes) => {
|
|
|
+ console.log('获取用户信息成功:', profileRes);
|
|
|
+
|
|
|
+ // 准备完整的登录参数
|
|
|
+ const loginParams = {
|
|
|
+ code: this.wxLoginCode,
|
|
|
+ userInfo: profileRes.userInfo,
|
|
|
+ signature: profileRes.signature,
|
|
|
+ rawData: profileRes.rawData,
|
|
|
+ encryptedData: profileRes.encryptedData,
|
|
|
+ iv: profileRes.iv
|
|
|
+ };
|
|
|
+
|
|
|
+ // 隐藏授权弹窗
|
|
|
+ this.showAuthModal = false;
|
|
|
+
|
|
|
+ // 发送登录请求
|
|
|
+ this.wxLoginRequest(loginParams);
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('获取用户信息失败:', err);
|
|
|
+ this.showAuthModal = false;
|
|
|
+
|
|
|
+ // 如果用户拒绝授权,仍然可以使用code登录,但没有用户信息
|
|
|
+ this.wxLoginRequest({
|
|
|
+ code: this.wxLoginCode,
|
|
|
+ userInfo: {
|
|
|
+ nickName: '微信用户',
|
|
|
+ avatarUrl: '',
|
|
|
+ gender: 0,
|
|
|
+ province: '',
|
|
|
+ city: '',
|
|
|
+ country: ''
|
|
|
}
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 取消授权
|
|
|
+ cancelAuth() {
|
|
|
+ this.showAuthModal = false;
|
|
|
+ // 使用code进行静默登录
|
|
|
+ this.wxLoginRequest({
|
|
|
+ code: this.wxLoginCode,
|
|
|
+ userInfo: {
|
|
|
+ nickName: '微信用户',
|
|
|
+ avatarUrl: '',
|
|
|
+ gender: 0,
|
|
|
+ province: '',
|
|
|
+ city: '',
|
|
|
+ country: ''
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 头像选择回调
|
|
|
+ onChooseAvatar(e) {
|
|
|
+ const { avatarUrl } = e.detail;
|
|
|
+ // 这里可以将头像上传到服务器或进行其他处理
|
|
|
+ console.log('用户选择的头像:', avatarUrl);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 发送微信登录请求并处理结果
|
|
|
+ async wxLoginRequest(loginParams) {
|
|
|
+ try {
|
|
|
+ uni.showLoading({ title: '登录中...' });
|
|
|
+
|
|
|
+ console.log('发送登录请求,参数:', loginParams);
|
|
|
+
|
|
|
+ // 发送登录请求
|
|
|
+ const data = await wxLogin(loginParams);
|
|
|
+ console.log('登录成功,返回数据:', data);
|
|
|
+
|
|
|
+ // 构建用户信息对象
|
|
|
+ const userData = this.buildUserData(data, loginParams);
|
|
|
+
|
|
|
+ // 保存登录状态
|
|
|
+ this.saveLoginState(data, userData);
|
|
|
+
|
|
|
+ // 步骤6: 获取用户详细信息 - 如果需要的话
|
|
|
+ if (userData.userId) {
|
|
|
+ this.fetchUserDetail();
|
|
|
+ } else {
|
|
|
+ console.log('无法获取用户ID,跳过获取详细信息');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否需要获取手机号
|
|
|
+ if (!userData.phone) {
|
|
|
+ console.log('用户未绑定手机号,可以提示用户绑定');
|
|
|
+ // 这里可以显示提示或自动弹出获取手机号的按钮
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.handleLoginError(error, loginParams);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建用户数据对象
|
|
|
+ * @param {Object} data - 后端返回的数据
|
|
|
+ * @param {Object} loginParams - 登录参数
|
|
|
+ * @returns {Object} - 构建的用户数据
|
|
|
+ */
|
|
|
+ buildUserData(data, loginParams) {
|
|
|
+ console.log('构建用户数据,服务器返回:', data);
|
|
|
+
|
|
|
+ // 处理不同的返回格式
|
|
|
+ let userData = {
|
|
|
+ // 用户基本信息 - 优先使用服务器返回的数据
|
|
|
+ username: data.username || data.nickName ||
|
|
|
+ (loginParams.userInfo ? loginParams.userInfo.nickName : '微信用户'),
|
|
|
+
|
|
|
+ // 用户ID可能在不同字段
|
|
|
+ userId: data.userId || data.user_id || data.id || data.openid || '',
|
|
|
+
|
|
|
+ // 头像可能在不同字段
|
|
|
+ avatar: data.avatar || data.avatarUrl ||
|
|
|
+ (loginParams.userInfo ? loginParams.userInfo.avatarUrl : '/static/avatar.png'),
|
|
|
+
|
|
|
+ // 用户详细信息
|
|
|
+ phone: data.phone || data.mobile || '',
|
|
|
+ gender: data.gender || (loginParams.userInfo ? loginParams.userInfo.gender : 0),
|
|
|
+
|
|
|
+ // 微信相关信息
|
|
|
+ openid: data.openid || '',
|
|
|
+ unionid: data.unionid || '',
|
|
|
+ session_key: data.session_key || '',
|
|
|
+
|
|
|
+ // 是否新用户
|
|
|
+ is_new_user: data.is_new_user || false,
|
|
|
+
|
|
|
+ // 登录时间
|
|
|
+ loginTime: new Date().getTime()
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('构建的用户数据:', userData);
|
|
|
+ return userData;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存登录状态和用户信息
|
|
|
+ * @param {Object} data - 后端返回的数据
|
|
|
+ * @param {Object} userData - 构建的用户数据
|
|
|
+ */
|
|
|
+ saveLoginState(data, userData) {
|
|
|
+ // 保存token - 可能在不同字段
|
|
|
+ const token = data.token || data.session_key || '';
|
|
|
+ if (token) {
|
|
|
+ uni.setStorageSync('token', token);
|
|
|
+ console.log('Token已保存:', token);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存用户信息
|
|
|
+ uni.setStorageSync('userInfo', JSON.stringify(userData));
|
|
|
+ console.log('用户信息已保存');
|
|
|
|
|
|
- // 微信登录
|
|
|
- wxLogin() {
|
|
|
- // 判断是否在微信环境中
|
|
|
- // #ifdef MP-WEIXIN
|
|
|
- uni.showLoading({
|
|
|
- title: '登录中...'
|
|
|
+ // 更新页面状态
|
|
|
+ this.isLogin = true;
|
|
|
+ this.userInfo = userData;
|
|
|
+
|
|
|
+ // 显示成功提示
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: '登录成功',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理登录错误
|
|
|
+ * @param {Error} error - 错误对象
|
|
|
+ * @param {Object} loginParams - 登录参数
|
|
|
+ */
|
|
|
+ handleLoginError(error, loginParams) {
|
|
|
+ uni.hideLoading();
|
|
|
+
|
|
|
+ // 检查是否是 code 无效错误
|
|
|
+ if (error.message && (
|
|
|
+ error.message.includes('code无效') ||
|
|
|
+ error.message.includes('已过期') ||
|
|
|
+ error.message.includes('已被使用') ||
|
|
|
+ error.status === 999)) {
|
|
|
+ console.error('微信登录code无效,重新获取:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: 'code已过期,请重试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
});
|
|
|
|
|
|
- // 直接使用 uni.login 获取 code
|
|
|
- uni.login({
|
|
|
- provider: 'weixin',
|
|
|
- success: (loginRes) => {
|
|
|
- // 获取登录凭证成功后,直接请求后端
|
|
|
- this.wxLoginRequest(loginRes.code);
|
|
|
-
|
|
|
- // 如果需要用户头像和昵称,可以使用新的接口
|
|
|
- this.getUserProfileNew();
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- uni.hideLoading();
|
|
|
- uni.showToast({
|
|
|
- title: '微信登录失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- console.error('微信登录失败', err);
|
|
|
- }
|
|
|
+ // 延迟一下再重新获取code,避免频繁调用
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getWxLoginCode();
|
|
|
+ }, 1000);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其他错误处理保持不变
|
|
|
+ if (error.code === 10001) {
|
|
|
+ // 微信未绑定账号,跳转到绑定页面
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/bind/bind?code=' + (loginParams.code || '')
|
|
|
});
|
|
|
- // #endif
|
|
|
+ } else if (error.message && error.message.includes('CSRF')) {
|
|
|
+ // CSRF 错误处理
|
|
|
+ console.error('CSRF验证失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: 'CSRF验证失败,请刷新页面重试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ setTimeout(() => this.refreshCSRFToken(), 2000);
|
|
|
+ } else {
|
|
|
+ // 其他错误
|
|
|
+ console.error('微信登录失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: error.message || '登录失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户详细信息
|
|
|
+ * 步骤6: 获取并更新用户详细信息
|
|
|
+ */
|
|
|
+ async fetchUserDetail() {
|
|
|
+ try {
|
|
|
+ if (!this.isLogin) return;
|
|
|
+
|
|
|
+ // 获取用户ID
|
|
|
+ const userId = this.userInfo.userId;
|
|
|
+
|
|
|
+ // 调用获取用户详情API
|
|
|
+ const userDetail = await getUserInfo(userId);
|
|
|
+ console.log('获取用户详细信息成功:', userDetail);
|
|
|
|
|
|
- // 非微信环境提示
|
|
|
- // #ifndef MP-WEIXIN
|
|
|
+ if (userDetail) {
|
|
|
+ // 更新用户信息
|
|
|
+ this.updateUserInfo(userDetail);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取用户详细信息失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新用户信息
|
|
|
+ * @param {Object} userDetail - 用户详细信息
|
|
|
+ */
|
|
|
+ updateUserInfo(userDetail) {
|
|
|
+ // 合并现有信息和新获取的详细信息
|
|
|
+ const updatedUserInfo = {
|
|
|
+ ...this.userInfo,
|
|
|
+ // 更新基本信息
|
|
|
+ username: userDetail.username || userDetail.nickName || this.userInfo.username,
|
|
|
+ avatar: userDetail.avatar || userDetail.avatarUrl || this.userInfo.avatar,
|
|
|
+ phone: userDetail.phone || userDetail.mobile || this.userInfo.phone,
|
|
|
+
|
|
|
+ // 更新详细信息
|
|
|
+ email: userDetail.email || '',
|
|
|
+ address: userDetail.address || '',
|
|
|
+ birthday: userDetail.birthday || '',
|
|
|
+
|
|
|
+ // 其他字段
|
|
|
+ ...userDetail
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新状态和存储
|
|
|
+ this.userInfo = updatedUserInfo;
|
|
|
+ uni.setStorageSync('userInfo', JSON.stringify(updatedUserInfo));
|
|
|
+ console.log('用户详细信息已更新');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户手机号
|
|
|
+ * @param {Object} e - 事件对象
|
|
|
+ */
|
|
|
+ async getPhoneNumber(e) {
|
|
|
+ console.log('获取手机号事件:', e);
|
|
|
+
|
|
|
+ // 检查是否成功获取
|
|
|
+ if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
|
|
+ console.error('用户拒绝授权手机号');
|
|
|
uni.showToast({
|
|
|
- title: '请在微信环境中使用微信登录',
|
|
|
+ title: '获取手机号失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
- // #endif
|
|
|
- },
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 使用新的方式获取用户头像和昵称
|
|
|
- getUserProfileNew() {
|
|
|
- // 获取头像
|
|
|
- wx.getUserInfo({
|
|
|
- desc: '用于完善用户资料',
|
|
|
- success: (res) => {
|
|
|
- console.log('获取用户信息成功', res);
|
|
|
- // 可以在这里更新用户头像
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.error('获取用户信息失败', err);
|
|
|
- }
|
|
|
+ try {
|
|
|
+ uni.showLoading({ title: '获取手机号中...' });
|
|
|
+
|
|
|
+ // 需要重新获取登录code
|
|
|
+ const loginResult = await new Promise((resolve, reject) => {
|
|
|
+ uni.login({
|
|
|
+ provider: 'weixin',
|
|
|
+ success: resolve,
|
|
|
+ fail: reject
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
- // 如果需要获取头像,可以使用 button 组件的开放能力
|
|
|
- // 在模板中添加:
|
|
|
- // <button open-type="chooseAvatar" @chooseavatar="onChooseAvatar">获取头像</button>
|
|
|
- },
|
|
|
+ // 准备请求参数
|
|
|
+ const params = {
|
|
|
+ code: loginResult.code,
|
|
|
+ encryptedData: e.detail.encryptedData,
|
|
|
+ iv: e.detail.iv,
|
|
|
+ openid: JSON.parse(uni.getStorageSync('userInfo')).openid
|
|
|
+ };
|
|
|
+ console.log('获取手机号请求参数:', JSON.parse(uni.getStorageSync('userInfo')).openid);
|
|
|
+ // 调用获取手机号API
|
|
|
+ const phoneData = await getUserPhoneNumber(params);
|
|
|
+ console.log('获取手机号成功:', phoneData);
|
|
|
+
|
|
|
+ // 更新用户信息
|
|
|
+ if (phoneData && phoneData.phoneNumber) {
|
|
|
+ const updatedUserInfo = {
|
|
|
+ ...this.userInfo,
|
|
|
+ phone: phoneData.phoneNumber
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新状态和存储
|
|
|
+ this.userInfo = updatedUserInfo;
|
|
|
+ uni.setStorageSync('userInfo', JSON.stringify(updatedUserInfo));
|
|
|
+
|
|
|
+ uni.showToast({
|
|
|
+ title: '手机号绑定成功',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ throw new Error('未能获取到手机号');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取手机号失败:', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: error.message || '获取手机号失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ uni.hideLoading();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 添加刷新 CSRF token 的方法
|
|
|
+ refreshCSRFToken() {
|
|
|
+ // 这里实现获取新的 CSRF token 的逻辑
|
|
|
+ // 可能需要调用特定的 API 或刷新页面
|
|
|
+ uni.request({
|
|
|
+ url: 'your-api-endpoint/csrf-token', // 替换为获取 CSRF token 的 API
|
|
|
+ method: 'GET',
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.csrfToken) {
|
|
|
+ uni.setStorageSync('csrfToken', res.data.csrfToken);
|
|
|
+ console.log('CSRF token 已刷新');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('获取 CSRF token 失败', err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ handleMenuClick(item) {
|
|
|
+ // 检查是否需要登录
|
|
|
+ const needLogin = ['profile', 'orders', 'favorites'];
|
|
|
|
|
|
- // 头像选择回调
|
|
|
- onChooseAvatar(e) {
|
|
|
- const { avatarUrl } = e.detail;
|
|
|
- // 这里可以将头像上传到服务器或进行其他处理
|
|
|
- console.log('用户选择的头像:', avatarUrl);
|
|
|
- },
|
|
|
+ if (needLogin.includes(item.action) && !this.isLogin) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请先登录',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ this.wxLogin()
|
|
|
+ //this.goLogin();
|
|
|
+ }, 1500);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 发送微信登录请求到服务器
|
|
|
- wxLoginRequest(code, userInfo = {}) {
|
|
|
- // 这里替换为您的实际接口地址
|
|
|
- uni.request({
|
|
|
- url: 'https://your-api-domain.com/api/wx/login',
|
|
|
- method: 'POST',
|
|
|
- data: {
|
|
|
- code: code,
|
|
|
- // 不再依赖 getUserProfile 获取的信息
|
|
|
- // 如果有用户选择的头像,可以在这里传递
|
|
|
- },
|
|
|
- success: (res) => {
|
|
|
- uni.hideLoading();
|
|
|
- if (res.data.code === 0) {
|
|
|
- // 登录成功,保存用户信息和token
|
|
|
- const userData = {
|
|
|
- username: res.data.data.username || '微信用户',
|
|
|
- userId: res.data.data.userId,
|
|
|
- avatar: res.data.data.avatar || '/static/avatar.png'
|
|
|
- };
|
|
|
-
|
|
|
- try {
|
|
|
- uni.setStorageSync('token', res.data.data.token);
|
|
|
- uni.setStorageSync('userInfo', JSON.stringify(userData));
|
|
|
-
|
|
|
- // 更新状态
|
|
|
- this.isLogin = true;
|
|
|
- this.userInfo = userData;
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- title: '登录成功',
|
|
|
- icon: 'success'
|
|
|
- });
|
|
|
- } catch (e) {
|
|
|
- console.error('保存登录信息失败', e);
|
|
|
- }
|
|
|
- } else {
|
|
|
+ // 根据action跳转到对应页面
|
|
|
+ switch(item.action) {
|
|
|
+ case 'profile':
|
|
|
+ uni.navigateTo({ url: '/pages/profile/profile' });
|
|
|
+ break;
|
|
|
+ case 'orders':
|
|
|
+ uni.navigateTo({ url: '/pages/orders/orders' });
|
|
|
+ break;
|
|
|
+ case 'favorites':
|
|
|
+ uni.navigateTo({ url: '/pages/favorites/favorites' });
|
|
|
+ break;
|
|
|
+ case 'settings':
|
|
|
+ uni.navigateTo({ url: '/pages/settings/settings' });
|
|
|
+ break;
|
|
|
+ case 'help':
|
|
|
+ uni.navigateTo({ url: '/pages/help/help' });
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ uni.showToast({
|
|
|
+ title: `点击了${item.title}`,
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理退出登录 - 增强版
|
|
|
+ handleLogout(showConfirm = true) {
|
|
|
+ const doLogout = () => {
|
|
|
+ // 调用登出 API
|
|
|
+ logout().then(() => {
|
|
|
+ // 清除登录信息
|
|
|
+ try {
|
|
|
+ uni.removeStorageSync('token');
|
|
|
+ uni.removeStorageSync('userInfo');
|
|
|
+
|
|
|
+ // 更新状态
|
|
|
+ this.isLogin = false;
|
|
|
+ this.userInfo = {
|
|
|
+ username: '',
|
|
|
+ userId: '',
|
|
|
+ avatar: '',
|
|
|
+ phone: ''
|
|
|
+ };
|
|
|
+
|
|
|
+ // 显示提示(如果需要)
|
|
|
+ if (showConfirm) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '已退出登录',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('退出登录失败', e);
|
|
|
+ if (showConfirm) {
|
|
|
uni.showToast({
|
|
|
- title: res.data.msg || '登录失败',
|
|
|
+ title: '退出登录失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
}
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- uni.hideLoading();
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ console.error('退出登录请求失败', err);
|
|
|
+ // 即使 API 请求失败,也清除本地登录状态
|
|
|
+ uni.removeStorageSync('token');
|
|
|
+ uni.removeStorageSync('userInfo');
|
|
|
+ this.isLogin = false;
|
|
|
+
|
|
|
+ if (showConfirm) {
|
|
|
uni.showToast({
|
|
|
- title: '网络请求失败',
|
|
|
+ title: err.message || '退出登录失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
- console.error('微信登录请求失败', err);
|
|
|
}
|
|
|
});
|
|
|
- },
|
|
|
-
|
|
|
- handleMenuClick(item) {
|
|
|
- // 检查是否需要登录
|
|
|
- const needLogin = ['profile', 'orders', 'favorites'];
|
|
|
-
|
|
|
- if (needLogin.includes(item.action) && !this.isLogin) {
|
|
|
- uni.showToast({
|
|
|
- title: '请先登录',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- setTimeout(() => {
|
|
|
- this.goLogin();
|
|
|
- }, 1500);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 根据action跳转到对应页面
|
|
|
- switch(item.action) {
|
|
|
- case 'profile':
|
|
|
- uni.navigateTo({ url: '/pages/profile/profile' });
|
|
|
- break;
|
|
|
- case 'orders':
|
|
|
- uni.navigateTo({ url: '/pages/orders/orders' });
|
|
|
- break;
|
|
|
- case 'favorites':
|
|
|
- uni.navigateTo({ url: '/pages/favorites/favorites' });
|
|
|
- break;
|
|
|
- case 'settings':
|
|
|
- uni.navigateTo({ url: '/pages/settings/settings' });
|
|
|
- break;
|
|
|
- case 'help':
|
|
|
- uni.navigateTo({ url: '/pages/help/help' });
|
|
|
- break;
|
|
|
- default:
|
|
|
- uni.showToast({
|
|
|
- title: `点击了${item.title}`,
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
+ };
|
|
|
|
|
|
- handleLogout() {
|
|
|
+ // 是否需要显示确认对话框
|
|
|
+ if (showConfirm) {
|
|
|
uni.showModal({
|
|
|
title: '提示',
|
|
|
content: '确定要退出登录吗?',
|
|
|
success: (res) => {
|
|
|
if (res.confirm) {
|
|
|
- // 清除登录信息
|
|
|
- try {
|
|
|
- uni.removeStorageSync('token');
|
|
|
- uni.removeStorageSync('userInfo');
|
|
|
-
|
|
|
- // 更新状态
|
|
|
- this.isLogin = false;
|
|
|
- this.userInfo = {
|
|
|
- username: '',
|
|
|
- userId: '',
|
|
|
- avatar: ''
|
|
|
- };
|
|
|
-
|
|
|
- uni.showToast({
|
|
|
- title: '已退出登录',
|
|
|
- icon: 'success'
|
|
|
- });
|
|
|
- } catch (e) {
|
|
|
- console.error('退出登录失败', e);
|
|
|
- uni.showToast({
|
|
|
- title: '退出登录失败',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- }
|
|
|
+ doLogout();
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
+ } else {
|
|
|
+ // 直接登出,不显示确认
|
|
|
+ doLogout();
|
|
|
}
|
|
|
+ },
|
|
|
+ // 格式化手机号,例如:188****8888
|
|
|
+ formatPhone(phone) {
|
|
|
+ if (!phone || phone.length < 11) return phone;
|
|
|
+ return phone.substring(0, 3) + '****' + phone.substring(7);
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
@@ -333,6 +705,12 @@
|
|
|
color: #999;
|
|
|
}
|
|
|
|
|
|
+ .user-phone {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666;
|
|
|
+ margin-top: 6rpx;
|
|
|
+ }
|
|
|
+
|
|
|
.menu-list {
|
|
|
background-color: #ffffff;
|
|
|
border-radius: 12rpx;
|
|
@@ -379,4 +757,70 @@
|
|
|
.icon-right {
|
|
|
color: #cccccc;
|
|
|
}
|
|
|
+
|
|
|
+ /* 授权弹窗样式 */
|
|
|
+ .auth-modal {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-content {
|
|
|
+ width: 80%;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 40rpx;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-title {
|
|
|
+ font-size: 36rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-desc {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ line-height: 80rpx;
|
|
|
+ background-color: #07c160;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .auth-cancel {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ line-height: 80rpx;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ color: #333;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 添加获取手机号按钮样式 */
|
|
|
+ .get-phone-btn {
|
|
|
+ margin-top: 20rpx;
|
|
|
+ background-color: #07c160;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ padding: 16rpx 0;
|
|
|
+ }
|
|
|
</style>
|