From e2c0b6b87a1823d37aee7ec33ac93976db6b5d77 Mon Sep 17 00:00:00 2001 From: renjianbo <18691577328@163.com> Date: Sun, 3 May 2026 09:54:32 +0800 Subject: [PATCH] feat(S4): new user onboarding wizard with 3-step guided flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Backend: check-login API returns is_new_user flag (no prompt history) - Vue: OnboardingWizard component (scene select → tips → ready) - Vue: HomeView conditionally shows wizard for new users - Auth store: expose isNewUser state, auto-detect on refresh Co-Authored-By: Claude Opus 4.6 --- src/flask_prompt_master/routes/auth.py | 14 +- vue-app/src/api/types/user.ts | 1 + .../onboarding/OnboardingWizard.vue | 179 ++++++++++++++++++ vue-app/src/stores/auth.ts | 4 +- vue-app/src/views/HomeView.vue | 79 ++++---- 5 files changed, 238 insertions(+), 39 deletions(-) create mode 100644 vue-app/src/components/onboarding/OnboardingWizard.vue diff --git a/src/flask_prompt_master/routes/auth.py b/src/flask_prompt_master/routes/auth.py index 2401aaa..fb46869 100644 --- a/src/flask_prompt_master/routes/auth.py +++ b/src/flask_prompt_master/routes/auth.py @@ -138,11 +138,20 @@ def change_password(): def check_login(): """检查登录状态API""" if 'user_id' in session: + uid = session['user_id'] + # 判断是否新用户(无任何生成记录) + is_new = False + try: + from src.flask_prompt_master.models.models import Prompt + is_new = Prompt.query.filter_by(user_id=uid).count() == 0 + except Exception: + pass return jsonify({ 'success': True, 'logged_in': True, + 'is_new_user': is_new, 'user': { - 'user_id': session['user_id'], + 'user_id': uid, 'nickname': session.get('nickname'), 'login_name': session.get('login_name') } @@ -150,7 +159,8 @@ def check_login(): else: return jsonify({ 'success': True, - 'logged_in': False + 'logged_in': False, + 'is_new_user': True, # 未登录也算新用户, 引导注册 }) @auth_bp.route('/api/profile/stats', methods=['GET']) diff --git a/vue-app/src/api/types/user.ts b/vue-app/src/api/types/user.ts index e04f6d8..f5eb8b2 100644 --- a/vue-app/src/api/types/user.ts +++ b/vue-app/src/api/types/user.ts @@ -1,6 +1,7 @@ export interface CheckLoginResponse { success: boolean logged_in: boolean + is_new_user?: boolean user?: { user_id: number nickname?: string | null diff --git a/vue-app/src/components/onboarding/OnboardingWizard.vue b/vue-app/src/components/onboarding/OnboardingWizard.vue new file mode 100644 index 0000000..6fe4cd0 --- /dev/null +++ b/vue-app/src/components/onboarding/OnboardingWizard.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/vue-app/src/stores/auth.ts b/vue-app/src/stores/auth.ts index 10bcc71..b6c6472 100644 --- a/vue-app/src/stores/auth.ts +++ b/vue-app/src/stores/auth.ts @@ -7,11 +7,13 @@ export const useAuthStore = defineStore('auth', () => { const nickname = ref(null) const userId = ref(null) const ready = ref(false) + const isNewUser = ref(false) async function refresh() { try { const r = await checkLogin() loggedIn.value = Boolean(r.logged_in) + isNewUser.value = Boolean(r.is_new_user) if (r.user) { userId.value = r.user.user_id nickname.value = r.user.nickname ?? r.user.login_name ?? null @@ -52,5 +54,5 @@ export const useAuthStore = defineStore('auth', () => { await refresh() } - return { loggedIn, nickname, userId, ready, refresh, login, logout, register } + return { loggedIn, nickname, userId, ready, isNewUser, refresh, login, logout, register } }) diff --git a/vue-app/src/views/HomeView.vue b/vue-app/src/views/HomeView.vue index b944eed..1726b53 100644 --- a/vue-app/src/views/HomeView.vue +++ b/vue-app/src/views/HomeView.vue @@ -1,48 +1,62 @@ @@ -71,13 +85,6 @@ function openLegacyGenerate() { line-height: 1.65; color: $text-secondary; font-size: 0.95rem; - - code { - font-size: 0.85em; - padding: 0.1em 0.35em; - background: $gray-100; - border-radius: 4px; - } } .status {