From 75286acc9a04856cf768f72cb3a4af060a0b3d38 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Sat, 10 May 2025 10:11:39 +0800 Subject: [PATCH] update --- docker-compose.yml | 2 +- src/App.vue | 376 +++++++++++++++++++++++--------------- src/services/api.ts | 31 ++++ src/stores/user.ts | 10 + src/views/AIAgentView.vue | 2 +- src/views/HomeView.vue | 45 ++++- 6 files changed, 320 insertions(+), 146 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0748afd..1ae1a21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: context: . dockerfile: Dockerfile - image: tradus-web:1.0.26 + image: tradus-web:1.0.27 container_name: tradus-web ports: - '6000:80' diff --git a/src/App.vue b/src/App.vue index 852496d..b4ca5b7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -12,6 +12,17 @@ const showUserMenu = ref(false) const showLoginModal = ref(false) const loginMode = ref('login') // 'login' 或 'register' +// 获取最新用户数据 +const fetchUserInfo = async () => { + if (isAuthenticated.value) { + try { + await authApi.getUserInfo() + } catch (error) { + console.error('获取用户数据失败:', error) + } + } +} + // 表单数据 const formData = ref({ email: '', @@ -212,6 +223,7 @@ const openAuthModal = (mode: 'login' | 'register') => { onMounted(() => { document.addEventListener('click', closeMenus) + fetchUserInfo() // 获取最新用户数据 }) onUnmounted(() => { @@ -285,7 +297,15 @@ onUnmounted(() => {
{{ userInfo?.nickname?.charAt(0) || 'U' }}
- {{ userInfo?.nickname }} +
+ {{ + userInfo?.nickname + }} +
+ + {{ userInfo.points }} 积分 +
+
{
{{ userInfo?.nickname?.charAt(0) || 'U' }}
- {{ userInfo?.nickname }} +
+ {{ + userInfo?.nickname + }} +
+ + {{ userInfo.points }} 积分 +
+
diff --git a/src/services/api.ts b/src/services/api.ts index 180a8c2..cda49c6 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -70,6 +70,37 @@ export const authApi = { return authData }, + + // 获取用户最新数据 + async getUserInfo() { + const userStore = useUserStore() + if (!userStore.isAuthenticated) { + throw new Error('用户未登录') + } + + const response = await fetch(`${apiBaseUrl}/user/me`, { + method: 'GET', + headers: { + Authorization: userStore.authHeader, + }, + }) + + if (!response.ok) { + if (response.status === 401) { + userStore.logout() + throw new Error('登录已过期,请重新登录') + } + const errorData = await response.json().catch(() => ({})) + throw new Error(errorData.detail || `请求失败: ${response.status}`) + } + + const userData = await response.json() + + // 更新用户信息 + userStore.updateUserInfo(userData) + + return userData + }, } // 创建带有认证头的请求函数 diff --git a/src/stores/user.ts b/src/stores/user.ts index 5eaea4d..95e64be 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -7,6 +7,7 @@ export interface UserInfo { nickname: string level: number create_time: string + points?: number } export interface AuthResponse { @@ -42,6 +43,14 @@ export const useUserStore = defineStore('user', () => { localStorage.setItem('user_info', JSON.stringify(authResponse.user_info)) } + // 更新用户信息 + function updateUserInfo(newUserInfo: UserInfo) { + userInfo.value = newUserInfo + + // 更新本地存储 + localStorage.setItem('user_info', JSON.stringify(newUserInfo)) + } + // 登出 function logout() { accessToken.value = null @@ -63,6 +72,7 @@ export const useUserStore = defineStore('user', () => { isAuthenticated, authHeader, setAuth, + updateUserInfo, logout, } }) diff --git a/src/views/AIAgentView.vue b/src/views/AIAgentView.vue index a2a426f..f5c8481 100644 --- a/src/views/AIAgentView.vue +++ b/src/views/AIAgentView.vue @@ -673,7 +673,7 @@ const getIconPath = (agent: Agent) => { } .input-container { - padding: 0.5rem 0.5rem 5.5rem 0.5rem; + padding: 0.5rem 0.5rem 2rem 0.5rem; background-color: var(--color-bg-primary); width: 100%; max-width: 900px; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 9591f7d..96609ab 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -24,7 +24,10 @@ const openAuthModal = (mode: 'login' | 'register') => {
- 开始提问 +
+ 开始提问 + Beta +
@@ -192,6 +195,37 @@ const openAuthModal = (mode: 'login' | 'register') => { height: 20px; } +.btn-wrapper { + position: relative; + display: inline-block; +} + +.free-tag { + position: absolute; + top: -10px; + right: -10px; + background-color: #ff3355; + color: white; + font-size: 0.7rem; + padding: 2px 8px; + border-radius: 10px; + font-weight: 600; + box-shadow: 0 2px 4px rgba(255, 51, 85, 0.3); + animation: pulse 1.5s infinite; +} + +@keyframes pulse { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.05); + } + 100% { + transform: scale(1); + } +} + @media (max-width: 768px) { .hero-section { padding: 4rem 1.5rem; @@ -235,5 +269,14 @@ const openAuthModal = (mode: 'login' | 'register') => { .btn { width: 100%; } + + .btn-wrapper { + width: 100%; + } + + .free-tag { + top: -8px; + right: 20px; + } }