From efb3b9428672e1dc4c0ba335374e17d4728d2031 Mon Sep 17 00:00:00 2001 From: yml Date: Sat, 23 May 2026 00:01:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=89=8D=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=AE=9E=E5=90=8D=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/client.ts | 1 + frontend/src/router/index.ts | 22 ++++++++++++++++-- frontend/src/stores/session.ts | 4 +++- .../views/mobile/MobileListingDetailView.vue | 23 ++++++++++++++++++- .../src/views/mobile/MobileRealnameView.vue | 17 +++++++++++++- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 9148212..ddd6e69 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -38,6 +38,7 @@ apiClient.interceptors.response.use( localStorage.removeItem('access_token') localStorage.removeItem('refresh_token') localStorage.removeItem('user_id') + localStorage.removeItem('realname_status') if (!window.location.pathname.startsWith('/m/login') && !window.location.pathname.startsWith('/m/register')) { const redirect = encodeURIComponent(currentPath) diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index b746c69..d03d65b 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -1,5 +1,6 @@ import { createRouter, createWebHistory } from "vue-router"; +import { useSessionStore } from "@/stores/session"; import { isMobileHost, toMobilePath } from "./mobileHost"; const router = createRouter({ @@ -65,7 +66,7 @@ const router = createRouter({ name: "mobile-seller-listing-create", component: () => import("@/views/mobile/MobileSellerListingCreateView.vue"), - meta: { layout: "blank", requiresAuth: true }, + meta: { layout: "blank", requiresAuth: true, requiresRealname: true }, }, { path: "/", @@ -212,7 +213,7 @@ const router = createRouter({ ], }); -router.beforeEach((to) => { +router.beforeEach(async (to) => { if (isMobileHost() && to.path !== toMobilePath(to.path)) { return { path: toMobilePath(to.path), query: to.query, hash: to.hash }; } @@ -221,6 +222,23 @@ router.beforeEach((to) => { return { path: "/m/login", query: { redirect: to.fullPath } }; } + if (to.meta.requiresRealname) { + const session = useSessionStore(); + if (session.realnameStatus !== "verified") { + try { + await session.loadMe(); + } catch { + if (!localStorage.getItem("access_token")) { + return { path: "/m/login", query: { redirect: to.fullPath } }; + } + } + } + + if (session.realnameStatus !== "verified") { + return { path: "/m/realname", query: { redirect: to.fullPath } }; + } + } + if ( to.path === "/admin/login" && localStorage.getItem("admin_access_token") diff --git a/frontend/src/stores/session.ts b/frontend/src/stores/session.ts index 9d12606..c046637 100644 --- a/frontend/src/stores/session.ts +++ b/frontend/src/stores/session.ts @@ -8,7 +8,7 @@ export const useSessionStore = defineStore('session', { refreshToken: localStorage.getItem('refresh_token') || '', userId: Number(localStorage.getItem('user_id') || 0), phone: '', - realnameStatus: 'unknown', + realnameStatus: localStorage.getItem('realname_status') || 'unknown', }), actions: { async login(phone: string, code: string) { @@ -30,6 +30,7 @@ export const useSessionStore = defineStore('session', { localStorage.removeItem('access_token') localStorage.removeItem('refresh_token') localStorage.removeItem('user_id') + localStorage.removeItem('realname_status') }, applySession(user: AuthUser, accessToken: string, refreshToken: string) { this.token = accessToken @@ -45,6 +46,7 @@ export const useSessionStore = defineStore('session', { localStorage.setItem('user_id', String(user.id)) this.phone = user.phone this.realnameStatus = user.realname_status + localStorage.setItem('realname_status', user.realname_status) }, }, }) diff --git a/frontend/src/views/mobile/MobileListingDetailView.vue b/frontend/src/views/mobile/MobileListingDetailView.vue index 353a59e..7093f68 100644 --- a/frontend/src/views/mobile/MobileListingDetailView.vue +++ b/frontend/src/views/mobile/MobileListingDetailView.vue @@ -44,7 +44,28 @@ async function handleCreateOrder() { cancelButtonText: "取消", showCancelButton: true, }).then(() => { - router.push("/m/login"); + router.push({ path: "/m/login", query: { redirect: route.fullPath } }); + }); + return; + } + + if (session.realnameStatus !== "verified") { + try { + await session.loadMe(); + } catch { + // 401 会由全局拦截器处理。 + } + } + + if (session.realnameStatus !== "verified") { + showDialog({ + title: "请先实名认证", + message: "租号下单前需要完成实名认证。", + confirmButtonText: "去认证", + cancelButtonText: "取消", + showCancelButton: true, + }).then(() => { + router.push({ path: "/m/realname", query: { redirect: route.fullPath } }); }); return; } diff --git a/frontend/src/views/mobile/MobileRealnameView.vue b/frontend/src/views/mobile/MobileRealnameView.vue index 62e8060..1a46ca2 100644 --- a/frontend/src/views/mobile/MobileRealnameView.vue +++ b/frontend/src/views/mobile/MobileRealnameView.vue @@ -1,6 +1,6 @@