From 5487ece142ba7f74218a8969c1c924c53262867e Mon Sep 17 00:00:00 2001 From: gqt <3217233537@qq.com> Date: Mon, 13 Jul 2026 21:09:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=99=BB=E5=BD=95=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E9=87=8D=E6=9E=84=20-=20=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5+=E5=AE=8C=E5=96=84=E4=BF=A1=E6=81=AF=E9=A1=B5+401?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 profile/login.vue 登录页(UnauthLoginPanel) - 新增 profile/setup.vue 完善信息页(头像/昵称/手机号) - profile/index 未登录态显示头像占位+点击登录+菜单列表 - 登录后始终跳转setup页,completeLogin后才持久化token - auth.js 登录后用pendingToken(内存),不检查profile_completed - request.js 401时reLaunch到登录页,不显示toast,防重复跳转 - 约课页移除UnauthLoginPanel,未登录直接显示列表 - session.js 新增needsSetup状态和completeLogin方法 --- .../src/modules/comprehensive/api/auth.js | 3 +- .../src/modules/comprehensive/api/member.js | 1 + .../src/modules/comprehensive/api/request.js | 39 ++- .../modules/comprehensive/stores/session.js | 14 +- miniprogram/src/pages.json | 12 + .../src/pages/comprehensive/courses/index.vue | 13 +- .../src/pages/comprehensive/profile/index.vue | 193 +++++++++---- .../src/pages/comprehensive/profile/login.vue | 28 ++ .../src/pages/comprehensive/profile/setup.vue | 265 ++++++++++++++++++ 9 files changed, 489 insertions(+), 79 deletions(-) create mode 100644 miniprogram/src/pages/comprehensive/profile/login.vue create mode 100644 miniprogram/src/pages/comprehensive/profile/setup.vue diff --git a/miniprogram/src/modules/comprehensive/api/auth.js b/miniprogram/src/modules/comprehensive/api/auth.js index 42b6012..4f68df1 100644 --- a/miniprogram/src/modules/comprehensive/api/auth.js +++ b/miniprogram/src/modules/comprehensive/api/auth.js @@ -10,6 +10,7 @@ const toMember = (backendMember = {}) => ({ avatar_url: backendMember.avatar_url || '', balance: backendMember.balance || '0.00', is_active: backendMember.is_active === true, + profile_completed: backendMember.profile_completed === true, created_at: backendMember.created_at || '' }) @@ -33,7 +34,7 @@ export const authApi = { } }).then(toWechatLogin) - authStorage.setToken(loginData.access_token) + authStorage.setPendingToken(loginData.access_token) return loginData }, logout() { diff --git a/miniprogram/src/modules/comprehensive/api/member.js b/miniprogram/src/modules/comprehensive/api/member.js index 20fd25b..dbaacd9 100644 --- a/miniprogram/src/modules/comprehensive/api/member.js +++ b/miniprogram/src/modules/comprehensive/api/member.js @@ -10,6 +10,7 @@ const toMember = (backendMember = {}) => ({ avatar_url: backendMember.avatar_url || '', balance: backendMember.balance || '0.00', is_active: backendMember.is_active === true, + profile_completed: backendMember.profile_completed === true, created_at: backendMember.created_at || '' }) diff --git a/miniprogram/src/modules/comprehensive/api/request.js b/miniprogram/src/modules/comprehensive/api/request.js index c84474c..da97125 100644 --- a/miniprogram/src/modules/comprehensive/api/request.js +++ b/miniprogram/src/modules/comprehensive/api/request.js @@ -2,6 +2,8 @@ const KEY_TOKEN = 'COMPREHENSIVE_VENUE_TOKEN' const API_BASE_URL = import.meta.env.VITE_COMPREHENSIVE_API_BASE_URL || 'http://127.0.0.1:8001' +let pendingToken = null + const normalizeError = (res, fallbackMessage = '请求服务失败') => { const body = res?.data || res || {} return { @@ -19,16 +21,41 @@ export const authStorage = { getToken() { return uni.getStorageSync(KEY_TOKEN) }, + setPendingToken(token) { + pendingToken = token + }, + getPendingToken() { + return pendingToken + }, + clearPendingToken() { + pendingToken = null + }, clear() { uni.removeStorageSync(KEY_TOKEN) + pendingToken = null }, isLoggedIn() { return !!uni.getStorageSync(KEY_TOKEN) } } +let isRedirecting = false + +function redirectToLogin() { + if (isRedirecting) return + const pages = getCurrentPages() + const current = pages[pages.length - 1] + const currentRoute = current?.route || '' + if (currentRoute === 'pages/comprehensive/profile/login' || currentRoute === 'pages/comprehensive/profile/setup') { + return + } + isRedirecting = true + authStorage.clear() + uni.reLaunch({ url: '/pages/comprehensive/profile/login', complete: () => { isRedirecting = false } }) +} + export function request(options = {}) { - const token = authStorage.getToken() + const token = authStorage.getToken() || authStorage.getPendingToken() const header = { 'Content-Type': 'application/json', ...(options.header || {}) @@ -48,7 +75,9 @@ export function request(options = {}) { const body = res.data if (res.statusCode === 401 || body?.code === 40001) { - authStorage.clear() + redirectToLogin() + reject(normalizeError(res, '')) + return } if (res.statusCode >= 200 && res.statusCode < 300 && body?.code === 0) { @@ -76,7 +105,7 @@ export function request(options = {}) { } export function uploadFile(options = {}) { - const token = authStorage.getToken() + const token = authStorage.getToken() || authStorage.getPendingToken() const header = { ...(options.header || {}) } @@ -101,7 +130,9 @@ export function uploadFile(options = {}) { } if (res.statusCode === 401 || body?.code === 40001) { - authStorage.clear() + redirectToLogin() + reject(normalizeError({ ...res, data: body }, '')) + return } if (res.statusCode >= 200 && res.statusCode < 300 && body?.code === 0) { diff --git a/miniprogram/src/modules/comprehensive/stores/session.js b/miniprogram/src/modules/comprehensive/stores/session.js index 8298c8d..fda6d80 100644 --- a/miniprogram/src/modules/comprehensive/stores/session.js +++ b/miniprogram/src/modules/comprehensive/stores/session.js @@ -6,6 +6,7 @@ export const useComprehensiveSessionStore = defineStore('comprehensiveVenueSessi state: () => ({ isReady: false, isLoggedIn: false, + needsSetup: false, member: null }), actions: { @@ -28,12 +29,23 @@ export const useComprehensiveSessionStore = defineStore('comprehensiveVenueSessi const loginResult = await loginByWechat() const data = await authApi.wechatLogin({ code: loginResult.code }) this.member = data.member - this.isLoggedIn = true + this.needsSetup = true + return data + }, + completeLogin() { + const pendingToken = authStorage.getPendingToken() + if (pendingToken) { + authStorage.setToken(pendingToken) + authStorage.clearPendingToken() + this.isLoggedIn = true + this.needsSetup = false + } }, logout() { authApi.logout() this.member = null this.isLoggedIn = false + this.needsSetup = false }, async refreshMember() { if (!authStorage.isLoggedIn()) return diff --git a/miniprogram/src/pages.json b/miniprogram/src/pages.json index 58d514b..c0322a7 100644 --- a/miniprogram/src/pages.json +++ b/miniprogram/src/pages.json @@ -174,6 +174,18 @@ "navigationBarTitleText": "个人信息" } }, + { + "path": "pages/comprehensive/profile/login", + "style": { + "navigationBarTitleText": "登录" + } + }, + { + "path": "pages/comprehensive/profile/setup", + "style": { + "navigationBarTitleText": "完善信息" + } + }, { "path": "pages/comprehensive/mall/index", "style": { diff --git a/miniprogram/src/pages/comprehensive/courses/index.vue b/miniprogram/src/pages/comprehensive/courses/index.vue index 95f7aee..7d39eeb 100644 --- a/miniprogram/src/pages/comprehensive/courses/index.vue +++ b/miniprogram/src/pages/comprehensive/courses/index.vue @@ -1,11 +1,6 @@